[Intel-gfx] [PATCH] support tiled rendering in 2D driver

Eric Anholt eric at anholt.net
Sat Jan 24 02:57:41 CET 2009


On Fri, 2009-01-23 at 16:24 -0800, Eric Anholt wrote:
> On Fri, 2009-01-23 at 14:15 -0800, Jesse Barnes wrote:
> > Set alignments, tile settings and flags correctly in the 2D driver to support
> > tiled rendering.  UXA's create pixmap function currently assumes the worst
> > about the alignment constraints; that should probably be fixed.  Some of the
> > 1M alignment fixes could probably be done more cleanly as well.

Updated version incorporating my comments.  Note the XXXs.  With this
I've seen OA go from 5.5fps to 34.7fps on my eee 901, so I think we're
looking pretty good once we clean a few messes up.  I had to disable
TILING_Y to get correct rendering with OA, which we should probably look
into.

From 1d9cda617f29badf50584bafa42ea597f1a5b27d Mon Sep 17 00:00:00 2001
From: Jesse Barnes <jbarnes at virtuousgeek.org>
Date: Fri, 23 Jan 2009 14:15:26 -0800
Subject: [PATCH] Support tiled back/depth on 915-class hardware with DRI2.

Set alignments, tile settings and flags correctly in the 2D driver to support
tiled rendering.  UXA's create pixmap function currently assumes the worst
about the alignment constraints; that should probably be fixed.  Some of the
1M alignment fixes could probably be done more cleanly as well.
---
 src/i830.h        |    4 +++
 src/i830_dri.c    |   14 ++++-------
 src/i830_driver.c |    1 +
 src/i830_exa.c    |   23 ++++++++++++++++---
 src/i830_memory.c |   61 +++++++++++++++++++++++++++++++++++++++++++++++-----
 5 files changed, 84 insertions(+), 19 deletions(-)

diff --git a/src/i830.h b/src/i830.h
index 4794169..d9adfbf 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -724,6 +724,7 @@ typedef struct _I830Rec {
    enum last_3d *last_3d;
 
    Bool use_drm_mode;
+   Bool kernel_exec_fencing;
 #ifdef XF86DRM_MODE
    drmmode_rec drmmode;
    int drm_mm_init;
@@ -910,6 +911,9 @@ extern void i830WaitSync(ScrnInfoPtr pScrn);
 /* i830_memory.c */
 Bool i830_bind_all_memory(ScrnInfoPtr pScrn);
 Bool i830_unbind_all_memory(ScrnInfoPtr pScrn);
+unsigned long i830_get_fence_size(I830Ptr pI830, unsigned long size);
+unsigned long i830_get_fence_pitch(I830Ptr pI830, unsigned long pitch, int format);
+unsigned long i830_get_fence_alignment(I830Ptr pI830, unsigned long size);
 
 Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
 Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index d6698da..da5b7cd 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1570,7 +1570,7 @@ I830DRI2CreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count)
 					       pDraw->depth, 0);
 	    switch (attachments[i]) {
 	    case DRI2BufferDepth:
-		if (IS_I965G(pI830))
+		if (IS_I965G(pI830) /* || IS_I945GM(pI830) || IS_I945G(pI830) */)
 		    tiling = I915_TILING_Y;
 		else
 		    tiling = I915_TILING_X;
@@ -1583,19 +1583,15 @@ I830DRI2CreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count)
 		break;
 	    }
 
-	    /* Disable tiling on 915-class 3D for now.  Because the 2D blitter
-	     * requires fence regs to operate, and they're not being managed
-	     * by the kernel yet, we don't want to expose tiled buffers to the
-	     * 3D client as it'll just render incorrectly if it pays attention
-	     * to our tiling bits at all.
-	     */
-	    if (!IS_I965G(pI830))
+	    if (!pI830->tiling ||
+		(!IS_I965G(pI830) && !pI830->kernel_exec_fencing))
 		tiling = I915_TILING_NONE;
 
+	    ErrorF("tiling %d %d\n", attachments[i], tiling);
 	    if (tiling != I915_TILING_NONE) {
 		bo = i830_get_pixmap_bo(pPixmap);
 		drm_intel_bo_set_tiling(bo, &tiling,
-					pDraw->width * pDraw->bitsPerPixel / 8);
+					intel_get_pixmap_pitch(pPixmap));
 	    }
 	}
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index bf5ecc4..2c4ea07 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1822,6 +1822,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
    pI830->SaveGeneration = -1;
    pI830->pEnt = pEnt;
    pI830->use_drm_mode = drm_mode_setting;
+   pI830->kernel_exec_fencing = pI830->use_drm_mode;
 
    if (!I830LoadSyms(pScrn))
        return FALSE;
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 9249074..f293d19 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -872,7 +872,7 @@ i830_uxa_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usag
     ScrnInfoPtr scrn = xf86Screens[screen->myNum];
     I830Ptr i830 = I830PTR(scrn);
     dri_bo *bo;
-    int stride;
+    int stride, align;
     PixmapPtr pixmap;
     
     if (w > 32767 || h > 32767)
