/**************************************************************************
- *
+ *
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
- *
+ *
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
+ *
**************************************************************************/
#include <GL/gl.h>
assert(brw->gen == 7);
return INTEL_MSAA_LAYOUT_UMS;
} else {
- /* For now, if we're going to be texturing from this surface,
- * force UMS, so that the shader doesn't have to do different things
- * based on whether there's a multisample control surface needing sampled first.
- * We can't just blindly read the MCS surface in all cases because:
- *
- * From the Ivy Bridge PRM, Vol4 Part1 p77 ("MCS Enable"):
- *
- * If this field is disabled and the sampling engine <ld_mcs> message
- * is issued on this surface, the MCS surface may be accessed. Software
- * must ensure that the surface is defined to avoid GTT errors.
- */
- if (target == GL_TEXTURE_2D_MULTISAMPLE ||
- target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) {
- return INTEL_MSAA_LAYOUT_UMS;
- } else {
- return INTEL_MSAA_LAYOUT_CMS;
- }
+ return INTEL_MSAA_LAYOUT_CMS;
}
}
}
struct intel_mipmap_tree *mt)
{
/* MCS support does not exist prior to Gen7 */
- if (brw->gen < 7)
+ if (brw->gen < 7 || brw->gen >= 8)
return false;
/* MCS is only supported for color buffers */
mt->logical_width0 = width0;
mt->logical_height0 = height0;
mt->logical_depth0 = depth0;
- mt->mcs_state = INTEL_MCS_STATE_NONE;
+ mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_NO_MCS;
/* The cpp is bytes per (1, blockheight)-sized block for compressed
* textures. This is why you'll see divides by blockheight all over
mt->num_samples = num_samples;
mt->compressed = _mesa_is_format_compressed(format);
mt->msaa_layout = INTEL_MSAA_LAYOUT_NONE;
- mt->refcount = 1;
+ mt->refcount = 1;
if (num_samples > 1) {
/* Adjust width/height/depth for MSAA */
if (minimum_pitch < 64)
return I915_TILING_NONE;
- if (ALIGN(minimum_pitch, 512) >= 32768) {
+ if (ALIGN(minimum_pitch, 512) >= 32768 ||
+ mt->total_width >= 32768 || mt->total_height >= 32768) {
perf_debug("%dx%d miptree too large to blit, falling back to untiled",
mt->total_width, mt->total_height);
return I915_TILING_NONE;
if (brw->gen != 7 && mt->cpp >= 16)
return I915_TILING_X;
+ /* From the Ivy Bridge PRM, Vol4 Part1 2.12.2.1 (SURFACE_STATE for most
+ * messages), on p64, under the heading "Surface Vertical Alignment":
+ *
+ * This field must be set to VALIGN_4 for all tiled Y Render Target
+ * surfaces.
+ *
+ * So if the surface is renderable and uses a vertical alignment of 2,
+ * force it to be X tiled. This is somewhat conservative (it's possible
+ * that the client won't ever render to this surface), but it's difficult
+ * to know that ahead of time. And besides, since we use a vertical
+ * alignment of 4 as often as we can, this shouldn't happen very often.
+ */
+ if (brw->gen == 7 && mt->align_h == 2 &&
+ brw->format_supported_as_render_target[format]) {
+ return I915_TILING_X;
+ }
+
return I915_TILING_Y | I915_TILING_X;
}
return NULL;
}
+
+ if (mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) {
+ if (!intel_miptree_alloc_mcs(brw, mt, num_samples)) {
+ intel_miptree_release(&mt);
+ return NULL;
+ }
+ }
+
/* If this miptree is capable of supporting fast color clears, set
- * mcs_state appropriately to ensure that fast clears will occur.
+ * fast_clear_state appropriately to ensure that fast clears will occur.
* Allocation of the MCS miptree will be deferred until the first fast
* clear actually occurs.
*/
if (intel_is_non_msrt_mcs_buffer_supported(brw, mt))
- mt->mcs_state = INTEL_MCS_STATE_RESOLVED;
+ mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED;
return mt;
}
0, 0,
width, height, 1,
true, 0 /* num_samples */);
- if (!mt)
+ if (!mt) {
+ free(region);
return mt;
+ }
region->cpp = mt->cpp;
region->width = width;
singlesample_mt->region->name = region->name;
/* If this miptree is capable of supporting fast color clears, set
- * mcs_state appropriately to ensure that fast clears will occur.
+ * fast_clear_state appropriately to ensure that fast clears will occur.
* Allocation of the MCS miptree will be deferred until the first fast
* clear actually occurs.
*/
if (intel_is_non_msrt_mcs_buffer_supported(brw, singlesample_mt))
- singlesample_mt->mcs_state = INTEL_MCS_STATE_RESOLVED;
+ singlesample_mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED;
if (num_samples == 0)
return singlesample_mt;
if (!singlesample_mt)
return NULL;
- intel_region_reference(&singlesample_mt->region, region);
+ /* If this miptree is capable of supporting fast color clears, set
+ * mcs_state appropriately to ensure that fast clears will occur.
+ * Allocation of the MCS miptree will be deferred until the first fast
+ * clear actually occurs.
+ */
+ if (intel_is_non_msrt_mcs_buffer_supported(intel, singlesample_mt))
+ singlesample_mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED;
if (num_samples == 0)
return singlesample_mt;
multisample_mt->singlesample_mt = singlesample_mt;
multisample_mt->need_downsample = false;
- intel_region_reference(&multisample_mt->region, region);
-
if (intel->is_front_buffer_rendering && buffer_type == __DRI_IMAGE_BUFFER_FRONT) {
intel_miptree_upsample(intel, multisample_mt);
}
goto fail;
}
- if (mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) {
- ok = intel_miptree_alloc_mcs(brw, mt, num_samples);
- if (!ok)
- goto fail;
- }
-
return mt;
fail:
*
* "The MCS surface must be stored as Tile Y."
*/
- mt->mcs_state = INTEL_MCS_STATE_MSAA;
mt->mcs_mt = intel_miptree_create(brw,
mt->target,
format,
void *data = intel_miptree_map_raw(brw, mt->mcs_mt);
memset(data, 0xff, mt->mcs_mt->region->bo->size);
intel_miptree_unmap_raw(brw, mt->mcs_mt);
+ mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_CLEAR;
return mt->mcs_mt;
}
intel_miptree_resolve_color(struct brw_context *brw,
struct intel_mipmap_tree *mt)
{
- switch (mt->mcs_state) {
- case INTEL_MCS_STATE_NONE:
- case INTEL_MCS_STATE_MSAA:
- case INTEL_MCS_STATE_RESOLVED:
+ switch (mt->fast_clear_state) {
+ case INTEL_FAST_CLEAR_STATE_NO_MCS:
+ case INTEL_FAST_CLEAR_STATE_RESOLVED:
/* No resolve needed */
break;
- case INTEL_MCS_STATE_UNRESOLVED:
- case INTEL_MCS_STATE_CLEAR:
- brw_blorp_resolve_color(brw, mt);
+ case INTEL_FAST_CLEAR_STATE_UNRESOLVED:
+ case INTEL_FAST_CLEAR_STATE_CLEAR:
+ /* Fast color clear resolves only make sense for non-MSAA buffers. */
+ if (mt->msaa_layout == INTEL_MSAA_LAYOUT_NONE)
+ brw_blorp_resolve_color(brw, mt);
break;
}
}
* process or another miptree.
*
* Fast color clears are unsafe with shared buffers, so we need to resolve and
- * then discard the MCS buffer, if present. We also set the mcs_state to
- * INTEL_MCS_STATE_NONE to ensure that no MCS buffer gets allocated in the
- * future.
+ * then discard the MCS buffer, if present. We also set the fast_clear_state
+ * to INTEL_FAST_CLEAR_STATE_NO_MCS to ensure that no MCS buffer gets
+ * allocated in the future.
*/
void
intel_miptree_make_shareable(struct brw_context *brw,
if (mt->mcs_mt) {
intel_miptree_resolve_color(brw, mt);
intel_miptree_release(&mt->mcs_mt);
- mt->mcs_state = INTEL_MCS_STATE_NONE;
+ mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_NO_MCS;
}
}
*map = NULL;
}
+static bool
+can_blit_slice(struct intel_mipmap_tree *mt,
+ 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);
+ if (image_x >= 32768 || image_y >= 32768)
+ return false;
+
+ if (mt->region->pitch >= 32768)
+ return false;
+
+ return true;
+}
+
static void
intel_miptree_map_singlesample(struct brw_context *brw,
struct intel_mipmap_tree *mt,
!mt->compressed &&
(mt->region->tiling == I915_TILING_X ||
(brw->gen >= 6 && mt->region->tiling == I915_TILING_Y)) &&
- mt->region->pitch < 32768) {
+ can_blit_slice(mt, level, slice)) {
intel_miptree_map_blit(brw, mt, map, level, slice);
} else if (mt->region->tiling != I915_TILING_NONE &&
mt->region->bo->size >= brw->max_gtt_map_object_size) {
- assert(mt->region->pitch < 32768);
+ assert(can_blit_slice(mt, level, slice));
intel_miptree_map_blit(brw, mt, map, level, slice);
#ifdef __SSE4_1__
} else if (!(mode & GL_MAP_WRITE_BIT) && !mt->compressed) {