Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
/**
 * glGetTexImage for YCbCr pixels.
 */
static void
get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
              GLenum format, GLenum type, GLvoid *pixels,
              struct gl_texture_image *texImage)
{
   const GLint width = texImage->Width;
   const GLint height = texImage->Height;
   const GLint depth = texImage->Depth;
   GLint img, row;

   for (img = 0; img < depth; img++) {
      GLubyte *srcMap;
      GLint rowstride;

      /* map src texture buffer */
      ctx->Driver.MapTextureImage(ctx, texImage, img,
                                  0, 0, width, height, GL_MAP_READ_BIT,
                                  &srcMap, &rowstride);

      if (srcMap) {
         for (row = 0; row < height; row++) {
            const GLubyte *src = srcMap + row * rowstride;
            void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                             width, height, format, type,
                                             img, row, 0);
            memcpy(dest, src, width * sizeof(GLushort));

            /* check for byte swapping */
            if ((texImage->TexFormat == MESA_FORMAT_YCBCR
                 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
                (texImage->TexFormat == MESA_FORMAT_YCBCR_REV
                 && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
               if (!ctx->Pack.SwapBytes)
                  _mesa_swap2((GLushort *) dest, width);
            }
            else if (ctx->Pack.SwapBytes) {
               _mesa_swap2((GLushort *) dest, width);
            }
         }

         ctx->Driver.UnmapTextureImage(ctx, texImage, img);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         break;
      }
   }
}
Exemplo n.º 3
0
void
_mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, GLvoid *image)
{
   const struct gl_convolution_attrib *filter;
   GLuint row;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (ctx->NewState) {
      _mesa_update_state(ctx);
   }

   if (!_mesa_is_legal_format_and_type(format, type)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionFilter(format or type)");
      return;
   }

   if (format == GL_COLOR_INDEX ||
       format == GL_STENCIL_INDEX ||
       format == GL_DEPTH_COMPONENT ||
       format == GL_INTENSITY ||
       type == GL_BITMAP) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)");
      return;
   }

   switch (target) {
      case GL_CONVOLUTION_1D:
         filter = &(ctx->Convolution1D);
         break;
      case GL_CONVOLUTION_2D:
         filter = &(ctx->Convolution2D);
         break;
      default:
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(target)");
         return;
   }

   for (row = 0; row < filter->Height; row++) {
      GLvoid *dst = _mesa_image_address( &ctx->Pack, image, filter->Width,
                                         filter->Height, format, type,
                                         0, row, 0);
      const GLfloat *src = filter->Filter + row * filter->Width * 4;
      _mesa_pack_float_rgba_span(ctx, filter->Width,
                                 (const GLfloat (*)[4]) src,
                                 format, type, dst, &ctx->Pack, 0);
   }
}
Exemplo n.º 4
0
/**
 * glGetTexImage for depth/stencil pixels.
 */
static void
get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions,
                      GLenum format, GLenum type, GLvoid *pixels,
                      struct gl_texture_image *texImage)
{
   const GLint width = texImage->Width;
   const GLint height = texImage->Height;
   const GLint depth = texImage->Depth;
   GLint img, row;

   assert(format == GL_DEPTH_STENCIL);
   assert(type == GL_UNSIGNED_INT_24_8);
   /* XXX type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV is not handled yet */

   for (img = 0; img < depth; img++) {
      GLubyte *srcMap;
      GLint rowstride;

      /* map src texture buffer */
      ctx->Driver.MapTextureImage(ctx, texImage, img,
                                  0, 0, width, height, GL_MAP_READ_BIT,
                                  &srcMap, &rowstride);

      if (srcMap) {
         for (row = 0; row < height; row++) {
            const GLubyte *src = srcMap + row * rowstride;
            void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                             width, height, format, type,
                                             img, row, 0);
            /* Unpack from texture's format to GL's z24_s8 layout */
            _mesa_unpack_uint_24_8_depth_stencil_row(texImage->TexFormat,
                                                     width,
                                                     (const GLuint *) src,
                                                     dest);
            if (ctx->Pack.SwapBytes) {
               _mesa_swap4((GLuint *) dest, width);
            }
         }

         ctx->Driver.UnmapTextureImage(ctx, texImage, img);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         break;
      }
   }
}
Exemplo n.º 5
0
/**
 * glGetTexImagefor sRGB pixels;
 */
static void
get_tex_srgb(GLcontext *ctx, GLuint dimensions,
             GLenum format, GLenum type, GLvoid *pixels,
             const struct gl_texture_image *texImage)
{
   const GLint width = texImage->Width;
   const GLint height = texImage->Height;
   const GLint depth = texImage->Depth;
   const GLbitfield transferOps = 0x0;
   GLint img, row;

   for (img = 0; img < depth; img++) {
      for (row = 0; row < height; row++) {
         void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                          width, height, format, type,
                                          img, row, 0);

         GLfloat rgba[MAX_WIDTH][4];
         GLint col;

         /* convert row to RGBA format */
         for (col = 0; col < width; col++) {
            texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
            if (texImage->_BaseFormat == GL_LUMINANCE) {
               rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
               rgba[col][GCOMP] = 0.0;
               rgba[col][BCOMP] = 0.0;
            }
            else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
               rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
               rgba[col][GCOMP] = 0.0;
               rgba[col][BCOMP] = 0.0;
            }
            else if (texImage->_BaseFormat == GL_RGB ||
                     texImage->_BaseFormat == GL_RGBA) {
               rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
               rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
               rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
            }
         }
         _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
                                    format, type, dest,
                                    &ctx->Pack, transferOps);
      }
   }
}
Exemplo n.º 6
0
/**
 * 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;
}
Exemplo n.º 7
0
/**
 * Teximage storage routine for when a simple memcpy will do.
 * No pixel transfer operations or special texel encodings allowed.
 * 1D, 2D and 3D images supported.
 */
static void
memcpy_texture(struct gl_context *ctx,
	       GLuint dimensions,
               mesa_format dstFormat,
               GLint dstRowStride,
               GLubyte **dstSlices,
               GLint srcWidth, GLint srcHeight, GLint srcDepth,
               GLenum srcFormat, GLenum srcType,
               const GLvoid *srcAddr,
               const struct gl_pixelstore_attrib *srcPacking)
{
   const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
                                                     srcFormat, srcType);
   const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
                                      srcWidth, srcHeight, srcFormat, srcType);
   const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
        srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
   const GLint bytesPerRow = srcWidth * texelBytes;

   if (dstRowStride == srcRowStride &&
       dstRowStride == bytesPerRow) {
      /* memcpy image by image */
      GLint img;
      for (img = 0; img < srcDepth; img++) {
         GLubyte *dstImage = dstSlices[img];
         memcpy(dstImage, srcImage, bytesPerRow * srcHeight);
         srcImage += srcImageStride;
      }
   }
   else {
      /* memcpy row by row */
      GLint img, row;
      for (img = 0; img < srcDepth; img++) {
         const GLubyte *srcRow = srcImage;
         GLubyte *dstRow = dstSlices[img];
         for (row = 0; row < srcHeight; row++) {
            memcpy(dstRow, srcRow, bytesPerRow);
            dstRow += dstRowStride;
            srcRow += srcRowStride;
         }
         srcImage += srcImageStride;
      }
   }
}
/**
 * glGetTexImage for depth/Z pixels.
 */
