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 + -
显示快捷键?