/** * 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; } } }
/** * 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; }
/* * 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); }
/* * 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 }
/** * 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); } }
/** * 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); }