Merge branch 'server-21.1-branch' into 'server-21.1-branch'

rootless: Fix Glyphs damage bounding box to correctly compute union

See merge request xorg/xserver!2154
This commit is contained in:
Jeremy Huddleston Sequoia 2026-03-24 21:00:11 -07:00
commit ff1347c18f
2 changed files with 176 additions and 3 deletions

View file

@ -108,6 +108,9 @@ typedef struct _RootlessScreenRec {
CompositeProcPtr Composite;
GlyphsProcPtr Glyphs;
TrapezoidsProcPtr Trapezoids;
TrianglesProcPtr Triangles;
CompositeRectsProcPtr CompositeRects;
InstallColormapProcPtr InstallColormap;
UninstallColormapProcPtr UninstallColormap;

View file

@ -41,6 +41,7 @@
#include "propertyst.h"
#include "mivalidate.h"
#include "picturestr.h"
#include "mipict.h"
#include "colormapst.h"
#include <sys/types.h>
@ -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?