xf86-video-intel: man/intel.man src/intel_batchbuffer.h src/intel_display.c src/intel_dri.c src/intel_driver.c src/intel.h src/intel_memory.c src/intel_uxa.c src/intel_video.c uxa/uxa.c uxa/uxa-glyphs.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Sep 8 05:35:04 PDT 2010


 man/intel.man           |   14 +++
 src/intel.h             |   14 ++-
 src/intel_batchbuffer.h |    3 
 src/intel_display.c     |   45 ++++++---
 src/intel_dri.c         |    9 +
 src/intel_driver.c      |   52 ++++++++++-
 src/intel_memory.c      |    4 
 src/intel_uxa.c         |  217 ++++++++++++++++++++++++++++++++++++++++++++----
 src/intel_video.c       |    4 
 uxa/uxa-glyphs.c        |   27 +++--
 uxa/uxa.c               |   15 +--
 11 files changed, 342 insertions(+), 62 deletions(-)

New commits:
commit 2b96c18165d713cd6781dbf217ec33e11cc961bc
Author: Chris Wilson <chris at 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 at 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,
+						   -1, -1,
+						   intel->front_pitch,
+						   NULL);
+		}
+		scrn->displayWidth = intel->front_pitch / intel->cpp;
 	}
 }
 
@@ -1131,8 +1321,6 @@ Bool intel_uxa_init(ScreenPtr screen)
 
 	memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver));
 
-	intel->force_fallback = FALSE;
-
 	intel->bufferOffset = 0;
 	intel->uxa_driver->uxa_major = 1;
 	intel->uxa_driver->uxa_minor = 0;
@@ -1206,6 +1394,7 @@ Bool intel_uxa_init(ScreenPtr screen)
 	}
 
 	uxa_set_fallback_debug(screen, intel->fallback_debug);
+	uxa_set_force_fallback(screen, intel->force_fallback);
 
 	return TRUE;
 }
diff --git a/src/intel_video.c b/src/intel_video.c
index cde596c..30a0c37 100644
--- a/src/intel_video.c
+++ b/src/intel_video.c
@@ -362,7 +362,9 @@ void I830InitVideo(ScreenPtr screen)
 	/* Set up textured video if we can do it at this depth and we are on
 	 * supported hardware.
 	 */
-	if (scrn->bitsPerPixel >= 16 && (IS_I9XX(intel) || IS_I965G(intel))) {
+	if (scrn->bitsPerPixel >= 16 &&
+	    (IS_I9XX(intel) || IS_I965G(intel)) &&
+	    !intel->use_shadow) {
 		texturedAdaptor = I830SetupImageVideoTextured(screen);
 		if (texturedAdaptor != NULL) {
 			xf86DrvMsg(scrn->scrnIndex, X_INFO,
diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c
index 8c00e90..ad4f387 100644
--- a/uxa/uxa-glyphs.c
+++ b/uxa/uxa-glyphs.c
@@ -197,13 +197,6 @@ bail:
 
 Bool uxa_glyphs_init(ScreenPtr pScreen)
 {
-	/* We are trying to initialise per screen resources prior to the
-	 * complete initialisation of the screen. So ensure the components
-	 * that we depend upon are initialsed prior to our use.
-	 */
-	if (!CreateScratchPixmapsForScreen(pScreen->myNum))
-		return FALSE;
-
 #if HAS_DIXREGISTERPRIVATEKEY
 	if (!dixRegisterPrivateKey(&uxa_glyph_key, PRIVATE_GLYPH, 0))
 		return FALSE;
@@ -212,6 +205,17 @@ Bool uxa_glyphs_init(ScreenPtr pScreen)
 		return FALSE;
 #endif
 
+	/* Skip pixmap creation if we don't intend to use it. */
+	if (uxa_get_screen(pScreen)->force_fallback)
+		return TRUE;
+
+	/* We are trying to initialise per screen resources prior to the
+	 * complete initialisation of the screen. So ensure the components
+	 * that we depend upon are initialsed prior to our use.
+	 */
+	if (!CreateScratchPixmapsForScreen(pScreen->myNum))
+		return FALSE;
+
 	if (!uxa_realize_glyph_caches(pScreen))
 		return FALSE;
 
@@ -293,18 +297,19 @@ uxa_glyph_cache_upload_glyph(ScreenPtr screen,
 }
 
 void
-uxa_glyph_unrealize(ScreenPtr pScreen,
-		    GlyphPtr pGlyph)
+uxa_glyph_unrealize(ScreenPtr screen,
+		    GlyphPtr glyph)
 {
 	struct uxa_glyph *priv;
 
-	priv = uxa_glyph_get_private(pGlyph);
+	/* Use Lookup in case we have not attached to this glyph. */
+	priv = dixLookupPrivate(&glyph->devPrivates, &uxa_glyph_key);
 	if (priv == NULL)
 		return;
 
 	priv->cache->glyphs[priv->pos] = NULL;
 
-	uxa_glyph_set_private(pGlyph, NULL);
+	uxa_glyph_set_private(glyph, NULL);
 	free(priv);
 }
 
diff --git a/uxa/uxa.c b/uxa/uxa.c
index 4a5907e..3c81a85 100644
--- a/uxa/uxa.c
+++ b/uxa/uxa.c
@@ -385,12 +385,15 @@ static Bool uxa_close_screen(int i, ScreenPtr pScreen)
 
 	uxa_glyphs_fini(pScreen);
 
-	/* Destroy the pixmap created by miScreenInit() *before* chaining up as
-	 * we finalize ourselves here and so this is the last chance we have of
-	 * releasing our resources associated with the Pixmap. So do it first.
-	 */
-	(void) (*pScreen->DestroyPixmap) (pScreen->devPrivate);
-	pScreen->devPrivate = NULL;
+	if (pScreen->devPrivate) {
+		/* Destroy the pixmap created by miScreenInit() *before*
+		 * chaining up as we finalize ourselves here and so this
+		 * is the last chance we have of releasing our resources
+		 * associated with the Pixmap. So do it first.
+		 */
+		(void) (*pScreen->DestroyPixmap) (pScreen->devPrivate);
+		pScreen->devPrivate = NULL;
+	}
 
 	pScreen->CreateGC = uxa_screen->SavedCreateGC;
 	pScreen->CloseScreen = uxa_screen->SavedCloseScreen;


More information about the xorg-commit mailing list