summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/i830.h13
-rw-r--r--src/i830_batchbuffer.c12
-rw-r--r--src/i830_driver.c1
-rw-r--r--src/i830_uxa.c88
4 files changed, 82 insertions, 32 deletions
diff --git a/src/i830.h b/src/i830.h
index 43c58875..88949f6f 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -136,14 +136,22 @@ list_is_empty(struct list *head)
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
+#define list_foreach(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define list_foreach_entry(pos, type, head, member) \
+ for (pos = list_entry((head)->next, type, member);\
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, type, member))
+
struct intel_pixmap {
dri_bo *bo;
- uint32_t tiling;
+ uint32_t tiling, stride;
uint32_t flush_write_domain;
uint32_t flush_read_domains;
uint32_t batch_write_domain;
uint32_t batch_read_domains;
- struct list flush, batch;
+ struct list flush, batch, in_flight;
};
struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap);
@@ -252,6 +260,7 @@ typedef struct intel_screen_private {
int batch_atomic_limit;
struct list batch_pixmaps;
struct list flush_pixmaps;
+ struct list in_flight;
/* For Xvideo */
Bool use_drmmode_overlay;
diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index a02e9808..492472e7 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -195,6 +195,18 @@ void intel_batch_submit(ScrnInfoPtr scrn)
list_del(&entry->flush);
}
+ while (!list_is_empty(&intel->in_flight)) {
+ struct intel_pixmap *entry;
+
+ entry = list_first_entry(&intel->in_flight,
+ struct intel_pixmap,
+ in_flight);
+
+ dri_bo_unreference(entry->bo);
+ list_del(&entry->in_flight);
+ xfree(entry);
+ }
+
/* Save a ref to the last batch emitted, which we use for syncing
* in debug code.
*/
diff --git a/src/i830_driver.c b/src/i830_driver.c
index d0ce552d..db8af063 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1054,6 +1054,7 @@ void i830_init_bufmgr(ScrnInfoPtr scrn)
list_init(&intel->batch_pixmaps);
list_init(&intel->flush_pixmaps);
+ list_init(&intel->in_flight);
}
Bool i830_crtc_on(xf86CrtcPtr crtc)
diff --git a/src/i830_uxa.c b/src/i830_uxa.c
index f3f0f651..984069e7 100644
--- a/src/i830_uxa.c
+++ b/src/i830_uxa.c
@@ -127,7 +127,7 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap,
{
ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
- int pitch_align;
+ int pitch, pitch_align;
int size;
if (*tiling != I915_TILING_NONE) {
@@ -151,6 +151,9 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap,
}
}
+ pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8;
+ if (pitch <= 256)
+ *tiling = I915_TILING_NONE;
repeat:
if (*tiling == I915_TILING_NONE) {
pitch_align = intel->accel_pixmap_pitch_alignment;
@@ -158,8 +161,7 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap,
pitch_align = 512;
}
- *stride = ROUND_TO((w * pixmap->drawable.bitsPerPixel + 7) / 8,
- pitch_align);
+ *stride = ROUND_TO(pitch, pitch_align);
if (*tiling == I915_TILING_NONE) {
/* Round the height up so that the GPU's access to a 2x2 aligned
@@ -548,17 +550,19 @@ dri_bo *i830_get_pixmap_bo(PixmapPtr pixmap)
void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo)
{
+ ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
struct intel_pixmap *priv;
priv = i830_get_pixmap_intel(pixmap);
if (priv != NULL) {
- dri_bo_unreference(priv->bo);
-
- priv->flush_read_domains = priv->flush_write_domain = 0;
- priv->batch_read_domains = priv->batch_write_domain = 0;
- list_del(&priv->batch);
- list_del(&priv->flush);
+ if (list_is_empty(&priv->batch)) {
+ dri_bo_unreference(priv->bo);
+ } else {
+ list_add(&priv->in_flight, &intel->in_flight);
+ priv = NULL;
+ }
}
if (bo != NULL) {
@@ -576,6 +580,7 @@ void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo)
dri_bo_reference(bo);
priv->bo = bo;
+ priv->stride = i830_pixmap_pitch(pixmap);
ret = drm_intel_bo_get_tiling(bo,
&priv->tiling,
@@ -883,35 +888,26 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
if (w && h) {
struct intel_pixmap *priv;
- unsigned int size;
+ unsigned int size, tiling;
int stride;
- priv = xcalloc(1, sizeof (struct intel_pixmap));
- if (priv == NULL) {
- fbDestroyPixmap(pixmap);
- return NullPixmap;
- }
-
/* Always attempt to tile, compute_size() will remove the
* tiling for pixmaps that are either too large or too small
* to be effectively tiled.
*/
- priv->tiling = I915_TILING_X;
+ tiling = I915_TILING_X;
if (usage == INTEL_CREATE_PIXMAP_TILING_Y)
- priv->tiling = I915_TILING_Y;
+ tiling = I915_TILING_Y;
if (usage == UXA_CREATE_PIXMAP_FOR_MAP)
- priv->tiling = I915_TILING_NONE;
-
- if (priv->tiling != I915_TILING_NONE) {
- if (w < 256)
- priv->tiling = I915_TILING_NONE;
- if (h < 8)
- priv->tiling = I915_TILING_NONE;
- if (h < 32 && priv->tiling == I915_TILING_Y)
- priv->tiling = I915_TILING_X;
+ tiling = I915_TILING_NONE;
+
+ if (tiling != I915_TILING_NONE) {
+ if (h <= 4)
+ tiling = I915_TILING_NONE;
+ if (h <= 16 && tiling == I915_TILING_Y)
+ tiling = I915_TILING_X;
}
- size = i830_uxa_pixmap_compute_size(pixmap, w, h,
- &priv->tiling, &stride);
+ size = i830_uxa_pixmap_compute_size(pixmap, w, h, &tiling, &stride);
/* Fail very large allocations on 32-bit systems. Large BOs will
* tend to hit SW fallbacks frequently, and also will tend to fail
@@ -923,7 +919,37 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
*/
if (sizeof(unsigned long) == 4 &&
size > (unsigned int)(1024 * 1024 * 1024)) {
- xfree(priv);
+ fbDestroyPixmap(pixmap);
+ return NullPixmap;
+ }
+
+ /* Perform a premilinary search for an in-flight bo */
+ if (usage != UXA_CREATE_PIXMAP_FOR_MAP) {
+ int aligned_h;
+
+ if (tiling == I915_TILING_X)
+ aligned_h = ALIGN(h, 8);
+ else if (tiling == I915_TILING_Y)
+ aligned_h = ALIGN(h, 32);
+ else
+ aligned_h = ALIGN(h, 2);
+
+ list_foreach_entry(priv, struct intel_pixmap,
+ &intel->in_flight,
+ in_flight) {
+ if (priv->tiling == tiling &&
+ priv->stride >= stride &&
+ priv->bo->size >= priv->stride * aligned_h) {
+ list_del(&priv->in_flight);
+ screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, priv->stride, NULL);
+ i830_uxa_set_pixmap_intel(pixmap, priv);
+ return pixmap;
+ }
+ }
+ }
+
+ priv = xcalloc(1, sizeof (struct intel_pixmap));
+ if (priv == NULL) {
fbDestroyPixmap(pixmap);
return NullPixmap;
}
@@ -941,6 +967,8 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
return NullPixmap;
}
+ priv->stride = stride;
+ priv->tiling = tiling;
if (priv->tiling != I915_TILING_NONE)
drm_intel_bo_set_tiling(priv->bo,
&priv->tiling,