exa_driver.c revision 6747b715
16747b715Smrg/*
26747b715Smrg * 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
366747b715Smrgstatic _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,
516747b715Smrg		unsigned usage_hint)
526747b715Smrg{
536747b715Smrg    PixmapPtr pPixmap;
546747b715Smrg    ExaPixmapPrivPtr	pExaPixmap;
556747b715Smrg    int bpp;
566747b715Smrg    size_t paddedWidth, datasize;
576747b715Smrg    ExaScreenPriv(pScreen);
586747b715Smrg
596747b715Smrg    if (w > 32767 || h > 32767)
606747b715Smrg	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    /* Set this before driver hooks, to allow for driver pixmaps without gpu
756747b715Smrg     * memory to back it. These pixmaps have a valid pointer at all times.
766747b715Smrg     */
776747b715Smrg    pPixmap->devPrivate.ptr = NULL;
786747b715Smrg
796747b715Smrg    if (pExaScr->info->CreatePixmap2) {
806747b715Smrg	int new_pitch = 0;
816747b715Smrg	pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, &new_pitch);
826747b715Smrg	paddedWidth = pExaPixmap->fb_pitch = new_pitch;
836747b715Smrg    }
846747b715Smrg    else {
856747b715Smrg	paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
866747b715Smrg	if (paddedWidth / 4 > 32767 || h > 32767)
876747b715Smrg	    return NullPixmap;
886747b715Smrg
896747b715Smrg	exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
906747b715Smrg
916747b715Smrg	if (paddedWidth < pExaPixmap->fb_pitch)
926747b715Smrg	    paddedWidth = pExaPixmap->fb_pitch;
936747b715Smrg	datasize = h * paddedWidth;
946747b715Smrg	pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
956747b715Smrg    }
966747b715Smrg
976747b715Smrg    if (!pExaPixmap->driverPriv) {
986747b715Smrg	swap(pExaScr, pScreen, DestroyPixmap);
996747b715Smrg	pScreen->DestroyPixmap (pPixmap);
1006747b715Smrg	swap(pExaScr, pScreen, DestroyPixmap);
1016747b715Smrg	return NULL;
1026747b715Smrg    }
1036747b715Smrg
1046747b715Smrg    /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */
1056747b715Smrg    pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
1066747b715Smrg    pExaPixmap->fb_ptr = NULL;
1076747b715Smrg    pExaPixmap->pDamage = NULL;
1086747b715Smrg    pExaPixmap->sys_ptr = NULL;
1096747b715Smrg
1106747b715Smrg    (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
1116747b715Smrg				    paddedWidth, NULL);
1126747b715Smrg
1136747b715Smrg    pExaPixmap->area = NULL;
1146747b715Smrg
1156747b715Smrg    exaSetAccelBlock(pExaScr, pExaPixmap,
1166747b715Smrg                     w, h, bpp);
1176747b715Smrg
1186747b715Smrg    /* During a fallback we must prepare access. */
1196747b715Smrg    if (pExaScr->fallback_counter)
1206747b715Smrg	exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
1216747b715Smrg
1226747b715Smrg    return pPixmap;
1236747b715Smrg}
1246747b715Smrg
1256747b715SmrgBool
1266747b715SmrgexaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, int depth,
1276747b715Smrg		      int bitsPerPixel, int devKind, pointer pPixData)
1286747b715Smrg{
1296747b715Smrg    ScreenPtr pScreen;
1306747b715Smrg    ExaScreenPrivPtr pExaScr;
1316747b715Smrg    ExaPixmapPrivPtr pExaPixmap;
1326747b715Smrg    Bool ret;
1336747b715Smrg
1346747b715Smrg    if (!pPixmap)
1356747b715Smrg        return FALSE;
1366747b715Smrg
1376747b715Smrg    pScreen = pPixmap->drawable.pScreen;
1386747b715Smrg    pExaScr = ExaGetScreenPriv(pScreen);
1396747b715Smrg    pExaPixmap = ExaGetPixmapPriv(pPixmap);
1406747b715Smrg
1416747b715Smrg    if (pExaPixmap) {
1426747b715Smrg        if (pPixData)
1436747b715Smrg            pExaPixmap->sys_ptr = pPixData;
1446747b715Smrg
1456747b715Smrg        if (devKind > 0)
1466747b715Smrg            pExaPixmap->sys_pitch = devKind;
1476747b715Smrg
1486747b715Smrg        if (width > 0 && height > 0 && bitsPerPixel > 0) {
1496747b715Smrg            exaSetFbPitch(pExaScr, pExaPixmap,
1506747b715Smrg                          width, height, bitsPerPixel);
1516747b715Smrg
1526747b715Smrg            exaSetAccelBlock(pExaScr, pExaPixmap,
1536747b715Smrg                             width, height, bitsPerPixel);
1546747b715Smrg        }
1556747b715Smrg    }
1566747b715Smrg
1576747b715Smrg    if (pExaScr->info->ModifyPixmapHeader) {
1586747b715Smrg	ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
1596747b715Smrg						bitsPerPixel, devKind, pPixData);
1606747b715Smrg	/* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
1616747b715Smrg	 * If pPixmap->devPrivate.ptr is non-NULL, then we've got a
1626747b715Smrg	 * !has_gpu_copy pixmap. We need to store the pointer,
1636747b715Smrg	 * because PrepareAccess won't be called.
1646747b715Smrg	 */
1656747b715Smrg	if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
1666747b715Smrg	    pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
1676747b715Smrg	    pExaPixmap->sys_pitch = pPixmap->devKind;
1686747b715Smrg	}
1696747b715Smrg	if (ret == TRUE)
1706747b715Smrg	    goto out;
1716747b715Smrg    }
1726747b715Smrg
1736747b715Smrg    swap(pExaScr, pScreen, ModifyPixmapHeader);
1746747b715Smrg    ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
1756747b715Smrg					    bitsPerPixel, devKind, pPixData);
1766747b715Smrg    swap(pExaScr, pScreen, ModifyPixmapHeader);
1776747b715Smrg
1786747b715Smrgout:
1796747b715Smrg    /* Always NULL this, we don't want lingering pointers. */
1806747b715Smrg    pPixmap->devPrivate.ptr = NULL;
1816747b715Smrg
1826747b715Smrg    return ret;
1836747b715Smrg}
1846747b715Smrg
1856747b715SmrgBool
1866747b715SmrgexaDestroyPixmap_driver (PixmapPtr pPixmap)
1876747b715Smrg{
1886747b715Smrg    ScreenPtr	pScreen = pPixmap->drawable.pScreen;
1896747b715Smrg    ExaScreenPriv(pScreen);
1906747b715Smrg    Bool ret;
1916747b715Smrg
1926747b715Smrg    if (pPixmap->refcnt == 1)
1936747b715Smrg    {
1946747b715Smrg	ExaPixmapPriv (pPixmap);
1956747b715Smrg
1966747b715Smrg	exaDestroyPixmap(pPixmap);
1976747b715Smrg
1986747b715Smrg	if (pExaPixmap->driverPriv)
1996747b715Smrg	    pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
2006747b715Smrg	pExaPixmap->driverPriv = NULL;
2016747b715Smrg    }
2026747b715Smrg
2036747b715Smrg    swap(pExaScr, pScreen, DestroyPixmap);
2046747b715Smrg    ret = pScreen->DestroyPixmap (pPixmap);
2056747b715Smrg    swap(pExaScr, pScreen, DestroyPixmap);
2066747b715Smrg
2076747b715Smrg    return ret;
2086747b715Smrg}
2096747b715Smrg
2106747b715SmrgBool
2116747b715SmrgexaPixmapHasGpuCopy_driver(PixmapPtr pPixmap)
2126747b715Smrg{
2136747b715Smrg    ScreenPtr pScreen = pPixmap->drawable.pScreen;
2146747b715Smrg    ExaScreenPriv(pScreen);
2156747b715Smrg    pointer saved_ptr;
2166747b715Smrg    Bool ret;
2176747b715Smrg
2186747b715Smrg    saved_ptr = pPixmap->devPrivate.ptr;
2196747b715Smrg    pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
2206747b715Smrg    ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
2216747b715Smrg    pPixmap->devPrivate.ptr = saved_ptr;
2226747b715Smrg
2236747b715Smrg    return ret;
2246747b715Smrg}
225