summaryrefslogtreecommitdiff
path: root/src/mesa/state_tracker/st_cb_drawpixels.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/state_tracker/st_cb_drawpixels.c')
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c296
1 files changed, 187 insertions, 109 deletions
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 122d8f0765..1fc47688e4 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -94,88 +94,61 @@ is_passthrough_program(const struct gl_fragment_program *prog)
/**
* Make fragment shader for glDraw/CopyPixels. This shader is made
* by combining the pixel transfer shader with the user-defined shader.
- * \return pointer to Gallium driver fragment shader
+ * \param fpIn the current/incoming fragment program
+ * \param fpOut returns the combined fragment program
*/
-static void *
-combined_drawpix_fragment_program(struct gl_context *ctx)
+void
+st_make_drawpix_fragment_program(struct st_context *st,
+ struct gl_fragment_program *fpIn,
+ struct gl_fragment_program **fpOut)
{
- struct st_context *st = st_context(ctx);
- struct st_fragment_program *stfp;
+ struct gl_program *newProg;
- if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
- && st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
- /* the pixel tranfer program has not changed and the user-defined
- * program has not changed, so re-use the combined program.
- */
- stfp = st->pixel_xfer.combined_prog;
+ if (is_passthrough_program(fpIn)) {
+ newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx,
+ &st->pixel_xfer.program->Base);
}
else {
- /* Concatenate the pixel transfer program with the current user-
- * defined program.
- */
- if (is_passthrough_program(&st->fp->Base)) {
- stfp = (struct st_fragment_program *)
- _mesa_clone_fragment_program(ctx, &st->pixel_xfer.program->Base);
- }
- else {
#if 0
- printf("Base program:\n");
- _mesa_print_program(&st->fp->Base.Base);
- printf("DrawPix program:\n");
- _mesa_print_program(&st->pixel_xfer.program->Base.Base);
+ /* debug */
+ printf("Base program:\n");
+ _mesa_print_program(&fpIn->Base);
+ printf("DrawPix program:\n");
+ _mesa_print_program(&st->pixel_xfer.program->Base.Base);
#endif
- stfp = (struct st_fragment_program *)
- _mesa_combine_programs(ctx,
- &st->pixel_xfer.program->Base.Base,
- &st->fp->Base.Base);
- }
+ newProg = _mesa_combine_programs(st->ctx,
+ &st->pixel_xfer.program->Base.Base,
+ &fpIn->Base);
+ }
#if 0
- {
- struct gl_program *p = &stfp->Base.Base;
- printf("Combined DrawPixels program:\n");
- _mesa_print_program(p);
- printf("InputsRead: 0x%x\n", p->InputsRead);
- printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
- _mesa_print_parameter_list(p->Parameters);
- }
+ /* debug */
+ printf("Combined DrawPixels program:\n");
+ _mesa_print_program(newProg);
+ printf("InputsRead: 0x%x\n", newProg->InputsRead);
+ printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten);
+ _mesa_print_parameter_list(newProg->Parameters);
#endif
- /* translate to TGSI tokens */
- st_translate_fragment_program(st, stfp);
-
- /* save new program, update serial numbers */
- st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
- st->pixel_xfer.user_prog_sn = st->fp->serialNo;
- st->pixel_xfer.combined_prog_sn = stfp->serialNo;
- /* can't reference new program directly, already have a reference on it */
- st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
- st->pixel_xfer.combined_prog = stfp;
- }
-
- /* Ideally we'd have updated the pipe constants during the normal
- * st/atom mechanism. But we can't since this is specific to glDrawPixels.
- */
- st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
-
- return stfp->driver_shader;
+ *fpOut = (struct gl_fragment_program *) newProg;
}
/**
- * Create fragment shader that does a TEX() instruction to get a Z and/or
+ * Create fragment program that does a TEX() instruction to get a Z and/or
* stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL.
* Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX).
* Pass fragment color through as-is.
- * \return pointer to the Gallium driver fragment shader
+ * \return pointer to the gl_fragment program
*/
-static void *
-make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth,
- GLboolean write_stencil)
+struct gl_fragment_program *
+st_make_drawpix_z_stencil_program(struct st_context *st,
+ GLboolean write_depth,
+ GLboolean write_stencil)
{
struct gl_context *ctx = st->ctx;
struct gl_program *p;
- struct st_fragment_program *stp;
+ struct gl_fragment_program *fp;
GLuint ic = 0;
const GLuint shaderIndex = write_depth * 2 + write_stencil;
@@ -183,7 +156,7 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth,
if (st->drawpix.shaders[shaderIndex]) {
/* already have the proper shader */
- return st->drawpix.shaders[shaderIndex]->driver_shader;
+ return st->drawpix.shaders[shaderIndex];
}
/*
@@ -245,18 +218,15 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth,
if (write_stencil)
p->SamplersUsed |= 1 << 1;
- stp = st_fragment_program((struct gl_fragment_program *) p);
+ fp = (struct gl_fragment_program *) p;
/* save the new shader */
- st->drawpix.shaders[shaderIndex] = stp;
+ st->drawpix.shaders[shaderIndex] = fp;
- st_translate_fragment_program(st, stp);
-
- return stp->driver_shader;
+ return fp;
}
-
/**
* Create a simple vertex shader that just passes through the
* vertex position and texcoord (and optionally, color).
@@ -427,9 +397,9 @@ make_texture(struct st_context *st,
/* we'll do pixel transfer in a fragment shader */
ctx->_ImageTransferState = 0x0;
- transfer = pipe_get_transfer(st->pipe, pt, 0, 0, 0,
- PIPE_TRANSFER_WRITE, 0, 0,
- width, height);
+ transfer = pipe_get_transfer(st->pipe, pt, 0, 0,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ width, height);
/* map texture transfer */
dest = pipe_transfer_map(pipe, transfer);
@@ -591,7 +561,6 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
assert(width <= maxSize);
assert(height <= maxSize);
- cso_save_depth_stencil_alpha(cso);
cso_save_rasterizer(cso);
cso_save_viewport(cso);
cso_save_samplers(cso);
@@ -599,6 +568,10 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
cso_save_fragment_shader(cso);
cso_save_vertex_shader(cso);
cso_save_vertex_elements(cso);
+ if (write_stencil) {
+ cso_save_depth_stencil_alpha(cso);
+ cso_save_blend(cso);
+ }
/* rasterizer state: just scissor */
{
@@ -609,22 +582,30 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
cso_set_rasterizer(cso, &rasterizer);
}
- if (write_depth || write_stencil)
- {
+ if (write_stencil) {
+ /* Stencil writing bypasses the normal fragment pipeline to
+ * disable color writing and set stencil test to always pass.
+ */
struct pipe_depth_stencil_alpha_state dsa;
+ struct pipe_blend_state blend;
+
+ /* depth/stencil */
memset(&dsa, 0, sizeof(dsa));
+ dsa.stencil[0].enabled = 1;
+ dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
+ dsa.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
if (write_depth) {
- dsa.depth.enabled = 1;
- dsa.depth.func = PIPE_FUNC_ALWAYS;
- dsa.depth.writemask = 1;
- }
- if (write_stencil) {
- dsa.stencil[0].enabled = 1;
- dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
- dsa.stencil[0].writemask = 0xff;
- dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
+ /* writing depth+stencil: depth test always passes */
+ dsa.depth.enabled = 1;
+ dsa.depth.writemask = ctx->Depth.Mask;
+ dsa.depth.func = PIPE_FUNC_ALWAYS;
}
cso_set_depth_stencil_alpha(cso, &dsa);
+
+ /* blend (colormask) */
+ memset(&blend, 0, sizeof(blend));
+ cso_set_blend(cso, &blend);
}
/* fragment shader state: TEX lookup program */
@@ -696,7 +677,6 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
normalized ? ((GLfloat) height / sv[0]->texture->height0) : (GLfloat)height);
/* restore state */
- cso_restore_depth_stencil_alpha(cso);
cso_restore_rasterizer(cso);
cso_restore_viewport(cso);
cso_restore_samplers(cso);
@@ -704,6 +684,10 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
cso_restore_fragment_shader(cso);
cso_restore_vertex_shader(cso);
cso_restore_vertex_elements(cso);
+ if (write_stencil) {
+ cso_restore_depth_stencil_alpha(cso);
+ cso_restore_blend(cso);
+ }
}
@@ -749,9 +733,9 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
else
usage = PIPE_TRANSFER_WRITE;
- pt = pipe_get_transfer(st_context(ctx)->pipe, strb->texture, 0, 0, 0,
- usage, x, y,
- width, height);
+ pt = pipe_get_transfer(st_context(ctx)->pipe, strb->texture, 0, 0,
+ usage, x, y,
+ width, height);
stmap = pipe_transfer_map(pipe, pt);
@@ -859,6 +843,61 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
/**
+ * Get fragment program variant for a glDrawPixels or glCopyPixels
+ * command for RGBA data.
+ */
+static struct st_fp_variant *
+get_color_fp_variant(struct st_context *st)
+{
+ struct gl_context *ctx = st->ctx;
+ struct st_fp_variant_key key;
+ struct st_fp_variant *fpv;
+
+ memset(&key, 0, sizeof(key));
+
+ key.st = st;
+ key.drawpixels = 1;
+ key.scaleAndBias = (ctx->Pixel.RedBias != 0.0 ||
+ ctx->Pixel.RedScale != 1.0 ||
+ ctx->Pixel.GreenBias != 0.0 ||
+ ctx->Pixel.GreenScale != 1.0 ||
+ ctx->Pixel.BlueBias != 0.0 ||
+ ctx->Pixel.BlueScale != 1.0 ||
+ ctx->Pixel.AlphaBias != 0.0 ||
+ ctx->Pixel.AlphaScale != 1.0);
+ key.pixelMaps = ctx->Pixel.MapColorFlag;
+
+ fpv = st_get_fp_variant(st, st->fp, &key);
+
+ return fpv;
+}
+
+
+/**
+ * Get fragment program variant for a glDrawPixels or glCopyPixels
+ * command for depth/stencil data.
+ */
+static struct st_fp_variant *
+get_depth_stencil_fp_variant(struct st_context *st, GLboolean write_depth,
+ GLboolean write_stencil)
+{
+ struct st_fp_variant_key key;
+ struct st_fp_variant *fpv;
+
+ memset(&key, 0, sizeof(key));
+
+ key.st = st;
+ key.drawpixels = 1;
+ key.drawpixels_z = write_depth;
+ key.drawpixels_stencil = write_stencil;
+
+ fpv = st_get_fp_variant(st, st->fp, &key);
+
+ return fpv;
+}
+
+
+/**
* Called via ctx->Driver.DrawPixels()
*/
static void
@@ -875,6 +914,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
struct pipe_sampler_view *sv[2];
int num_sampler_view = 1;
enum pipe_format stencil_format = PIPE_FORMAT_NONE;
+ struct st_fp_variant *fpv;
if (format == GL_DEPTH_STENCIL)
write_stencil = write_depth = GL_TRUE;
@@ -907,14 +947,25 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
st_validate_state(st);
+ /*
+ * Get vertex/fragment shaders
+ */
if (write_depth || write_stencil) {
- driver_fp = make_fragment_shader_z_stencil(st, write_depth, write_stencil);
+ fpv = get_depth_stencil_fp_variant(st, write_depth, write_stencil);
+
+ driver_fp = fpv->driver_shader;
+
driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
+
color = ctx->Current.RasterColor;
}
else {
- driver_fp = combined_drawpix_fragment_program(ctx);
+ fpv = get_color_fp_variant(st);
+
+ driver_fp = fpv->driver_shader;
+
driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
+
color = NULL;
if (st->pixel_xfer.pixelmap_enabled) {
sv[1] = st->pixel_xfer.pixelmap_sampler_view;
@@ -922,6 +973,9 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
}
}
+ /* update fragment program constants */
+ st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
+
/* draw with textured quad */
{
struct pipe_resource *pt
@@ -994,20 +1048,32 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
&ctx->DefaultPacking, buffer);
+ if (0) {
+ /* debug code: dump stencil values */
+ GLint row, col;
+ for (row = 0; row < height; row++) {
+ printf("%3d: ", row);
+ for (col = 0; col < width; col++) {
+ printf("%02x ", buffer[col + row * width]);
+ }
+ printf("\n");
+ }
+ }
+
if (util_format_get_component_bits(rbDraw->format,
UTIL_FORMAT_COLORSPACE_ZS, 0) != 0)
usage = PIPE_TRANSFER_READ_WRITE;
else
usage = PIPE_TRANSFER_WRITE;
-
+
if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
dsty = rbDraw->Base.Height - dsty - height;
}
ptDraw = pipe_get_transfer(st_context(ctx)->pipe,
- rbDraw->texture, 0, 0, 0,
- usage, dstx, dsty,
- width, height);
+ rbDraw->texture, 0, 0,
+ usage, dstx, dsty,
+ width, height);
assert(util_format_get_blockwidth(ptDraw->resource->format) == 1);
assert(util_format_get_blockheight(ptDraw->resource->format) == 1);
@@ -1090,6 +1156,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
GLint readX, readY, readW, readH;
GLuint sample_count;
struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
+ struct st_fp_variant *fpv;
st_validate_state(st);
@@ -1099,11 +1166,18 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
return;
}
+ /*
+ * Get vertex/fragment shaders
+ */
if (type == GL_COLOR) {
rbRead = st_get_color_read_renderbuffer(ctx);
color = NULL;
- driver_fp = combined_drawpix_fragment_program(ctx);
+
+ fpv = get_color_fp_variant(st);
+ driver_fp = fpv->driver_shader;
+
driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
+
if (st->pixel_xfer.pixelmap_enabled) {
sv[1] = st->pixel_xfer.pixelmap_sampler_view;
num_sampler_view++;
@@ -1113,10 +1187,17 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
assert(type == GL_DEPTH);
rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
- driver_fp = make_fragment_shader_z_stencil(st, GL_TRUE, GL_FALSE);
+
+ fpv = get_depth_stencil_fp_variant(st, GL_TRUE, GL_FALSE);
+ driver_fp = fpv->driver_shader;
+
driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
}
+ /* update fragment program constants */
+ st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
+
+
if (rbRead->Base.Wrapped)
rbRead = st_renderbuffer(rbRead->Base.Wrapped);
@@ -1183,27 +1264,24 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
/* Make temporary texture which is a copy of the src region.
*/
if (srcFormat == texFormat) {
- struct pipe_subresource srcsub, dstsub;
- srcsub.face = 0;
- srcsub.level = 0;
- dstsub.face = 0;
- dstsub.level = 0;
- /* copy source framebuffer surface into mipmap/texture */
+ struct pipe_box src_box;
+ u_box_2d(readX, readY, readW, readH, &src_box);
+ /* copy source framebuffer surface into mipmap/texture */
pipe->resource_copy_region(pipe,
pt, /* dest tex */
- dstsub,
+ 0,
pack.SkipPixels, pack.SkipRows, 0, /* dest pos */
rbRead->texture, /* src tex */
- srcsub,
- readX, readY, 0, readW, readH); /* src region */
+ 0,
+ &src_box);
}
else {
/* CPU-based fallback/conversion */
struct pipe_transfer *ptRead =
- pipe_get_transfer(st->pipe, rbRead->texture, 0, 0, 0,
- PIPE_TRANSFER_READ,
- readX, readY, readW, readH);
+ pipe_get_transfer(st->pipe, rbRead->texture, 0, 0,
+ PIPE_TRANSFER_READ,
+ readX, readY, readW, readH);
struct pipe_transfer *ptTex;
enum pipe_transfer_usage transfer_usage;
@@ -1215,8 +1293,8 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
else
transfer_usage = PIPE_TRANSFER_WRITE;
- ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, 0, transfer_usage,
- 0, 0, width, height);
+ ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, transfer_usage,
+ 0, 0, width, height);
/* copy image from ptRead surface to ptTex surface */
if (type == GL_COLOR) {
@@ -1271,7 +1349,7 @@ st_destroy_drawpix(struct st_context *st)
for (i = 0; i < Elements(st->drawpix.shaders); i++) {
if (st->drawpix.shaders[i])
- st_reference_fragprog(st, &st->drawpix.shaders[i], NULL);
+ _mesa_reference_fragprog(st->ctx, &st->drawpix.shaders[i], NULL);
}
st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);