@@ -882,11 +882,26 @@ i830_uxa_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usag
     
     if (w && h)
     {
+	unsigned int size;
+
 	stride = ROUND_TO((w * pixmap->drawable.bitsPerPixel + 7) / 8,
 			  i830->accel_pixmap_pitch_alignment);
-    
-	bo = dri_bo_alloc (i830->bufmgr, "pixmap", stride * h, 
-			   i830->accel_pixmap_offset_alignment);
+
+	/* Use the I915_FENCE_TILING_X even if it may end up being TILING_Y,
+	 * as it just results in larger alignment.  Really, we need to use the
+	 * usage hint to tell what the pixmap's going to be.
+	 */
+	stride = i830_get_fence_pitch(i830, stride, I915_TILING_X);
+	/* XXX: Hack!  The kernel should really just allocate the aperture
+	 * space for us, and stuff our tiny object into it.
+	 */
+	size = i830_get_fence_size(i830, stride * h);
+	/* XXX: The kernel just calculates this anyway, we shouldn't have to
+	 * care.
+	 */
+	align = i830_get_fence_alignment(i830, size);
+
+	bo = dri_bo_alloc (i830->bufmgr, "pixmap", size, align);
 	if (!bo) {
 	    fbDestroyPixmap (pixmap);
 	    return NullPixmap;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 9bfee81..7830e4c 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -132,10 +132,9 @@ static void i830_clear_tiling(ScrnInfoPtr pScrn, unsigned int fence_nr);
 /**
  * Returns the fence size for a tiled area of the given size.
  */
-static unsigned long
-i830_get_fence_size(ScrnInfoPtr pScrn, unsigned long size)
+unsigned long
+i830_get_fence_size(I830Ptr pI830, unsigned long size)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
     unsigned long i;
     unsigned long start;
 
@@ -158,6 +157,43 @@ i830_get_fence_size(ScrnInfoPtr pScrn, unsigned long size)
     }
 }
 
+/**
+ * On some chips, pitch width has to be a power of two tile width, so
+ * calculate that here.
+ */
+unsigned long
+i830_get_fence_pitch(I830Ptr pI830, unsigned long pitch, int format)
+{
+    unsigned long i;
+    unsigned long tile_width = (format == I915_TILING_Y) ? 128 : 512;
+
+    if (format == TILE_NONE)
+	return pitch;
+
+    /* 965 is flexible */
+    if (IS_I965G(pI830))
+	return ROUND_TO(pitch, tile_width);
+
+    /* Pre-965 needs power of two tile width */
+    for (i = tile_width; i < pitch; i <<= 1)
+	;
+
+    return i;
+}
+
+/**
+ * On some chips, pitch width has to be a power of two tile width, so
+ * calculate that here.
+ */
+unsigned long
+i830_get_fence_alignment(I830Ptr pI830, unsigned long size)
+{
+    if (IS_I965G(pI830))
+	return 4096;
+    else
+	return i830_get_fence_size(pI830, size);
+}
+
 static Bool
 i830_check_display_stride(ScrnInfoPtr pScrn, int stride, Bool tiling)
 {
@@ -388,6 +424,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 #ifdef XF86DRI
     int dri_major, dri_minor, dri_patch;
     struct drm_i915_getparam gp;
+    struct drm_i915_setparam sp;
     int has_gem;
     int has_dri;
 #endif
@@ -499,6 +536,18 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 		struct drm_i915_gem_init init;
 		int ret;
 
+		sp.param = I915_SETPARAM_NUM_USED_FENCES;
+		if (pI830->use_drm_mode)
+		    sp.value = 0; /* kernel gets them all */
+		else if (pI830->directRenderingType == DRI_XF86DRI)
+		    sp.value = 3; /* front/back/depth */
+		else
+		    sp.value = 2; /* just front for DRI2 (both old & new though) */
+		ret = drmCommandWrite(pI830->drmSubFD, DRM_I915_SETPARAM, &sp,
+				      sizeof(sp));
+		if (ret == 0)
+		    pI830->kernel_exec_fencing = TRUE;
+
 		init.gtt_start = pI830->memory_manager->offset;
 		init.gtt_end = pI830->memory_manager->offset +
 		    pI830->memory_manager->size;
@@ -769,7 +818,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
 
     /* Only allocate page-sized increments. */
     size = ALIGN(size, GTT_PAGE_SIZE);
-    align = ROUND_TO(align, GTT_PAGE_SIZE);
+    align = size > 1024*1024 ? size : 1024*1024;
 
     mem = xcalloc(1, sizeof(*mem));
     if (mem == NULL)
@@ -887,7 +936,7 @@ i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
 	}
 
 	/* round to size necessary for the fence register to work */
-	size = i830_get_fence_size(pScrn, size);
+	size = i830_get_fence_size(pI830, size);
 	if (IS_I965G(pI830)) {
 	    if (alignment < GTT_PAGE_SIZE)
 		alignment = GTT_PAGE_SIZE;
@@ -895,7 +944,7 @@ i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
 	    /* The offset has to be aligned to at least the size of the fence
 	     * region.
 	     */
-	    alignment = size;
+	    alignment = size > 1024*1024 ? size : 1024*1024;
 	}
     }
 #ifdef XF86DRI
-- 
1.5.6.5

-- 
Eric Anholt
eric at anholt.net                         eric.anholt at intel.com


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: This is a digitally signed message part
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20090123/916686d1/attachment.sig>


More information about the Intel-gfx mailing list