sna: Make the failure to create render caches non-fatal

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-08-12 10:34:10 +01:00
parent b580abdfa6
commit dc18eaa585
6 changed files with 252 additions and 302 deletions

View File

@ -629,13 +629,13 @@ static inline uint32_t pixmap_size(PixmapPtr pixmap)
}
bool sna_accel_init(ScreenPtr sreen, struct sna *sna);
void sna_accel_create(struct sna *sna);
void sna_accel_block_handler(struct sna *sna, struct timeval **tv);
void sna_accel_wakeup_handler(struct sna *sna);
void sna_accel_watch_flush(struct sna *sna, int enable);
void sna_accel_close(struct sna *sna);
void sna_accel_free(struct sna *sna);
bool sna_accel_create(ScreenPtr screen, struct sna *sna);
void sna_copy_fbcon(struct sna *sna);
bool sna_composite_create(struct sna *sna);

View File

@ -13874,18 +13874,24 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna)
return true;
}
bool sna_accel_create(ScreenPtr screen, struct sna *sna)
void sna_accel_create(struct sna *sna)
{
if (!sna_glyphs_create(sna))
return false;
goto fail;
if (!sna_gradients_create(sna))
return false;
goto fail;
if (!sna_composite_create(sna))
return false;
goto fail;
return true;
return;
fail:
xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
"Failed to allocate caches, disabling RENDER acceleration\n");
sna->have_render = false;
no_render_init(sna);
}
void sna_accel_watch_flush(struct sna *sna, int enable)

View File

@ -46,6 +46,9 @@ bool sna_composite_create(struct sna *sna)
xRenderColor color ={ 0 };
int error;
if (!can_render(sna))
return true;
sna->clear = CreateSolidPicture(0, &color, &error);
return sna->clear != NULL;
}

View File

