/** * Returns the pixmap which backs a drawable, and the offsets to add to * coordinates to make them address the same bits in the backing drawable. */ PixmapPtr uxa_get_offscreen_pixmap(DrawablePtr drawable, int *xp, int *yp) { PixmapPtr pixmap = uxa_get_drawable_pixmap(drawable); uxa_get_drawable_deltas(drawable, pixmap, xp, yp); if (uxa_pixmap_is_offscreen(pixmap)) return pixmap; else return NULL; }
/** * uxa_finish_access() is UXA's wrapper for the driver's finish_access() handler. * * It deals with calling the driver's finish_access() only if necessary. */ void uxa_finish_access(DrawablePtr pDrawable) { ScreenPtr pScreen = pDrawable->pScreen; uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable); if (uxa_screen->info->finish_access == NULL) return; if (!uxa_pixmap_is_offscreen(pPixmap)) return; (*uxa_screen->info->finish_access) (pPixmap); }
/** * uxa_prepare_access() is UXA's wrapper for the driver's PrepareAccess() handler. * * It deals with waiting for synchronization with the card, determining if * PrepareAccess() is necessary, and working around PrepareAccess() failure. */ Bool uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access) { ScreenPtr pScreen = pDrawable->pScreen; uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable); Bool offscreen = uxa_pixmap_is_offscreen(pPixmap); if (!offscreen) return TRUE; if (uxa_screen->info->prepare_access) return (*uxa_screen->info->prepare_access) (pPixmap, access); return TRUE; }
/** * uxa_drawable_is_offscreen() is a convenience wrapper for * uxa_pixmap_is_offscreen(). */ Bool uxa_drawable_is_offscreen(DrawablePtr pDrawable) { return uxa_pixmap_is_offscreen(uxa_get_drawable_pixmap(pDrawable)); }
static int uxa_glyphs_via_mask(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) { ScreenPtr screen = pDst->pDrawable->pScreen; uxa_screen_t *uxa_screen = uxa_get_screen(screen); CARD32 component_alpha; PixmapPtr pixmap, white_pixmap; PicturePtr glyph_atlas, mask, white; int xDst = list->xOff, yDst = list->yOff; int x, y, width, height; int dst_off_x, dst_off_y; int n, error; BoxRec box; uxa_glyph_extents(nlist, list, glyphs, &box); if (box.x2 <= box.x1 || box.y2 <= box.y1) return 0; dst_off_x = box.x1; dst_off_y = box.y1; width = box.x2 - box.x1; height = box.y2 - box.y1; x = -box.x1; y = -box.y1; if (maskFormat->depth == 1) { PictFormatPtr a8Format = PictureMatchFormat(screen, 8, PICT_a8); if (!a8Format) return -1; maskFormat = a8Format; } pixmap = screen->CreatePixmap(screen, width, height, maskFormat->depth, CREATE_PIXMAP_USAGE_SCRATCH); if (!pixmap) return 1; if (!uxa_pixmap_is_offscreen(pixmap)) { screen->DestroyPixmap(pixmap); return -1; } white_pixmap = NULL; white = create_white_solid(screen); if (white) white_pixmap = uxa_get_drawable_pixmap(white->pDrawable); if (!white_pixmap) { if (white) FreePicture(white, 0); screen->DestroyPixmap(pixmap); return -1; } uxa_clear_pixmap(screen, uxa_screen, pixmap); component_alpha = NeedsComponent(maskFormat->format); mask = CreatePicture(0, &pixmap->drawable, maskFormat, CPComponentAlpha, &component_alpha, serverClient, &error); screen->DestroyPixmap(pixmap); if (!mask) { FreePicture(white, 0); return 1; } ValidatePicture(mask); glyph_atlas = NULL; while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; while (n--) { GlyphPtr glyph = *glyphs++; PicturePtr this_atlas; int glyph_x, glyph_y; struct uxa_glyph *priv; if (glyph->info.width == 0 || glyph->info.height == 0) goto next_glyph; priv = uxa_glyph_get_private(glyph); if (priv != NULL) { glyph_x = priv->x; glyph_y = priv->y; this_atlas = priv->cache->picture; } else { if (glyph_atlas) { uxa_screen->info->done_composite(pixmap); glyph_atlas = NULL; } this_atlas = uxa_glyph_cache(screen, glyph, &glyph_x, &glyph_y); if (this_atlas == NULL) { /* no cache for this glyph */ this_atlas = GetGlyphPicture(glyph, screen); glyph_x = glyph_y = 0; } } if (this_atlas != glyph_atlas) { PixmapPtr glyph_pixmap; if (glyph_atlas) uxa_screen->info->done_composite(pixmap); glyph_pixmap = uxa_get_drawable_pixmap(this_atlas->pDrawable); if (!uxa_pixmap_is_offscreen(glyph_pixmap) || !uxa_screen->info->prepare_composite(PictOpAdd, white, this_atlas, mask, white_pixmap, glyph_pixmap, pixmap)) { FreePicture(white, 0); FreePicture(mask, 0); return -1; } glyph_atlas = this_atlas; } uxa_screen->info->composite(pixmap, 0, 0, glyph_x, glyph_y, x - glyph->info.x, y - glyph->info.y, glyph->info.width, glyph->info.height); next_glyph: x += glyph->info.xOff; y += glyph->info.yOff; } list++; } if (glyph_atlas) uxa_screen->info->done_composite(pixmap); uxa_composite(op, pSrc, mask, pDst, dst_off_x + xSrc - xDst, dst_off_y + ySrc - yDst, 0, 0, dst_off_x, dst_off_y, width, height); FreePicture(white, 0); FreePicture(mask, 0); return 0; }
void uxa_copy_n_to_n(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { ScreenPtr screen = pDstDrawable->pScreen; uxa_screen_t *uxa_screen = uxa_get_screen(screen); int src_off_x, src_off_y; int dst_off_x, dst_off_y; PixmapPtr pSrcPixmap, pDstPixmap; if (uxa_screen->info->flags & UXA_USE_GLAMOR) { int ok = 0; if (uxa_prepare_access(pSrcDrawable, UXA_GLAMOR_ACCESS_RO)) { if (uxa_prepare_access(pDstDrawable, UXA_GLAMOR_ACCESS_RW)) { ok = glamor_copy_n_to_n_nf(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure); uxa_finish_access(pDstDrawable, UXA_GLAMOR_ACCESS_RW); } uxa_finish_access(pSrcDrawable, UXA_GLAMOR_ACCESS_RO); } if (!ok) goto fallback; return; } if (uxa_screen->force_fallback) goto fallback; pSrcPixmap = uxa_get_drawable_pixmap(pSrcDrawable); pDstPixmap = uxa_get_drawable_pixmap(pDstDrawable); if (!pSrcPixmap || !pDstPixmap) goto fallback; if (uxa_screen->info->check_copy && !uxa_screen->info->check_copy(pSrcPixmap, pDstPixmap, pGC ? pGC->alu : GXcopy, pGC ? pGC->planemask : FB_ALLONES)) goto fallback; uxa_get_drawable_deltas(pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); uxa_get_drawable_deltas(pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); /* Mixed directions must be handled specially if the card is lame */ if ((uxa_screen->info->flags & UXA_TWO_BITBLT_DIRECTIONS) && reverse != upsidedown) { if (uxa_copy_n_to_n_two_dir (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy)) return; goto fallback; } if (!uxa_pixmap_is_offscreen(pDstPixmap)) { int stride, bpp; char *dst; if (!uxa_pixmap_is_offscreen(pSrcPixmap)) goto fallback; if (!uxa_screen->info->get_image) goto fallback; /* Don't bother with under 8bpp, XYPixmaps. */ bpp = pSrcPixmap->drawable.bitsPerPixel; if (bpp != pDstDrawable->bitsPerPixel || bpp < 8) goto fallback; /* Only accelerate copies: no rop or planemask. */ if (pGC && (!UXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask) || pGC->alu != GXcopy)) goto fallback; dst = pDstPixmap->devPrivate.ptr; stride = pDstPixmap->devKind; bpp /= 8; while (nbox--) { if (!uxa_screen->info->get_image(pSrcPixmap, pbox->x1 + dx + src_off_x, pbox->y1 + dy + src_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, (char *) dst + (pbox->y1 + dst_off_y) * stride + (pbox->x1 + dst_off_x) * bpp, stride)) goto fallback; pbox++; } return; } if (uxa_pixmap_is_offscreen(pSrcPixmap)) { if (!(*uxa_screen->info->prepare_copy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, upsidedown ? -1 : 1, pGC ? pGC->alu : GXcopy, pGC ? pGC-> planemask : FB_ALLONES)) goto fallback; while (nbox--) { (*uxa_screen->info->copy) (pDstPixmap, pbox->x1 + dx + src_off_x, pbox->y1 + dy + src_off_y, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); pbox++; } (*uxa_screen->info->done_copy) (pDstPixmap); } else { int stride, bpp; char *src; if (!uxa_screen->info->put_image) goto fallback; /* Don't bother with under 8bpp, XYPixmaps. */ bpp = pSrcPixmap->drawable.bitsPerPixel; if (bpp != pDstDrawable->bitsPerPixel || bpp < 8) goto fallback; /* Only accelerate copies: no rop or planemask. */ if (pGC && (!UXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask) || pGC->alu != GXcopy)) goto fallback; src = pSrcPixmap->devPrivate.ptr; stride = pSrcPixmap->devKind; bpp /= 8; while (nbox--) { if (!uxa_screen->info->put_image(pDstPixmap, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, (char *) src + (pbox->y1 + dy + src_off_y) * stride + (pbox->x1 + dx + src_off_x) * bpp, stride)) goto fallback; pbox++; } } return; fallback: UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, uxa_drawable_location(pSrcDrawable), uxa_drawable_location(pDstDrawable))); if (uxa_prepare_access(pDstDrawable, UXA_ACCESS_RW)) { if (pSrcDrawable == pDstDrawable || uxa_prepare_access(pSrcDrawable, UXA_ACCESS_RO)) { fbCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure); if (pSrcDrawable != pDstDrawable) uxa_finish_access(pSrcDrawable, UXA_ACCESS_RO); } uxa_finish_access(pDstDrawable, UXA_ACCESS_RW); } }
/** * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory. * * This is probably the only case we actually care about. The rest fall through * to migration and fbGetImage, which hopefully will result in migration pushing * the pixmap out of framebuffer. */ void uxa_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, unsigned int format, unsigned long planeMask, char *d) { ScreenPtr screen = pDrawable->pScreen; uxa_screen_t *uxa_screen = uxa_get_screen(screen); BoxRec Box; PixmapPtr pPix = uxa_get_drawable_pixmap(pDrawable); int xoff, yoff; Bool ok; uxa_get_drawable_deltas(pDrawable, pPix, &xoff, &yoff); Box.x1 = pDrawable->y + x + xoff; Box.y1 = pDrawable->y + y + yoff; Box.x2 = Box.x1 + w; Box.y2 = Box.y1 + h; if (uxa_screen->info->flags & UXA_USE_GLAMOR) { ok = 0; if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) { ok = glamor_get_image_nf(pDrawable, x, y, w, h, format, planeMask, d); uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW); } if (!ok) goto fallback; return; } if (uxa_screen->force_fallback) goto fallback; pPix = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); if (pPix == NULL || uxa_screen->info->get_image == NULL) goto fallback; /* Only cover the ZPixmap, solid copy case. */ if (format != ZPixmap || !UXA_PM_IS_SOLID(pDrawable, planeMask)) goto fallback; /* Only try to handle the 8bpp and up cases, since we don't want to * think about <8bpp. */ if (pDrawable->bitsPerPixel < 8) goto fallback; ok = uxa_screen->info->get_image(pPix, pDrawable->x + x + xoff, pDrawable->y + y + yoff, w, h, d, PixmapBytePad(w, pDrawable->depth)); if (ok) return; fallback: UXA_FALLBACK(("from %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable))); if (uxa_prepare_access(pDrawable, UXA_ACCESS_RO)) { fbGetImage(pDrawable, x, y, w, h, format, planeMask, d); uxa_finish_access(pDrawable, UXA_ACCESS_RO); } return; }