Search
lxdream.org :: lxdream/src/pvr2/glrender.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/glrender.c
changeset 639:162ee7614b60
next645:a7392098299c
author nkeynes
date Mon Feb 18 09:21:43 2008 +0000 (12 years ago)
branchlxdream-render
permissions -rw-r--r--
last change More render WIP - initial glrender.c
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/pvr2/glrender.c Mon Feb 18 09:21:43 2008 +0000
1.3 @@ -0,0 +1,159 @@
1.4 +/**
1.5 + * $Id$
1.6 + *
1.7 + * Standard OpenGL rendering engine.
1.8 + *
1.9 + * Copyright (c) 2005 Nathan Keynes.
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +
1.22 +#include "display.h"
1.23 +#include "pvr2/pvr2.h"
1.24 +#include "pvr2/scene.h"
1.25 +
1.26 +/**
1.27 + * Clip the tile bounds to the clipping plane.
1.28 + * @return TRUE if the tile was not clipped completely.
1.29 + */
1.30 +static gboolean clip_tile_bounds( uint32_t *tile, float *clip )
1.31 +{
1.32 + if( tile[0] < clip[0] ) tile[0] = clip[0];
1.33 + if( tile[1] > clip[1] ) tile[1] = clip[1];
1.34 + if( tile[2] < clip[2] ) tile[2] = clip[2];
1.35 + if( tile[3] > clip[3] ) tile[3] = clip[3];
1.36 + return tile[0] < tile[1] && tile[2] < tile[3];
1.37 +}
1.38 +
1.39 +/**
1.40 + * Once-off call to setup the OpenGL context.
1.41 + */
1.42 +void pvr2_setup_gl_context()
1.43 +{
1.44 + texcache_gl_init(); // Allocate texture IDs
1.45 + glShadeModel(GL_SMOOTH);
1.46 + glCullFace( GL_BACK );
1.47 + glEnable( GL_BLEND );
1.48 + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1.49 + glMatrixMode(GL_MODELVIEW);
1.50 + glLoadIdentity();
1.51 +
1.52 + glEnableClientState( GL_COLOR_ARRAY );
1.53 + glEnableClientState( GL_VERTEX_ARRAY );
1.54 + glEnableClientState( GL_TEXTURE_COORD_ARRAY );
1.55 + glEnableClientState( GL_SECONDARY_COLOR_ARRAY );
1.56 +
1.57 + glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1.58 + glClearDepth(0);
1.59 + glClearStencil(0);
1.60 +}
1.61 +
1.62 +static void gl_render_poly( struct polygon_struct *poly )
1.63 +{
1.64 + render_set_context( poly->context, RENDER_NORMAL );
1.65 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
1.66 +}
1.67 +
1.68 +static void gl_render_tilelist( pvraddr_t tile_entry )
1.69 +{
1.70 + uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
1.71 + int strip_count;
1.72 + struct polygon_struct *poly;
1.73 +
1.74 + while(1) {
1.75 + uint32_t entry = *tile_list++;
1.76 + switch( entry >> 28 ) {
1.77 + case 0x0F:
1.78 + return; // End-of-list
1.79 + case 0x0E:
1.80 + tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
1.81 + break;
1.82 + case 0x08:
1.83 + case 0x09:
1.84 + case 0x0A:
1.85 + case 0x0B:
1.86 + strip_count = ((entry >> 25) & 0x0F)+1;
1.87 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
1.88 + while( strip_count > 0 ) {
1.89 + gl_render_poly( poly );
1.90 + poly = poly->next;
1.91 + strip_count--;
1.92 + }
1.93 + break;
1.94 + default:
1.95 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
1.96 + gl_render_poly( poly );
1.97 + }
1.98 + }
1.99 +}
1.100 +
1.101 +
1.102 +/**
1.103 + * Render the currently defined scene in pvr2_scene
1.104 + */
1.105 +void pvr2_scene_render( render_buffer_t buffer )
1.106 +{
1.107 + /* Scene setup */
1.108 + display_driver->set_render_target(buffer);
1.109 + pvr2_check_palette_changed();
1.110 +
1.111 + /* Setup view projection matrix */
1.112 + glMatrixMode(GL_PROJECTION);
1.113 + glLoadIdentity();
1.114 + float nearz = pvr2_scene.bounds[4];
1.115 + float farz = pvr2_scene.bounds[5];
1.116 + if( nearz == farz ) {
1.117 + farz*= 2.0;
1.118 + }
1.119 + glOrtho( 0, pvr2_scene.buffer_width, pvr2_scene.buffer_height, 0,
1.120 + -nearz, -farz );
1.121 +
1.122 + /* Clear the buffer (FIXME: May not want always want to do this) */
1.123 + glDisable( GL_SCISSOR_TEST );
1.124 + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
1.125 +
1.126 + /* Setup vertex array pointers */
1.127 + glInterleavedArrays(GL_T2F_C4UB_V3F, sizeof(struct vertex_struct), pvr2_scene.vertex_array);
1.128 + glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].offset_rgba );
1.129 +
1.130 + uint32_t bgplane_mode = MMIO_READ(PVR2, RENDER_BGPLANE);
1.131 + uint32_t *bgplane = pvr2_scene.pvr2_pbuf + (((bgplane_mode & 0x00FFFFFF)) >> 3) ;
1.132 + render_backplane( bgplane, pvr2_scene.buffer_width, pvr2_scene.buffer_height, bgplane_mode );
1.133 +
1.134 + glEnable( GL_SCISSOR_TEST );
1.135 +
1.136 + /* Process the segment list */
1.137 + struct tile_segment *segment = pvr2_scene.segment_list;
1.138 + do {
1.139 + int tilex = SEGMENT_X(segment->control);
1.140 + int tiley = SEGMENT_Y(segment->control);
1.141 +
1.142 + int tile_bounds[4] = { tilex << 5, (tilex+1)<<5, tiley<<5, (tiley+1)<<5 };
1.143 + if( !clip_tile_bounds(tile_bounds, pvr2_scene.bounds) ) {
1.144 + continue; // fully clipped, skip tile
1.145 + }
1.146 +
1.147 + /* Clip to the visible part of the tile */
1.148 + glScissor( tile_bounds[0], pvr2_scene.buffer_height-tile_bounds[3],
1.149 + tile_bounds[1]-tile_bounds[0], tile_bounds[3] - tile_bounds[2] );
1.150 + if( IS_TILE_PTR(segment->opaque_ptr) ) {
1.151 + gl_render_tilelist(segment->opaque_ptr);
1.152 + }
1.153 + if( IS_TILE_PTR(segment->trans_ptr) ) {
1.154 + gl_render_tilelist(segment->trans_ptr);
1.155 + }
1.156 + if( IS_TILE_PTR(segment->punchout_ptr) ) {
1.157 + gl_render_tilelist(segment->punchout_ptr);
1.158 + }
1.159 + } while( !IS_LAST_SEGMENT(segment++) );
1.160 + glDisable( GL_SCISSOR_TEST );
1.161 +
1.162 +}
.