i965: Don't call the blitter on addresses it can't handle.
[mesa.git] / src / mesa / drivers / dri / i965 / intel_mipmap_tree.c
index bb986bddeb594937282b8784918c8553324d9204..0818226f3c4a2ead5688fcae5c7f98b90a8c3f4a 100644 (file)
@@ -1,8 +1,8 @@
 /**************************************************************************
- * 
+ *
  * 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.
@@ -22,7 +22,7 @@
  * 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>
@@ -99,23 +99,7 @@ compute_msaa_layout(struct brw_context *brw, gl_format format, GLenum target)
          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;
       }
    }
 }
@@ -202,7 +186,7 @@ intel_is_non_msrt_mcs_buffer_supported(struct brw_context *brw,
                                        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 */
@@ -266,7 +250,7 @@ intel_miptree_create_layout(struct brw_context *brw,
    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
@@ -279,7 +263,7 @@ intel_miptree_create_layout(struct brw_context *brw,
    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 */
@@ -459,7 +443,8 @@ intel_miptree_choose_tiling(struct brw_context *brw,
    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;
@@ -478,6 +463,23 @@ intel_miptree_choose_tiling(struct brw_context *brw,
    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;
 }
 
@@ -594,13 +596,21 @@ intel_miptree_create(struct brw_context *brw,
        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;
 }
@@ -636,8 +646,10 @@ intel_miptree_create_for_bo(struct brw_context *brw,
                                     0, 0,
                                     width, height, 1,
                                     true, 0 /* num_samples */);
-   if (!mt)
+   if (!mt) {
+      free(region);
       return mt;
+   }
 
    region->cpp = mt->cpp;
    region->width = width;
@@ -694,12 +706,12 @@ intel_miptree_create_for_dri2_buffer(struct brw_context *brw,
    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;
@@ -760,7 +772,13 @@ intel_miptree_create_for_image_buffer(struct brw_context *intel,
    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;
@@ -778,8 +796,6 @@ intel_miptree_create_for_image_buffer(struct brw_context *intel,
    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);
    }
@@ -810,12 +826,6 @@ intel_miptree_create_for_renderbuffer(struct brw_context *brw,
          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:
@@ -1228,7 +1238,6 @@ intel_miptree_alloc_mcs(struct brw_context *brw,
     *
     *     "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,
@@ -1254,6 +1263,7 @@ intel_miptree_alloc_mcs(struct brw_context *brw,
    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;
 }
@@ -1506,15 +1516,16 @@ void
 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;
    }
 }
@@ -1525,9 +1536,9 @@ intel_miptree_resolve_color(struct brw_context *brw,
  * 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,
@@ -1543,7 +1554,7 @@ 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;
    }
 }
 
@@ -2223,6 +2234,22 @@ intel_miptree_release_map(struct intel_mipmap_tree *mt,
    *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,
@@ -2266,11 +2293,11 @@ intel_miptree_map_singlesample(struct brw_context *brw,
             !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) {