summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c5
-rw-r--r--src/mesa/drivers/dri/i965/intel_mipmap_tree.c174
-rw-r--r--src/mesa/drivers/dri/i965/intel_mipmap_tree.h24
3 files changed, 134 insertions, 69 deletions
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 c55182d7ffb..c3d267721e1 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -521,7 +521,7 @@ static void brw_update_texture_surface(struct gl_context *ctx,
*/
mesa_fmt = mt->format;
} else if (mt->etc_format != MESA_FORMAT_NONE) {
- mesa_fmt = mt->format;
+ mesa_fmt = mt->shadow_mt->format;
} else if (plane > 0) {
mesa_fmt = mt->format;
} else {
@@ -581,6 +581,9 @@ static void brw_update_texture_surface(struct gl_context *ctx,
assert(mt->shadow_mt && !mt->shadow_needs_update);
mt = mt->shadow_mt;
format = ISL_FORMAT_R8_UINT;
+ } else if (intel_miptree_needs_fake_etc(brw, mt)) {
+ assert(mt->shadow_mt);
+ mt = mt->shadow_mt;
}
const int surf_index = surf_offset - &brw->wm.base.surf_offset[0];
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
index e364fed2cc7..976a004ade0 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
@@ -57,6 +57,11 @@ static void *intel_miptree_map_raw(struct brw_context *brw,
GLbitfield mode);
static void intel_miptree_unmap_raw(struct intel_mipmap_tree *mt);
+static void intel_miptree_update_etc_shadow(struct brw_context *brw,
+ struct intel_mipmap_tree *mt,
+ unsigned int level,
+ unsigned int slice,
+ int level_w, int level_h);
static bool
intel_miptree_supports_mcs(struct brw_context *brw,
@@ -687,15 +692,12 @@ miptree_create(struct brw_context *brw,
if (devinfo->gen < 6 && _mesa_is_format_color_format(format))
tiling_flags &= ~ISL_TILING_Y0_BIT;
- mesa_format mt_fmt;
- if (_mesa_is_format_color_format(format)) {
- mt_fmt = intel_lower_compressed_format(brw, format);
- } else {
+ mesa_format mt_fmt = format;
+ if (!_mesa_is_format_color_format(format) && devinfo->gen >= 6) {
/* Fix up the Z miptree format for how we're splitting out separate
* stencil. Gen7 expects there to be no stencil bits in its depth buffer.
*/
- mt_fmt = (devinfo->gen < 6) ? format :
- intel_depth_format_for_depthstencil_format(format);
+ mt_fmt = intel_depth_format_for_depthstencil_format(format);
}
struct intel_mipmap_tree *mt =
@@ -707,6 +709,25 @@ miptree_create(struct brw_context *brw,
if (mt == NULL)
return NULL;
+ if (intel_miptree_needs_fake_etc(brw, mt)) {
+ mesa_format decomp_format = intel_lower_compressed_format(brw, format);
+ mt->etc_format = format;
+ mt->shadow_mt = make_surface(brw, target, decomp_format, first_level,
+ last_level, width0, height0, depth0,
+ num_samples, tiling_flags,
+ mt_surf_usage(decomp_format),
+ alloc_flags, 0, NULL);
+
+ if (mt->shadow_mt == NULL) {
+ intel_miptree_release(&mt);
+ return NULL;
+ }
+
+ mt->shadow_mt->etc_format = MESA_FORMAT_NONE;
+ } else {
+ mt->etc_format = MESA_FORMAT_NONE;
+ }
+
if (needs_separate_stencil(brw, mt, format)) {
mt->stencil_mt =
make_surface(brw, target, MESA_FORMAT_S_UINT8, first_level, last_level,
@@ -719,9 +740,6 @@ miptree_create(struct brw_context *brw,
}
}
- mt->etc_format = (_mesa_is_format_color_format(format) && mt_fmt != format) ?
- format : MESA_FORMAT_NONE;
-
if (!(flags & MIPTREE_CREATE_NO_AUX))
intel_miptree_choose_aux_usage(brw, mt);
@@ -2426,8 +2444,11 @@ intel_miptree_finish_write(struct brw_context *brw,
switch (mt->aux_usage) {
case ISL_AUX_USAGE_NONE:
- if (mt->format == MESA_FORMAT_S_UINT8 && devinfo->gen <= 7)
+ if (mt->format == MESA_FORMAT_S_UINT8 && devinfo->gen <= 7) {
mt->shadow_needs_update = true;
+ } else if (intel_miptree_has_etc_shadow(brw, mt)) {
+ mt->shadow_needs_update = true;
+ }
break;
case ISL_AUX_USAGE_MCS:
@@ -3454,61 +3475,6 @@ intel_miptree_map_s8(struct brw_context *brw,
map->unmap = intel_miptree_unmap_s8;
}
-static void
-intel_miptree_unmap_etc(struct brw_context *brw,
- 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, slice, &image_x, &image_y);
-
- image_x += map->x;
- image_y += map->y;
-
- uint8_t *dst = intel_miptree_map_raw(brw, mt, GL_MAP_WRITE_BIT)
- + image_y * mt->surf.row_pitch_B
- + image_x * mt->cpp;
-
- if (mt->etc_format == MESA_FORMAT_ETC1_RGB8)
- _mesa_etc1_unpack_rgba8888(dst, mt->surf.row_pitch_B,
- map->ptr, map->stride,
- map->w, map->h);
- else
- _mesa_unpack_etc2_format(dst, mt->surf.row_pitch_B,
- map->ptr, map->stride,
- map->w, map->h, mt->etc_format, true);
-
- intel_miptree_unmap_raw(mt);
- free(map->buffer);
-}
-
-static void
-intel_miptree_map_etc(struct brw_context *brw,
- struct intel_mipmap_tree *mt,
- struct intel_miptree_map *map,
- unsigned int level,
- unsigned int slice)
-{
- assert(mt->etc_format != MESA_FORMAT_NONE);
- if (mt->etc_format == MESA_FORMAT_ETC1_RGB8) {
- assert(mt->format == MESA_FORMAT_R8G8B8X8_UNORM);
- }
-
- assert(map->mode & GL_MAP_WRITE_BIT);
- assert(map->mode & GL_MAP_INVALIDATE_RANGE_BIT);
-
- intel_miptree_access_raw(brw, mt, level, slice, true);
-
- map->stride = _mesa_format_row_stride(mt->etc_format, map->w);
- map->buffer = malloc(_mesa_format_image_size(mt->etc_format,
- map->w, map->h, 1));
- map->ptr = map->buffer;
- map->unmap = intel_miptree_unmap_etc;
-}
-
/**
* Mapping functions for packed depth/stencil miptrees backed by real separate
* miptrees for depth and stencil.
@@ -3781,9 +3747,6 @@ intel_miptree_map(struct brw_context *brw,
if (mt->format == MESA_FORMAT_S_UINT8) {
intel_miptree_map_s8(brw, mt, map, level, slice);
- } else if (mt->etc_format != MESA_FORMAT_NONE &&
- !(mode & BRW_MAP_DIRECT_BIT)) {
- intel_miptree_map_etc(brw, mt, map, level, slice);
} else if (mt->stencil_mt && !(mode & BRW_MAP_DIRECT_BIT)) {
intel_miptree_map_depthstencil(brw, mt, map, level, slice);
} else if (use_intel_mipree_map_blit(brw, mt, map)) {
@@ -3816,6 +3779,7 @@ intel_miptree_unmap(struct brw_context *brw,
unsigned int slice)
{
struct intel_miptree_map *map = mt->level[level].slice[slice].map;
+ int level_w, level_h;
assert(mt->surf.samples == 1);
@@ -3825,10 +3789,21 @@ intel_miptree_unmap(struct brw_context *brw,
DBG("%s: mt %p (%s) level %d slice %d\n", __func__,
mt, _mesa_get_format_name(mt->format), level, slice);
+ level_w = minify(mt->surf.phys_level0_sa.width,
+ level - mt->first_level);
+ level_h = minify(mt->surf.phys_level0_sa.height,
+ level - mt->first_level);
+
if (map->unmap)
map->unmap(brw, mt, map, level, slice);
intel_miptree_release_map(mt, level, slice);
+
+ if (intel_miptree_has_etc_shadow(brw, mt) && mt->shadow_needs_update) {
+ mt->shadow_needs_update = false;
+ intel_miptree_update_etc_shadow(brw, mt, level, slice, level_w,
+ level_h);
+ }
}
enum isl_surf_dim
@@ -3943,3 +3918,66 @@ intel_miptree_get_clear_color(const struct gen_device_info *devinfo,
return mt->fast_clear_color;
}
}
+
+static void
+intel_miptree_update_etc_shadow(struct brw_context *brw,
+ struct intel_mipmap_tree *mt,
+ unsigned int level,
+ unsigned int slice,
+ int level_w,
+ int level_h)
+{
+ ptrdiff_t etc_stride, shadow_stride;
+ void *mptr, *sptr;
+ struct intel_mipmap_tree *smt = mt->shadow_mt;
+
+ assert(intel_miptree_has_etc_shadow(brw, mt));
+
+ intel_miptree_map(brw, mt, level, slice, 0, 0, level_w, level_h,
+ GL_MAP_READ_BIT, &mptr, &etc_stride);
+ intel_miptree_map(brw, smt, level, slice, 0, 0, level_w, level_h,
+ GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT,
+ &sptr, &shadow_stride);
+
+ if (mt->format == MESA_FORMAT_ETC1_RGB8) {
+ _mesa_etc1_unpack_rgba8888(sptr, shadow_stride, mptr, etc_stride,
+ level_w, level_h);
+ } else {
+ /* destination and source images must have the same swizzle */
+ bool is_bgra = (smt->format == MESA_FORMAT_B8G8R8A8_SRGB);
+ _mesa_unpack_etc2_format(sptr, shadow_stride, mptr, etc_stride,
+ level_w, level_h, mt->format, is_bgra);
+ }
+
+ intel_miptree_unmap(brw, mt, level, slice);
+ intel_miptree_unmap(brw, smt, level, slice);
+}
+
+void
+intel_miptree_update_etc_shadow_levels(struct brw_context *brw,
+ struct intel_mipmap_tree *mt)
+{
+ struct intel_mipmap_tree *smt;
+ int num_slices;
+
+ assert(mt);
+ assert(mt->surf.size_B > 0);
+ assert(intel_miptree_has_etc_shadow(brw, mt));
+
+ smt = mt->shadow_mt;
+ num_slices = smt->surf.logical_level0_px.array_len;
+
+ for (int level = smt->first_level; level <= smt->last_level; level++) {
+ int level_w = minify(smt->surf.logical_level0_px.width,
+ level - smt->first_level);
+ int level_h = minify(smt->surf.logical_level0_px.height,
+ level - smt->first_level);
+
+ for (unsigned int slice = 0; slice < num_slices; slice++) {
+ intel_miptree_update_etc_shadow(brw, mt, level, slice, level_w,
+ level_h);
+ }
+ }
+
+ mt->shadow_needs_update = false;
+}
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
index 1a7507023a1..752aeaaf9b7 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
@@ -301,6 +301,8 @@ struct intel_mipmap_tree
*
* This miptree may be used for:
* - Stencil texturing (pre-BDW) as required by GL_ARB_stencil_texturing.
+ * - To store the decompressed ETC/EAC data in case we emulate the ETC
+ * compression on Gen 7 or earlier GPUs.
*/
struct intel_mipmap_tree *shadow_mt;
bool shadow_needs_update;
@@ -730,6 +732,28 @@ isl_memcpy_type
intel_miptree_get_memcpy_type(mesa_format tiledFormat, GLenum format, GLenum type,
uint32_t *cpp);
+static inline bool
+intel_miptree_needs_fake_etc(struct brw_context *brw,
+ struct intel_mipmap_tree *mt)
+{
+ const struct gen_device_info *devinfo = &brw->screen->devinfo;
+ bool is_etc = _mesa_is_format_etc2(mt->format) ||
+ (mt->format == MESA_FORMAT_ETC1_RGB8);
+
+ return devinfo->gen < 8 && !devinfo->is_baytrail && is_etc;
+}
+
+static inline bool
+intel_miptree_has_etc_shadow(struct brw_context *brw,
+ struct intel_mipmap_tree *mt)
+{
+ return intel_miptree_needs_fake_etc(brw, mt) && mt->shadow_mt;
+}
+
+void
+intel_miptree_update_etc_shadow_levels(struct brw_context *brw,
+ struct intel_mipmap_tree *mt);
+
#ifdef __cplusplus
}
#endif