static void
get_tex_depth(struct gl_context *ctx, GLuint dimensions,
              GLenum format, GLenum type, GLvoid *pixels,
              struct gl_texture_image *texImage)
{
   const GLint width = texImage->Width;
   const GLint height = texImage->Height;
   const GLint depth = texImage->Depth;
   GLint img, row;
   GLfloat *depthRow = (GLfloat *) malloc(width * sizeof(GLfloat));

   if (!depthRow) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
      return;
   }

   for (img = 0; img < depth; img++) {
      GLubyte *srcMap;
      GLint srcRowStride;

      /* map src texture buffer */
      ctx->Driver.MapTextureImage(ctx, texImage, img,
                                  0, 0, width, height, GL_MAP_READ_BIT,
                                  &srcMap, &srcRowStride);

      if (srcMap) {
         for (row = 0; row < height; row++) {
            void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                             width, height, format, type,
                                             img, row, 0);
            const GLubyte *src = srcMap + row * srcRowStride;
            _mesa_unpack_float_z_row(texImage->TexFormat, width, src, depthRow);
            _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack);
         }

         ctx->Driver.UnmapTextureImage(ctx, texImage, img);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         break;
      }
   }

   free(depthRow);
}
Exemplo n.º 9
0
/**
 * glGetTexImage for color index pixels.
 */
static void
get_tex_color_index(GLcontext *ctx, GLuint dimensions,
                    GLenum format, GLenum type, GLvoid *pixels,
                    const struct gl_texture_image *texImage)
{
   const GLint width = texImage->Width;
   const GLint height = texImage->Height;
   const GLint depth = texImage->Depth;
   const GLuint indexBits =
      _mesa_get_format_bits(texImage->TexFormat, GL_TEXTURE_INDEX_SIZE_EXT);
   const GLbitfield transferOps = 0x0;
   GLint img, row, col;

   for (img = 0; img < depth; img++) {
      for (row = 0; row < height; row++) {
         GLuint indexRow[MAX_WIDTH] = { 0 };
         void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                          width, height, format, type,
                                          img, row, 0);
         assert(dest);

         if (indexBits == 8) {
            const GLubyte *src = (const GLubyte *) texImage->Data;
            src += width * (img * texImage->Height + row);
            for (col = 0; col < width; col++) {
               indexRow[col] = src[col];
            }
         }
         else if (indexBits == 16) {
            const GLushort *src = (const GLushort *) texImage->Data;
            src += width * (img * texImage->Height + row);
            for (col = 0; col < width; col++) {
               indexRow[col] = src[col];
            }
         }
         else {
            _mesa_problem(ctx, "Color index problem in _mesa_GetTexImage");
         }
         _mesa_pack_index_span(ctx, width, type, dest,
                               indexRow, &ctx->Pack, transferOps);
      }
   }
}
Exemplo n.º 10
0
/**
 * glGetTexImage for stencil pixels.
 */
static void
get_tex_stencil(struct gl_context *ctx, GLuint dimensions,
                GLenum format, GLenum type, GLvoid *pixels,
                struct gl_texture_image *texImage)
{
   const GLint width = texImage->Width;
   const GLint height = texImage->Height;
   const GLint depth = texImage->Depth;
   GLint img, row;

   assert(format == GL_STENCIL_INDEX);

   for (img = 0; img < depth; img++) {
      GLubyte *srcMap;
      GLint rowstride;

      /* map src texture buffer */
      ctx->Driver.MapTextureImage(ctx, texImage, img,
                                  0, 0, width, height, GL_MAP_READ_BIT,
                                  &srcMap, &rowstride);

      if (srcMap) {
         for (row = 0; row < height; row++) {
            const GLubyte *src = srcMap + row * rowstride;
            void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                             width, height, format, type,
                                             img, row, 0);
//            _mesa_unpack_ubyte_stencil_row(texImage->TexFormat,
//                                           width,
//                                           (const GLuint *) src,
//                                           dest);
         }

         ctx->Driver.UnmapTextureImage(ctx, texImage, img);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         break;
      }
   }
}
/**
 * glGetTexImage for depth/stencil pixels.
 */
static void
get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions,
                      GLenum format, GLenum type, GLvoid *pixels,
                      struct gl_texture_image *texImage)
{
   const GLint width = texImage->Width;
   const GLint height = texImage->Height;
   const GLint depth = texImage->Depth;
   GLint img, row;

   for (img = 0; img < depth; img++) {
      GLubyte *srcMap;
      GLint rowstride;

      /* map src texture buffer */
      ctx->Driver.MapTextureImage(ctx, texImage, img,
                                  0, 0, width, height, GL_MAP_READ_BIT,
                                  &srcMap, &rowstride);

      if (srcMap) {
         for (row = 0; row < height; row++) {
            const GLubyte *src = srcMap + row * rowstride;
            void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                             width, height, format, type,
                                             img, row, 0);
            /* XXX Z24_S8 vs. S8_Z24??? */
            memcpy(dest, src, width * sizeof(GLuint));
            if (ctx->Pack.SwapBytes) {
               _mesa_swap4((GLuint *) dest, width);
            }
         }

         ctx->Driver.UnmapTextureImage(ctx, texImage, img);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         break;
      }
   }
}
Exemplo n.º 12
0
/**
 * Get a color texture image with decompression.
 */
static void
get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions,
                        GLenum format, GLenum type, GLvoid *pixels,
                        struct gl_texture_image *texImage,
                        GLbitfield transferOps)
{
   /* don't want to apply sRGB -> RGB conversion here so override the format */
   const mesa_format texFormat =
      _mesa_get_srgb_format_linear(texImage->TexFormat);
   const GLenum baseFormat = _mesa_get_format_base_format(texFormat);
   const GLuint width = texImage->Width;
   const GLuint height = texImage->Height;
   const GLuint depth = texImage->Depth;
   GLfloat *tempImage, *tempSlice;
   GLuint slice;
   int srcStride, dstStride;
   uint32_t dstFormat;
   bool needsRebase;
   uint8_t rebaseSwizzle[4];

   /* Decompress into temp float buffer, then pack into user buffer */
   tempImage = malloc(width * height * depth
                                  * 4 * sizeof(GLfloat));
   if (!tempImage) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
      return;
   }

   /* Decompress the texture image slices - results in 'tempImage' */
   for (slice = 0; slice < depth; slice++) {
      GLubyte *srcMap;
      GLint srcRowStride;

      tempSlice = tempImage + slice * 4 * width * height;

      ctx->Driver.MapTextureImage(ctx, texImage, slice,
                                  0, 0, width, height,
                                  GL_MAP_READ_BIT,
                                  &srcMap, &srcRowStride);
      if (srcMap) {
         _mesa_decompress_image(texFormat, width, height,
                                srcMap, srcRowStride, tempSlice);

         ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         free(tempImage);
         return;
      }
   }

   /* Depending on the base format involved we may need to apply a rebase
    * transform (for example: if we download to a Luminance format we want
    * G=0 and B=0).
    */
   if (baseFormat == GL_LUMINANCE ||
       baseFormat == GL_INTENSITY) {
      needsRebase = true;
      rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
   } else if (baseFormat == GL_LUMINANCE_ALPHA) {
      needsRebase = true;
      rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_W;
   } else {
      needsRebase = false;
   }

   srcStride = 4 * width * sizeof(GLfloat);
   dstStride = _mesa_image_row_stride(&ctx->Pack, width, format, type);
   dstFormat = _mesa_format_from_format_and_type(format, type);
   tempSlice = tempImage;
   for (slice = 0; slice < depth; slice++) {
      void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                       width, height, format, type,
                                       slice, 0, 0);
