summaryrefslogtreecommitdiffstats
path: root/src/mesa/state_tracker
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/state_tracker')
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c54
-rw-r--r--src/mesa/state_tracker/st_format.c24
-rw-r--r--src/mesa/state_tracker/st_texture.c11
-rw-r--r--src/mesa/state_tracker/st_texture.h12
4 files changed, 93 insertions, 8 deletions
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index c4b2107ba6e..62075c67463 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -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;
diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
index 409079bd453..ff3f494f39f 100644
--- a/src/mesa/state_tracker/st_format.c
+++ b/src/mesa/state_tracker/st_format.c
@@ -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);
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index c1488214220..9f57cfb3d96 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -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__);
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index affb5681264..04b886ee39f 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -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;
};