st/mesa: add support for ETC2 formats
The formats are emulated by translating them into plain uncompressed formats, because I don't know of any hardware which supports them. This is required for GLES 3.0 and ARB_ES3_compatibility (GL 4.3).
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
#include "main/pbo.h"
|
||||
#include "main/pixeltransfer.h"
|
||||
#include "main/texcompress.h"
|
||||
#include "main/texcompress_etc.h"
|
||||
#include "main/texgetimage.h"
|
||||
#include "main/teximage.h"
|
||||
#include "main/texobj.h"
|
||||
@@ -207,8 +208,31 @@ st_MapTextureImage(struct gl_context *ctx,
|
||||
map = st_texture_image_map(st, stImage, pipeMode, x, y, slice, w, h, 1,
|
||||
&transfer);
|
||||
if (map) {
|
||||
*mapOut = map;
|
||||
*rowStrideOut = transfer->stride;
|
||||
if (_mesa_is_format_etc2(texImage->TexFormat)) {
|
||||
/* ETC isn't supported by gallium and it's represented
|
||||
* by uncompressed formats. Only write transfers with precompressed
|
||||
* data are supported by ES3, which makes this really simple.
|
||||
*
|
||||
* Just create a temporary storage where the ETC texture will
|
||||
* be stored. It will be decompressed in the Unmap function.
|
||||
*/
|
||||
unsigned z = transfer->box.z;
|
||||
struct st_texture_image_transfer *itransfer = &stImage->transfer[z];
|
||||
|
||||
itransfer->temp_data =
|
||||
malloc(_mesa_format_image_size(texImage->TexFormat, w, h, 1));
|
||||
itransfer->temp_stride =
|
||||
_mesa_format_row_stride(texImage->TexFormat, w);
|
||||
itransfer->map = map;
|
||||
|
||||
*mapOut = itransfer->temp_data;
|
||||
*rowStrideOut = itransfer->temp_stride;
|
||||
}
|
||||
else {
|
||||
/* supported mapping */
|
||||
*mapOut = map;
|
||||
*rowStrideOut = transfer->stride;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*mapOut = NULL;
|
||||
@@ -225,6 +249,26 @@ st_UnmapTextureImage(struct gl_context *ctx,
|
||||
{
|
||||
struct st_context *st = st_context(ctx);
|
||||
struct st_texture_image *stImage = st_texture_image(texImage);
|
||||
|
||||
if (_mesa_is_format_etc2(texImage->TexFormat)) {
|
||||
/* Decompress the ETC texture to the mapped one. */
|
||||
unsigned z = slice + stImage->base.Face;
|
||||
struct st_texture_image_transfer *itransfer = &stImage->transfer[z];
|
||||
struct pipe_transfer *transfer = itransfer->transfer;
|
||||
|
||||
assert(z == transfer->box.z);
|
||||
|
||||
_mesa_unpack_etc2_format(itransfer->map, transfer->stride,
|
||||
itransfer->temp_data, itransfer->temp_stride,
|
||||
transfer->box.width, transfer->box.height,
|
||||
texImage->TexFormat);
|
||||
|
||||
free(itransfer->temp_data);
|
||||
itransfer->temp_data = NULL;
|
||||
itransfer->temp_stride = 0;
|
||||
itransfer->map = 0;
|
||||
}
|
||||
|
||||
st_texture_image_unmap(st, stImage, slice);
|
||||
}
|
||||
|
||||
@@ -613,6 +657,8 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,
|
||||
unsigned bind;
|
||||
GLubyte *map;
|
||||
|
||||
assert(!_mesa_is_format_etc2(texImage->TexFormat));
|
||||
|
||||
if (!st->prefer_blit_based_texture_transfer) {
|
||||
goto fallback;
|
||||
}
|
||||
@@ -872,6 +918,8 @@ st_GetTexImage(struct gl_context * ctx,
|
||||
ubyte *map = NULL;
|
||||
boolean done = FALSE;
|
||||
|
||||
assert(!_mesa_is_format_etc2(texImage->TexFormat));
|
||||
|
||||
if (!st->prefer_blit_based_texture_transfer &&
|
||||
!_mesa_is_format_compressed(texImage->TexFormat)) {
|
||||
/* Try to avoid the fallback if we're doing texture decompression here */
|
||||
@@ -1308,6 +1356,8 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
|
||||
unsigned bind;
|
||||
GLint srcY0, srcY1;
|
||||
|
||||
assert(!_mesa_is_format_etc2(texImage->TexFormat));
|
||||
|
||||
if (!strb || !strb->surface || !stImage->pt) {
|
||||
debug_printf("%s: null strb or stImage\n", __FUNCTION__);
|
||||
return;
|
||||
|
||||
@@ -402,6 +402,26 @@ st_mesa_format_to_pipe_format(mesa_format mesaFormat)
|
||||
case MESA_FORMAT_B8G8R8X8_SRGB:
|
||||
return PIPE_FORMAT_B8G8R8X8_SRGB;
|
||||
|
||||
/* ETC2 formats are emulated as uncompressed ones.
|
||||
* The destination formats mustn't be changed, because they are also
|
||||
* destination formats of the unpack/decompression function. */
|
||||
case MESA_FORMAT_ETC2_RGB8:
|
||||
case MESA_FORMAT_ETC2_RGBA8_EAC:
|
||||
case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
|
||||
return PIPE_FORMAT_R8G8B8A8_UNORM;
|
||||
case MESA_FORMAT_ETC2_SRGB8:
|
||||
case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
|
||||
case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
|
||||
return PIPE_FORMAT_B8G8R8A8_SRGB;
|
||||
case MESA_FORMAT_ETC2_R11_EAC:
|
||||
return PIPE_FORMAT_R16_UNORM;
|
||||
case MESA_FORMAT_ETC2_RG11_EAC:
|
||||
return PIPE_FORMAT_R16G16_UNORM;
|
||||
case MESA_FORMAT_ETC2_SIGNED_R11_EAC:
|
||||
return PIPE_FORMAT_R16_SNORM;
|
||||
case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
|
||||
return PIPE_FORMAT_R16G16_SNORM;
|
||||
|
||||
default:
|
||||
return PIPE_FORMAT_NONE;
|
||||
}
|
||||
@@ -781,6 +801,10 @@ test_format_conversion(void)
|
||||
|
||||
/* test all Mesa formats */
|
||||
for (i = 1; i < MESA_FORMAT_COUNT; i++) {
|
||||
/* ETC2 formats are translated differently, skip them. */
|
||||
if (_mesa_is_format_etc2(i))
|
||||
continue;
|
||||
|
||||
enum pipe_format pf = st_mesa_format_to_pipe_format(i);
|
||||
if (pf != PIPE_FORMAT_NONE) {
|
||||
mesa_format mf = st_pipe_format_to_mesa_format(pf);
|
||||
|
||||
@@ -269,14 +269,15 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
|
||||
unsigned new_size = z + 1;
|
||||
|
||||
stImage->transfer = realloc(stImage->transfer,
|
||||
new_size * sizeof(void*));
|
||||
new_size * sizeof(struct st_texture_image_transfer));
|
||||
memset(&stImage->transfer[stImage->num_transfers], 0,
|
||||
(new_size - stImage->num_transfers) * sizeof(void*));
|
||||
(new_size - stImage->num_transfers) *
|
||||
sizeof(struct st_texture_image_transfer));
|
||||
stImage->num_transfers = new_size;
|
||||
}
|
||||
|
||||
assert(!stImage->transfer[z]);
|
||||
stImage->transfer[z] = *transfer;
|
||||
assert(!stImage->transfer[z].transfer);
|
||||
stImage->transfer[z].transfer = *transfer;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
@@ -288,7 +289,7 @@ st_texture_image_unmap(struct st_context *st,
|
||||
{
|
||||
struct pipe_context *pipe = st->pipe;
|
||||
struct pipe_transfer **transfer =
|
||||
&stImage->transfer[slice + stImage->base.Face];
|
||||
&stImage->transfer[slice + stImage->base.Face].transfer;
|
||||
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
|
||||
@@ -38,6 +38,16 @@
|
||||
struct pipe_resource;
|
||||
|
||||
|
||||
struct st_texture_image_transfer {
|
||||
struct pipe_transfer *transfer;
|
||||
|
||||
/* For ETC fallback. */
|
||||
GLubyte *temp_data; /**< Temporary ETC texture storage. */
|
||||
unsigned temp_stride; /**< Stride of the ETC texture storage. */
|
||||
GLubyte *map; /**< Saved map pointer of the uncompressed transfer. */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of gl_texure_image.
|
||||
*/
|
||||
@@ -59,7 +69,7 @@ struct st_texture_image
|
||||
/* List of transfers, allocated on demand.
|
||||
* transfer[layer] is a mapping for that layer.
|
||||
*/
|
||||
struct pipe_transfer **transfer;
|
||||
struct st_texture_image_transfer *transfer;
|
||||
unsigned num_transfers;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user