On Sun, Aug 3, 2014 at 6:23 PM, Glenn Kennard <glenn.kenn...@gmail.com> wrote: > On Sun, 03 Aug 2014 14:40:37 +0200, Marek Olšák <mar...@gmail.com> wrote: > >> From: Marek Olšák <marek.ol...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev