free(stImage->transfer);
stImage->transfer = NULL;
stImage->num_transfers = 0;
+
+ if (stImage->etc_data) {
+ free(stImage->etc_data);
+ stImage->etc_data = NULL;
+ }
+}
+
+bool
+st_etc_fallback(struct st_context *st, struct gl_texture_image *texImage)
+{
+ return (_mesa_is_format_etc2(texImage->TexFormat) && !st->has_etc2) ||
+ (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
map = st_texture_image_map(st, stImage, pipeMode, x, y, slice, w, h, 1,
&transfer);
if (map) {
- if ((_mesa_is_format_etc2(texImage->TexFormat) && !st->has_etc2) ||
- (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.
+ if (st_etc_fallback(st, texImage)) {
+ /* 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 */
struct st_context *st = st_context(ctx);
struct st_texture_image *stImage = st_texture_image(texImage);
- if ((_mesa_is_format_etc2(texImage->TexFormat) && !st->has_etc2) ||
- (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)) {
+ if (st_etc_fallback(st, texImage)) {
/* Decompress the ETC texture to the mapped one. */
unsigned z = slice + stImage->base.Face;
struct st_texture_image_transfer *itransfer = &stImage->transfer[z];
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;
*/
firstImage = _mesa_base_tex_image(&stObj->base);
if (firstImage &&
+ firstImage->Width2 > 0 &&
+ firstImage->Height2 > 0 &&
+ firstImage->Depth2 > 0 &&
guess_base_level_size(stObj->base.Target,
firstImage->Width2,
firstImage->Height2,
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 &&
unsigned dst_level = 0;
st_flush_bitmap_cache(st);
+ st_invalidate_readpix_cache(st);
if (stObj->pt == stImage->pt)
dst_level = texImage->TexObject->MinLevel + texImage->Level;
if (!dst)
goto fallback;
- /* Try transfer_inline_write, which should be the fastest memcpy path. */
+ /* Try texture_subdata, which should be the fastest memcpy path. */
if (pixels &&
!_mesa_is_bufferobj(unpack->BufferObj) &&
_mesa_texstore_can_use_memcpy(ctx, texImage->_BaseFormat,
}
u_box_3d(xoffset, yoffset, zoffset + dstz, width, height, depth, &box);
- pipe->transfer_inline_write(pipe, dst, dst_level, 0,
- &box, data, stride, layer_stride);
+ pipe->texture_subdata(pipe, dst, dst_level, 0,
+ &box, data, stride, layer_stride);
return;
}
if (!_mesa_is_bufferobj(ctx->Unpack.BufferObj))
goto fallback;
- if ((_mesa_is_format_etc2(texImage->TexFormat) && !st->has_etc2) ||
- (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)) {
+ if (st_etc_fallback(st, texImage)) {
/* ETC isn't supported and is represented by uncompressed formats. */
goto fallback;
}
GLint srcY0, srcY1;
st_flush_bitmap_cache(st);
+ st_invalidate_readpix_cache(st);
assert(!_mesa_is_format_etc2(texImage->TexFormat) &&
texImage->TexFormat != MESA_FORMAT_ETC1_RGB8);
*/
pipe_resource_reference(&stObj->pt, NULL);
st_texture_release_all_sampler_views(st, stObj);
- st->dirty.st |= ST_NEW_FRAMEBUFFER;
+ st->dirty |= ST_NEW_FRAMEBUFFER;
}
}
struct st_texture_image *stImage =
st_texture_image(texObj->Image[face][level]);
pipe_resource_reference(&stImage->pt, stObj->pt);
+
+ etc_fallback_allocate(st, stImage);
}
}
static GLboolean
st_TestProxyTexImage(struct gl_context *ctx, GLenum target,
- GLint level, mesa_format format,
- GLint width, GLint height,
- GLint depth, GLint border)
+ GLuint numLevels, GLint level,
+ mesa_format format, GLuint numSamples,
+ GLint width, GLint height, GLint depth)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
pt.target = gl_target_to_pipe(target);
pt.format = st_mesa_format_to_pipe_format(st, format);
+ pt.nr_samples = numSamples;
st_gl_texture_dims_to_pipe_dims(target,
width, height, depth,
&pt.width0, &pt.height0,
&pt.depth0, &pt.array_size);
- if (level == 0 && (texObj->Sampler.MinFilter == GL_LINEAR ||
- texObj->Sampler.MinFilter == GL_NEAREST)) {
+ if (numLevels > 0) {
+ /* For immutable textures we know the final number of mip levels */
+ pt.last_level = numLevels - 1;
+ }
+ else if (level == 0 && (texObj->Sampler.MinFilter == GL_LINEAR ||
+ texObj->Sampler.MinFilter == GL_NEAREST)) {
/* assume just one mipmap level */
pt.last_level = 0;
}
}
else {
/* Use core Mesa fallback */
- return _mesa_test_proxy_teximage(ctx, target, level, format,
- width, height, depth, border);
+ return _mesa_test_proxy_teximage(ctx, target, numLevels, level, format,
+ numSamples, width, height, depth);
}
}
return;
st_flush_bitmap_cache(st);
+ st_invalidate_readpix_cache(st);
u_box_3d(xoffset, yoffset, zoffset + texImage->Face,
width, height, depth, &box);