diff --git a/miext/rootless/rootlessCommon.h b/miext/rootless/rootlessCommon.h index 83dec3bb7..e2630b826 100644 --- a/miext/rootless/rootlessCommon.h +++ b/miext/rootless/rootlessCommon.h @@ -108,6 +108,9 @@ typedef struct _RootlessScreenRec { CompositeProcPtr Composite; GlyphsProcPtr Glyphs; + TrapezoidsProcPtr Trapezoids; + TrianglesProcPtr Triangles; + CompositeRectsProcPtr CompositeRects; InstallColormapProcPtr InstallColormap; UninstallColormapProcPtr UninstallColormap; diff --git a/miext/rootless/rootlessScreen.c b/miext/rootless/rootlessScreen.c index 79fe3507b..2abe3ad0c 100644 --- a/miext/rootless/rootlessScreen.c +++ b/miext/rootless/rootlessScreen.c @@ -41,6 +41,7 @@ #include "propertyst.h" #include "mivalidate.h" #include "picturestr.h" +#include "mipict.h" #include "colormapst.h" #include @@ -51,6 +52,30 @@ #include "rootlessCommon.h" #include "rootlessWindow.h" +/* + * Render operations use PictFormat to describe pixel layout. Depth-24 + * windows use PICT_x8r8g8b8, where 'x' tells pixman the high byte is + * padding it may freely zero. The compositor needs this byte to be 0xFF + * (opaque). Temporarily upgrading the destination format from 'x' to 'a' + * prevents pixman from optimizing away the alpha channel, paralleling how + * ROOTLESS_PROTECT_ALPHA prevents fb from doing the same for GC ops. + */ + +#if ROOTLESS_PROTECT_ALPHA +#define RL_RENDER_SAVE_FORMAT(pict) \ + CARD32 _saved_format = (pict)->format; \ + if ((pict)->pDrawable->type == DRAWABLE_WINDOW && \ + (pict)->format == PICT_x8r8g8b8) \ + (pict)->format = PICT_a8r8g8b8 + +#define RL_RENDER_RESTORE_FORMAT(pict) \ + (pict)->format = _saved_format + +#else +#define RL_RENDER_SAVE_FORMAT(pict) +#define RL_RENDER_RESTORE_FORMAT(pict) +#endif + extern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, VTKind kind); extern Bool RootlessCreateGC(GCPtr pGC); @@ -257,8 +282,10 @@ RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); + RL_RENDER_SAVE_FORMAT(pDst); ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); + RL_RENDER_RESTORE_FORMAT(pDst); if (dstWin && IsFramedWindow(dstWin)) { RootlessDamageRect(dstWin, xDst, yDst, width, height); @@ -292,7 +319,9 @@ RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, //SCREEN_UNWRAP(ps, Glyphs); ps->Glyphs = SCREENREC(pScreen)->Glyphs; + RL_RENDER_SAVE_FORMAT(pDst); ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + RL_RENDER_RESTORE_FORMAT(pDst); ps->Glyphs = RootlessGlyphs; //SCREEN_WRAP(ps, Glyphs); @@ -332,8 +361,8 @@ RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, x2 = x1 + glyph->info.width; y2 = y1 + glyph->info.height; - box.x1 = max(box.x1, x1); - box.y1 = max(box.y1, y1); + box.x1 = min(box.x1, x1); + box.y1 = min(box.y1, y1); box.x2 = max(box.x2, x2); box.y2 = max(box.y2, y2); @@ -348,6 +377,141 @@ RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, } } +static void +RootlessTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid *traps) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + WindowPtr srcWin, dstWin; + + srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr) pSrc->pDrawable : NULL; + dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr) pDst->pDrawable : NULL; + + ps->Trapezoids = SCREENREC(pScreen)->Trapezoids; + + if (srcWin && IsFramedWindow(srcWin)) + RootlessStartDrawing(srcWin); + if (dstWin && IsFramedWindow(dstWin)) + RootlessStartDrawing(dstWin); + + RL_RENDER_SAVE_FORMAT(pDst); + ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); + RL_RENDER_RESTORE_FORMAT(pDst); + + if (dstWin && IsFramedWindow(dstWin) && ntrap > 0) { + BoxRec box; + + miTrapezoidBounds(ntrap, traps, &box); + + if (box.x1 < box.x2 && box.y1 < box.y2) { + box.x1 += dstWin->drawable.x; + box.y1 += dstWin->drawable.y; + box.x2 += dstWin->drawable.x; + box.y2 += dstWin->drawable.y; + RootlessDamageBox(dstWin, &box); + } + } + + ps->Trapezoids = RootlessTrapezoids; +} + +static void +RootlessTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntri, xTriangle *tris) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + WindowPtr srcWin, dstWin; + + srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr) pSrc->pDrawable : NULL; + dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr) pDst->pDrawable : NULL; + + ps->Triangles = SCREENREC(pScreen)->Triangles; + + if (srcWin && IsFramedWindow(srcWin)) + RootlessStartDrawing(srcWin); + if (dstWin && IsFramedWindow(dstWin)) + RootlessStartDrawing(dstWin); + + RL_RENDER_SAVE_FORMAT(pDst); + ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); + RL_RENDER_RESTORE_FORMAT(pDst); + + if (dstWin && IsFramedWindow(dstWin) && ntri > 0) { + BoxRec box; + + miTriangleBounds(ntri, tris, &box); + + if (box.x1 < box.x2 && box.y1 < box.y2) { + box.x1 += dstWin->drawable.x; + box.y1 += dstWin->drawable.y; + box.x2 += dstWin->drawable.x; + box.y2 += dstWin->drawable.y; + RootlessDamageBox(dstWin, &box); + } + } + + ps->Triangles = RootlessTriangles; +} + +static void +RootlessCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color, + int nRect, xRectangle *rects) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + WindowPtr dstWin; + + dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr) pDst->pDrawable : NULL; + + ps->CompositeRects = SCREENREC(pScreen)->CompositeRects; + + if (dstWin && IsFramedWindow(dstWin)) + RootlessStartDrawing(dstWin); + + RL_RENDER_SAVE_FORMAT(pDst); + ps->CompositeRects(op, pDst, color, nRect, rects); + RL_RENDER_RESTORE_FORMAT(pDst); + + if (dstWin && IsFramedWindow(dstWin) && nRect > 0) { + int i; + BoxRec box; + + box.x1 = rects[0].x; + box.y1 = rects[0].y; + box.x2 = rects[0].x + rects[0].width; + box.y2 = rects[0].y + rects[0].height; + + for (i = 1; i < nRect; i++) { + short x1 = rects[i].x; + short y1 = rects[i].y; + short x2 = x1 + rects[i].width; + short y2 = y1 + rects[i].height; + + if (x1 < box.x1) box.x1 = x1; + if (y1 < box.y1) box.y1 = y1; + if (x2 > box.x2) box.x2 = x2; + if (y2 > box.y2) box.y2 = y2; + } + + if (box.x1 < box.x2 && box.y1 < box.y2) { + RootlessDamageRect(dstWin, + box.x1, box.y1, + box.x2 - box.x1, box.y2 - box.y1); + } + } + + ps->CompositeRects = RootlessCompositeRects; +} + /* * RootlessValidateTree * ValidateTree is modified in two ways: @@ -685,13 +849,19 @@ RootlessWrap(ScreenPtr pScreen) WRAP(SetShape); { - // Composite and Glyphs don't use normal screen wrapping + // PictureScreen procs don't use normal screen wrapping PictureScreenPtr ps = GetPictureScreen(pScreen); s->Composite = ps->Composite; ps->Composite = RootlessComposite; s->Glyphs = ps->Glyphs; ps->Glyphs = RootlessGlyphs; + s->Trapezoids = ps->Trapezoids; + ps->Trapezoids = RootlessTrapezoids; + s->Triangles = ps->Triangles; + ps->Triangles = RootlessTriangles; + s->CompositeRects = ps->CompositeRects; + ps->CompositeRects = RootlessCompositeRects; } // WRAP(ClearToBackground); fixme put this back? useful for shaped wins?