summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2009-01-26 17:14:06 -0800
committerEric Anholt <eric@anholt.net>2009-01-27 14:33:43 -0800
commit8d4bc36fae50b09a73ba2cfab920adb32141a358 (patch)
tree509111af04c4094f685431997d2749987dc30a8b
parent6c0ca1676bf60529dd331cc739abdf68fa9e918d (diff)
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.
-rw-r--r--src/common.h2
-rw-r--r--src/i830.h4
-rw-r--r--src/i830_dri.c13
-rw-r--r--src/i830_driver.c1
-rw-r--r--src/i830_exa.c20
-rw-r--r--src/i830_memory.c71
6 files changed, 84 insertions, 27 deletions
diff --git a/src/common.h b/src/common.h
index 4a87acb6..be222df5 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 47941695..d9adfbfd 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 d6698daa..7a95d027 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 bf5ecc49..2c4ea077 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 92490741..28be786b 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -882,11 +882,25 @@ 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);
+ /* Round the object up to the size of the fence it will live in
+ * if necessary. We could potentially make the kernel allocate
+ * a larger aperture space and just bind the subset of pages in,
+ * but this is easier and also keeps us out of trouble (as much)
+ * with drm_intel_bufmgr_check_aperture().
+ */
+ 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 9bfee818..f3c55a34 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 = i830_get_fence_alignment(pI830, size);
mem = xcalloc(1, sizeof(*mem));
if (mem == NULL)
@@ -814,7 +863,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
break;
}
- ret = dri_bo_set_tiling(mem->bo, &bo_tiling_mode);
+ ret = drm_intel_bo_set_tiling(mem->bo, &bo_tiling_mode, pitch);
if (ret != 0 || (bo_tiling_mode == I915_TILING_NONE && tile_format != TILE_NONE)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to set tiling on %s: %s\n",
@@ -887,16 +936,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 &&