From e88cfbb95f631ca1275a5cef4ccc5aaffb70aaba Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Fri, 27 Jul 2012 20:42:31 -0700 Subject: [PATCH] intel: Support mapping multisample miptrees Add two new functions: intel_miptree_{map,unmap}_multisample, to which intel_miptree_{map,unmap} dispatch. Only mapping flat, renderbuffer-like miptrees are supported. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- .../drivers/dri/intel/intel_mipmap_tree.c | 114 +++++++++++++++++- .../drivers/dri/intel/intel_mipmap_tree.h | 18 +++ 2 files changed, 126 insertions(+), 6 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 9b0b4f7f1f8..e002c743b92 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -397,6 +397,8 @@ intel_miptree_create_for_renderbuffer(struct intel_context *intel, struct intel_mipmap_tree *mt; uint32_t depth = 1; enum intel_msaa_layout msaa_layout = INTEL_MSAA_LAYOUT_NONE; + const uint32_t singlesample_width = width; + const uint32_t singlesample_height = height; bool ok; if (num_samples > 1) { @@ -476,6 +478,9 @@ intel_miptree_create_for_renderbuffer(struct intel_context *intel, goto fail; } + mt->singlesample_width0 = singlesample_width; + mt->singlesample_height0 = singlesample_height; + return mt; fail: @@ -1576,6 +1581,93 @@ intel_miptree_unmap_singlesample(struct intel_context *intel, intel_miptree_release_map(mt, level, slice); } +static void +intel_miptree_map_multisample(struct intel_context *intel, + struct intel_mipmap_tree *mt, + unsigned int level, + unsigned int slice, + unsigned int x, + unsigned int y, + unsigned int w, + unsigned int h, + GLbitfield mode, + void **out_ptr, + int *out_stride) +{ + struct intel_miptree_map *map; + + assert(mt->num_samples > 1); + + /* Only flat, renderbuffer-like miptrees are supported. */ + if (mt->target != GL_TEXTURE_2D || + mt->first_level != 0 || + mt->last_level != 0) { + _mesa_problem(&intel->ctx, "attempt to map a multisample miptree for " + "which (target, first_level, last_level != " + "(GL_TEXTURE_2D, 0, 0)"); + goto fail; + } + + map = intel_miptree_attach_map(mt, level, slice, x, y, w, h, mode); + if (!map) + goto fail; + + if (!mt->singlesample_mt) { + mt->singlesample_mt = + intel_miptree_create_for_renderbuffer(intel, + mt->format, + mt->singlesample_width0, + mt->singlesample_height0, + 0 /*num_samples*/); + if (!mt->singlesample_mt) + goto fail; + + map->singlesample_mt_is_tmp = true; + mt->need_downsample = true; + } + + if (mode & GL_MAP_INVALIDATE_RANGE_BIT) + mt->need_downsample = false; + + intel_miptree_downsample(intel, mt); + intel_miptree_map_singlesample(intel, mt->singlesample_mt, + level, slice, + x, y, w, h, + mode, + out_ptr, out_stride); + return; + +fail: + intel_miptree_release_map(mt, level, slice); + *out_ptr = NULL; + *out_stride = 0; +} + +static void +intel_miptree_unmap_multisample(struct intel_context *intel, + struct intel_mipmap_tree *mt, + unsigned int level, + unsigned int slice) +{ + struct intel_miptree_map *map = mt->level[level].slice[slice].map; + + assert(mt->num_samples > 1); + + if (!map) + return; + + intel_miptree_unmap_singlesample(intel, mt->singlesample_mt, level, slice); + + mt->need_downsample = false; + if (map->mode & GL_MAP_WRITE_BIT) + intel_miptree_upsample(intel, mt); + + if (map->singlesample_mt_is_tmp) + intel_miptree_release(&mt->singlesample_mt); + + intel_miptree_release_map(mt, level, slice); +} + void intel_miptree_map(struct intel_context *intel, struct intel_mipmap_tree *mt, @@ -1589,11 +1681,18 @@ intel_miptree_map(struct intel_context *intel, void **out_ptr, int *out_stride) { - intel_miptree_map_singlesample(intel, mt, - level, slice, - x, y, w, h, - mode, - out_ptr, out_stride); + if (mt->num_samples <= 1) + intel_miptree_map_singlesample(intel, mt, + level, slice, + x, y, w, h, + mode, + out_ptr, out_stride); + else + intel_miptree_map_multisample(intel, mt, + level, slice, + x, y, w, h, + mode, + out_ptr, out_stride); } void @@ -1602,5 +1701,8 @@ intel_miptree_unmap(struct intel_context *intel, unsigned int level, unsigned int slice) { - intel_miptree_unmap_singlesample(intel, mt, level, slice); + if (mt->num_samples <= 1) + intel_miptree_unmap_singlesample(intel, mt, level, slice); + else + intel_miptree_unmap_multisample(intel, mt, level, slice); } diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index 12c7b6afcb7..0d0e7579460 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -79,6 +79,12 @@ struct intel_miptree_map { void *ptr; /** Stride of the mapping. */ int stride; + + /** + * intel_mipmap_tree::singlesample_mt is temporary storage that persists + * only for the duration of the map. + */ + bool singlesample_mt_is_tmp; }; /** @@ -211,6 +217,18 @@ struct intel_mipmap_tree GLuint num_samples; bool compressed; + /** + * If num_samples > 0, then singlesample_width0 is the value that width0 + * would have if instead a singlesample miptree were created. Note that, + * for non-interleaved msaa layouts, the two values are the same. + * + * If num_samples == 0, then singlesample_width0 is undefined. + */ + uint32_t singlesample_width0; + + /** \see singlesample_width0 */ + uint32_t singlesample_height0; + /** * For 1D array, 2D array, cube, and 2D multisampled surfaces on Gen7: true * if the surface only contains LOD 0, and hence no space is for LOD's -- 2.30.2