📄 s_readpix.c
字号:
/* * Read R, G, B, A, RGB, L, or LA pixels. */static voidread_rgba_pixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels, const struct gl_pixelstore_attrib *packing ){ SWcontext *swrast = SWRAST_CONTEXT(ctx); GLbitfield transferOps = ctx->_ImageTransferState; struct gl_framebuffer *fb = ctx->ReadBuffer; struct gl_renderbuffer *rb = fb->_ColorReadBuffer; if (!rb) return; if (type == GL_FLOAT && ((ctx->Color.ClampReadColor == GL_TRUE) || (ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB && rb->DataType != GL_FLOAT))) transferOps |= IMAGE_CLAMP_BIT; /* Try optimized path first */ if (fast_read_rgba_pixels(ctx, x, y, width, height, format, type, pixels, packing, transferOps)) { return; /* done! */ } /* width should never be > MAX_WIDTH since we did clipping earlier */ ASSERT(width <= MAX_WIDTH); if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) { GLfloat *dest, *src, *tmpImage, *convImage; GLint row; tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!tmpImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); return; } convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!convImage) { _mesa_free(tmpImage); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); return; } /* read full RGBA, FLOAT image */ dest = tmpImage; for (row = 0; row < height; row++, y++) { if (fb->Visual.rgbMode) { _swrast_read_rgba_span(ctx, rb, width, x, y, GL_FLOAT, dest); } else { GLuint index[MAX_WIDTH]; ASSERT(rb->DataType == GL_UNSIGNED_INT); rb->GetRow(ctx, rb, width, x, y, index); _mesa_apply_ci_transfer_ops(ctx, transferOps & IMAGE_SHIFT_OFFSET_BIT, width, index); _mesa_map_ci_to_rgba(ctx, width, index, (GLfloat (*)[4]) dest); } _mesa_apply_rgba_transfer_ops(ctx, transferOps & IMAGE_PRE_CONVOLUTION_BITS, width, (GLfloat (*)[4]) dest); dest += width * 4; } /* do convolution */ if (ctx->Pixel.Convolution2DEnabled) { _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage); } else { ASSERT(ctx->Pixel.Separable2DEnabled); _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage); } _mesa_free(tmpImage); /* finish transfer ops and pack the resulting image */ src = convImage; for (row = 0; row < height; row++) { GLvoid *dest; dest = _mesa_image_address2d(packing, pixels, width, height, format, type, row, 0); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) src, format, type, dest, packing, transferOps & IMAGE_POST_CONVOLUTION_BITS); src += width * 4; } _mesa_free(convImage); } else { /* no convolution */ const GLint dstStride = _mesa_image_row_stride(packing, width, format, type); GLfloat (*rgba)[4] = swrast->SpanArrays->attribs[FRAG_ATTRIB_COL0]; GLint row; GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, format, type, 0, 0); /* make sure we don't apply 1D convolution */ transferOps &= ~(IMAGE_CONVOLUTION_BIT | IMAGE_POST_CONVOLUTION_SCALE_BIAS); for (row = 0; row < height; row++, y++) { /* Get float rgba pixels */ if (fb->Visual.rgbMode) { _swrast_read_rgba_span(ctx, rb, width, x, y, GL_FLOAT, rgba); } else { /* read CI and convert to RGBA */ GLuint index[MAX_WIDTH]; ASSERT(rb->DataType == GL_UNSIGNED_INT); rb->GetRow(ctx, rb, width, x, y, index); _mesa_apply_ci_transfer_ops(ctx, transferOps & IMAGE_SHIFT_OFFSET_BIT, width, index); _mesa_map_ci_to_rgba(ctx, width, index, rgba); } /* apply fudge factor for shallow color buffers */ if (fb->Visual.redBits < 8 || fb->Visual.greenBits < 8 || fb->Visual.blueBits < 8) { adjust_colors(ctx, width, rgba); } /* pack the row of RGBA pixels into user's buffer */ _mesa_pack_rgba_span_float(ctx, width, rgba, format, type, dst, packing, transferOps); dst += dstStride; } }}/** * Read combined depth/stencil values. * We'll have already done error checking to be sure the expected * depth and stencil buffers really exist. */static voidread_depth_stencil_pixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum type, GLvoid *pixels, const struct gl_pixelstore_attrib *packing ){ const GLboolean scaleOrBias = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; const GLboolean stencilTransfer = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag; struct gl_renderbuffer *depthRb, *stencilRb; depthRb = ctx->ReadBuffer->_DepthBuffer; stencilRb = ctx->ReadBuffer->_StencilBuffer; if (!depthRb || !stencilRb) return; depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; if (depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT && stencilRb->_BaseFormat == GL_DEPTH_STENCIL_EXT && depthRb == stencilRb && !scaleOrBias && !stencilTransfer) { /* This is the ideal case. * Reading GL_DEPTH_STENCIL pixels from combined depth/stencil buffer. * Plus, no pixel transfer ops to worry about! */ GLint i; GLint dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_STENCIL_EXT, type); GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, GL_DEPTH_STENCIL_EXT, type, 0, 0); for (i = 0; i < height; i++) { depthRb->GetRow(ctx, depthRb, width, x, y + i, dst); dst += dstStride; } } else { /* Reading GL_DEPTH_STENCIL pixels from separate depth/stencil buffers, * or we need pixel transfer. */ GLint i; depthRb = ctx->ReadBuffer->_DepthBuffer; stencilRb = ctx->ReadBuffer->_StencilBuffer; for (i = 0; i < height; i++) { GLstencil stencilVals[MAX_WIDTH]; GLuint *depthStencilDst = (GLuint *) _mesa_image_address2d(packing, pixels, width, height, GL_DEPTH_STENCIL_EXT, type, i, 0); _swrast_read_stencil_span(ctx, stencilRb, width, x, y + i, stencilVals); if (!scaleOrBias && !stencilTransfer && ctx->ReadBuffer->Visual.depthBits == 24) { /* ideal case */ GLuint zVals[MAX_WIDTH]; /* 24-bit values! */ GLint j; ASSERT(depthRb->DataType == GL_UNSIGNED_INT); /* note, we've already been clipped */ depthRb->GetRow(ctx, depthRb, width, x, y + i, zVals); for (j = 0; j < width; j++) { depthStencilDst[j] = (zVals[j] << 8) | (stencilVals[j] & 0xff); } } else { /* general case */ GLfloat depthVals[MAX_WIDTH]; _swrast_read_depth_span_float(ctx, depthRb, width, x, y + i, depthVals); _mesa_pack_depth_stencil_span(ctx, width, depthStencilDst, depthVals, stencilVals, packing); } } }}/** * Software fallback routine for ctx->Driver.ReadPixels(). * By time we get here, all error checking will have been done. */void_swrast_ReadPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *packing, GLvoid *pixels ){ SWcontext *swrast = SWRAST_CONTEXT(ctx); struct gl_pixelstore_attrib clippedPacking = *packing; /* Need to do RENDER_START before clipping or anything else since this * is where a driver may grab the hw lock and get an updated window * size. */ RENDER_START(swrast, ctx); if (ctx->NewState) _mesa_update_state(ctx); if (swrast->NewState) _swrast_validate_derived( ctx ); /* Do all needed clipping here, so that we can forget about it later */ if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) { /* The ReadPixels region is totally outside the window bounds */ RENDER_FINISH(swrast, ctx); return; } pixels = _mesa_map_readpix_pbo(ctx, &clippedPacking, pixels); if (!pixels) return; switch (format) { case GL_COLOR_INDEX: read_index_pixels(ctx, x, y, width, height, type, pixels, &clippedPacking); break; case GL_STENCIL_INDEX: read_stencil_pixels(ctx, x, y, width, height, type, pixels, &clippedPacking); break; case GL_DEPTH_COMPONENT: read_depth_pixels(ctx, x, y, width, height, type, pixels, &clippedPacking); break; case GL_RED: case GL_GREEN: case GL_BLUE: case GL_ALPHA: case GL_RGB: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_RGBA: case GL_BGR: case GL_BGRA: case GL_ABGR_EXT: read_rgba_pixels(ctx, x, y, width, height, format, type, pixels, &clippedPacking); break; case GL_DEPTH_STENCIL_EXT: read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels, &clippedPacking); break; default: _mesa_problem(ctx, "unexpected format in _swrast_ReadPixels"); /* don't return yet, clean-up */ } RENDER_FINISH(swrast, ctx); _mesa_unmap_readpix_pbo(ctx, &clippedPacking);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -