On Monday, June 23, 2008 11:02 am Jesse Barnes wrote:
> On Monday, June 23, 2008 12:51 am Michel Dänzer wrote:
> > On Fri, 2008-06-20 at 14:27 -0700, Jesse Barnes wrote:
> > > On Friday, June 20, 2008 2:09 pm Jesse Barnes wrote:
> > > > Michel, can you take a look at this? vblank wait is working really
> > > > well for me with the latest bits, but I found what I think is a page
> > > > flip related bug on 965.
> >
> > No this isn't correct, it also needs to wait for scheduled non-flip
> > buffer swaps.
> >
> > Isn't this just a workaround for the lack of the 2D driver patch and not
> > necessary with it?
>
> I'm not sure what 2D patch you mean (page flipping for 965 I suppose), but
> clearly there's something wrong here since w/o this patch we end up doing
> an absolute wait on a 0 vblank count. :) Maybe I need to initialize the
> vbl_pending/vbl_waited values somewhere else instead? I'll poke around the
> page flipping & buffer swap code to see if I can make sense of it. Would
> be nice to have that feature available on 965, and preferably enable it by
> default if it works.
I guess this is what you meant? Looks like we need changes throughout the
whole stack to support page flipping on 965... Just tested this set of
patches, things seem to work ok, though I get pretty massive tearing on
glxgears by default, which I suppose is expected.
Thanks,
Jesse
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index 3f4fd1b..645213b 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -642,7 +642,7 @@ int i915_dispatch_batchbuffer(struct drm_device * dev,
static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- u32 num_pages, current_page, next_page, dspbase;
+ u32 num_pages, current_page, next_page, base, offset;
int shift = 2 * plane, x, y;
RING_LOCALS;
@@ -654,13 +654,13 @@ static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync)
switch (next_page) {
default:
case 0:
- dspbase = dev_priv->sarea_priv->front_offset;
+ base = dev_priv->sarea_priv->front_offset;
break;
case 1:
- dspbase = dev_priv->sarea_priv->back_offset;
+ base = dev_priv->sarea_priv->back_offset;
break;
case 2:
- dspbase = dev_priv->sarea_priv->third_offset;
+ base = dev_priv->sarea_priv->third_offset;
break;
}
@@ -672,20 +672,29 @@ static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync)
y = dev_priv->sarea_priv->planeB_y;
}
- dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp;
+ offset = (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp;
DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page,
- dspbase);
+ base + offset);
- BEGIN_LP_RING(4);
- OUT_RING(sync ? 0 :
- (MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP :
- MI_WAIT_FOR_PLANE_A_FLIP)));
- OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) |
- (plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
- OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
- OUT_RING(dspbase);
- ADVANCE_LP_RING();
+ if (IS_I965G(dev)) {
+ BEGIN_LP_RING(4);
+ OUT_RING(MI_DISPLAY_FLIP | (sync ? 0 : DISPLAY_FLIP_ASYNC) |
+ (plane ? DISPLAY_FLIP_PLANE_B : 0));
+ OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
+ OUT_RING((base + offset) | DISPLAY_FLIP_TILED);
+ OUT_RING(x << DISPLAY_FLIP_HSIZE_SHIFT | y);
+ } else {
+ BEGIN_LP_RING(4);
+ OUT_RING(sync ? 0 :
+ (MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP :
+ MI_WAIT_FOR_PLANE_A_FLIP)));
+ OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) |
+ (plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
+ OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
+ OUT_RING(base + offset);
+ ADVANCE_LP_RING();
+ }
dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift);
dev_priv->sarea_priv->pf_current_page |= next_page << shift;
diff --git a/src/i830_display.c b/src/i830_display.c
index 56a718d..04e5927 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -35,6 +35,7 @@
#include <assert.h>
#include <stdlib.h>
#include <math.h>
+#include <sys/ioctl.h>
#include "xf86.h"
#include "i830.h"
@@ -730,6 +731,40 @@ i830_use_fb_compression(xf86CrtcPtr crtc)
return TRUE;
}
+#if defined(DRM_IOCTL_MODESET_CTL) && defined(XF86DRI)
+static void i830_modeset_ctl(xf86CrtcPtr crtc, int pre)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ struct drm_modeset_ctl modeset;
+
+ modeset.crtc = intel_crtc->plane;
+ return;
+
+ /*
+ * DPMS will be called many times (especially off), but we only
+ * want to catch the transition from on->off and off->on.
+ */
+ if (pre && intel_crtc->dpms_mode != DPMSModeOff) {
+ /* On -> off is a pre modeset */
+ modeset.cmd = _DRM_PRE_MODESET;
+ ioctl(pI830->drmSubFD, DRM_IOCTL_MODESET_CTL, &modeset);
+ ErrorF("modeset: on -> off on plane %d\n", modeset.crtc);
+ } else if (!pre && intel_crtc->dpms_mode == DPMSModeOff) {
+ /* Off -> on means post modeset */
+ modeset.cmd = _DRM_POST_MODESET;
+ ioctl(pI830->drmSubFD, DRM_IOCTL_MODESET_CTL, &modeset);
+ ErrorF("modeset: off -> on on plane %d\n", modeset.crtc);
+ }
+}
+#else
+static void i830_modeset_ctl(xf86CrtcPtr crtc, int dpms_state)
+{
+ return;
+}
+#endif /* DRM_IOCTL_MODESET_CTL && XF86DRI */
+
/**
* Sets the power management mode of the pipe and plane.
*
@@ -797,8 +832,10 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
/* Reenable compression if needed */
if (i830_use_fb_compression(crtc))
i830_enable_fb_compression(crtc);
+ i830_modeset_ctl(crtc, 0);
break;
case DPMSModeOff:
+ i830_modeset_ctl(crtc, 1);
/* Shut off compression if in use */
if (i830_use_fb_compression(crtc))
i830_disable_fb_compression(crtc);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 4361ad0..57fb0a4 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -996,26 +996,35 @@ static void
I830DRIDoRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox, uint32_t dst)
{
I830Ptr pI830 = I830PTR(pScrn);
- int i, cmd, br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
+ unsigned int i, cmd, pitch, flags;
+
+ pitch = pScrn->displayWidth * pI830->cpp;
+ flags = 0xcc << 16; /* ROP_S */
if (pScrn->bitsPerPixel == 32) {
cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
- br13 |= 3 << 24;
+ flags |= 3 << 24;
} else {
cmd = (XY_SRC_COPY_BLT_CMD);
- br13 |= 1 << 24;
+ flags |= 1 << 24;
+ }
+
+ /* We can assume tiled buffers if page flipping is on */
+ if (IS_I965G(pI830)) {
+ cmd |= XY_SRC_COPY_BLT_DST_TILED | XY_SRC_COPY_BLT_SRC_TILED;
+ pitch >>= 2;
}
for (i = 0 ; i < num ; i++, pbox++) {
BEGIN_BATCH(8);
OUT_BATCH(cmd);
- OUT_BATCH(br13);
+ OUT_BATCH(flags | pitch);
OUT_BATCH((pbox->y1 << 16) | pbox->x1);
OUT_BATCH((pbox->y2 << 16) | pbox->x2);
OUT_BATCH(dst);
OUT_BATCH((pbox->y1 << 16) | pbox->x1);
- OUT_BATCH(br13 & 0xffff);
+ OUT_BATCH(pitch);
OUT_BATCH(pI830->front_buffer->offset);
ADVANCE_BATCH();
}
diff --git a/src/mesa/drivers/dri/intel/intel_buffers.c b/src/mesa/drivers/dri/intel/intel_buffers.c
index 2a25f07..37a9201 100644
--- a/src/mesa/drivers/dri/intel/intel_buffers.c
+++ b/src/mesa/drivers/dri/intel/intel_buffers.c
@@ -197,7 +197,6 @@ intelSetBackClipRects(struct intel_context *intel)
}
}
-#ifdef I915
static void
intelUpdatePageFlipping(struct intel_context *intel,
GLint areaA, GLint areaB)
@@ -267,7 +266,6 @@ intelUpdatePageFlipping(struct intel_context *intel,
intel_flip_renderbuffers(intel_fb);
intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
}
-#endif /* I915 */
/**
* This will be called whenever the currently bound window is moved/resized.
@@ -318,9 +316,7 @@ intelWindowMoved(struct intel_context *intel)
GLint areaB = driIntersectArea( drw_rect, planeB_rect );
GLuint flags = dPriv->vblFlags;
-#ifdef I915
intelUpdatePageFlipping(intel, areaA, areaB);
-#endif
/* Update vblank info
*/
@@ -645,7 +641,6 @@ intel_wait_flips(struct intel_context *intel)
static GLboolean
intelPageFlip(const __DRIdrawablePrivate * dPriv)
{
-#ifdef I915
struct intel_context *intel;
int ret;
struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
@@ -698,9 +693,6 @@ intelPageFlip(const __DRIdrawablePrivate * dPriv)
intel_draw_buffer(&intel->ctx, &intel_fb->Base);
return GL_TRUE;
-#else
- return GL_FALSE;
-#endif
}
#if 0
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel