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 specific implementation. */
356747b715Smrg
3635c4bbdfSmrgstatic _X_INLINE void *
376747b715SmrgExaGetPixmapAddress(PixmapPtr p)
386747b715Smrg{
396747b715Smrg    ExaPixmapPriv(p);
406747b715Smrg
416747b715Smrg    return pExaPixmap->sys_ptr;
426747b715Smrg}
436747b715Smrg
446747b715Smrg/**
456747b715Smrg * exaCreatePixmap() creates a new pixmap.
466747b715Smrg *
476747b715Smrg * Pixmaps are always marked as pinned, because exa has no control over them.
486747b715Smrg */
496747b715SmrgPixmapPtr
506747b715SmrgexaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
5135c4bbdfSmrg                       unsigned usage_hint)
526747b715Smrg{
536747b715Smrg    PixmapPtr pPixmap;
5435c4bbdfSmrg    ExaPixmapPrivPtr pExaPixmap;
556747b715Smrg    int bpp;
566747b715Smrg    size_t paddedWidth, datasize;
5735c4bbdfSmrg
586747b715Smrg    ExaScreenPriv(pScreen);
596747b715Smrg
606747b715Smrg    if (w > 32767 || h > 32767)
6135c4bbdfSmrg        return NullPixmap;
626747b715Smrg
636747b715Smrg    swap(pExaScr, pScreen, CreatePixmap);
646747b715Smrg    pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
656747b715Smrg    swap(pExaScr, pScreen, CreatePixmap);
666747b715Smrg
676747b715Smrg    if (!pPixmap)
686747b715Smrg        return NULL;
696747b715Smrg
706747b715Smrg    pExaPixmap = ExaGetPixmapPriv(pPixmap);
716747b715Smrg    pExaPixmap->driverPriv = NULL;
726747b715Smrg
736747b715Smrg    bpp = pPixmap->drawable.bitsPerPixel;
746747b715Smrg
756747b715Smrg    /* Set this before driver hooks, to allow for driver pixmaps without gpu
766747b715Smrg     * memory to back it. These pixmaps have a valid pointer at all times.
776747b715Smrg     */
786747b715Smrg    pPixmap->devPrivate.ptr = NULL;
796747b715Smrg
806747b715Smrg    if (pExaScr->info->CreatePixmap2) {
8135c4bbdfSmrg        int new_pitch = 0;
8235c4bbdfSmrg
8335c4bbdfSmrg        pExaPixmap->driverPriv =
8435c4bbdfSmrg            pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp,
8535c4bbdfSmrg                                         &new_pitch);
8635c4bbdfSmrg        paddedWidth = pExaPixmap->fb_pitch = new_pitch;
876747b715Smrg    }
886747b715Smrg    else {
8935c4bbdfSmrg        paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
9035c4bbdfSmrg        if (paddedWidth / 4 > 32767 || h > 32767)
9135c4bbdfSmrg            return NullPixmap;
926747b715Smrg
9335c4bbdfSmrg        exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
946747b715Smrg
9535c4bbdfSmrg        if (paddedWidth < pExaPixmap->fb_pitch)
9635c4bbdfSmrg            paddedWidth = pExaPixmap->fb_pitch;
9735c4bbdfSmrg        datasize = h * paddedWidth;
9835c4bbdfSmrg        pExaPixmap->driverPriv =
9935c4bbdfSmrg            pExaScr->info->CreatePixmap(pScreen, datasize, 0);
1006747b715Smrg    }
1016747b715Smrg
1026747b715Smrg    if (!pExaPixmap->driverPriv) {
10335c4bbdfSmrg        swap(pExaScr, pScreen, DestroyPixmap);
10435c4bbdfSmrg        pScreen->DestroyPixmap(pPixmap);
10535c4bbdfSmrg        swap(pExaScr, pScreen, DestroyPixmap);
10635c4bbdfSmrg        return NULL;
1076747b715Smrg    }
1086747b715Smrg
1096747b715Smrg    /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */
1106747b715Smrg    pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
1116747b715Smrg    pExaPixmap->fb_ptr = NULL;
1126747b715Smrg    pExaPixmap->pDamage = NULL;
1136747b715Smrg    pExaPixmap->sys_ptr = NULL;
1146747b715Smrg
11535c4bbdfSmrg    (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
1166747b715Smrg
1176747b715Smrg    pExaPixmap->area = NULL;
1186747b715Smrg
11935c4bbdfSmrg    exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);
1206747b715Smrg
1219ace9065Smrg    pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
1229ace9065Smrg
1236747b715Smrg    /* During a fallback we must prepare access. */
1246747b715Smrg    if (pExaScr->fallback_counter)
12535c4bbdfSmrg        exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
1266747b715Smrg
1276747b715Smrg    return pPixmap;
1286747b715Smrg}
1296747b715Smrg
1306747b715SmrgBool
13135c4bbdfSmrgexaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height,
13235c4bbdfSmrg                             int depth, int bitsPerPixel, int devKind,
13335c4bbdfSmrg                             void *pPixData)
1346747b715Smrg{
1356747b715Smrg    ScreenPtr pScreen;
1366747b715Smrg    ExaScreenPrivPtr pExaScr;
1376747b715Smrg    ExaPixmapPrivPtr pExaPixmap;
1386747b715Smrg    Bool ret;
1396747b715Smrg
1406747b715Smrg    if (!pPixmap)
1416747b715Smrg        return FALSE;
1426747b715Smrg
1436747b715Smrg    pScreen = pPixmap->drawable.pScreen;
1446747b715Smrg    pExaScr = ExaGetScreenPriv(pScreen);
1456747b715Smrg    pExaPixmap = ExaGetPixmapPriv(pPixmap);
1466747b715Smrg
1476747b715Smrg    if (pExaPixmap) {
1486747b715Smrg        if (pPixData)
1496747b715Smrg            pExaPixmap->sys_ptr = pPixData;
1506747b715Smrg
1516747b715Smrg        if (devKind > 0)
1526747b715Smrg            pExaPixmap->sys_pitch = devKind;
1536747b715Smrg
1546747b715Smrg        if (width > 0 && height > 0 && bitsPerPixel > 0) {
15535c4bbdfSmrg            exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
1566747b715Smrg
15735c4bbdfSmrg            exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel);
1586747b715Smrg        }
1596747b715Smrg    }
1606747b715Smrg
1616747b715Smrg    if (pExaScr->info->ModifyPixmapHeader) {
16235c4bbdfSmrg        ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
16335c4bbdfSmrg                                                bitsPerPixel, devKind,
16435c4bbdfSmrg                                                pPixData);
16535c4bbdfSmrg        /* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
16635c4bbdfSmrg         * If pPixmap->devPrivate.ptr is non-NULL, then we've got a
16735c4bbdfSmrg         * !has_gpu_copy pixmap. We need to store the pointer,
16835c4bbdfSmrg         * because PrepareAccess won't be called.
16935c4bbdfSmrg         */
17035c4bbdfSmrg        if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
17135c4bbdfSmrg            pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
17235c4bbdfSmrg            pExaPixmap->sys_pitch = pPixmap->devKind;
17335c4bbdfSmrg        }
17435c4bbdfSmrg        if (ret == TRUE)
17535c4bbdfSmrg            goto out;
1766747b715Smrg    }
1776747b715Smrg
1786747b715Smrg    swap(pExaScr, pScreen, ModifyPixmapHeader);
1796747b715Smrg    ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
18035c4bbdfSmrg                                      bitsPerPixel, devKind, pPixData);
1816747b715Smrg    swap(pExaScr, pScreen, ModifyPixmapHeader);
1826747b715Smrg
18335c4bbdfSmrg out:
1846747b715Smrg    /* Always NULL this, we don't want lingering pointers. */
1856747b715Smrg    pPixmap->devPrivate.ptr = NULL;
1866747b715Smrg
1876747b715Smrg    return ret;
1886747b715Smrg}
1896747b715Smrg
1906747b715SmrgBool
19135c4bbdfSmrgexaDestroyPixmap_driver(PixmapPtr pPixmap)
1926747b715Smrg{
19335c4bbdfSmrg    ScreenPtr pScreen = pPixmap->drawable.pScreen;
19435c4bbdfSmrg
1956747b715Smrg    ExaScreenPriv(pScreen);
1966747b715Smrg    Bool ret;
1976747b715Smrg
19835c4bbdfSmrg    if (pPixmap->refcnt == 1) {
19935c4bbdfSmrg        ExaPixmapPriv(pPixmap);
2006747b715Smrg
20135c4bbdfSmrg        exaDestroyPixmap(pPixmap);
2026747b715Smrg
20335c4bbdfSmrg        if (pExaPixmap->driverPriv)
20435c4bbdfSmrg            pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
20535c4bbdfSmrg        pExaPixmap->driverPriv = NULL;
2066747b715Smrg    }
2076747b715Smrg
2086747b715Smrg    swap(pExaScr, pScreen, DestroyPixmap);
20935c4bbdfSmrg    ret = pScreen->DestroyPixmap(pPixmap);
2106747b715Smrg    swap(pExaScr, pScreen, DestroyPixmap);
2116747b715Smrg
2126747b715Smrg    return ret;
2136747b715Smrg}
2146747b715Smrg
2156747b715SmrgBool
2166747b715SmrgexaPixmapHasGpuCopy_driver(PixmapPtr pPixmap)
2176747b715Smrg{
2186747b715Smrg    ScreenPtr pScreen = pPixmap->drawable.pScreen;
21935c4bbdfSmrg
2206747b715Smrg    ExaScreenPriv(pScreen);
22135c4bbdfSmrg    void *saved_ptr;
2226747b715Smrg    Bool ret;
2236747b715Smrg
2246747b715Smrg    saved_ptr = pPixmap->devPrivate.ptr;
2256747b715Smrg    pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
2266747b715Smrg    ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
2276747b715Smrg    pPixmap->devPrivate.ptr = saved_ptr;
2286747b715Smrg
2296747b715Smrg    return ret;
2306747b715Smrg}
231