From 4ab99d67990d5834061a10b0bd1dd220d4611248 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 16 Jun 2014 12:51:08 +0100 Subject: [PATCH] uxa: Allocate frontbuffer to meet old fence constaints libdrm is a little lax and does not allocate sufficient space for us to safely use buffers on old gen. So compute the size we want for ourselves. Reported-by: Cem Aydin Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=80088 Signed-off-by: Chris Wilson --- src/uxa/intel.h | 8 ++-- src/uxa/intel_display.c | 7 ++-- src/uxa/intel_driver.c | 5 +-- src/uxa/intel_memory.c | 107 +++--------------------------------------------- src/uxa/intel_uxa.c | 81 ++++++++++++++++++++++++++++++------ 5 files changed, 84 insertions(+), 124 deletions(-) diff --git a/src/uxa/intel.h b/src/uxa/intel.h index 2ebad64..409635d 100644 --- a/src/uxa/intel.h +++ b/src/uxa/intel.h @@ -536,11 +536,13 @@ int intel_crtc_to_pipe(xf86CrtcPtr crtc); unsigned long intel_get_fence_size(intel_screen_private *intel, unsigned long size); unsigned long intel_get_fence_pitch(intel_screen_private *intel, unsigned long pitch, uint32_t tiling_mode); +Bool intel_check_display_stride(ScrnInfoPtr scrn, int stride, Bool tiling); +void intel_set_gem_max_sizes(ScrnInfoPtr scrn); drm_intel_bo *intel_allocate_framebuffer(ScrnInfoPtr scrn, - int w, int h, int cpp, - unsigned long *pitch, - uint32_t *tiling); + int width, int height, int cpp, + int *out_stride, + uint32_t *out_tiling); /* i830_render.c */ Bool i830_check_composite(int op, diff --git a/src/uxa/intel_display.c b/src/uxa/intel_display.c index 5bb9d72..b90061b 100644 --- a/src/uxa/intel_display.c +++ b/src/uxa/intel_display.c @@ -511,7 +511,7 @@ intel_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) ScrnInfoPtr scrn = crtc->scrn; struct intel_crtc *intel_crtc = crtc->driver_private; struct intel_mode *mode = intel_crtc->mode; - unsigned long rotate_pitch; + int rotate_pitch; uint32_t tiling; int ret; @@ -1401,7 +1401,7 @@ intel_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) Bool ret; uint32_t old_fb_id; int i, old_width, old_height, old_pitch; - unsigned long pitch; + int pitch; uint32_t tiling; ScreenPtr screen; @@ -1431,8 +1431,7 @@ intel_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) intel->front_buffer = intel_allocate_framebuffer(scrn, width, height, intel->cpp, - &pitch, - &tiling); + &pitch, &tiling); if (!intel->front_buffer) goto fail; diff --git a/src/uxa/intel_driver.c b/src/uxa/intel_driver.c index 1952dcc..c73d831 100644 --- a/src/uxa/intel_driver.c +++ b/src/uxa/intel_driver.c @@ -717,14 +717,13 @@ intel_init_initial_framebuffer(ScrnInfoPtr scrn) intel_screen_private *intel = intel_get_screen_private(scrn); int width = scrn->virtualX; int height = scrn->virtualY; - unsigned long pitch; + int pitch; uint32_t tiling; intel->front_buffer = intel_allocate_framebuffer(scrn, width, height, intel->cpp, - &pitch, - &tiling); + &pitch, &tiling); if (!intel->front_buffer) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, diff --git a/src/uxa/intel_memory.c b/src/uxa/intel_memory.c index 7db1a04..809b636 100644 --- a/src/uxa/intel_memory.c +++ b/src/uxa/intel_memory.c @@ -137,11 +137,10 @@ intel_get_fence_pitch(intel_screen_private *intel, unsigned long pitch, return i; } -static Bool -intel_check_display_stride(ScrnInfoPtr scrn, int stride, Bool tiling) +Bool intel_check_display_stride(ScrnInfoPtr scrn, int stride, Bool tiling) { intel_screen_private *intel = intel_get_screen_private(scrn); - int limit = KB(32); + int limit; /* 8xx spec has always 8K limit, but tests show larger limit in non-tiling mode, which makes large monitor work. */ @@ -154,30 +153,19 @@ intel_check_display_stride(ScrnInfoPtr scrn, int stride, Bool tiling) limit = KB(16); else limit = KB(32); - } + } else + limit = KB(32); - if (stride <= limit) - return TRUE; - else - return FALSE; + return stride <= limit; } -/* - * Pad to accelerator requirement - */ -static inline int intel_pad_drawable_width(int width) -{ - return ALIGN(width, 64); -} - - static size_t agp_aperture_size(struct pci_device *dev, int gen) { return dev->regions[gen < 030 ? 0 : 2].size; } -static void intel_set_gem_max_sizes(ScrnInfoPtr scrn) +void intel_set_gem_max_sizes(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); size_t agp_size = agp_aperture_size(intel->PciInfo, @@ -202,86 +190,3 @@ static void intel_set_gem_max_sizes(ScrnInfoPtr scrn) */ intel->max_bo_size = intel->max_gtt_map_size; } - -/** - * Allocates a framebuffer for a screen. - * - * Used once for each X screen, so once with RandR 1.2 and twice with classic - * dualhead. - */ -drm_intel_bo *intel_allocate_framebuffer(ScrnInfoPtr scrn, - int width, int height, int cpp, - unsigned long *out_pitch, - uint32_t *out_tiling) -{ - intel_screen_private *intel = intel_get_screen_private(scrn); - drm_intel_bo *front_buffer; - uint32_t tiling_mode; - unsigned long pitch; - - if (intel->tiling & INTEL_TILING_FB) - tiling_mode = I915_TILING_X; - else - tiling_mode = I915_TILING_NONE; - - width = intel_pad_drawable_width(width); - if (!intel_check_display_stride(scrn, width * intel->cpp, - tiling_mode != I915_TILING_NONE)) - tiling_mode = I915_TILING_NONE; - if (!intel_check_display_stride(scrn, width * intel->cpp, - tiling_mode != I915_TILING_NONE)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Expected front buffer stride %d kB " - "will exceed display limit\n", - width * intel->cpp / 1024); - return NULL; - } - -retry: - front_buffer = drm_intel_bo_alloc_tiled(intel->bufmgr, "front buffer", - width, height, intel->cpp, - &tiling_mode, &pitch, 0); - if (front_buffer == NULL) { - if (tiling_mode != I915_TILING_NONE) { - tiling_mode = I915_TILING_NONE; - goto retry; - } - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Failed to allocate framebuffer.\n"); - return NULL; - } - - if (!intel_check_display_stride(scrn, pitch, - tiling_mode != I915_TILING_NONE)) { - drm_intel_bo_unreference(front_buffer); - if (tiling_mode != I915_TILING_NONE) { - tiling_mode = I915_TILING_NONE; - goto retry; - } - - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Front buffer stride %ld kB " - "exceeds display limit\n", pitch / 1024); - return NULL; - } - - /* If we could have used tiling but failed, warn */ - if (intel->tiling & INTEL_TILING_FB && - tiling_mode != I915_TILING_X && - intel_check_display_stride(scrn, pitch, I915_TILING_X)) - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "Failed to set tiling on frontbuffer.\n"); - - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "Allocated new frame buffer %dx%d stride %ld, %s\n", - width, height, pitch, - tiling_mode == I915_TILING_NONE ? "untiled" : "tiled"); - - drm_intel_bo_disable_reuse(front_buffer); - - intel_set_gem_max_sizes(scrn); - *out_pitch = pitch; - *out_tiling = tiling_mode; - - return front_buffer; -} diff --git a/src/uxa/intel_uxa.c b/src/uxa/intel_uxa.c index 81c59d2..5b037f1 100644 --- a/src/uxa/intel_uxa.c +++ b/src/uxa/intel_uxa.c @@ -156,19 +156,15 @@ intel_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, } static unsigned int -intel_uxa_pixmap_compute_size(PixmapPtr pixmap, - int w, int h, - uint32_t *tiling, - int *stride, - unsigned usage) +intel_uxa_compute_size(struct intel_screen_private *intel, + int w, int h, int bpp, unsigned usage, + uint32_t *tiling, int *stride) { - ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); - intel_screen_private *intel = intel_get_screen_private(scrn); int pitch, size; if (*tiling != I915_TILING_NONE) { /* First check whether tiling is necessary. */ - pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; + pitch = (w * bpp + 7) / 8; pitch = ALIGN(pitch, 64); size = pitch * ALIGN (h, 2); if (INTEL_INFO(intel)->gen < 040) { @@ -197,7 +193,7 @@ intel_uxa_pixmap_compute_size(PixmapPtr pixmap, } } - pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; + pitch = (w * bpp + 7) / 8; if (!(usage & INTEL_CREATE_PIXMAP_DRI2) && pitch <= 256) *tiling = I915_TILING_NONE; @@ -243,6 +239,58 @@ intel_uxa_pixmap_compute_size(PixmapPtr pixmap, return size; } +drm_intel_bo *intel_allocate_framebuffer(ScrnInfoPtr scrn, + int width, int height, int cpp, + int *out_stride, + uint32_t *out_tiling) +{ + intel_screen_private *intel = intel_get_screen_private(scrn); + uint32_t tiling; + int stride, size; + drm_intel_bo *bo; + + if (intel->tiling & INTEL_TILING_FB) + tiling = I915_TILING_X; + else + tiling = I915_TILING_NONE; + +retry: + size = intel_uxa_compute_size(intel, + width, height, + intel->cpp*8, 0, + &tiling, &stride); + if (!intel_check_display_stride(scrn, stride, tiling)) { + if (tiling != I915_TILING_NONE) { + tiling = I915_TILING_NONE; + goto retry; + } + + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Front buffer stride %d kB " + "exceeds display limit\n", stride / 1024); + return NULL; + } + + bo = drm_intel_bo_alloc(intel->bufmgr, "front buffer", size, 0); + if (bo == NULL) + return FALSE; + + if (tiling != I915_TILING_NONE) + drm_intel_bo_set_tiling(bo, &tiling, stride); + + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "Allocated new frame buffer %dx%d stride %d, %s\n", + width, height, stride, + tiling == I915_TILING_NONE ? "untiled" : "tiled"); + + drm_intel_bo_disable_reuse(bo); + + intel_set_gem_max_sizes(scrn); + *out_stride = stride; + *out_tiling = tiling; + return bo; +} + static Bool intel_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask) { @@ -856,8 +904,10 @@ static Bool intel_uxa_put_image(PixmapPtr pixmap, dri_bo *bo; /* Replace busy bo. */ - size = intel_uxa_pixmap_compute_size (pixmap, w, h, - &tiling, &stride, 0); + size = intel_uxa_compute_size(intel, + w, h, + pixmap->drawable.bitsPerPixel, pixmap->usage_hint, + &tiling, &stride); if (size > intel->max_gtt_map_size) return FALSE; @@ -1117,7 +1167,9 @@ intel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (h <= 16 && tiling == I915_TILING_Y) tiling = I915_TILING_X; } - size = intel_uxa_pixmap_compute_size(pixmap, w, h, &tiling, &stride, usage); + size = intel_uxa_compute_size(intel, + w, h, pixmap->drawable.bitsPerPixel, usage, + &tiling, &stride); /* Fail very large allocations. Large BOs will tend to hit SW fallbacks * frequently, and also will tend to fail to successfully map when doing @@ -1258,7 +1310,10 @@ intel_uxa_share_pixmap_backing(PixmapPtr ppix, ScreenPtr slave, void **fd_handle tiling = I915_TILING_NONE; - size = intel_uxa_pixmap_compute_size(ppix, ppix->drawable.width, ppix->drawable.height, &tiling, &stride, INTEL_CREATE_PIXMAP_DRI2); + size = intel_uxa_compute_size(intel, + ppix->drawable.width, ppix->drawable.height, + ppix->drawable.bitsPerPixel, INTEL_CREATE_PIXMAP_DRI2, + &tiling, &stride); newbo = drm_intel_bo_alloc_for_render(intel->bufmgr, "pixmap", -- 2.0.0