exa_mixed.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 + better initial placement code.
356747b715Smrg */
366747b715Smrg
376747b715Smrgstatic _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,
506747b715Smrg		unsigned usage_hint)
516747b715Smrg{
526747b715Smrg    PixmapPtr pPixmap;
536747b715Smrg    ExaPixmapPrivPtr	pExaPixmap;
546747b715Smrg    int bpp;
556747b715Smrg    size_t paddedWidth;
566747b715Smrg    ExaScreenPriv(pScreen);
576747b715Smrg
586747b715Smrg    if (w > 32767 || h > 32767)
596747b715Smrg	return NullPixmap;
606747b715Smrg
616747b715Smrg    swap(pExaScr, pScreen, CreatePixmap);
626747b715Smrg    pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
636747b715Smrg    swap(pExaScr, pScreen, CreatePixmap);
646747b715Smrg
656747b715Smrg    if (!pPixmap)
666747b715Smrg        return NULL;
676747b715Smrg
686747b715Smrg    pExaPixmap = ExaGetPixmapPriv(pPixmap);
696747b715Smrg    pExaPixmap->driverPriv = NULL;
706747b715Smrg
716747b715Smrg    bpp = pPixmap->drawable.bitsPerPixel;
726747b715Smrg
736747b715Smrg    paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
746747b715Smrg    if (paddedWidth / 4 > 32767 || h > 32767)
756747b715Smrg        return NullPixmap;
766747b715Smrg
776747b715Smrg    /* We will allocate the system pixmap later if needed. */
786747b715Smrg    pPixmap->devPrivate.ptr = NULL;
796747b715Smrg    pExaPixmap->sys_ptr = NULL;
806747b715Smrg    pExaPixmap->sys_pitch = paddedWidth;
816747b715Smrg
826747b715Smrg    pExaPixmap->area = NULL;
836747b715Smrg    pExaPixmap->fb_ptr = NULL;
846747b715Smrg    pExaPixmap->pDamage = NULL;
856747b715Smrg
866747b715Smrg    exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
876747b715Smrg    exaSetAccelBlock(pExaScr, pExaPixmap,
886747b715Smrg	w, h, bpp);
896747b715Smrg
906747b715Smrg    (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
916747b715Smrg				    paddedWidth, NULL);
926747b715Smrg
936747b715Smrg    /* A scratch pixmap will become a driver pixmap right away. */
946747b715Smrg    if (!w || !h) {
956747b715Smrg	exaCreateDriverPixmap_mixed(pPixmap);
966747b715Smrg	pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
976747b715Smrg    } else {
986747b715Smrg	pExaPixmap->use_gpu_copy = FALSE;
996747b715Smrg
1006747b715Smrg	if (w == 1 && h == 1) {
1016747b715Smrg	    pExaPixmap->sys_ptr = malloc((pPixmap->drawable.bitsPerPixel + 7) / 8);
1026747b715Smrg
1036747b715Smrg	    /* Set up damage tracking */
1046747b715Smrg	    pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
1056747b715Smrg					       DamageReportNonEmpty, TRUE,
1066747b715Smrg					       pPixmap->drawable.pScreen,
1076747b715Smrg					       pPixmap);
1086747b715Smrg
1096747b715Smrg	    DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
1106747b715Smrg	    /* This ensures that pending damage reflects the current operation. */
1116747b715Smrg	    /* This is used by exa to optimize migration. */
1126747b715Smrg	    DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
1136747b715Smrg	}
1146747b715Smrg    }
1156747b715Smrg
1166747b715Smrg    /* During a fallback we must prepare access. */
1176747b715Smrg    if (pExaScr->fallback_counter)
1186747b715Smrg	exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
1196747b715Smrg
1206747b715Smrg    return pPixmap;
1216747b715Smrg}
1226747b715Smrg
1236747b715SmrgBool
1246747b715SmrgexaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
1256747b715Smrg		      int bitsPerPixel, int devKind, pointer pPixData)
1266747b715Smrg{
1276747b715Smrg    ScreenPtr pScreen;
1286747b715Smrg    ExaScreenPrivPtr pExaScr;
1296747b715Smrg    ExaPixmapPrivPtr pExaPixmap;
1306747b715Smrg    Bool ret, has_gpu_copy;
1316747b715Smrg
1326747b715Smrg    if (!pPixmap)
1336747b715Smrg        return FALSE;
1346747b715Smrg
1356747b715Smrg    pScreen = pPixmap->drawable.pScreen;
1366747b715Smrg    pExaScr = ExaGetScreenPriv(pScreen);
1376747b715Smrg    pExaPixmap = ExaGetPixmapPriv(pPixmap);
1386747b715Smrg
1396747b715Smrg    if (pPixData) {
1406747b715Smrg	if (pExaPixmap->driverPriv) {
1416747b715Smrg	    if (pExaPixmap->pDamage) {
1426747b715Smrg		DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
1436747b715Smrg		DamageDestroy(pExaPixmap->pDamage);
1446747b715Smrg		pExaPixmap->pDamage = NULL;
1456747b715Smrg	    }
1466747b715Smrg
1476747b715Smrg	    pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
1486747b715Smrg	    pExaPixmap->driverPriv = NULL;
1496747b715Smrg	}
1506747b715Smrg
1516747b715Smrg	pExaPixmap->use_gpu_copy = FALSE;
1526747b715Smrg	pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
1536747b715Smrg    }
1546747b715Smrg
1556747b715Smrg    has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
1566747b715Smrg
1576747b715Smrg    if (width <= 0)
1586747b715Smrg	width = pPixmap->drawable.width;
1596747b715Smrg
1606747b715Smrg    if (height <= 0)
1616747b715Smrg	height = pPixmap->drawable.height;
1626747b715Smrg
1636747b715Smrg    if (bitsPerPixel <= 0) {
1646747b715Smrg	if (depth <= 0)
1656747b715Smrg	    bitsPerPixel = pPixmap->drawable.bitsPerPixel;
1666747b715Smrg	else
1676747b715Smrg	    bitsPerPixel = BitsPerPixel(depth);
1686747b715Smrg    }
1696747b715Smrg
1706747b715Smrg    if (depth <= 0)
1716747b715Smrg	depth = pPixmap->drawable.depth;
1726747b715Smrg
1736747b715Smrg    if (width != pPixmap->drawable.width ||
1746747b715Smrg	height != pPixmap->drawable.height ||
1756747b715Smrg	depth != pPixmap->drawable.depth ||
1766747b715Smrg	bitsPerPixel != pPixmap->drawable.bitsPerPixel) {
1776747b715Smrg	if (pExaPixmap->driverPriv) {
1786747b715Smrg            exaSetFbPitch(pExaScr, pExaPixmap,
1796747b715Smrg                          width, height, bitsPerPixel);
1806747b715Smrg
1816747b715Smrg            exaSetAccelBlock(pExaScr, pExaPixmap,
1826747b715Smrg                             width, height, bitsPerPixel);
1836747b715Smrg            RegionEmpty(&pExaPixmap->validFB);
1846747b715Smrg        }
1856747b715Smrg
1866747b715Smrg	/* Need to re-create system copy if there's also a GPU copy */
1876747b715Smrg	if (has_gpu_copy && pExaPixmap->sys_ptr) {
1886747b715Smrg	    free(pExaPixmap->sys_ptr);
1896747b715Smrg	    pExaPixmap->sys_ptr = NULL;
1906747b715Smrg	    pExaPixmap->sys_pitch = devKind > 0 ? devKind :
1916747b715Smrg	        PixmapBytePad(width, depth);
1926747b715Smrg	    DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
1936747b715Smrg	    DamageDestroy(pExaPixmap->pDamage);
1946747b715Smrg	    pExaPixmap->pDamage = NULL;
1956747b715Smrg	    RegionEmpty(&pExaPixmap->validSys);
1966747b715Smrg
1976747b715Smrg	    if (pExaScr->deferred_mixed_pixmap == pPixmap)
1986747b715Smrg		pExaScr->deferred_mixed_pixmap = NULL;
1996747b715Smrg	}
2006747b715Smrg    }
2016747b715Smrg
2026747b715Smrg    if (has_gpu_copy) {
2036747b715Smrg	pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
2046747b715Smrg	pPixmap->devKind = pExaPixmap->fb_pitch;
2056747b715Smrg    } else {
2066747b715Smrg	pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
2076747b715Smrg	pPixmap->devKind = pExaPixmap->sys_pitch;
2086747b715Smrg    }
2096747b715Smrg
2106747b715Smrg    /* Only pass driver pixmaps to the driver. */
2116747b715Smrg    if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
2126747b715Smrg	ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
2136747b715Smrg						bitsPerPixel, devKind, pPixData);
2146747b715Smrg	if (ret == TRUE)
2156747b715Smrg	    goto out;
2166747b715Smrg    }
2176747b715Smrg
2186747b715Smrg    swap(pExaScr, pScreen, ModifyPixmapHeader);
2196747b715Smrg    ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
2206747b715Smrg					    bitsPerPixel, devKind, pPixData);
2216747b715Smrg    swap(pExaScr, pScreen, ModifyPixmapHeader);
2226747b715Smrg
2236747b715Smrgout:
2246747b715Smrg    if (has_gpu_copy) {
2256747b715Smrg	pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
2266747b715Smrg	pExaPixmap->fb_pitch = pPixmap->devKind;
2276747b715Smrg    } else {
2286747b715Smrg	pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
2296747b715Smrg	pExaPixmap->sys_pitch = pPixmap->devKind;
2306747b715Smrg    }
2316747b715Smrg    /* Always NULL this, we don't want lingering pointers. */
2326747b715Smrg    pPixmap->devPrivate.ptr = NULL;
2336747b715Smrg
2346747b715Smrg    return ret;
2356747b715Smrg}
2366747b715Smrg
2376747b715SmrgBool
2386747b715SmrgexaDestroyPixmap_mixed(PixmapPtr pPixmap)
2396747b715Smrg{
2406747b715Smrg    ScreenPtr	pScreen = pPixmap->drawable.pScreen;
2416747b715Smrg    ExaScreenPriv(pScreen);
2426747b715Smrg    Bool ret;
2436747b715Smrg
2446747b715Smrg    if (pPixmap->refcnt == 1)
2456747b715Smrg    {
2466747b715Smrg	ExaPixmapPriv (pPixmap);
2476747b715Smrg
2486747b715Smrg	exaDestroyPixmap(pPixmap);
2496747b715Smrg
2506747b715Smrg	if (pExaScr->deferred_mixed_pixmap == pPixmap)
2516747b715Smrg	    pExaScr->deferred_mixed_pixmap = NULL;
2526747b715Smrg
2536747b715Smrg	if (pExaPixmap->driverPriv)
2546747b715Smrg	    pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
2556747b715Smrg	pExaPixmap->driverPriv = NULL;
2566747b715Smrg
2576747b715Smrg	if (pExaPixmap->pDamage) {
2586747b715Smrg	    free(pExaPixmap->sys_ptr);
2596747b715Smrg	    pExaPixmap->sys_ptr = NULL;
2606747b715Smrg	    pExaPixmap->pDamage = NULL;
2616747b715Smrg	}
2626747b715Smrg    }
2636747b715Smrg
2646747b715Smrg    swap(pExaScr, pScreen, DestroyPixmap);
2656747b715Smrg    ret = pScreen->DestroyPixmap (pPixmap);
2666747b715Smrg    swap(pExaScr, pScreen, DestroyPixmap);
2676747b715Smrg
2686747b715Smrg    return ret;
2696747b715Smrg}
2706747b715Smrg
2716747b715SmrgBool
2726747b715SmrgexaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap)
2736747b715Smrg{
2746747b715Smrg    ScreenPtr pScreen = pPixmap->drawable.pScreen;
2756747b715Smrg    ExaScreenPriv(pScreen);
2766747b715Smrg    ExaPixmapPriv(pPixmap);
2776747b715Smrg    pointer saved_ptr;
2786747b715Smrg    Bool ret;
2796747b715Smrg
2806747b715Smrg    if (!pExaPixmap->driverPriv)
2816747b715Smrg	return FALSE;
2826747b715Smrg
2836747b715Smrg    saved_ptr = pPixmap->devPrivate.ptr;
2846747b715Smrg    pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
2856747b715Smrg    ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
2866747b715Smrg    pPixmap->devPrivate.ptr = saved_ptr;
2876747b715Smrg
2886747b715Smrg    return ret;
2896747b715Smrg}
290