xf86-video-intel: 4 commits - src/common.h src/i830_batchbuffer.c src/i830_batchbuffer.h src/i830.h src/i830_uxa.c src/i915_render.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Jun 17 06:41:41 PDT 2010


 src/common.h           |    1 
 src/i830.h             |   20 ++-
 src/i830_batchbuffer.c |   51 +-------
 src/i830_batchbuffer.h |   12 -
 src/i830_uxa.c         |  312 +++++++++++++++++++++++++------------------------
 src/i915_render.c      |    9 +
 6 files changed, 199 insertions(+), 206 deletions(-)

New commits:
commit be55066c6481b4c5e2cd39ef1c0f3be88cae0c93
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 17 14:23:21 2010 +0100

    i830: Remove domain tracking from pixmaps.
    
    The 4 integers can be reduced to a single boolean value, so do so.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/i830.h b/src/i830.h
index a5fee3d..64acda3 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -168,14 +168,10 @@ struct intel_pixmap {
 
 	struct list flush, batch, in_flight;
 
-	int8_t busy;
-	uint8_t tiling;
 	uint16_t stride;
-
-	uint16_t flush_write_domain;
-	uint16_t flush_read_domains;
-	uint16_t batch_write_domain;
-	uint16_t batch_read_domains;
+	uint8_t tiling;
+	int8_t busy :2;
+	int8_t batch_write :1;
 };
 
 #if HAS_DEVPRIVATEKEYREC
@@ -207,7 +203,7 @@ static inline void i830_set_pixmap_intel(PixmapPtr pixmap, struct intel_pixmap *
 
 static inline Bool i830_uxa_pixmap_is_dirty(PixmapPtr pixmap)
 {
-	return i830_get_pixmap_intel(pixmap)->flush_write_domain != 0;
+	return !list_is_empty(&i830_get_pixmap_intel(pixmap)->flush);
 }
 
 static inline Bool i830_pixmap_tiled(PixmapPtr pixmap)
diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index 46c9d4f..6da20d7 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -109,27 +109,11 @@ void intel_batch_teardown(ScrnInfoPtr scrn)
 		intel->vertex_bo = NULL;
 	}
 
-	while (!list_is_empty(&intel->batch_pixmaps)) {
-		struct intel_pixmap *entry;
-
-		entry = list_first_entry(&intel->batch_pixmaps,
-					 struct intel_pixmap,
-					 batch);
-
-		entry->batch_read_domains = entry->batch_write_domain = 0;
-		list_del(&entry->batch);
-	}
-
-	while (!list_is_empty(&intel->flush_pixmaps)) {
-		struct intel_pixmap *entry;
-
-		entry = list_first_entry(&intel->flush_pixmaps,
-					 struct intel_pixmap,
-					 flush);
+	while (!list_is_empty(&intel->batch_pixmaps))
+		list_del(intel->batch_pixmaps.next);
 
-		entry->flush_read_domains = entry->flush_write_domain = 0;
-		list_del(&entry->flush);
-	}
+	while (!list_is_empty(&intel->flush_pixmaps))
+		list_del(intel->flush_pixmaps.next);
 
 	while (!list_is_empty(&intel->in_flight)) {
 		struct intel_pixmap *entry;
@@ -148,16 +132,8 @@ void intel_batch_do_flush(ScrnInfoPtr scrn)
 {
 	intel_screen_private *intel = intel_get_screen_private(scrn);
 
-	while (!list_is_empty(&intel->flush_pixmaps)) {
-		struct intel_pixmap *entry;
-
-		entry = list_first_entry(&intel->flush_pixmaps,
-					 struct intel_pixmap,
-					 flush);
-
-		entry->flush_read_domains = entry->flush_write_domain = 0;
-		list_del(&entry->flush);
-	}
+	while (!list_is_empty(&intel->flush_pixmaps))
+		list_del(intel->flush_pixmaps.next);
 
 	intel->need_mi_flush = FALSE;
 }
@@ -239,8 +215,8 @@ void intel_batch_submit(ScrnInfoPtr scrn)
 					 struct intel_pixmap,
 					 batch);
 
-		entry->batch_read_domains = entry->batch_write_domain = 0;
 		entry->busy = -1;
