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.c103
1 files changed, 86 insertions, 17 deletions
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 94b80f69f2..d80c068ea8 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -34,6 +34,7 @@
#include "main/image.h"
#include "main/bufferobj.h"
#include "main/macros.h"
+#include "main/pack.h"
#include "main/texformat.h"
#include "main/texstore.h"
#include "program/program.h"
@@ -298,8 +299,8 @@ make_passthrough_vertex_shader(struct st_context *st,
/**
- * Return a texture internalFormat for drawing/copying an image
- * of the given type.
+ * Return a texture base format for drawing/copying an image
+ * of the given format.
*/
static GLenum
base_format(GLenum format)
@@ -318,6 +319,47 @@ base_format(GLenum format)
/**
+ * Return a texture internalFormat for drawing/copying an image
+ * of the given format and type.
+ */
+static GLenum
+internal_format(GLenum format, GLenum type)
+{
+ switch (format) {
+ case GL_DEPTH_COMPONENT:
+ return GL_DEPTH_COMPONENT;
+ case GL_DEPTH_STENCIL:
+ return GL_DEPTH_STENCIL;
+ case GL_STENCIL_INDEX:
+ return GL_STENCIL_INDEX;
+ default:
+ if (_mesa_is_integer_format(format)) {
+ switch (type) {
+ case GL_BYTE:
+ return GL_RGBA8I;
+ case GL_UNSIGNED_BYTE:
+ return GL_RGBA8UI;
+ case GL_SHORT:
+ return GL_RGBA16I;
+ case GL_UNSIGNED_SHORT:
+ return GL_RGBA16UI;
+ case GL_INT:
+ return GL_RGBA32I;
+ case GL_UNSIGNED_INT:
+ return GL_RGBA32UI;
+ default:
+ assert(0 && "Unexpected type in internal_format()");
+ return GL_RGBA_INTEGER;
+ }
+ }
+ else {
+ return GL_RGBA;
+ }
+ }
+}
+
+
+/**
* Create a temporary texture to hold an image of the given size.
* If width, height are not POT and the driver only handles POT textures,
* allocate the next larger size of texture that is POT.
@@ -351,11 +393,12 @@ make_texture(struct st_context *st,
struct pipe_resource *pt;
enum pipe_format pipeFormat;
GLuint cpp;
- GLenum baseFormat;
+ GLenum baseFormat, intFormat;
baseFormat = base_format(format);
+ intFormat = internal_format(format, type);
- mformat = st_ChooseTextureFormat_renderable(ctx, baseFormat,
+ mformat = st_ChooseTextureFormat_renderable(ctx, intFormat,
format, type, GL_FALSE);
assert(mformat);
@@ -548,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);
@@ -556,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 */
{
@@ -566,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 */
@@ -653,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);
@@ -661,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);
+ }
}
@@ -951,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;