From 2922e749706297dba661e569b55c5252da5daecc Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 23 Jan 2018 11:55:18 +0100 Subject: [PATCH] Hook remaining XRender operations We had overlooked a few so we didn't track all screen changes properly. --- unix/xserver/hw/vnc/vncHooks.c | 304 +++++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) diff --git a/unix/xserver/hw/vnc/vncHooks.c b/unix/xserver/hw/vnc/vncHooks.c index 5b90f531..38dac928 100644 --- a/unix/xserver/hw/vnc/vncHooks.c +++ b/unix/xserver/hw/vnc/vncHooks.c @@ -71,6 +71,11 @@ typedef struct _vncHooksScreenRec { #ifdef RENDER CompositeProcPtr Composite; GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; + TrapezoidsProcPtr Trapezoids; + TrianglesProcPtr Triangles; + TriStripProcPtr TriStrip; + TriFanProcPtr TriFan; #endif #ifdef RANDR RRSetConfigProcPtr rrSetConfig; @@ -150,6 +155,20 @@ static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, static void vncHooksGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists, GlyphListPtr lists, GlyphPtr * glyphs); +static void vncHooksCompositeRects(CARD8 op, PicturePtr pDst, + xRenderColor * color, int nRect, xRectangle *rects); +static void vncHooksTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid * traps); +static void vncHooksTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntri, xTriangle * tris); +static void vncHooksTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int npoint, xPointFixed * points); +static void vncHooksTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int npoint, xPointFixed * points); #endif #ifdef RANDR static Bool vncHooksRandRSetConfig(ScreenPtr pScreen, Rotation rotation, @@ -307,6 +326,11 @@ int vncHooksInit(int scrIdx) if (ps) { wrap(vncHooksScreen, ps, Composite, vncHooksComposite); wrap(vncHooksScreen, ps, Glyphs, vncHooksGlyphs); + wrap(vncHooksScreen, ps, CompositeRects, vncHooksCompositeRects); + wrap(vncHooksScreen, ps, Trapezoids, vncHooksTrapezoids); + wrap(vncHooksScreen, ps, Triangles, vncHooksTriangles); + wrap(vncHooksScreen, ps, TriStrip, vncHooksTriStrip); + wrap(vncHooksScreen, ps, TriFan, vncHooksTriFan); } #endif #ifdef RANDR @@ -462,6 +486,11 @@ static Bool vncHooksCloseScreen(ScreenPtr pScreen_) if (ps) { unwrap(vncHooksScreen, ps, Composite); unwrap(vncHooksScreen, ps, Glyphs); + unwrap(vncHooksScreen, ps, CompositeRects); + unwrap(vncHooksScreen, ps, Trapezoids); + unwrap(vncHooksScreen, ps, Triangles); + unwrap(vncHooksScreen, ps, TriStrip); + unwrap(vncHooksScreen, ps, TriFan); } #endif #ifdef RANDR @@ -881,6 +910,281 @@ static void vncHooksGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, RENDER_EPILOGUE(Glyphs); } +static void vncHooksCompositeRects(CARD8 op, PicturePtr pDst, + xRenderColor * color, int nRect, xRectangle *rects) +{ + RegionPtr changed; + + RENDER_PROLOGUE(pDst->pDrawable->pScreen, CompositeRects); + + if (is_visible(pDst->pDrawable)) { + changed = RECTS_TO_REGION(pScreen, nRect, rects, CT_NONE); + } else { + changed = REGION_CREATE(pScreen, NullBox, 0); + } + + (*ps->CompositeRects)(op, pDst, color, nRect, rects); + + if (REGION_NOTEMPTY(pScreen, changed)) + add_changed(pScreen, changed); + + REGION_DESTROY(pScreen, changed); + + RENDER_EPILOGUE(CompositeRects); +} + +static inline short FixedToShort(xFixed fixed) +{ + return (fixed + 0x8000) >> 16; +} + +static void vncHooksTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid * traps) +{ + RegionRec changed; + + RENDER_PROLOGUE(pDst->pDrawable->pScreen, Trapezoids); + + if (is_visible(pDst->pDrawable)) { + BoxRec box; + RegionRec fbreg; + + // FIXME: We do a very crude bounding box around everything. + // Might not be worth optimizing since this call is rarely + // used. + box.x1 = SHRT_MAX; + box.y1 = SHRT_MAX; + box.x2 = 0; + box.y2 = 0; + for (int i = 0;i < ntrap;i++) { + if (FixedToShort(traps[i].left.p1.x) < box.x1) + box.x1 = FixedToShort(traps[i].left.p1.x); + if (FixedToShort(traps[i].left.p2.x) < box.x1) + box.x1 = FixedToShort(traps[i].left.p2.x); + if (FixedToShort(traps[i].top) < box.y1) + box.y1 = FixedToShort(traps[i].top); + if (FixedToShort(traps[i].right.p1.x) > box.x2) + box.x2 = FixedToShort(traps[i].right.p1.x); + if (FixedToShort(traps[i].right.p2.x) > box.x2) + box.x2 = FixedToShort(traps[i].right.p2.x); + if (FixedToShort(traps[i].bottom) > box.y2) + box.y2 = FixedToShort(traps[i].bottom); + } + + box.x1 += pDst->pDrawable->x; + box.y1 += pDst->pDrawable->y; + box.x2 += pDst->pDrawable->x; + box.y2 += pDst->pDrawable->y; + REGION_INIT(pScreen, &changed, &box, 0); + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &fbreg, &box, 0); + + REGION_INTERSECT(pScreen, &changed, &changed, &fbreg); + + REGION_UNINIT(pScreen, &fbreg); + } else { + REGION_NULL(pScreen, &changed); + } + + (*ps->Trapezoids)(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); + + if (REGION_NOTEMPTY(pScreen, &changed)) + add_changed(pScreen, &changed); + + REGION_UNINIT(pScreen, &changed); + + RENDER_EPILOGUE(Trapezoids); +} + +static void vncHooksTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntri, xTriangle * tris) +{ + RegionRec changed; + + RENDER_PROLOGUE(pDst->pDrawable->pScreen, Triangles); + + if (is_visible(pDst->pDrawable)) { + BoxRec box; + RegionRec fbreg; + + // FIXME: We do a very crude bounding box around everything. + // Might not be worth optimizing since this call is rarely + // used. + box.x1 = SHRT_MAX; + box.y1 = SHRT_MAX; + box.x2 = 0; + box.y2 = 0; + for (int i = 0;i < ntri;i++) { + xFixed left, right, top, bottom; + + left = min(min(tris[i].p1.x, tris[i].p2.x), tris[i].p3.x); + right = max(max(tris[i].p1.x, tris[i].p2.x), tris[i].p3.x); + top = min(min(tris[i].p1.y, tris[i].p2.y), tris[i].p3.y); + bottom = max(max(tris[i].p1.y, tris[i].p2.y), tris[i].p3.y); + + if (FixedToShort(left) < box.x1) + box.x1 = FixedToShort(left); + if (FixedToShort(top) < box.y1) + box.y1 = FixedToShort(top); + if (FixedToShort(right) > box.x2) + box.x2 = FixedToShort(right); + if (FixedToShort(bottom) > box.y2) + box.y2 = FixedToShort(bottom); + } + + box.x1 += pDst->pDrawable->x; + box.y1 += pDst->pDrawable->y; + box.x2 += pDst->pDrawable->x; + box.y2 += pDst->pDrawable->y; + REGION_INIT(pScreen, &changed, &box, 0); + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &fbreg, &box, 0); + + REGION_INTERSECT(pScreen, &changed, &changed, &fbreg); + + REGION_UNINIT(pScreen, &fbreg); + } else { + REGION_NULL(pScreen, &changed); + } + + (*ps->Triangles)(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); + + if (REGION_NOTEMPTY(pScreen, &changed)) + add_changed(pScreen, &changed); + + REGION_UNINIT(pScreen, &changed); + + RENDER_EPILOGUE(Triangles); +} + +static void vncHooksTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int npoint, xPointFixed * points) +{ + RegionRec changed; + + RENDER_PROLOGUE(pDst->pDrawable->pScreen, TriStrip); + + if (is_visible(pDst->pDrawable)) { + BoxRec box; + RegionRec fbreg; + + // FIXME: We do a very crude bounding box around everything. + // Might not be worth optimizing since this call is rarely + // used. + box.x1 = SHRT_MAX; + box.y1 = SHRT_MAX; + box.x2 = 0; + box.y2 = 0; + for (int i = 0;i < npoint;i++) { + if (FixedToShort(points[i].x) < box.x1) + box.x1 = FixedToShort(points[i].x); + if (FixedToShort(points[i].y) < box.y1) + box.y1 = FixedToShort(points[i].y); + if (FixedToShort(points[i].x) > box.x2) + box.x2 = FixedToShort(points[i].x); + if (FixedToShort(points[i].y) > box.y2) + box.y2 = FixedToShort(points[i].y); + } + + box.x1 += pDst->pDrawable->x; + box.y1 += pDst->pDrawable->y; + box.x2 += pDst->pDrawable->x; + box.y2 += pDst->pDrawable->y; + REGION_INIT(pScreen, &changed, &box, 0); + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &fbreg, &box, 0); + + REGION_INTERSECT(pScreen, &changed, &changed, &fbreg); + + REGION_UNINIT(pScreen, &fbreg); + } else { + REGION_NULL(pScreen, &changed); + } + + (*ps->TriStrip)(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, points); + + if (REGION_NOTEMPTY(pScreen, &changed)) + add_changed(pScreen, &changed); + + REGION_UNINIT(pScreen, &changed); + + RENDER_EPILOGUE(TriStrip); +} + +static void vncHooksTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int npoint, xPointFixed * points) +{ + RegionRec changed; + + RENDER_PROLOGUE(pDst->pDrawable->pScreen, TriFan); + + if (is_visible(pDst->pDrawable)) { + BoxRec box; + RegionRec fbreg; + + // FIXME: We do a very crude bounding box around everything. + // Might not be worth optimizing since this call is rarely + // used. + box.x1 = SHRT_MAX; + box.y1 = SHRT_MAX; + box.x2 = 0; + box.y2 = 0; + for (int i = 0;i < npoint;i++) { + if (FixedToShort(points[i].x) < box.x1) + box.x1 = FixedToShort(points[i].x); + if (FixedToShort(points[i].y) < box.y1) + box.y1 = FixedToShort(points[i].y); + if (FixedToShort(points[i].x) > box.x2) + box.x2 = FixedToShort(points[i].x); + if (FixedToShort(points[i].y) > box.y2) + box.y2 = FixedToShort(points[i].y); + } + + box.x1 += pDst->pDrawable->x; + box.y1 += pDst->pDrawable->y; + box.x2 += pDst->pDrawable->x; + box.y2 += pDst->pDrawable->y; + REGION_INIT(pScreen, &changed, &box, 0); + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &fbreg, &box, 0); + + REGION_INTERSECT(pScreen, &changed, &changed, &fbreg); + + REGION_UNINIT(pScreen, &fbreg); + } else { + REGION_NULL(pScreen, &changed); + } + + (*ps->TriFan)(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, points); + + if (REGION_NOTEMPTY(pScreen, &changed)) + add_changed(pScreen, &changed); + + REGION_UNINIT(pScreen, &changed); + + RENDER_EPILOGUE(TriFan); +} + #endif /* RENDER */ #ifdef RANDR -- 2.39.5