@ -168,11 +168,7 @@ static Bool sna_create_screen_resources(ScreenPtr screen)
free(screen->devPrivate);
screen->devPrivate = NULL;
if (!sna_accel_create(screen, sna)) {
xf86DrvMsg(screen->myNum, X_ERROR,
"[intel] Failed to initialise acceleration routines\n");
goto cleanup_front;
}
sna_accel_create(sna);
sna->front = screen->CreatePixmap(screen,
screen->width,

View File

@ -881,7 +881,7 @@ glyphs_via_mask(struct sna *sna,
memset(pixmap->devPrivate.ptr, 0, pixmap->devKind*height);
#if HAS_PIXMAN_GLYPHS
{
if (sna->render.glyph_cache) {
pixman_glyph_t stack_glyphs[N_STACK_GLYPHS];
pixman_glyph_t *pglyphs = stack_glyphs;
pixman_glyph_cache_t *cache;
@ -909,7 +909,7 @@ glyphs_via_mask(struct sna *sna,
const void *ptr;
if (g->info.width == 0 || g->info.height == 0)
goto next_image;
goto next_pglyph;
ptr = pixman_glyph_cache_lookup(cache, g, NULL);
if (ptr == NULL) {
@ -917,14 +917,14 @@ glyphs_via_mask(struct sna *sna,
glyph_image = sna_glyph_get_image(g, screen);
if (glyph_image == NULL)
goto next_image;
goto next_pglyph;
ptr = pixman_glyph_cache_insert(cache, g, NULL,
g->info.x,
g->info.y,
glyph_image);
if (ptr == NULL)
goto next_image;
goto next_pglyph;
}
pglyphs[count].x = x;
@ -932,7 +932,7 @@ glyphs_via_mask(struct sna *sna,
pglyphs[count].glyph = ptr;
count++;
next_image:
next_pglyph:
x += g->info.xOff;
y += g->info.yOff;
}
@ -948,8 +948,8 @@ next_image:
pixman_glyph_cache_thaw(cache);
if (pglyphs != stack_glyphs)
free(pglyphs);
}
#else
} else
#endif
do {
int n = list->len;
x += list->xOff;
@ -1011,7 +1011,6 @@ next_image:
}
list++;
} while (--nlist);
#endif
pixman_image_unref(mask_image);
mask = CreatePicture(0, &pixmap->drawable,
@ -1290,7 +1289,6 @@ static bool can_discard_mask(uint8_t op, PicturePtr src, PictFormatPtr mask,
return color >> 24 == 0xff;
}
#if HAS_PIXMAN_GLYPHS
static void
glyphs_fallback(CARD8 op,
PicturePtr src,
@ -1356,312 +1354,254 @@ glyphs_fallback(CARD8 op,
mask_format = NULL;
}
cache = sna->render.glyph_cache;
pixman_glyph_cache_freeze(cache);
#if HAS_PIXMAN_GLYPHS
if (sna->render.glyph_cache) {
cache = sna->render.glyph_cache;
pixman_glyph_cache_freeze(cache);
count = 0;
for (n = 0; n < nlist; ++n)
count += list[n].len;
if (count > N_STACK_GLYPHS) {
pglyphs = malloc (count * sizeof(pixman_glyph_t));
if (pglyphs == NULL)
count = 0;
for (n = 0; n < nlist; ++n)
count += list[n].len;
if (count > N_STACK_GLYPHS) {
pglyphs = malloc (count * sizeof(pixman_glyph_t));
if (pglyphs == NULL)
goto out;
}
count = 0;
x = y = 0;
while (nlist--) {
n = list->len;
x += list->xOff;
y += list->yOff;
while (n--) {
GlyphPtr g = *glyphs++;
const void *ptr;
if (g->info.width == 0 || g->info.height == 0)
goto next;
ptr = pixman_glyph_cache_lookup(cache, g, NULL);
if (ptr == NULL) {
pixman_image_t *glyph_image;
glyph_image = sna_glyph_get_image(g, screen);
if (glyph_image == NULL)
goto next;
ptr = pixman_glyph_cache_insert(cache, g, NULL,
g->info.x,
g->info.y,
glyph_image);
if (ptr == NULL)
goto out;
}
pglyphs[count].x = x;
pglyphs[count].y = y;
pglyphs[count].glyph = ptr;
count++;
next:
x += g->info.xOff;
y += g->info.yOff;
}
list++;
}
src_image = image_from_pict(src, FALSE, &src_dx, &src_dy);
if (src_image == NULL)
goto out;
}
count = 0;
x = y = 0;
while (nlist--) {
n = list->len;
x += list->xOff;
y += list->yOff;
while (n--) {
GlyphPtr g = *glyphs++;
const void *ptr;
dst_image = image_from_pict(dst, TRUE, &dst_dx, &dst_dy);
if (dst_image == NULL)
goto out_free_src;
if (g->info.width == 0 || g->info.height == 0)
goto next;
if (mask_format) {
pixman_composite_glyphs(op, src_image, dst_image,
mask_format->format | (mask_format->depth << 24),
src_x + src_dx + region.extents.x1 - dst_x,
src_y + src_dy + region.extents.y1 - dst_y,
region.extents.x1, region.extents.y1,
region.extents.x1 + dst_dx, region.extents.y1 + dst_dy,
region.extents.x2 - region.extents.x1,
region.extents.y2 - region.extents.y1,
cache, count, pglyphs);
} else {
pixman_composite_glyphs_no_mask(op, src_image, dst_image,
src_x + src_dx - dst_x, src_y + src_dy - dst_y,
dst_dx, dst_dy,
cache, count, pglyphs);
}
ptr = pixman_glyph_cache_lookup(cache, g, NULL);
if (ptr == NULL) {
free_pixman_pict(dst, dst_image);
out_free_src:
free_pixman_pict(src, src_image);
out:
pixman_glyph_cache_thaw(cache);
if (pglyphs != stack_glyphs)
free(pglyphs);
} else
#endif
{
pixman_image_t *mask_image;
dst_image = image_from_pict(dst, TRUE, &x, &y);
if (dst_image == NULL)
goto cleanup_region;
DBG(("%s: dst offset (%d, %d)\n", __FUNCTION__, x, y));
if (x | y) {
region.extents.x1 += x;
region.extents.x2 += x;
region.extents.y1 += y;
region.extents.y2 += y;
}
src_image = image_from_pict(src, FALSE, &src_dx, &src_dy);
if (src_image == NULL)
goto cleanup_dst;
DBG(("%s: src offset (%d, %d)\n", __FUNCTION__, src_dx, src_dy));
src_x += src_dx - list->xOff;
src_y += src_dy - list->yOff;
if (mask_format) {
DBG(("%s: create mask (%d, %d)x(%d,%d) + (%d,%d) + (%d,%d), depth=%d, format=%lx [%lx], ca? %d\n",
__FUNCTION__,
region.extents.x1, region.extents.y1,
region.extents.x2 - region.extents.x1,
region.extents.y2 - region.extents.y1,
dst->pDrawable->x, dst->pDrawable->y,
x, y,
mask_format->depth,
(long)mask_format->format,
(long)(mask_format->depth << 24 | mask_format->format),
NeedsComponent(mask_format->format)));
mask_image =
pixman_image_create_bits(mask_format->depth << 24 | mask_format->format,
region.extents.x2 - region.extents.x1,
region.extents.y2 - region.extents.y1,
NULL, 0);
if (mask_image == NULL)
goto cleanup_src;
if (NeedsComponent(mask_format->format))
pixman_image_set_component_alpha(mask_image, TRUE);
x -= region.extents.x1;
y -= region.extents.y1;
} else {
mask_image = dst_image;
src_x -= x - dst->pDrawable->x;
src_y -= y - dst->pDrawable->y;
}
do {
n = list->len;
x += list->xOff;
y += list->yOff;
while (n--) {
GlyphPtr g = *glyphs++;
pixman_image_t *glyph_image;
if (g->info.width == 0 || g->info.height == 0)
goto next_glyph;
glyph_image = sna_glyph_get_image(g, screen);
if (glyph_image == NULL)
goto next;
goto next_glyph;
ptr = pixman_glyph_cache_insert(cache, g, NULL,
g->info.x,
g->info.y,
glyph_image);
if (ptr == NULL)
goto out;
}
if (mask_format) {
DBG(("%s: glyph to mask (%d, %d)x(%d, %d)\n",
__FUNCTION__,
x - g->info.x,
y - g->info.y,
g->info.width,
g->info.height));
pglyphs[count].x = x;
pglyphs[count].y = y;
pglyphs[count].glyph = ptr;
count++;
next:
x += g->info.xOff;
y += g->info.yOff;
}
list++;
}
src_image = image_from_pict(src, FALSE, &src_dx, &src_dy);
if (src_image == NULL)
goto out;
dst_image = image_from_pict(dst, TRUE, &dst_dx, &dst_dy);
if (dst_image == NULL)
goto out_free_src;
if (mask_format) {
pixman_composite_glyphs(op, src_image, dst_image,
mask_format->format | (mask_format->depth << 24),
src_x + src_dx + region.extents.x1 - dst_x,
src_y + src_dy + region.extents.y1 - dst_y,
region.extents.x1, region.extents.y1,
region.extents.x1 + dst_dx, region.extents.y1 + dst_dy,
region.extents.x2 - region.extents.x1,
region.extents.y2 - region.extents.y1,
cache, count, pglyphs);
} else {
pixman_composite_glyphs_no_mask(op, src_image, dst_image,
src_x + src_dx - dst_x, src_y + src_dy - dst_y,
dst_dx, dst_dy,
cache, count, pglyphs);
}
free_pixman_pict(dst, dst_image);
out_free_src:
free_pixman_pict(src, src_image);
out:
pixman_glyph_cache_thaw(cache);
if (pglyphs != stack_glyphs)
free(pglyphs);
}
#else
static void
glyphs_fallback(CARD8 op,
PicturePtr src,
PicturePtr dst,
PictFormatPtr mask_format,
int src_x,
int src_y,
int nlist,
GlyphListPtr list,
GlyphPtr *glyphs)
{
struct sna *sna = to_sna_from_drawable(dst->pDrawable);
ScreenPtr screen = dst->pDrawable->pScreen;
pixman_image_t *dst_image, *mask_image, *src_image;
int dx, dy, x, y;
RegionRec region;
glyph_extents(nlist, list, glyphs, &region.extents);
if (region.extents.x2 <= region.extents.x1 ||
region.extents.y2 <= region.extents.y1)
return;
DBG(("%s: (%d, %d), (%d, %d)\n", __FUNCTION__,
region.extents.x1, region.extents.y1,
region.extents.x2, region.extents.y2));
region.data = NULL;
RegionTranslate(&region, dst->pDrawable->x, dst->pDrawable->y);
if (dst->pCompositeClip)
RegionIntersect(&region, &region, dst->pCompositeClip);
DBG(("%s: clipped extents (%d, %d), (%d, %d)\n",
__FUNCTION__,
RegionExtents(&region)->x1, RegionExtents(&region)->y1,
RegionExtents(&region)->x2, RegionExtents(&region)->y2));
if (!RegionNotEmpty(&region))
return;
if (!sna_drawable_move_region_to_cpu(dst->pDrawable, &region,
MOVE_READ | MOVE_WRITE))
return;
if (dst->alphaMap &&
!sna_drawable_move_to_cpu(dst->alphaMap->pDrawable,
MOVE_READ | MOVE_WRITE))
return;
if (src->pDrawable) {
if (!sna_drawable_move_to_cpu(src->pDrawable,
MOVE_READ))
return;
if (src->alphaMap &&
!sna_drawable_move_to_cpu(src->alphaMap->pDrawable,
MOVE_READ))
return;
}
RegionTranslate(&region, -dst->pDrawable->x, -dst->pDrawable->y);
dst_image = image_from_pict(dst, TRUE, &x, &y);
if (dst_image == NULL)
goto cleanup_region;
DBG(("%s: dst offset (%d, %d)\n", __FUNCTION__, x, y));
if (x | y) {
region.extents.x1 += x;
region.extents.x2 += x;
region.extents.y1 += y;
region.extents.y2 += y;
}
src_image = image_from_pict(src, FALSE, &dx, &dy);
if (src_image == NULL)
goto cleanup_dst;
DBG(("%s: src offset (%d, %d)\n", __FUNCTION__, dx, dy));
src_x += dx - list->xOff;
src_y += dy - list->yOff;
if (mask_format &&
(op_is_bounded(op) || (nlist == 1 && list->len == 1)) &&
mask_format == glyphs_format(nlist, list, glyphs))
mask_format = NULL;
if (mask_format) {
DBG(("%s: create mask (%d, %d)x(%d,%d) + (%d,%d) + (%d,%d), depth=%d, format=%lx [%lx], ca? %d\n",
__FUNCTION__,
region.extents.x1, region.extents.y1,
region.extents.x2 - region.extents.x1,
region.extents.y2 - region.extents.y1,
dst->pDrawable->x, dst->pDrawable->y,
x, y,
mask_format->depth,
(long)mask_format->format,
(long)(mask_format->depth << 24 | mask_format->format),
NeedsComponent(mask_format->format)));
mask_image =
pixman_image_create_bits(mask_format->depth << 24 | mask_format->format,
region.extents.x2 - region.extents.x1,
region.extents.y2 - region.extents.y1,
NULL, 0);
if (mask_image == NULL)
goto cleanup_src;
if (NeedsComponent(mask_format->format))
pixman_image_set_component_alpha(mask_image, TRUE);
x -= region.extents.x1;
y -= region.extents.y1;
} else {
mask_image = dst_image;
src_x -= x - dst->pDrawable->x;
src_y -= y - dst->pDrawable->y;
}
do {
int n = list->len;
x += list->xOff;
y += list->yOff;
while (n--) {
GlyphPtr g = *glyphs++;
pixman_image_t *glyph_image;
if (g->info.width == 0 || g->info.height == 0)
goto next_glyph;
glyph_image = sna_glyph_get_image(g, screen);
if (glyph_image == NULL)
goto next_glyph;
if (mask_format) {
DBG(("%s: glyph+(%d,%d) to mask (%d, %d)x(%d, %d)\n",
__FUNCTION__,
dx, dy,
x - g->info.x,
y - g->info.y,
g->info.width,
g->info.height));
if (list->format == mask_format) {
assert(pixman_image_get_format(glyph_image) == pixman_image_get_format(mask_image));
pixman_image_composite(PictOpAdd,
glyph_image,
NULL,
mask_image,
dx, dy,
0, 0,
x - g->info.x,
y - g->info.y,
g->info.width,
g->info.height);
if (list->format == mask_format) {
assert(pixman_image_get_format(glyph_image) == pixman_image_get_format(mask_image));
pixman_image_composite(PictOpAdd,
glyph_image,
NULL,
mask_image,
0, 0,
0, 0,
x - g->info.x,
y - g->info.y,
g->info.width,
g->info.height);
} else {
pixman_image_composite(PictOpAdd,
sna->render.white_image,
glyph_image,
mask_image,
0, 0,
0, 0,
x - g->info.x,
y - g->info.y,
g->info.width,
g->info.height);
}
} else {
pixman_image_composite(PictOpAdd,
sna->render.white_image,
int xi = x - g->info.x;
int yi = y - g->info.y;
DBG(("%s: glyph to dst (%d, %d)x(%d, %d)/[(%d, %d)x(%d, %d)], src (%d, %d) [op=%d]\n",
__FUNCTION__,
xi, yi,
g->info.width, g->info.height,
dst->pDrawable->x,
dst->pDrawable->y,
dst->pDrawable->width,
dst->pDrawable->height,
src_x + xi,
src_y + yi,
op));
pixman_image_composite(op,
src_image,
glyph_image,
mask_image,
dx, dy,
dst_image,
src_x + xi,
src_y + yi,
0, 0,
x - g->info.x,
y - g->info.y,
xi, yi,
g->info.width,
g->info.height);
}
} else {
int xi = x - g->info.x;
int yi = y - g->info.y;
DBG(("%s: glyph+(%d, %d) to dst (%d, %d)x(%d, %d)/[(%d, %d)x(%d, %d)], src (%d, %d) [op=%d]\n",
__FUNCTION__,
dx, dy,
xi, yi,
g->info.width, g->info.height,
dst->pDrawable->x,
dst->pDrawable->y,
dst->pDrawable->width,
dst->pDrawable->height,
src_x + xi,
src_y + yi,
op));
pixman_image_composite(op,
src_image,
glyph_image,
dst_image,
src_x + xi,
src_y + yi,
dx, dy,
xi, yi,
g->info.width,
g->info.height);
}
next_glyph:
x += g->info.xOff;
y += g->info.yOff;
}
list++;
} while (--nlist);
x += g->info.xOff;
y += g->info.yOff;
}
list++;
} while (--nlist);
if (mask_format) {
DBG(("%s: glyph mask composite src=(%d+%d,%d+%d) dst=(%d, %d)x(%d, %d)\n",
__FUNCTION__,
src_x, region.extents.x1, src_y, region.extents.y1,
region.extents.x1, region.extents.y1,
region.extents.x2 - region.extents.x1,
region.extents.y2 - region.extents.y1));
pixman_image_composite(op, src_image, mask_image, dst_image,
src_x, src_y,
0, 0,
region.extents.x1, region.extents.y1,
region.extents.x2 - region.extents.x1,
region.extents.y2 - region.extents.y1);
pixman_image_unref(mask_image);
}
if (mask_format) {
DBG(("%s: glyph mask composite src=(%d+%d,%d+%d) dst=(%d, %d)x(%d, %d)\n",
__FUNCTION__,
src_x, region.extents.x1, src_y, region.extents.y1,
region.extents.x1, region.extents.y1,
region.extents.x2 - region.extents.x1,
region.extents.y2 - region.extents.y1));
pixman_image_composite(op, src_image, mask_image, dst_image,
src_x, src_y,
0, 0,
region.extents.x1, region.extents.y1,
region.extents.x2 - region.extents.x1,
region.extents.y2 - region.extents.y1);
pixman_image_unref(mask_image);
}
cleanup_src:
free_pixman_pict(src, src_image);
free_pixman_pict(src, src_image);
cleanup_dst:
free_pixman_pict(dst, dst_image);
free_pixman_pict(dst, dst_image);
}
cleanup_region:
RegionUninit(&region);
}
#endif
void
sna_glyphs(CARD8 op,
@ -1757,7 +1697,9 @@ sna_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph)
if (priv->image) {
#if HAS_PIXMAN_GLYPHS
struct sna *sna = to_sna_from_screen(screen);
pixman_glyph_cache_remove(sna->render.glyph_cache, glyph, NULL);
if (sna->render.glyph_cache)
pixman_glyph_cache_remove(sna->render.glyph_cache,
glyph, NULL);
#endif
pixman_image_unref(priv->image);
priv->image = NULL;

View File

@ -382,6 +382,9 @@ bool sna_gradients_create(struct sna *sna)
{
DBG(("%s\n", __FUNCTION__));
if (!can_render(sna))
return true;
if (!sna_alpha_cache_init(sna))
return false;