+		entry->batch_write = 0;
 		list_del(&entry->batch);
 	}
 
@@ -249,16 +225,8 @@ void intel_batch_submit(ScrnInfoPtr scrn)
 	 * the work.
 	 */
 	intel->need_mi_flush = !list_is_empty(&intel->flush_pixmaps);
-	while (!list_is_empty(&intel->flush_pixmaps)) {
-		struct intel_pixmap *entry;
-
-		entry = list_first_entry(&intel->flush_pixmaps,
-					 struct intel_pixmap,
-					 flush);
-
-		entry->flush_read_domains = entry->flush_write_domain = 0;
-		list_del(&entry->flush);
-	}
+	while (!list_is_empty(&intel->flush_pixmaps))
+		list_del(intel->flush_pixmaps.next);
 
 	while (!list_is_empty(&intel->in_flight)) {
 		struct intel_pixmap *entry;
diff --git a/src/i830_batchbuffer.h b/src/i830_batchbuffer.h
index 93f786a..5375d2c 100644
--- a/src/i830_batchbuffer.h
+++ b/src/i830_batchbuffer.h
@@ -123,19 +123,13 @@ intel_batch_mark_pixmap_domains(intel_screen_private *intel,
 {
 	assert (read_domains);
 	assert (write_domain == 0 || write_domain == read_domains);
-	assert (write_domain == 0 ||
-		priv->flush_write_domain == 0 ||
-		priv->flush_write_domain == write_domain);
-
-	priv->flush_read_domains |= read_domains;
-	priv->batch_read_domains |= read_domains;
-	priv->flush_write_domain |= write_domain;
-	priv->batch_write_domain |= write_domain;
+
 	if (list_is_empty(&priv->batch))
 		list_add(&priv->batch, &intel->batch_pixmaps);
 	if (list_is_empty(&priv->flush))
 		list_add(&priv->flush, &intel->flush_pixmaps);
 
+	priv->batch_write |= write_domain != 0;
 	priv->busy = 1;
 }
 
diff --git a/src/i830_uxa.c b/src/i830_uxa.c
index 8d67665..7946f91 100644
--- a/src/i830_uxa.c
+++ b/src/i830_uxa.c
@@ -676,7 +676,7 @@ static Bool i830_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access)
 	int ret;
 
 	if (!list_is_empty(&priv->batch) &&
-	    (access == UXA_ACCESS_RW || priv->batch_write_domain))
+	    (access == UXA_ACCESS_RW || priv->batch_write))
 		intel_batch_submit(scrn);
 
 	if (bo->size > intel->max_gtt_map_size) {
commit c187da9a24e98cbdf86f0f0dfbdcd9025c8a4c76
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jun 16 13:16:28 2010 +0100

    i830: GetImage acceleration.
    
    The presumption is that we wish to keep the target hot, so
    copy to a new bo and move that to the CPU in preference to
    causing ping-pong of the original.
    
    Also the gpu is much faster at detiling.
    
    Before (PineView):
     400000 trep @   0.1128 msec (  8860.0/sec): GetImage 10x10 square
      18000 trep @   1.3839 msec (   723.0/sec): GetImage 100x100 square
        800 trep @  30.0987 msec (    33.2/sec): GetImage 500x500 square
    
    After: (PineView)
     180000 trep @   0.1478 msec (  6770.0/sec): GetImage 10x10 square
      60000 trep @   0.4545 msec (  2200.0/sec): GetImage 100x100 square
       4000 trep @   8.0739 msec (   124.0/sec): GetImage 500x500 square
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/common.h b/src/common.h
index 883aaa8..30f1c78 100644
--- a/src/common.h
+++ b/src/common.h
@@ -421,6 +421,7 @@ intel_host_bridge (void);
 enum {
 	INTEL_CREATE_PIXMAP_TILING_X = 0x10000000,
 	INTEL_CREATE_PIXMAP_TILING_Y,
+	INTEL_CREATE_PIXMAP_TILING_NONE,
 };
 
 #endif /* _INTEL_COMMON_H_ */
diff --git a/src/i830_uxa.c b/src/i830_uxa.c
index b69d45e..8d67665 100644
--- a/src/i830_uxa.c
+++ b/src/i830_uxa.c
@@ -831,6 +831,94 @@ static Bool i830_uxa_put_image(PixmapPtr pixmap,
 	}
 }
 