//      _mesa_format_convert(dest, dstFormat, dstStride,
//                           tempSlice, RGBA32_FLOAT, srcStride,
//                           width, height,
//                           needsRebase ? rebaseSwizzle : NULL);
      tempSlice += 4 * width * height;
   }

   free(tempImage);
}
/**
 * Get an uncompressed color texture image.
 */
static void
get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
                          GLenum format, GLenum type, GLvoid *pixels,
                          struct gl_texture_image *texImage,
                          GLbitfield transferOps)
{
   /* don't want to apply sRGB -> RGB conversion here so override the format */
   const gl_format texFormat =
      _mesa_get_srgb_format_linear(texImage->TexFormat);
   const GLuint width = texImage->Width;
   const GLenum destBaseFormat = _mesa_base_tex_format(ctx, format);
   GLenum rebaseFormat = GL_NONE;
   GLuint height = texImage->Height;
   GLuint depth = texImage->Depth;
   GLuint img, row;
   GLfloat (*rgba)[4];
   GLuint (*rgba_uint)[4];
   GLboolean tex_is_integer = _mesa_is_format_integer_color(texImage->TexFormat);
   GLboolean tex_is_uint = _mesa_is_format_unsigned(texImage->TexFormat);

   /* Allocate buffer for one row of texels */
   rgba = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
   rgba_uint = (GLuint (*)[4]) rgba;
   if (!rgba) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
      return;
   }

   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
      depth = height;
      height = 1;
   }

   if (texImage->_BaseFormat == GL_LUMINANCE ||
       texImage->_BaseFormat == GL_INTENSITY ||
       texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
      /* If a luminance (or intensity) texture is read back as RGB(A), the
       * returned value should be (L,0,0,1), not (L,L,L,1).  Set rebaseFormat
       * here to get G=B=0.
       */
      rebaseFormat = texImage->_BaseFormat;
   }
   else if ((texImage->_BaseFormat == GL_RGBA ||
             texImage->_BaseFormat == GL_RGB ||
             texImage->_BaseFormat == GL_RG) &&
            (destBaseFormat == GL_LUMINANCE ||
             destBaseFormat == GL_LUMINANCE_ALPHA ||
             destBaseFormat == GL_LUMINANCE_INTEGER_EXT ||
             destBaseFormat == GL_LUMINANCE_ALPHA_INTEGER_EXT)) {
      /* If we're reading back an RGB(A) texture as luminance then we need
       * to return L=tex(R).  Note, that's different from glReadPixels which
       * returns L=R+G+B.
       */
      rebaseFormat = GL_LUMINANCE_ALPHA; /* this covers GL_LUMINANCE too */
   }

   for (img = 0; img < depth; img++) {
      GLubyte *srcMap;
      GLint rowstride;

      /* map src texture buffer */
      ctx->Driver.MapTextureImage(ctx, texImage, img,
                                  0, 0, width, height, GL_MAP_READ_BIT,
                                  &srcMap, &rowstride);
      if (srcMap) {
         for (row = 0; row < height; row++) {
            const GLubyte *src = srcMap + row * rowstride;
            void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                             width, height, format, type,
                                             img, row, 0);

	    if (tex_is_integer) {
	       _mesa_unpack_uint_rgba_row(texFormat, width, src, rgba_uint);
               if (rebaseFormat)
                  _mesa_rebase_rgba_uint(width, rgba_uint, rebaseFormat);
               if (tex_is_uint) {
                  _mesa_pack_rgba_span_from_uints(ctx, width,
                                                  (GLuint (*)[4]) rgba_uint,
                                                  format, type, dest);
               } else {
                  _mesa_pack_rgba_span_from_ints(ctx, width,
                                                 (GLint (*)[4]) rgba_uint,
                                                 format, type, dest);
               }
	    } else {
	       _mesa_unpack_rgba_row(texFormat, width, src, rgba);
               if (rebaseFormat)
                  _mesa_rebase_rgba_float(width, rgba, rebaseFormat);
	       _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
					  format, type, dest,
					  &ctx->Pack, transferOps);
	    }
	 }

         /* Unmap the src texture buffer */
         ctx->Driver.UnmapTextureImage(ctx, texImage, img);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         break;
      }
   }

   free(rgba);
}
/**
 * Get a color texture image with decompression.
 */
