s_readpix.c
来自「mesa-6.5-minigui源码」· C语言 代码 · 共 597 行 · 第 1/2 页
C
597 行
const GLuint transferOps = ctx->_ImageTransferState; 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++) { GLchan rgba[MAX_WIDTH][4]; if (fb->Visual.rgbMode) { _swrast_read_rgba_span(ctx, rb, width, x, y, rgba); } else { GLuint index[MAX_WIDTH]; ASSERT(rb->DataType == GL_UNSIGNED_INT); rb->GetRow(ctx, rb, width, x, y, index); if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset !=0 ) { _mesa_map_ci(ctx, width, index); } _mesa_map_ci_to_rgba_chan(ctx, width, index, rgba); } _mesa_pack_rgba_span_chan(ctx, width, (const GLchan (*)[4]) rgba, GL_RGBA, GL_FLOAT, dest, &ctx->DefaultPacking, transferOps & IMAGE_PRE_CONVOLUTION_BITS); 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, (const GLfloat (*)[4]) src, format, type, dest, packing, transferOps & IMAGE_POST_CONVOLUTION_BITS); src += width * 4; } } else { /* no convolution */ GLint row; for (row = 0; row < height; row++, y++) { GLchan rgba[MAX_WIDTH][4]; GLvoid *dst; if (fb->Visual.rgbMode) { _swrast_read_rgba_span(ctx, rb, width, x, y, rgba); } else { GLuint index[MAX_WIDTH]; ASSERT(rb->DataType == GL_UNSIGNED_INT); rb->GetRow(ctx, rb, width, x, y, index); if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) { _mesa_map_ci(ctx, width, index); } _mesa_map_ci_to_rgba_chan(ctx, width, index, rgba); } dst = _mesa_image_address2d(packing, pixels, width, height, format, type, row, 0); if (fb->Visual.redBits < CHAN_BITS || fb->Visual.greenBits < CHAN_BITS || fb->Visual.blueBits < CHAN_BITS) { /* Requantize the color values into floating point and go from * there. This fixes conformance failures with 16-bit color * buffers, for example. */ GLfloat rgbaf[MAX_WIDTH][4]; _mesa_chan_to_float_span(ctx, width, (CONST GLchan (*)[4]) rgba, rgbaf); _mesa_pack_rgba_span_float(ctx, width, (CONST GLfloat (*)[4]) rgbaf, format, type, dst, packing, ctx->_ImageTransferState); } else { /* GLubytes are fine */ _mesa_pack_rgba_span_chan(ctx, width, (CONST GLchan (*)[4]) rgba, format, type, dst, packing, ctx->_ImageTransferState); } } }}/** * 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; ASSERT(depthRb); ASSERT(stencilRb); 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 */ return; } if (clippedPacking.BufferObj->Name) { /* pack into PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(2, &clippedPacking, width, height, 1, format, type, pixels)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(invalid PBO access)"); goto end; } buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, GL_WRITE_ONLY_ARB, clippedPacking.BufferObj); if (!buf) { /* buffer is already mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)"); goto end; } pixels = ADD_POINTERS(buf, pixels); } 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 */ }end: RENDER_FINISH(swrast, ctx); if (clippedPacking.BufferObj->Name) { /* done with PBO so unmap it now */ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, clippedPacking.BufferObj); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?