From 3cb8acd5abcb410ab2982f55aec94b5a793a47d6 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 11 Sep 2007 03:48:46 -0700 Subject: Disambiguate planes & pipes for swap operations This mod makes the SAREA track plane to pipe mappings and corrects the name of the plane info variables (they were mislabeled as pipe info since until now all code assumed a direct mapping between planes and pipes). It also updates the flip ioctl argument to take a set of planes rather than pipes, since planes are flipped while pipes generate vblank events. --- shared-core/i915_irq.c | 66 ++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 31 deletions(-) (limited to 'shared-core/i915_irq.c') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 1056b3e6..72c61876 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -44,28 +44,28 @@ */ static void i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw, - int pipe) + int plane) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; u16 x1, y1, x2, y2; - int pf_pipes = 1 << pipe; + int pf_planes = 1 << plane; DRM_SPINLOCK_ASSERT(&dev->drw_lock); - /* If the window is visible on the other pipe, we have to flip on that - * pipe as well. + /* If the window is visible on the other plane, we have to flip on that + * plane as well. */ - if (pipe == 1) { - x1 = sarea_priv->pipeA_x; - y1 = sarea_priv->pipeA_y; - x2 = x1 + sarea_priv->pipeA_w; - y2 = y1 + sarea_priv->pipeA_h; + if (plane == 1) { + x1 = sarea_priv->planeA_x; + y1 = sarea_priv->planeA_y; + x2 = x1 + sarea_priv->planeA_w; + y2 = y1 + sarea_priv->planeA_h; } else { - x1 = sarea_priv->pipeB_x; - y1 = sarea_priv->pipeB_y; - x2 = x1 + sarea_priv->pipeB_w; - y2 = y1 + sarea_priv->pipeB_h; + x1 = sarea_priv->planeB_x; + y1 = sarea_priv->planeB_y; + x2 = x1 + sarea_priv->planeB_w; + y2 = y1 + sarea_priv->planeB_h; } if (x2 > 0 && y2 > 0) { @@ -75,13 +75,13 @@ i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw, for (i = 0; i < num_rects; i++) if (!(rect[i].x1 >= x2 || rect[i].y1 >= y2 || rect[i].x2 <= x1 || rect[i].y2 <= y1)) { - pf_pipes = 0x3; + pf_planes = 0x3; break; } } - i915_dispatch_flip(dev, pf_pipes, 1); + i915_dispatch_flip(dev, pf_planes, 1); } /** @@ -124,8 +124,10 @@ static void i915_vblank_tasklet(struct drm_device *dev) list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { drm_i915_vbl_swap_t *vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); + int pipe = vbl_swap->plane ? sarea_priv->planeB_pipe : + sarea_priv->planeA_pipe; - if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23)) + if ((counter[pipe] - vbl_swap->sequence) > (1<<23)) continue; list_del(list); @@ -176,10 +178,10 @@ static void i915_vblank_tasklet(struct drm_device *dev) i915_kernel_lost_context(dev); upper[0] = upper[1] = 0; - slice[0] = max(sarea_priv->pipeA_h / nhits, 1); - slice[1] = max(sarea_priv->pipeB_h / nhits, 1); - lower[0] = sarea_priv->pipeA_y + slice[0]; - lower[1] = sarea_priv->pipeB_y + slice[0]; + slice[0] = max(sarea_priv->planeA_h / nhits, 1); + slice[1] = max(sarea_priv->planeB_h / nhits, 1); + lower[0] = sarea_priv->planeA_y + slice[0]; + lower[1] = sarea_priv->planeB_y + slice[0]; offsets[0] = sarea_priv->front_offset; offsets[1] = sarea_priv->back_offset; @@ -205,7 +207,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) drm_i915_vbl_swap_t *swap_hit = list_entry(hit, drm_i915_vbl_swap_t, head); struct drm_clip_rect *rect; - int num_rects, pipe, front, back; + int num_rects, plane, front, back; unsigned short top, bottom; drw = drm_get_drawable_info(dev, swap_hit->drw_id); @@ -213,10 +215,10 @@ static void i915_vblank_tasklet(struct drm_device *dev) if (!drw) continue; - pipe = swap_hit->pipe; + plane = swap_hit->plane; if (swap_hit->flip) { - i915_dispatch_vsync_flip(dev, drw, pipe); + i915_dispatch_vsync_flip(dev, drw, plane); continue; } @@ -238,11 +240,11 @@ static void i915_vblank_tasklet(struct drm_device *dev) } rect = drw->rects; - top = upper[pipe]; - bottom = lower[pipe]; + top = upper[plane]; + bottom = lower[plane]; front = (dev_priv->sarea_priv->pf_current_page >> - (2 * pipe)) & 0x3; + (2 * plane)) & 0x3; back = (front + 1) % num_pages; for (num_rects = drw->num_rects; num_rects--; rect++) { @@ -560,9 +562,10 @@ int i915_vblank_swap(struct drm_device *dev, void *data, drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_vblank_swap_t *swap = data; drm_i915_vbl_swap_t *vbl_swap; - unsigned int pipe, seqtype, curseq; + unsigned int pipe, seqtype, curseq, plane; unsigned long irqflags; struct list_head *list; + drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __func__); @@ -581,7 +584,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data, return -EINVAL; } - pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; + plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; + pipe = plane ? sarea_priv->planeB_pipe : sarea_priv->planeA_pipe; seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); @@ -624,7 +628,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, return -EINVAL; } - i915_dispatch_vsync_flip(dev, drw, pipe); + i915_dispatch_vsync_flip(dev, drw, plane); DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags); @@ -638,7 +642,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); if (vbl_swap->drw_id == swap->drawable && - vbl_swap->pipe == pipe && + vbl_swap->plane == plane && vbl_swap->sequence == swap->sequence) { vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP); DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->swaps_lock, irqflags); @@ -664,7 +668,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, DRM_DEBUG("\n"); vbl_swap->drw_id = swap->drawable; - vbl_swap->pipe = pipe; + vbl_swap->plane = plane; vbl_swap->sequence = swap->sequence; vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP); -- cgit v1.2.3 From 852232fb803bef92b12136be2766ddee3e3613b2 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 12 Sep 2007 08:55:33 -0700 Subject: Remove plane->pipe mapping from SAREA private after all We can figure out which pipe a given plane is mapped to by looking at the display control registers instead of tracking it in a new SAREA private field. If this becomes a performance problem, we could move to an ioctl based solution by adding a new parameter for the DDX to set (defaulting to the old behavior if the param was never set of course). --- shared-core/i915_irq.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'shared-core/i915_irq.c') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 72c61876..804e3fb1 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -37,6 +37,26 @@ #define MAX_NOPID ((u32)~0) +/** + * i915_get_pipe - return the the pipe associated with a given plane + * @dev: DRM device + * @plane: plane to look for + * + * We need to get the pipe associated with a given plane to correctly perform + * vblank driven swapping, and they may not always be equal. So look up the + * pipe associated with @plane here. + */ +static int +i915_get_pipe(struct drm_device *dev, int plane) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + u32 dspcntr; + + dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR); + + return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0; +} + /** * Emit a synchronous flip. * @@ -124,8 +144,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { drm_i915_vbl_swap_t *vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); - int pipe = vbl_swap->plane ? sarea_priv->planeB_pipe : - sarea_priv->planeA_pipe; + int pipe = i915_get_pipe(dev, vbl_swap->plane); if ((counter[pipe] - vbl_swap->sequence) > (1<<23)) continue; @@ -565,7 +584,6 @@ int i915_vblank_swap(struct drm_device *dev, void *data, unsigned int pipe, seqtype, curseq, plane; unsigned long irqflags; struct list_head *list; - drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __func__); @@ -585,7 +603,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, } plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; - pipe = plane ? sarea_priv->planeB_pipe : sarea_priv->planeA_pipe; + pipe = i915_get_pipe(dev, plane); seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); -- cgit v1.2.3 From 78d111fa967d18e7f9f9b2acd26aff20b884eb6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 18 Sep 2007 20:55:43 +0100 Subject: i915: Fix scheduled buffer swaps. One instance of unlocking a spinlock was converted incorrectly when this code was fixed to build on BSD. --- shared-core/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core/i915_irq.c') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 804e3fb1..ea84c708 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -188,7 +188,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) DRM_SPINLOCK(&dev_priv->swaps_lock); } - DRM_SPINUNLOCK(&dev->drw_lock); + DRM_SPINUNLOCK(&dev_priv->swaps_lock); if (nhits == 0) { return; -- cgit v1.2.3 From e349b58b4a6ebfe299720cb921039a600c145e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 18 Sep 2007 21:03:22 +0100 Subject: i915: Reinstate check that drawable has valid information in i915_vblank_swap. --- shared-core/i915_irq.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'shared-core/i915_irq.c') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index ea84c708..7baa23c0 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -612,6 +612,21 @@ int i915_vblank_swap(struct drm_device *dev, void *data, return -EINVAL; } + DRM_SPINLOCK_IRQSAVE(&dev->drw_lock, irqflags); + + /* It makes no sense to schedule a swap for a drawable that doesn't have + * valid information at this point. E.g. this could mean that the X + * server is too old to push drawable information to the DRM, in which + * case all such swaps would become ineffective. + */ + if (!drm_get_drawable_info(dev, swap->drawable)) { + DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags); + DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable); + return -EINVAL; + } + + DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags); + curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received); if (seqtype == _DRM_VBLANK_RELATIVE) -- cgit v1.2.3