105b261ecSmrg/*
205b261ecSmrg
305b261ecSmrgCopyright 1993, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included
1205b261ecSmrgin all copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1505b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1605b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1705b261ecSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
1805b261ecSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1905b261ecSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2005b261ecSmrgOTHER DEALINGS IN THE SOFTWARE.
2105b261ecSmrg
2205b261ecSmrgExcept as contained in this notice, the name of The Open Group shall
2305b261ecSmrgnot be used in advertising or otherwise to promote the sale, use or
2405b261ecSmrgother dealings in this Software without prior written authorization
2505b261ecSmrgfrom The Open Group.
2605b261ecSmrg
2705b261ecSmrg*/
2805b261ecSmrg
2905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3005b261ecSmrg#include <dix-config.h>
3105b261ecSmrg#endif
3205b261ecSmrg
3305b261ecSmrg#include <X11/X.h>
3405b261ecSmrg#include "scrnintstr.h"
3525da500fSmrg#include "mi.h"
3605b261ecSmrg#include "misc.h"
3705b261ecSmrg#include "os.h"
3805b261ecSmrg#include "windowstr.h"
3905b261ecSmrg#include "resource.h"
4005b261ecSmrg#include "dixstruct.h"
4105b261ecSmrg#include "gcstruct.h"
4205b261ecSmrg#include "servermd.h"
4335c4bbdfSmrg#include "X11/extensions/render.h"
4435c4bbdfSmrg#include "picturestr.h"
4535c4bbdfSmrg#include "randrstr.h"
4605b261ecSmrg/*
4705b261ecSmrg *  Scratch pixmap management and device independent pixmap allocation
4805b261ecSmrg *  function.
4905b261ecSmrg */
5005b261ecSmrg
5105b261ecSmrg/* callable by ddx */
526747b715SmrgPixmapPtr
5335c4bbdfSmrgGetScratchPixmapHeader(ScreenPtr pScreen, int width, int height, int depth,
5435c4bbdfSmrg                       int bitsPerPixel, int devKind, void *pPixData)
5505b261ecSmrg{
5605b261ecSmrg    PixmapPtr pPixmap = pScreen->pScratchPixmap;
5705b261ecSmrg
5805b261ecSmrg    if (pPixmap)
5935c4bbdfSmrg        pScreen->pScratchPixmap = NULL;
6005b261ecSmrg    else
6135c4bbdfSmrg        /* width and height of 0 means don't allocate any pixmap data */
6235c4bbdfSmrg        pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, 0);
6305b261ecSmrg
6405b261ecSmrg    if (pPixmap) {
6535c4bbdfSmrg        if ((*pScreen->ModifyPixmapHeader) (pPixmap, width, height, depth,
6635c4bbdfSmrg                                            bitsPerPixel, devKind, pPixData))
6735c4bbdfSmrg            return pPixmap;
6835c4bbdfSmrg        (*pScreen->DestroyPixmap) (pPixmap);
6905b261ecSmrg    }
7005b261ecSmrg    return NullPixmap;
7105b261ecSmrg}
7205b261ecSmrg
7305b261ecSmrg/* callable by ddx */
746747b715Smrgvoid
7505b261ecSmrgFreeScratchPixmapHeader(PixmapPtr pPixmap)
7605b261ecSmrg{
7735c4bbdfSmrg    if (pPixmap) {
7835c4bbdfSmrg        ScreenPtr pScreen = pPixmap->drawable.pScreen;
7935c4bbdfSmrg
8035c4bbdfSmrg        pPixmap->devPrivate.ptr = NULL; /* lest ddx chases bad ptr */
8135c4bbdfSmrg        if (pScreen->pScratchPixmap)
8235c4bbdfSmrg            (*pScreen->DestroyPixmap) (pPixmap);
8335c4bbdfSmrg        else
8435c4bbdfSmrg            pScreen->pScratchPixmap = pPixmap;
8505b261ecSmrg    }
8605b261ecSmrg}
8705b261ecSmrg
8805b261ecSmrgBool
8935c4bbdfSmrgCreateScratchPixmapsForScreen(ScreenPtr pScreen)
9005b261ecSmrg{
9135c4bbdfSmrg    unsigned int pixmap_size;
926747b715Smrg
9335c4bbdfSmrg    pixmap_size = sizeof(PixmapRec) + dixScreenSpecificPrivatesSize(pScreen, PRIVATE_PIXMAP);
9435c4bbdfSmrg    pScreen->totalPixmapSize =
9535c4bbdfSmrg        BitmapBytePad(pixmap_size * 8);
966747b715Smrg
9705b261ecSmrg    /* let it be created on first use */
9835c4bbdfSmrg    pScreen->pScratchPixmap = NULL;
9905b261ecSmrg    return TRUE;
10005b261ecSmrg}
10105b261ecSmrg
10205b261ecSmrgvoid
10335c4bbdfSmrgFreeScratchPixmapsForScreen(ScreenPtr pScreen)
10405b261ecSmrg{
10535c4bbdfSmrg    FreeScratchPixmapHeader(pScreen->pScratchPixmap);
10605b261ecSmrg}
10705b261ecSmrg
10805b261ecSmrg/* callable by ddx */
1096747b715SmrgPixmapPtr
11005b261ecSmrgAllocatePixmap(ScreenPtr pScreen, int pixDataSize)
11105b261ecSmrg{
11205b261ecSmrg    PixmapPtr pPixmap;
11305b261ecSmrg
1146747b715Smrg    assert(pScreen->totalPixmapSize > 0);
1156747b715Smrg
11635c4bbdfSmrg    if (pScreen->totalPixmapSize > ((size_t) - 1) - pixDataSize)
11735c4bbdfSmrg        return NullPixmap;
11835c4bbdfSmrg
11932414907Smaya    pPixmap = calloc(1, pScreen->totalPixmapSize + pixDataSize);
12005b261ecSmrg    if (!pPixmap)
12135c4bbdfSmrg        return NullPixmap;
12205b261ecSmrg
12335c4bbdfSmrg    dixInitScreenPrivates(pScreen, pPixmap, pPixmap + 1, PRIVATE_PIXMAP);
12405b261ecSmrg    return pPixmap;
12505b261ecSmrg}
1266747b715Smrg
1276747b715Smrg/* callable by ddx */
1286747b715Smrgvoid
1296747b715SmrgFreePixmap(PixmapPtr pPixmap)
1306747b715Smrg{
1316747b715Smrg    dixFiniPrivates(pPixmap, PRIVATE_PIXMAP);
1326747b715Smrg    free(pPixmap);
1336747b715Smrg}
13435c4bbdfSmrg
1355a112b11Smrgvoid PixmapUnshareSecondaryPixmap(PixmapPtr secondary_pixmap)
1361b5d61b8Smrg{
1371b5d61b8Smrg     int ihandle = -1;
1385a112b11Smrg     ScreenPtr pScreen = secondary_pixmap->drawable.pScreen;
1395a112b11Smrg     pScreen->SetSharedPixmapBacking(secondary_pixmap, ((void *)(long)ihandle));
1401b5d61b8Smrg}
1411b5d61b8Smrg
1425a112b11SmrgPixmapPtr PixmapShareToSecondary(PixmapPtr pixmap, ScreenPtr secondary)
14335c4bbdfSmrg{
14435c4bbdfSmrg    PixmapPtr spix;
14535c4bbdfSmrg    int ret;
14635c4bbdfSmrg    void *handle;
1475a112b11Smrg    ScreenPtr primary = pixmap->drawable.pScreen;
14835c4bbdfSmrg    int depth = pixmap->drawable.depth;
14935c4bbdfSmrg
1505a112b11Smrg    ret = primary->SharePixmapBacking(pixmap, secondary, &handle);
15135c4bbdfSmrg    if (ret == FALSE)
15235c4bbdfSmrg        return NULL;
15335c4bbdfSmrg
1545a112b11Smrg    spix = secondary->CreatePixmap(secondary, 0, 0, depth,
15535c4bbdfSmrg                               CREATE_PIXMAP_USAGE_SHARED);
1565a112b11Smrg    secondary->ModifyPixmapHeader(spix, pixmap->drawable.width,
1575a112b11Smrg                                  pixmap->drawable.height, depth, 0,
1585a112b11Smrg                                  pixmap->devKind, NULL);
15935c4bbdfSmrg
1605a112b11Smrg    /* have the secondary pixmap take a reference on the primary pixmap
16135c4bbdfSmrg       later we destroy them both at the same time */
16235c4bbdfSmrg    pixmap->refcnt++;
16335c4bbdfSmrg
1645a112b11Smrg    spix->primary_pixmap = pixmap;
16535c4bbdfSmrg
1665a112b11Smrg    ret = secondary->SetSharedPixmapBacking(spix, handle);
16735c4bbdfSmrg    if (ret == FALSE) {
1685a112b11Smrg        secondary->DestroyPixmap(spix);
16935c4bbdfSmrg        return NULL;
17035c4bbdfSmrg    }
17135c4bbdfSmrg
17235c4bbdfSmrg    return spix;
17335c4bbdfSmrg}
17435c4bbdfSmrg
1751b5d61b8Smrgstatic void
1761b5d61b8SmrgPixmapDirtyDamageDestroy(DamagePtr damage, void *closure)
1771b5d61b8Smrg{
1781b5d61b8Smrg    PixmapDirtyUpdatePtr dirty = closure;
1791b5d61b8Smrg
1801b5d61b8Smrg    dirty->damage = NULL;
1811b5d61b8Smrg}
1821b5d61b8Smrg
18335c4bbdfSmrgBool
1841b5d61b8SmrgPixmapStartDirtyTracking(DrawablePtr src,
1855a112b11Smrg                         PixmapPtr secondary_dst,
18635c4bbdfSmrg                         int x, int y, int dst_x, int dst_y,
18735c4bbdfSmrg                         Rotation rotation)
18835c4bbdfSmrg{
1891b5d61b8Smrg    ScreenPtr screen = src->pScreen;
19035c4bbdfSmrg    PixmapDirtyUpdatePtr dirty_update;
19135c4bbdfSmrg    RegionPtr damageregion;
19235c4bbdfSmrg    RegionRec dstregion;
19335c4bbdfSmrg    BoxRec box;
19435c4bbdfSmrg
19535c4bbdfSmrg    dirty_update = calloc(1, sizeof(PixmapDirtyUpdateRec));
19635c4bbdfSmrg    if (!dirty_update)
19735c4bbdfSmrg        return FALSE;
19835c4bbdfSmrg
19935c4bbdfSmrg    dirty_update->src = src;
2005a112b11Smrg    dirty_update->secondary_dst = secondary_dst;
20135c4bbdfSmrg    dirty_update->x = x;
20235c4bbdfSmrg    dirty_update->y = y;
20335c4bbdfSmrg    dirty_update->dst_x = dst_x;
20435c4bbdfSmrg    dirty_update->dst_y = dst_y;
20535c4bbdfSmrg    dirty_update->rotation = rotation;
2061b5d61b8Smrg    dirty_update->damage = DamageCreate(NULL, PixmapDirtyDamageDestroy,
2071b5d61b8Smrg                                        DamageReportNone, TRUE, screen,
2081b5d61b8Smrg                                        dirty_update);
20935c4bbdfSmrg
21035c4bbdfSmrg    if (rotation != RR_Rotate_0) {
21135c4bbdfSmrg        RRTransformCompute(x, y,
2125a112b11Smrg                           secondary_dst->drawable.width,
2135a112b11Smrg                           secondary_dst->drawable.height,
21435c4bbdfSmrg                           rotation,
21535c4bbdfSmrg                           NULL,
21635c4bbdfSmrg                           &dirty_update->transform,
21735c4bbdfSmrg                           &dirty_update->f_transform,
21835c4bbdfSmrg                           &dirty_update->f_inverse);
21935c4bbdfSmrg    }
22035c4bbdfSmrg    if (!dirty_update->damage) {
22135c4bbdfSmrg        free(dirty_update);
22235c4bbdfSmrg        return FALSE;
22335c4bbdfSmrg    }
22435c4bbdfSmrg
22535c4bbdfSmrg    /* Damage destination rectangle so that the destination pixmap contents
22635c4bbdfSmrg     * will get fully initialized
22735c4bbdfSmrg     */
22835c4bbdfSmrg    box.x1 = dirty_update->x;
22935c4bbdfSmrg    box.y1 = dirty_update->y;
23035c4bbdfSmrg    if (dirty_update->rotation == RR_Rotate_90 ||
23135c4bbdfSmrg        dirty_update->rotation == RR_Rotate_270) {
2325a112b11Smrg        box.x2 = dirty_update->x + secondary_dst->drawable.height;
2335a112b11Smrg        box.y2 = dirty_update->y + secondary_dst->drawable.width;
23435c4bbdfSmrg    } else {
2355a112b11Smrg        box.x2 = dirty_update->x + secondary_dst->drawable.width;
2365a112b11Smrg        box.y2 = dirty_update->y + secondary_dst->drawable.height;
23735c4bbdfSmrg    }
23835c4bbdfSmrg    RegionInit(&dstregion, &box, 1);
23935c4bbdfSmrg    damageregion = DamageRegion(dirty_update->damage);
24035c4bbdfSmrg    RegionUnion(damageregion, damageregion, &dstregion);
24135c4bbdfSmrg    RegionUninit(&dstregion);
24235c4bbdfSmrg
2431b5d61b8Smrg    DamageRegister(src, dirty_update->damage);
24435c4bbdfSmrg    xorg_list_add(&dirty_update->ent, &screen->pixmap_dirty_list);
24535c4bbdfSmrg    return TRUE;
24635c4bbdfSmrg}
24735c4bbdfSmrg
24835c4bbdfSmrgBool
2495a112b11SmrgPixmapStopDirtyTracking(DrawablePtr src, PixmapPtr secondary_dst)
25035c4bbdfSmrg{
2511b5d61b8Smrg    ScreenPtr screen = src->pScreen;
25235c4bbdfSmrg    PixmapDirtyUpdatePtr ent, safe;
25335c4bbdfSmrg
25435c4bbdfSmrg    xorg_list_for_each_entry_safe(ent, safe, &screen->pixmap_dirty_list, ent) {
2555a112b11Smrg        if (ent->src == src && ent->secondary_dst == secondary_dst) {
2561b5d61b8Smrg            if (ent->damage)
2571b5d61b8Smrg                DamageDestroy(ent->damage);
25835c4bbdfSmrg            xorg_list_del(&ent->ent);
25935c4bbdfSmrg            free(ent);
26035c4bbdfSmrg        }
26135c4bbdfSmrg    }
26235c4bbdfSmrg    return TRUE;
26335c4bbdfSmrg}
26435c4bbdfSmrg
26535c4bbdfSmrgstatic void
26635c4bbdfSmrgPixmapDirtyCopyArea(PixmapPtr dst,
26735c4bbdfSmrg                    PixmapDirtyUpdatePtr dirty,
26835c4bbdfSmrg                    RegionPtr dirty_region)
26935c4bbdfSmrg{
2701b5d61b8Smrg    DrawablePtr src = dirty->src;
2711b5d61b8Smrg    ScreenPtr pScreen = src->pScreen;
27235c4bbdfSmrg    int n;
27335c4bbdfSmrg    BoxPtr b;
27435c4bbdfSmrg    GCPtr pGC;
27535c4bbdfSmrg
27635c4bbdfSmrg    n = RegionNumRects(dirty_region);
27735c4bbdfSmrg    b = RegionRects(dirty_region);
27835c4bbdfSmrg
2791b5d61b8Smrg    pGC = GetScratchGC(src->depth, pScreen);
2801b5d61b8Smrg    if (pScreen->root) {
2811b5d61b8Smrg        ChangeGCVal subWindowMode;
2821b5d61b8Smrg
2831b5d61b8Smrg        subWindowMode.val = IncludeInferiors;
2841b5d61b8Smrg        ChangeGC(NullClient, pGC, GCSubwindowMode, &subWindowMode);
2851b5d61b8Smrg    }
28635c4bbdfSmrg    ValidateGC(&dst->drawable, pGC);
28735c4bbdfSmrg
28835c4bbdfSmrg    while (n--) {
28935c4bbdfSmrg        BoxRec dst_box;
29035c4bbdfSmrg        int w, h;
29135c4bbdfSmrg
29235c4bbdfSmrg        dst_box = *b;
29335c4bbdfSmrg        w = dst_box.x2 - dst_box.x1;
29435c4bbdfSmrg        h = dst_box.y2 - dst_box.y1;
29535c4bbdfSmrg
2961b5d61b8Smrg        pGC->ops->CopyArea(src, &dst->drawable, pGC,
29735c4bbdfSmrg                           dirty->x + dst_box.x1, dirty->y + dst_box.y1, w, h,
29835c4bbdfSmrg                           dirty->dst_x + dst_box.x1,
29935c4bbdfSmrg                           dirty->dst_y + dst_box.y1);
30035c4bbdfSmrg        b++;
30135c4bbdfSmrg    }
30235c4bbdfSmrg    FreeScratchGC(pGC);
30335c4bbdfSmrg}
30435c4bbdfSmrg
30535c4bbdfSmrgstatic void
30635c4bbdfSmrgPixmapDirtyCompositeRotate(PixmapPtr dst_pixmap,
30735c4bbdfSmrg                           PixmapDirtyUpdatePtr dirty,
30835c4bbdfSmrg                           RegionPtr dirty_region)
30935c4bbdfSmrg{
3101b5d61b8Smrg    ScreenPtr pScreen = dirty->src->pScreen;
31135c4bbdfSmrg    PictFormatPtr format = PictureWindowFormat(pScreen->root);
31235c4bbdfSmrg    PicturePtr src, dst;
31335c4bbdfSmrg    XID include_inferiors = IncludeInferiors;
31435c4bbdfSmrg    int n = RegionNumRects(dirty_region);
31535c4bbdfSmrg    BoxPtr b = RegionRects(dirty_region);
31635c4bbdfSmrg    int error;
31735c4bbdfSmrg
31835c4bbdfSmrg    src = CreatePicture(None,
3191b5d61b8Smrg                        dirty->src,
32035c4bbdfSmrg                        format,
32135c4bbdfSmrg                        CPSubwindowMode,
32235c4bbdfSmrg                        &include_inferiors, serverClient, &error);
32335c4bbdfSmrg    if (!src)
32435c4bbdfSmrg        return;
32535c4bbdfSmrg
32635c4bbdfSmrg    dst = CreatePicture(None,
32735c4bbdfSmrg                        &dst_pixmap->drawable,
32835c4bbdfSmrg                        format, 0L, NULL, serverClient, &error);
32935c4bbdfSmrg    if (!dst)
33035c4bbdfSmrg        return;
33135c4bbdfSmrg
33235c4bbdfSmrg    error = SetPictureTransform(src, &dirty->transform);
33335c4bbdfSmrg    if (error)
33435c4bbdfSmrg        return;
33535c4bbdfSmrg    while (n--) {
33635c4bbdfSmrg        BoxRec dst_box;
33735c4bbdfSmrg
33835c4bbdfSmrg        dst_box = *b;
33935c4bbdfSmrg        dst_box.x1 += dirty->x;
34035c4bbdfSmrg        dst_box.x2 += dirty->x;
34135c4bbdfSmrg        dst_box.y1 += dirty->y;
34235c4bbdfSmrg        dst_box.y2 += dirty->y;
34335c4bbdfSmrg        pixman_f_transform_bounds(&dirty->f_inverse, &dst_box);
34435c4bbdfSmrg
34535c4bbdfSmrg        CompositePicture(PictOpSrc,
34635c4bbdfSmrg                         src, NULL, dst,
34735c4bbdfSmrg                         dst_box.x1,
34835c4bbdfSmrg                         dst_box.y1,
34935c4bbdfSmrg                         0, 0,
35035c4bbdfSmrg                         dst_box.x1,
35135c4bbdfSmrg                         dst_box.y1,
35235c4bbdfSmrg                         dst_box.x2 - dst_box.x1,
35335c4bbdfSmrg                         dst_box.y2 - dst_box.y1);
35435c4bbdfSmrg        b++;
35535c4bbdfSmrg    }
35635c4bbdfSmrg
35735c4bbdfSmrg    FreePicture(src, None);
35835c4bbdfSmrg    FreePicture(dst, None);
35935c4bbdfSmrg}
36035c4bbdfSmrg
36135c4bbdfSmrg/*
36235c4bbdfSmrg * this function can possibly be improved and optimised, by clipping
36335c4bbdfSmrg * instead of iterating
36435c4bbdfSmrg * Drivers are free to implement their own version of this.
36535c4bbdfSmrg */
36635c4bbdfSmrgBool PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty)
36735c4bbdfSmrg{
3681b5d61b8Smrg    ScreenPtr pScreen = dirty->src->pScreen;
36935c4bbdfSmrg    RegionPtr region = DamageRegion(dirty->damage);
37035c4bbdfSmrg    PixmapPtr dst;
37135c4bbdfSmrg    SourceValidateProcPtr SourceValidate;
37235c4bbdfSmrg    RegionRec pixregion;
37335c4bbdfSmrg    BoxRec box;
37435c4bbdfSmrg
3755a112b11Smrg    dst = dirty->secondary_dst->primary_pixmap;
37635c4bbdfSmrg    if (!dst)
3775a112b11Smrg        dst = dirty->secondary_dst;
37835c4bbdfSmrg
37935c4bbdfSmrg    box.x1 = 0;
38035c4bbdfSmrg    box.y1 = 0;
38135c4bbdfSmrg    if (dirty->rotation == RR_Rotate_90 ||
38235c4bbdfSmrg        dirty->rotation == RR_Rotate_270) {
38335c4bbdfSmrg        box.x2 = dst->drawable.height;
38435c4bbdfSmrg        box.y2 = dst->drawable.width;
38535c4bbdfSmrg    } else {
38635c4bbdfSmrg        box.x2 = dst->drawable.width;
38735c4bbdfSmrg        box.y2 = dst->drawable.height;
38835c4bbdfSmrg    }
38935c4bbdfSmrg    RegionInit(&pixregion, &box, 1);
39035c4bbdfSmrg
39135c4bbdfSmrg    /*
39235c4bbdfSmrg     * SourceValidate is used by the software cursor code
39335c4bbdfSmrg     * to pull the cursor off of the screen when reading
39435c4bbdfSmrg     * bits from the frame buffer. Bypassing this function
39535c4bbdfSmrg     * leaves the software cursor in place
39635c4bbdfSmrg     */
39735c4bbdfSmrg    SourceValidate = pScreen->SourceValidate;
39825da500fSmrg    pScreen->SourceValidate = miSourceValidate;
39935c4bbdfSmrg
40035c4bbdfSmrg    RegionTranslate(&pixregion, dirty->x, dirty->y);
40135c4bbdfSmrg    RegionIntersect(&pixregion, &pixregion, region);
40235c4bbdfSmrg
40335c4bbdfSmrg    if (RegionNil(&pixregion)) {
40435c4bbdfSmrg        RegionUninit(&pixregion);
40535c4bbdfSmrg        return FALSE;
40635c4bbdfSmrg    }
40735c4bbdfSmrg
40835c4bbdfSmrg    RegionTranslate(&pixregion, -dirty->x, -dirty->y);
40935c4bbdfSmrg
41035c4bbdfSmrg    if (!pScreen->root || dirty->rotation == RR_Rotate_0)
41135c4bbdfSmrg        PixmapDirtyCopyArea(dst, dirty, &pixregion);
41235c4bbdfSmrg    else
41335c4bbdfSmrg        PixmapDirtyCompositeRotate(dst, dirty, &pixregion);
41435c4bbdfSmrg    pScreen->SourceValidate = SourceValidate;
41535c4bbdfSmrg    return TRUE;
41635c4bbdfSmrg}
417