@@ -871,8 +871,8 @@ void i915_gem_release_mmap(struct drm_gem_object *obj);
void i915_gem_lastclose(struct drm_device *dev);
uint32_t i915_get_gem_seqno(struct drm_device *dev);
bool i915_seqno_passed(uint32_t seq1, uint32_t seq2);
-int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
-int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
+int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, int pipelined);
+int i915_gem_object_put_fence_reg(struct drm_gem_object *obj, int pipelined);
void i915_gem_retire_requests(struct drm_device *dev);
void i915_gem_retire_work_handler(struct work_struct *work);
void i915_gem_clflush_object(struct drm_gem_object *obj);
@@ -49,7 +49,8 @@ static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *o
static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
unsigned alignment);
-static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
+static void i915_gem_clear_fence_reg(struct drm_gem_object *obj,
+ int pipelined);
static int i915_gem_evict_something(struct drm_device *dev, int min_size);
static int i915_gem_evict_from_inactive_list(struct drm_device *dev);
static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
@@ -1215,7 +1216,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
/* Need a new fence register? */
if (obj_priv->tiling_mode != I915_TILING_NONE) {
- ret = i915_gem_object_get_fence_reg(obj);
+ ret = i915_gem_object_get_fence_reg(obj, 0);
if (ret)
goto unlock;
}
@@ -2075,7 +2076,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
/* release the fence reg _after_ flushing */
if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
- i915_gem_clear_fence_reg(obj);
+ i915_gem_clear_fence_reg(obj, 0);
if (obj_priv->agp_mem != NULL) {
drm_unbind_agp(obj_priv->agp_mem);
@@ -2426,7 +2427,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
}
-static int i915_find_fence_reg(struct drm_device *dev)
+static int i915_find_fence_reg(struct drm_device *dev, int pipelined)
{
struct drm_i915_fence_reg *reg = NULL;
struct drm_i915_gem_object *obj_priv = NULL;
@@ -2471,7 +2472,7 @@ static int i915_find_fence_reg(struct drm_device *dev)
* under us.
*/
drm_gem_object_reference(obj);
- ret = i915_gem_object_put_fence_reg(obj);
+ ret = i915_gem_object_put_fence_reg(obj, pipelined);
drm_gem_object_unreference(obj);
if (ret != 0)
return ret;
@@ -2493,7 +2494,7 @@ static int i915_find_fence_reg(struct drm_device *dev)
* and tiling format.
*/
int
-i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
+i915_gem_object_get_fence_reg(struct drm_gem_object *obj, int pipelined)
{
struct drm_device *dev = obj->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2528,7 +2529,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
break;
}
- ret = i915_find_fence_reg(dev);
+ ret = i915_find_fence_reg(dev, pipelined);
if (ret < 0)
return ret;
@@ -2538,6 +2539,12 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
reg->obj = obj;
+ if (pipelined && reg->last_rendering_seqno != 0) {
+ ret = i915_wait_request(dev, reg->last_rendering_seqno);
+ if (ret != 0)
+ return ret;
+ }
+
if (IS_I965G(dev))
i965_write_fence_reg(reg);
else if (IS_I9XX(dev))
@@ -2559,7 +2566,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
* data structures in dev_priv and obj_priv.
*/
static void
-i915_gem_clear_fence_reg(struct drm_gem_object *obj)
+i915_gem_clear_fence_reg(struct drm_gem_object *obj, int pipelined)
{
struct drm_device *dev = obj->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -2567,6 +2574,8 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
struct drm_i915_fence_reg *reg =
&dev_priv->fence_regs[obj_priv->fence_reg];
+ if (pipelined)
+ goto end;
if (IS_I965G(dev))
I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
else {
@@ -2581,6 +2590,7 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
I915_WRITE(fence_reg, 0);
}
+end:
reg->obj = NULL;
obj_priv->fence_reg = I915_FENCE_REG_NONE;
list_del_init(®->lru_list);
@@ -2595,7 +2605,8 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
* data structures in dev_priv and obj_priv.
*/
int
-i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
+i915_gem_object_put_fence_reg(struct drm_gem_object *obj,
+ int pipelined)
{
struct drm_i915_gem_object *obj_priv = obj->driver_private;
@@ -2611,13 +2622,13 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
if (obj_priv->fenced_gpu_access) {
int ret;
- ret = i915_gem_object_flush_gpu_write_domain(obj, 0);
+ ret = i915_gem_object_flush_gpu_write_domain(obj, pipelined);
if (ret != 0)
return ret;
}
i915_gem_object_flush_gtt_write_domain(obj);
- i915_gem_clear_fence_reg (obj);
+ i915_gem_clear_fence_reg(obj, pipelined);
return 0;
}
@@ -3317,7 +3328,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
* properly handle blits to/from tiled surfaces.
*/
if (need_fence) {
- ret = i915_gem_object_get_fence_reg(obj);
+ ret = i915_gem_object_get_fence_reg(obj, 1);
if (ret != 0) {
if (ret != -EBUSY && ret != -ERESTARTSYS)
DRM_ERROR("Failure to install fence: %d\n",
@@ -362,7 +362,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
ret = i915_gem_object_unbind(obj);
else
- ret = i915_gem_object_put_fence_reg(obj);
+ ret = i915_gem_object_put_fence_reg(obj, 0);
if (ret != 0) {
WARN(ret != -ERESTARTSYS,
"failed to reset object for tiling switch");
@@ -1149,7 +1149,9 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj)
*/
if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
obj_priv->tiling_mode != I915_TILING_NONE) {
- ret = i915_gem_object_get_fence_reg(obj);
+ /* FIXME: Check whether pipelined fencing makes
+ * sense for the pageflip. */
+ ret = i915_gem_object_get_fence_reg(obj, 0);
if (ret != 0) {
i915_gem_object_unpin(obj);
return ret;