static GLboolean _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS) { GLint img, row; const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) / sizeof(uint64_t); assert(dstFormat == MESA_FORMAT_Z32_FLOAT_S8X24_UINT); assert(srcFormat == GL_DEPTH_STENCIL || srcFormat == GL_DEPTH_COMPONENT || srcFormat == GL_STENCIL_INDEX); assert(srcFormat != GL_DEPTH_STENCIL || srcType == GL_UNSIGNED_INT_24_8 || srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); /* In case we only upload depth we need to preserve the stencil */ for (img = 0; img < srcDepth; img++) { uint64_t *dstRow = (uint64_t *) dstSlices[img]; const uint64_t *src = (const uint64_t *) _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); for (row = 0; row < srcHeight; row++) { /* The unpack functions with: * dstType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV * only write their own dword, so the other dword (stencil * or depth) is preserved. */ if (srcFormat != GL_STENCIL_INDEX) _mesa_unpack_depth_span(ctx, srcWidth, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */ dstRow, /* dst addr */ ~0U, srcType, src, srcPacking); if (srcFormat != GL_DEPTH_COMPONENT) _mesa_unpack_stencil_span(ctx, srcWidth, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */ dstRow, /* dst addr */ srcType, src, srcPacking, ctx->_ImageTransferState); src += srcRowStride; dstRow += dstRowStride / sizeof(uint64_t); } } return GL_TRUE; }
/** * Store simple 8-bit/value stencil texture data. */ static GLboolean _mesa_texstore_s8(TEXSTORE_PARAMS) { assert(dstFormat == MESA_FORMAT_S_UINT8); assert(srcFormat == GL_STENCIL_INDEX); { const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); GLint img, row; GLubyte *stencil = malloc(srcWidth * sizeof(GLubyte)); if (!stencil) return GL_FALSE; for (img = 0; img < srcDepth; img++) { GLubyte *dstRow = dstSlices[img]; const GLubyte *src = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); for (row = 0; row < srcHeight; row++) { GLint i; /* get the 8-bit stencil values */ _mesa_unpack_stencil_span(ctx, srcWidth, GL_UNSIGNED_BYTE, /* dst type */ stencil, /* dst addr */ srcType, src, srcPacking, ctx->_ImageTransferState); /* merge stencil values into depth values */ for (i = 0; i < srcWidth; i++) dstRow[i] = stencil[i]; src += srcRowStride; dstRow += dstRowStride / sizeof(GLubyte); } } free(stencil); } return GL_TRUE; }
/* * Draw stencil image. */ static void draw_stencil_pixels( struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels ) { const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; const GLenum destType = GL_UNSIGNED_BYTE; GLint row; GLubyte *values; values = malloc(width * sizeof(GLubyte)); if (!values) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); return; } for (row = 0; row < height; row++) { const GLvoid *source = _mesa_image_address2d(unpack, pixels, width, height, GL_STENCIL_INDEX, type, row, 0); _mesa_unpack_stencil_span(ctx, width, destType, values, type, source, unpack, ctx->_ImageTransferState); if (zoom) { _swrast_write_zoomed_stencil_span(ctx, x, y, width, x, y, values); } else { _swrast_write_stencil_span(ctx, width, x, y, values); } y++; } free(values); }
/* * Draw stencil image. */ static void draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels ) { const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; GLint skipPixels; /* if width > MAX_WIDTH, have to process image in chunks */ skipPixels = 0; while (skipPixels < width) { const GLint spanX = x + skipPixels; const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); GLint row; for (row = 0; row < height; row++) { const GLint spanY = y + row; GLstencil values[MAX_WIDTH]; GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte)) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; const GLvoid *source = _mesa_image_address2d(unpack, pixels, width, height, GL_COLOR_INDEX, type, row, skipPixels); _mesa_unpack_stencil_span(ctx, spanWidth, destType, values, type, source, unpack, ctx->_ImageTransferState); if (zoom) { _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth, spanX, spanY, values); } else { _swrast_write_stencil_span(ctx, spanWidth, spanX, spanY, values); } } skipPixels += spanWidth; } }
/** * Software fallback to do glDrawPixels(GL_STENCIL_INDEX) when we * can't use a fragment shader to write stencil values. */ static void draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_renderbuffer *strb; enum pipe_transfer_usage usage; struct pipe_transfer *pt; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; GLint skipPixels; ubyte *stmap; struct gl_pixelstore_attrib clippedUnpack = *unpack; if (!zoom) { if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &clippedUnpack)) { /* totally clipped */ return; } } strb = st_renderbuffer(ctx->DrawBuffer-> Attachment[BUFFER_STENCIL].Renderbuffer); if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { y = ctx->DrawBuffer->Height - y - height; } if(format != GL_DEPTH_STENCIL && util_format_get_component_bits(strb->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0) usage = PIPE_TRANSFER_READ_WRITE; else usage = PIPE_TRANSFER_WRITE; pt = pipe_get_transfer(pipe, strb->texture, strb->rtt_level, strb->rtt_face + strb->rtt_slice, usage, x, y, width, height); stmap = pipe_transfer_map(pipe, pt); pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels); assert(pixels); /* if width > MAX_WIDTH, have to process image in chunks */ skipPixels = 0; while (skipPixels < width) { const GLint spanX = skipPixels; const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); GLint row; for (row = 0; row < height; row++) { GLubyte sValues[MAX_WIDTH]; GLuint zValues[MAX_WIDTH]; GLenum destType = GL_UNSIGNED_BYTE; const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels, width, height, format, type, row, skipPixels); _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues, type, source, &clippedUnpack, ctx->_ImageTransferState); if (format == GL_DEPTH_STENCIL) { _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues, (1 << 24) - 1, type, source, &clippedUnpack); } if (zoom) { _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with " "zoom not complete"); } { GLint spanY; if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { spanY = height - row - 1; } else { spanY = row; } /* now pack the stencil (and Z) values in the dest format */ switch (pt->resource->format) { case PIPE_FORMAT_S8_USCALED: { ubyte *dest = stmap + spanY * pt->stride + spanX; assert(usage == PIPE_TRANSFER_WRITE); memcpy(dest, sValues, spanWidth); } break; case PIPE_FORMAT_Z24_UNORM_S8_USCALED: if (format == GL_DEPTH_STENCIL) { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; assert(usage == PIPE_TRANSFER_WRITE); for (k = 0; k < spanWidth; k++) { dest[k] = zValues[k] | (sValues[k] << 24); } } else { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; assert(usage == PIPE_TRANSFER_READ_WRITE); for (k = 0; k < spanWidth; k++) { dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24); } } break; case PIPE_FORMAT_S8_USCALED_Z24_UNORM: if (format == GL_DEPTH_STENCIL) { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; assert(usage == PIPE_TRANSFER_WRITE); for (k = 0; k < spanWidth; k++) { dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff); } } else { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; assert(usage == PIPE_TRANSFER_READ_WRITE); for (k = 0; k < spanWidth; k++) { dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff); } } break; default: assert(0); } } } skipPixels += spanWidth; } _mesa_unmap_pbo_source(ctx, &clippedUnpack); /* unmap the stencil buffer */ pipe_transfer_unmap(pipe, pt); pipe->transfer_destroy(pipe, pt); }
/** * Store a combined depth/stencil texture image. */ static GLboolean _mesa_texstore_s8_z24(TEXSTORE_PARAMS) { const GLuint depthScale = 0xffffff; const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); GLint img, row; GLuint *depth; GLubyte *stencil; assert(dstFormat == MESA_FORMAT_Z24_UNORM_S8_UINT); assert(srcFormat == GL_DEPTH_STENCIL_EXT || srcFormat == GL_DEPTH_COMPONENT || srcFormat == GL_STENCIL_INDEX); assert(srcFormat != GL_DEPTH_STENCIL_EXT || srcType == GL_UNSIGNED_INT_24_8_EXT || srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); depth = malloc(srcWidth * sizeof(GLuint)); stencil = malloc(srcWidth * sizeof(GLubyte)); if (!depth || !stencil) { free(depth); free(stencil); return GL_FALSE; } for (img = 0; img < srcDepth; img++) { GLuint *dstRow = (GLuint *) dstSlices[img]; const GLubyte *src = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); for (row = 0; row < srcHeight; row++) { GLint i; GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE; if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */ keepstencil = GL_TRUE; } else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */ keepdepth = GL_TRUE; } if (keepdepth == GL_FALSE) /* the 24 depth bits will be in the low position: */ _mesa_unpack_depth_span(ctx, srcWidth, GL_UNSIGNED_INT, /* dst type */ keepstencil ? depth : dstRow, /* dst addr */ depthScale, srcType, src, srcPacking); if (keepstencil == GL_FALSE) /* get the 8-bit stencil values */ _mesa_unpack_stencil_span(ctx, srcWidth, GL_UNSIGNED_BYTE, /* dst type */ stencil, /* dst addr */ srcType, src, srcPacking, ctx->_ImageTransferState); /* merge stencil values into depth values */ for (i = 0; i < srcWidth; i++) { if (keepstencil) dstRow[i] = depth[i] | (dstRow[i] & 0xFF000000); else dstRow[i] = (dstRow[i] & 0xFFFFFF) | (stencil[i] << 24); } src += srcRowStride; dstRow += dstRowStride / sizeof(GLuint); } } free(depth); free(stencil); return GL_TRUE; }