st/mesa: fix glDrawPixels(depth/stencil) bugs
authorBrian Paul <brianp@vmware.com>
Tue, 16 Nov 2010 01:36:50 +0000 (18:36 -0700)
committerBrian Paul <brianp@vmware.com>
Tue, 16 Nov 2010 01:40:32 +0000 (18:40 -0700)
When drawing GL_DEPTH_COMPONENT the usual fragment pipeline steps apply
so don't override the depth state.

When drawing GL_STENCIL_INDEX (or GL_DEPTH_STENCIL) the fragment pipeline
does not apply (only the stencil and Z writemasks apply) so disable writes
to the color buffers.

Fixes some regressions from commit ef8bb7ada98f1ddc8e2554a7336af5d669cb1290

src/mesa/state_tracker/st_cb_drawpixels.c

index 122d8f07654dec092cac47a8d2820be65446a4a5..d80c068ea813546525eaa40dad34c7533521c352 100644 (file)
@@ -591,7 +591,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 +598,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 +612,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 +707,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 +714,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);
+   }
 }
 
 
@@ -994,6 +1008,18 @@ 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;