diff options
author | Ben Skeggs <skeggsb@gmail.com> | 2007-11-21 15:38:28 +1100 |
---|---|---|
committer | Ben Skeggs <skeggsb@gmail.com> | 2007-11-21 15:38:28 +1100 |
commit | af1a38893946cf2fabd0fc6956efd07ef15b954b (patch) | |
tree | 32802116388e3fd0e49e524b172fba04b6fc6710 /src | |
parent | 0655cdcf48daecbe10ff8c16c443686a64848d1b (diff) | |
parent | 5a6017d496ccce94d7e3cf9a6cfe1db886dcc767 (diff) |
Merge branch 'upstream-gallium-0.1' into darktama-gallium-0.1
Diffstat (limited to 'src')
27 files changed, 545 insertions, 377 deletions
diff --git a/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c index 49e04d81ec..ed223977e2 100644 --- a/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c @@ -307,20 +307,6 @@ intel_batchbuffer_flush(struct intel_batchbuffer *batch) } -void -intel_batchbuffer_finish(struct intel_batchbuffer *batch) -{ - struct _DriFenceObject *fence = intel_batchbuffer_flush(batch); - if (fence) { - driFenceReference(fence); - driFenceFinish(fence, - DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, - GL_FALSE); - driFenceUnReference(fence); - } -} - - /* This is the only way buffers get added to the validate list. */ boolean diff --git a/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h index 82feafa21f..2c943e68e5 100644 --- a/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h +++ b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h @@ -72,8 +72,6 @@ struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context *intel); void intel_batchbuffer_free(struct intel_batchbuffer *batch); -void intel_batchbuffer_finish(struct intel_batchbuffer *batch); - struct _DriFenceObject *intel_batchbuffer_flush(struct intel_batchbuffer *batch); diff --git a/src/mesa/drivers/dri/intel_winsys/intel_winsys.h b/src/mesa/drivers/dri/intel_winsys/intel_winsys.h index 89e63e0a79..f944cd23c3 100644 --- a/src/mesa/drivers/dri/intel_winsys/intel_winsys.h +++ b/src/mesa/drivers/dri/intel_winsys/intel_winsys.h @@ -32,7 +32,9 @@ struct intel_context; struct pipe_context; struct pipe_winsys; struct pipe_buffer_handle; +struct pipe_fence; struct _DriBufferObject; +struct _DriFenceObject; struct pipe_winsys * intel_create_pipe_winsys( int fd ); @@ -66,5 +68,20 @@ pipe_bo( struct _DriBufferObject *bo ) } +/* Turn the pipe opaque buffer pointer into a dri_bufmgr opaque + * buffer pointer... + */ +static INLINE struct _DriFenceObject * +dri_fo( struct pipe_fence *bo ) +{ + return (struct _DriFenceObject *)bo; +} + +static INLINE struct pipe_fence * +pipe_fo( struct _DriFenceObject *bo ) +{ + return (struct pipe_fence *)bo; +} + #endif diff --git a/src/mesa/drivers/dri/intel_winsys/intel_winsys_i915.c b/src/mesa/drivers/dri/intel_winsys/intel_winsys_i915.c index 8e0eea4392..d73b309fd4 100644 --- a/src/mesa/drivers/dri/intel_winsys/intel_winsys_i915.c +++ b/src/mesa/drivers/dri/intel_winsys/intel_winsys_i915.c @@ -111,19 +111,62 @@ static void intel_i915_batch_reloc( struct i915_winsys *sws, -static void intel_i915_batch_flush( struct i915_winsys *sws ) +static void +intel_i915_batch_flush( struct i915_winsys *sws, + struct pipe_fence **fence ) { struct intel_context *intel = intel_i915_winsys(sws)->intel; + struct pipe_fence *tmp_fence; + + tmp_fence = pipe_fo(intel_batchbuffer_flush( intel->batch )); + + /* this also increases the fence reference count, which is not done inside + * intel_batchbuffer_flush call above + */ + sws->fence_reference(sws, fence, tmp_fence); +} - intel_batchbuffer_flush( intel->batch ); -// if (0) intel_i915_batch_wait_idle( sws ); + +static void +intel_i915_fence_reference( struct i915_winsys *sws, + struct pipe_fence **dst_fence, + struct pipe_fence *src_fence ) +{ + struct _DriFenceObject **dri_dst_fence = (struct _DriFenceObject **)dst_fence; + struct _DriFenceObject *dri_src_fence = (struct _DriFenceObject *)src_fence; + + if(dri_src_fence) + driFenceReference(dri_src_fence); + + if(*dri_dst_fence) + driFenceUnReference(*dri_dst_fence); + + *dri_dst_fence = dri_src_fence; } -static void intel_i915_batch_finish( struct i915_winsys *sws ) +static int +intel_i915_fence_is_signalled( struct i915_winsys *sws, + struct pipe_fence *fence ) { - struct intel_context *intel = intel_i915_winsys(sws)->intel; - intel_batchbuffer_finish( intel->batch ); + struct _DriFenceObject *dri_fence = dri_fo(fence); + if (fence) + return driFenceSignaled(dri_fence, + DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW); + return 1; +} + + +static int +intel_i915_fence_wait( struct i915_winsys *sws, + struct pipe_fence *fence ) +{ + struct _DriFenceObject *dri_fence = dri_fo(fence); + if (fence) + driFenceFinish(dri_fence, + DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, + GL_FALSE); + return 1; } @@ -143,7 +186,10 @@ intel_create_i915simple( struct intel_context *intel, iws->winsys.batch_dword = intel_i915_batch_dword; iws->winsys.batch_reloc = intel_i915_batch_reloc; iws->winsys.batch_flush = intel_i915_batch_flush; - iws->winsys.batch_finish = intel_i915_batch_finish; + iws->winsys.fence_reference = intel_i915_fence_reference; + iws->winsys.fence_is_signalled = intel_i915_fence_is_signalled; + iws->winsys.fence_wait = intel_i915_fence_wait; + iws->intel = intel; /* Create the i915simple context: diff --git a/src/mesa/pipe/draw/draw_validate.c b/src/mesa/pipe/draw/draw_validate.c index fdeb1be8ca..4e8f986b27 100644 --- a/src/mesa/pipe/draw/draw_validate.c +++ b/src/mesa/pipe/draw/draw_validate.c @@ -85,6 +85,7 @@ static void validate_begin( struct draw_stage *stage ) /* Clip stage */ + if (!draw->rasterizer->bypass_clipping) { draw->pipeline.clip->next = next; next = draw->pipeline.clip; diff --git a/src/mesa/pipe/draw/draw_vertex_fetch.c b/src/mesa/pipe/draw/draw_vertex_fetch.c index eca10e89fb..b510a4dbba 100644 --- a/src/mesa/pipe/draw/draw_vertex_fetch.c +++ b/src/mesa/pipe/draw/draw_vertex_fetch.c @@ -37,6 +37,10 @@ #include "pipe/tgsi/exec/tgsi_core.h" + +#define DBG 0 + + /** * Fetch a float[4] vertex attribute from memory, doing format/type * conversion as needed. @@ -96,7 +100,9 @@ void draw_vertex_fetch( struct draw_context *draw, for (j = 0; j < count; j++) { uint attr; - /*printf("fetch vertex %u: \n", j);*/ +#if DBG + printf("fetch vertex %u: \n", j); +#endif /* loop over vertex attributes (vertex shader inputs) */ for (attr = 0; attr < draw->vertex_shader->state->num_inputs; attr++) { @@ -111,7 +117,9 @@ void draw_vertex_fetch( struct draw_context *draw, fetch_attrib4(src, draw->vertex_element[attr].src_format, p); - /*printf(" %u: %f %f %f %f\n", attr, p[0], p[1], p[2], p[3]);*/ +#if DBG + printf(" %u: %f %f %f %f\n", attr, p[0], p[1], p[2], p[3]); +#endif /* Transform to AoS xxxx/yyyy/zzzz/wwww representation: */ diff --git a/src/mesa/pipe/i915simple/i915_batch.h b/src/mesa/pipe/i915simple/i915_batch.h index fb88cd6db0..603d193f62 100644 --- a/src/mesa/pipe/i915simple/i915_batch.h +++ b/src/mesa/pipe/i915simple/i915_batch.h @@ -44,11 +44,11 @@ #define ADVANCE_BATCH() -#define FLUSH_BATCH() do { \ - if (0) i915_dump_batchbuffer( i915 ); \ - i915->winsys->batch_flush( i915->winsys ); \ - i915->batch_start = NULL; \ - i915->hardware_dirty = ~0; \ +#define FLUSH_BATCH() do { \ + if (0) i915_dump_batchbuffer( i915 ); \ + i915->winsys->batch_flush( i915->winsys, &i915->last_fence ); \ + i915->batch_start = NULL; \ + i915->hardware_dirty = ~0; \ } while (0) #endif diff --git a/src/mesa/pipe/i915simple/i915_context.c b/src/mesa/pipe/i915simple/i915_context.c index e43274dc66..f5d770ce0d 100644 --- a/src/mesa/pipe/i915simple/i915_context.c +++ b/src/mesa/pipe/i915simple/i915_context.c @@ -175,6 +175,8 @@ static void i915_destroy( struct pipe_context *pipe ) draw_destroy( i915->draw ); + i915->winsys->fence_reference( i915->winsys, &i915->last_fence, NULL ); + free( i915 ); } diff --git a/src/mesa/pipe/i915simple/i915_context.h b/src/mesa/pipe/i915simple/i915_context.h index ee430ebc90..488682f852 100644 --- a/src/mesa/pipe/i915simple/i915_context.h +++ b/src/mesa/pipe/i915simple/i915_context.h @@ -80,6 +80,7 @@ +struct pipe_fence; struct i915_cache_context; /* Use to calculate differences between state emitted to hardware and @@ -184,6 +185,8 @@ struct i915_context unsigned dirty; unsigned *batch_start; + + struct pipe_fence *last_fence; /** Vertex buffer */ struct pipe_buffer_handle *vbo; diff --git a/src/mesa/pipe/i915simple/i915_flush.c b/src/mesa/pipe/i915simple/i915_flush.c index 3c2069b827..1044cb1bdb 100644 --- a/src/mesa/pipe/i915simple/i915_flush.c +++ b/src/mesa/pipe/i915simple/i915_flush.c @@ -69,7 +69,8 @@ static void i915_flush( struct pipe_context *pipe, FLUSH_BATCH(); if (flags & PIPE_FLUSH_WAIT) { - i915->winsys->batch_finish(i915->winsys); + if( i915->last_fence ) + i915->winsys->fence_wait(i915->winsys, i915->last_fence); } } diff --git a/src/mesa/pipe/i915simple/i915_winsys.h b/src/mesa/pipe/i915simple/i915_winsys.h index 2c0f335d34..386ed745d3 100644 --- a/src/mesa/pipe/i915simple/i915_winsys.h +++ b/src/mesa/pipe/i915simple/i915_winsys.h @@ -52,6 +52,7 @@ struct pipe_buffer_handle; struct pipe_winsys; +struct pipe_fence; /** @@ -97,8 +98,28 @@ struct i915_winsys { unsigned access_flags, unsigned delta ); - void (*batch_flush)( struct i915_winsys *sws ); - void (*batch_finish)( struct i915_winsys *sws ); + /** + * Flush the batch buffer. + * + * Fence argument must point to NULL or to a previous fence, and the caller + * must call fence_reference when done with the fence. + */ + void (*batch_flush)( struct i915_winsys *sws, + struct pipe_fence **fence ); + + + /* Fence + */ + void (*fence_reference)( struct i915_winsys *sws, + struct pipe_fence **dst_fence, + struct pipe_fence *src_fence ); + + int (*fence_is_signalled)( struct i915_winsys *sws, + struct pipe_fence *fence ); + + int (*fence_wait)( struct i915_winsys *sws, + struct pipe_fence *fence ); + }; #define I915_BUFFER_ACCESS_WRITE 0x1 diff --git a/src/mesa/pipe/p_state.h b/src/mesa/pipe/p_state.h index 848c32701f..570f44e24e 100644 --- a/src/mesa/pipe/p_state.h +++ b/src/mesa/pipe/p_state.h @@ -92,6 +92,7 @@ struct pipe_rasterizer_state unsigned line_stipple_enable:1; unsigned line_stipple_factor:8; /**< [1..256] actually */ unsigned line_stipple_pattern:16; + unsigned bypass_clipping:1; float line_width; float point_size; /**< used when no per-vertex size */ diff --git a/src/mesa/pipe/softpipe/Makefile b/src/mesa/pipe/softpipe/Makefile index 2cbd9e5b51..59628531cc 100644 --- a/src/mesa/pipe/softpipe/Makefile +++ b/src/mesa/pipe/softpipe/Makefile @@ -18,6 +18,7 @@ DRIVER_SOURCES = \ sp_quad_colormask.c \ sp_quad_coverage.c \ sp_quad_depth_test.c \ + sp_quad_earlyz.c \ sp_quad_fs.c \ sp_quad_occlusion.c \ sp_quad_output.c \ diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c index be4da0ec64..d5e68c189d 100644 --- a/src/mesa/pipe/softpipe/sp_context.c +++ b/src/mesa/pipe/softpipe/sp_context.c @@ -161,6 +161,7 @@ static void softpipe_destroy( struct pipe_context *pipe ) draw_destroy( softpipe->draw ); softpipe->quad.polygon_stipple->destroy( softpipe->quad.polygon_stipple ); + softpipe->quad.earlyz->destroy( softpipe->quad.earlyz ); softpipe->quad.shade->destroy( softpipe->quad.shade ); softpipe->quad.alpha_test->destroy( softpipe->quad.alpha_test ); softpipe->quad.depth_test->destroy( softpipe->quad.depth_test ); @@ -369,6 +370,7 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys, /* setup quad rendering stages */ softpipe->quad.polygon_stipple = sp_quad_polygon_stipple_stage(softpipe); + softpipe->quad.earlyz = sp_quad_earlyz_stage(softpipe); softpipe->quad.shade = sp_quad_shade_stage(softpipe); softpipe->quad.alpha_test = sp_quad_alpha_test_stage(softpipe); softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe); diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h index a411969bc0..872766101d 100644 --- a/src/mesa/pipe/softpipe/sp_context.h +++ b/src/mesa/pipe/softpipe/sp_context.h @@ -134,6 +134,7 @@ struct softpipe_context { /** Software quad rendering pipeline */ struct { struct quad_stage *polygon_stipple; + struct quad_stage *earlyz; struct quad_stage *shade; struct quad_stage *alpha_test; struct quad_stage *stencil_test; diff --git a/src/mesa/pipe/softpipe/sp_quad.c b/src/mesa/pipe/softpipe/sp_quad.c index 429497e9b2..5a0df6de9d 100644 --- a/src/mesa/pipe/softpipe/sp_quad.c +++ b/src/mesa/pipe/softpipe/sp_quad.c @@ -28,24 +28,52 @@ #include "sp_context.h" +#include "sp_state.h" +#include "pipe/tgsi/exec/tgsi_token.h" +static void +sp_push_quad_first( + struct softpipe_context *sp, + struct quad_stage *quad ) +{ + quad->next = sp->quad.first; + sp->quad.first = quad; +} + +static void +sp_build_depth_stencil( + struct softpipe_context *sp ) +{ + if (sp->depth_stencil->stencil.front_enabled || + sp->depth_stencil->stencil.back_enabled) { + sp_push_quad_first( sp, sp->quad.stencil_test ); + } + else if (sp->depth_stencil->depth.enabled && + sp->framebuffer.zbuf) { + sp_push_quad_first( sp, sp->quad.depth_test ); + } +} void sp_build_quad_pipeline(struct softpipe_context *sp) { + boolean early_depth_test = + sp->depth_stencil->depth.enabled && + sp->framebuffer.zbuf && + !sp->alpha_test->enabled && + sp->fs->shader.output_semantic_name[0] != TGSI_SEMANTIC_POSITION; + /* build up the pipeline in reverse order... */ sp->quad.first = sp->quad.output; if (sp->blend->colormask != 0xf) { - sp->quad.colormask->next = sp->quad.first; - sp->quad.first = sp->quad.colormask; + sp_push_quad_first( sp, sp->quad.colormask ); } if (sp->blend->blend_enable || sp->blend->logicop_enable) { - sp->quad.blend->next = sp->quad.first; - sp->quad.first = sp->quad.blend; + sp_push_quad_first( sp, sp->quad.blend ); } if (sp->framebuffer.num_cbufs == 1) { @@ -54,46 +82,38 @@ sp_build_quad_pipeline(struct softpipe_context *sp) } else { /* insert bufloop stage */ - sp->quad.bufloop->next = sp->quad.first; - sp->quad.first = sp->quad.bufloop; + sp_push_quad_first( sp, sp->quad.bufloop ); } if (sp->depth_stencil->depth.occlusion_count) { - sp->quad.occlusion->next = sp->quad.first; - sp->quad.first = sp->quad.occlusion; + sp_push_quad_first( sp, sp->quad.occlusion ); } if (sp->rasterizer->poly_smooth || sp->rasterizer->line_smooth || sp->rasterizer->point_smooth) { - sp->quad.coverage->next = sp->quad.first; - sp->quad.first = sp->quad.coverage; + sp_push_quad_first( sp, sp->quad.coverage ); } - if ( sp->depth_stencil->stencil.front_enabled - || sp->depth_stencil->stencil.back_enabled) { - sp->quad.stencil_test->next = sp->quad.first; - sp->quad.first = sp->quad.stencil_test; - } - else if (sp->depth_stencil->depth.enabled && - sp->framebuffer.zbuf) { - sp->quad.depth_test->next = sp->quad.first; - sp->quad.first = sp->quad.depth_test; + if (!early_depth_test) { + sp_build_depth_stencil( sp ); } if (sp->alpha_test->enabled) { - sp->quad.alpha_test->next = sp->quad.first; - sp->quad.first = sp->quad.alpha_test; + sp_push_quad_first( sp, sp->quad.alpha_test ); } /* XXX always enable shader? */ if (1) { - sp->quad.shade->next = sp->quad.first; - sp->quad.first = sp->quad.shade; + sp_push_quad_first( sp, sp->quad.shade ); + } + + if (early_depth_test) { + sp_build_depth_stencil( sp ); + sp_push_quad_first( sp, sp->quad.earlyz ); } if (sp->rasterizer->poly_stipple_enable) { - sp->quad.polygon_stipple->next = sp->quad.first; - sp->quad.first = sp->quad.polygon_stipple; + sp_push_quad_first( sp, sp->quad.polygon_stipple ); } } diff --git a/src/mesa/pipe/softpipe/sp_quad.h b/src/mesa/pipe/softpipe/sp_quad.h index 534541122b..f1e0281764 100644 --- a/src/mesa/pipe/softpipe/sp_quad.h +++ b/src/mesa/pipe/softpipe/sp_quad.h @@ -51,6 +51,7 @@ struct quad_stage { struct quad_stage *sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_earlyz_stage( struct softpipe_context *softpipe ); struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe ); struct quad_stage *sp_quad_alpha_test_stage( struct softpipe_context *softpipe ); struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe ); diff --git a/src/mesa/pipe/softpipe/sp_quad_depth_test.c b/src/mesa/pipe/softpipe/sp_quad_depth_test.c index f7e93af784..3318189621 100644 --- a/src/mesa/pipe/softpipe/sp_quad_depth_test.c +++ b/src/mesa/pipe/softpipe/sp_quad_depth_test.c @@ -119,6 +119,21 @@ sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad) } } break; + case PIPE_FORMAT_Z24_S8: + { + float scale = (float) ((1 << 24) - 1); + + for (j = 0; j < QUAD_SIZE; j++) { + qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale); + } + + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + bzzzz[j] = tile->data.depth32[y][x] >> 8; + } + } + break; default: assert(0); } @@ -210,6 +225,15 @@ sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad) tile->data.depth32[y][x] = s8z24; } break; + case PIPE_FORMAT_Z24_S8: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + uint z24s8 = tile->data.depth32[y][x]; + z24s8 = (z24s8 & 0xff) | (bzzzz[j] << 24); + tile->data.depth32[y][x] = z24s8; + } + break; default: assert(0); } diff --git a/src/mesa/pipe/softpipe/sp_quad_earlyz.c b/src/mesa/pipe/softpipe/sp_quad_earlyz.c new file mode 100644 index 0000000000..89fab2dd35 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_earlyz.c @@ -0,0 +1,92 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * \brief Quad early-z testing + */ + +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "sp_headers.h" +#include "sp_quad.h" + + +/** + * All this stage does is compute the quad's Z values (which is normally + * done by the shading stage). + * The next stage will do the actual depth test. + */ +static void +earlyz_quad( + struct quad_stage *qs, + struct quad_header *quad ) +{ + const float fx = (float) quad->x0; + const float fy = (float) quad->y0; + const float dzdx = quad->coef[0].dadx[2]; + const float dzdy = quad->coef[0].dady[2]; + const float z0 = quad->coef[0].a0[2] + dzdx * fx + dzdy * fy; + + quad->outputs.depth[0] = z0; + quad->outputs.depth[1] = z0 + dzdx; + quad->outputs.depth[2] = z0 + dzdy; + quad->outputs.depth[3] = z0 + dzdx + dzdy; + + if (qs->next) { + qs->next->run( qs->next, quad ); + } +} + +static void +earlyz_begin( + struct quad_stage *qs ) +{ + if (qs->next) { + qs->next->begin( qs->next ); + } +} + +static void +earlyz_destroy( + struct quad_stage *qs ) +{ + FREE( qs ); +} + +struct quad_stage * +sp_quad_earlyz_stage( + struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT( quad_stage ); + + stage->softpipe = softpipe; + stage->begin = earlyz_begin; + stage->run = earlyz_quad; + stage->destroy = earlyz_destroy; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_quad_fs.c b/src/mesa/pipe/softpipe/sp_quad_fs.c index 17fb10ea72..ed14dac18e 100644 --- a/src/mesa/pipe/softpipe/sp_quad_fs.c +++ b/src/mesa/pipe/softpipe/sp_quad_fs.c @@ -104,6 +104,10 @@ shade_quad( machine->Inputs[0].xyzw[0].f[2] = fx; machine->Inputs[0].xyzw[0].f[3] = fx + 1.0f; + /* XXX for OpenGL we need to invert the Y pos here (y=0=top). + * but that'll mess up linear/perspective interpolation of other + * attributes... + */ machine->Inputs[0].xyzw[1].f[0] = fy; machine->Inputs[0].xyzw[1].f[1] = fy; machine->Inputs[0].xyzw[1].f[2] = fy + 1.0f; diff --git a/src/mesa/pipe/softpipe/sp_quad_stencil.c b/src/mesa/pipe/softpipe/sp_quad_stencil.c index 831ad8bad0..0149b20f48 100644 --- a/src/mesa/pipe/softpipe/sp_quad_stencil.c +++ b/src/mesa/pipe/softpipe/sp_quad_stencil.c @@ -241,6 +241,13 @@ stencil_test_quad(struct quad_stage *qs, struct quad_header *quad) stencilVals[j] = tile->data.depth32[y][x] >> 24; } break; + case PIPE_FORMAT_Z24_S8: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + stencilVals[j] = tile->data.depth32[y][x] & 0xff; + } + break; case PIPE_FORMAT_U_S8: for (j = 0; j < QUAD_SIZE; j++) { int x = quad->x0 % TILE_SIZE + (j & 1); @@ -300,6 +307,15 @@ stencil_test_quad(struct quad_stage *qs, struct quad_header *quad) tile->data.depth32[y][x] = s8z24; } break; + case PIPE_FORMAT_Z24_S8: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + uint z24s8 = tile->data.depth32[y][x]; + z24s8 = (z24s8 & 0xffffff00) | stencilVals[j]; + tile->data.depth32[y][x] = z24s8; + } + break; case PIPE_FORMAT_U_S8: for (j = 0; j < QUAD_SIZE; j++) { int x = quad->x0 % TILE_SIZE + (j & 1); diff --git a/src/mesa/pipe/softpipe/sp_surface.c b/src/mesa/pipe/softpipe/sp_surface.c index ccaf38de3e..b7c9d4f004 100644 --- a/src/mesa/pipe/softpipe/sp_surface.c +++ b/src/mesa/pipe/softpipe/sp_surface.c @@ -461,6 +461,40 @@ s8z24_get_tile(struct pipe_surface *ps, } +/*** PIPE_FORMAT_Z24_S8 ***/ + +/** + * Return Z component as four float in [0,1]. Stencil part ignored. + */ +static void +z24s8_get_tile(struct pipe_surface *ps, + unsigned x, unsigned y, unsigned w, unsigned h, float *p) +{ + const uint *src + = ((const uint *) (ps->region->map + ps->offset)) + + y * ps->region->pitch + x; + const double scale = 1.0 / ((1 << 24) - 1); + unsigned i, j; + unsigned w0 = w; + + assert(ps->format == PIPE_FORMAT_Z24_S8); + + CLIP_TILE; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++) { + pRow[j * 4 + 0] = + pRow[j * 4 + 1] = + pRow[j * 4 + 2] = + pRow[j * 4 + 3] = (float) (scale * (src[j] >> 8)); + } + src += ps->region->pitch; + p += 4 * w0; + } +} + + /** * Called via pipe->get_tex_surface() * XXX is this in the right place? @@ -601,6 +635,9 @@ softpipe_get_tile_rgba(struct pipe_context *pipe, case PIPE_FORMAT_S8_Z24: s8z24_get_tile(ps, x, y, w, h, p); break; + case PIPE_FORMAT_Z24_S8: + z24s8_get_tile(ps, x, y, w, h, p); + break; default: assert(0); } @@ -645,6 +682,9 @@ softpipe_put_tile_rgba(struct pipe_context *pipe, case PIPE_FORMAT_S8_Z24: /*s8z24_put_tile(ps, x, y, w, h, p);*/ break; + case PIPE_FORMAT_Z24_S8: + /*z24s8_put_tile(ps, x, y, w, h, p);*/ + break; default: assert(0); } diff --git a/src/mesa/pipe/softpipe/sp_tile_cache.c b/src/mesa/pipe/softpipe/sp_tile_cache.c index 19c06323e1..ea0c8b8f91 100644 --- a/src/mesa/pipe/softpipe/sp_tile_cache.c +++ b/src/mesa/pipe/softpipe/sp_tile_cache.c @@ -166,6 +166,7 @@ sp_flush_tile_cache(struct softpipe_context *softpipe, return; is_depth_stencil = (ps->format == PIPE_FORMAT_S8_Z24 || + ps->format == PIPE_FORMAT_Z24_S8 || ps->format == PIPE_FORMAT_U_Z16 || ps->format == PIPE_FORMAT_U_Z32 || ps->format == PIPE_FORMAT_U_S8); @@ -203,6 +204,7 @@ sp_get_cached_tile(struct softpipe_context *softpipe, struct pipe_surface *ps = tc->surface; boolean is_depth_stencil = (ps->format == PIPE_FORMAT_S8_Z24 || + ps->format == PIPE_FORMAT_Z24_S8 || ps->format == PIPE_FORMAT_U_Z16 || ps->format == PIPE_FORMAT_U_Z32 || ps->format == PIPE_FORMAT_U_S8); @@ -268,6 +270,17 @@ sp_get_cached_tile(struct softpipe_context *softpipe, } } break; + case PIPE_FORMAT_Z24_S8: + { + uint clear_val = ((uint) (tc->clear_value[0] * 0xffffff)) << 8; + clear_val |= ((uint) tc->clear_value[1]) & 0xff; + for (i = 0; i < TILE_SIZE; i++) { + for (j = 0; j < TILE_SIZE; j++) { + tile->data.depth32[i][j] = clear_val; + } + } + } + break; case PIPE_FORMAT_U_S8: { ubyte clear_val = (uint) tc->clear_value[0]; diff --git a/src/mesa/pipe/tgsi/exec/tgsi_exec.c b/src/mesa/pipe/tgsi/exec/tgsi_exec.c index 5c2fecb3e3..ea6c5021b3 100644 --- a/src/mesa/pipe/tgsi/exec/tgsi_exec.c +++ b/src/mesa/pipe/tgsi/exec/tgsi_exec.c @@ -1346,17 +1346,15 @@ linear_interpolation( unsigned attrib, unsigned chan ) { - unsigned i; - - for( i = 0; i < QUAD_SIZE; i++ ) { - const float x = mach->Inputs[0].xyzw[0].f[i]; - const float y = mach->Inputs[0].xyzw[1].f[i]; - - mach->Inputs[attrib].xyzw[chan].f[i] = - mach->InterpCoefs[attrib].a0[chan] + - mach->InterpCoefs[attrib].dadx[chan] * x + - mach->InterpCoefs[attrib].dady[chan] * y; - } + const float x = mach->Inputs[0].xyzw[0].f[0]; + const float y = mach->Inputs[0].xyzw[1].f[0]; + const float dadx = mach->InterpCoefs[attrib].dadx[chan]; + const float dady = mach->InterpCoefs[attrib].dady[chan]; + const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y; + mach->Inputs[attrib].xyzw[chan].f[0] = a0; + mach->Inputs[attrib].xyzw[chan].f[1] = a0 + dadx; + mach->Inputs[attrib].xyzw[chan].f[2] = a0 + dady; + mach->Inputs[attrib].xyzw[chan].f[3] = a0 + dadx + dady; } static void @@ -1365,20 +1363,15 @@ perspective_interpolation( unsigned attrib, unsigned chan ) { - unsigned i; - - for( i = 0; i < QUAD_SIZE; i++ ) { - const float x = mach->Inputs[0].xyzw[0].f[i]; - const float y = mach->Inputs[0].xyzw[1].f[i]; - /* WPOS.w here is really 1/w */ - const float w = 1.0f / mach->Inputs[0].xyzw[3].f[i]; - assert(mach->Inputs[0].xyzw[3].f[i] != 0.0); - - mach->Inputs[attrib].xyzw[chan].f[i] = - (mach->InterpCoefs[attrib].a0[chan] + - mach->InterpCoefs[attrib].dadx[chan] * x + - mach->InterpCoefs[attrib].dady[chan] * y) * w; - } + const float x = mach->Inputs[0].xyzw[0].f[0]; + const float y = mach->Inputs[0].xyzw[1].f[0]; + const float dadx = mach->InterpCoefs[attrib].dadx[chan]; + const float dady = mach->InterpCoefs[attrib].dady[chan]; + const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y; + mach->Inputs[attrib].xyzw[chan].f[0] = a0 / mach->Inputs[0].xyzw[3].f[0]; + mach->Inputs[attrib].xyzw[chan].f[1] = (a0 + dadx) / mach->Inputs[0].xyzw[3].f[1]; + mach->Inputs[attrib].xyzw[chan].f[2] = (a0 + dady) / mach->Inputs[0].xyzw[3].f[2]; + mach->Inputs[attrib].xyzw[chan].f[3] = (a0 + dadx + dady) / mach->Inputs[0].xyzw[3].f[3]; } diff --git a/src/mesa/state_tracker/st_cb_rasterpos.c b/src/mesa/state_tracker/st_cb_rasterpos.c index 5b97c1ee34..5279cb1cd4 100644 --- a/src/mesa/state_tracker/st_cb_rasterpos.c +++ b/src/mesa/state_tracker/st_cb_rasterpos.c @@ -25,353 +25,229 @@ * **************************************************************************/ - /* - * Authors: - * Brian Paul - */ +/** + * glRasterPos implementation. Basically render a GL_POINT with our + * private draw module. Plug in a special "rasterpos" stage at the end + * of the 'draw' pipeline to capture the results and update the current + * raster pos attributes. + * + * Authors: + * Brian Paul + */ + #include "main/imports.h" -#include "main/feedback.h" #include "main/macros.h" #include "st_context.h" #include "st_atom.h" -#include "st_cache.h" #include "st_draw.h" -#include "st_program.h" #include "st_cb_rasterpos.h" #include "st_draw.h" -#include "st_format.h" -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_winsys.h" +#include "pipe/draw/draw_context.h" +#include "pipe/draw/draw_private.h" #include "shader/prog_instruction.h" +#include "vbo/vbo.h" -static void -setup_vertex_attribs(GLcontext *ctx) +/** + * Our special drawing pipeline stage (replaces rasterization). + */ +struct rastpos_stage { - struct pipe_context *pipe = ctx->st->pipe; - const struct cso_vertex_shader *vs = ctx->st->state.vs; - const struct st_vertex_program *stvp = ctx->st->vp; - uint slot; - - /* all attributes come from the default attribute buffer */ - { - struct pipe_vertex_buffer vbuffer; - vbuffer.buffer = ctx->st->default_attrib_buffer; - vbuffer.buffer_offset = 0; - vbuffer.pitch = 0; /* must be zero! */ - vbuffer.max_index = 1; - pipe->set_vertex_buffer(pipe, 0, &vbuffer); - } + struct draw_stage stage; /**< Base class */ + GLcontext *ctx; /**< Rendering context */ - for (slot = 0; slot < vs->state.num_inputs; slot++) { - struct pipe_vertex_element velement; - const GLuint attr = stvp->index_to_input[slot]; + /* vertex attrib info we can setup once and re-use */ + struct gl_client_array array[VERT_ATTRIB_MAX]; + const struct gl_client_array *arrays[VERT_ATTRIB_MAX]; + struct _mesa_prim prim; +}; - velement.src_offset = attr * 4 * sizeof(GLfloat); - velement.vertex_buffer_index = 0; - velement.dst_offset = 0; - velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - pipe->set_vertex_element(pipe, slot, &velement); - } -} +static INLINE struct rastpos_stage * +rastpos_stage( struct draw_stage *stage ) +{ + return (struct rastpos_stage *) stage; +} static void -setup_feedback(GLcontext *ctx) +rastpos_begin( struct draw_stage *stage ) { - struct pipe_context *pipe = ctx->st->pipe; - const struct pipe_shader_state *vs = &ctx->st->state.vs->state; - struct pipe_feedback_state feedback; - uint i; - - memset(&feedback, 0, sizeof(feedback)); - feedback.enabled = 1; - feedback.interleaved = 1; - feedback.discard = 1; - feedback.num_attribs = 0; - - /* feedback all results from vertex shader */ - for (i = 0; i < vs->num_outputs; i++) { - feedback.attrib[feedback.num_attribs] = i; - feedback.size[feedback.num_attribs] = 4; - feedback.num_attribs++; - } - - if (pipe->set_feedback_state) - pipe->set_feedback_state(pipe, &feedback); + /* no-op */ } +static void +rastpos_end( struct draw_stage *stage ) +{ + /* no-op */ +} - - - -/** - * Clip a point against the view volume. - * - * \param v vertex vector describing the point to clip. - * - * \return zero if outside view volume, or one if inside. - */ -static GLuint -viewclip_point( const GLfloat v[] ) +static void +rastpos_reset_stipple_counter( struct draw_stage *stage ) { - if ( v[0] > v[3] || v[0] < -v[3] - || v[1] > v[3] || v[1] < -v[3] - || v[2] > v[3] || v[2] < -v[3] ) { - return 0; - } - else { - return 1; - } + /* no-op */ } +static void +rastpos_tri( struct draw_stage *stage, struct prim_header *prim ) +{ + /* should never get here */ + assert(0); +} -/** - * Clip a point against the far/near Z clipping planes. - * - * \param v vertex vector describing the point to clip. - * - * \return zero if outside view volume, or one if inside. - */ -static GLuint -viewclip_point_z( const GLfloat v[] ) +static void +rastpos_line( struct draw_stage *stage, struct prim_header *prim ) { - if (v[2] > v[3] || v[2] < -v[3] ) { - return 0; - } - else { - return 1; - } + /* should never get here */ + assert(0); } /** - * Clip a point against the user clipping planes. - * - * \param ctx GL context. - * \param v vertex vector describing the point to clip. - * - * \return zero if the point was clipped, or one otherwise. + * Update a raster pos attribute from the vertex result if it's present, + * else copy the current attrib. */ -static GLuint -userclip_point( GLcontext *ctx, const GLfloat v[] ) +static void +update_attrib(GLcontext *ctx, const GLuint *outputMapping, + const struct vertex_header *vert, + GLfloat *dest, + GLuint result, GLuint defaultAttrib) { - GLuint p; - - for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { - if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { - GLfloat dot = v[0] * ctx->Transform._ClipUserPlane[p][0] - + v[1] * ctx->Transform._ClipUserPlane[p][1] - + v[2] * ctx->Transform._ClipUserPlane[p][2] - + v[3] * ctx->Transform._ClipUserPlane[p][3]; - if (dot < 0.0F) { - return 0; - } - } - } - - return 1; + const GLfloat *src; + const GLuint k = outputMapping[result]; + if (k != ~0) + src = vert->data[k]; + else + src = ctx->Current.Attrib[defaultAttrib]; + COPY_4V(dest, src); } /** - * Update the current raster position. - * Do clip testing, etc. here. + * Normally, this function would render a GL_POINT. */ static void -update_rasterpos(GLcontext *ctx, - const float clipPos[4], - const float color0[4], - const float color1[4], - const float *fog, - const float *tex) +rastpos_point(struct draw_stage *stage, struct prim_header *prim) { - uint i; - float d, ndc[3]; - - /* clip to view volume */ - if (ctx->Transform.RasterPositionUnclipped) { - /* GL_IBM_rasterpos_clip: only clip against Z */ - if (viewclip_point_z(clipPos) == 0) { - ctx->Current.RasterPosValid = GL_FALSE; - return; - } - } - else if (viewclip_point(clipPos) == 0) { - /* Normal OpenGL behaviour */ - ctx->Current.RasterPosValid = GL_FALSE; - return; - } - - /* clip to user clipping planes */ - if (ctx->Transform.ClipPlanesEnabled && !userclip_point(ctx, clipPos)) { - ctx->Current.RasterPosValid = GL_FALSE; - return; - } + struct rastpos_stage *rs = rastpos_stage(stage); + GLcontext *ctx = rs->ctx; + struct st_context *st = ctx->st; + const GLfloat height = ctx->DrawBuffer->Height; + const GLuint *outputMapping = st->vertex_result_to_slot; + const GLfloat *pos; + GLuint i; + + /* if we get here, we didn't get clipped */ + ctx->Current.RasterPosValid = GL_TRUE; + /* update raster pos */ + pos = prim->v[0]->data[0]; + ctx->Current.RasterPos[0] = pos[0]; + ctx->Current.RasterPos[1] = height - 1 - pos[1]; + ctx->Current.RasterPos[2] = pos[2]; + ctx->Current.RasterPos[3] = pos[3]; - /* - * update current raster position - */ - /* ndc = clip / W */ - d = (clipPos[3] == 0.0F) ? 1.0F : 1.0F / clipPos[3]; - ndc[0] = clipPos[0] * d; - ndc[1] = clipPos[1] * d; - ndc[2] = clipPos[2] * d; - /* wincoord = viewport_mapping(ndc) */ - ctx->Current.RasterPos[0] = (ndc[0] * ctx->Viewport._WindowMap.m[MAT_SX] - + ctx->Viewport._WindowMap.m[MAT_TX]); - ctx->Current.RasterPos[1] = (ndc[1] * ctx->Viewport._WindowMap.m[MAT_SY] - + ctx->Viewport._WindowMap.m[MAT_TY]); - ctx->Current.RasterPos[2] = (ndc[2] * ctx->Viewport._WindowMap.m[MAT_SZ] - + ctx->Viewport._WindowMap.m[MAT_TZ]) - / ctx->DrawBuffer->_DepthMaxF; - ctx->Current.RasterPos[3] = clipPos[3]; - - /* compute raster distance */ -#if 0 - if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) - ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0]; - else { - /* XXX we don't have an eye coord! */ - ctx->Current.RasterDistance = - SQRTF( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] ); - } -#else - ctx->Current.RasterDistance = fog[0]; -#endif - - /* colors and texcoords */ - COPY_4FV(ctx->Current.RasterColor, color0); - COPY_4FV(ctx->Current.RasterSecondaryColor, color1); - for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { - COPY_4FV(ctx->Current.RasterTexCoords + i, tex + i *4); - } + /* update other raster attribs */ + update_attrib(ctx, outputMapping, prim->v[0], + ctx->Current.RasterColor, + VERT_RESULT_COL0, VERT_ATTRIB_COLOR0); - ctx->Current.RasterPosValid = GL_TRUE; + update_attrib(ctx, outputMapping, prim->v[0], + ctx->Current.RasterSecondaryColor, + VERT_RESULT_COL1, VERT_ATTRIB_COLOR1); - if (ctx->RenderMode == GL_SELECT) { - _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] ); + for (i = 0; i < MAX_TEXTURE_UNITS; i++) { + update_attrib(ctx, outputMapping, prim->v[0], + ctx->Current.RasterTexCoords[i], + VERT_RESULT_TEX0 + i, VERT_ATTRIB_TEX0 + i); } } +/** + * Create rasterpos "drawing" stage. + */ +static struct rastpos_stage * +new_draw_rastpos_stage(GLcontext *ctx, struct draw_context *draw) +{ + struct rastpos_stage *rs = CALLOC_STRUCT(rastpos_stage); + + rs->stage.draw = draw; + rs->stage.next = NULL; + rs->stage.begin = rastpos_begin; + rs->stage.point = rastpos_point; + rs->stage.line = rastpos_line; + rs->stage.tri = rastpos_tri; + rs->stage.end = rastpos_end; + rs->stage.reset_stipple_counter = rastpos_reset_stipple_counter; + rs->ctx = ctx; + + return rs; +} + static void st_RasterPos(GLcontext *ctx, const GLfloat v[4]) { - const struct st_context *st = ctx->st; - struct pipe_context *pipe = st->pipe; - float *buf_map; - struct pipe_feedback_buffer fb_buf; + struct st_context *st = ctx->st; + struct draw_context *draw = st->draw; + struct rastpos_stage *rs; - st_validate_state(ctx->st); - - /* setup vertex buffers */ - setup_vertex_attribs(ctx); - - /* - * Load the default attribute buffer with current attribs. - */ - { - struct pipe_buffer_handle *buf = st->default_attrib_buffer; - const unsigned size = sizeof(ctx->Current.Attrib); - const void *data = ctx->Current.Attrib; - /* colors, texcoords, etc */ - pipe->winsys->buffer_data(pipe->winsys, buf, - size, data, - PIPE_BUFFER_USAGE_VERTEX); - /* position */ - pipe->winsys->buffer_subdata(pipe->winsys, buf, - 0, /* offset */ - 4 * sizeof(float), /* size */ - v); /* data */ + if (st->rastpos_stage) { + /* get rastpos stage info */ + rs = rastpos_stage(st->rastpos_stage); } - - - /* setup feedback state */ - setup_feedback(ctx); - - /* setup vertex feedback buffer */ - { - fb_buf.size = 8 * 4 * sizeof(float); - fb_buf.buffer = pipe->winsys->buffer_create(pipe->winsys, 0); - fb_buf.start_offset = 0; - pipe->winsys->buffer_data(pipe->winsys, fb_buf.buffer, - fb_buf.size, - NULL, /* data */ - PIPE_BUFFER_USAGE_VERTEX); - if (pipe->set_feedback_buffer) - pipe->set_feedback_buffer(pipe, 0, &fb_buf); - } - - - /* draw a point */ - pipe->draw_arrays(pipe, GL_POINTS, 0, 1); - - /* get feedback */ - buf_map = (float *) pipe->winsys->buffer_map(pipe->winsys, fb_buf.buffer, - PIPE_BUFFER_FLAG_READ); - - /* extract values and update rasterpos state */ - { - const GLuint *outputMapping = st->vertex_result_to_slot; - const float *pos, *color0, *color1, *fog, *tex0; - float *buf = buf_map; - - assert(outputMapping[VERT_RESULT_HPOS] != ~0); - pos = buf; - buf += 4; - - if (outputMapping[VERT_RESULT_COL0] != ~0) { - color0 = buf; - buf += 4; - } - else { - color0 = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; + else { + /* create rastpos draw stage */ + GLuint i; + + rs = new_draw_rastpos_stage(ctx, draw); + st->rastpos_stage = &rs->stage; + + /* one-time init */ + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + rs->array[i].Size = 4; + rs->array[i].Type = GL_FLOAT; + rs->array[i].Stride = 0; + rs->array[i].StrideB = 0; + rs->array[i].Ptr = (GLubyte *) ctx->Current.Attrib[i]; + rs->array[i].Enabled = GL_TRUE; + rs->array[i].Normalized = GL_TRUE; + rs->array[i].BufferObj = NULL; + rs->arrays[i] = &rs->array[i]; } - if (outputMapping[VERT_RESULT_COL1] != ~0) { - color1 = buf; - buf += 4; - } - else { - color1 = ctx->Current.Attrib[VERT_ATTRIB_COLOR1]; - } + rs->prim.mode = GL_POINTS; + rs->prim.indexed = 0; + rs->prim.begin = 1; + rs->prim.end = 1; + rs->prim.weak = 0; + rs->prim.start = 0; + rs->prim.count = 1; + } - if (outputMapping[VERT_RESULT_FOGC] != ~0) { - fog = buf; - buf += 4; - } - else { - fog = ctx->Current.Attrib[VERT_ATTRIB_FOG]; - } + /* plug our rastpos stage into the draw module */ + draw_set_rasterize_stage(st->draw, st->rastpos_stage); - if (outputMapping[VERT_RESULT_TEX0] != ~0) { - tex0 = buf; - buf += 4; - } - else { - tex0 = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; - } + /* make sure everything's up to date */ + st_validate_state(ctx->st); - update_rasterpos(ctx, pos, color0, color1, fog, tex0); - } + /* This will get set only if rastpos_point(), above, gets called */ + ctx->Current.RasterPosValid = GL_FALSE; - /* free vertex feedback buffer */ - pipe->winsys->buffer_unmap(pipe->winsys, fb_buf.buffer); - pipe->winsys->buffer_reference(pipe->winsys, &fb_buf.buffer, NULL); + /* All vertex attribs but position were previously initialized above. + * Just plug in position pointer now. + */ + rs->array[0].Ptr = (GLubyte *) v; - /* restore pipe state */ - if (pipe->set_feedback_state) - pipe->set_feedback_state(pipe, &st->state.feedback); + /* draw the point */ + st_feedback_draw_vbo(ctx, rs->arrays, &rs->prim, 1, NULL, 0, 1); } + void st_init_rasterpos_functions(struct dd_function_table *functions) { functions->RasterPos = st_RasterPos; diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 82e133911f..a6045230a0 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -68,9 +68,10 @@ struct st_context struct pipe_context *pipe; - struct draw_context *draw; /**< For selection/feedback */ + struct draw_context *draw; /**< For selection/feedback/rastpos only */ struct draw_stage *feedback_stage; /**< For GL_FEEDBACK rendermode */ struct draw_stage *selection_stage; /**< For GL_SELECT rendermode */ + struct draw_stage *rastpos_stage; /**< For glRasterPos */ /* Some state is contained in constant objects. * Other state is just parameter values. diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 3e2ed6cada..3b6d829145 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -318,7 +318,7 @@ st_draw_vertices(GLcontext *ctx, unsigned prim, /** * Set the (private) draw module's post-transformed vertex format when in - * GL_SELECT or GL_FEEDBACK mode. + * GL_SELECT or GL_FEEDBACK mode or for glRasterPos. */ static void set_feedback_vertex_format(GLcontext *ctx) @@ -328,7 +328,14 @@ set_feedback_vertex_format(GLcontext *ctx) enum interp_mode interp[PIPE_MAX_SHADER_OUTPUTS]; GLuint n, i; - if (ctx->RenderMode == GL_FEEDBACK) { + if (ctx->RenderMode == GL_SELECT) { + assert(ctx->RenderMode == GL_SELECT); + n = 1; + attrs[0] = FORMAT_4F; + interp[0] = INTERP_NONE; + } + else { + /* GL_FEEDBACK, or glRasterPos */ /* emit all attribs (pos, color, texcoord) as GLfloat[4] */ n = st->state.vs->state.num_outputs; for (i = 0; i < n; i++) { @@ -336,19 +343,14 @@ set_feedback_vertex_format(GLcontext *ctx) interp[i] = INTERP_NONE; } } - else { - assert(ctx->RenderMode == GL_SELECT); - n = 1; - attrs[0] = FORMAT_4F; - interp[0] = INTERP_NONE; - } draw_set_vertex_attributes(st->draw, attrs, interp, n); } /** - * Called by VBO to draw arrays when in selection or feedback mode. + * Called by VBO to draw arrays when in selection or feedback mode and + * to implement glRasterPos. * This is very much like the normal draw_vbo() function above. * Look at code refactoring some day. * Might move this into the failover module some day. @@ -373,8 +375,6 @@ st_feedback_draw_vbo(GLcontext *ctx, GLuint attr, i; ubyte *mapped_constants; - assert(ctx->RenderMode == GL_SELECT || - ctx->RenderMode == GL_FEEDBACK); assert(draw); st_validate_state(ctx->st); |