static void
get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions,
                        GLenum format, GLenum type, GLvoid *pixels,
                        struct gl_texture_image *texImage,
                        GLbitfield transferOps)
{
   /* don't want to apply sRGB -> RGB conversion here so override the format */
   const gl_format texFormat =
      _mesa_get_srgb_format_linear(texImage->TexFormat);
   const GLenum baseFormat = _mesa_get_format_base_format(texFormat);
   const GLenum destBaseFormat = _mesa_base_tex_format(ctx, format);
   GLenum rebaseFormat = GL_NONE;
   const GLuint width = texImage->Width;
   const GLuint height = texImage->Height;
   const GLuint depth = texImage->Depth;
   GLfloat *tempImage, *srcRow;
   GLuint row;

   /* Decompress into temp float buffer, then pack into user buffer */
   tempImage = (GLfloat *) malloc(width * height * depth
                                  * 4 * sizeof(GLfloat));
   if (!tempImage) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
      return;
   }

   /* Decompress the texture image - results in 'tempImage' */
   {
      GLubyte *srcMap;
      GLint srcRowStride;

      ctx->Driver.MapTextureImage(ctx, texImage, 0,
                                  0, 0, width, height,
                                  GL_MAP_READ_BIT,
                                  &srcMap, &srcRowStride);
      if (srcMap) {
         _mesa_decompress_image(texFormat, width, height,
                                srcMap, srcRowStride, tempImage);

         ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         free(tempImage);
         return;
      }
   }

   if (baseFormat == GL_LUMINANCE ||
       baseFormat == GL_INTENSITY ||
       baseFormat == GL_LUMINANCE_ALPHA) {
      /* If a luminance (or intensity) texture is read back as RGB(A), the
       * returned value should be (L,0,0,1), not (L,L,L,1).  Set rebaseFormat
       * here to get G=B=0.
       */
      rebaseFormat = texImage->_BaseFormat;
   }
   else if ((baseFormat == GL_RGBA ||
             baseFormat == GL_RGB  ||
             baseFormat == GL_RG) &&
            (destBaseFormat == GL_LUMINANCE ||
             destBaseFormat == GL_LUMINANCE_ALPHA ||
             destBaseFormat == GL_LUMINANCE_INTEGER_EXT ||
             destBaseFormat == GL_LUMINANCE_ALPHA_INTEGER_EXT)) {
      /* If we're reading back an RGB(A) texture as luminance then we need
       * to return L=tex(R).  Note, that's different from glReadPixels which
       * returns L=R+G+B.
       */
      rebaseFormat = GL_LUMINANCE_ALPHA; /* this covers GL_LUMINANCE too */
   }

   if (rebaseFormat) {
      _mesa_rebase_rgba_float(width * height, (GLfloat (*)[4]) tempImage,
                              rebaseFormat);
   }

   srcRow = tempImage;
   for (row = 0; row < height; row++) {
      void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                       width, height, format, type,
                                       0, row, 0);

      _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) srcRow,
                                 format, type, dest, &ctx->Pack, transferOps);
      srcRow += width * 4;
   }

   free(tempImage);
}
Exemplo n.º 15
0
static GLboolean
texstore_rgba(TEXSTORE_PARAMS)
{
   void *tempImage = NULL, *tempRGBA = NULL;
   int srcRowStride, img;
   GLubyte *src, *dst;
   uint32_t srcMesaFormat;
   uint8_t rebaseSwizzle[4];
   bool needRebase;
   bool transferOpsDone = false;

   /* We have to handle MESA_FORMAT_YCBCR manually because it is a special case
    * and _mesa_format_convert does not support it. In this case the we only
    * allow conversions between YCBCR formats and it is mostly a memcpy.
    */
   if (dstFormat == MESA_FORMAT_YCBCR || dstFormat == MESA_FORMAT_YCBCR_REV) {
      return _mesa_texstore_ycbcr(ctx, dims, baseInternalFormat,
                                  dstFormat, dstRowStride, dstSlices,
                                  srcWidth, srcHeight, srcDepth,
                                  srcFormat, srcType, srcAddr,
                                  srcPacking);
   }

   /* We have to deal with GL_COLOR_INDEX manually because
    * _mesa_format_convert does not handle this format. So what we do here is
    * convert it to RGBA ubyte first and then convert from that to dst as usual.
    */
   if (srcFormat == GL_COLOR_INDEX) {
      /* Notice that this will already handle byte swapping if necessary */
      tempImage =
         _mesa_unpack_color_index_to_rgba_ubyte(ctx, dims,
                                                srcAddr, srcFormat, srcType,
                                                srcWidth, srcHeight, srcDepth,
                                                srcPacking,
                                                ctx->_ImageTransferState);
      if (!tempImage)
         return GL_FALSE;

      /* _mesa_unpack_color_index_to_rgba_ubyte has handled transferops
       * if needed.
       */
      transferOpsDone = true;

      /* Now we only have to adjust our src info for a conversion from
       * the RGBA ubyte and then we continue as usual.
       */
      srcAddr = tempImage;
      srcFormat = GL_RGBA;
      srcType = GL_UNSIGNED_BYTE;
   } else if (srcPacking->SwapBytes) {
      /* We have to handle byte-swapping scenarios before calling
       * _mesa_format_convert
       */
      GLint swapSize = _mesa_sizeof_packed_type(srcType);
      if (swapSize == 2 || swapSize == 4) {
         int bytesPerPixel = _mesa_bytes_per_pixel(srcFormat, srcType);
         int swapsPerPixel = bytesPerPixel / swapSize;
         int elementCount = srcWidth * srcHeight * srcDepth;
         assert(bytesPerPixel % swapSize == 0);
         tempImage = malloc(elementCount * bytesPerPixel);
         if (!tempImage)
            return GL_FALSE;
         if (swapSize == 2)
            _mesa_swap2_copy(tempImage, (GLushort *) srcAddr,
                             elementCount * swapsPerPixel);
         else
            _mesa_swap4_copy(tempImage, (GLuint *) srcAddr,
                             elementCount * swapsPerPixel);
         srcAddr = tempImage;
      }
   }

   srcRowStride =
      _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);

   srcMesaFormat = _mesa_format_from_format_and_type(srcFormat, srcType);
   dstFormat = _mesa_get_srgb_format_linear(dstFormat);

   /* If we have transferOps then we need to convert to RGBA float first,
      then apply transferOps, then do the conversion to dst
    */
   if (!transferOpsDone &&
       _mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat)) {
      /* Allocate RGBA float image */
      int elementCount = srcWidth * srcHeight * srcDepth;
      tempRGBA = malloc(4 * elementCount * sizeof(float));
      if (!tempRGBA) {
         free(tempImage);
         free(tempRGBA);
         return GL_FALSE;
      }

      /* Convert from src to RGBA float */
      src = (GLubyte *) srcAddr;
      dst = (GLubyte *) tempRGBA;
      for (img = 0; img < srcDepth; img++) {
         _mesa_format_convert(dst, RGBA32_FLOAT, 4 * srcWidth * sizeof(float),
                              src, srcMesaFormat, srcRowStride,
                              srcWidth, srcHeight, NULL);
         src += srcHeight * srcRowStride;
         dst += srcHeight * 4 * srcWidth * sizeof(float);
      }

      /* Apply transferOps */
      _mesa_apply_rgba_transfer_ops(ctx, ctx->_ImageTransferState, elementCount,
                                    (float(*)[4]) tempRGBA);

      /* Now we have to adjust our src info for a conversion from
       * the RGBA float image and then we continue as usual.
       */
      srcAddr = tempRGBA;
      srcFormat = GL_RGBA;
      srcType = GL_FLOAT;
      srcRowStride = srcWidth * 4 * sizeof(float);
      srcMesaFormat = RGBA32_FLOAT;
   }

   src = (GLubyte *)
      _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
                          srcFormat, srcType, 0, 0, 0);

   if (_mesa_get_format_base_format(dstFormat) != baseInternalFormat) {
      needRebase =
         _mesa_compute_rgba2base2rgba_component_mapping(baseInternalFormat,
                                                        rebaseSwizzle);
   } else {
      needRebase = false;
   }

   for (img = 0; img < srcDepth; img++) {
      _mesa_format_convert(dstSlices[img], dstFormat, dstRowStride,
                           src, srcMesaFormat, srcRowStride,
                           srcWidth, srcHeight,
                           needRebase ? rebaseSwizzle : NULL);
      src += srcHeight * srcRowStride;
   }

   free(tempImage);
   free(tempRGBA);

   return GL_TRUE;
}
Exemplo n.º 16
0
/* Pros:  
 *   - no waiting for idle before updating framebuffer.
 *   
 * Cons:
 *   - if upload is by memcpy, this may actually be slower than fallback path.
 *   - uploads the whole image even if destination is clipped
 *   
 * Need to benchmark.
 *
 * Given the questions about performance, implement for pbo's only.
 * This path is definitely a win if the pbo is already in agp.  If it
 * turns out otherwise, we can add the code necessary to upload client
 * data to agp space before performing the blit.  (Though it may turn
 * out to be better/simpler just to use the texture engine).
 */