+static Bool i830_uxa_pixmap_get_image(PixmapPtr pixmap,
+				      int x, int y, int w, int h,
+				      char *dst, int dst_pitch)
+{
+	struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap);
+	int stride = i830_pixmap_pitch(pixmap);
+
+	if (dst_pitch == stride && w == pixmap->drawable.width) {
+		return drm_intel_bo_get_subdata(priv->bo, y * stride, stride * h, dst) == 0;
+	} else {
+		char *src;
+		int cpp;
+
+		if (drm_intel_bo_map(priv->bo, FALSE))
+		    return FALSE;
+
+		cpp = pixmap->drawable.bitsPerPixel/8;
+		src = (char *) priv->bo->virtual + y * stride + x * cpp;
+		w *= cpp;
+		do {
+			memcpy(dst, src, w);
+			src += stride;
+			dst += dst_pitch;
+		} while (--h);
+
+		drm_intel_bo_unmap(priv->bo);
+
+		return TRUE;
+	}
+}
+
+static Bool i830_uxa_get_image(PixmapPtr pixmap,
+			       int x, int y,
+			       int w, int h,
+			       char *dst, int dst_pitch)
+{
+	struct intel_pixmap *priv;
+	PixmapPtr scratch = NULL;
+	Bool ret;
+
+	/* The presumption is that we wish to keep the target hot, so
+	 * copy to a new bo and move that to the CPU in preference to
+	 * causing ping-pong of the original.
+	 *
+	 * Also the gpu is much faster at detiling.
+	 */
+
+	priv = i830_get_pixmap_intel(pixmap);
+	if (intel_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) {
+		ScreenPtr screen = pixmap->drawable.pScreen;
+		GCPtr gc;
+
+		/* Copy to a linear buffer and pull.  */
+		scratch = screen->CreatePixmap(screen, w, h,
+					       pixmap->drawable.depth,
+					       INTEL_CREATE_PIXMAP_TILING_NONE);
+		if (!scratch)
+			return FALSE;
+
+		gc = GetScratchGC(pixmap->drawable.depth, screen);
+		if (!gc) {
+			screen->DestroyPixmap(scratch);
+			return FALSE;
+		}
+
+		ValidateGC(&pixmap->drawable, gc);
+
+		gc->ops->CopyArea(&pixmap->drawable,
+				  &scratch->drawable,
+				  gc, x, y, w, h, 0, 0);
+
+		FreeScratchGC(gc);
+
+		intel_batch_submit(xf86Screens[screen->myNum]);
+
+		x = y = 0;
+		pixmap = scratch;
+	}
+
+	ret = i830_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch);
+
+	if (scratch)
+		scratch->drawable.pScreen->DestroyPixmap(scratch);
+
+	return ret;
+
+}
+
 void i830_uxa_block_handler(ScreenPtr screen)
 {
 	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
@@ -884,7 +972,7 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
 		tiling = I915_TILING_X;
 		if (usage == INTEL_CREATE_PIXMAP_TILING_Y)
 			tiling = I915_TILING_Y;
-		if (usage == UXA_CREATE_PIXMAP_FOR_MAP)
+		if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage == INTEL_CREATE_PIXMAP_TILING_NONE)
 			tiling = I915_TILING_NONE;
 
 		if (tiling != I915_TILING_NONE) {
@@ -1069,6 +1157,7 @@ Bool i830_uxa_init(ScreenPtr screen)
 
 	/* PutImage */
 	intel->uxa_driver->put_image = i830_uxa_put_image;
+	intel->uxa_driver->get_image = i830_uxa_get_image;
 
 	intel->uxa_driver->prepare_access = i830_uxa_prepare_access;
 	intel->uxa_driver->finish_access = i830_uxa_finish_access;
commit 0e0101758438debf98f989d815989b45e78cf5f6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 15 12:48:57 2010 +0100

    i830: Tidy i830_uxa_put_image()
    
    Use a single code path to upload the image data after selecting the
    right bo, and take advantage of pwrite() when possible.
    
    Fixes:
    
      Bug 28569 - [i965] IGN's flash-based video player crashes X
      https://bugs.freedesktop.org/show_bug.cgi?id=28569
    
      Bug 28573 - [i965] Fullscreen flash and windowed SDL games fail to
                  update the screen
      https://bugs.freedesktop.org/show_bug.cgi?id=28573
    
    Reported-and-tested-by: Brian Rogers <brian at xyzw.org>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/i830.h b/src/i830.h
index 02220ea..a5fee3d 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -165,12 +165,17 @@ list_is_empty(struct list *head)
 
 struct intel_pixmap {
 	dri_bo *bo;
-	uint32_t tiling, stride;
-	uint32_t flush_write_domain;
-	uint32_t flush_read_domains;
-	uint32_t batch_write_domain;
-	uint32_t batch_read_domains;
+
 	struct list flush, batch, in_flight;
+
+	int8_t busy;
+	uint8_t tiling;
+	uint16_t stride;
+
+	uint16_t flush_write_domain;
+	uint16_t flush_read_domains;
+	uint16_t batch_write_domain;
+	uint16_t batch_read_domains;
 };
 
 #if HAS_DEVPRIVATEKEYREC
@@ -188,6 +193,13 @@ static inline struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap)
 #endif
 }
 
