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

Jesse Barnes jbarnes at virtuousgeek.org
Tue Jan 27 02:14:06 CET 2009


On Friday, January 23, 2009 5:57 pm Eric Anholt wrote:
> 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.

Ok this one should be a little cleaner.  I just removed the alignment passing
in create_pixmap since we don't use it anyway.  As for size & stride, we can
probably calculate that in the kernel given the object's tiling mode, but then
our obj->size wouldn't match reality (right now I think it give an accurate
view of aperture space required for an object, might be a pain to lose that).

Testers welcome on this patchset (the libdrm portion hasn't changed); hope we
can get it pushed upstream soon.

Thanks,
Jesse

diff --git a/src/common.h b/src/common.h
index 4a87acb..be222df 100644
--- a/src/common.h
+++ b/src/common.h
@@ -367,6 +367,8 @@ extern int I810_DEBUG;
 #define SUPPORTS_INTEGRATED_HDMI(pI810) (IS_G4X(pI810))
 /* dsparb controlled by hw only */
 #define DSPARB_HWCONTROL(pI810) (IS_G4X(pI810))
+/* supports Y tiled surfaces (pre-965 Mesa isn't ready yet) */
+#define SUPPORTS_YTILING(pI810) (IS_I965G(pI830))
 
 #define GTT_PAGE_SIZE			KB(4)
 #define ROUND_TO(x, y)			(((x) + (y) - 1) / (y) * (y))
diff --git a/src/i830.h b/src/i830.h
index 4ee9c39..f601dbd 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -725,6 +725,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;
@@ -911,6 +912,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..7a95d02 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 (SUPPORTS_YTILING(pI830))
 		    tiling = I915_TILING_Y;
 		else
 		    tiling = I915_TILING_X;
@@ -1583,19 +1583,14 @@ 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;
 
 	    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..0a8dced 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -882,11 +882,22 @@ 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);
+
+	bo = dri_bo_alloc (i830->bufmgr, "pixmap", size, 0);
 	if (!bo) {
 	    fbDestroyPixmap (pixmap);
 	    return NullPixmap;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index ab4e5ce..9709480 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -133,10 +133,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;
 
@@ -159,6 +158,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)
 {
@@ -390,6 +426,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
@@ -501,6 +538,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;
@@ -771,7 +820,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 = i830_get_fence_alignment(pI830, size);
 
     mem = xcalloc(1, sizeof(*mem));
     if (mem == NULL)
@@ -889,16 +938,8 @@ 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);
-	if (IS_I965G(pI830)) {
-	    if (alignment < GTT_PAGE_SIZE)
-		alignment = GTT_PAGE_SIZE;
-	} else {
-	    /* The offset has to be aligned to at least the size of the fence
-	     * region.
-	     */
-	    alignment = size;
-	}
+	size = i830_get_fence_size(pI830, size);
+	alignment = i830_get_fence_alignment(pI830, size);
     }
 #ifdef XF86DRI
     if (pI830->use_drm_mode || (pI830->memory_manager &&



More information about the Intel-gfx mailing list