static GLboolean
do_blit_drawpixels(GLcontext * ctx,
                   GLint x, GLint y,
                   GLsizei width, GLsizei height,
                   GLenum format, GLenum type,
                   const struct gl_pixelstore_attrib *unpack,
                   const GLvoid * pixels)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_region *dest = intel_drawbuf_region(intel);
   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
   GLuint src_offset;
   GLuint rowLength;
   struct _DriFenceObject *fence = NULL;

   if (INTEL_DEBUG & DEBUG_PIXEL)
      _mesa_printf("%s\n", __FUNCTION__);


   if (!dest) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - no dest\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (src) {
      /* This validation should be done by core mesa:
       */
      if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
                                     format, type, pixels)) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
         return GL_TRUE;
      }
   }
   else {
      /* PBO only for now:
       */
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - not PBO\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (!intel_check_blit_format(dest, format, type)) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad format for blit\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (!intel_check_blit_fragment_ops(ctx)) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad GL fragment state for blitter\n",
                      __FUNCTION__);
      return GL_FALSE;
   }

   if (ctx->Pixel.ZoomX != 1.0F) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad PixelZoomX for blit\n", __FUNCTION__);
      return GL_FALSE;
   }


   if (unpack->RowLength > 0)
      rowLength = unpack->RowLength;
   else
      rowLength = width;

   if (ctx->Pixel.ZoomY == -1.0F) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
      return GL_FALSE;          /* later */
      y -= height;
   }
   else if (ctx->Pixel.ZoomY == 1.0F) {
      rowLength = -rowLength;
   }
   else {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
      return GL_FALSE;
   }

   src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
                                             format, type, 0, 0, 0);

   intelFlush(&intel->ctx);
   LOCK_HARDWARE(intel);

   if (intel->driDrawable->numClipRects) {
      __DRIdrawablePrivate *dPriv = intel->driDrawable;
      int nbox = dPriv->numClipRects;
      drm_clip_rect_t *box = dPriv->pClipRects;
      drm_clip_rect_t rect;
      drm_clip_rect_t dest_rect;
      struct _DriBufferObject *src_buffer =
         intel_bufferobj_buffer(intel, src, INTEL_READ);
      int i;

      dest_rect.x1 = dPriv->x + x;
      dest_rect.y1 = dPriv->y + dPriv->h - (y + height);
      dest_rect.x2 = dest_rect.x1 + width;
      dest_rect.y2 = dest_rect.y1 + height;

      for (i = 0; i < nbox; i++) {
         if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
            continue;

         intelEmitCopyBlit(intel,
                           dest->cpp,
                           rowLength,
                           src_buffer, src_offset,
                           dest->pitch,
                           dest->buffer, 0,
                           rect.x1 - dest_rect.x1,
                           rect.y2 - dest_rect.y2,
                           rect.x1,
                           rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1,
			   ctx->Color.ColorLogicOpEnabled ?
			   ctx->Color.LogicOp : GL_COPY);
      }
      fence = intel_batchbuffer_flush(intel->batch);
      driFenceReference(fence);
   }
   UNLOCK_HARDWARE(intel);

   if (fence) {
      driFenceFinish(fence, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, GL_FALSE);
      driFenceUnReference(fence);
   }

   if (INTEL_DEBUG & DEBUG_PIXEL)
      _mesa_printf("%s - DONE\n", __FUNCTION__);

   return GL_TRUE;
}
Exemplo n.º 17
0
/**
 * glGetTexImagefor RGBA, Luminance, etc. pixels.
 * This is the slow way since we use texture sampling.
 */
static void
get_tex_rgba(GLcontext *ctx, GLuint dimensions,
             GLenum format, GLenum type, GLvoid *pixels,
             const struct gl_texture_image *texImage)
{
   const GLint width = texImage->Width;
   const GLint height = texImage->Height;
   const GLint depth = texImage->Depth;
   /* Normally, no pixel transfer ops are performed during glGetTexImage.
    * The only possible exception is component clamping to [0,1].
    */
   GLbitfield transferOps = 0x0;
   GLint img, row;

   for (img = 0; img < depth; img++) {
      for (row = 0; row < height; row++) {
         void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                          width, height, format, type,
                                          img, row, 0);
         GLfloat rgba[MAX_WIDTH][4];
         GLint col;
         GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat);

         /* clamp does not apply to GetTexImage (final conversion)?
          * Looks like we need clamp though when going from format
          * containing negative values to unsigned format.
          */
         if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) {
            transferOps |= IMAGE_CLAMP_BIT;
         }
         else if (!type_with_negative_values(type) &&
                  (dataType == GL_FLOAT ||
                   dataType == GL_SIGNED_NORMALIZED)) {
            transferOps |= IMAGE_CLAMP_BIT;
         }

         for (col = 0; col < width; col++) {
            texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
            if (texImage->_BaseFormat == GL_ALPHA) {
               rgba[col][RCOMP] = 0.0F;
               rgba[col][GCOMP] = 0.0F;
               rgba[col][BCOMP] = 0.0F;
            }
            else if (texImage->_BaseFormat == GL_LUMINANCE) {
               rgba[col][GCOMP] = 0.0F;
               rgba[col][BCOMP] = 0.0F;
               rgba[col][ACOMP] = 1.0F;
            }
            else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
               rgba[col][GCOMP] = 0.0F;
               rgba[col][BCOMP] = 0.0F;
            }
            else if (texImage->_BaseFormat == GL_INTENSITY) {
               rgba[col][GCOMP] = 0.0F;
               rgba[col][BCOMP] = 0.0F;
               rgba[col][ACOMP] = 1.0F;
            }
         }
         _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
                                    format, type, dest,
                                    &ctx->Pack, transferOps);
      }
   }
}
Exemplo n.º 18
0
/**
 * This is the software fallback for Driver.GetTexImage().
 * All error checking will have been done before this routine is called.
 */
void
_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
                   GLenum format, GLenum type, GLvoid *pixels,
                   struct gl_texture_object *texObj,
                   struct gl_texture_image *texImage)
{
   const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;

   if (ctx->Pack.BufferObj->Name) {
      /* Packing texture image into a PBO.
       * Map the (potentially) VRAM-based buffer into our process space so
       * we can write into it with the code below.
       * A hardware driver might use a sophisticated blit to move the
       * texture data to the PBO if the PBO is in VRAM along with the texture.
       */
      GLubyte *buf = (GLubyte *)
         ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                               GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
      if (!buf) {
         /* buffer is already mapped - that's an error */
         _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
         return;
      }
      /* <pixels> was an offset into the PBO.
       * Now make it a real, client-side pointer inside the mapped region.
       */
      pixels = ADD_POINTERS(buf, pixels);
   }
   else if (!pixels) {
      /* not an error */
      return;
   }

