revision 863:a5e5310061e2
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 863:a5e5310061e2 |
parent | 862:d3b2066d5daa |
child | 864:a90f3d5e57e1 |
author | nkeynes |
date | Sun Sep 28 01:09:51 2008 +0000 (15 years ago) |
Initial shadow volume implementation for opaque polygons (stencil isn't quite
right, but we get some kind of shadows now)
right, but we get some kind of shadows now)
1.1 --- a/src/display.h Sun Sep 28 00:31:58 2008 +00001.2 +++ b/src/display.h Sun Sep 28 01:09:51 2008 +00001.3 @@ -102,6 +102,10 @@1.4 unsigned char *data;1.5 };1.7 +struct display_capabilities {1.8 + int stencil_bits; /* 0 = no stencil buffer */1.9 +};1.10 +1.11 /**1.12 * Core video driver - exports function to setup a GL context, as well as handle1.13 * keyboard input and display resultant output.1.14 @@ -201,6 +205,7 @@1.15 gboolean (*read_render_buffer)( unsigned char *target, render_buffer_t buffer,1.16 int rowstride, int format );1.18 + struct display_capabilities capabilities;1.19 } *display_driver_t;1.21 /**
2.1 --- a/src/drivers/gl_fbo.c Sun Sep 28 00:31:58 2008 +00002.2 +++ b/src/drivers/gl_fbo.c Sun Sep 28 01:09:51 2008 +00002.3 @@ -58,6 +58,7 @@2.4 };2.6 static GLint gl_fbo_max_attachments = 0;2.7 +static gboolean gl_fbo_have_packed_stencil = FALSE;2.8 static struct gl_fbo_info fbo[MAX_FRAMEBUFFERS];2.10 #define ATTACHMENT_POINT(n) (GL_COLOR_ATTACHMENT0_EXT+(n))2.11 @@ -93,6 +94,15 @@2.12 }2.13 last_used_fbo = 0;2.15 + if( isGLExtensionSupported("GL_EXT_packed_depth_stencil" ) ) {2.16 + driver->capabilities.stencil_bits = 8;2.17 + gl_fbo_have_packed_stencil = TRUE;2.18 + } else {2.19 + driver->capabilities.stencil_bits = 0;2.20 + gl_fbo_have_packed_stencil = FALSE;2.21 + WARN( "Packed depth stencil not available - disabling shadow volumes" );2.22 + }2.23 +2.24 driver->create_render_buffer = gl_fbo_create_render_buffer;2.25 driver->destroy_render_buffer = gl_fbo_destroy_render_buffer;2.26 driver->set_render_target = gl_fbo_set_render_target;2.27 @@ -117,24 +127,31 @@2.28 }2.29 }2.31 -void gl_fbo_setup_framebuffer( int bufno, int width, int height )2.32 +static void gl_fbo_setup_framebuffer( int bufno, int width, int height )2.33 {2.34 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo[bufno].fb_id);2.35 - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo[bufno].depth_id);2.36 - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);2.37 - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,2.38 - GL_RENDERBUFFER_EXT, fbo[bufno].depth_id);2.39 - /* Stencil doesn't work on ATI, and we're not using it at the moment anyway, so...2.40 - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo[bufno].stencil_id);2.41 - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, width, height);2.42 - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,2.43 - GL_RENDERBUFFER_EXT, fbo[bufno].stencil_id);2.44 - */2.45 + if( gl_fbo_have_packed_stencil ) {2.46 + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo[bufno].depth_id);2.47 + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, width, height);2.48 + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,2.49 + GL_RENDERBUFFER_EXT, fbo[bufno].depth_id);2.50 + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,2.51 + GL_RENDERBUFFER_EXT, fbo[bufno].depth_id);2.52 + } else {2.53 + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo[bufno].depth_id);2.54 + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);2.55 + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,2.56 + GL_RENDERBUFFER_EXT, fbo[bufno].depth_id);2.57 + /* In theory you could attach a separate stencil buffer. In practice this2.58 + * isn't actually supported by any hardware I've had access to, so we're2.59 + * stencil-less.2.60 + */2.61 + }2.62 fbo[bufno].width = width;2.63 fbo[bufno].height = height;2.64 }2.66 -int gl_fbo_get_framebuffer( int width, int height )2.67 +static int gl_fbo_get_framebuffer( int width, int height )2.68 {2.69 int bufno = -1, i;2.70 /* find a compatible framebuffer context */
3.1 --- a/src/drivers/video_glx.c Sun Sep 28 00:31:58 2008 +00003.2 +++ b/src/drivers/video_glx.c Sun Sep 28 01:09:51 2008 +00003.3 @@ -96,19 +96,25 @@3.4 if( result != False ) {3.5 glx_version = (major*100) + minor;3.6 }3.7 -3.8 +#ifdef APPLE_BUILD3.9 + /* fbconfig is broken on at least the 10.5 GLX implementation */3.10 + glx_fbconfig_supported = FALSE;3.11 +#else3.12 glx_fbconfig_supported = (glx_version >= 103 ||3.13 isServerGLXExtensionSupported(display, screen,3.14 "GLX_SGIX_fbconfig") );3.15 +#endif3.16 glx_pbuffer_supported = (glx_version >= 103 ||3.17 isServerGLXExtensionSupported(display, screen,3.18 "GLX_SGIX_pbuffer") );3.19 +// glx_fbconfig_supported = FALSE;3.20 if( glx_fbconfig_supported ) {3.21 int nelem;3.22 int fb_attribs[] = { GLX_DRAWABLE_TYPE,3.23 GLX_PBUFFER_BIT|GLX_WINDOW_BIT,3.24 GLX_RENDER_TYPE, GLX_RGBA_BIT,3.25 - GLX_DEPTH_SIZE, 24, 0 };3.26 + GLX_DEPTH_SIZE, 24,3.27 + GLX_STENCIL_SIZE, 8, 0 };3.28 GLXFBConfig *configs = glXChooseFBConfig( display, screen,3.29 fb_attribs, &nelem );3.31 @@ -133,7 +139,7 @@3.32 }3.34 if( !glx_fbconfig_supported ) {3.35 - int attribs[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, 0 };3.36 + int attribs[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8, 0 };3.37 glx_visual = glXChooseVisual( display, screen, attribs );3.38 if( glx_visual == NULL ) {3.39 /* Try the 16-bit fallback here too */3.40 @@ -262,6 +268,12 @@3.41 */3.42 static void glx_pbuffer_init( display_driver_t driver )3.43 {3.44 + GLint stencil_bits = 0;3.45 +3.46 + /* Retrieve the number of stencil bits */3.47 + glGetIntegerv( GL_STENCIL_BITS, &stencil_bits );3.48 + driver->capabilities.stencil_bits = stencil_bits;3.49 +3.50 glGenTextures( 1, &glx_pbuffer_texture );3.51 driver->create_render_buffer = glx_pbuffer_create_render_buffer;3.52 driver->destroy_render_buffer = glx_pbuffer_destroy_render_buffer;
4.1 --- a/src/pvr2/glrender.c Sun Sep 28 00:31:58 2008 +00004.2 +++ b/src/pvr2/glrender.c Sun Sep 28 01:09:51 2008 +00004.3 @@ -24,6 +24,8 @@4.4 #include "pvr2/scene.h"4.5 #include "pvr2/glutil.h"4.7 +#define IS_EMPTY_TILE_LIST(p) ((*((uint32_t *)(video_base+(p))) >> 28) == 0x0F)4.8 +4.9 int pvr2_poly_depthmode[8] = { GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL,4.10 GL_GREATER, GL_NOTEQUAL, GL_GEQUAL,4.11 GL_ALWAYS };4.12 @@ -65,9 +67,13 @@4.13 POLY2_TEX_WIDTH(poly->context[1]),4.14 POLY2_TEX_HEIGHT(poly->context[1]) );4.15 if( poly->mod_vertex_index != -1 ) {4.16 - poly->mod_tex_id = texcache_get_texture( poly->context[4],4.17 - POLY2_TEX_WIDTH(poly->context[3]),4.18 - POLY2_TEX_HEIGHT(poly->context[3]) );4.19 + if( pvr2_scene.shadow_mode == SHADOW_FULL ) {4.20 + poly->mod_tex_id = texcache_get_texture( poly->context[4],4.21 + POLY2_TEX_WIDTH(poly->context[3]),4.22 + POLY2_TEX_HEIGHT(poly->context[3]) );4.23 + } else {4.24 + poly->mod_tex_id = poly->tex_id;4.25 + }4.26 }4.27 } else {4.28 poly->tex_id = -1;4.29 @@ -117,22 +123,11 @@4.30 }4.32 /**4.33 - * Setup the GL context for the supplied polygon context.4.34 - * @param context pointer to 3 or 5 words of polygon context4.35 - * @param modified boolean flag indicating that the modified4.36 - * version should be used, rather than the normal version.4.37 + * Setup the basic context that's shared between normal and modified modes -4.38 + * depth, culling, shade model, and color sum4.39 */4.40 -void render_set_context( uint32_t *context, int render_mode )4.41 +static void render_set_base_context( uint32_t poly1 )4.42 {4.43 - uint32_t poly1 = context[0], poly2, texture;4.44 - if( render_mode == RENDER_FULLMOD ) {4.45 - poly2 = context[3];4.46 - texture = context[4];4.47 - } else {4.48 - poly2 = context[1];4.49 - texture = context[2];4.50 - }4.51 -4.52 glDepthFunc( POLY1_DEPTH_MODE(poly1) );4.53 glDepthMask( POLY1_DEPTH_WRITE(poly1) ? GL_TRUE : GL_FALSE );4.55 @@ -151,60 +146,84 @@4.56 break;4.57 }4.59 + glShadeModel( POLY1_SHADE_MODEL(poly1) );4.60 +4.61 if( POLY1_SPECULAR(poly1) ) {4.62 glEnable(GL_COLOR_SUM);4.63 } else {4.64 glDisable(GL_COLOR_SUM);4.65 }4.66 +}4.68 +/**4.69 + * Setup the texture/shading settings (TSP) which vary between mod/unmod modes.4.70 + */4.71 +static void render_set_tsp_context( uint32_t poly1, uint32_t poly2, uint32_t texture )4.72 +{4.73 + if( POLY1_TEXTURED(poly1) ) {4.74 + glEnable(GL_TEXTURE_2D);4.75 + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, pvr2_poly_texblend[POLY2_TEX_BLEND(poly2)] );4.76 + if( POLY2_TEX_CLAMP_U(poly2) ) {4.77 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );4.78 + } else if( POLY2_TEX_MIRROR_U(poly2) ) {4.79 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT_ARB );4.80 + } else {4.81 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );4.82 + }4.83 + if( POLY2_TEX_CLAMP_V(poly2) ) {4.84 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );4.85 + } else if( POLY2_TEX_MIRROR_V(poly2) ) {4.86 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT_ARB );4.87 + } else {4.88 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );4.89 + }4.90 + } else {4.91 + glDisable( GL_TEXTURE_2D );4.92 + }4.93 +4.94 + switch( POLY2_FOG_MODE(poly2) ) {4.95 + case PVR2_POLY_FOG_LOOKUP:4.96 + glFogfv( GL_FOG_COLOR, pvr2_scene.fog_lut_colour );4.97 + glEnable( GL_FOG );4.98 + break;4.99 + case PVR2_POLY_FOG_VERTEX:4.100 + if( POLY1_SPECULAR(poly1) ) {4.101 + glFogfv( GL_FOG_COLOR, pvr2_scene.fog_vert_colour );4.102 + glEnable( GL_FOG );4.103 + break;4.104 + } /* else fallthrough */4.105 + default:4.106 + glDisable( GL_FOG );4.107 + }4.109 - if( POLY1_TEXTURED(poly1) ) {4.110 - glEnable(GL_TEXTURE_2D);4.111 - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, pvr2_poly_texblend[POLY2_TEX_BLEND(poly2)] );4.112 - if( POLY2_TEX_CLAMP_U(poly2) ) {4.113 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );4.114 - } else if( POLY2_TEX_MIRROR_U(poly2) ) {4.115 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT_ARB );4.116 - } else {4.117 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );4.118 - }4.119 - if( POLY2_TEX_CLAMP_V(poly2) ) {4.120 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );4.121 - } else if( POLY2_TEX_MIRROR_V(poly2) ) {4.122 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT_ARB );4.123 - } else {4.124 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );4.125 - }4.126 + int srcblend = POLY2_SRC_BLEND(poly2);4.127 + int destblend = POLY2_DEST_BLEND(poly2);4.128 + glBlendFunc( srcblend, destblend );4.129 +4.130 + if( POLY2_SRC_BLEND_TARGET(poly2) || POLY2_DEST_BLEND_TARGET(poly2) ) {4.131 + WARN( "Accumulation buffer not supported" );4.132 + }4.133 +}4.134 +4.135 +/**4.136 + * Setup the GL context for the supplied polygon context.4.137 + * @param context pointer to 3 or 5 words of polygon context4.138 + * @param modified boolean flag indicating that the modified4.139 + * version should be used, rather than the normal version.4.140 + */4.141 +void render_set_context( uint32_t *context, int render_mode )4.142 +{4.143 + uint32_t poly1 = context[0], poly2, texture;4.144 + if( render_mode == RENDER_FULLMOD ) {4.145 + poly2 = context[3];4.146 + texture = context[4];4.147 } else {4.148 - glDisable( GL_TEXTURE_2D );4.149 - }4.150 -4.151 - switch( POLY2_FOG_MODE(poly2) ) {4.152 - case PVR2_POLY_FOG_LOOKUP:4.153 - glFogfv( GL_FOG_COLOR, pvr2_scene.fog_lut_colour );4.154 - glEnable( GL_FOG );4.155 - break;4.156 - case PVR2_POLY_FOG_VERTEX:4.157 - if( POLY1_SPECULAR(poly1) ) {4.158 - glFogfv( GL_FOG_COLOR, pvr2_scene.fog_vert_colour );4.159 - glEnable( GL_FOG );4.160 - break;4.161 - } /* else fallthrough */4.162 - default:4.163 - glDisable( GL_FOG );4.164 - }4.165 -4.166 -4.167 - glShadeModel( POLY1_SHADE_MODEL(poly1) );4.168 -4.169 - int srcblend = POLY2_SRC_BLEND(poly2);4.170 - int destblend = POLY2_DEST_BLEND(poly2);4.171 - glBlendFunc( srcblend, destblend );4.172 -4.173 - if( POLY2_SRC_BLEND_TARGET(poly2) || POLY2_DEST_BLEND_TARGET(poly2) ) {4.174 - ERROR( "Accumulation buffer not supported" );4.175 + poly2 = context[1];4.176 + texture = context[2];4.177 }4.179 + render_set_base_context(poly1);4.180 + render_set_tsp_context(poly1,poly2,texture);4.181 }4.184 @@ -213,11 +232,26 @@4.185 if( poly->tex_id != -1 ) {4.186 glBindTexture(GL_TEXTURE_2D, poly->tex_id);4.187 }4.188 - render_set_context( poly->context, RENDER_NORMAL );4.189 - glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );4.190 + if( poly->mod_vertex_index == -1 ) {4.191 + render_set_context( poly->context, RENDER_NORMAL );4.192 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );4.193 + } else {4.194 + render_set_base_context( poly->context[0] );4.195 + render_set_tsp_context( poly->context[0], poly->context[1], poly->context[2] );4.196 + glStencilFunc(GL_EQUAL, 0, 1);4.197 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );4.198 +4.199 + if( pvr2_scene.shadow_mode == SHADOW_FULL ) {4.200 + if( poly->mod_tex_id != -1 ) {4.201 + glBindTexture(GL_TEXTURE_2D, poly->mod_tex_id);4.202 + }4.203 + render_set_tsp_context( poly->context[0], poly->context[3], poly->context[4] );4.204 + }4.205 + glStencilFunc(GL_EQUAL, 1, 1);4.206 + glDrawArrays(GL_TRIANGLE_STRIP, poly->mod_vertex_index, poly->vertex_count );4.207 + }4.208 }4.210 -4.211 static void gl_render_bkgnd( struct polygon_struct *poly )4.212 {4.213 if( poly->tex_id != -1 ) {4.214 @@ -232,14 +266,15 @@4.215 glEnable( GL_DEPTH_TEST );4.216 }4.218 -4.219 -4.220 void gl_render_tilelist( pvraddr_t tile_entry )4.221 {4.222 uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);4.223 int strip_count;4.224 struct polygon_struct *poly;4.226 + if( !IS_TILE_PTR(tile_entry) )4.227 + return;4.228 +4.229 while(1) {4.230 uint32_t entry = *tile_list++;4.231 switch( entry >> 28 ) {4.232 @@ -264,7 +299,102 @@4.233 gl_render_poly( poly );4.234 }4.235 }4.236 - }4.237 + }4.238 +}4.239 +4.240 +/**4.241 + * Render the tilelist with depthbuffer updates only.4.242 + */4.243 +void gl_render_tilelist_depthonly( pvraddr_t tile_entry )4.244 +{4.245 + uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);4.246 + int strip_count;4.247 + struct polygon_struct *poly;4.248 +4.249 + if( !IS_TILE_PTR(tile_entry) )4.250 + return;4.251 +4.252 + glDisable( GL_TEXTURE_2D );4.253 + glDisable( GL_FOG );4.254 + glDisable( GL_COLOR_SUM );4.255 +4.256 + while(1) {4.257 + uint32_t entry = *tile_list++;4.258 + switch( entry >> 28 ) {4.259 + case 0x0F:4.260 + return; // End-of-list4.261 + case 0x0E:4.262 + tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));4.263 + break;4.264 + case 0x08: case 0x09: case 0x0A: case 0x0B:4.265 + strip_count = ((entry >> 25) & 0x0F)+1;4.266 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];4.267 + while( strip_count > 0 ) {4.268 + render_set_base_context(poly->context[0]);4.269 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );4.270 + poly = poly->next;4.271 + strip_count--;4.272 + }4.273 + break;4.274 + default:4.275 + if( entry & 0x7E000000 ) {4.276 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];4.277 + render_set_base_context(poly->context[0]);4.278 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );4.279 + }4.280 + }4.281 + }4.282 +}4.283 +4.284 +void gl_render_modifier_tilelist( pvraddr_t tile_entry )4.285 +{4.286 + uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);4.287 + int strip_count;4.288 + struct polygon_struct *poly;4.289 +4.290 + if( !IS_TILE_PTR(tile_entry) )4.291 + return;4.292 +4.293 + glDisable( GL_TEXTURE_2D );4.294 + glDisable( GL_FOG );4.295 + glDisable( GL_COLOR_SUM );4.296 + glDisable( GL_CULL_FACE );4.297 + glEnable( GL_STENCIL_TEST );4.298 + glEnable( GL_DEPTH_TEST );4.299 + glDepthFunc( GL_LEQUAL );4.300 +4.301 + glStencilFunc( GL_ALWAYS, 0, 1 );4.302 + glStencilOp( GL_KEEP,GL_INVERT, GL_KEEP );4.303 +4.304 + glDepthMask( GL_FALSE );4.305 +4.306 + while(1) {4.307 + uint32_t entry = *tile_list++;4.308 + switch( entry >> 28 ) {4.309 + case 0x0F:4.310 + glDepthMask( GL_TRUE );4.311 + glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );4.312 + return; // End-of-list4.313 + case 0x0E:4.314 + tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));4.315 + break;4.316 + case 0x08: case 0x09: case 0x0A: case 0x0B:4.317 + strip_count = ((entry >> 25) & 0x0F)+1;4.318 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];4.319 + while( strip_count > 0 ) {4.320 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );4.321 + poly = poly->next;4.322 + strip_count--;4.323 + }4.324 + break;4.325 + default:4.326 + if( entry & 0x7E000000 ) {4.327 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];4.328 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );4.329 + }4.330 + }4.331 + }4.332 +4.333 }4.336 @@ -336,9 +466,26 @@4.337 /* Clip to the visible part of the tile */4.338 glScissor( tile_bounds[0], pvr2_scene.buffer_height-tile_bounds[3],4.339 tile_bounds[1]-tile_bounds[0], tile_bounds[3] - tile_bounds[2] );4.340 - if( IS_TILE_PTR(segment->opaque_ptr) ) {4.341 - gl_render_tilelist(segment->opaque_ptr);4.342 + if( display_driver->capabilities.stencil_bits != 0 &&4.343 + IS_TILE_PTR(segment->opaquemod_ptr) &&4.344 + !IS_EMPTY_TILE_LIST(segment->opaquemod_ptr) ) {4.345 + /* Don't do this unless there's actually some shadow polygons */4.346 +4.347 + /* Use colormask instead of drawbuffer for simplicity */4.348 + glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );4.349 + gl_render_tilelist_depthonly(segment->opaque_ptr);4.350 + gl_render_modifier_tilelist(segment->opaquemod_ptr);4.351 + glClear( GL_DEPTH_BUFFER_BIT );4.352 + glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );4.353 }4.354 + gl_render_tilelist(segment->opaque_ptr);4.355 + if( IS_TILE_PTR(segment->punchout_ptr) ) {4.356 + glEnable(GL_ALPHA_TEST );4.357 + render_autosort_tile(segment->punchout_ptr, RENDER_NORMAL );4.358 + glDisable(GL_ALPHA_TEST );4.359 + }4.360 + glDisable( GL_STENCIL_TEST );4.361 +4.362 if( IS_TILE_PTR(segment->trans_ptr) ) {4.363 if( pvr2_scene.sort_mode == SORT_NEVER ||4.364 (pvr2_scene.sort_mode == SORT_TILEFLAG && (segment->control&SEGMENT_SORT_TRANS))) {4.365 @@ -347,11 +494,6 @@4.366 render_autosort_tile(segment->trans_ptr, RENDER_NORMAL );4.367 }4.368 }4.369 - if( IS_TILE_PTR(segment->punchout_ptr) ) {4.370 - glEnable(GL_ALPHA_TEST );4.371 - render_autosort_tile(segment->punchout_ptr, RENDER_NORMAL );4.372 - glDisable(GL_ALPHA_TEST );4.373 - }4.374 } while( !IS_LAST_SEGMENT(segment++) );4.375 glDisable( GL_SCISSOR_TEST );
5.1 --- a/src/pvr2/scene.c Sun Sep 28 00:31:58 2008 +00005.2 +++ b/src/pvr2/scene.c Sun Sep 28 01:09:51 2008 +00005.3 @@ -27,6 +27,8 @@5.4 #include "pvr2/glutil.h"5.5 #include "pvr2/scene.h"5.7 +#define U8TOFLOAT(n) (((float)((n)+1))/256.0)5.8 +5.9 static void unpack_bgra(uint32_t bgra, float *rgba)5.10 {5.11 rgba[0] = ((float)(((bgra&0x00FF0000)>>16) + 1)) / 256.0;5.12 @@ -65,10 +67,10 @@5.13 return u.f;5.14 }5.16 -5.17 struct pvr2_scene_struct pvr2_scene;5.19 static gboolean vbo_init = FALSE;5.20 +static float scene_shadow_intensity = 0.0;5.22 #ifdef ENABLE_VERTEX_BUFFER5.23 static gboolean vbo_supported = FALSE;5.24 @@ -173,9 +175,9 @@5.25 }5.27 static struct polygon_struct *scene_add_polygon( pvraddr_t poly_idx, int vertex_count,5.28 - gboolean is_modified )5.29 + shadow_mode_t is_modified )5.30 {5.31 - int vert_mul = is_modified ? 2 : 1;5.32 + int vert_mul = is_modified != SHADOW_NONE ? 2 : 1;5.34 if( pvr2_scene.buf_to_poly_map[poly_idx] != NULL ) {5.35 if( vertex_count > pvr2_scene.buf_to_poly_map[poly_idx]->vertex_count ) {5.36 @@ -389,8 +391,31 @@5.37 }5.38 }5.40 +static void scene_add_cheap_shadow_vertexes( struct vertex_struct *src, struct vertex_struct *dest, int count )5.41 +{5.42 + unsigned int i, j;5.43 +5.44 + for( i=0; i<count; i++ ) {5.45 + dest->x = src->x;5.46 + dest->y = src->y;5.47 + dest->z = src->z;5.48 + dest->u = src->u;5.49 + dest->v = src->v;5.50 + dest->rgba[0] = src->rgba[0] * scene_shadow_intensity;5.51 + dest->rgba[1] = src->rgba[1] * scene_shadow_intensity;5.52 + dest->rgba[2] = src->rgba[2] * scene_shadow_intensity;5.53 + dest->rgba[3] = src->rgba[3] * scene_shadow_intensity;5.54 + dest->offset_rgba[0] = src->offset_rgba[0] * scene_shadow_intensity;5.55 + dest->offset_rgba[1] = src->offset_rgba[1] * scene_shadow_intensity;5.56 + dest->offset_rgba[2] = src->offset_rgba[2] * scene_shadow_intensity;5.57 + dest->offset_rgba[3] = src->offset_rgba[3];5.58 + dest++;5.59 + src++;5.60 + }5.61 +}5.62 +5.63 static void scene_add_vertexes( pvraddr_t poly_idx, int vertex_length,5.64 - gboolean is_modified )5.65 + shadow_mode_t is_modified )5.66 {5.67 struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_idx];5.68 uint32_t *ptr = &pvr2_scene.pvr2_pbuf[poly_idx];5.69 @@ -398,7 +423,7 @@5.70 unsigned int i;5.72 if( poly->vertex_index == -1 ) {5.73 - ptr += (is_modified ? 5 : 3 );5.74 + ptr += (is_modified == SHADOW_FULL ? 5 : 3 );5.75 poly->vertex_index = pvr2_scene.vertex_index;5.77 assert( poly != NULL );5.78 @@ -408,20 +433,26 @@5.79 ptr += vertex_length;5.80 }5.81 if( is_modified ) {5.82 - int mod_offset = (vertex_length - 3)>>1;5.83 assert( pvr2_scene.vertex_index + poly->vertex_count <= pvr2_scene.vertex_count );5.84 - ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;5.85 poly->mod_vertex_index = pvr2_scene.vertex_index;5.86 - for( i=0; i<poly->vertex_count; i++ ) {5.87 - pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[3], ptr, mod_offset );5.88 - ptr += vertex_length;5.89 + if( is_modified == SHADOW_FULL ) {5.90 + int mod_offset = (vertex_length - 3)>>1;5.91 + ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;5.92 + for( i=0; i<poly->vertex_count; i++ ) {5.93 + pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[3], ptr, mod_offset );5.94 + ptr += vertex_length;5.95 + }5.96 + } else {5.97 + scene_add_cheap_shadow_vertexes( &pvr2_scene.vertex_array[poly->vertex_index],5.98 + &pvr2_scene.vertex_array[poly->mod_vertex_index], poly->vertex_count );5.99 + pvr2_scene.vertex_index += poly->vertex_count;5.100 }5.101 }5.102 }5.103 }5.105 static void scene_add_quad_vertexes( pvraddr_t poly_idx, int vertex_length,5.106 - gboolean is_modified )5.107 + shadow_mode_t is_modified )5.108 {5.109 struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_idx];5.110 uint32_t *ptr = &pvr2_scene.pvr2_pbuf[poly_idx];5.111 @@ -436,7 +467,7 @@5.113 assert( poly != NULL );5.114 assert( pvr2_scene.vertex_index + poly->vertex_count <= pvr2_scene.vertex_count );5.115 - ptr += (is_modified ? 5 : 3 );5.116 + ptr += (is_modified == SHADOW_FULL ? 5 : 3 );5.117 poly->vertex_index = pvr2_scene.vertex_index;5.118 for( i=0; i<4; i++ ) {5.119 pvr2_decode_render_vertex( &quad[i], context[0], context[1], ptr, 0 );5.120 @@ -450,18 +481,24 @@5.121 pvr2_scene.vertex_index += 4;5.123 if( is_modified ) {5.124 - int mod_offset = (vertex_length - 3)>>1;5.125 assert( pvr2_scene.vertex_index + poly->vertex_count <= pvr2_scene.vertex_count );5.126 - ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;5.127 poly->mod_vertex_index = pvr2_scene.vertex_index;5.128 - for( i=0; i<4; i++ ) {5.129 - pvr2_decode_render_vertex( &quad[4], context[0], context[3], ptr, mod_offset );5.130 - ptr += vertex_length;5.131 + if( is_modified == SHADOW_FULL ) {5.132 + int mod_offset = (vertex_length - 3)>>1;5.133 + ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;5.134 + for( i=0; i<4; i++ ) {5.135 + pvr2_decode_render_vertex( &quad[4], context[0], context[3], ptr, mod_offset );5.136 + ptr += vertex_length;5.137 + }5.138 + scene_compute_vertexes( &quad[3], 1, &quad[0], !POLY1_GOURAUD_SHADED(context[0]) );5.139 + memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index], quad, sizeof(struct vertex_struct)*2 );5.140 + memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+2], &quad[3], sizeof(struct vertex_struct) );5.141 + memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+3], &quad[2], sizeof(struct vertex_struct) );5.142 + } else {5.143 + scene_add_cheap_shadow_vertexes( &pvr2_scene.vertex_array[poly->vertex_index],5.144 + &pvr2_scene.vertex_array[poly->mod_vertex_index], poly->vertex_count );5.145 + pvr2_scene.vertex_index += poly->vertex_count;5.146 }5.147 - scene_compute_vertexes( &quad[3], 1, &quad[0], !POLY1_GOURAUD_SHADED(context[0]) );5.148 - memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index], quad, sizeof(struct vertex_struct)*2 );5.149 - memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+2], &quad[3], sizeof(struct vertex_struct) );5.150 - memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+3], &quad[2], sizeof(struct vertex_struct) );5.151 pvr2_scene.vertex_index += 4;5.152 }5.153 }5.154 @@ -478,10 +515,10 @@5.155 tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));5.156 } else {5.157 pvraddr_t polyaddr = entry&0x000FFFFF;5.158 - int is_modified = (entry & 0x01000000) && pvr2_scene.full_shadow;5.159 + shadow_mode_t is_modified = (entry & 0x01000000) ? pvr2_scene.shadow_mode : SHADOW_NONE;5.160 int vertex_length = (entry >> 21) & 0x07;5.161 int context_length = 3;5.162 - if( is_modified ) {5.163 + if( is_modified == SHADOW_FULL ) {5.164 context_length = 5;5.165 vertex_length <<= 1 ;5.166 }5.167 @@ -543,10 +580,10 @@5.168 tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));5.169 } else {5.170 pvraddr_t polyaddr = entry&0x000FFFFF;5.171 - int is_modified = (entry & 0x01000000) && pvr2_scene.full_shadow;5.172 + shadow_mode_t is_modified = (entry & 0x01000000) ? pvr2_scene.shadow_mode : SHADOW_NONE;5.173 int vertex_length = (entry >> 21) & 0x07;5.174 int context_length = 3;5.175 - if( is_modified ) {5.176 + if( is_modified == SHADOW_FULL ) {5.177 context_length = 5;5.178 vertex_length <<=1 ;5.179 }5.180 @@ -592,16 +629,18 @@5.181 uint32_t bgplane = MMIO_READ(PVR2, RENDER_BGPLANE);5.182 int vertex_length = (bgplane >> 24) & 0x07;5.183 int context_length = 3, i;5.184 - int is_modified = (bgplane & 0x08000000) && pvr2_scene.full_shadow;5.185 + shadow_mode_t is_modified = (bgplane & 0x08000000) ? pvr2_scene.shadow_mode : SHADOW_NONE;5.187 struct polygon_struct *poly = &pvr2_scene.poly_array[pvr2_scene.poly_count++];5.188 uint32_t *context = &pvr2_scene.pvr2_pbuf[(bgplane & 0x00FFFFFF)>>3];5.189 poly->context = context;5.190 poly->vertex_count = 4;5.191 poly->vertex_index = pvr2_scene.vertex_count;5.192 - if( is_modified ) {5.193 + if( is_modified == SHADOW_FULL ) {5.194 context_length = 5;5.195 vertex_length <<= 1;5.196 + }5.197 + if( is_modified != SHADOW_NONE ) {5.198 poly->mod_vertex_index = pvr2_scene.vertex_count + 4;5.199 pvr2_scene.vertex_count += 8;5.200 } else {5.201 @@ -628,7 +667,7 @@5.202 result_vertexes[2].y = result_vertexes[3].y = pvr2_scene.buffer_height;5.203 scene_compute_vertexes( result_vertexes, 4, base_vertexes, !POLY1_GOURAUD_SHADED(context[0]) );5.205 - if( is_modified ) {5.206 + if( is_modified == SHADOW_FULL ) {5.207 int mod_offset = (vertex_length - 3)>>1;5.208 ptr = context + context_length;5.209 for( i=0; i<3; i++ ) {5.210 @@ -642,6 +681,10 @@5.211 result_vertexes[1].y = result_vertexes[2].x = 0;5.212 result_vertexes[2].y = result_vertexes[3].y = pvr2_scene.buffer_height;5.213 scene_compute_vertexes( result_vertexes, 4, base_vertexes, !POLY1_GOURAUD_SHADED(context[0]) );5.214 + } else if( is_modified == SHADOW_CHEAP ) {5.215 + scene_add_cheap_shadow_vertexes( &pvr2_scene.vertex_array[poly->vertex_index],5.216 + &pvr2_scene.vertex_array[poly->mod_vertex_index], poly->vertex_count );5.217 + pvr2_scene.vertex_index += poly->vertex_count;5.218 }5.220 }5.221 @@ -696,9 +739,11 @@5.223 uint32_t *tilebuffer = (uint32_t *)(video_base + MMIO_READ( PVR2, RENDER_TILEBASE ));5.224 uint32_t *segment = tilebuffer;5.225 + uint32_t shadow = MMIO_READ(PVR2,RENDER_SHADOW);5.226 pvr2_scene.segment_list = (struct tile_segment *)tilebuffer;5.227 pvr2_scene.pvr2_pbuf = (uint32_t *)(video_base + MMIO_READ(PVR2,RENDER_POLYBASE));5.228 - pvr2_scene.full_shadow = MMIO_READ( PVR2, RENDER_SHADOW ) & 0x100 ? FALSE : TRUE;5.229 + pvr2_scene.shadow_mode = shadow & 0x100 ? SHADOW_CHEAP : SHADOW_FULL;5.230 + scene_shadow_intensity = U8TOFLOAT(shadow&0xFF);5.232 int max_tile_x = 0;5.233 int max_tile_y = 0;
6.1 --- a/src/pvr2/scene.h Sun Sep 28 00:31:58 2008 +00006.2 +++ b/src/pvr2/scene.h Sun Sep 28 01:09:51 2008 +00006.3 @@ -31,6 +31,9 @@6.4 SORT_ALWAYS = 26.5 } tile_sort_mode_t;6.7 +typedef enum { SHADOW_NONE=0, SHADOW_CHEAP=1, SHADOW_FULL=2 } shadow_mode_t;6.8 +6.9 +6.10 struct vertex_struct {6.11 float u,v;6.12 float x,y,z;6.13 @@ -120,12 +123,10 @@6.14 * render the scene */6.15 uint32_t buffer_width, buffer_height;6.17 - /** True if modifier volumes use the two-parameter form, False if they6.18 - * use the cheap-shadow option.6.19 - */6.20 - gboolean full_shadow;6.21 /** Specifies the translucency auto-sort mode for the scene */6.22 tile_sort_mode_t sort_mode;6.23 +6.24 + shadow_mode_t shadow_mode;6.26 float fog_lut_colour[4];6.27 float fog_vert_colour[4];
.