summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-01-05 10:25:12 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-01-05 11:50:26 +0000
commit6ffd3605640bacaf0d744075622463aacf78d797 (patch)
treec067e1da323593307fe0428653998640fba9ee8c
parenta09ebe0b6cc66d08e52b57851d9b8a6a1f71df2b (diff)
sna: Deferred attachment to a pixmap needs to mark the pixmap as entirely dirty
As demonstrated with oversized glyphs and a chain of catastrophy, when attaching our private to a pixmap after creation we need to mark the entire CPU pixmap as dirty as we never tracked exactly which bits were dirtied. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/kgem.c2
-rw-r--r--src/sna/sna.h12
-rw-r--r--src/sna/sna_accel.c79
-rw-r--r--src/sna/sna_render.c1
4 files changed, 63 insertions, 31 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index d08faa47..24a47aaf 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2158,7 +2158,7 @@ static void _kgem_bo_delete_partial(struct kgem *kgem, struct kgem_bo *bo)
struct kgem_partial_bo *io = (struct kgem_partial_bo *)bo->proxy;
if (list_is_empty(&io->base.list))
- return;
+ return;
if (bo->size == io->used) {
assert(io->base.exec == NULL);
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 1e6a803a..a1737c11 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -422,7 +422,17 @@ static inline Bool pixmap_is_scanout(PixmapPtr pixmap)
return pixmap == screen->GetScreenPixmap(screen);
}
-struct sna_pixmap *sna_pixmap_attach(PixmapPtr pixmap);
+struct sna_pixmap *_sna_pixmap_attach(PixmapPtr pixmap);
+inline static struct sna_pixmap *sna_pixmap_attach(PixmapPtr pixmap)
+{
+ struct sna_pixmap *priv;
+
+ priv = sna_pixmap(pixmap);
+ if (priv)
+ return priv;
+
+ return _sna_pixmap_attach(pixmap);
+}
PixmapPtr sna_pixmap_create_upload(ScreenPtr screen,
int width, int height, int depth);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 8b450b65..e34ecf07 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -410,8 +410,8 @@ _sna_pixmap_reset(PixmapPtr pixmap)
return _sna_pixmap_init(priv, pixmap);
}
-static struct sna_pixmap *_sna_pixmap_attach(struct sna *sna,
- PixmapPtr pixmap)
+static struct sna_pixmap *__sna_pixmap_attach(struct sna *sna,
+ PixmapPtr pixmap)
{
struct sna_pixmap *priv;
@@ -423,16 +423,18 @@ static struct sna_pixmap *_sna_pixmap_attach(struct sna *sna,
return _sna_pixmap_init(priv, pixmap);
}
-struct sna_pixmap *sna_pixmap_attach(PixmapPtr pixmap)
+struct sna_pixmap *_sna_pixmap_attach(PixmapPtr pixmap)
{
- struct sna *sna;
+ struct sna *sna = to_sna_from_pixmap(pixmap);
struct sna_pixmap *priv;
- priv = sna_pixmap(pixmap);
- if (priv)
- return priv;
+ DBG(("%s: serial=%ld, %dx%d, usage=%d\n",
+ __FUNCTION__,
+ pixmap->drawable.serialNumber,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ pixmap->usage_hint));
- sna = to_sna_from_pixmap(pixmap);
switch (pixmap->usage_hint) {
case CREATE_PIXMAP_USAGE_GLYPH_PICTURE:
#if FAKE_CREATE_PIXMAP_USAGE_SCRATCH_HEADER
@@ -454,7 +456,17 @@ struct sna_pixmap *sna_pixmap_attach(PixmapPtr pixmap)
break;
}
- return _sna_pixmap_attach(sna, pixmap);
+ priv = __sna_pixmap_attach(sna, pixmap);
+ if (priv == NULL)
+ return NULL;
+
+ DBG(("%s: created priv and marking all cpu damaged\n", __FUNCTION__));
+
+ sna_damage_all(&priv->cpu_damage,
+ pixmap->drawable.width,
+ pixmap->drawable.height);
+
+ return priv;
}
static inline PixmapPtr
@@ -468,6 +480,13 @@ create_pixmap(struct sna *sna, ScreenPtr screen,
if (pixmap == NullPixmap)
return NullPixmap;
+ DBG(("%s: serial=%ld, usage=%d, %dx%d\n",
+ __FUNCTION__,
+ pixmap->drawable.serialNumber,
+ pixmap->usage_hint,
+ pixmap->drawable.width,
+ pixmap->drawable.height));
+
assert(sna_private_index.offset == 0);
dixSetPrivate(&pixmap->devPrivates, &sna_private_index, sna);
return pixmap;
@@ -518,6 +537,13 @@ sna_pixmap_create_scratch(ScreenPtr screen,
pixmap->drawable.bitsPerPixel = bpp;
pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ DBG(("%s: serial=%ld, usage=%d, %dx%d\n",
+ __FUNCTION__,
+ pixmap->drawable.serialNumber,
+ pixmap->usage_hint,
+ pixmap->drawable.width,
+ pixmap->drawable.height));
+
priv = _sna_pixmap_reset(pixmap);
} else {
pixmap = create_pixmap(sna, screen, 0, 0, depth,
@@ -530,7 +556,7 @@ sna_pixmap_create_scratch(ScreenPtr screen,
pixmap->drawable.depth = depth;
pixmap->drawable.bitsPerPixel = bpp;
- priv = _sna_pixmap_attach(sna, pixmap);
+ priv = __sna_pixmap_attach(sna, pixmap);
if (!priv) {
fbDestroyPixmap(pixmap);
return NullPixmap;
@@ -610,7 +636,7 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
if (pixmap == NullPixmap)
return NullPixmap;
- sna_pixmap_attach(pixmap);
+ __sna_pixmap_attach(sna, pixmap);
} else {
struct sna_pixmap *priv;
@@ -623,7 +649,7 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
pixmap->devKind = pad;
pixmap->devPrivate.ptr = NULL;
- priv = _sna_pixmap_attach(sna, pixmap);
+ priv = __sna_pixmap_attach(sna, pixmap);
if (priv == NULL) {
free(pixmap);
return create_pixmap(sna, screen,
@@ -1363,6 +1389,11 @@ sna_pixmap_create_upload(ScreenPtr screen,
pixmap->usage_hint = CREATE_PIXMAP_USAGE_SCRATCH;
pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
pixmap->refcnt = 1;
+
+ DBG(("%s: serial=%ld, usage=%d\n",
+ __FUNCTION__,
+ pixmap->drawable.serialNumber,
+ pixmap->usage_hint));
} else {
pixmap = create_pixmap(sna, screen, 0, 0, depth,
CREATE_PIXMAP_USAGE_SCRATCH);
@@ -1410,19 +1441,11 @@ sna_pixmap_force_to_gpu(PixmapPtr pixmap, unsigned flags)
DBG(("%s(pixmap=%p)\n", __FUNCTION__, pixmap));
- priv = sna_pixmap(pixmap);
- if (priv == NULL) {
- priv = sna_pixmap_attach(pixmap);
- if (priv == NULL)
- return NULL;
-
- DBG(("%s: created priv and marking all cpu damaged\n",
- __FUNCTION__));
- sna_damage_all(&priv->cpu_damage,
- pixmap->drawable.width,
- pixmap->drawable.height);
- }
+ priv = sna_pixmap_attach(pixmap);
+ if (priv == NULL)
+ return NULL;
+ /* Unlike move-to-gpu, we ignore wedged and always create the GPU bo */
if (priv->gpu_bo == NULL) {
struct sna *sna = to_sna_from_pixmap(pixmap);
unsigned flags;
@@ -1459,7 +1482,8 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
BoxPtr box;
int n;
- DBG(("%s()\n", __FUNCTION__));
+ DBG(("%s(pixmap=%ld, usage=%d)\n",
+ __FUNCTION__, pixmap->drawable.serialNumber, pixmap->usage_hint));
priv = sna_pixmap(pixmap);
if (priv == NULL)
@@ -1516,9 +1540,8 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
box, n);
if (!ok) {
if (n == 1 && !priv->pinned &&
- box->x1 <= 0 && box->y1 <= 0 &&
- box->x2 >= pixmap->drawable.width &&
- box->y2 >= pixmap->drawable.height) {
+ (box->x2 - box->x1) >= pixmap->drawable.width &&
+ (box->y2 - box->y1) >= pixmap->drawable.height) {
priv->gpu_bo =
sna_replace(sna,
pixmap,
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index aa9c160d..faa2730b 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -505,7 +505,6 @@ sna_render_pixmap_bo(struct sna *sna,
*/
if (pixmap->usage_hint != CREATE_PIXMAP_USAGE_SCRATCH_HEADER &&
w * pixmap->drawable.bitsPerPixel * h > 8*4096) {
- priv = sna_pixmap_attach(pixmap);
bo = pixmap_vmap(&sna->kgem, pixmap);
if (bo)
bo = kgem_bo_reference(bo);