diff options
author | Eric Anholt <eric@anholt.net> | 2009-05-18 18:01:05 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-05-19 10:09:41 -0700 |
commit | 09beee378cecd1079e7a9fa6eee8f084d680d37e (patch) | |
tree | 079c53d1e96e60e89f496bd98871145dbfb84e8f /src | |
parent | 34660fd2df5d61b77ed7041d32ac29053fc94f5a (diff) |
Don't do GTT maps on objects bigger than half the available aperture size.
The basic problem is that software fallbacks will do single instructions that
copy from one GTT-mapped BO into another GTT-mapped BO. If we can't get both
of them bound simultanously, we fault one in, retry the instruction, fault the
other in (kicking out #1), retry the instruction, fault #1 back in
(kicking out #2), etc.
Note that we'll still get into a nasty spot if you do a composite operation
with a mask where all 3 are big-but-less-than-half-available-aperture, where
you'll thrash. It at least means you'll make progress, though, since each
instruction will only be operating on two BOs at at time, and the situation
seems unlikely.
Bug #20152 (3/3)
Diffstat (limited to 'src')
-rw-r--r-- | src/drmmode_display.c | 2 | ||||
-rw-r--r-- | src/i830.h | 2 | ||||
-rw-r--r-- | src/i830_exa.c | 20 | ||||
-rw-r--r-- | src/i830_memory.c | 26 |
4 files changed, 46 insertions, 4 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 7df7b6fb..24e0e269 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -232,6 +232,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, drmmode_output_dpms(output, DPMSModeOn); } + i830_set_max_gtt_map_size(pScrn); + done: if (!ret) { crtc->x = saved_x; @@ -437,6 +437,7 @@ typedef struct _I830Rec { int accel_pixmap_offset_alignment; int accel_max_x; int accel_max_y; + int max_gtt_map_size; I830WriteIndexedByteFunc writeControl; I830ReadIndexedByteFunc readControl; @@ -748,6 +749,7 @@ 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); +void i830_set_max_gtt_map_size(ScrnInfoPtr pScrn); Bool I830BindAGPMemory(ScrnInfoPtr pScrn); Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn); diff --git a/src/i830_exa.c b/src/i830_exa.c index 824f032b..3ca79334 100644 --- a/src/i830_exa.c +++ b/src/i830_exa.c @@ -506,9 +506,18 @@ i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access) /* Kernel manages fences at GTT map/fault time */ if (i830->kernel_exec_fencing) { - if (drm_intel_gem_bo_map_gtt(bo)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: bo map failed\n", - __FUNCTION__); + if (bo->size < i830->max_gtt_map_size) { + if (drm_intel_gem_bo_map_gtt(bo)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "%s: bo map failed\n", + __FUNCTION__); + return FALSE; + } + } else { + if (dri_bo_map(bo, access == UXA_ACCESS_RW) != 0) + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "%s: bo map failed\n", + __FUNCTION__); return FALSE; } pixmap->devPrivate.ptr = bo->virtual; @@ -542,7 +551,10 @@ i830_uxa_finish_access (PixmapPtr pixmap) } if (i830->kernel_exec_fencing) - drm_intel_gem_bo_unmap_gtt(bo); + if (bo->size < i830->max_gtt_map_size) + drm_intel_gem_bo_unmap_gtt(bo); + else + dri_bo_unmap(bo); else drm_intel_bo_unpin(bo); pixmap->devPrivate.ptr = NULL; diff --git a/src/i830_memory.c b/src/i830_memory.c index 2a697a7d..99b9fc85 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -1128,6 +1128,8 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn) if (!pI830->use_drm_mode && pI830->FbBase && front_buffer->bound) memset (pI830->FbBase + front_buffer->offset, 0, size); + i830_set_max_gtt_map_size(pScrn); + return front_buffer; } @@ -1588,6 +1590,7 @@ i830_bind_all_memory(ScrnInfoPtr pScrn) } if (!pI830->use_drm_mode) i830_update_cursor_offsets(pScrn); + i830_set_max_gtt_map_size(pScrn); return TRUE; } @@ -1672,3 +1675,26 @@ Bool i830_allocate_xvmc_buffer(ScrnInfoPtr pScrn, const char *name, return TRUE; } #endif + +void +i830_set_max_gtt_map_size(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + struct drm_i915_gem_get_aperture aperture; + int ret; + + /* Default low value in case it gets used during server init. */ + pI830->max_gtt_map_size = 16 * 1024 * 1024; + + if (!pI830->have_gem) + return; + + ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture); + if (ret == 0) { + /* Let objects up get bound up to the size where only 2 would fit in + * the aperture, but then leave slop to account for alignment like + * libdrm does. + */ + pI830->max_gtt_map_size = aperture.aper_available_size * 3 / 4 / 2; + } +} |