   {
      const GLint width = texImage->Width;
      const GLint height = texImage->Height;
      const GLint depth = texImage->Depth;
      GLint img, row;
      for (img = 0; img < depth; img++) {
         for (row = 0; row < height; row++) {
            /* compute destination address in client memory */
            GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
                                                width, height, format, type,
                                                img, row, 0);
            assert(dest);

            if (format == GL_COLOR_INDEX) {
               GLuint indexRow[MAX_WIDTH];
               GLint col;
               /* Can't use FetchTexel here because that returns RGBA */
               if (texImage->TexFormat->IndexBits == 8) {
                  const GLubyte *src = (const GLubyte *) texImage->Data;
                  src += width * (img * texImage->Height + row);
                  for (col = 0; col < width; col++) {
                     indexRow[col] = src[col];
                  }
               }
               else if (texImage->TexFormat->IndexBits == 16) {
                  const GLushort *src = (const GLushort *) texImage->Data;
                  src += width * (img * texImage->Height + row);
                  for (col = 0; col < width; col++) {
                     indexRow[col] = src[col];
                  }
               }
               else {
                  _mesa_problem(ctx,
                                "Color index problem in _mesa_GetTexImage");
               }
               _mesa_pack_index_span(ctx, width, type, dest,
                                     indexRow, &ctx->Pack,
                                     0 /* no image transfer */);
            }
            else if (format == GL_DEPTH_COMPONENT) {
               GLfloat depthRow[MAX_WIDTH];
               GLint col;
               for (col = 0; col < width; col++) {
                  (*texImage->FetchTexelf)(texImage, col, row, img,
                                           depthRow + col);
               }
               _mesa_pack_depth_span(ctx, width, dest, type,
                                     depthRow, &ctx->Pack);
            }
            else if (format == GL_DEPTH_STENCIL_EXT) {
               /* XXX Note: we're bypassing texImage->FetchTexel()! */
               const GLuint *src = (const GLuint *) texImage->Data;
               src += width * row + width * height * img;
               _mesa_memcpy(dest, src, width * sizeof(GLuint));
               if (ctx->Pack.SwapBytes) {
                  _mesa_swap4((GLuint *) dest, width);
               }
            }
            else if (format == GL_YCBCR_MESA) {
               /* No pixel transfer */
               const GLint rowstride = texImage->RowStride;
               MEMCPY(dest,
                      (const GLushort *) texImage->Data + row * rowstride,
                      width * sizeof(GLushort));
               /* check for byte swapping */
               if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
                    && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
                   (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
                    && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
                  if (!ctx->Pack.SwapBytes)
                     _mesa_swap2((GLushort *) dest, width);
               }
               else if (ctx->Pack.SwapBytes) {
                  _mesa_swap2((GLushort *) dest, width);
               }
            }
#if FEATURE_EXT_texture_sRGB
            else if (is_srgb_teximage(texImage)) {
               /* special case this since need to backconvert values */
               /* convert row to RGBA format */
               GLfloat rgba[MAX_WIDTH][4];
               GLint col;
               GLbitfield transferOps = 0x0;

               for (col = 0; col < width; col++) {
                  (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
                  if (texImage->_BaseFormat == GL_LUMINANCE) {
                     rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                  }
                  else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
                     rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                  }
                  else if (texImage->_BaseFormat == GL_RGB ||
                     texImage->_BaseFormat == GL_RGBA) {
                     rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
                     rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
                     rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
                  }
               }
               _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
                                          format, type, dest,
                                          &ctx->Pack, transferOps);
            }
#endif /* FEATURE_EXT_texture_sRGB */
            else {
               /* general case:  convert row to RGBA format */
               GLfloat rgba[MAX_WIDTH][4];
               GLint col;
               GLbitfield transferOps = 0x0;

               /* clamp does not apply to GetTexImage (final conversion)?
                * Looks like we need clamp though when going from format
                * containing negative values to unsigned format.
                */
               if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA)
                  transferOps |= IMAGE_CLAMP_BIT;
               else if (!type_with_negative_values(type) &&
                        (texImage->TexFormat->DataType == GL_FLOAT ||
                         texImage->TexFormat->DataType == GL_SIGNED_NORMALIZED))
                  transferOps |= IMAGE_CLAMP_BIT;

               for (col = 0; col < width; col++) {
                  (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
                  if (texImage->_BaseFormat == GL_ALPHA) {
                     rgba[col][RCOMP] = 0.0;
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                  }
                  else if (texImage->_BaseFormat == GL_LUMINANCE) {
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                     rgba[col][ACOMP] = 1.0;
                  }
                  else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                  }
                  else if (texImage->_BaseFormat == GL_INTENSITY) {
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                     rgba[col][ACOMP] = 1.0;
                  }
               }
               _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
                                          format, type, dest,
                                          &ctx->Pack, transferOps);
            } /* format */
         } /* row */
      } /* img */
   }

   if (ctx->Pack.BufferObj->Name) {
      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                              ctx->Pack.BufferObj);
   }
}
Exemplo n.º 19
0
/**
 * Get an uncompressed color texture image.
 */
static void
get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
                          GLenum format, GLenum type, GLvoid *pixels,
                          struct gl_texture_image *texImage,
                          GLbitfield transferOps)
{
   /* don't want to apply sRGB -> RGB conversion here so override the format */
   const mesa_format texFormat =
      _mesa_get_srgb_format_linear(texImage->TexFormat);
   const GLuint width = texImage->Width;
   GLuint height = texImage->Height;
   GLuint depth = texImage->Depth;
   GLuint img;
   GLboolean dst_is_integer;
   uint32_t dst_format;
   int dst_stride;
   uint8_t rebaseSwizzle[4];
   bool needsRebase;
   void *rgba = NULL;

   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
      depth = height;
      height = 1;
   }

   /* Depending on the base format involved we may need to apply a rebase
    * transform (for example: if we download to a Luminance format we want
    * G=0 and B=0).
    */
   if (texImage->_BaseFormat == GL_LUMINANCE ||
       texImage->_BaseFormat == GL_INTENSITY) {
      needsRebase = true;
      rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
   } else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
      needsRebase = true;
      rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_W;
//    } else if (texImage->_BaseFormat != _mesa_get_format_base_format(texFormat)) {
//      needsRebase =
//         _mesa_compute_rgba2base2rgba_component_mapping(texImage->_BaseFormat,
//                                                        rebaseSwizzle);
    } else {
      needsRebase = false;
    }

   /* Describe the dst format */
   dst_is_integer = _mesa_is_enum_format_integer(format);
   dst_format = _mesa_format_from_format_and_type(format, type);
   dst_stride = _mesa_image_row_stride(&ctx->Pack, width, format, type);

   /* Since _mesa_format_convert does not handle transferOps we need to handle
    * them before we call the function. This requires to convert to RGBA float
    * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
    * integer then transferOps do not apply.
    */
   assert(!transferOps || (transferOps && !dst_is_integer));
   (void) dst_is_integer; /* silence unused var warning */

   for (img = 0; img < depth; img++) {
      GLubyte *srcMap;
      GLint rowstride;
      GLubyte *img_src;
      void *dest;
      void *src;
      int src_stride;
      uint32_t src_format;

      /* map src texture buffer */
      ctx->Driver.MapTextureImage(ctx, texImage, img,
                                  0, 0, width, height, GL_MAP_READ_BIT,
                                  &srcMap, &rowstride);
      if (!srcMap) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         goto done;
      }

      img_src = srcMap;
      dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                 width, height, format, type,
                                 img, 0, 0);

      if (transferOps) {
         uint32_t rgba_format;
         int rgba_stride;
         bool need_convert = false;

         /* We will convert to RGBA float */
//         rgba_format = RGBA32_FLOAT;
         rgba_stride = width * 4 * sizeof(GLfloat);

         /* If we are lucky and the dst format matches the RGBA format we need
          * to convert to, then we can convert directly into the dst buffer
          * and avoid the final conversion/copy from the rgba buffer to the dst
          * buffer.
          */
         if (format == rgba_format) {
            rgba = dest;
         } else if (rgba == NULL) { /* Allocate the RGBA buffer only once */
            need_convert = true;
            rgba = malloc(height * rgba_stride);
            if (!rgba) {
               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
               ctx->Driver.UnmapTextureImage(ctx, texImage, img);
               return;
            }
         }

//         _mesa_format_convert(rgba, rgba_format, rgba_stride,
//                              img_src, texFormat, rowstride,
//                              width, height,
//                              needsRebase ? rebaseSwizzle : NULL);

         /* Handle transfer ops now */
         _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);

         /* If we had to rebase, we have already handled that */
         needsRebase = false;

         /* If we were lucky and our RGBA conversion matches the dst format, then
          * we are done.
          */
         if (!need_convert)
            goto do_swap;

         /* Otherwise, we need to convert from RGBA to dst next */
         src = rgba;
         src_format = rgba_format;
         src_stride = rgba_stride;
      } else {
         /* No RGBA conversion needed, convert directly to dst */
         src = img_src;
         src_format = texFormat;
         src_stride = rowstride;
      }

      /* Do the conversion to destination format */