+static inline Bool intel_pixmap_is_busy(struct intel_pixmap *priv)
+{
+	if (priv->busy == -1)
+		priv->busy = drm_intel_bo_busy(priv->bo);
+	return priv->busy;
+}
+
 static inline void i830_set_pixmap_intel(PixmapPtr pixmap, struct intel_pixmap *intel)
 {
 	dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, intel);
diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index ada5809..46c9d4f 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -240,6 +240,7 @@ void intel_batch_submit(ScrnInfoPtr scrn)
 					 batch);
 
 		entry->batch_read_domains = entry->batch_write_domain = 0;
+		entry->busy = -1;
 		list_del(&entry->batch);
 	}
 
diff --git a/src/i830_batchbuffer.h b/src/i830_batchbuffer.h
index 7508a9c..93f786a 100644
--- a/src/i830_batchbuffer.h
+++ b/src/i830_batchbuffer.h
@@ -135,6 +135,8 @@ intel_batch_mark_pixmap_domains(intel_screen_private *intel,
 		list_add(&priv->batch, &intel->batch_pixmaps);
 	if (list_is_empty(&priv->flush))
 		list_add(&priv->flush, &intel->flush_pixmaps);
+
+	priv->busy = 1;
 }
 
 static inline void
diff --git a/src/i830_uxa.c b/src/i830_uxa.c
index bf364f8..b69d45e 100644
--- a/src/i830_uxa.c
+++ b/src/i830_uxa.c
@@ -629,6 +629,7 @@ void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo)
 	}
 
 	if (bo != NULL) {
+		uint32_t tiling;
 		uint32_t swizzle_mode;
 		int ret;
 
@@ -646,12 +647,15 @@ void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo)
 		priv->stride = i830_pixmap_pitch(pixmap);
 
 		ret = drm_intel_bo_get_tiling(bo,
-					      &priv->tiling,
+					      &tiling,
 					      &swizzle_mode);
 		if (ret != 0) {
 			FatalError("Couldn't get tiling on bo %p: %s\n",
 				   bo, strerror(-ret));
 		}
+
+		priv->tiling = tiling;
+		priv->busy = -1;
 	} else {
 		if (priv != NULL) {
 			free(priv);
@@ -696,6 +700,7 @@ static Bool i830_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access)
 	}
 
 	pixmap->devPrivate.ptr = bo->virtual;
+	priv->busy = 0;
 
 	return TRUE;
 }
@@ -718,78 +723,33 @@ static void i830_uxa_finish_access(PixmapPtr pixmap)
 	pixmap->devPrivate.ptr = NULL;
 }
 
-static Bool i830_bo_put_image(PixmapPtr pixmap, dri_bo *bo, char *src, int src_pitch, int w, int h)
+static Bool i830_uxa_pixmap_put_image(PixmapPtr pixmap,
+				      char *src, int src_pitch,
+				      int x, int y, int w, int h)
 {
+	struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap);
 	int stride = i830_pixmap_pitch(pixmap);
