summaryrefslogtreecommitdiff
path: root/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c14
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h2
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_winsys.h17
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_winsys_i915.c60
-rw-r--r--src/mesa/pipe/draw/draw_validate.c1
-rw-r--r--src/mesa/pipe/draw/draw_vertex_fetch.c12
-rw-r--r--src/mesa/pipe/i915simple/i915_batch.h10
-rw-r--r--src/mesa/pipe/i915simple/i915_context.c2
-rw-r--r--src/mesa/pipe/i915simple/i915_context.h3
-rw-r--r--src/mesa/pipe/i915simple/i915_flush.c3
-rw-r--r--src/mesa/pipe/i915simple/i915_winsys.h25
-rw-r--r--src/mesa/pipe/p_state.h1
-rw-r--r--src/mesa/pipe/softpipe/Makefile1
-rw-r--r--src/mesa/pipe/softpipe/sp_context.c2
-rw-r--r--src/mesa/pipe/softpipe/sp_context.h1
-rw-r--r--src/mesa/pipe/softpipe/sp_quad.c70
-rw-r--r--src/mesa/pipe/softpipe/sp_quad.h1
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_depth_test.c24
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_earlyz.c92
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_fs.c4
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_stencil.c16
-rw-r--r--src/mesa/pipe/softpipe/sp_surface.c40
-rw-r--r--src/mesa/pipe/softpipe/sp_tile_cache.c13
-rw-r--r--src/mesa/pipe/tgsi/exec/tgsi_exec.c43
-rw-r--r--src/mesa/state_tracker/st_cb_rasterpos.c440
-rw-r--r--src/mesa/state_tracker/st_context.h3
-rw-r--r--src/mesa/state_tracker/st_draw.c22
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);