summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2010-04-11 23:37:10 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2010-04-11 23:37:10 +0200
commit59df68861382a3c31c35f440cbce0b0884cb8865 (patch)
tree70136a99bb6b600fbe466cbdc98e38fda411cb50
parent6005cd921a923dd10f3fd2c04f598e23d1457e44 (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.h6
-rw-r--r--src/i830_batchbuffer.c2
-rw-r--r--src/i830_driver.c31
-rw-r--r--src/i830_uxa.c59
4 files changed, 98 insertions, 0 deletions
diff --git a/src/i830.h b/src/i830.h
index 7593cdea..ee829a97 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -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))