diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c index ddf38e3dd35..82e44f9b83a 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -551,6 +551,11 @@ brw_init_surface_formats(struct brw_context *brw) ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT] = true; ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT_X24S8] = true; ctx->TextureFormatSupported[MESA_FORMAT_Z16] = true; + + /* On hardware that lacks support for ETC1, we map ETC1 to RGBX + * during glCompressedTexImage2D(). See intel_mipmap_tree::wraps_etc1. + */ + ctx->TextureFormatSupported[MESA_FORMAT_ETC1_RGB8] = true; } bool diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c index 953b98389c3..844125dc8a5 100755 --- a/src/mesa/drivers/dri/intel/intel_extensions.c +++ b/src/mesa/drivers/dri/intel/intel_extensions.c @@ -91,6 +91,7 @@ intelInitExtensions(struct gl_context *ctx) ctx->Extensions.OES_EGL_image = true; #endif ctx->Extensions.OES_draw_texture = true; + ctx->Extensions.OES_compressed_ETC1_RGB8_texture = true; if (intel->gen >= 6) ctx->Const.GLSLVersion = 130; diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 4e892b27fd1..d6572cd90f1 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -38,6 +38,7 @@ #include "main/enums.h" #include "main/formats.h" #include "main/image.h" +#include "main/texcompress_etc.h" #include "main/teximage.h" #define FILE_DEBUG_FLAG DEBUG_MIPTREE @@ -190,7 +191,15 @@ intel_miptree_create(struct intel_context *intel, { struct intel_mipmap_tree *mt; uint32_t tiling = I915_TILING_NONE; - GLenum base_format = _mesa_get_format_base_format(format); + GLenum base_format; + bool wraps_etc1 = false; + + if (format == MESA_FORMAT_ETC1_RGB8) { + format = MESA_FORMAT_RGBX8888_REV; + wraps_etc1 = true; + } + + base_format = _mesa_get_format_base_format(format); if (intel->use_texture_tiling && !_mesa_is_format_compressed(format)) { if (intel->gen >= 4 && @@ -237,6 +246,7 @@ intel_miptree_create(struct intel_context *intel, return NULL; } + mt->wraps_etc1 = wraps_etc1; mt->region = intel_region_alloc(intel->intelScreen, tiling, mt->cpp, @@ -1049,6 +1059,60 @@ intel_miptree_unmap_s8(struct intel_context *intel, free(map->buffer); } +static void +intel_miptree_map_etc1(struct intel_context *intel, + struct intel_mipmap_tree *mt, + struct intel_miptree_map *map, + unsigned int level, + unsigned int slice) +{ + /* For justification of these invariants, + * see intel_mipmap_tree:wraps_etc1. + */ + assert(mt->wraps_etc1); + assert(mt->format == MESA_FORMAT_RGBX8888_REV); + + /* From the GL_OES_compressed_ETC1_RGB8_texture spec: + * INVALID_OPERATION is generated by CompressedTexSubImage2D, + * TexSubImage2D, or CopyTexSubImage2D if the texture image + * bound to has internal format ETC1_RGB8_OES. + * + * This implies that intel_miptree_map_etc1() can only be called from + * glCompressedTexImage2D, and hence the assertions below hold. + */ + assert(map->mode & GL_MAP_WRITE_BIT); + assert(map->mode & GL_MAP_INVALIDATE_RANGE_BIT); + assert(map->x == 0); + assert(map->y == 0); + + /* Each ETC1 block contains 4x4 pixels in 8 bytes. */ + map->stride = 2 * map->w; + map->buffer = map->ptr = malloc(map->stride * map->h); +} + +static void +intel_miptree_unmap_etc1(struct intel_context *intel, + struct intel_mipmap_tree *mt, + struct intel_miptree_map *map, + unsigned int level, + unsigned int slice) +{ + uint32_t image_x; + uint32_t image_y; + intel_miptree_get_image_offset(mt, level, 0, slice, &image_x, &image_y); + + uint8_t *xbgr = intel_region_map(intel, mt->region, map->mode) + + image_y * mt->region->pitch * mt->region->cpp + + image_x * mt->region->cpp; + + _mesa_etc1_unpack_rgba8888(xbgr, mt->region->pitch * mt->region->cpp, + map->ptr, map->stride, + map->w, map->h); + + intel_region_unmap(intel, mt->region); + free(map->buffer); +} + /** * Mapping function for packed depth/stencil miptrees backed by real separate * miptrees for depth and stencil. @@ -1225,6 +1289,8 @@ intel_miptree_map(struct intel_context *intel, if (mt->format == MESA_FORMAT_S8) { intel_miptree_map_s8(intel, mt, map, level, slice); + } else if (mt->wraps_etc1) { + intel_miptree_map_etc1(intel, mt, map, level, slice); } else if (mt->stencil_mt) { intel_miptree_map_depthstencil(intel, mt, map, level, slice); } else if (intel->has_llc && @@ -1261,6 +1327,8 @@ intel_miptree_unmap(struct intel_context *intel, if (mt->format == MESA_FORMAT_S8) { intel_miptree_unmap_s8(intel, mt, map, level, slice); + } else if (mt->wraps_etc1) { + intel_miptree_unmap_etc1(intel, mt, map, level, slice); } else if (mt->stencil_mt) { intel_miptree_unmap_depthstencil(intel, mt, map, level, slice); } else if (map->bo) { diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index 74fcc796cf5..2fb5775c02f 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -190,6 +190,9 @@ struct intel_mipmap_tree * MESA_FORMAT_Z32_FLOAT_X24S8, then mt->format will be * MESA_FORMAT_Z32_FLOAT, otherwise for MESA_FORMAT_S8_Z24 objects it will be * MESA_FORMAT_X8_Z24. + * + * For ETC1 textures, this is MESA_FORMAT_RGBX8888_REV if the hardware + * lacks support for ETC1. See @ref wraps_etc1. */ gl_format format;