summaryrefslogtreecommitdiff
path: root/shared-core/i915_irq.c
diff options
context:
space:
mode:
authorMichel Dänzer <michel@tungstengraphics.com>2007-02-19 12:27:54 +0100
committerMichel Dänzer <michel@tungstengraphics.com>2007-02-19 15:08:40 +0100
commit6f89584e136211d7c4c69d88005f0e70393274f8 (patch)
tree70419c2c8a2394c0d6cd96468e1c9d4391e455a4 /shared-core/i915_irq.c
parent34aa3393d04da1201815143c92a5bef83bf0d585 (diff)
i915: Improved page flipping support, including triple buffering.
Pages are tracked independently on each pipe. Bump the minor version for 3D clients to know page flipping is usable, and bump driver date.
Diffstat (limited to 'shared-core/i915_irq.c')
-rw-r--r--shared-core/i915_irq.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index e373a8df..cd2adbf3 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -47,12 +47,12 @@ static void i915_vblank_tasklet(drm_device_t *dev)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long irqflags;
struct list_head *list, *tmp, hits, *hit;
- int nhits, nrects, slice[2], upper[2], lower[2], i;
+ int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
unsigned counter[2] = { atomic_read(&dev->vbl_received),
atomic_read(&dev->vbl_received2) };
drm_drawable_info_t *drw;
drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
- u32 cpp = dev_priv->cpp;
+ u32 cpp = dev_priv->cpp, offsets[3];
u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB)
@@ -144,6 +144,11 @@ static void i915_vblank_tasklet(drm_device_t *dev)
lower[0] = sarea_priv->pipeA_y + slice[0];
lower[1] = sarea_priv->pipeB_y + slice[0];
+ offsets[0] = sarea_priv->front_offset;
+ offsets[1] = sarea_priv->back_offset;
+ offsets[2] = sarea_priv->third_offset;
+ num_pages = sarea_priv->third_handle ? 3 : 2;
+
spin_lock(&dev->drw_lock);
/* Emit blits for buffer swaps, partitioning both outputs into as many
@@ -161,7 +166,7 @@ static void i915_vblank_tasklet(drm_device_t *dev)
drm_i915_vbl_swap_t *swap_hit =
list_entry(hit, drm_i915_vbl_swap_t, head);
drm_clip_rect_t *rect;
- int num_rects, pipe;
+ int num_rects, pipe, front, back;
unsigned short top, bottom;
drw = drm_get_drawable_info(dev, swap_hit->drw_id);
@@ -174,6 +179,9 @@ static void i915_vblank_tasklet(drm_device_t *dev)
top = upper[pipe];
bottom = lower[pipe];
+ front = (dev_priv->current_page >> (2 * pipe)) & 0x3;
+ back = (front + 1) % num_pages;
+
for (num_rects = drw->num_rects; num_rects--; rect++) {
int y1 = max(rect->y1, top);
int y2 = min(rect->y2, bottom);
@@ -187,10 +195,10 @@ static void i915_vblank_tasklet(drm_device_t *dev)
OUT_RING(pitchropcpp);
OUT_RING((y1 << 16) | rect->x1);
OUT_RING((y2 << 16) | rect->x2);
- OUT_RING(sarea_priv->front_offset);
+ OUT_RING(offsets[front]);
OUT_RING((y1 << 16) | rect->x1);
OUT_RING(pitchropcpp & 0xffff);
- OUT_RING(sarea_priv->back_offset);
+ OUT_RING(offsets[back]);
ADVANCE_LP_RING();
}