[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xserver-xorg-video-intel: Changes to 'upstream-unstable'



Rebased ref, commits from common ancestor:
commit f63c7df6866fed61551d39209b1a262e2a0c4b28
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
Date:   Fri Sep 17 16:39:12 2010 +0800

    Disable swap buffer wait on Sandybridge
    
    MI_LOAD_SCAN_LINE_INCL command is not available on sandybridge.
    I haven't got reply on any substitution for it, so turn it off for now.
    
    Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>

diff --git a/src/intel_driver.c b/src/intel_driver.c
index 6087f55..c0ad69e 100644
--- a/src/intel_driver.c
+++ b/src/intel_driver.c
@@ -873,6 +873,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv)
 			intel->swapbuffers_wait = FALSE;
 	}
 
+	if (IS_GEN6(intel))
+	    intel->swapbuffers_wait = FALSE;
+
 	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Tiling %sabled\n",
 		   intel->tiling ? "en" : "dis");
 	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "SwapBuffers wait %sabled\n",

commit 55b5fe888002258dd863d41977bfbfcf1a922179
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Thu Sep 16 16:50:13 2010 +0100

    Add alternate pci-id for B43
    
    Confirmed by http://en.wikipedia.org/wiki/Intel_GMA
    
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=30221
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/intel_driver.h b/src/intel_driver.h
index 50f176a..b55c8c9 100644
--- a/src/intel_driver.h
+++ b/src/intel_driver.h
@@ -158,6 +158,11 @@
 #define PCI_CHIP_B43_G_BRIDGE	0x2E40
 #endif
 
+#ifndef PCI_CHIP_B43_G1
+#define PCI_CHIP_B43_G1		0x2E92
+#define PCI_CHIP_B43_G1_BRIDGE	0x2E90
+#endif
+
 #ifndef PCI_CHIP_IGDNG_D_G
 #define PCI_CHIP_IGDNG_D_G		0x0042
 #define PCI_CHIP_IGDNG_D_G_BRIDGE	0x0040
diff --git a/src/intel_module.c b/src/intel_module.c
index d37896e..53e1cb6 100644
--- a/src/intel_module.c
+++ b/src/intel_module.c
@@ -70,6 +70,7 @@ static const SymTabRec _intel_chipsets[] = {
     {PCI_CHIP_Q45_G,		"Q45/Q43"},
     {PCI_CHIP_G41_G,		"G41"},
     {PCI_CHIP_B43_G,		"B43"},
+    {PCI_CHIP_B43_G1,		"B43"},
     {PCI_CHIP_IGDNG_D_G,		"Clarkdale"},
     {PCI_CHIP_IGDNG_M_G,		"Arrandale"},
     {PCI_CHIP_SANDYBRIDGE_GT1,	"Sandybridge" },

commit 08c2caca48323d6d5701dcef3486f850619d7905
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Sun Sep 12 12:34:51 2010 +0100

    uxa: Apply source clipping to blits
    
    Yes, this should be done in the higher layers. Yes, I have written code
    to that. No, it is not ready, hence add the sanity check to the
    SRC_COPY_BLT.
    
    This isn't the first report that I've seen, but will be the last.
    
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=30120
    Reported-by: rezbit.hex@gmail.com
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/intel_uxa.c b/src/intel_uxa.c
index 0dcd5d3..ef4c553 100644
--- a/src/intel_uxa.c
+++ b/src/intel_uxa.c
@@ -411,12 +411,39 @@ i830_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1,
 	ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
 	intel_screen_private *intel = intel_get_screen_private(scrn);
 	uint32_t cmd;
-	int dst_x2, dst_y2;
+	int dst_x2, dst_y2, src_x2, src_y2;
 	unsigned int dst_pitch, src_pitch;
 
 	dst_x2 = dst_x1 + w;
 	dst_y2 = dst_y1 + h;
 
+	/* XXX Fixup extents as a lamentable workaround for missing
+	 * source clipping in the upper layers.
+	 */
+	if (dst_x1 < 0)
+		src_x1 -= dst_x1, dst_x1 = 0;
+	if (dst_y1 < 0)
+		src_y1 -= dst_y1, dst_y1 = 0;
+	if (dst_x2 > dest->drawable.width)
+		dst_x2 = dest->drawable.width;
+	if (dst_y2 > dest->drawable.height)
+		dst_y2 = dest->drawable.height;
+
+	src_x2 = src_x1 + (dst_x2 - dst_x1);
+	src_y2 = src_y1 + (dst_y2 - dst_y1);
+
+	if (src_x1 < 0)
+		dst_x1 -= src_x1, src_x1 = 0;
+	if (src_y1 < 0)
+		dst_y1 -= src_y1, src_y1 = 0;
+	if (src_x2 > intel->render_source->drawable.width)
+		dst_x2 -= src_x2 - intel->render_source->drawable.width;
+	if (src_y2 > intel->render_source->drawable.height)
+		dst_y2 -= src_y2 - intel->render_source->drawable.height;
+
+	if (dst_x2 <= dst_x1 || dst_y2 <= dst_y1)
+		return;
+
 	dst_pitch = intel_pixmap_pitch(dest);
 	src_pitch = intel_pixmap_pitch(intel->render_source);
 

commit ae160d7fbfc79e78dad8702efcc55d9c0c25ff67
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Sep 10 13:19:12 2010 +0100

    shadow: Simply modify the Screen pixmap header
    
    This is a slightly less risky strategy than having to remember to update
    all pointers to the old Screen pixmap.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/intel.h b/src/intel.h
index c258a87..b816aeb 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -282,9 +282,10 @@ typedef struct intel_screen_private {
 	long GTTMapSize;
 
 	void *modes;
-	drm_intel_bo *front_buffer, *shadow_buffer;
+	drm_intel_bo *front_buffer;
 	long front_pitch, front_tiling;
-	PixmapPtr shadow_pixmap;
+	void *shadow_buffer;
+	int shadow_stride;
 	DamagePtr shadow_damage;
 
 	dri_bufmgr *bufmgr;
diff --git a/src/intel_driver.c b/src/intel_driver.c
index eab5c2c..6087f55 100644
--- a/src/intel_driver.c
+++ b/src/intel_driver.c
@@ -1140,22 +1140,19 @@ static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen)
 		intel->front_buffer = NULL;
 	}
 