-
-	if (src_pitch == stride) {
-		memcpy (bo->virtual, src, stride * h);
-	} else {
-		char *dst = bo->virtual;
-		int row_length = w * pixmap->drawable.bitsPerPixel/8;
+	int ret = FALSE;
+
+	if (src_pitch == stride && w == pixmap->drawable.width && priv->tiling == I915_TILING_NONE) {
+		ret = drm_intel_bo_subdata(priv->bo, y * stride, stride * h, src) == 0;
+	} else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) {
+		char *dst = priv->bo->virtual;
+		int cpp = pixmap->drawable.bitsPerPixel/8;
+		int row_length = w * cpp;
 		int num_rows = h;
-		while (num_rows--) {
+		if (row_length == src_pitch && src_pitch == stride)
+			num_rows = 1, row_length *= h;
+		dst += y * stride + x * cpp;
+		do {
 			memcpy (dst, src, row_length);
 			src += src_pitch;
 			dst += stride;
-		}
-	}
-
-	return TRUE;
-}
-
-static Bool
-i830_uxa_pixmap_swap_bo_with_image(PixmapPtr pixmap,
-				   char *src, int src_pitch)
-{
-	ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum];
-	intel_screen_private *intel = intel_get_screen_private(scrn);
-	struct intel_pixmap *priv;
-	dri_bo *bo;
-	uint32_t tiling = I915_TILING_X;
-	int stride;
-	int w = pixmap->drawable.width;
-	int h = pixmap->drawable.height;
-	Bool ret;
-
-	priv = i830_get_pixmap_intel(pixmap);
-
-	if (priv->batch_read_domains || drm_intel_bo_busy(priv->bo)) {
-		unsigned int size;
-
-		size = i830_uxa_pixmap_compute_size (pixmap, w, h,
-						     &tiling, &stride);
-		if (size > intel->max_gtt_map_size)
-			return FALSE;
-
-		bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0);
-		if (bo == NULL)
-			return FALSE;
-
-		if (tiling != I915_TILING_NONE)
-			drm_intel_bo_set_tiling(bo, &tiling, stride);
-
-		pixmap->drawable.pScreen->ModifyPixmapHeader(pixmap,
-							     w, h,
-							     0, 0,
-							     stride, NULL);
-		i830_set_pixmap_bo(pixmap, bo);
-		dri_bo_unreference(bo);
-	} else {
-		bo = priv->bo;
-		stride = i830_pixmap_pitch(pixmap);
-	}
-
-	if (drm_intel_gem_bo_map_gtt(bo)) {
-		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-			   "%s: bo map failed\n", __FUNCTION__);
-		return FALSE;
+		} while (--num_rows);
+		drm_intel_gem_bo_unmap_gtt(priv->bo);
+		ret = TRUE;
 	}
 
-	ret = i830_bo_put_image(pixmap, bo, src, src_pitch, w, h);
-
-	drm_intel_gem_bo_unmap_gtt(bo);
-
 	return ret;
 }
 
