[Mesa-dev] [PATCH 2/5] st/mesa: add support for ETC2 formats
Marek Olšák
maraeo at gmail.com
Sun Aug 3 10:10:17 PDT 2014
On Sun, Aug 3, 2014 at 6:23 PM, Glenn Kennard <glenn.kennard at gmail.com> wrote:
> On Sun, 03 Aug 2014 14:40:37 +0200, Marek Olšák <maraeo at gmail.com> wrote:
>
>> From: Marek Olšák <marek.olsak at amd.com>
>>
>> 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).
>> ---
>> src/mesa/state_tracker/st_cb_texture.c | 54
>> ++++++++++++++++++++++++++++++++--
>> src/mesa/state_tracker/st_format.c | 24 +++++++++++++++
>> src/mesa/state_tracker/st_texture.c | 11 +++----
>> src/mesa/state_tracker/st_texture.h | 12 +++++++-
>> 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 aa6b05f..88c4b25 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
>
>
> Freedreno could definitely support it natively, at least for a3xx. Though it
> can cross that bridge once it gets there i suppose.
>
>
>> + * 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.
>> + */
>
>
> Question: Is it possible to create a permanent map of a texture in GL?
No, it's not. OpenGL doesn't have an API for mapping textures.
>
>
>> + unsigned z = transfer->box.z;
>
>
> Nitpick: transfer->box.z is a signed int.
In this case, it's set to slice+face, which is always a positive number.
>
>
>> + 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;
>
>
> int
>
>
>> + 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);
>
>
> Is the ETC source data always an integer number of blocks?
Yes. Compressed texture uploads must always be aligned to 4x4.
>
>
>> +
>> + 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;
>> }
>> @@ -870,6 +916,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 */
>> @@ -1306,6 +1354,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 409079b..ff3f494 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 c148821..9f57cfb 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 affb568..04b886e 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;
>
>
> Nitpick: Might want to call it texture_image_transfer to distinguish it from
> pipe_transfer where its used.
To me, it doesn't seem to make any difference in readability and
"texture_image_transfer" is too long.
Marek
More information about the mesa-dev
mailing list