diff mbox

i830 uxa: track fence reg usage exactly

Message ID 1271969327-16945-3-git-send-email-daniel.vetter@ffwll.ch (mailing list archive)
State Deferred, archived
Headers show

Commit Message

Daniel Vetter April 22, 2010, 8:48 p.m. UTC
None
diff mbox

Patch

diff --git a/src/i830.h b/src/i830.h
index 88949f6..fd9a798 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -71,11 +71,13 @@  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "i915_drm.h"
 
 #include "uxa.h"
+struct intel_pixmap;
 Bool i830_uxa_init(ScreenPtr pScreen);
 void i830_uxa_create_screen_resources(ScreenPtr pScreen);
 void i830_uxa_block_handler(ScreenPtr pScreen);
-Bool i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
-			     int num_bos);
+Bool i830_get_aperture_space(ScrnInfoPtr scrn,
+			     struct intel_pixmap ** pixmap_table,
+			     int num_pixmaps);
 
 /* classic doubly-link circular list */
 struct list {
@@ -152,6 +154,7 @@  struct intel_pixmap {
 	uint32_t batch_write_domain;
 	uint32_t batch_read_domains;
 	struct list flush, batch, in_flight;
+	unsigned int fence_allocated : 1;
 };
 
 struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap);
@@ -262,6 +265,12 @@  typedef struct intel_screen_private {
 	struct list flush_pixmaps;
 	struct list in_flight;
 
+	/** Available fence registers */
+	int available_fences;
+	int unfenced_relocs;
+	/** 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 492472e..b41e567 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 db8af06..b84c3a0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1051,6 +1051,38 @@  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);
+	intel->unfenced_relocs = 
+		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_render.c b/src/i830_render.c
index 8e559c9..b415fe9 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -438,11 +438,10 @@  i830_prepare_composite(int op, PicturePtr source_picture,
 {
 	ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum];
 	intel_screen_private *intel = intel_get_screen_private(scrn);
-	drm_intel_bo *bo_table[] = {
-		NULL,		/* batch_bo */
-		i830_get_pixmap_bo(source),
-		mask ? i830_get_pixmap_bo(mask) : NULL,
-		i830_get_pixmap_bo(dest),
+	struct intel_pixmap *pixmap_table[] = {
+		i830_get_pixmap_intel(source),
+		mask ? i830_get_pixmap_intel(mask) : NULL,
+		i830_get_pixmap_intel(dest),
 	};
 
 	intel->render_source_picture = source_picture;
@@ -464,7 +463,8 @@  i830_prepare_composite(int op, PicturePtr source_picture,
 	if (!i830_get_dest_format(dest_picture, &intel->render_dest_format))
 		return FALSE;
 
-	if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
+	if (!i830_get_aperture_space(scrn, pixmap_table,
+				     ARRAY_SIZE(pixmap_table)))
 		return FALSE;
 
 	if (mask) {
diff --git a/src/i830_uxa.c b/src/i830_uxa.c
index 984069e..8ed1198 100644
--- a/src/i830_uxa.c
+++ b/src/i830_uxa.c
@@ -80,11 +80,67 @@  const int I830PatternROP[16] = {
 
 static int uxa_pixmap_index;
 
+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 = 1;
+	goto retry;
+}
+
 Bool
-i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
-			int num_bos)
+i830_get_aperture_space(ScrnInfoPtr scrn,
+			struct intel_pixmap ** pixmap_table,
+			int num_pixmaps)
 {
 	intel_screen_private *intel = intel_get_screen_private(scrn);
+	drm_intel_bo *bo_table[num_pixmaps + 1];
+	int i;
+
+	bo_table[0] = NULL; /* for the batch bo */
+
+	for (i = 0; i < num_pixmaps; i++) {
+		if (pixmap_table[i])
+			bo_table[i + 1] = pixmap_table[i]->bo;
+		else
+			bo_table[i + 1] = NULL;
+	}
 
 	if (intel->batch_bo == NULL) {
 		intel_debug_fallback(scrn, "VT inactive\n");
@@ -92,16 +148,21 @@  i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
 	}
 
 	bo_table[0] = intel->batch_bo;
-	if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) {
+	if (drm_intel_bufmgr_check_aperture_space(bo_table, num_pixmaps) != 0) {
 		intel_batch_submit(scrn);
 		bo_table[0] = intel->batch_bo;
-		if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) !=
-		    0) {
+		if (drm_intel_bufmgr_check_aperture_space(bo_table,
+							  num_pixmaps) != 0) {
 			intel_debug_fallback(scrn, "Couldn't get aperture "
 					    "space for BOs\n");
 			return FALSE;
 		}
 	}
+
+	if (!intel->unfenced_relocs)
+		return i830_get_fence_registers(scrn, pixmap_table,
+						num_pixmaps);
+
 	return TRUE;
 }
 
@@ -203,9 +264,8 @@  i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
 {
 	ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum];
 	intel_screen_private *intel = intel_get_screen_private(scrn);
-	drm_intel_bo *bo_table[] = {
-		NULL,		/* batch_bo */
-		i830_get_pixmap_bo(pixmap),
+	struct intel_pixmap *pixmap_table[] = {
+		i830_get_pixmap_intel(pixmap),
 	};
 
 	if (IS_GEN6(intel)) {
@@ -237,7 +297,12 @@  i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
 		return FALSE;
 	}
 
-	if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
+	if (!i830_get_aperture_space(scrn, pixmap_table,
+				     ARRAY_SIZE(pixmap_table)))
+		return FALSE;
+
+	if (!i830_get_fence_registers(scrn, pixmap_table,
+				      ARRAY_SIZE(pixmap_table)))
 		return FALSE;
 
 	intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16;
@@ -321,10 +386,9 @@  i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
 {
 	ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
 	intel_screen_private *intel = intel_get_screen_private(scrn);
-	drm_intel_bo *bo_table[] = {
-		NULL,		/* batch_bo */
-		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)) {
@@ -343,9 +407,12 @@  i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
 		return FALSE;
 	}
 
-	if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
+	if (!i830_get_aperture_space(scrn, pixmap_table, ARRAY_SIZE(pixmap_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))
diff --git a/src/i915_render.c b/src/i915_render.c
index 98b5b88..cbc82f7 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -367,11 +367,10 @@  i915_prepare_composite(int op, PicturePtr source_picture,
 {
 	ScrnInfoPtr scrn = xf86Screens[source_picture->pDrawable->pScreen->myNum];
 	intel_screen_private *intel = intel_get_screen_private(scrn);
-	drm_intel_bo *bo_table[] = {
-		NULL,		/* batch_bo */
-		i830_get_pixmap_bo(source),
-		mask ? i830_get_pixmap_bo(mask) : NULL,
-		i830_get_pixmap_bo(dest),
+	struct intel_pixmap *pixmap_table[] = {
+		i830_get_pixmap_intel(source),
+		mask ? i830_get_pixmap_intel(mask) : NULL,
+		i830_get_pixmap_intel(dest),
 	};
 	int tex_unit = 0;
 
@@ -424,8 +423,10 @@  i915_prepare_composite(int op, PicturePtr source_picture,
 				  &intel->i915_render_state.dst_format))
 		return FALSE;
 
-	if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
+	if (!i830_get_aperture_space(scrn, pixmap_table,
+				     ARRAY_SIZE(pixmap_table)))
 		return FALSE;
+
 	intel->dst_coord_adjust = 0;
 	intel->src_coord_adjust = 0;
 	intel->mask_coord_adjust = 0;