//      _mesa_format_convert(dest, dst_format, dst_stride,
//                           src, src_format, src_stride,
//                           width, height,
//                           needsRebase ? rebaseSwizzle : NULL);

   do_swap:
      /* Handle byte swapping if required */
      if (ctx->Pack.SwapBytes) {
         GLint swapSize = _mesa_sizeof_packed_type(type);
         if (swapSize == 2 || swapSize == 4) {
            int swapsPerPixel = _mesa_bytes_per_pixel(format, type) / swapSize;
            assert(_mesa_bytes_per_pixel(format, type) % swapSize == 0);
            if (swapSize == 2)
               _mesa_swap2((GLushort *) dest, width * height * swapsPerPixel);
            else if (swapSize == 4)
               _mesa_swap4((GLuint *) dest, width * height * swapsPerPixel);
         }
      }

      /* Unmap the src texture buffer */
      ctx->Driver.UnmapTextureImage(ctx, texImage, img);
   }

done:
   if (rgba)
      free(rgba);
}
Exemplo n.º 20
0
static GLboolean
do_texture_drawpixels(GLcontext * ctx,
                      GLint x, GLint y,
                      GLsizei width, GLsizei height,
                      GLenum format, GLenum type,
                      const struct gl_pixelstore_attrib *unpack,
                      const GLvoid * pixels)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_region *dst = intel_drawbuf_region(intel);
   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
   GLuint rowLength = unpack->RowLength ? unpack->RowLength : width;
   GLuint src_offset;

   if (INTEL_DEBUG & DEBUG_PIXEL)
      fprintf(stderr, "%s\n", __FUNCTION__);

   intelFlush(&intel->ctx);
   intel->vtbl.render_start(intel);
   intel->vtbl.emit_state(intel);

   if (!dst)
      return GL_FALSE;

   if (src) {
      if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
                                     format, type, pixels)) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
         return GL_TRUE;
      }
   }
   else {
      /* PBO only for now:
       */
/*       _mesa_printf("%s - not PBO\n", __FUNCTION__); */
      return GL_FALSE;
   }

   /* There are a couple of things we can't do yet, one of which is
    * set the correct state for pixel operations when GL texturing is
    * enabled.  That's a pretty rare state and probably not worth the
    * effort.  A completely device-independent version of this may do
    * more.
    *
    * Similarly, we make no attempt to merge metaops processing with
    * an enabled fragment program, though it would certainly be
    * possible.
    */
   if (!intel_check_meta_tex_fragment_ops(ctx)) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad GL fragment state for metaops texture\n",
                      __FUNCTION__);
      return GL_FALSE;
   }

   intel->vtbl.install_meta_state(intel);


   /* Is this true?  Also will need to turn depth testing on according
    * to state:
    */
   intel->vtbl.meta_no_stencil_write(intel);
   intel->vtbl.meta_no_depth_write(intel);

   /* Set the 3d engine to draw into the destination region:
    */
   intel->vtbl.meta_draw_region(intel, dst, intel->intelScreen->depth_region);

   intel->vtbl.meta_import_pixel_state(intel);

   src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
                                             format, type, 0, 0, 0);


   /* Setup the pbo up as a rectangular texture, if possible.
    *
    * TODO: This is almost always possible if the i915 fragment
    * program is adjusted to correctly swizzle the sampled colors.
    * The major exception is any 24bit texture, like RGB888, for which
    * there is no hardware support.  
    */
   if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, src_offset,
                                         rowLength, height, format, type)) {
      intel->vtbl.leave_meta_state(intel);
      return GL_FALSE;
   }

   intel->vtbl.meta_texture_blend_replace(intel);


   LOCK_HARDWARE(intel);

   if (intel->driDrawable->numClipRects) {
      __DRIdrawablePrivate *dPriv = intel->driDrawable;
      GLint srcx, srcy;
      GLint dstx, dsty;

      dstx = x;
      dsty = dPriv->h - (y + height);

      srcx = 0;                 /* skiprows/pixels already done */
      srcy = 0;

      if (0) {
         const GLint orig_x = dstx;
         const GLint orig_y = dsty;

         if (!_mesa_clip_to_region(0, 0, dst->pitch, dst->height,
                                   &dstx, &dsty, &width, &height))
            goto out;

         srcx += dstx - orig_x;
         srcy += dsty - orig_y;
      }


      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("draw %d,%d %dx%d\n", dstx, dsty, width, height);

      /* Must use the regular cliprect mechanism in order to get the
       * drawing origin set correctly.  Otherwise scissor state is in
       * incorrect coordinate space.  Does this even need to hold the
       * lock???
       */
      intel_meta_draw_quad(intel,
                           dstx, dstx + width * ctx->Pixel.ZoomX,
                           dPriv->h - (y + height * ctx->Pixel.ZoomY),
                           dPriv->h - (y),
                           -ctx->Current.RasterPos[2] * .5,
                           0x00ff00ff,
                           srcx, srcx + width, srcy + height, srcy);
    out:
      intel->vtbl.leave_meta_state(intel);
      intel_batchbuffer_flush(intel->batch);
   }
   UNLOCK_HARDWARE(intel);
   return GL_TRUE;
}
Exemplo n.º 21
0
static GLboolean
do_blit_readpixels(GLcontext * ctx,
                   GLint x, GLint y, GLsizei width, GLsizei height,
                   GLenum format, GLenum type,
                   const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_region *src = intel_readbuf_region(intel);
   struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
   GLuint dst_offset;
   GLuint rowLength;
   drm_intel_bo *dst_buffer;
   GLboolean all;
   GLint dst_x, dst_y;

   if (INTEL_DEBUG & DEBUG_PIXEL)
      printf("%s\n", __FUNCTION__);

   if (!src)
      return GL_FALSE;

   if (!_mesa_is_bufferobj(pack->BufferObj)) {
      /* PBO only for now:
       */
      if (INTEL_DEBUG & DEBUG_PIXEL)
         printf("%s - not PBO\n", __FUNCTION__);
      return GL_FALSE;
   }


   if (ctx->_ImageTransferState ||
       !intel_check_blit_format(src, format, type)) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         printf("%s - bad format for blit\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         printf("%s: bad packing params\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (pack->RowLength > 0)
      rowLength = pack->RowLength;
   else
      rowLength = width;

   if (pack->Invert) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         printf("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__);
      return GL_FALSE;
   }
   else {
      if (ctx->ReadBuffer->Name == 0)
	 rowLength = -rowLength;
   }

   dst_offset = (GLintptr) _mesa_image_address(2, pack, pixels, width, height,
					       format, type, 0, 0, 0);

   if (!_mesa_clip_copytexsubimage(ctx,
				   &dst_x, &dst_y,
				   &x, &y,
				   &width, &height)) {
      return GL_TRUE;
   }

   intel_prepare_render(intel);

   all = (width * height * src->cpp == dst->Base.Size &&
	  x == 0 && dst_offset == 0);

   dst_x = 0;
   dst_y = 0;

   dst_buffer = intel_bufferobj_buffer(intel, dst,
					       all ? INTEL_WRITE_FULL :
					       INTEL_WRITE_PART);

   if (ctx->ReadBuffer->Name == 0)
      y = ctx->ReadBuffer->Height - (y + height);

   if (!intelEmitCopyBlit(intel,
			  src->cpp,
			  src->pitch, src->buffer, 0, src->tiling,
			  rowLength, dst_buffer, dst_offset, GL_FALSE,
			  x, y,
			  dst_x, dst_y,
			  width, height,
			  GL_COPY)) {
      return GL_FALSE;
   }

   if (INTEL_DEBUG & DEBUG_PIXEL)
      printf("%s - DONE\n", __FUNCTION__);

   return GL_TRUE;
}
Exemplo n.º 22
0
void
_mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image)
{
   GLint baseFormat;
   GLint i, components;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   if (target != GL_CONVOLUTION_2D) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(target)");
      return;
   }

   baseFormat = base_filter_format(internalFormat);
   if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(internalFormat)");
      return;
   }

   if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(width)");
      return;
   }
   if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(height)");
      return;
   }

   if (!_mesa_is_legal_format_and_type(format, type)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter2D(format or type)");
      return;
   }
   if (format == GL_COLOR_INDEX ||
       format == GL_STENCIL_INDEX ||
       format == GL_DEPTH_COMPONENT ||
       format == GL_INTENSITY ||
       type == GL_BITMAP) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(format or type)");
      return;
   }

   components = _mesa_components_in_format(format);
   assert(components > 0);  /* this should have been caught earlier */

   ctx->Convolution2D.Format = format;
   ctx->Convolution2D.InternalFormat = internalFormat;
   ctx->Convolution2D.Width = width;
   ctx->Convolution2D.Height = height;

   /* Unpack filter image.  We always store filters in RGBA format. */
   for (i = 0; i < height; i++) {
      const GLvoid *src = _mesa_image_address(&ctx->Unpack, image, width,
                                              height, format, type, 0, i, 0);
      GLfloat *dst = ctx->Convolution2D.Filter + i * width * 4;
      _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
                                    format, type, src, &ctx->Unpack,
                                    0, GL_FALSE);
   }

   /* apply scale and bias */
   {
      const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[1];
      const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[1];
      for (i = 0; i < width * height; i++) {
         GLfloat r = ctx->Convolution2D.Filter[i * 4 + 0];
         GLfloat g = ctx->Convolution2D.Filter[i * 4 + 1];
         GLfloat b = ctx->Convolution2D.Filter[i * 4 + 2];
         GLfloat a = ctx->Convolution2D.Filter[i * 4 + 3];
         r = r * scale[0] + bias[0];
         g = g * scale[1] + bias[1];
         b = b * scale[2] + bias[2];
         a = a * scale[3] + bias[3];
         ctx->Convolution2D.Filter[i * 4 + 0] = r;
         ctx->Convolution2D.Filter[i * 4 + 1] = g;
         ctx->Convolution2D.Filter[i * 4 + 2] = b;
         ctx->Convolution2D.Filter[i * 4 + 3] = a;
      }
   }

   ctx->NewState |= _NEW_PIXEL;
}
Exemplo n.º 23
0
Arquivo: s_bitmap.c Projeto: aosm/X11
/*
 * Render a bitmap.
 */
