i965: Don't call the blitter on addresses it can't handle.
authorEric Anholt <eric@anholt.net>
Mon, 23 Dec 2013 23:30:03 +0000 (15:30 -0800)
committerEric Anholt <eric@anholt.net>
Thu, 9 Jan 2014 07:23:00 +0000 (15:23 +0800)
Noticed by tex3d-maxsize on my next commit to check that our addresses
don't overflow.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Anuj Phogat <anuj.phogat@gmail.com>
src/mesa/drivers/dri/i965/intel_blit.c
src/mesa/drivers/dri/i965/intel_mipmap_tree.c

index 7bc289f350eb7e9aa3e6f879ada57e53b020b048..13cc77792e479d5ef361145a9b042c3484f83ce5 100644 (file)
@@ -229,12 +229,32 @@ intel_miptree_blit(struct brw_context *brw,
    src_x += src_image_x;
    src_y += src_image_y;
 
+   /* The blitter interprets the 16-bit src x/y as a signed 16-bit value,
+    * where negative values are invalid.  The values we're working with are
+    * unsigned, so make sure we don't overflow.
+    */
+   if (src_x >= 32768 || src_y >= 32768) {
+      perf_debug("Falling back due to >=32k src offset (%d, %d)\n",
+                 src_x, src_y);
+      return false;
+   }
+
    uint32_t dst_image_x, dst_image_y;
    intel_miptree_get_image_offset(dst_mt, dst_level, dst_slice,
                                   &dst_image_x, &dst_image_y);
    dst_x += dst_image_x;
    dst_y += dst_image_y;
 
+   /* The blitter interprets the 16-bit destination x/y as a signed 16-bit
+    * value.  The values we're working with are unsigned, so make sure we
+    * don't overflow.
+    */
+   if (dst_x >= 32768 || dst_y >= 32768) {
+      perf_debug("Falling back due to >=32k dst offset (%d, %d)\n",
+                 dst_x, dst_y);
+      return false;
+   }
+
    if (!intelEmitCopyBlit(brw,
                           src_mt->cpp,
                           src_pitch,
index de47143397a1a69a529fa31841a97a654cd86a24..0818226f3c4a2ead5688fcae5c7f98b90a8c3f4a 100644 (file)
@@ -443,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;
@@ -2233,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,
@@ -2276,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) {