From f4873babdc27f697df9f4642209eca21a02ac476 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Thu, 19 Jul 2012 09:45:14 -0700 Subject: [PATCH] intel: Allocate miptree for multisample DRI2 buffers Immediately after obtaining, with DRI2GetBuffersWithFormat, the DRM buffer handle for a DRI2 buffer, we wrap that DRM buffer handle with a region and a miptree. This patch additionally allocates an accompanying multisample miptree if the DRI2 buffer is multisampled. Since we do not yet advertise multisample GL configs, the code for allocating the multisample miptree is currently inactive. This patch adds the following fields to intel_mipmap_tree: singlesample_mt needs_downsample and the following function stubs: intel_miptree_downsample intel_miptree_upsample Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_context.c | 27 ++++-- .../drivers/dri/intel/intel_mipmap_tree.c | 84 +++++++++++++++++++ .../drivers/dri/intel/intel_mipmap_tree.h | 59 +++++++++++++ 3 files changed, 162 insertions(+), 8 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 3b67f87c21a..759fead2d42 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -926,14 +926,24 @@ intel_process_dri2_buffer(struct intel_context *intel, if (!rb) return; + unsigned num_samples = rb->Base.Base.NumSamples; + /* We try to avoid closing and reopening the same BO name, because the first * use of a mapping of the buffer involves a bunch of page faulting which is * moderately expensive. */ - if (rb->mt && - rb->mt->region && - rb->mt->region->name == buffer->name) - return; + if (num_samples == 0) { + if (rb->mt && + rb->mt->region && + rb->mt->region->name == buffer->name) + return; + } else { + if (rb->mt && + rb->mt->singlesample_mt && + rb->mt->singlesample_mt->region && + rb->mt->singlesample_mt->region->name == buffer->name) + return; + } if (unlikely(INTEL_DEBUG & DEBUG_DRI)) { fprintf(stderr, @@ -953,9 +963,10 @@ intel_process_dri2_buffer(struct intel_context *intel, if (!region) return; - rb->mt = intel_miptree_create_for_region(intel, - GL_TEXTURE_2D, - intel_rb_format(rb), - region); + rb->mt = intel_miptree_create_for_dri2_buffer(intel, + buffer->attachment, + intel_rb_format(rb), + num_samples, + region); intel_region_release(®ion); } diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index b6ecbca9162..5da24f2c9c6 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -25,6 +25,9 @@ * **************************************************************************/ +#include +#include + #include "intel_batchbuffer.h" #include "intel_context.h" #include "intel_mipmap_tree.h" @@ -324,6 +327,62 @@ compute_msaa_layout(struct intel_context *intel, gl_format format) } } +/** + * For a singlesample DRI2 buffer, this simply wraps the given region with a miptree. + * + * For a multisample DRI2 buffer, this wraps the given region with + * a singlesample miptree, then creates a multisample miptree into which the + * singlesample miptree is embedded as a child. + */ +struct intel_mipmap_tree* +intel_miptree_create_for_dri2_buffer(struct intel_context *intel, + unsigned dri_attachment, + gl_format format, + uint32_t num_samples, + struct intel_region *region) +{ + struct intel_mipmap_tree *singlesample_mt = NULL; + struct intel_mipmap_tree *multisample_mt = NULL; + GLenum base_format = _mesa_get_format_base_format(format); + + /* Only the front and back buffers, which are color buffers, are shared + * through DRI2. + */ + assert(dri_attachment == __DRI_BUFFER_BACK_LEFT || + dri_attachment == __DRI_BUFFER_FRONT_LEFT || + dri_attachment == __DRI_BUFFER_FAKE_FRONT_LEFT); + assert(base_format == GL_RGB || base_format == GL_RGBA); + + singlesample_mt = intel_miptree_create_for_region(intel, GL_TEXTURE_2D, + format, region); + if (!singlesample_mt) + return NULL; + + if (num_samples == 0) + return singlesample_mt; + + multisample_mt = intel_miptree_create_for_renderbuffer(intel, + format, + region->width, + region->height, + num_samples); + if (!multisample_mt) { + intel_miptree_release(&singlesample_mt); + return NULL; + } + + multisample_mt->singlesample_mt = singlesample_mt; + multisample_mt->need_downsample = false; + + if (intel->is_front_buffer_rendering && + (dri_attachment == __DRI_BUFFER_FRONT_LEFT || + dri_attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)) { + intel_miptree_upsample(intel, multisample_mt); + } + + return multisample_mt; +} + struct intel_mipmap_tree* intel_miptree_create_for_renderbuffer(struct intel_context *intel, gl_format format, @@ -454,6 +513,7 @@ intel_miptree_release(struct intel_mipmap_tree **mt) intel_miptree_release(&(*mt)->stencil_mt); intel_miptree_release(&(*mt)->hiz_mt); intel_miptree_release(&(*mt)->mcs_mt); + intel_miptree_release(&(*mt)->singlesample_mt); intel_resolve_map_clear(&(*mt)->hiz_map); for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { @@ -899,6 +959,30 @@ intel_miptree_all_slices_resolve_depth(struct intel_context *intel, GEN6_HIZ_OP_DEPTH_RESOLVE); } +/** + * \brief Downsample from mt to mt->singlesample_mt. + * + * If the miptree needs no downsample, then skip. + */ +void +intel_miptree_downsample(struct intel_context *intel, + struct intel_mipmap_tree *mt) +{ + /* TODO: stub */ +} + +/** + * \brief Upsample from mt->singlesample_mt to mt. + * + * The upsample is done unconditionally. + */ +void +intel_miptree_upsample(struct intel_context *intel, + struct intel_mipmap_tree *mt) +{ + /* TODO: stub */ +} + static void intel_miptree_map_gtt(struct intel_context *intel, struct intel_mipmap_tree *mt, diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index bfeb69c36f8..12c7b6afcb7 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -247,6 +247,50 @@ struct intel_mipmap_tree */ uint32_t offset; + /** + * \brief Singlesample miptree. + * + * This is used under two cases. + * + * --- Case 1: As persistent singlesample storage for multisample window + * system front and back buffers --- + * + * Suppose that the window system FBO was created with a multisample + * config. Let `back_irb` be the `intel_renderbuffer` for the FBO's back + * buffer. Then `back_irb` contains two miptrees: a parent multisample + * miptree (back_irb->mt) and a child singlesample miptree + * (back_irb->mt->singlesample_mt). The DRM buffer shared with DRI2 + * belongs to `back_irb->mt->singlesample_mt` and contains singlesample + * data. The singlesample miptree is created at the same time as and + * persists for the lifetime of its parent multisample miptree. + * + * When access to the singlesample data is needed, such as at + * eglSwapBuffers and glReadPixels, an automatic downsample occurs from + * `back_rb->mt` to `back_rb->mt->singlesample_mt` when necessary. + * + * This description of the back buffer applies analogously to the front + * buffer. + * + * + * --- Case 2: As temporary singlesample storage for mapping multisample + * miptrees --- + * + * Suppose the intel_miptree_map is called on a multisample miptree, `mt`, + * for which case 1 does not apply (that is, `mt` does not belong to + * a front or back buffer). Then `mt->singlesample_mt` is null at the + * start of the call. intel_miptree_map will create a temporary + * singlesample miptree, store it at `mt->singlesample_mt`, downsample from + * `mt` to `mt->singlesample_mt` if necessary, then map + * `mt->singlesample_mt`. The temporary miptree is later deleted during + * intel_miptree_unmap. + */ + struct intel_mipmap_tree *singlesample_mt; + + /** + * \brief A downsample is needed from this miptree to singlesample_mt. + */ + bool need_downsample; + /** * \brief HiZ miptree * @@ -325,6 +369,13 @@ intel_miptree_create_for_region(struct intel_context *intel, gl_format format, struct intel_region *region); +struct intel_mipmap_tree* +intel_miptree_create_for_dri2_buffer(struct intel_context *intel, + unsigned dri_attachment, + gl_format format, + uint32_t num_samples, + struct intel_region *region); + /** * Create a miptree appropriate as the storage for a non-texture renderbuffer. * The miptree has the following properties: @@ -484,6 +535,14 @@ intel_miptree_all_slices_resolve_depth(struct intel_context *intel, /**\}*/ +void +intel_miptree_downsample(struct intel_context *intel, + struct intel_mipmap_tree *mt); + +void +intel_miptree_upsample(struct intel_context *intel, + struct intel_mipmap_tree *mt); + /* i915_mipmap_tree.c: */ void i915_miptree_layout(struct intel_mipmap_tree *mt); -- 2.30.2