From 6d33e578de4e23336ac69cc3c5d0935a65d4dda1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 23 Jun 2010 21:28:50 +0100 Subject: [PATCH] Limit maximum tiled stride to 8k and untiled to 32k. Tiling on gen 2/3 hardware is only supported for pitches up to 8192 bytes, so above this limit the surface will be untiled and we will no longer have to comply with the power-of-two pitch alignment. So disabling tiling for these too wide surface should ~halve the memory requirement for the full surface. Also the absolute limit for the 2D blitter is 32,768 bytes. The documentation says "up to 32,768 bytes" and my PineView box was malfunction with a surface stride of 32,768 so set the limit to be 32,767. References: Bug 28497 - Graphics corruption after opening a specific website https://bugs.freedesktop.org/show_bug.cgi?id=28497 Signed-off-by: Chris Wilson --- src/i830_uxa.c | 53 +++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/i830_uxa.c b/src/i830_uxa.c index 1ec7ab8f..61e857ff 100644 --- a/src/i830_uxa.c +++ b/src/i830_uxa.c @@ -152,14 +152,13 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, { ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); - int pitch, pitch_align; - int size; + int pitch, size; if (*tiling != I915_TILING_NONE) { /* First check whether tiling is necessary. */ - pitch_align = intel->accel_pixmap_pitch_alignment; - size = ROUND_TO((w * pixmap->drawable.bitsPerPixel + 7) / 8, - pitch_align) * ALIGN (h, 2); + pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; + pitch = ROUND_TO(pitch, intel->accel_pixmap_pitch_alignment); + size = pitch * ALIGN (h, 2); if (!IS_I965G(intel)) { /* Older hardware requires fences to be pot size * aligned with a minimum of 1 MiB, so causes @@ -167,6 +166,12 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, */ if (size < 1024*1024/2) *tiling = I915_TILING_NONE; + + /* Gen 2/3 has a maximum stride for tiling of + * 8192 bytes. + */ + if (pitch > KB(8)) + *tiling = I915_TILING_NONE; } else if (size <= 4096) { /* Disable tiling beneath a page size, we will not see * any benefit from reducing TLB misses and instead @@ -179,29 +184,19 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; if (pitch <= 256) *tiling = I915_TILING_NONE; - repeat: - if (*tiling == I915_TILING_NONE) { - pitch_align = intel->accel_pixmap_pitch_alignment; - } else { - pitch_align = 512; - } - *stride = ROUND_TO(pitch, pitch_align); - - if (*tiling == I915_TILING_NONE) { - /* Round the height up so that the GPU's access to a 2x2 aligned - * subspan doesn't address an invalid page offset beyond the - * end of the GTT. - */ - size = *stride * ALIGN(h, 2); - } else { + if (*tiling != I915_TILING_NONE) { int aligned_h; + if (*tiling == I915_TILING_X) aligned_h = ALIGN(h, 8); else aligned_h = ALIGN(h, 32); - *stride = i830_get_fence_pitch(intel, *stride, *tiling); + *stride = i830_get_fence_pitch(intel, + ROUND_TO(pitch, 512), + *tiling); + /* 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, @@ -209,12 +204,18 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, * with drm_intel_bufmgr_check_aperture(). */ size = i830_get_fence_size(intel, *stride * aligned_h); - assert(size >= *stride * aligned_h); + + if (size > intel->max_tiling_size) + *tiling = I915_TILING_NONE; } - if (*tiling != I915_TILING_NONE && size > intel->max_tiling_size) { - *tiling = I915_TILING_NONE; - goto repeat; + if (*tiling == I915_TILING_NONE) { + /* Round the height up so that the GPU's access to a 2x2 aligned + * subspan doesn't address an invalid page offset beyond the + * end of the GTT. + */ + *stride = ROUND_TO(pitch, intel->accel_pixmap_pitch_alignment); + size = *stride * ALIGN(h, 2); } return size; @@ -987,7 +988,7 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, * frequently, and also will tend to fail to successfully map when doing * SW fallbacks because we overcommit address space for BO access. */ - if (size > intel->max_bo_size) { + if (size > intel->max_bo_size || stride >= KB(32)) { fbDestroyPixmap(pixmap); return fbCreatePixmap(screen, w, h, depth, usage); }