/** * Store user's image in rgba_dxt1 format. */ GLboolean _mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS) { const GLubyte *pixels; GLubyte *dst; const GLubyte *tempImage = NULL; assert(dstFormat == MESA_FORMAT_RGBA_DXT1 || dstFormat == MESA_FORMAT_SRGBA_DXT1); if (srcFormat != GL_RGBA || srcType != GL_UNSIGNED_BYTE || ctx->_ImageTransferState || ALIGN(srcPacking->RowLength, srcPacking->Alignment) != srcWidth || srcPacking->SwapBytes) { /* convert image to RGBA/GLubyte */ GLubyte *tempImageSlices[1]; int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte); tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte)); if (!tempImage) return GL_FALSE; /* out of memory */ tempImageSlices[0] = (GLubyte *) tempImage; _mesa_texstore(ctx, dims, baseInternalFormat, _mesa_little_endian() ? MESA_FORMAT_R8G8B8A8_UNORM : MESA_FORMAT_A8B8G8R8_UNORM, rgbaRowStride, tempImageSlices, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); pixels = tempImage; srcFormat = GL_RGBA; } else { pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0); } dst = dstSlices[0]; if (ext_tx_compress_dxtn) { (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, dst, dstRowStride); } else { _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt1"); } free((void*) tempImage); return GL_TRUE; }
static void radeonInitTextureFormats(void) { if (_mesa_little_endian()) { _radeon_texformat_rgba8888 = MESA_FORMAT_RGBA8888; _radeon_texformat_argb8888 = MESA_FORMAT_ARGB8888; _radeon_texformat_rgb565 = MESA_FORMAT_RGB565; _radeon_texformat_argb4444 = MESA_FORMAT_ARGB4444; _radeon_texformat_argb1555 = MESA_FORMAT_ARGB1555; _radeon_texformat_al88 = MESA_FORMAT_AL88; } else { _radeon_texformat_rgba8888 = MESA_FORMAT_RGBA8888_REV; _radeon_texformat_argb8888 = MESA_FORMAT_ARGB8888_REV; _radeon_texformat_rgb565 = MESA_FORMAT_RGB565_REV; _radeon_texformat_argb4444 = MESA_FORMAT_ARGB4444_REV; _radeon_texformat_argb1555 = MESA_FORMAT_ARGB1555_REV; _radeon_texformat_al88 = MESA_FORMAT_AL88_REV; } }
/** * 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; }
/** * Allocate renderbuffer storage. We don't actually allocate any storage * since we're using a user-provided buffer. * Just set up all the gl_renderbuffer methods. */ static GLboolean osmesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); /* Note: we can ignoring internalFormat for "window-system" renderbuffers */ (void) internalFormat; /* Given the user-provided format and type, figure out which MESA_FORMAT_x * to use. * XXX There aren't Mesa formats for all the possible combinations here! * XXX Specifically, there's only RGBA-order 16-bit/channel and float * XXX formats. * XXX The 8-bit/channel formats should all be OK. */ if (osmesa->format == OSMESA_RGBA) { if (osmesa->DataType == GL_UNSIGNED_BYTE) { if (_mesa_little_endian()) rb->Format = MESA_FORMAT_RGBA8888_REV; else rb->Format = MESA_FORMAT_RGBA8888; } else if (osmesa->DataType == GL_UNSIGNED_SHORT) { rb->Format = MESA_FORMAT_RGBA_16; } else { rb->Format = MESA_FORMAT_RGBA_FLOAT32; } } else if (osmesa->format == OSMESA_BGRA) { if (osmesa->DataType == GL_UNSIGNED_BYTE) { if (_mesa_little_endian()) rb->Format = MESA_FORMAT_ARGB8888; else rb->Format = MESA_FORMAT_ARGB8888_REV; } else if (osmesa->DataType == GL_UNSIGNED_SHORT) { _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLushort"); rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */ } else { _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLfloat"); rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */ } } else if (osmesa->format == OSMESA_ARGB) { if (osmesa->DataType == GL_UNSIGNED_BYTE) { if (_mesa_little_endian()) rb->Format = MESA_FORMAT_ARGB8888_REV; else rb->Format = MESA_FORMAT_ARGB8888; } else if (osmesa->DataType == GL_UNSIGNED_SHORT) { _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLushort"); rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */ } else { _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLfloat"); rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */ } } else if (osmesa->format == OSMESA_RGB) { if (osmesa->DataType == GL_UNSIGNED_BYTE) { rb->Format = MESA_FORMAT_RGB888; } else if (osmesa->DataType == GL_UNSIGNED_SHORT) { _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLushort"); rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */ } else { _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLfloat"); rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */ } } else if (osmesa->format == OSMESA_BGR) { if (osmesa->DataType == GL_UNSIGNED_BYTE) { rb->Format = MESA_FORMAT_BGR888; } else if (osmesa->DataType == GL_UNSIGNED_SHORT) { _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLushort"); rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */ } else { _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLfloat"); rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */ } } else if (osmesa->format == OSMESA_RGB_565) { ASSERT(osmesa->DataType == GL_UNSIGNED_BYTE); rb->Format = MESA_FORMAT_RGB565; } else { _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage"); } rb->Width = width; rb->Height = height; compute_row_addresses( osmesa ); return GL_TRUE; }
/** * This is a software fallback for the gl_renderbuffer->AllocStorage * function. * Device drivers will typically override this function for the buffers * which it manages (typically color buffers, Z and stencil). * Other buffers (like software accumulation and aux buffers) which the driver * doesn't manage can be handled with this function. * * This one multi-purpose function can allocate stencil, depth, accum, color * or color-index buffers! */ static GLboolean soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); GLuint bpp; switch (internalFormat) { case GL_RGB: case GL_R3_G3_B2: case GL_RGB4: case GL_RGB5: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: rb->Format = MESA_FORMAT_BGR_UNORM8; break; case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1: case GL_RGBA8: #if 1 case GL_RGB10_A2: case GL_RGBA12: #endif if (_mesa_little_endian()) rb->Format = MESA_FORMAT_R8G8B8A8_UNORM; else rb->Format = MESA_FORMAT_A8B8G8R8_UNORM; break; case GL_RGBA16: case GL_RGBA16_SNORM: /* for accum buffer */ rb->Format = MESA_FORMAT_RGBA_SNORM16; break; case GL_STENCIL_INDEX: case GL_STENCIL_INDEX1_EXT: case GL_STENCIL_INDEX4_EXT: case GL_STENCIL_INDEX8_EXT: case GL_STENCIL_INDEX16_EXT: rb->Format = MESA_FORMAT_S_UINT8; break; case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT16: rb->Format = MESA_FORMAT_Z_UNORM16; break; case GL_DEPTH_COMPONENT24: rb->Format = MESA_FORMAT_Z24_UNORM_X8_UINT; break; case GL_DEPTH_COMPONENT32: rb->Format = MESA_FORMAT_Z_UNORM32; break; case GL_DEPTH_STENCIL_EXT: case GL_DEPTH24_STENCIL8_EXT: rb->Format = MESA_FORMAT_S8_UINT_Z24_UNORM; break; default: /* unsupported format */ return GL_FALSE; } bpp = _mesa_get_format_bytes(rb->Format); /* free old buffer storage */ free(srb->Buffer); srb->Buffer = NULL; srb->RowStride = width * bpp; if (width > 0 && height > 0) { /* allocate new buffer storage */ srb->Buffer = malloc(srb->RowStride * height); if (srb->Buffer == NULL) { rb->Width = 0; rb->Height = 0; _mesa_error(ctx, GL_OUT_OF_MEMORY, "software renderbuffer allocation (%d x %d x %d)", width, height, bpp); return GL_FALSE; } } rb->Width = width; rb->Height = height; rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); if (rb->Name == 0 && internalFormat == GL_RGBA16_SNORM && rb->_BaseFormat == 0) { /* NOTE: This is a special case just for accumulation buffers. * This is a very limited use case- there's no snorm texturing or * rendering going on. */ rb->_BaseFormat = GL_RGBA; } else { /* the internalFormat should have been error checked long ago */ assert(rb->_BaseFormat); } return GL_TRUE; }
/** * Create the Mesa framebuffer and renderbuffers for a given window/drawable. * * \todo This function (and its interface) will need to be updated to support * pbuffers. */ static GLboolean radeonCreateBuffer( __DRIscreen *driScrnPriv, __DRIdrawable *driDrawPriv, const struct gl_config *mesaVis, GLboolean isPixmap ) { radeonScreenPtr screen = (radeonScreenPtr) driScrnPriv->driverPrivate; const GLboolean swDepth = GL_FALSE; const GLboolean swAlpha = GL_FALSE; const GLboolean swAccum = mesaVis->accumRedBits > 0; const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24; mesa_format rgbFormat; struct radeon_framebuffer *rfb; if (isPixmap) return GL_FALSE; /* not implemented */ rfb = CALLOC_STRUCT(radeon_framebuffer); if (!rfb) return GL_FALSE; _mesa_initialize_window_framebuffer(&rfb->base, mesaVis); if (mesaVis->redBits == 5) rgbFormat = _mesa_little_endian() ? MESA_FORMAT_B5G6R5_UNORM : MESA_FORMAT_R5G6B5_UNORM; else if (mesaVis->alphaBits == 0) rgbFormat = _mesa_little_endian() ? MESA_FORMAT_B8G8R8X8_UNORM : MESA_FORMAT_X8R8G8B8_UNORM; else rgbFormat = _mesa_little_endian() ? MESA_FORMAT_B8G8R8A8_UNORM : MESA_FORMAT_A8R8G8B8_UNORM; /* front color renderbuffer */ rfb->color_rb[0] = radeon_create_renderbuffer(rgbFormat, driDrawPriv); _mesa_add_renderbuffer(&rfb->base, BUFFER_FRONT_LEFT, &rfb->color_rb[0]->base.Base); rfb->color_rb[0]->has_surface = 1; /* back color renderbuffer */ if (mesaVis->doubleBufferMode) { rfb->color_rb[1] = radeon_create_renderbuffer(rgbFormat, driDrawPriv); _mesa_add_renderbuffer(&rfb->base, BUFFER_BACK_LEFT, &rfb->color_rb[1]->base.Base); rfb->color_rb[1]->has_surface = 1; } if (mesaVis->depthBits == 24) { if (mesaVis->stencilBits == 8) { struct radeon_renderbuffer *depthStencilRb = radeon_create_renderbuffer(MESA_FORMAT_Z24_UNORM_S8_UINT, driDrawPriv); _mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depthStencilRb->base.Base); _mesa_add_renderbuffer(&rfb->base, BUFFER_STENCIL, &depthStencilRb->base.Base); depthStencilRb->has_surface = screen->depthHasSurface; } else { /* depth renderbuffer */ struct radeon_renderbuffer *depth = radeon_create_renderbuffer(MESA_FORMAT_Z24_UNORM_X8_UINT, driDrawPriv); _mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depth->base.Base); depth->has_surface = screen->depthHasSurface; } } else if (mesaVis->depthBits == 16) { /* just 16-bit depth buffer, no hw stencil */ struct radeon_renderbuffer *depth = radeon_create_renderbuffer(MESA_FORMAT_Z_UNORM16, driDrawPriv); _mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depth->base.Base); depth->has_surface = screen->depthHasSurface; } _swrast_add_soft_renderbuffers(&rfb->base, GL_FALSE, /* color */ swDepth, swStencil, swAccum, swAlpha, GL_FALSE /* aux */); driDrawPriv->driverPrivate = (void *) rfb; return (driDrawPriv->driverPrivate != NULL); }
/** * Create a renderbuffer for a window's color, depth and/or stencil buffer. * Not used for user-created renderbuffers. */ struct radeon_renderbuffer * radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv) { struct radeon_renderbuffer *rrb; rrb = CALLOC_STRUCT(radeon_renderbuffer); radeon_print(RADEON_TEXTURE, RADEON_TRACE, "%s( rrb %p ) \n", __func__, rrb); if (!rrb) return NULL; _mesa_init_renderbuffer(&rrb->base, 0); rrb->base.ClassID = RADEON_RB_CLASS; rrb->base.Format = format; switch (format) { case MESA_FORMAT_RGB565: assert(_mesa_little_endian()); rrb->base.DataType = GL_UNSIGNED_BYTE; rrb->base._BaseFormat = GL_RGB; break; case MESA_FORMAT_RGB565_REV: assert(!_mesa_little_endian()); rrb->base.DataType = GL_UNSIGNED_BYTE; rrb->base._BaseFormat = GL_RGB; break; case MESA_FORMAT_XRGB8888: assert(_mesa_little_endian()); rrb->base.DataType = GL_UNSIGNED_BYTE; rrb->base._BaseFormat = GL_RGB; break; case MESA_FORMAT_XRGB8888_REV: assert(!_mesa_little_endian()); rrb->base.DataType = GL_UNSIGNED_BYTE; rrb->base._BaseFormat = GL_RGB; break; case MESA_FORMAT_ARGB8888: assert(_mesa_little_endian()); rrb->base.DataType = GL_UNSIGNED_BYTE; rrb->base._BaseFormat = GL_RGBA; break; case MESA_FORMAT_ARGB8888_REV: assert(!_mesa_little_endian()); rrb->base.DataType = GL_UNSIGNED_BYTE; rrb->base._BaseFormat = GL_RGBA; break; case MESA_FORMAT_S8: rrb->base.DataType = GL_UNSIGNED_BYTE; rrb->base._BaseFormat = GL_STENCIL_INDEX; break; case MESA_FORMAT_Z16: rrb->base.DataType = GL_UNSIGNED_SHORT; rrb->base._BaseFormat = GL_DEPTH_COMPONENT; break; case MESA_FORMAT_X8_Z24: rrb->base.DataType = GL_UNSIGNED_INT; rrb->base._BaseFormat = GL_DEPTH_COMPONENT; break; case MESA_FORMAT_S8_Z24: rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; rrb->base._BaseFormat = GL_DEPTH_STENCIL; break; default: fprintf(stderr, "%s: Unknown format %s\n", __FUNCTION__, _mesa_get_format_name(format)); _mesa_delete_renderbuffer(&rrb->base); return NULL; } rrb->dPriv = driDrawPriv; rrb->base.InternalFormat = _mesa_get_format_base_format(format); rrb->base.Delete = radeon_delete_renderbuffer; rrb->base.AllocStorage = radeon_alloc_window_storage; rrb->base.GetPointer = radeon_get_pointer; rrb->bo = NULL; return rrb; }
GLboolean _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS) { GLubyte *dst; const GLubyte *tempImage = NULL; int i, j; int numxpixels, numypixels; const GLubyte *srcaddr; GLubyte srcpixels[4][4]; GLubyte *blkaddr; GLint dstRowDiff, rgRowStride; mesa_format tempFormat; GLubyte *tempImageSlices[1]; assert(dstFormat == MESA_FORMAT_RG_RGTC2_UNORM || dstFormat == MESA_FORMAT_LA_LATC2_UNORM); if (baseInternalFormat == GL_RG) tempFormat = _mesa_little_endian() ? MESA_FORMAT_R8G8_UNORM : MESA_FORMAT_G8R8_UNORM; else tempFormat = _mesa_little_endian() ? MESA_FORMAT_L8A8_UNORM : MESA_FORMAT_A8L8_UNORM; rgRowStride = 2 * srcWidth * sizeof(GLubyte); tempImage = malloc(srcWidth * srcHeight * 2 * sizeof(GLubyte)); if (!tempImage) return GL_FALSE; /* out of memory */ tempImageSlices[0] = (GLubyte *) tempImage; _mesa_texstore(ctx, dims, baseInternalFormat, tempFormat, rgRowStride, tempImageSlices, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); dst = dstSlices[0]; blkaddr = dst; dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0; for (j = 0; j < srcHeight; j+=4) { if (srcHeight > j + 3) numypixels = 4; else numypixels = srcHeight - j; srcaddr = tempImage + j * srcWidth * 2; for (i = 0; i < srcWidth; i += 4) { if (srcWidth > i + 3) numxpixels = 4; else numxpixels = srcWidth - i; extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2); util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); blkaddr += 8; extractsrc_u(srcpixels, (GLubyte *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2); util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); blkaddr += 8; srcaddr += numxpixels * 2; } blkaddr += dstRowDiff; } free((void *) tempImage); return GL_TRUE; }
/** * Try to do glGetTexImage() with simple memcpy(). * \return GL_TRUE if done, GL_FALSE otherwise */ static GLboolean get_tex_memcpy(GLcontext *ctx, GLenum format, GLenum type, GLvoid *pixels, const struct gl_texture_object *texObj, const struct gl_texture_image *texImage) { GLboolean memCopy = GL_FALSE; /* Texture image should have been mapped already */ assert(texImage->Data); /* * Check if the src/dst formats are compatible. * Also note that GL's pixel transfer ops don't apply to glGetTexImage() * so we don't have to worry about those. * XXX more format combinations could be supported here. */ if ((texObj->Target == GL_TEXTURE_1D || texObj->Target == GL_TEXTURE_2D || texObj->Target == GL_TEXTURE_RECTANGLE || (texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) { if (texImage->TexFormat == MESA_FORMAT_ARGB8888 && format == GL_BGRA && type == GL_UNSIGNED_BYTE && !ctx->Pack.SwapBytes && _mesa_little_endian()) { memCopy = GL_TRUE; } else if (texImage->TexFormat == MESA_FORMAT_AL88 && format == GL_LUMINANCE_ALPHA && type == GL_UNSIGNED_BYTE && !ctx->Pack.SwapBytes && _mesa_little_endian()) { memCopy = GL_TRUE; } else if (texImage->TexFormat == MESA_FORMAT_L8 && format == GL_LUMINANCE && type == GL_UNSIGNED_BYTE) { memCopy = GL_TRUE; } else if (texImage->TexFormat == MESA_FORMAT_A8 && format == GL_ALPHA && type == GL_UNSIGNED_BYTE) { memCopy = GL_TRUE; } } if (memCopy) { const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat); const GLuint bytesPerRow = texImage->Width * bpp; GLubyte *dst = _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width, texImage->Height, format, type, 0, 0); const GLint dstRowStride = _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type); const GLubyte *src = texImage->Data; const GLint srcRowStride = texImage->RowStride * bpp; GLuint row; if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) { memcpy(dst, src, bytesPerRow * texImage->Height); } else { for (row = 0; row < texImage->Height; row++) { memcpy(dst, src, bytesPerRow); dst += dstRowStride; src += srcRowStride; } } } return memCopy; }
/** * Try to do glGetTexImage() with simple memcpy(). * \return GL_TRUE if done, GL_FALSE otherwise */ static GLboolean get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { const GLenum target = texImage->TexObject->Target; GLboolean memCopy = GL_FALSE; /* * Check if the src/dst formats are compatible. * Also note that GL's pixel transfer ops don't apply to glGetTexImage() * so we don't have to worry about those. * XXX more format combinations could be supported here. */ if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || _mesa_is_cube_face(target)) { if ((texImage->TexFormat == MESA_FORMAT_ARGB8888) && format == GL_BGRA && (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) && !ctx->Pack.SwapBytes && _mesa_little_endian()) { memCopy = GL_TRUE; } else if ((texImage->TexFormat == MESA_FORMAT_AL88) && format == GL_LUMINANCE_ALPHA && type == GL_UNSIGNED_BYTE && !ctx->Pack.SwapBytes && _mesa_little_endian()) { memCopy = GL_TRUE; } else if ((texImage->TexFormat == MESA_FORMAT_L8) && format == GL_LUMINANCE && type == GL_UNSIGNED_BYTE) { memCopy = GL_TRUE; } else if (texImage->TexFormat == MESA_FORMAT_L16 && format == GL_LUMINANCE && type == GL_UNSIGNED_SHORT) { memCopy = GL_TRUE; } else if (texImage->TexFormat == MESA_FORMAT_A8 && format == GL_ALPHA && type == GL_UNSIGNED_BYTE) { memCopy = GL_TRUE; } else if (texImage->TexFormat == MESA_FORMAT_A16 && format == GL_ALPHA && type == GL_UNSIGNED_SHORT) { memCopy = GL_TRUE; } } if (memCopy) { const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat); const GLuint bytesPerRow = texImage->Width * bpp; GLubyte *dst = _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width, texImage->Height, format, type, 0, 0); const GLint dstRowStride = _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type); GLubyte *src; GLint srcRowStride; /* map src texture buffer */ ctx->Driver.MapTextureImage(ctx, texImage, 0, 0, 0, texImage->Width, texImage->Height, GL_MAP_READ_BIT, &src, &srcRowStride); if (src) { if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) { memcpy(dst, src, bytesPerRow * texImage->Height); } else { GLuint row; for (row = 0; row < texImage->Height; row++) { memcpy(dst, src, bytesPerRow); dst += dstRowStride; src += srcRowStride; } } /* unmap src texture buffer */ ctx->Driver.UnmapTextureImage(ctx, texImage, 0); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); } } return memCopy; }