static void flush_astc_denorms(struct gl_context *ctx, GLuint dims, struct gl_texture_image *texImage, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) { struct compressed_pixelstore store; _mesa_compute_compressed_pixelstore(dims, texImage->TexFormat, width, height, depth, &ctx->Unpack, &store); for (int slice = 0; slice < store.CopySlices; slice++) { /* Map dest texture buffer */ GLubyte *dstMap; GLint dstRowStride; ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset, xoffset, yoffset, width, height, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, &dstMap, &dstRowStride); if (!dstMap) continue; for (int i = 0; i < store.CopyRowsPerSlice; i++) { /* An ASTC block is stored in little endian mode. The byte that * contains bits 0..7 is stored at the lower address in memory. */ struct astc_void_extent { uint16_t header : 12; uint16_t dontcare[3]; uint16_t R; uint16_t G; uint16_t B; uint16_t A; } *blocks = (struct astc_void_extent*) dstMap; /* Iterate over every copied block in the row */ for (int j = 0; j < store.CopyBytesPerRow / 16; j++) { /* Check if the header matches that of an LDR void-extent block */ if (blocks[j].header == 0xDFC) { /* Flush UNORM16 values that would be denormalized */ if (blocks[j].A < 4) blocks[j].A = 0; if (blocks[j].B < 4) blocks[j].B = 0; if (blocks[j].G < 4) blocks[j].G = 0; if (blocks[j].R < 4) blocks[j].R = 0; } } dstMap += dstRowStride; } ctx->Driver.UnmapTextureImage(ctx, texImage, slice + zoffset); } }
/** * This is the software fallback for Driver.GetCompressedTexImage(). * All error checking will have been done before this routine is called. */ void _mesa_GetCompressedTexImage_sw(struct gl_context *ctx, struct gl_texture_image *texImage, GLvoid *img) { const GLuint dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target); struct compressed_pixelstore store; GLint slice; GLubyte *dest; _mesa_compute_compressed_pixelstore(dimensions, texImage->TexFormat, texImage->Width, texImage->Height, texImage->Depth, &ctx->Pack, &store); if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* pack texture image into a PBO */ dest = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, MAP_INTERNAL); if (!dest) { /* out of memory or other unexpected error */ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage(map PBO failed)"); return; } dest = ADD_POINTERS(dest, img); } else { dest = img; } dest += store.SkipBytes; for (slice = 0; slice < store.CopySlices; slice++) { GLint srcRowStride; GLubyte *src; /* map src texture buffer */ ctx->Driver.MapTextureImage(ctx, texImage, slice, 0, 0, texImage->Width, texImage->Height, GL_MAP_READ_BIT, &src, &srcRowStride); if (src) { GLint i; for (i = 0; i < store.CopyRowsPerSlice; i++) { memcpy(dest, src, store.CopyBytesPerRow); dest += store.TotalBytesPerRow; src += srcRowStride; } ctx->Driver.UnmapTextureImage(ctx, texImage, slice); /* Advance to next slice */ dest += store.TotalBytesPerRow * (store.TotalRowsPerSlice - store.CopyRowsPerSlice); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage"); } } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); } }
/** * Fallback for Driver.CompressedTexSubImage() */ void _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *texImage, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) { struct compressed_pixelstore store; GLint dstRowStride; GLint i, slice; GLubyte *dstMap; const GLubyte *src; if (dims == 1) { _mesa_problem(ctx, "Unexpected 1D compressed texsubimage call"); return; } _mesa_compute_compressed_pixelstore(dims, texImage->TexFormat, width, height, depth, &ctx->Unpack, &store); /* get pointer to src pixels (may be in a pbo which we'll map here) */ data = _mesa_validate_pbo_compressed_teximage(ctx, dims, imageSize, data, &ctx->Unpack, "glCompressedTexSubImage"); if (!data) return; src = (const GLubyte *) data + store.SkipBytes; for (slice = 0; slice < store.CopySlices; slice++) { /* Map dest texture buffer */ ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset, xoffset, yoffset, width, height, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, &dstMap, &dstRowStride); if (dstMap) { /* copy rows of blocks */ for (i = 0; i < store.CopyRowsPerSlice; i++) { memcpy(dstMap, src, store.CopyBytesPerRow); dstMap += dstRowStride; src += store.TotalBytesPerRow; } ctx->Driver.UnmapTextureImage(ctx, texImage, slice + zoffset); /* advance to next slice */ src += store.TotalBytesPerRow * (store.TotalRowsPerSlice - store.CopyRowsPerSlice); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage%uD", dims); } } _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); }