4 * Standard OpenGL rendering engine.
6 * Copyright (c) 2005 Nathan Keynes.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
20 #include "pvr2/pvr2.h"
21 #include "pvr2/scene.h"
24 * Clip the tile bounds to the clipping plane.
25 * @return TRUE if the tile was not clipped completely.
27 static gboolean clip_tile_bounds( uint32_t *tile, float *clip )
29 if( tile[0] < clip[0] ) tile[0] = clip[0];
30 if( tile[1] > clip[1] ) tile[1] = clip[1];
31 if( tile[2] < clip[2] ) tile[2] = clip[2];
32 if( tile[3] > clip[3] ) tile[3] = clip[3];
33 return tile[0] < tile[1] && tile[2] < tile[3];
37 * Once-off call to setup the OpenGL context.
39 void pvr2_setup_gl_context()
41 texcache_gl_init(); // Allocate texture IDs
42 glShadeModel(GL_SMOOTH);
43 glCullFace( GL_BACK );
45 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
46 glMatrixMode(GL_MODELVIEW);
49 glEnableClientState( GL_COLOR_ARRAY );
50 glEnableClientState( GL_VERTEX_ARRAY );
51 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
52 glEnableClientState( GL_SECONDARY_COLOR_ARRAY );
54 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
59 static void gl_render_poly( struct polygon_struct *poly )
61 render_set_context( poly->context, RENDER_NORMAL );
62 glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
65 static void gl_render_tilelist( pvraddr_t tile_entry )
67 uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
69 struct polygon_struct *poly;
72 uint32_t entry = *tile_list++;
73 switch( entry >> 28 ) {
75 return; // End-of-list
77 tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
83 strip_count = ((entry >> 25) & 0x0F)+1;
84 poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
85 while( strip_count > 0 ) {
86 gl_render_poly( poly );
92 poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
93 gl_render_poly( poly );
100 * Render the currently defined scene in pvr2_scene
102 void pvr2_scene_render( render_buffer_t buffer )
105 display_driver->set_render_target(buffer);
106 pvr2_check_palette_changed();
108 /* Setup view projection matrix */
109 glMatrixMode(GL_PROJECTION);
111 float nearz = pvr2_scene.bounds[4];
112 float farz = pvr2_scene.bounds[5];
113 if( nearz == farz ) {
116 glOrtho( 0, pvr2_scene.buffer_width, pvr2_scene.buffer_height, 0,
119 /* Clear the buffer (FIXME: May not want always want to do this) */
120 glDisable( GL_SCISSOR_TEST );
121 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
123 /* Setup vertex array pointers */
124 glInterleavedArrays(GL_T2F_C4UB_V3F, sizeof(struct vertex_struct), pvr2_scene.vertex_array);
125 glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].offset_rgba );
127 uint32_t bgplane_mode = MMIO_READ(PVR2, RENDER_BGPLANE);
128 uint32_t *bgplane = pvr2_scene.pvr2_pbuf + (((bgplane_mode & 0x00FFFFFF)) >> 3) ;
129 render_backplane( bgplane, pvr2_scene.buffer_width, pvr2_scene.buffer_height, bgplane_mode );
131 glEnable( GL_SCISSOR_TEST );
133 /* Process the segment list */
134 struct tile_segment *segment = pvr2_scene.segment_list;
136 int tilex = SEGMENT_X(segment->control);
137 int tiley = SEGMENT_Y(segment->control);
139 int tile_bounds[4] = { tilex << 5, (tilex+1)<<5, tiley<<5, (tiley+1)<<5 };
140 if( !clip_tile_bounds(tile_bounds, pvr2_scene.bounds) ) {
141 continue; // fully clipped, skip tile
144 /* Clip to the visible part of the tile */
145 glScissor( tile_bounds[0], pvr2_scene.buffer_height-tile_bounds[3],
146 tile_bounds[1]-tile_bounds[0], tile_bounds[3] - tile_bounds[2] );
147 if( IS_TILE_PTR(segment->opaque_ptr) ) {
148 gl_render_tilelist(segment->opaque_ptr);
150 if( IS_TILE_PTR(segment->trans_ptr) ) {
151 gl_render_tilelist(segment->trans_ptr);
153 if( IS_TILE_PTR(segment->punchout_ptr) ) {
154 gl_render_tilelist(segment->punchout_ptr);
156 } while( !IS_LAST_SEGMENT(segment++) );
157 glDisable( GL_SCISSOR_TEST );
.