Search
lxdream.org :: lxdream :: r863:a5e5310061e2
lxdream 0.9.1
released Jun 29
Download Now
changeset863:a5e5310061e2
parent862:d3b2066d5daa
child864:a90f3d5e57e1
authornkeynes
dateSun 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)
src/display.h
src/drivers/gl_fbo.c
src/drivers/video_glx.c
src/pvr2/glrender.c
src/pvr2/scene.c
src/pvr2/scene.h
1.1 --- a/src/display.h Sun Sep 28 00:31:58 2008 +0000
1.2 +++ b/src/display.h Sun Sep 28 01:09:51 2008 +0000
1.3 @@ -102,6 +102,10 @@
1.4 unsigned char *data;
1.5 };
1.6
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 handle
1.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.17
1.18 + struct display_capabilities capabilities;
1.19 } *display_driver_t;
1.20
1.21 /**
2.1 --- a/src/drivers/gl_fbo.c Sun Sep 28 00:31:58 2008 +0000
2.2 +++ b/src/drivers/gl_fbo.c Sun Sep 28 01:09:51 2008 +0000
2.3 @@ -58,6 +58,7 @@
2.4 };
2.5
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.9
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.14
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.30
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 this
2.58 + * isn't actually supported by any hardware I've had access to, so we're
2.59 + * stencil-less.
2.60 + */
2.61 + }
2.62 fbo[bufno].width = width;
2.63 fbo[bufno].height = height;
2.64 }
2.65
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 +0000
3.2 +++ b/src/drivers/video_glx.c Sun Sep 28 01:09:51 2008 +0000
3.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_BUILD
3.9 + /* fbconfig is broken on at least the 10.5 GLX implementation */
3.10 + glx_fbconfig_supported = FALSE;
3.11 +#else
3.12 glx_fbconfig_supported = (glx_version >= 103 ||
3.13 isServerGLXExtensionSupported(display, screen,
3.14 "GLX_SGIX_fbconfig") );
3.15 +#endif
3.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.30
3.31 @@ -133,7 +139,7 @@
3.32 }
3.33
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 +0000
4.2 +++ b/src/pvr2/glrender.c Sun Sep 28 01:09:51 2008 +0000
4.3 @@ -24,6 +24,8 @@
4.4 #include "pvr2/scene.h"
4.5 #include "pvr2/glutil.h"
4.6
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.31
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 context
4.35 - * @param modified boolean flag indicating that the modified
4.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 sum
4.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.54
4.55 @@ -151,60 +146,84 @@
4.56 break;
4.57 }
4.58
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.67
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.108
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 context
4.138 + * @param modified boolean flag indicating that the modified
4.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.178
4.179 + render_set_base_context(poly1);
4.180 + render_set_tsp_context(poly1,poly2,texture);
4.181 }
4.182
4.183
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.209
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.217
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.225
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-list
4.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-list
4.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.334
4.335
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 );
4.376
5.1 --- a/src/pvr2/scene.c Sun Sep 28 00:31:58 2008 +0000
5.2 +++ b/src/pvr2/scene.c Sun Sep 28 01:09:51 2008 +0000
5.3 @@ -27,6 +27,8 @@
5.4 #include "pvr2/glutil.h"
5.5 #include "pvr2/scene.h"
5.6
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.15
5.16 -
5.17 struct pvr2_scene_struct pvr2_scene;
5.18
5.19 static gboolean vbo_init = FALSE;
5.20 +static float scene_shadow_intensity = 0.0;
5.21
5.22 #ifdef ENABLE_VERTEX_BUFFER
5.23 static gboolean vbo_supported = FALSE;
5.24 @@ -173,9 +175,9 @@
5.25 }
5.26
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.33
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.39
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.71
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.76
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.104
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.112
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.122
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.186
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.204
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.219
5.220 }
5.221 @@ -696,9 +739,11 @@
5.222
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.231
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 +0000
6.2 +++ b/src/pvr2/scene.h Sun Sep 28 01:09:51 2008 +0000
6.3 @@ -31,6 +31,9 @@
6.4 SORT_ALWAYS = 2
6.5 } tile_sort_mode_t;
6.6
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.16
6.17 - /** True if modifier volumes use the two-parameter form, False if they
6.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.25
6.26 float fog_lut_colour[4];
6.27 float fog_vert_colour[4];
.