Search
lxdream.org :: lxdream/src/pvr2/glrender.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/glrender.c
changeset 863:a5e5310061e2
prev856:02ac5f37bfc9
next864:a90f3d5e57e1
author nkeynes
date Sun Sep 28 01:09:51 2008 +0000 (11 years ago)
permissions -rw-r--r--
last change Initial shadow volume implementation for opaque polygons (stencil isn't quite
right, but we get some kind of shadows now)
file annotate diff log raw
1.1 --- a/src/pvr2/glrender.c Thu Sep 11 22:51:24 2008 +0000
1.2 +++ b/src/pvr2/glrender.c Sun Sep 28 01:09:51 2008 +0000
1.3 @@ -24,6 +24,8 @@
1.4 #include "pvr2/scene.h"
1.5 #include "pvr2/glutil.h"
1.6
1.7 +#define IS_EMPTY_TILE_LIST(p) ((*((uint32_t *)(video_base+(p))) >> 28) == 0x0F)
1.8 +
1.9 int pvr2_poly_depthmode[8] = { GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL,
1.10 GL_GREATER, GL_NOTEQUAL, GL_GEQUAL,
1.11 GL_ALWAYS };
1.12 @@ -65,9 +67,13 @@
1.13 POLY2_TEX_WIDTH(poly->context[1]),
1.14 POLY2_TEX_HEIGHT(poly->context[1]) );
1.15 if( poly->mod_vertex_index != -1 ) {
1.16 - poly->mod_tex_id = texcache_get_texture( poly->context[4],
1.17 - POLY2_TEX_WIDTH(poly->context[3]),
1.18 - POLY2_TEX_HEIGHT(poly->context[3]) );
1.19 + if( pvr2_scene.shadow_mode == SHADOW_FULL ) {
1.20 + poly->mod_tex_id = texcache_get_texture( poly->context[4],
1.21 + POLY2_TEX_WIDTH(poly->context[3]),
1.22 + POLY2_TEX_HEIGHT(poly->context[3]) );
1.23 + } else {
1.24 + poly->mod_tex_id = poly->tex_id;
1.25 + }
1.26 }
1.27 } else {
1.28 poly->tex_id = -1;
1.29 @@ -117,22 +123,11 @@
1.30 }
1.31
1.32 /**
1.33 - * Setup the GL context for the supplied polygon context.
1.34 - * @param context pointer to 3 or 5 words of polygon context
1.35 - * @param modified boolean flag indicating that the modified
1.36 - * version should be used, rather than the normal version.
1.37 + * Setup the basic context that's shared between normal and modified modes -
1.38 + * depth, culling, shade model, and color sum
1.39 */
1.40 -void render_set_context( uint32_t *context, int render_mode )
1.41 +static void render_set_base_context( uint32_t poly1 )
1.42 {
1.43 - uint32_t poly1 = context[0], poly2, texture;
1.44 - if( render_mode == RENDER_FULLMOD ) {
1.45 - poly2 = context[3];
1.46 - texture = context[4];
1.47 - } else {
1.48 - poly2 = context[1];
1.49 - texture = context[2];
1.50 - }
1.51 -
1.52 glDepthFunc( POLY1_DEPTH_MODE(poly1) );
1.53 glDepthMask( POLY1_DEPTH_WRITE(poly1) ? GL_TRUE : GL_FALSE );
1.54
1.55 @@ -151,60 +146,84 @@
1.56 break;
1.57 }
1.58
1.59 + glShadeModel( POLY1_SHADE_MODEL(poly1) );
1.60 +
1.61 if( POLY1_SPECULAR(poly1) ) {
1.62 glEnable(GL_COLOR_SUM);
1.63 } else {
1.64 glDisable(GL_COLOR_SUM);
1.65 }
1.66 +}
1.67
1.68 +/**
1.69 + * Setup the texture/shading settings (TSP) which vary between mod/unmod modes.
1.70 + */
1.71 +static void render_set_tsp_context( uint32_t poly1, uint32_t poly2, uint32_t texture )
1.72 +{
1.73 + if( POLY1_TEXTURED(poly1) ) {
1.74 + glEnable(GL_TEXTURE_2D);
1.75 + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, pvr2_poly_texblend[POLY2_TEX_BLEND(poly2)] );
1.76 + if( POLY2_TEX_CLAMP_U(poly2) ) {
1.77 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
1.78 + } else if( POLY2_TEX_MIRROR_U(poly2) ) {
1.79 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT_ARB );
1.80 + } else {
1.81 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
1.82 + }
1.83 + if( POLY2_TEX_CLAMP_V(poly2) ) {
1.84 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
1.85 + } else if( POLY2_TEX_MIRROR_V(poly2) ) {
1.86 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT_ARB );
1.87 + } else {
1.88 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
1.89 + }
1.90 + } else {
1.91 + glDisable( GL_TEXTURE_2D );
1.92 + }
1.93 +
1.94 + switch( POLY2_FOG_MODE(poly2) ) {
1.95 + case PVR2_POLY_FOG_LOOKUP:
1.96 + glFogfv( GL_FOG_COLOR, pvr2_scene.fog_lut_colour );
1.97 + glEnable( GL_FOG );
1.98 + break;
1.99 + case PVR2_POLY_FOG_VERTEX:
1.100 + if( POLY1_SPECULAR(poly1) ) {
1.101 + glFogfv( GL_FOG_COLOR, pvr2_scene.fog_vert_colour );
1.102 + glEnable( GL_FOG );
1.103 + break;
1.104 + } /* else fallthrough */
1.105 + default:
1.106 + glDisable( GL_FOG );
1.107 + }
1.108
1.109 - if( POLY1_TEXTURED(poly1) ) {
1.110 - glEnable(GL_TEXTURE_2D);
1.111 - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, pvr2_poly_texblend[POLY2_TEX_BLEND(poly2)] );
1.112 - if( POLY2_TEX_CLAMP_U(poly2) ) {
1.113 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
1.114 - } else if( POLY2_TEX_MIRROR_U(poly2) ) {
1.115 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT_ARB );
1.116 - } else {
1.117 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
1.118 - }
1.119 - if( POLY2_TEX_CLAMP_V(poly2) ) {
1.120 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
1.121 - } else if( POLY2_TEX_MIRROR_V(poly2) ) {
1.122 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT_ARB );
1.123 - } else {
1.124 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
1.125 - }
1.126 + int srcblend = POLY2_SRC_BLEND(poly2);
1.127 + int destblend = POLY2_DEST_BLEND(poly2);
1.128 + glBlendFunc( srcblend, destblend );
1.129 +
1.130 + if( POLY2_SRC_BLEND_TARGET(poly2) || POLY2_DEST_BLEND_TARGET(poly2) ) {
1.131 + WARN( "Accumulation buffer not supported" );
1.132 + }
1.133 +}
1.134 +
1.135 +/**
1.136 + * Setup the GL context for the supplied polygon context.
1.137 + * @param context pointer to 3 or 5 words of polygon context
1.138 + * @param modified boolean flag indicating that the modified
1.139 + * version should be used, rather than the normal version.
1.140 + */
1.141 +void render_set_context( uint32_t *context, int render_mode )
1.142 +{
1.143 + uint32_t poly1 = context[0], poly2, texture;
1.144 + if( render_mode == RENDER_FULLMOD ) {
1.145 + poly2 = context[3];
1.146 + texture = context[4];
1.147 } else {
1.148 - glDisable( GL_TEXTURE_2D );
1.149 - }
1.150 -
1.151 - switch( POLY2_FOG_MODE(poly2) ) {
1.152 - case PVR2_POLY_FOG_LOOKUP:
1.153 - glFogfv( GL_FOG_COLOR, pvr2_scene.fog_lut_colour );
1.154 - glEnable( GL_FOG );
1.155 - break;
1.156 - case PVR2_POLY_FOG_VERTEX:
1.157 - if( POLY1_SPECULAR(poly1) ) {
1.158 - glFogfv( GL_FOG_COLOR, pvr2_scene.fog_vert_colour );
1.159 - glEnable( GL_FOG );
1.160 - break;
1.161 - } /* else fallthrough */
1.162 - default:
1.163 - glDisable( GL_FOG );
1.164 - }
1.165 -
1.166 -
1.167 - glShadeModel( POLY1_SHADE_MODEL(poly1) );
1.168 -
1.169 - int srcblend = POLY2_SRC_BLEND(poly2);
1.170 - int destblend = POLY2_DEST_BLEND(poly2);
1.171 - glBlendFunc( srcblend, destblend );
1.172 -
1.173 - if( POLY2_SRC_BLEND_TARGET(poly2) || POLY2_DEST_BLEND_TARGET(poly2) ) {
1.174 - ERROR( "Accumulation buffer not supported" );
1.175 + poly2 = context[1];
1.176 + texture = context[2];
1.177 }
1.178
1.179 + render_set_base_context(poly1);
1.180 + render_set_tsp_context(poly1,poly2,texture);
1.181 }
1.182
1.183
1.184 @@ -213,11 +232,26 @@
1.185 if( poly->tex_id != -1 ) {
1.186 glBindTexture(GL_TEXTURE_2D, poly->tex_id);
1.187 }
1.188 - render_set_context( poly->context, RENDER_NORMAL );
1.189 - glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
1.190 + if( poly->mod_vertex_index == -1 ) {
1.191 + render_set_context( poly->context, RENDER_NORMAL );
1.192 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
1.193 + } else {
1.194 + render_set_base_context( poly->context[0] );
1.195 + render_set_tsp_context( poly->context[0], poly->context[1], poly->context[2] );
1.196 + glStencilFunc(GL_EQUAL, 0, 1);
1.197 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
1.198 +
1.199 + if( pvr2_scene.shadow_mode == SHADOW_FULL ) {
1.200 + if( poly->mod_tex_id != -1 ) {
1.201 + glBindTexture(GL_TEXTURE_2D, poly->mod_tex_id);
1.202 + }
1.203 + render_set_tsp_context( poly->context[0], poly->context[3], poly->context[4] );
1.204 + }
1.205 + glStencilFunc(GL_EQUAL, 1, 1);
1.206 + glDrawArrays(GL_TRIANGLE_STRIP, poly->mod_vertex_index, poly->vertex_count );
1.207 + }
1.208 }
1.209
1.210 -
1.211 static void gl_render_bkgnd( struct polygon_struct *poly )
1.212 {
1.213 if( poly->tex_id != -1 ) {
1.214 @@ -232,14 +266,15 @@
1.215 glEnable( GL_DEPTH_TEST );
1.216 }
1.217
1.218 -
1.219 -
1.220 void gl_render_tilelist( pvraddr_t tile_entry )
1.221 {
1.222 uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
1.223 int strip_count;
1.224 struct polygon_struct *poly;
1.225
1.226 + if( !IS_TILE_PTR(tile_entry) )
1.227 + return;
1.228 +
1.229 while(1) {
1.230 uint32_t entry = *tile_list++;
1.231 switch( entry >> 28 ) {
1.232 @@ -264,7 +299,102 @@
1.233 gl_render_poly( poly );
1.234 }
1.235 }
1.236 - }
1.237 + }
1.238 +}
1.239 +
1.240 +/**
1.241 + * Render the tilelist with depthbuffer updates only.
1.242 + */
1.243 +void gl_render_tilelist_depthonly( pvraddr_t tile_entry )
1.244 +{
1.245 + uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
1.246 + int strip_count;
1.247 + struct polygon_struct *poly;
1.248 +
1.249 + if( !IS_TILE_PTR(tile_entry) )
1.250 + return;
1.251 +
1.252 + glDisable( GL_TEXTURE_2D );
1.253 + glDisable( GL_FOG );
1.254 + glDisable( GL_COLOR_SUM );
1.255 +
1.256 + while(1) {
1.257 + uint32_t entry = *tile_list++;
1.258 + switch( entry >> 28 ) {
1.259 + case 0x0F:
1.260 + return; // End-of-list
1.261 + case 0x0E:
1.262 + tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
1.263 + break;
1.264 + case 0x08: case 0x09: case 0x0A: case 0x0B:
1.265 + strip_count = ((entry >> 25) & 0x0F)+1;
1.266 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
1.267 + while( strip_count > 0 ) {
1.268 + render_set_base_context(poly->context[0]);
1.269 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
1.270 + poly = poly->next;
1.271 + strip_count--;
1.272 + }
1.273 + break;
1.274 + default:
1.275 + if( entry & 0x7E000000 ) {
1.276 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
1.277 + render_set_base_context(poly->context[0]);
1.278 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
1.279 + }
1.280 + }
1.281 + }
1.282 +}
1.283 +
1.284 +void gl_render_modifier_tilelist( pvraddr_t tile_entry )
1.285 +{
1.286 + uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
1.287 + int strip_count;
1.288 + struct polygon_struct *poly;
1.289 +
1.290 + if( !IS_TILE_PTR(tile_entry) )
1.291 + return;
1.292 +
1.293 + glDisable( GL_TEXTURE_2D );
1.294 + glDisable( GL_FOG );
1.295 + glDisable( GL_COLOR_SUM );
1.296 + glDisable( GL_CULL_FACE );
1.297 + glEnable( GL_STENCIL_TEST );
1.298 + glEnable( GL_DEPTH_TEST );
1.299 + glDepthFunc( GL_LEQUAL );
1.300 +
1.301 + glStencilFunc( GL_ALWAYS, 0, 1 );
1.302 + glStencilOp( GL_KEEP,GL_INVERT, GL_KEEP );
1.303 +
1.304 + glDepthMask( GL_FALSE );
1.305 +
1.306 + while(1) {
1.307 + uint32_t entry = *tile_list++;
1.308 + switch( entry >> 28 ) {
1.309 + case 0x0F:
1.310 + glDepthMask( GL_TRUE );
1.311 + glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
1.312 + return; // End-of-list
1.313 + case 0x0E:
1.314 + tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
1.315 + break;
1.316 + case 0x08: case 0x09: case 0x0A: case 0x0B:
1.317 + strip_count = ((entry >> 25) & 0x0F)+1;
1.318 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
1.319 + while( strip_count > 0 ) {
1.320 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
1.321 + poly = poly->next;
1.322 + strip_count--;
1.323 + }
1.324 + break;
1.325 + default:
1.326 + if( entry & 0x7E000000 ) {
1.327 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
1.328 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
1.329 + }
1.330 + }
1.331 + }
1.332 +
1.333 }
1.334
1.335
1.336 @@ -336,9 +466,26 @@
1.337 /* Clip to the visible part of the tile */
1.338 glScissor( tile_bounds[0], pvr2_scene.buffer_height-tile_bounds[3],
1.339 tile_bounds[1]-tile_bounds[0], tile_bounds[3] - tile_bounds[2] );
1.340 - if( IS_TILE_PTR(segment->opaque_ptr) ) {
1.341 - gl_render_tilelist(segment->opaque_ptr);
1.342 + if( display_driver->capabilities.stencil_bits != 0 &&
1.343 + IS_TILE_PTR(segment->opaquemod_ptr) &&
1.344 + !IS_EMPTY_TILE_LIST(segment->opaquemod_ptr) ) {
1.345 + /* Don't do this unless there's actually some shadow polygons */
1.346 +
1.347 + /* Use colormask instead of drawbuffer for simplicity */
1.348 + glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
1.349 + gl_render_tilelist_depthonly(segment->opaque_ptr);
1.350 + gl_render_modifier_tilelist(segment->opaquemod_ptr);
1.351 + glClear( GL_DEPTH_BUFFER_BIT );
1.352 + glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
1.353 }
1.354 + gl_render_tilelist(segment->opaque_ptr);
1.355 + if( IS_TILE_PTR(segment->punchout_ptr) ) {
1.356 + glEnable(GL_ALPHA_TEST );
1.357 + render_autosort_tile(segment->punchout_ptr, RENDER_NORMAL );
1.358 + glDisable(GL_ALPHA_TEST );
1.359 + }
1.360 + glDisable( GL_STENCIL_TEST );
1.361 +
1.362 if( IS_TILE_PTR(segment->trans_ptr) ) {
1.363 if( pvr2_scene.sort_mode == SORT_NEVER ||
1.364 (pvr2_scene.sort_mode == SORT_TILEFLAG && (segment->control&SEGMENT_SORT_TRANS))) {
1.365 @@ -347,11 +494,6 @@
1.366 render_autosort_tile(segment->trans_ptr, RENDER_NORMAL );
1.367 }
1.368 }
1.369 - if( IS_TILE_PTR(segment->punchout_ptr) ) {
1.370 - glEnable(GL_ALPHA_TEST );
1.371 - render_autosort_tile(segment->punchout_ptr, RENDER_NORMAL );
1.372 - glDisable(GL_ALPHA_TEST );
1.373 - }
1.374 } while( !IS_LAST_SEGMENT(segment++) );
1.375 glDisable( GL_SCISSOR_TEST );
1.376
.