aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/state_tracker/st_cb_texture.c
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/state_tracker/st_cb_texture.c')
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_texture.c94
1 files changed, 82 insertions, 12 deletions
diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c
index c4b2107ba..ad14bd939 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_texture.c
+++ b/mesalib/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,32 @@ 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) ||
+ (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)) {
+ /* 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 +250,35 @@ 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) ||
+ (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)) {
+ /* 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);
+
+ 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;
+ }
+
st_texture_image_unmap(st, stImage, slice);
}
@@ -398,7 +452,7 @@ guess_and_alloc_texture(struct st_context *st,
stObj->height0 = height;
stObj->depth0 = depth;
- fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat);
+ fmt = st_mesa_format_to_pipe_format(st, stImage->base.TexFormat);
bindings = default_bindings(st, fmt);
@@ -449,7 +503,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx,
/* Look if the parent texture object has space for this image */
if (stObj->pt &&
level <= stObj->pt->last_level &&
- st_texture_match_image(stObj->pt, texImage)) {
+ st_texture_match_image(st, stObj->pt, texImage)) {
/* this image will fit in the existing texture object's memory */
pipe_resource_reference(&stImage->pt, stObj->pt);
return GL_TRUE;
@@ -472,7 +526,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx,
}
if (stObj->pt &&
- st_texture_match_image(stObj->pt, texImage)) {
+ st_texture_match_image(st, stObj->pt, texImage)) {
/* The image will live in the object's mipmap memory */
pipe_resource_reference(&stImage->pt, stObj->pt);
assert(stImage->pt);
@@ -486,7 +540,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx,
* level.
*/
enum pipe_format format =
- st_mesa_format_to_pipe_format(texImage->TexFormat);
+ st_mesa_format_to_pipe_format(st, texImage->TexFormat);
GLuint bindings = default_bindings(st, format);
GLuint ptWidth, ptHeight, ptDepth, ptLayers;
@@ -613,6 +667,9 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,
unsigned bind;
GLubyte *map;
+ assert(!_mesa_is_format_etc2(texImage->TexFormat) &&
+ texImage->TexFormat != MESA_FORMAT_ETC1_RGB8);
+
if (!st->prefer_blit_based_texture_transfer) {
goto fallback;
}
@@ -660,7 +717,7 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,
}
/* Choose the source format. */
- src_format = st_choose_matching_format(screen, PIPE_BIND_SAMPLER_VIEW,
+ src_format = st_choose_matching_format(st, PIPE_BIND_SAMPLER_VIEW,
format, type, unpack->SwapBytes);
if (!src_format) {
goto fallback;
@@ -872,6 +929,9 @@ st_GetTexImage(struct gl_context * ctx,
ubyte *map = NULL;
boolean done = FALSE;
+ assert(!_mesa_is_format_etc2(texImage->TexFormat) &&
+ texImage->TexFormat != MESA_FORMAT_ETC1_RGB8);
+
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 */
@@ -934,7 +994,7 @@ st_GetTexImage(struct gl_context * ctx,
/* Choose the destination format by finding the best match
* for the format+type combo. */
- dst_format = st_choose_matching_format(screen, bind, format, type,
+ dst_format = st_choose_matching_format(st, bind, format, type,
ctx->Pack.SwapBytes);
if (dst_format == PIPE_FORMAT_NONE) {
@@ -956,6 +1016,7 @@ st_GetTexImage(struct gl_context * ctx,
case PIPE_FORMAT_RGTC1_UNORM:
case PIPE_FORMAT_RGTC2_UNORM:
case PIPE_FORMAT_ETC1_RGB8:
+ case PIPE_FORMAT_BPTC_RGBA_UNORM:
dst_glformat = GL_RGBA8;
break;
case PIPE_FORMAT_RGTC1_SNORM:
@@ -964,7 +1025,12 @@ st_GetTexImage(struct gl_context * ctx,
goto fallback;
dst_glformat = GL_RGBA8_SNORM;
break;
- /* TODO: for BPTC_*FLOAT, set RGBA32F and check for ARB_texture_float */
+ case PIPE_FORMAT_BPTC_RGB_FLOAT:
+ case PIPE_FORMAT_BPTC_RGB_UFLOAT:
+ if (!ctx->Extensions.ARB_texture_float)
+ goto fallback;
+ dst_glformat = GL_RGBA32F;
+ break;
default:
assert(0);
goto fallback;
@@ -1308,6 +1374,9 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
unsigned bind;
GLint srcY0, srcY1;
+ assert(!_mesa_is_format_etc2(texImage->TexFormat) &&
+ texImage->TexFormat != MESA_FORMAT_ETC1_RGB8);
+
if (!strb || !strb->surface || !stImage->pt) {
debug_printf("%s: null strb or stImage\n", __FUNCTION__);
return;
@@ -1531,7 +1600,8 @@ st_finalize_texture(struct gl_context *ctx,
}
/* Find gallium format for the Mesa texture */
- firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
+ firstImageFormat =
+ st_mesa_format_to_pipe_format(st, firstImage->base.TexFormat);
/* Find size of level=0 Gallium mipmap image, plus number of texture layers */
{
@@ -1649,7 +1719,7 @@ st_AllocTextureStorage(struct gl_context *ctx,
stObj->depth0 = depth;
stObj->lastLevel = levels - 1;
- fmt = st_mesa_format_to_pipe_format(texImage->TexFormat);
+ fmt = st_mesa_format_to_pipe_format(st, texImage->TexFormat);
bindings = default_bindings(st, fmt);
@@ -1728,7 +1798,7 @@ st_TestProxyTexImage(struct gl_context *ctx, GLenum target,
memset(&pt, 0, sizeof(pt));
pt.target = gl_target_to_pipe(target);
- pt.format = st_mesa_format_to_pipe_format(format);
+ pt.format = st_mesa_format_to_pipe_format(st, format);
st_gl_texture_dims_to_pipe_dims(target,
width, height, depth,