@@ -798,114 +758,77 @@ static Bool i830_uxa_put_image(PixmapPtr pixmap,
 			       int w, int h,
 			       char *src, int src_pitch)
 {
-	ScreenPtr screen = pixmap->drawable.pScreen;
-	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-	PixmapPtr scratch;
 	struct intel_pixmap *priv;
-	GCPtr gc;
-	Bool ret;
-
-	if (x == 0 && y == 0 &&
-	    w == pixmap->drawable.width &&
-	    h == pixmap->drawable.height)
-	{
-		/* Replace GPU hot bo with new CPU data. */
-		return i830_uxa_pixmap_swap_bo_with_image(pixmap,
-							  src, src_pitch);
-	}
 
 	priv = i830_get_pixmap_intel(pixmap);
-	if (priv->batch_read_domains ||
-	    drm_intel_bo_busy(priv->bo)) {
-		dri_bo *bo;
-
-		/* Partial replacement, copy incoming image to a bo and blit. */
-		scratch = (*screen->CreatePixmap)(screen, w, h,
-						  pixmap->drawable.depth,
-						  UXA_CREATE_PIXMAP_FOR_MAP);
-		if (!scratch)
-			return FALSE;
-
-		bo = i830_get_pixmap_bo(scratch);
-		if (drm_intel_gem_bo_map_gtt(bo)) {
-			(*screen->DestroyPixmap) (scratch);
-			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-				   "%s: bo map failed\n", __FUNCTION__);
-			return FALSE;
-		}
-
-		ret = i830_bo_put_image(scratch, bo, src, src_pitch, w, h);
-
-		drm_intel_gem_bo_unmap_gtt(bo);
-
-		if (ret) {
-			gc = GetScratchGC(pixmap->drawable.depth, screen);
-			if (gc) {
-				ValidateGC(&pixmap->drawable, gc);
-
-				(*gc->ops->CopyArea)(&scratch->drawable,
-						     &pixmap->drawable,
-						     gc, 0, 0, w, h, x, y);
-
-				FreeScratchGC(gc);
-			} else
-				ret = FALSE;
-		}
-
-		(*screen->DestroyPixmap)(scratch);
+	if (!intel_pixmap_is_busy(priv)) {
+		/* bo is not busy so can be replaced without a stall, upload in-place. */
+		return i830_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h);
 	} else {
-		int dst_pitch;
+		ScreenPtr screen = pixmap->drawable.pScreen;
 
-		/* bo is not busy so can be mapped without a stall, upload in-place. */
-		if (drm_intel_gem_bo_map_gtt(priv->bo)) {
-			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-				   "%s: bo map failed\n", __FUNCTION__);
-			return FALSE;
+		if (x == 0 && y == 0 &&
+		    w == pixmap->drawable.width &&
+		    h == pixmap->drawable.height)
+		{
+			intel_screen_private *intel = intel_get_screen_private(xf86Screens[screen->myNum]);
+			uint32_t tiling = priv->tiling;
+			int size, stride;
+			dri_bo *bo;
+
+			/* Replace busy bo. */
+			size = i830_uxa_pixmap_compute_size (pixmap, w, h,
+							     &tiling, &stride);
+			if (size > intel->max_gtt_map_size)
+				return FALSE;
+
+			bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0);
+			if (bo == NULL)
+				return FALSE;
+
+			if (tiling != I915_TILING_NONE)
+				drm_intel_bo_set_tiling(bo, &tiling, stride);
+
+			screen->ModifyPixmapHeader(pixmap,
+						   w, h,
+						   0, 0,
+						   stride, NULL);
+			i830_set_pixmap_bo(pixmap, bo);
+			dri_bo_unreference(bo);
+
+			return i830_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h);
 		}
-
-		ret = TRUE;
-
-		/* Older version of pixman did not allow blt for <= 8bpp
-		 * images, so if the blt fails fallback to using the fb.
-		 */
-		dst_pitch = i830_pixmap_pitch (pixmap);
-		if (! pixman_blt((uint32_t *)src,
-				 priv->bo->virtual,
-				 src_pitch / sizeof(uint32_t),
-				 dst_pitch / sizeof(uint32_t),
-				 pixmap->drawable.bitsPerPixel,
-				 pixmap->drawable.bitsPerPixel,
-				 0, 0,
-				 x, y,
-				 w, h))
+		else
 		{
-			ret = FALSE;
-
-			scratch = GetScratchPixmapHeader(screen,
-							 w, h,
-							 pixmap->drawable.depth,
-							 pixmap->drawable.bitsPerPixel,
-							 src_pitch,
-							 (pointer) src);
-			if (scratch) {
-				gc = GetScratchGC(pixmap->drawable.depth, screen);
+			PixmapPtr scratch;
+			Bool ret;
+
+			/* Upload to a linear buffer and queue a blit.  */
+			scratch = (*screen->CreatePixmap)(screen, w, h,
+							  pixmap->drawable.depth,
+							  UXA_CREATE_PIXMAP_FOR_MAP);
+			if (!scratch)
+				return FALSE;
+
+			ret = i830_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h);
+			if (ret) {
+				GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen);
 				if (gc) {
 					ValidateGC(&pixmap->drawable, gc);
-					pixmap->devPrivate.ptr = priv->bo->virtual;
-					ret = !! fbCopyArea(&scratch->drawable, &pixmap->drawable, gc,
-							    0, 0,
-							    w, h,
-							    x, y);
+
+					(*gc->ops->CopyArea)(&scratch->drawable,
+							     &pixmap->drawable,
+							     gc, 0, 0, w, h, x, y);
+
 					FreeScratchGC(gc);
-				}
-				FreeScratchPixmapHeader(scratch);
+				} else
+					ret = FALSE;
 			}
