diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2010-04-11 23:37:10 +0200 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2010-04-11 23:37:10 +0200 |
commit | 59df68861382a3c31c35f440cbce0b0884cb8865 (patch) | |
tree | 70136a99bb6b600fbe466cbdc98e38fda411cb50 | |
parent | 6005cd921a923dd10f3fd2c04f598e23d1457e44 (diff) |
i830 uxa: track fence reg usage exactlyno_fence_accounting
This tells libdrm to not take fence registers into account. Instead
it checks for fence register availability for the current batchbuffer
in the various uxa_prepare_* hooks where it's know how many fences
are needed _exactly_.
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | src/i830.h | 6 | ||||
-rw-r--r-- | src/i830_batchbuffer.c | 2 | ||||
-rw-r--r-- | src/i830_driver.c | 31 | ||||
-rw-r--r-- | src/i830_uxa.c | 59 |
4 files changed, 98 insertions, 0 deletions
@@ -144,6 +144,7 @@ struct intel_pixmap { uint32_t batch_write_domain; uint32_t batch_read_domains; struct list flush, batch; + unsigned int fence_allocated : 1; }; struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap); @@ -253,6 +254,11 @@ typedef struct intel_screen_private { struct list batch_pixmaps; struct list flush_pixmaps; + /** Available fence registers */ + int available_fences; + /** Fence registers used in current batchbuffer */ + int used_fences; + /* For Xvideo */ Bool use_drmmode_overlay; #ifdef INTEL_XVMC diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c index a02e9808..7537eb58 100644 --- a/src/i830_batchbuffer.c +++ b/src/i830_batchbuffer.c @@ -176,8 +176,10 @@ void intel_batch_submit(ScrnInfoPtr scrn) batch); entry->batch_read_domains = entry->batch_write_domain = 0; + entry->fence_allocated = 0; list_del(&entry->batch); } + intel->used_fences = 0; /* Mark that we need to flush whatever potential rendering we've done in the * blockhandler. We could set this less often, but it's probably not worth diff --git a/src/i830_driver.c b/src/i830_driver.c index 0c36b25e..0fc2afff 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1057,6 +1057,37 @@ void i830_init_bufmgr(ScrnInfoPtr scrn) intel->bufmgr = drm_intel_bufmgr_gem_init(intel->drmSubFD, batch_size); drm_intel_bufmgr_gem_enable_reuse(intel->bufmgr); drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr); + drm_intel_bufmgr_gem_disable_fence_accounting(intel->bufmgr); + + if (!IS_I965G(intel)) { + drm_i915_getparam_t gp; + int ret; + + gp.param = I915_PARAM_NUM_FENCES_AVAIL; + gp.value = &intel->available_fences; + ret = ioctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp); + if (ret) { + fprintf(stderr, "get fences failed: %d [%d]\n", ret, + errno); + fprintf(stderr, "param: %d, val: %d\n", gp.param, + *gp.value); + intel->available_fences = 0; + } else { + /* XXX The kernel reports the total number of fences, + * including any that may be pinned. + * + * libdrm subtracts to fences for maximal two scanout + * buffers. But we know that there's (currently) only + * at most one tiled scanout buffer, so subtract just + * one. */ + intel->available_fences -= 1; + if (intel->available_fences < 0) + intel->available_fences = 0; + } + } else + intel->available_fences = 0; + + intel->used_fences = 0; list_init(&intel->batch_pixmaps); list_init(&intel->flush_pixmaps); diff --git a/src/i830_uxa.c b/src/i830_uxa.c index 09c2ef31..7f02d9f3 100644 --- a/src/i830_uxa.c +++ b/src/i830_uxa.c @@ -105,6 +105,51 @@ i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, return TRUE; } +static Bool +i830_get_fence_registers(ScrnInfoPtr scrn, + struct intel_pixmap ** pixmap_table, + int num_pixmaps) +{ + intel_screen_private *intel = intel_get_screen_private(scrn); + int i, retried = 0; + int reserved_fences; + + if (IS_I965G(intel)) + return TRUE; + +retry: + reserved_fences = 0; + for (i = 0; i < num_pixmaps; i++) { + if (pixmap_table[i]->tiling == I915_TILING_NONE) + continue; + + if (pixmap_table[i]->fence_allocated) + continue; + + pixmap_table[i]->fence_allocated = 1; + reserved_fences++; + } + + if (reserved_fences + intel->used_fences + <= intel->available_fences) { + intel->used_fences += reserved_fences; + return TRUE; + } + + if (retried) { + intel_debug_fallback(scrn, "Couldn't get fence " + "registers for BOs\n"); + return FALSE; + } + + intel_batch_submit(scrn); + for (i = 0; i < num_pixmaps; i++) + pixmap_table[i]->fence_allocated = 0; + retried = 0; + goto retry; +} + + static unsigned long i830_pixmap_pitch(PixmapPtr pixmap) { return pixmap->devKind; @@ -205,6 +250,9 @@ i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) NULL, /* batch_bo */ i830_get_pixmap_bo(pixmap), }; + struct intel_pixmap *pixmap_table[] = { + i830_get_pixmap_intel(pixmap), + }; if (IS_GEN6(intel)) { intel_debug_fallback(scrn, @@ -238,6 +286,10 @@ i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) return FALSE; + if (!i830_get_fence_registers(scrn, pixmap_table, + ARRAY_SIZE(pixmap_table))) + return FALSE; + intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16; switch (pixmap->drawable.bitsPerPixel) { case 8: @@ -324,6 +376,10 @@ i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, i830_get_pixmap_bo(source), i830_get_pixmap_bo(dest), }; + struct intel_pixmap *pixmap_table[] = { + i830_get_pixmap_intel(source), + i830_get_pixmap_intel(dest), + }; if (IS_GEN6(intel)) { intel_debug_fallback(scrn, @@ -344,6 +400,9 @@ i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) return FALSE; + if (!i830_get_fence_registers(scrn, pixmap_table, + ARRAY_SIZE(pixmap_table))) + return FALSE; if (!intel_check_pitch_2d(source)) return FALSE; if (!intel_check_pitch_2d(dest)) |