exa_mixed.c revision 35c4bbdf
16747b715Smrg/*
235c4bbdfSmrg * Copyright © 2009 Maarten Maathuis
36747b715Smrg *
46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
56747b715Smrg * copy of this software and associated documentation files (the "Software"),
66747b715Smrg * to deal in the Software without restriction, including without limitation
76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
96747b715Smrg * Software is furnished to do so, subject to the following conditions:
106747b715Smrg *
116747b715Smrg * The above copyright notice and this permission notice (including the next
126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
136747b715Smrg * Software.
146747b715Smrg *
156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
206747b715Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
216747b715Smrg * SOFTWARE.
226747b715Smrg *
236747b715Smrg */
246747b715Smrg
256747b715Smrg#ifdef HAVE_DIX_CONFIG_H
266747b715Smrg#include <dix-config.h>
276747b715Smrg#endif
286747b715Smrg
296747b715Smrg#include <string.h>
306747b715Smrg
316747b715Smrg#include "exa_priv.h"
326747b715Smrg#include "exa.h"
336747b715Smrg
346747b715Smrg/* This file holds the driver allocated pixmaps + better initial placement code.
356747b715Smrg */
366747b715Smrg
3735c4bbdfSmrgstatic _X_INLINE void *
386747b715SmrgExaGetPixmapAddress(PixmapPtr p)
396747b715Smrg{
406747b715Smrg    ExaPixmapPriv(p);
416747b715Smrg
426747b715Smrg    return pExaPixmap->sys_ptr;
436747b715Smrg}
446747b715Smrg
456747b715Smrg/**
466747b715Smrg * exaCreatePixmap() creates a new pixmap.
476747b715Smrg */
486747b715SmrgPixmapPtr
496747b715SmrgexaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
5035c4bbdfSmrg                      unsigned usage_hint)
516747b715Smrg{
526747b715Smrg    PixmapPtr pPixmap;
5335c4bbdfSmrg    ExaPixmapPrivPtr pExaPixmap;
546747b715Smrg    int bpp;
556747b715Smrg    size_t paddedWidth;
5635c4bbdfSmrg
576747b715Smrg    ExaScreenPriv(pScreen);
586747b715Smrg
596747b715Smrg    if (w > 32767 || h > 32767)
6035c4bbdfSmrg        return NullPixmap;
616747b715Smrg
626747b715Smrg    swap(pExaScr, pScreen, CreatePixmap);
636747b715Smrg    pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
646747b715Smrg    swap(pExaScr, pScreen, CreatePixmap);
656747b715Smrg
666747b715Smrg    if (!pPixmap)
676747b715Smrg        return NULL;
686747b715Smrg
696747b715Smrg    pExaPixmap = ExaGetPixmapPriv(pPixmap);
706747b715Smrg    pExaPixmap->driverPriv = NULL;
716747b715Smrg
726747b715Smrg    bpp = pPixmap->drawable.bitsPerPixel;
736747b715Smrg
746747b715Smrg    paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
756747b715Smrg    if (paddedWidth / 4 > 32767 || h > 32767)
766747b715Smrg        return NullPixmap;
776747b715Smrg
786747b715Smrg    /* We will allocate the system pixmap later if needed. */
796747b715Smrg    pPixmap->devPrivate.ptr = NULL;
806747b715Smrg    pExaPixmap->sys_ptr = NULL;
816747b715Smrg    pExaPixmap->sys_pitch = paddedWidth;
826747b715Smrg
836747b715Smrg    pExaPixmap->area = NULL;
846747b715Smrg    pExaPixmap->fb_ptr = NULL;
856747b715Smrg    pExaPixmap->pDamage = NULL;
866747b715Smrg
876747b715Smrg    exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
8835c4bbdfSmrg    exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);
896747b715Smrg
9035c4bbdfSmrg    (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
916747b715Smrg
926747b715Smrg    /* A scratch pixmap will become a driver pixmap right away. */
936747b715Smrg    if (!w || !h) {
9435c4bbdfSmrg        exaCreateDriverPixmap_mixed(pPixmap);
9535c4bbdfSmrg        pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
9635c4bbdfSmrg    }
9735c4bbdfSmrg    else {
9835c4bbdfSmrg        pExaPixmap->use_gpu_copy = FALSE;
9935c4bbdfSmrg
10035c4bbdfSmrg        if (w == 1 && h == 1) {
10135c4bbdfSmrg            pExaPixmap->sys_ptr = malloc(paddedWidth);
10235c4bbdfSmrg
10335c4bbdfSmrg            /* Set up damage tracking */
10435c4bbdfSmrg            pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
10535c4bbdfSmrg                                               DamageReportNonEmpty, TRUE,
10635c4bbdfSmrg                                               pPixmap->drawable.pScreen,
10735c4bbdfSmrg                                               pPixmap);
10835c4bbdfSmrg
10935c4bbdfSmrg            if (pExaPixmap->pDamage) {
11035c4bbdfSmrg                DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
11135c4bbdfSmrg                /* This ensures that pending damage reflects the current
11235c4bbdfSmrg                 * operation. This is used by exa to optimize migration.
11335c4bbdfSmrg                 */
11435c4bbdfSmrg                DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
11535c4bbdfSmrg            }
11635c4bbdfSmrg        }
1176747b715Smrg    }
1186747b715Smrg
1196747b715Smrg    /* During a fallback we must prepare access. */
1206747b715Smrg    if (pExaScr->fallback_counter)
12135c4bbdfSmrg        exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
1226747b715Smrg
1236747b715Smrg    return pPixmap;
1246747b715Smrg}
1256747b715Smrg
1266747b715SmrgBool
1276747b715SmrgexaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
12835c4bbdfSmrg                            int bitsPerPixel, int devKind, void *pPixData)
1296747b715Smrg{
1306747b715Smrg    ScreenPtr pScreen;
1316747b715Smrg    ExaScreenPrivPtr pExaScr;
1326747b715Smrg    ExaPixmapPrivPtr pExaPixmap;
1336747b715Smrg    Bool ret, has_gpu_copy;
1346747b715Smrg
1356747b715Smrg    if (!pPixmap)
1366747b715Smrg        return FALSE;
1376747b715Smrg
1386747b715Smrg    pScreen = pPixmap->drawable.pScreen;
1396747b715Smrg    pExaScr = ExaGetScreenPriv(pScreen);
1406747b715Smrg    pExaPixmap = ExaGetPixmapPriv(pPixmap);
1416747b715Smrg
1426747b715Smrg    if (pPixData) {
14335c4bbdfSmrg        if (pExaPixmap->driverPriv) {
14435c4bbdfSmrg            if (pExaPixmap->pDamage) {
14535c4bbdfSmrg                DamageDestroy(pExaPixmap->pDamage);
14635c4bbdfSmrg                pExaPixmap->pDamage = NULL;
14735c4bbdfSmrg            }
14835c4bbdfSmrg
14935c4bbdfSmrg            pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
15035c4bbdfSmrg            pExaPixmap->driverPriv = NULL;
15135c4bbdfSmrg        }
15235c4bbdfSmrg
15335c4bbdfSmrg        pExaPixmap->use_gpu_copy = FALSE;
15435c4bbdfSmrg        pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
1556747b715Smrg    }
1566747b715Smrg
1576747b715Smrg    has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
1586747b715Smrg
1596747b715Smrg    if (width <= 0)
16035c4bbdfSmrg        width = pPixmap->drawable.width;
1616747b715Smrg
1626747b715Smrg    if (height <= 0)
16335c4bbdfSmrg        height = pPixmap->drawable.height;
1646747b715Smrg
1656747b715Smrg    if (bitsPerPixel <= 0) {
16635c4bbdfSmrg        if (depth <= 0)
16735c4bbdfSmrg            bitsPerPixel = pPixmap->drawable.bitsPerPixel;
16835c4bbdfSmrg        else
16935c4bbdfSmrg            bitsPerPixel = BitsPerPixel(depth);
1706747b715Smrg    }
1716747b715Smrg
1726747b715Smrg    if (depth <= 0)
17335c4bbdfSmrg        depth = pPixmap->drawable.depth;
1746747b715Smrg
1756747b715Smrg    if (width != pPixmap->drawable.width ||
17635c4bbdfSmrg        height != pPixmap->drawable.height ||
17735c4bbdfSmrg        depth != pPixmap->drawable.depth ||
17835c4bbdfSmrg        bitsPerPixel != pPixmap->drawable.bitsPerPixel) {
17935c4bbdfSmrg        if (pExaPixmap->driverPriv) {
18035c4bbdfSmrg            if (devKind > 0)
18135c4bbdfSmrg                pExaPixmap->fb_pitch = devKind;
18235c4bbdfSmrg            else
18335c4bbdfSmrg                exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
18435c4bbdfSmrg
18535c4bbdfSmrg            exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel);
1866747b715Smrg            RegionEmpty(&pExaPixmap->validFB);
1876747b715Smrg        }
1886747b715Smrg
18935c4bbdfSmrg        /* Need to re-create system copy if there's also a GPU copy */
19035c4bbdfSmrg        if (has_gpu_copy) {
19135c4bbdfSmrg            if (pExaPixmap->sys_ptr) {
19235c4bbdfSmrg                free(pExaPixmap->sys_ptr);
19335c4bbdfSmrg                pExaPixmap->sys_ptr = NULL;
19435c4bbdfSmrg                DamageDestroy(pExaPixmap->pDamage);
19535c4bbdfSmrg                pExaPixmap->pDamage = NULL;
19635c4bbdfSmrg                RegionEmpty(&pExaPixmap->validSys);
19735c4bbdfSmrg
19835c4bbdfSmrg                if (pExaScr->deferred_mixed_pixmap == pPixmap)
19935c4bbdfSmrg                    pExaScr->deferred_mixed_pixmap = NULL;
20035c4bbdfSmrg            }
20135c4bbdfSmrg
20235c4bbdfSmrg            pExaPixmap->sys_pitch = PixmapBytePad(width, depth);
20335c4bbdfSmrg        }
2046747b715Smrg    }
2056747b715Smrg
2066747b715Smrg    if (has_gpu_copy) {
20735c4bbdfSmrg        pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
20835c4bbdfSmrg        pPixmap->devKind = pExaPixmap->fb_pitch;
20935c4bbdfSmrg    }
21035c4bbdfSmrg    else {
21135c4bbdfSmrg        pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
21235c4bbdfSmrg        pPixmap->devKind = pExaPixmap->sys_pitch;
2136747b715Smrg    }
2146747b715Smrg
2156747b715Smrg    /* Only pass driver pixmaps to the driver. */
2166747b715Smrg    if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
21735c4bbdfSmrg        ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
21835c4bbdfSmrg                                                bitsPerPixel, devKind,
21935c4bbdfSmrg                                                pPixData);
22035c4bbdfSmrg        if (ret == TRUE)
22135c4bbdfSmrg            goto out;
2226747b715Smrg    }
2236747b715Smrg
2246747b715Smrg    swap(pExaScr, pScreen, ModifyPixmapHeader);
2256747b715Smrg    ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
22635c4bbdfSmrg                                      bitsPerPixel, devKind, pPixData);
2276747b715Smrg    swap(pExaScr, pScreen, ModifyPixmapHeader);
2286747b715Smrg
22935c4bbdfSmrg out:
2306747b715Smrg    if (has_gpu_copy) {
23135c4bbdfSmrg        pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
23235c4bbdfSmrg        pExaPixmap->fb_pitch = pPixmap->devKind;
23335c4bbdfSmrg    }
23435c4bbdfSmrg    else {
23535c4bbdfSmrg        pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
23635c4bbdfSmrg        pExaPixmap->sys_pitch = pPixmap->devKind;
2376747b715Smrg    }
2386747b715Smrg    /* Always NULL this, we don't want lingering pointers. */
2396747b715Smrg    pPixmap->devPrivate.ptr = NULL;
2406747b715Smrg
2416747b715Smrg    return ret;
2426747b715Smrg}
2436747b715Smrg
2446747b715SmrgBool
2456747b715SmrgexaDestroyPixmap_mixed(PixmapPtr pPixmap)
2466747b715Smrg{
24735c4bbdfSmrg    ScreenPtr pScreen = pPixmap->drawable.pScreen;
24835c4bbdfSmrg
2496747b715Smrg    ExaScreenPriv(pScreen);
2506747b715Smrg    Bool ret;
2516747b715Smrg
25235c4bbdfSmrg    if (pPixmap->refcnt == 1) {
25335c4bbdfSmrg        ExaPixmapPriv(pPixmap);
2546747b715Smrg
25535c4bbdfSmrg        exaDestroyPixmap(pPixmap);
2566747b715Smrg
25735c4bbdfSmrg        if (pExaScr->deferred_mixed_pixmap == pPixmap)
25835c4bbdfSmrg            pExaScr->deferred_mixed_pixmap = NULL;
2596747b715Smrg
26035c4bbdfSmrg        if (pExaPixmap->driverPriv)
26135c4bbdfSmrg            pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
26235c4bbdfSmrg        pExaPixmap->driverPriv = NULL;
2636747b715Smrg
26435c4bbdfSmrg        if (pExaPixmap->pDamage) {
26535c4bbdfSmrg            free(pExaPixmap->sys_ptr);
26635c4bbdfSmrg            pExaPixmap->sys_ptr = NULL;
26735c4bbdfSmrg            pExaPixmap->pDamage = NULL;
26835c4bbdfSmrg        }
2696747b715Smrg    }
2706747b715Smrg
2716747b715Smrg    swap(pExaScr, pScreen, DestroyPixmap);
27235c4bbdfSmrg    ret = pScreen->DestroyPixmap(pPixmap);
2736747b715Smrg    swap(pExaScr, pScreen, DestroyPixmap);
2746747b715Smrg
2756747b715Smrg    return ret;
2766747b715Smrg}
2776747b715Smrg
2786747b715SmrgBool
2796747b715SmrgexaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap)
2806747b715Smrg{
2816747b715Smrg    ScreenPtr pScreen = pPixmap->drawable.pScreen;
28235c4bbdfSmrg
2836747b715Smrg    ExaScreenPriv(pScreen);
2846747b715Smrg    ExaPixmapPriv(pPixmap);
28535c4bbdfSmrg    void *saved_ptr;
2866747b715Smrg    Bool ret;
2876747b715Smrg
2886747b715Smrg    if (!pExaPixmap->driverPriv)
28935c4bbdfSmrg        return FALSE;
2906747b715Smrg
2916747b715Smrg    saved_ptr = pPixmap->devPrivate.ptr;
2926747b715Smrg    pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
2936747b715Smrg    ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
2946747b715Smrg    pPixmap->devPrivate.ptr = saved_ptr;
2956747b715Smrg
2966747b715Smrg    return ret;
2976747b715Smrg}
29835c4bbdfSmrg
29935c4bbdfSmrgBool
30035c4bbdfSmrgexaSharePixmapBacking_mixed(PixmapPtr pPixmap, ScreenPtr slave, void **handle_p)
30135c4bbdfSmrg{
30235c4bbdfSmrg    ScreenPtr pScreen = pPixmap->drawable.pScreen;
30335c4bbdfSmrg    ExaScreenPriv(pScreen);
30435c4bbdfSmrg    Bool ret = FALSE;
30535c4bbdfSmrg
30635c4bbdfSmrg    exaMoveInPixmap(pPixmap);
30735c4bbdfSmrg    /* get the driver to give us a handle */
30835c4bbdfSmrg    if (pExaScr->info->SharePixmapBacking)
30935c4bbdfSmrg        ret = pExaScr->info->SharePixmapBacking(pPixmap, slave, handle_p);
31035c4bbdfSmrg
31135c4bbdfSmrg    return ret;
31235c4bbdfSmrg}
31335c4bbdfSmrg
31435c4bbdfSmrgBool
31535c4bbdfSmrgexaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap, void *handle)
31635c4bbdfSmrg{
31735c4bbdfSmrg    ScreenPtr pScreen = pPixmap->drawable.pScreen;
31835c4bbdfSmrg    ExaScreenPriv(pScreen);
31935c4bbdfSmrg    Bool ret = FALSE;
32035c4bbdfSmrg
32135c4bbdfSmrg    if (pExaScr->info->SetSharedPixmapBacking)
32235c4bbdfSmrg        ret = pExaScr->info->SetSharedPixmapBacking(pPixmap, handle);
32335c4bbdfSmrg
32435c4bbdfSmrg    if (ret == TRUE)
32535c4bbdfSmrg        exaMoveInPixmap(pPixmap);
32635c4bbdfSmrg
32735c4bbdfSmrg    return ret;
32835c4bbdfSmrg}
32935c4bbdfSmrg
33035c4bbdfSmrg
331