drm/i915: Rebind the buffer if its alignment constraints changes with tiling
authorChris Wilson <chris@chris-wilson.co.uk>
Mon, 7 Mar 2011 10:42:03 +0000 (10:42 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 7 Mar 2011 11:02:16 +0000 (11:02 +0000)
Early gen3 and gen2 chipset do not have the relaxed per-surface tiling
constraints of the later chipsets, so we need to check that the GTT
alignment is correct for the new tiling. If it is not, we need to
rebind.

Reported-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_tiling.c

index d023b9b33d602246a2fb073cdb980a9d8ae3dada..456f4048483827d04c84375e0268351057688d15 100644 (file)
@@ -1178,6 +1178,9 @@ void i915_gem_detach_phys_object(struct drm_device *dev,
 void i915_gem_free_all_phys_object(struct drm_device *dev);
 void i915_gem_release(struct drm_device *dev, struct drm_file *file);
 
+uint32_t
+i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj);
+
 /* i915_gem_gtt.c */
 void i915_gem_restore_gtt_mappings(struct drm_device *dev);
 int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj);
index cf4f74c7c6fb6fb7fa8dcedc4839ce2910039846..36e66cc5225ebf23c090289562d3e1dc2ee14092 100644 (file)
@@ -1398,7 +1398,7 @@ i915_gem_get_gtt_alignment(struct drm_i915_gem_object *obj)
  * Return the required GTT alignment for an object, only taking into account
  * unfenced tiled surface requirements.
  */
-static uint32_t
+uint32_t
 i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj)
 {
        struct drm_device *dev = obj->base.dev;
index 22a32b9932c59c45761521415fb3d092d562e855..d64843e18df2c6d0565801c44ea96353b780c2d3 100644 (file)
@@ -349,14 +349,27 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
                        (obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end &&
                         i915_gem_object_fence_ok(obj, args->tiling_mode));
 
-               obj->tiling_changed = true;
-               obj->tiling_mode = args->tiling_mode;
-               obj->stride = args->stride;
+               /* Rebind if we need a change of alignment */
+               if (!obj->map_and_fenceable) {
+                       u32 unfenced_alignment =
+                               i915_gem_get_unfenced_gtt_alignment(obj);
+                       if (obj->gtt_offset & (unfenced_alignment - 1))
+                               ret = i915_gem_object_unbind(obj);
+               }
+
+               if (ret == 0) {
+                       obj->tiling_changed = true;
+                       obj->tiling_mode = args->tiling_mode;
+                       obj->stride = args->stride;
+               }
        }
+       /* we have to maintain this existing ABI... */
+       args->stride = obj->stride;
+       args->tiling_mode = obj->tiling_mode;
        drm_gem_object_unreference(&obj->base);
        mutex_unlock(&dev->struct_mutex);
 
-       return 0;
+       return ret;
 }
 
 /**