diff options
Diffstat (limited to 'uxa/uxa-render.c')
-rw-r--r-- | uxa/uxa-render.c | 208 |
1 files changed, 205 insertions, 3 deletions
diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c index 51c12f17..878b0288 100644 --- a/uxa/uxa-render.c +++ b/uxa/uxa-render.c @@ -29,11 +29,24 @@ #include <stdlib.h> #include "uxa-priv.h" +#include "uxa-glamor.h" #include <xorgVersion.h> #ifdef RENDER #include "mipict.h" +/* Note: when using glamor we can not fail through to the ordinary UXA + * code paths, as glamor keeps an internal texture which will become + * inconsistent with the original bo. (The texture is replaced whenever + * the format changes, e.g. switching between xRGB and ARGB, for which mesa + * will allocate its own bo.) + * + * Ergo it is unsafe to fall through to the original backend operations if + * glamor is enabled. + * + * XXX This has some serious implications for mixing Render, DRI, scanout... + */ + static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string, int n) { @@ -986,6 +999,20 @@ uxa_solid_rects (CARD8 op, if (!pixman_region_not_empty(dst->pCompositeClip)) return; + if (uxa_screen->info->flags & UXA_USE_GLAMOR) { + int ok; + + uxa_picture_prepare_access(dst, UXA_GLAMOR_ACCESS_RW); + ok = glamor_composite_rects_nf(op, dst, color, + num_rects, rects); + uxa_picture_finish_access(dst, UXA_GLAMOR_ACCESS_RW); + + if (!ok) + goto fallback; + + return; + } + if (dst->alphaMap) goto fallback; @@ -1530,6 +1557,30 @@ uxa_composite(CARD8 op, RegionRec region; int tx, ty; + if (uxa_screen->info->flags & UXA_USE_GLAMOR) { + int ok; + + uxa_picture_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW); + uxa_picture_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO); + if (pMask) + uxa_picture_prepare_access(pMask, UXA_GLAMOR_ACCESS_RO); + + ok = glamor_composite_nf(op, + pSrc, pMask, pDst, xSrc, ySrc, + xMask, yMask, xDst, yDst, + width, height); + + if (pMask) + uxa_picture_finish_access(pMask, UXA_GLAMOR_ACCESS_RO); + uxa_picture_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO); + uxa_picture_finish_access(pDst, UXA_GLAMOR_ACCESS_RW); + + if (!ok) + goto fallback; + + return; + } + if (uxa_screen->swappedOut || uxa_screen->force_fallback) goto fallback; @@ -1766,8 +1817,8 @@ uxa_create_alpha_picture(ScreenPtr pScreen, static void uxa_check_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, - PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, - int ntrap, xTrapezoid * traps) + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid * traps) { ScreenPtr screen = dst->pDrawable->pScreen; @@ -1871,7 +1922,25 @@ uxa_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, BoxRec bounds; Bool direct; + if (uxa_screen->info->flags & UXA_USE_GLAMOR) { + int ok; + + uxa_picture_prepare_access(dst, UXA_GLAMOR_ACCESS_RW); + uxa_picture_prepare_access(src, UXA_GLAMOR_ACCESS_RO); + ok = glamor_trapezoids_nf(op, + src, dst, maskFormat, xSrc, + ySrc, ntrap, traps); + uxa_picture_finish_access(src, UXA_GLAMOR_ACCESS_RO); + uxa_picture_finish_access(dst, UXA_GLAMOR_ACCESS_RW); + + if (!ok) + goto fallback; + + return; + } + if (uxa_screen->swappedOut || uxa_screen->force_fallback) { +fallback: uxa_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, ntrap, traps); return; } @@ -1976,6 +2045,88 @@ uxa_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, } } +static void +uxa_check_triangles(CARD8 op, PicturePtr src, PicturePtr dst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntri, xTriangle *tri) +{ + ScreenPtr screen = dst->pDrawable->pScreen; + + if (maskFormat) { + PixmapPtr scratch = NULL; + PicturePtr mask; + INT16 xDst, yDst; + INT16 xRel, yRel; + BoxRec bounds; + int width, height; + pixman_image_t *image; + pixman_format_code_t format; + int error; + + xDst = pixman_fixed_to_int(tri[0].p1.x); + yDst = pixman_fixed_to_int(tri[0].p1.y); + + miTriangleBounds (ntri, tri, &bounds); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + + width = bounds.x2 - bounds.x1; + height = bounds.y2 - bounds.y1; + + format = maskFormat->format | + (BitsPerPixel(maskFormat->depth) << 24); + image = + pixman_image_create_bits(format, width, height, NULL, 0); + if (!image) + return; + + pixman_add_triangles(image, + -bounds.x1, -bounds.y1, + ntri, (pixman_triangle_t *)tri); + + scratch = GetScratchPixmapHeader(screen, width, height, + PIXMAN_FORMAT_DEPTH(format), + PIXMAN_FORMAT_BPP(format), + pixman_image_get_stride(image), + pixman_image_get_data(image)); + if (!scratch) { + pixman_image_unref(image); + return; + } + + mask = CreatePicture(0, &scratch->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), + format), + 0, 0, serverClient, &error); + if (!mask) { + FreeScratchPixmapHeader(scratch); + pixman_image_unref(image); + return; + } + + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture(op, src, mask, dst, + xRel, yRel, + 0, 0, + bounds.x1, bounds.y1, + width, height); + FreePicture(mask, 0); + + FreeScratchPixmapHeader(scratch); + pixman_image_unref(image); + } else { + if (dst->polyEdge == PolyEdgeSharp) + maskFormat = PictureMatchFormat(screen, 1, PICT_a1); + else + maskFormat = PictureMatchFormat(screen, 8, PICT_a8); + + for (; ntri; ntri--, tri++) + uxa_check_triangles(op, src, dst, maskFormat, xSrc, ySrc, 1, tri); + } +} + /** * uxa_triangles is essentially a copy of miTriangles that uses * uxa_create_alpha_picture instead of miCreateAlphaPicture. @@ -1995,10 +2146,36 @@ uxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, int ntri, xTriangle * tris) { ScreenPtr pScreen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); PictureScreenPtr ps = GetPictureScreen(pScreen); BoxRec bounds; - Bool direct = op == PictOpAdd && miIsSolidAlpha(pSrc); + Bool direct; + + if (uxa_screen->info->flags & UXA_USE_GLAMOR) { + int ok; + + uxa_picture_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW); + uxa_picture_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO); + ok = glamor_triangles_nf(op, + pSrc, pDst, maskFormat, xSrc, + ySrc, ntri, tris); + uxa_picture_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO); + uxa_picture_finish_access(pDst, UXA_GLAMOR_ACCESS_RW); + + if (!ok) + goto fallback; + + return; + } + + if (uxa_screen->swappedOut || uxa_screen->force_fallback) { +fallback: + uxa_check_triangles(op, pSrc, pDst, maskFormat, + xSrc, ySrc, ntri, tris); + return; + } + direct = op == PictOpAdd && miIsSolidAlpha(pSrc); if (maskFormat || direct) { miTriangleBounds(ntri, tris, &bounds); @@ -2069,3 +2246,28 @@ uxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, tris); } } + +void +uxa_add_traps(PicturePtr pPicture, + INT16 x_off, INT16 y_off, int ntrap, xTrap * traps) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); + + if (uxa_screen->info->flags & UXA_USE_GLAMOR) { + int ok; + + uxa_picture_prepare_access(pPicture, UXA_GLAMOR_ACCESS_RW); + ok = glamor_add_traps_nf(pPicture, + x_off, y_off, ntrap, traps); + uxa_picture_finish_access(pPicture, UXA_GLAMOR_ACCESS_RW); + + if (!ok) + goto fallback; + + return; + } + +fallback: + uxa_check_add_traps(pPicture, x_off, y_off, ntrap, traps); +} |