void
_swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
		GLsizei width, GLsizei height,
		const struct gl_pixelstore_attrib *unpack,
		const GLubyte *bitmap )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   GLint row, col;
   GLuint count = 0;
   struct sw_span span;

   ASSERT(ctx->RenderMode == GL_RENDER);
   ASSERT(bitmap);

   RENDER_START(swrast,ctx);

   if (SWRAST_CONTEXT(ctx)->NewState)
      _swrast_validate_derived( ctx );

   INIT_SPAN(span, GL_BITMAP, width, 0, SPAN_XY);

   if (ctx->Visual.rgbMode) {
      span.interpMask |= SPAN_RGBA;
      span.red   = FloatToFixed(ctx->Current.RasterColor[0] * CHAN_MAXF);
      span.green = FloatToFixed(ctx->Current.RasterColor[1] * CHAN_MAXF);
      span.blue  = FloatToFixed(ctx->Current.RasterColor[2] * CHAN_MAXF);
      span.alpha = FloatToFixed(ctx->Current.RasterColor[3] * CHAN_MAXF);
      span.redStep = span.greenStep = span.blueStep = span.alphaStep = 0;
   }
   else {
      span.interpMask |= SPAN_INDEX;
      span.index = ChanToFixed(ctx->Current.RasterIndex);
      span.indexStep = 0;
   }

   if (ctx->Depth.Test)
      _mesa_span_default_z(ctx, &span);
   if (ctx->Fog.Enabled)
      _mesa_span_default_fog(ctx, &span);
   if (ctx->Texture._EnabledUnits)
      _mesa_span_default_texcoords(ctx, &span);

   for (row = 0; row < height; row++, span.y++) {
      const GLubyte *src = (const GLubyte *) _mesa_image_address( unpack,
                 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );

      if (unpack->LsbFirst) {
         /* Lsb first */
         GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
         for (col = 0; col < width; col++) {
            if (*src & mask) {
               span.array->x[count] = px + col;
               span.array->y[count] = py + row;
               count++;
            }
            if (mask == 128U) {
               src++;
               mask = 1U;
            }
            else {
               mask = mask << 1;
            }
         }

         /* get ready for next row */
         if (mask != 1)
            src++;
      }
      else {
         /* Msb first */
         GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
         for (col = 0; col < width; col++) {
            if (*src & mask) {
               span.array->x[count] = px + col;
               span.array->y[count] = py + row;
               count++;
            }
            if (mask == 1U) {
               src++;
               mask = 128U;
            }
            else {
               mask = mask >> 1;
            }
         }

         /* get ready for next row */
         if (mask != 128)
            src++;
      }

      if (count + width >= MAX_WIDTH || row + 1 == height) {
         /* flush the span */
         span.end = count;
         if (ctx->Visual.rgbMode)
            _mesa_write_rgba_span(ctx, &span);
         else
            _mesa_write_index_span(ctx, &span);
         span.end = 0;
         count = 0;
      }
   }

   RENDER_FINISH(swrast,ctx);
}
Exemplo n.º 24
0
/**
 * 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;
}