-		}
 
-		drm_intel_gem_bo_unmap_gtt(priv->bo);
+			(*screen->DestroyPixmap)(scratch);
+			return ret;
+		}
 	}
-
-	return ret;
 }
 
 void i830_uxa_block_handler(ScreenPtr screen)
@@ -1024,25 +947,26 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
 			return NullPixmap;
 		}
 
-		if (usage == UXA_CREATE_PIXMAP_FOR_MAP)
+		if (usage == UXA_CREATE_PIXMAP_FOR_MAP) {
+			priv->busy = 0;
 			priv->bo = drm_intel_bo_alloc(intel->bufmgr,
 						      "pixmap", size, 0);
-		else
+		} else {
+			priv->busy = -1;
 			priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr,
 								 "pixmap",
 								 size, 0);
+		}
 		if (!priv->bo) {
 			free(priv);
 			fbDestroyPixmap(pixmap);
 			return NullPixmap;
 		}
 
+		if (tiling != I915_TILING_NONE)
+			drm_intel_bo_set_tiling(priv->bo, &tiling, stride);
 		priv->stride = stride;
 		priv->tiling = tiling;
-		if (priv->tiling != I915_TILING_NONE)
-			drm_intel_bo_set_tiling(priv->bo,
-						&priv->tiling,
-						stride);
 
 		screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL);
 
@@ -1072,6 +996,7 @@ void i830_uxa_create_screen_resources(ScreenPtr screen)
 	if (bo != NULL) {
 		PixmapPtr pixmap = screen->GetScreenPixmap(screen);
 		i830_set_pixmap_bo(pixmap, bo);
+		i830_get_pixmap_intel(pixmap)->busy = 1;
 	}
 }
 
commit 2ff7a2fc9d939554502e9adec89cae5597a9e82c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 17 13:56:30 2010 +0100

    i915: Force the emission of BUF_INFO on every composite_setup
    
    We should be able to eliminate these as the drawable remains unchanged.
    However, the implicit flush of BUF_INFO fixes the rendering in KDE.
    Alternatively, we need an MI_FLUSH | INHIBIT_RENDER_CACHE_FLUSH between
    composites. (Note that it is not stale cache data causing the rendering
    corruption and that a pipelined flush is not sufficient either.) Also,
    having tried varies points at which to flush, the only place where the
    flush is effective seems to be between composite operations - that is a
    flush after 2D is not sufficient.
    
    Reported-by: Vasily Khoruzhick <anarsoul at gmail.com>
    Reported-by: Clemens Eisserer <linuxhippy at gmail.com>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/i915_render.c b/src/i915_render.c
index b2bc7a7..782c259 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -1032,10 +1032,15 @@ static void i915_emit_composite_setup(ScrnInfoPtr scrn)
 	    OUT_BATCH (intel->render_mask_solid);
 	}
 
-	/* BUF_INFO is an implicit flush, so avoid if the target has not changed */
-	if (dest != intel->render_current_dest) {
+	/* BUF_INFO is an implicit flush, so avoid if the target has not changed.
+	 * XXX However for reasons unfathomed, correct rendering in KDE requires
+	 * at least a MI_FLUSH | INHIBIT_RENDER_CACHE_FLUSH here.
+	 */
+	if (1 || dest != intel->render_current_dest) {
 		uint32_t tiling_bits;
 
+		intel_batch_do_flush(scrn);
+
 		if (i830_pixmap_tiled(dest)) {
 			tiling_bits = BUF_3D_TILED_SURFACE;
 			if (i830_get_pixmap_intel(dest)->tiling


More information about the xorg-commit mailing list