diff options
Diffstat (limited to 'src/mesa/state_tracker/st_cb_texture.c')
-rw-r--r-- | src/mesa/state_tracker/st_cb_texture.c | 77 |
1 files changed, 53 insertions, 24 deletions
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 8670261..c2f5fdc 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -187,6 +187,11 @@ st_FreeTextureImageBuffer(struct gl_context *ctx, free(stImage->transfer); stImage->transfer = NULL; stImage->num_transfers = 0; + + if (stImage->etc_data) { + free(stImage->etc_data); + stImage->etc_data = NULL; + } } bool @@ -196,6 +201,26 @@ st_etc_fallback(struct st_context *st, struct gl_texture_image *texImage) (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1); } +static void +etc_fallback_allocate(struct st_context *st, struct st_texture_image *stImage) +{ + struct gl_texture_image *texImage = &stImage->base; + + if (!st_etc_fallback(st, texImage)) + return; + + if (stImage->etc_data) + free(stImage->etc_data); + + unsigned data_size = _mesa_format_image_size(texImage->TexFormat, + texImage->Width2, + texImage->Height2, + texImage->Depth2); + + stImage->etc_data = + malloc(data_size * _mesa_num_tex_faces(texImage->TexObject->Target)); +} + /** called via ctx->Driver.MapTextureImage() */ static void st_MapTextureImage(struct gl_context *ctx, @@ -222,24 +247,23 @@ st_MapTextureImage(struct gl_context *ctx, &transfer); if (map) { if (st_etc_fallback(st, texImage)) { - /* 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. + /* ETC isn't supported by all gallium drivers, where it's represented + * by uncompressed formats. We store the compressed data (as it's + * needed for image copies in OES_copy_image), and decompress as + * necessary in Unmap. * - * Just create a temporary storage where the ETC texture will - * be stored. It will be decompressed in the Unmap function. + * Note: all ETC1/ETC2 formats have 4x4 block sizes. */ 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); + unsigned bytes = _mesa_get_format_bytes(texImage->TexFormat); + unsigned stride = *rowStrideOut = itransfer->temp_stride = + _mesa_format_row_stride(texImage->TexFormat, texImage->Width2); + *mapOut = itransfer->temp_data = + stImage->etc_data + ((x / 4) * bytes + (y / 4) * stride) + + z * stride * texImage->Height2 / 4; itransfer->map = map; - - *mapOut = itransfer->temp_data; - *rowStrideOut = itransfer->temp_stride; } else { /* supported mapping */ @@ -271,20 +295,21 @@ st_UnmapTextureImage(struct gl_context *ctx, assert(z == transfer->box.z); - if (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8) { - _mesa_etc1_unpack_rgba8888(itransfer->map, transfer->stride, - itransfer->temp_data, - itransfer->temp_stride, - transfer->box.width, transfer->box.height); - } - else { - _mesa_unpack_etc2_format(itransfer->map, transfer->stride, - itransfer->temp_data, itransfer->temp_stride, - transfer->box.width, transfer->box.height, - texImage->TexFormat); + if (transfer->usage & PIPE_TRANSFER_WRITE) { + if (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8) { + _mesa_etc1_unpack_rgba8888(itransfer->map, transfer->stride, + itransfer->temp_data, + itransfer->temp_stride, + transfer->box.width, transfer->box.height); + } + else { + _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; @@ -572,6 +597,8 @@ st_AllocTextureImageBuffer(struct gl_context *ctx, assert(!stImage->pt); /* xxx this might be wrong */ + etc_fallback_allocate(st, stImage); + /* Look if the parent texture object has space for this image */ if (stObj->pt && level <= stObj->pt->last_level && @@ -2680,6 +2707,8 @@ st_AllocTextureStorage(struct gl_context *ctx, struct st_texture_image *stImage = st_texture_image(texObj->Image[face][level]); pipe_resource_reference(&stImage->pt, stObj->pt); + + etc_fallback_allocate(st, stImage); } } |