-	if (intel->shadow_pixmap) {
-		PixmapPtr pixmap = intel->shadow_pixmap;
-
-		if (intel->shadow_damage) {
-			DamageUnregister(&pixmap->drawable,
-					 intel->shadow_damage);
-			DamageDestroy(intel->shadow_damage);
-			intel->shadow_damage = NULL;
-		}
-
-		if (intel->shadow_buffer) {
+	if (intel->shadow_buffer) {
+		if (IS_I8XX(intel))
 			drm_intel_bo_unreference(intel->shadow_buffer);
-			intel->shadow_buffer = NULL;
-		}
+		else
+			free(intel->shadow_buffer);
+		intel->shadow_buffer = NULL;
+	}
 
-		intel->shadow_pixmap = NULL;
+	if (intel->shadow_damage) {
+		DamageUnregister(&screen->GetScreenPixmap(screen)->drawable,
+				 intel->shadow_damage);
+		DamageDestroy(intel->shadow_damage);
+		intel->shadow_damage = NULL;
 	}
 
 	intel_batch_teardown(scrn);
diff --git a/src/intel_uxa.c b/src/intel_uxa.c
index 706d634..0dcd5d3 100644
--- a/src/intel_uxa.c
+++ b/src/intel_uxa.c
@@ -904,8 +904,8 @@ intel_shadow_create_bo(intel_screen_private *intel,
 	bo = drm_intel_bo_alloc(intel->bufmgr, "shadow", size, 0);
 	if (bo && drm_intel_gem_bo_map_gtt(bo) == 0) {
 		char *dst = bo->virtual;
-		char *src = intel->shadow_pixmap->devPrivate.ptr;
-		int src_pitch = intel->shadow_pixmap->devKind;
+		char *src = intel->shadow_buffer;
+		int src_pitch = intel->shadow_stride;
 		int row_length = w * intel->cpp;
 		int num_rows = h;
 		src += y1 * src_pitch + x1 * intel->cpp;
@@ -961,10 +961,10 @@ intel_shadow_blt(intel_screen_private *intel)
 		dri_bo *bo;
 		int offset;
 
-		if (intel->shadow_buffer) {
+		if (IS_I8XX(intel)) {
 			bo = intel->shadow_buffer;
 			offset = box->x1 | box->y1 << 16;
-			pitch = intel->shadow_pixmap->devKind;
+			pitch = intel->shadow_stride;
 		} else {
 			bo = intel_shadow_create_bo(intel,
 						    box->x1, box->y1,
@@ -1004,16 +1004,7 @@ static void intel_shadow_create(struct intel_screen_private *intel)
 	PixmapPtr pixmap;
 	int stride;
 
-	if (IS_I8XX(intel))
-		pixmap = screen->GetScreenPixmap(screen);
-	else
-		pixmap = intel->shadow_pixmap;
-
-	if (intel->shadow_damage) {
-		DamageUnregister(&pixmap->drawable, intel->shadow_damage);
-		DamageDestroy(intel->shadow_damage);
-	}
-
+	pixmap = screen->GetScreenPixmap(screen);
 	if (IS_I8XX(intel)) {
 		dri_bo *bo;
 		int size;
@@ -1043,29 +1034,37 @@ static void intel_shadow_create(struct intel_screen_private *intel)
 			intel->shadow_buffer = bo;
 		}
 	} else {
-		if (intel->shadow_pixmap)
-			fbDestroyPixmap(intel->shadow_pixmap);
-
-		pixmap = fbCreatePixmap(screen,
-					scrn->virtualX,
-					scrn->virtualY,
-					scrn->depth,
-					0);
-
-		screen->SetScreenPixmap(pixmap);
-		stride = pixmap->devKind;
+		void *buffer;
+
+		stride = intel->cpp*scrn->virtualX;
+		buffer = malloc(stride * scrn->virtualY);
+
+		if (buffer && screen->ModifyPixmapHeader(pixmap,
+							 scrn->virtualX,
+							 scrn->virtualY,
+							 -1, -1,
+							 stride,
+							 buffer)) {
+			if (intel->shadow_buffer)
+				free(intel->shadow_buffer);
+
+			intel->shadow_buffer = buffer;
+		} else
+			stride = intel->shadow_stride;
 	}
 
-	intel->shadow_pixmap = pixmap;
-	intel->shadow_damage = DamageCreate(NULL, NULL,
-					    DamageReportNone,
-					    TRUE,
-					    screen,
-					    intel);
-	DamageRegister(&pixmap->drawable, intel->shadow_damage);
-	DamageSetReportAfterOp(intel->shadow_damage, TRUE);
+	if (!intel->shadow_damage) {
+		intel->shadow_damage = DamageCreate(NULL, NULL,
+						    DamageReportNone,
+						    TRUE,
+						    screen,
+						    intel);
+		DamageRegister(&pixmap->drawable, intel->shadow_damage);
+		DamageSetReportAfterOp(intel->shadow_damage, TRUE);
+	}
 
 	scrn->displayWidth = stride / intel->cpp;
+	intel->shadow_stride = stride;
 }
 
 void intel_uxa_block_handler(intel_screen_private *intel)

commit 0515256490d5bcd55f85af83b84918d1bfe7f8f8
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Sep 10 00:08:58 2010 +0100

    display: Free the EDID blob after we copy it to the output, not before.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/intel_display.c b/src/intel_display.c
index e22c415..5d85baa 100644
--- a/src/intel_display.c
+++ b/src/intel_display.c
@@ -741,11 +741,12 @@ intel_output_attach_edid(xf86OutputPtr output)
 
 		if (mon && edid_blob->length > 128)
 			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
-
-		drmModeFreePropertyBlob(edid_blob);
 	}
 
 	xf86OutputSetEDID(output, mon);
+
+	if (edid_blob)
+		drmModeFreePropertyBlob(edid_blob);
 }
 
 static DisplayModePtr

commit 2b96c18165d713cd6781dbf217ec33e11cc961bc
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Aug 25 12:56:43 2010 +0100

    Enable a shadow buffer and disable GPU acceleration.
    
    An attempt to workaround the incoherency in gen2 chipsets, we avoid
    using dynamic reallocation as much as possible.
    
    The first step is to disable allocation of pixmaps using GEM and simply
    create them in system memory without a backing buffer object. This
    forces all rendering to use S/W fallbacks.
    
    The second step is to allocate a shadow front buffer and assign that to
    the Screen pixmap. This ensure that the front buffer remains in the GTT
    and pinned for scanout. The shadow buffer will be rendered to in the
    normal fashion via the Screen pixmap, and be marked dirty. In the block
    handler, the dirty shadow buffer is then blitted (using the GPU) over
    the front buffer. This should completely avoid having to move pages
    around in the GTT and avoid incurring the wrath of those early chipsets.
    Secondly, performance should be reasonable as we avoid the ping-pong
    caused by the small aperture and weak GPU forcing software fallbacks.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/man/intel.man b/man/intel.man
index c2447be..31860f2 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -156,6 +156,20 @@ i.e. perform synchronous rendering.
 .IP
 Default: Disabled
 .TP
+.BI "Option \*qShadow\*q \*q" boolean \*q
+This option controls the use of GPU acceleration and placement of auxiliary
+buffers in memory. Enabling the Shadow will disable all use of the GPU for
+RENDER acceleration and force software-fallbacks for all but updating the
+scan-out buffer. Hardware overlay is still supported so Xv will continue to
+playback videos using the GPU, but GL will be forced to use software
+rasterisation as well.  This is a last resort measure for systems with
+crippling bugs, such as early 8xx chipsets. It is still hoped that we will
+find a workaround to enable as much hardware acceleration on those
+architectures as is possible, but until then, using a shadow buffer should
+maintain system stability.
+.IP
+Default: Disabled
+.TP
 .BI "Option \*qSwapbuffersWait\*q \*q" boolean \*q
 This option controls the behavior of glXSwapBuffers and glXCopySubBufferMESA
 calls by GL applications.  If enabled, the calls will avoid tearing by making
diff --git a/src/intel.h b/src/intel.h
index 9e8323c..c258a87 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -271,6 +271,7 @@ enum dri_type {
 };
 
 typedef struct intel_screen_private {
+	ScrnInfoPtr scrn;
 	unsigned char *MMIOBase;
 	int cpp;
 
@@ -281,7 +282,10 @@ typedef struct intel_screen_private {
 	long GTTMapSize;
 
 	void *modes;
-	drm_intel_bo *front_buffer;
+	drm_intel_bo *front_buffer, *shadow_buffer;
+	long front_pitch, front_tiling;
+	PixmapPtr shadow_pixmap;
+	DamagePtr shadow_damage;
 
 	dri_bufmgr *bufmgr;
 
@@ -415,6 +419,7 @@ typedef struct intel_screen_private {
 
 	Bool use_pageflipping;
 	Bool force_fallback;
+	Bool use_shadow;
 
 	/* Broken-out options. */
 	OptionInfoPtr Options;
@@ -446,7 +451,9 @@ extern int intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crt
 extern int intel_crtc_id(xf86CrtcPtr crtc);
 extern int intel_output_dpms_status(xf86OutputPtr output);
 
-extern Bool intel_do_pageflip(ScreenPtr screen, dri_bo *new_front, void *data);
+extern Bool intel_do_pageflip(intel_screen_private *intel,
+			      dri_bo *new_front,
+			      void *data);
 
 static inline intel_screen_private *
 intel_get_screen_private(ScrnInfoPtr scrn)
@@ -501,7 +508,8 @@ void intel_set_gem_max_sizes(ScrnInfoPtr scrn);
 
 drm_intel_bo *intel_allocate_framebuffer(ScrnInfoPtr scrn,
 					int w, int h, int cpp,
-					unsigned long *pitch);
+					unsigned long *pitch,
+					uint32_t *tiling);
 
 /* i830_render.c */
 Bool i830_check_composite(int op,
diff --git a/src/intel_batchbuffer.h b/src/intel_batchbuffer.h
index 02997ba..bf7a5d9 100644
--- a/src/intel_batchbuffer.h
+++ b/src/intel_batchbuffer.h
@@ -153,6 +153,9 @@ intel_batch_emit_reloc_pixmap(intel_screen_private *intel, PixmapPtr pixmap,
 #define OUT_RELOC(bo, read_domains, write_domains, delta) \
 	intel_batch_emit_reloc(intel, bo, read_domains, write_domains, delta, 0)
 
+#define OUT_RELOC_FENCED(bo, read_domains, write_domains, delta) \
+	intel_batch_emit_reloc(intel, bo, read_domains, write_domains, delta, 1)
+
 #define OUT_RELOC_PIXMAP(pixmap, reads, write, delta)	\
 	intel_batch_emit_reloc_pixmap(intel, pixmap, reads, write, delta, 0)
 
diff --git a/src/intel_display.c b/src/intel_display.c
index ed3fdd0..e22c415 100644
--- a/src/intel_display.c
+++ b/src/intel_display.c
@@ -488,12 +488,14 @@ intel_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
 	struct intel_crtc *intel_crtc = crtc->driver_private;
 	struct intel_mode *mode = intel_crtc->mode;
 	unsigned long rotate_pitch;
+	uint32_t tiling;
 	int ret;
 
 	intel_crtc->rotate_bo = intel_allocate_framebuffer(scrn,
 							     width, height,
 							     mode->cpp,
-							     &rotate_pitch);
+							     &rotate_pitch,
+							     &tiling);
 
 	if (!intel_crtc->rotate_bo) {
 		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
@@ -580,7 +582,7 @@ intel_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
 		intel_crtc->rotate_bo = NULL;
 	}
 
-	intel->shadow_present = FALSE;
+	intel->shadow_present = intel->use_shadow;
 }
 
 static void
@@ -1310,11 +1312,10 @@ intel_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
 	intel_screen_private *intel = intel_get_screen_private(scrn);
 	drm_intel_bo *old_front = NULL;
 	Bool	    ret;
-	ScreenPtr   screen = screenInfo.screens[scrn->scrnIndex];
-	PixmapPtr   pixmap;
 	uint32_t    old_fb_id;
 	int	    i, old_width, old_height, old_pitch;
 	unsigned long pitch;
+	uint32_t tiling;
 
 	if (scrn->virtualX == width && scrn->virtualY == height)
 		return TRUE;
@@ -1328,7 +1329,8 @@ intel_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
 	intel->front_buffer = intel_allocate_framebuffer(scrn,
 							 width, height,
 							 intel->cpp,
-							 &pitch);
+							 &pitch,
+							 &tiling);
 	if (!intel->front_buffer)
 		goto fail;
 
@@ -1339,14 +1341,11 @@ intel_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
 	if (ret)
 		goto fail;
 
+	intel->front_pitch = pitch;
+	intel->front_tiling = tiling;
+
 	scrn->virtualX = width;
 	scrn->virtualY = height;
-	scrn->displayWidth = pitch / intel->cpp;
-
-	pixmap = screen->GetScreenPixmap(screen);
-	screen->ModifyPixmapHeader(pixmap, width, height, -1, -1, pitch, NULL);
-	intel_set_pixmap_bo(pixmap, intel->front_buffer);
-	intel_get_pixmap_private(pixmap)->busy = 1;
 
 	for (i = 0; i < xf86_config->num_crtc; i++) {
 		xf86CrtcPtr crtc = xf86_config->crtc[i];
@@ -1358,6 +1357,8 @@ intel_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
 			goto fail;
 	}
 
+	intel_uxa_create_screen_resources(scrn->pScreen);
+
 	if (old_fb_id)
 		drmModeRmFB(mode->fd, old_fb_id);
 	if (old_front)
@@ -1380,10 +1381,11 @@ fail:
 }
 
 Bool
-intel_do_pageflip(ScreenPtr screen, dri_bo *new_front, void *data)
+intel_do_pageflip(intel_screen_private *intel,
+		  dri_bo *new_front,
+		  void *data)
 {
-	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-	intel_screen_private *intel = intel_get_screen_private(scrn);
+	ScrnInfoPtr scrn = intel->scrn;
 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
 	struct intel_crtc *crtc = config->crtc[0]->driver_private;
 	struct intel_mode *mode = crtc->mode;
@@ -1454,22 +1456,31 @@ intel_page_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
 {
 	struct intel_mode *mode = event_data;
 
+
 	mode->flip_count--;
 	if (mode->flip_count > 0)
 		return;
 
 	drmModeRmFB(mode->fd, mode->old_fb_id);
 
+	if (mode->event_data == NULL)
+		return;
+
 	I830DRI2FlipEventHandler(frame, tv_sec, tv_usec, mode->event_data);
 }
 
 static void
 drm_wakeup_handler(pointer data, int err, pointer p)
 {
-	struct intel_mode *mode = data;
-	fd_set *read_mask = p;
+	struct intel_mode *mode;
+	fd_set *read_mask;
+
+	if (data == NULL || err < 0)
+		return;
 
-	if (err >= 0 && FD_ISSET(mode->fd, read_mask))
+	mode = data;
+	read_mask = p;
+	if (FD_ISSET(mode->fd, read_mask))
 		drmHandleEvent(mode->fd, &mode->event_context);
 }
 
diff --git a/src/intel_dri.c b/src/intel_dri.c
index 07782c6..db1f81a 100644
--- a/src/intel_dri.c
+++ b/src/intel_dri.c
@@ -488,10 +488,10 @@ I830DRI2ExchangeBuffers(DrawablePtr draw, DRI2BufferPtr front,
  * flipping buffers as necessary.
  */
 static Bool
-I830DRI2ScheduleFlip(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
+I830DRI2ScheduleFlip(struct intel_screen_private *intel,
+		     ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		     DRI2BufferPtr back, DRI2SwapEventPtr func, void *data)
 {
-	ScreenPtr screen = draw->pScreen;
 	I830DRI2BufferPrivatePtr back_priv;
 	DRI2FrameEventPtr flip_info;
 
@@ -507,7 +507,7 @@ I830DRI2ScheduleFlip(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 
 	/* Page flip the full screen buffer */
 	back_priv = back->driverPrivate;
-	return intel_do_pageflip(screen,
+	return intel_do_pageflip(intel,
 				 intel_get_pixmap_bo(back_priv->pixmap),
 				 flip_info);
 }
@@ -567,7 +567,8 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 		if (DRI2CanFlip(drawable) && !intel->shadow_present &&
 		    intel->use_pageflipping &&
 		    can_exchange(event->front, event->back) &&
-		    I830DRI2ScheduleFlip(event->client, drawable, event->front,
+		    I830DRI2ScheduleFlip(intel,
+					 event->client, drawable, event->front,
 					 event->back, event->event_complete,
 					 event->event_data)) {
 			I830DRI2ExchangeBuffers(drawable,
diff --git a/src/intel_driver.c b/src/intel_driver.c
index 9b2fdaf..eab5c2c 100644
--- a/src/intel_driver.c
+++ b/src/intel_driver.c
@@ -98,6 +98,7 @@ typedef enum {
    OPTION_COLOR_KEY,
    OPTION_FALLBACKDEBUG,
    OPTION_TILING,
+   OPTION_SHADOW,
    OPTION_SWAPBUFFERS_WAIT,
 #ifdef INTEL_XVMC
    OPTION_XVMC,
@@ -115,6 +116,7 @@ static OptionInfoRec I830Options[] = {
    {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_FALLBACKDEBUG, "FallbackDebug", OPTV_BOOLEAN, {0},	FALSE},
    {OPTION_TILING,	"Tiling",	OPTV_BOOLEAN,	{0},	TRUE},
+   {OPTION_SHADOW,	"Shadow",	OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_SWAPBUFFERS_WAIT, "SwapbuffersWait", OPTV_BOOLEAN,	{0},	TRUE},
 #ifdef INTEL_XVMC
    {OPTION_XVMC,	"XvMC",		OPTV_BOOLEAN,	{0},	TRUE},
@@ -536,6 +538,7 @@ static Bool I830PreInit(ScrnInfoPtr scrn, int flags)
 
 		scrn->driverPrivate = intel;
 	}
+	intel->scrn = scrn;
 	intel->pEnt = pEnt;
 
 	scrn->displayWidth = 640;	/* default it */
@@ -726,13 +729,16 @@ static Bool
 intel_init_initial_framebuffer(ScrnInfoPtr scrn)
 {
 	intel_screen_private *intel = intel_get_screen_private(scrn);
+	int width = scrn->virtualX;
+	int height = scrn->virtualY;
 	unsigned long pitch;
+	uint32_t tiling;
 
 	intel->front_buffer = intel_allocate_framebuffer(scrn,
-							 scrn->virtualX,
-							 scrn->virtualY,
+							 width, height,
 							 intel->cpp,
-							 &pitch);
+							 &pitch,
+							 &tiling);
 
 	if (!intel->front_buffer) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
@@ -740,6 +746,8 @@ intel_init_initial_framebuffer(ScrnInfoPtr scrn)
 		return FALSE;
 	}
 
+	intel->front_pitch = pitch;
+	intel->front_tiling = tiling;
 	scrn->displayWidth = pitch / intel->cpp;
 
 	return TRUE;
@@ -828,6 +836,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv)
 		intel->directRenderingType = DRI_DRI2;
 #endif
 
+	intel->force_fallback = FALSE;
+	intel->use_shadow = FALSE;
+
 	/* Enable tiling by default */
 	intel->tiling = TRUE;
 
@@ -839,6 +850,17 @@ I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv)
 			intel->tiling = FALSE;
 	}
 
+	if (xf86IsOptionSet(intel->Options, OPTION_SHADOW)) {
+		if (xf86ReturnOptValBool(intel->Options, OPTION_SHADOW, FALSE))
+			intel->force_fallback = intel->use_shadow = TRUE;
+	}
+
+	if (intel->use_shadow) {
+		xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
+			   "Shadow buffer enabled,"
+			   " GPU acceleration disabled.\n");
+	}
+
 	/* SwapBuffers delays to avoid tearing */
 	intel->swapbuffers_wait = TRUE;
 
@@ -1101,6 +1123,8 @@ static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen)
 		I830LeaveVT(scrnIndex, 0);
 	}
 
+	DeleteCallback(&FlushCallback, intel_flush_callback, scrn);
+
 	if (intel->uxa_driver) {
 		uxa_driver_fini(screen);
 		free(intel->uxa_driver);
@@ -1108,13 +1132,31 @@ static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen)
 	}
 
 	if (intel->front_buffer) {
-		intel_set_pixmap_bo(screen->GetScreenPixmap(screen), NULL);
+		if (!intel->use_shadow)
+			intel_set_pixmap_bo(screen->GetScreenPixmap(screen),
+					    NULL);
 		intel_mode_remove_fb(intel);
 		drm_intel_bo_unreference(intel->front_buffer);
 		intel->front_buffer = NULL;
 	}
 
-	DeleteCallback(&FlushCallback, intel_flush_callback, scrn);
+	if (intel->shadow_pixmap) {
+		PixmapPtr pixmap = intel->shadow_pixmap;
+
+		if (intel->shadow_damage) {
+			DamageUnregister(&pixmap->drawable,
+					 intel->shadow_damage);
+			DamageDestroy(intel->shadow_damage);
+			intel->shadow_damage = NULL;
+		}
+
+		if (intel->shadow_buffer) {
+			drm_intel_bo_unreference(intel->shadow_buffer);
+			intel->shadow_buffer = NULL;
+		}
+
+		intel->shadow_pixmap = NULL;
+	}
 
 	intel_batch_teardown(scrn);
 
diff --git a/src/intel_memory.c b/src/intel_memory.c
index 091e3d0..4f1b009 100644
--- a/src/intel_memory.c
+++ b/src/intel_memory.c
@@ -178,7 +178,8 @@ static inline int intel_pad_drawable_width(int width)
  */
 drm_intel_bo *intel_allocate_framebuffer(ScrnInfoPtr scrn,
 					int width, int height, int cpp,
-					unsigned long *out_pitch)
+					unsigned long *out_pitch,
+					uint32_t *out_tiling)
 {
 	intel_screen_private *intel = intel_get_screen_private(scrn);
 	drm_intel_bo *front_buffer;
@@ -241,6 +242,7 @@ retry:
 
 	intel_set_gem_max_sizes(scrn);
 	*out_pitch = pitch;
+	*out_tiling = tiling_mode;
 
 	return front_buffer;
 }
diff --git a/src/intel_uxa.c b/src/intel_uxa.c
index 1681b70..706d634 100644
--- a/src/intel_uxa.c
+++ b/src/intel_uxa.c
@@ -688,9 +688,6 @@ static void intel_uxa_finish_access(PixmapPtr pixmap)
 	struct intel_pixmap *priv = intel_get_pixmap_private(pixmap);
 	dri_bo *bo = priv->bo;
 
-	if (bo == intel->front_buffer)
-		intel->need_sync = TRUE;
-
 	if (priv->tiling || bo->size <= intel->max_gtt_map_size)
 		drm_intel_gem_bo_unmap_gtt(bo);
 	else
@@ -892,14 +889,197 @@ static Bool intel_uxa_get_image(PixmapPtr pixmap,
 		scratch->drawable.pScreen->DestroyPixmap(scratch);
 
 	return ret;
+}
+
+static dri_bo *
+intel_shadow_create_bo(intel_screen_private *intel,
+		       int16_t x1, int16_t y1,
+		       int16_t x2, int16_t y2,
+		       int *pitch)
+{
+	int w = x2 - x1, h = y2 - y1;
+	int size = h * w * intel->cpp;
+	dri_bo *bo;
+
+	bo = drm_intel_bo_alloc(intel->bufmgr, "shadow", size, 0);
+	if (bo && drm_intel_gem_bo_map_gtt(bo) == 0) {
+		char *dst = bo->virtual;
+		char *src = intel->shadow_pixmap->devPrivate.ptr;
+		int src_pitch = intel->shadow_pixmap->devKind;
+		int row_length = w * intel->cpp;
+		int num_rows = h;
+		src += y1 * src_pitch + x1 * intel->cpp;
+		do {
+			memcpy (dst, src, row_length);
+			src += src_pitch;
+			dst += row_length;
+		} while (--num_rows);
+		drm_intel_gem_bo_unmap_gtt(bo);
+	}
+
+	*pitch = w * intel->cpp;
+	return bo;
+}
+
+static void
+intel_shadow_blt(intel_screen_private *intel)
+{
+	ScrnInfoPtr scrn = intel->scrn;
+	unsigned int dst_pitch;
+	uint32_t blt, br13;
+	RegionPtr region;
+	BoxPtr box;
+	int n;
+
+	dst_pitch = intel->front_pitch;
+
+	blt = XY_SRC_COPY_BLT_CMD;
+	if (intel->cpp == 4)
+		blt |= (XY_SRC_COPY_BLT_WRITE_ALPHA |
+				XY_SRC_COPY_BLT_WRITE_RGB);
+
+	if (IS_I965G(intel)) {
+		if (intel->front_tiling) {
+			dst_pitch >>= 2;
+			blt |= XY_SRC_COPY_BLT_DST_TILED;
+		}
+	}
+
+	br13 = ROP_S << 16 | dst_pitch;
+	switch (intel->cpp) {
+		default:
+		case 4: br13 |= 1 << 25; /* RGB8888 */
+		case 2: br13 |= 1 << 24; /* RGB565 */
+		case 1: break;
+	}
+
+	region = DamageRegion(intel->shadow_damage);
+	box = REGION_RECTS(region);
+	n = REGION_NUM_RECTS(region);
+	while (n--) {
+		int pitch;
+		dri_bo *bo;
+		int offset;
+
+		if (intel->shadow_buffer) {
+			bo = intel->shadow_buffer;
+			offset = box->x1 | box->y1 << 16;
+			pitch = intel->shadow_pixmap->devKind;
+		} else {
+			bo = intel_shadow_create_bo(intel,
+						    box->x1, box->y1,
+						    box->x2, box->y2,
+						    &pitch);
+			if (bo == NULL)
+				return;
+
+			offset = 0;
+		}
+
+		BEGIN_BATCH(8);
+		OUT_BATCH(blt);
+		OUT_BATCH(br13);
+		OUT_BATCH(box->y1 << 16 | box->x1);
+		OUT_BATCH(box->y2 << 16 | box->x2);
+		OUT_RELOC_FENCED(intel->front_buffer,
+				I915_GEM_DOMAIN_RENDER,
+				I915_GEM_DOMAIN_RENDER,
+				0);
+		OUT_BATCH(offset);
+		OUT_BATCH(pitch);
+		OUT_RELOC(bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+
+		ADVANCE_BATCH();
 
+		if (bo != intel->shadow_buffer)
+			drm_intel_bo_unreference(bo);
+		box++;
+	}
+}
+
+static void intel_shadow_create(struct intel_screen_private *intel)
+{
+	ScrnInfoPtr scrn = intel->scrn;
+	ScreenPtr screen = scrn->pScreen;
+	PixmapPtr pixmap;
+	int stride;
+
+	if (IS_I8XX(intel))
+		pixmap = screen->GetScreenPixmap(screen);
+	else
+		pixmap = intel->shadow_pixmap;
+
+	if (intel->shadow_damage) {
+		DamageUnregister(&pixmap->drawable, intel->shadow_damage);
+		DamageDestroy(intel->shadow_damage);
+	}
+
+	if (IS_I8XX(intel)) {
+		dri_bo *bo;
+		int size;
+
+		/* Reduce the incoherency worries for gen2
+		 * by only allocating a static shadow, at about 2-3x
+		 * performance cost for forcing rendering to uncached memory.
+		 */
+		if (intel->shadow_buffer) {
+			drm_intel_gem_bo_unmap_gtt(intel->shadow_buffer);
+			drm_intel_bo_unreference(intel->shadow_buffer);
+			intel->shadow_buffer = NULL;
+		}
+
+		stride = ALIGN(scrn->virtualX * intel->cpp, 4);
+		size = stride * scrn->virtualY;
+		bo = drm_intel_bo_alloc(intel->bufmgr,
+					"shadow", size,
+					0);
+		if (bo && drm_intel_gem_bo_map_gtt(bo) == 0) {
+			screen->ModifyPixmapHeader(pixmap,
+						   scrn->virtualX,
+						   scrn->virtualY,
+						   -1, -1,
+						   stride,
+						   bo->virtual);
+			intel->shadow_buffer = bo;
+		}
+	} else {
+		if (intel->shadow_pixmap)
+			fbDestroyPixmap(intel->shadow_pixmap);
+
+		pixmap = fbCreatePixmap(screen,
+					scrn->virtualX,
+					scrn->virtualY,
+					scrn->depth,
+					0);
+
+		screen->SetScreenPixmap(pixmap);
+		stride = pixmap->devKind;
+	}
+
+	intel->shadow_pixmap = pixmap;
+	intel->shadow_damage = DamageCreate(NULL, NULL,
+					    DamageReportNone,
+					    TRUE,
+					    screen,
+					    intel);
+	DamageRegister(&pixmap->drawable, intel->shadow_damage);
+	DamageSetReportAfterOp(intel->shadow_damage, TRUE);
+
+	scrn->displayWidth = stride / intel->cpp;
 }
 
 void intel_uxa_block_handler(intel_screen_private *intel)
 {
-	if (intel->need_sync) {
-		dri_bo_wait_rendering(intel->front_buffer);
-		intel->need_sync = FALSE;
+	if (intel->shadow_damage &&
+	    pixman_region_not_empty(DamageRegion(intel->shadow_damage))) {
+		intel_shadow_blt(intel);
+		/* Emit a flush of the rendering cache, or on the 965
+		 * and beyond rendering results may not hit the
+		 * framebuffer until significantly later.
+		 */
+		intel_batch_submit(intel->scrn, TRUE);
+
+		DamageEmpty(intel->shadow_damage);
 	}
 }
 
@@ -1045,17 +1225,27 @@ static Bool intel_uxa_destroy_pixmap(PixmapPtr pixmap)
 	return TRUE;
 }
 
-
 void intel_uxa_create_screen_resources(ScreenPtr screen)
 {
 	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
 	intel_screen_private *intel = intel_get_screen_private(scrn);
-	dri_bo *bo = intel->front_buffer;
 
-	if (bo != NULL) {
-		PixmapPtr pixmap = screen->GetScreenPixmap(screen);
-		intel_set_pixmap_bo(pixmap, bo);
-		intel_get_pixmap_private(pixmap)->busy = 1;
+	if (intel->use_shadow) {
+		intel_shadow_create(intel);
+	} else {
+		dri_bo *bo = intel->front_buffer;
+		if (bo != NULL) {
+			PixmapPtr pixmap = screen->GetScreenPixmap(screen);
+			intel_set_pixmap_bo(pixmap, bo);
+			intel_get_pixmap_private(pixmap)->busy = 1;
+			screen->ModifyPixmapHeader(pixmap,
+						   scrn->virtualX,
+						   scrn->virtualY,


Reply to: