[Mesa-dev] [PATCH 2/5] st/mesa: add support for ETC2 formats
Glenn Kennard
glenn.kennard at gmail.com
Sun Aug 3 09:23:30 PDT 2014
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?
> + unsigned z = transfer->box.z;
Nitpick: transfer->box.z is a signed int.
> + 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?
> +
> + 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.
> unsigned num_transfers;
> };
More information about the mesa-dev
mailing list