Beispiel #1
0
/**
 * glGetTexImage for YCbCr pixels.
 */
static void
get_tex_ycbcr(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 GLint rowstride = texImage->RowStride;
   const GLushort *src = (const GLushort *) texImage->Data;
   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);
         _mesa_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);
         }

         src += rowstride;
      }
   }
}
/**
 * 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;
      }
   }
}
Beispiel #3
0
/**
 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV.
 */
static GLboolean
_mesa_texstore_ycbcr(TEXSTORE_PARAMS)
{
   const GLboolean littleEndian = _mesa_little_endian();

   (void) ctx; (void) dims; (void) baseInternalFormat;

   assert((dstFormat == MESA_FORMAT_YCBCR) ||
          (dstFormat == MESA_FORMAT_YCBCR_REV));
   assert(_mesa_get_format_bytes(dstFormat) == 2);
   assert(ctx->Extensions.MESA_ycbcr_texture);
   assert(srcFormat == GL_YCBCR_MESA);
   assert((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
          (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
   assert(baseInternalFormat == GL_YCBCR_MESA);

   /* always just memcpy since no pixel transfer ops apply */
   memcpy_texture(ctx, dims,
                  dstFormat,
                  dstRowStride, dstSlices,
                  srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                  srcAddr, srcPacking);

   /* Check if we need byte swapping */
   /* XXX the logic here _might_ be wrong */
   if (srcPacking->SwapBytes ^
       (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
       (dstFormat == MESA_FORMAT_YCBCR_REV) ^
       !littleEndian) {
      GLint img, row;
      for (img = 0; img < srcDepth; img++) {
         GLubyte *dstRow = dstSlices[img];
         for (row = 0; row < srcHeight; row++) {
            _mesa_swap2((GLushort *) dstRow, srcWidth);
            dstRow += dstRowStride;
         }
      }
   }
   return GL_TRUE;
}
Beispiel #4
0
/*
 * Read R, G, B, A, RGB, L, or LA pixels.
 */
static void
read_rgba_pixels( struct gl_context *ctx,
                  GLint x, GLint y,
                  GLsizei width, GLsizei height,
                  GLenum format, GLenum type, GLvoid *pixels,
                  const struct gl_pixelstore_attrib *packing )
{
   GLbitfield transferOps;
   bool dst_is_integer, dst_is_luminance, needs_rebase;
   int dst_stride, src_stride, rb_stride;
   uint32_t dst_format, src_format;
   GLubyte *dst, *map;
   mesa_format rb_format;
   bool needs_rgba;
   void *rgba, *src;
   bool src_is_uint = false;
   uint8_t rebase_swizzle[4];
   struct gl_framebuffer *fb = ctx->ReadBuffer;
   struct gl_renderbuffer *rb = fb->_ColorReadBuffer;

   if (!rb)
      return;

   transferOps = get_readpixels_transfer_ops(ctx, rb->Format, format, type,
                                             GL_FALSE);
   /* Describe the dst format */
   dst_is_integer = _mesa_is_enum_format_integer(format);
   dst_stride = _mesa_image_row_stride(packing, width, format, type);
   dst_format = _mesa_format_from_format_and_type(format, type);
   dst_is_luminance = format == GL_LUMINANCE ||
                      format == GL_LUMINANCE_ALPHA ||
                      format == GL_LUMINANCE_INTEGER_EXT ||
                      format == GL_LUMINANCE_ALPHA_INTEGER_EXT;
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
                                           format, type, 0, 0);

   /* Map the source render buffer */
   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
                               &map, &rb_stride);
   if (!map) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
      return;
   }
   rb_format = _mesa_get_srgb_format_linear(rb->Format);

   /*
    * Depending on the base formats involved in the conversion we might need to
    * rebase some values, so for these formats we compute a rebase swizzle.
    */
   if (rb->_BaseFormat == GL_LUMINANCE || rb->_BaseFormat == GL_INTENSITY) {
      needs_rebase = true;
      rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
   } else if (rb->_BaseFormat == GL_LUMINANCE_ALPHA) {
      needs_rebase = true;
      rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_W;
   } else if (_mesa_get_format_base_format(rb_format) != rb->_BaseFormat) {
      needs_rebase =
         _mesa_compute_rgba2base2rgba_component_mapping(rb->_BaseFormat,
                                                        rebase_swizzle);
   } else {
      needs_rebase = false;
   }

   /* 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 transferOps do not apply.
    *
    * Converting to luminance also requires converting to RGBA first, so we can
    * then compute luminance values as L=R+G+B. Notice that this is different
    * from GetTexImage, where we compute L=R.
    */
   assert(!transferOps || (transferOps && !dst_is_integer));

   needs_rgba = transferOps || dst_is_luminance;
   rgba = NULL;
   if (needs_rgba) {
      uint32_t rgba_format;
      int rgba_stride;
      bool need_convert;

      /* Convert to RGBA float or int/uint depending on the type of the src */
      if (dst_is_integer) {
         src_is_uint = _mesa_is_format_unsigned(rb_format);
         if (src_is_uint) {
            rgba_format = RGBA32_UINT;
            rgba_stride = width * 4 * sizeof(GLuint);
         } else {
            rgba_format = RGBA32_INT;
            rgba_stride = width * 4 * sizeof(GLint);
         }
      } else {
         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 (dst_format == rgba_format) {
         need_convert = false;
         rgba = dst;
      } else {
         need_convert = true;
         rgba = malloc(height * rgba_stride);
         if (!rgba) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
            goto done_unmap;
         }
      }

      /* Convert to RGBA now */
      _mesa_format_convert(rgba, rgba_format, rgba_stride,
                           map, rb_format, rb_stride,
                           width, height,
                           needs_rebase ? rebase_swizzle : NULL);

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

      /* If we had to rebase, we have already taken care of that */
      needs_rebase = false;

      /* If we were lucky and our RGBA conversion matches the dst format, then
       * we are done.
       */
      if (!need_convert)
         goto done_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 = map;
      src_format = rb_format;
      src_stride = rb_stride;
   }

   /* Do the conversion.
    *
    * If the dst format is Luminance, we need to do the conversion by computing
    * L=R+G+B values.
    */
   if (!dst_is_luminance) {
      _mesa_format_convert(dst, dst_format, dst_stride,
                           src, src_format, src_stride,
                           width, height,
                           needs_rebase ? rebase_swizzle : NULL);
   } else if (!dst_is_integer) {
      /* Compute float Luminance values from RGBA float */
      int luminance_stride, luminance_bytes;
      void *luminance;
      uint32_t luminance_format;

      luminance_stride = width * sizeof(GL_FLOAT);
      if (format == GL_LUMINANCE_ALPHA)
         luminance_stride *= 2;
      luminance_bytes = height * luminance_stride;
      luminance = malloc(luminance_bytes);
      if (!luminance) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
         free(rgba);
         goto done_unmap;
      }
      _mesa_pack_luminance_from_rgba_float(width * height, src,
                                           luminance, format, transferOps);

      /* Convert from Luminance float to dst (this will hadle type conversion
       * from float to the type of dst if necessary)
       */
      luminance_format = _mesa_format_from_format_and_type(format, GL_FLOAT);
      _mesa_format_convert(dst, dst_format, dst_stride,
                           luminance, luminance_format, luminance_stride,
                           width, height, NULL);
   } else {
      _mesa_pack_luminance_from_rgba_integer(width * height, src, !src_is_uint,
                                             dst, format, type);
   }

   if (rgba)
      free(rgba);

done_swap:
   /* Handle byte swapping if required */
   if (packing->SwapBytes) {
      int components = _mesa_components_in_format(format);
      GLint swapSize = _mesa_sizeof_packed_type(type);
      if (swapSize == 2)
         _mesa_swap2((GLushort *) dst, width * height * components);
      else if (swapSize == 4)
         _mesa_swap4((GLuint *) dst, width * height * components);
   }

done_unmap:
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
Beispiel #5
0
/*
 * XXX the packed pixel formats haven't been tested.
 */
static void
pack_histogram( GLcontext *ctx,
                GLuint n, CONST GLuint rgba[][4],
                GLenum format, GLenum type, GLvoid *destination,
                const struct gl_pixelstore_attrib *packing )
{
   const GLint comps = _mesa_components_in_format(format);
   GLuint luminance[MAX_WIDTH];

   if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) {
      GLuint i;
      for (i = 0; i < n; i++) {
         luminance[i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
      }
   }

#define PACK_MACRO(TYPE)					\
   {								\
      GLuint i;							\
      switch (format) {						\
         case GL_RED:						\
            for (i=0;i<n;i++)					\
               dst[i] = (TYPE) rgba[i][RCOMP];			\
            break;						\
         case GL_GREEN:						\
            for (i=0;i<n;i++)					\
               dst[i] = (TYPE) rgba[i][GCOMP];			\
            break;						\
         case GL_BLUE:						\
            for (i=0;i<n;i++)					\
               dst[i] = (TYPE) rgba[i][BCOMP];			\
            break;						\
         case GL_ALPHA:						\
            for (i=0;i<n;i++)					\
               dst[i] = (TYPE) rgba[i][ACOMP];			\
            break;						\
         case GL_LUMINANCE:					\
            for (i=0;i<n;i++)					\
               dst[i] = (TYPE) luminance[i];			\
            break;						\
         case GL_LUMINANCE_ALPHA:				\
            for (i=0;i<n;i++) {					\
               dst[i*2+0] = (TYPE) luminance[i];		\
               dst[i*2+1] = (TYPE) rgba[i][ACOMP];		\
            }							\
            break;						\
         case GL_RGB:						\
            for (i=0;i<n;i++) {					\
               dst[i*3+0] = (TYPE) rgba[i][RCOMP];		\
               dst[i*3+1] = (TYPE) rgba[i][GCOMP];		\
               dst[i*3+2] = (TYPE) rgba[i][BCOMP];		\
            }							\
            break;						\
         case GL_RGBA:						\
            for (i=0;i<n;i++) {					\
               dst[i*4+0] = (TYPE) rgba[i][RCOMP];		\
               dst[i*4+1] = (TYPE) rgba[i][GCOMP];		\
               dst[i*4+2] = (TYPE) rgba[i][BCOMP];		\
               dst[i*4+3] = (TYPE) rgba[i][ACOMP];		\
            }							\
            break;						\
         case GL_BGR:						\
            for (i=0;i<n;i++) {					\
               dst[i*3+0] = (TYPE) rgba[i][BCOMP];		\
               dst[i*3+1] = (TYPE) rgba[i][GCOMP];		\
               dst[i*3+2] = (TYPE) rgba[i][RCOMP];		\
            }							\
            break;						\
         case GL_BGRA:						\
            for (i=0;i<n;i++) {					\
               dst[i*4+0] = (TYPE) rgba[i][BCOMP];		\
               dst[i*4+1] = (TYPE) rgba[i][GCOMP];		\
               dst[i*4+2] = (TYPE) rgba[i][RCOMP];		\
               dst[i*4+3] = (TYPE) rgba[i][ACOMP];		\
            }							\
            break;						\
         case GL_ABGR_EXT:					\
            for (i=0;i<n;i++) {					\
               dst[i*4+0] = (TYPE) rgba[i][ACOMP];		\
               dst[i*4+1] = (TYPE) rgba[i][BCOMP];		\
               dst[i*4+2] = (TYPE) rgba[i][GCOMP];		\
               dst[i*4+3] = (TYPE) rgba[i][RCOMP];		\
            }							\
            break;						\
         default:						\
            _mesa_problem(ctx, "bad format in pack_histogram");	\
      }								\
   }

   switch (type) {
      case GL_UNSIGNED_BYTE:
         {
            GLubyte *dst = (GLubyte *) destination;
            PACK_MACRO(GLubyte);
         }
         break;
      case GL_BYTE:
         {
            GLbyte *dst = (GLbyte *) destination;
            PACK_MACRO(GLbyte);
         }
         break;
      case GL_UNSIGNED_SHORT:
         {
            GLushort *dst = (GLushort *) destination;
            PACK_MACRO(GLushort);
            if (packing->SwapBytes) {
               _mesa_swap2(dst, n * comps);
            }
         }
         break;
      case GL_SHORT:
         {
            GLshort *dst = (GLshort *) destination;
            PACK_MACRO(GLshort);
            if (packing->SwapBytes) {
               _mesa_swap2((GLushort *) dst, n * comps);
            }
         }
         break;
      case GL_UNSIGNED_INT:
         {
            GLuint *dst = (GLuint *) destination;
            PACK_MACRO(GLuint);
            if (packing->SwapBytes) {
               _mesa_swap4(dst, n * comps);
            }
         }
         break;
      case GL_INT:
         {
            GLint *dst = (GLint *) destination;
            PACK_MACRO(GLint);
            if (packing->SwapBytes) {
               _mesa_swap4((GLuint *) dst, n * comps);
            }
         }
         break;
      case GL_FLOAT:
         {
            GLfloat *dst = (GLfloat *) destination;
            PACK_MACRO(GLfloat);
            if (packing->SwapBytes) {
               _mesa_swap4((GLuint *) dst, n * comps);
            }
         }
         break;
      case GL_HALF_FLOAT_ARB:
         {
            /* temporarily store as GLuints */
            GLuint temp[4*HISTOGRAM_TABLE_SIZE];
            GLuint *dst = temp;
            GLhalfARB *half = (GLhalfARB *) destination;
            GLuint i;
            /* get GLuint values */
            PACK_MACRO(GLuint);
            /* convert to GLhalf */
            for (i = 0; i < n * comps; i++) {
               half[i] = _mesa_float_to_half((GLfloat) temp[i]);
            }
            if (packing->SwapBytes) {
               _mesa_swap2((GLushort *) half, n * comps);
            }
         }
         break;
      case GL_UNSIGNED_BYTE_3_3_2:
         if (format == GL_RGB) {
            GLubyte *dst = (GLubyte *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0x7) << 5)
                      | ((rgba[i][GCOMP] & 0x7) << 2)
                      | ((rgba[i][BCOMP] & 0x3)     );
            }
         }
         else {
            GLubyte *dst = (GLubyte *) destination;
            GLuint i;
            ASSERT(format == GL_BGR);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][BCOMP] & 0x7) << 5)
                      | ((rgba[i][GCOMP] & 0x7) << 2)
                      | ((rgba[i][RCOMP] & 0x3)     );
            }
         }
         break;
      case GL_UNSIGNED_BYTE_2_3_3_REV:
         if (format == GL_RGB) {
            GLubyte *dst = (GLubyte *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0x3) << 6)
                      | ((rgba[i][GCOMP] & 0x7) << 3)
                      | ((rgba[i][BCOMP] & 0x7)     );
            }
         }
         else {
            GLubyte *dst = (GLubyte *) destination;
            GLuint i;
            ASSERT(format == GL_BGR);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][BCOMP] & 0x3) << 6)
                      | ((rgba[i][GCOMP] & 0x7) << 3)
                      | ((rgba[i][RCOMP] & 0x7)     );
            }
         }
         break;
      case GL_UNSIGNED_SHORT_5_6_5:
         if (format == GL_RGB) {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
                      | ((rgba[i][GCOMP] & 0x3f) <<  5)
                      | ((rgba[i][BCOMP] & 0x1f)      );
            }
         }
         else {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            ASSERT(format == GL_BGR);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11)
                      | ((rgba[i][GCOMP] & 0x3f) <<  5)
                      | ((rgba[i][RCOMP] & 0x1f)      );
            }
         }
         break;
      case GL_UNSIGNED_SHORT_5_6_5_REV:
         if (format == GL_RGB) {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11)
                      | ((rgba[i][GCOMP] & 0x3f) <<  5)
                      | ((rgba[i][RCOMP] & 0x1f)      );
            }
         }
         else {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            ASSERT(format == GL_BGR);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
                      | ((rgba[i][GCOMP] & 0x3f) <<  5)
                      | ((rgba[i][BCOMP] & 0x1f)      );
            }
         }
         break;
      case GL_UNSIGNED_SHORT_4_4_4_4:
         if (format == GL_RGBA) {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0xf) << 12)
                      | ((rgba[i][GCOMP] & 0xf) <<  8)
                      | ((rgba[i][BCOMP] & 0xf) <<  4)
                      | ((rgba[i][ACOMP] & 0xf)      );
            }
         }
         else if (format == GL_BGRA) {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][BCOMP] & 0xf) << 12)
                      | ((rgba[i][GCOMP] & 0xf) <<  8)
                      | ((rgba[i][RCOMP] & 0xf) <<  4)
                      | ((rgba[i][ACOMP] & 0xf)      );
            }
         }
         else {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            ASSERT(format == GL_ABGR_EXT);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0xf) << 12)
                      | ((rgba[i][BCOMP] & 0xf) <<  8)
                      | ((rgba[i][GCOMP] & 0xf) <<  4)
                      | ((rgba[i][RCOMP] & 0xf)      );
            }
         }
         break;
      case GL_UNSIGNED_SHORT_4_4_4_4_REV:
         if (format == GL_RGBA) {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0xf) << 12)
                      | ((rgba[i][BCOMP] & 0xf) <<  8)
                      | ((rgba[i][GCOMP] & 0xf) <<  4)
                      | ((rgba[i][RCOMP] & 0xf)      );
            }
         }
         else if (format == GL_BGRA) {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0xf) << 12)
                      | ((rgba[i][RCOMP] & 0xf) <<  8)
                      | ((rgba[i][GCOMP] & 0xf) <<  4)
                      | ((rgba[i][BCOMP] & 0xf)      );
            }
         }
         else {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            ASSERT(format == GL_ABGR_EXT);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0xf) << 12)
                      | ((rgba[i][GCOMP] & 0xf) <<  8)
                      | ((rgba[i][BCOMP] & 0xf) <<  4)
                      | ((rgba[i][ACOMP] & 0xf)      );
            }
         }
         break;
      case GL_UNSIGNED_SHORT_5_5_5_1:
         if (format == GL_RGBA) {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
                      | ((rgba[i][GCOMP] & 0x1f) <<  6)
                      | ((rgba[i][BCOMP] & 0x1f) <<  1)
                      | ((rgba[i][ACOMP] & 0x1)       );
            }
         }
         else if (format == GL_BGRA) {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11)
                      | ((rgba[i][GCOMP] & 0x1f) <<  6)
                      | ((rgba[i][RCOMP] & 0x1f) <<  1)
                      | ((rgba[i][ACOMP] & 0x1)       );
            }
         }
         else {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            ASSERT(format == GL_ABGR_EXT);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11)
                      | ((rgba[i][BCOMP] & 0x1f) <<  6)
                      | ((rgba[i][GCOMP] & 0x1f) <<  1)
                      | ((rgba[i][RCOMP] & 0x1)       );
            }
         }
         break;
      case GL_UNSIGNED_SHORT_1_5_5_5_REV:
         if (format == GL_RGBA) {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11)
                      | ((rgba[i][BCOMP] & 0x1f) <<  6)
                      | ((rgba[i][GCOMP] & 0x1f) <<  1)
                      | ((rgba[i][RCOMP] & 0x1)       );
            }
         }
         else if (format == GL_BGRA) {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11)
                      | ((rgba[i][RCOMP] & 0x1f) <<  6)
                      | ((rgba[i][GCOMP] & 0x1f) <<  1)
                      | ((rgba[i][BCOMP] & 0x1)       );
            }
         }
         else {
            GLushort *dst = (GLushort *) destination;
            GLuint i;
            ASSERT(format == GL_ABGR_EXT);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
                      | ((rgba[i][GCOMP] & 0x1f) <<  6)
                      | ((rgba[i][BCOMP] & 0x1f) <<  1)
                      | ((rgba[i][ACOMP] & 0x1)       );
            }
         }
         break;
      case GL_UNSIGNED_INT_8_8_8_8:
         if (format == GL_RGBA) {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0xff) << 24)
                      | ((rgba[i][GCOMP] & 0xff) << 16)
                      | ((rgba[i][BCOMP] & 0xff) <<  8)
                      | ((rgba[i][ACOMP] & 0xff)      );
            }
         }
         else if (format == GL_BGRA) {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][BCOMP] & 0xff) << 24)
                      | ((rgba[i][GCOMP] & 0xff) << 16)
                      | ((rgba[i][RCOMP] & 0xff) <<  8)
                      | ((rgba[i][ACOMP] & 0xff)      );
            }
         }
         else {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            ASSERT(format == GL_ABGR_EXT);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0xff) << 24)
                      | ((rgba[i][BCOMP] & 0xff) << 16)
                      | ((rgba[i][GCOMP] & 0xff) <<  8)
                      | ((rgba[i][RCOMP] & 0xff)      );
            }
         }
         break;
      case GL_UNSIGNED_INT_8_8_8_8_REV:
         if (format == GL_RGBA) {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0xff) << 24)
                      | ((rgba[i][BCOMP] & 0xff) << 16)
                      | ((rgba[i][GCOMP] & 0xff) <<  8)
                      | ((rgba[i][RCOMP] & 0xff)      );
            }
         }
         else if (format == GL_BGRA) {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0xff) << 24)
                      | ((rgba[i][RCOMP] & 0xff) << 16)
                      | ((rgba[i][GCOMP] & 0xff) <<  8)
                      | ((rgba[i][BCOMP] & 0xff)      );
            }
         }
         else {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            ASSERT(format == GL_ABGR_EXT);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0xff) << 24)
                      | ((rgba[i][GCOMP] & 0xff) << 16)
                      | ((rgba[i][BCOMP] & 0xff) <<  8)
                      | ((rgba[i][ACOMP] & 0xff)      );
            }
         }
         break;
      case GL_UNSIGNED_INT_10_10_10_2:
         if (format == GL_RGBA) {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0x3ff) << 22)
                      | ((rgba[i][GCOMP] & 0x3ff) << 12)
                      | ((rgba[i][BCOMP] & 0x3ff) <<  2)
                      | ((rgba[i][ACOMP] & 0x3)        );
            }
         }
         else if (format == GL_BGRA) {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][BCOMP] & 0x3ff) << 22)
                      | ((rgba[i][GCOMP] & 0x3ff) << 12)
                      | ((rgba[i][RCOMP] & 0x3ff) <<  2)
                      | ((rgba[i][ACOMP] & 0x3)        );
            }
         }
         else {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            ASSERT(format == GL_ABGR_EXT);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22)
                      | ((rgba[i][BCOMP] & 0x3ff) << 12)
                      | ((rgba[i][GCOMP] & 0x3ff) <<  2)
                      | ((rgba[i][RCOMP] & 0x3)        );
            }
         }
         break;
      case GL_UNSIGNED_INT_2_10_10_10_REV:
         if (format == GL_RGBA) {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22)
                      | ((rgba[i][BCOMP] & 0x3ff) << 12)
                      | ((rgba[i][GCOMP] & 0x3ff) <<  2)
                      | ((rgba[i][RCOMP] & 0x3)        );
            }
         }
         else if (format == GL_BGRA) {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22)
                      | ((rgba[i][RCOMP] & 0x3ff) << 12)
                      | ((rgba[i][GCOMP] & 0x3ff) <<  2)
                      | ((rgba[i][BCOMP] & 0x3)        );
            }
         }
         else {
            GLuint *dst = (GLuint *) destination;
            GLuint i;
            ASSERT(format == GL_ABGR_EXT);
            for (i = 0; i < n; i++) {
               dst[i] = ((rgba[i][RCOMP] & 0x3ff) << 22)
                      | ((rgba[i][GCOMP] & 0x3ff) << 12)
                      | ((rgba[i][BCOMP] & 0x3ff) <<  2)
                      | ((rgba[i][ACOMP] & 0x3)        );
            }
         }
         break;
      default:
         _mesa_problem(ctx, "Bad type in pack_histogram");
   }

#undef PACK_MACRO
}
Beispiel #6
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);
   }
}
Beispiel #7
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);
}