exa_classic.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 classic exa specific implementation. */
356747b715Smrg
366747b715Smrgstatic _X_INLINE void*
376747b715SmrgExaGetPixmapAddress(PixmapPtr p)
386747b715Smrg{
396747b715Smrg    ExaPixmapPriv(p);
406747b715Smrg
416747b715Smrg    if (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr)
426747b715Smrg	return pExaPixmap->fb_ptr;
436747b715Smrg    else
446747b715Smrg	return pExaPixmap->sys_ptr;
456747b715Smrg}
466747b715Smrg
476747b715Smrg/**
486747b715Smrg * exaCreatePixmap() creates a new pixmap.
496747b715Smrg *
506747b715Smrg * If width and height are 0, this won't be a full-fledged pixmap and it will
516747b715Smrg * get ModifyPixmapHeader() called on it later.  So, we mark it as pinned, because
526747b715Smrg * ModifyPixmapHeader() would break migration.  These types of pixmaps are used
536747b715Smrg * for scratch pixmaps, or to represent the visible screen.
546747b715Smrg */
556747b715SmrgPixmapPtr
566747b715SmrgexaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
576747b715Smrg		unsigned usage_hint)
586747b715Smrg{
596747b715Smrg    PixmapPtr pPixmap;
606747b715Smrg    ExaPixmapPrivPtr	pExaPixmap;
616747b715Smrg    BoxRec box;
626747b715Smrg    int bpp;
636747b715Smrg    ExaScreenPriv(pScreen);
646747b715Smrg
656747b715Smrg    if (w > 32767 || h > 32767)
666747b715Smrg	return NullPixmap;
676747b715Smrg
686747b715Smrg    swap(pExaScr, pScreen, CreatePixmap);
696747b715Smrg    pPixmap = pScreen->CreatePixmap (pScreen, w, h, depth, usage_hint);
706747b715Smrg    swap(pExaScr, pScreen, CreatePixmap);
716747b715Smrg
726747b715Smrg    if (!pPixmap)
736747b715Smrg        return NULL;
746747b715Smrg
756747b715Smrg    pExaPixmap = ExaGetPixmapPriv(pPixmap);
766747b715Smrg    pExaPixmap->driverPriv = NULL;
776747b715Smrg
786747b715Smrg    bpp = pPixmap->drawable.bitsPerPixel;
796747b715Smrg
806747b715Smrg    pExaPixmap->driverPriv = NULL;
816747b715Smrg    /* Scratch pixmaps may have w/h equal to zero, and may not be
826747b715Smrg     * migrated.
836747b715Smrg     */
846747b715Smrg    if (!w || !h)
856747b715Smrg	pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
866747b715Smrg    else
876747b715Smrg	pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
886747b715Smrg
896747b715Smrg    pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
906747b715Smrg    pExaPixmap->sys_pitch = pPixmap->devKind;
916747b715Smrg
926747b715Smrg    pPixmap->devPrivate.ptr = NULL;
936747b715Smrg    pExaPixmap->use_gpu_copy = FALSE;
946747b715Smrg
956747b715Smrg    pExaPixmap->fb_ptr = NULL;
966747b715Smrg    exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
976747b715Smrg    pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
986747b715Smrg
996747b715Smrg    if (pExaPixmap->fb_pitch > 131071) {
1006747b715Smrg	swap(pExaScr, pScreen, DestroyPixmap);
1016747b715Smrg	pScreen->DestroyPixmap (pPixmap);
1026747b715Smrg	swap(pExaScr, pScreen, DestroyPixmap);
1036747b715Smrg	return NULL;
1046747b715Smrg    }
1056747b715Smrg
1066747b715Smrg    /* Set up damage tracking */
1076747b715Smrg    pExaPixmap->pDamage = DamageCreate (NULL, NULL,
1086747b715Smrg					DamageReportNone, TRUE,
1096747b715Smrg					pScreen, pPixmap);
1106747b715Smrg
1116747b715Smrg    if (pExaPixmap->pDamage == NULL) {
1126747b715Smrg	swap(pExaScr, pScreen, DestroyPixmap);
1136747b715Smrg	pScreen->DestroyPixmap (pPixmap);
1146747b715Smrg	swap(pExaScr, pScreen, DestroyPixmap);
1156747b715Smrg	return NULL;
1166747b715Smrg    }
1176747b715Smrg
1186747b715Smrg    DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
1196747b715Smrg    /* This ensures that pending damage reflects the current operation. */
1206747b715Smrg    /* This is used by exa to optimize migration. */
1216747b715Smrg    DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
1226747b715Smrg
1236747b715Smrg    pExaPixmap->area = NULL;
1246747b715Smrg
1256747b715Smrg    /* We set the initial pixmap as completely valid for a simple reason.
1266747b715Smrg     * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
1276747b715Smrg     * could form single pixel rects as part of a region. Setting the complete region
1286747b715Smrg     * as valid is a natural defragmentation of the region.
1296747b715Smrg     */
1306747b715Smrg    box.x1 = 0;
1316747b715Smrg    box.y1 = 0;
1326747b715Smrg    box.x2 = w;
1336747b715Smrg    box.y2 = h;
1346747b715Smrg    RegionInit(&pExaPixmap->validSys, &box, 0);
1356747b715Smrg    RegionInit(&pExaPixmap->validFB, &box, 0);
1366747b715Smrg
1376747b715Smrg    exaSetAccelBlock(pExaScr, pExaPixmap,
1386747b715Smrg                     w, h, bpp);
1396747b715Smrg
1406747b715Smrg    /* During a fallback we must prepare access. */
1416747b715Smrg    if (pExaScr->fallback_counter)
1426747b715Smrg	exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
1436747b715Smrg
1446747b715Smrg    return pPixmap;
1456747b715Smrg}
1466747b715Smrg
1476747b715SmrgBool
1486747b715SmrgexaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, int depth,
1496747b715Smrg		      int bitsPerPixel, int devKind, pointer pPixData)
1506747b715Smrg{
1516747b715Smrg    ScreenPtr pScreen;
1526747b715Smrg    ExaScreenPrivPtr pExaScr;
1536747b715Smrg    ExaPixmapPrivPtr pExaPixmap;
1546747b715Smrg    Bool ret;
1556747b715Smrg
1566747b715Smrg    if (!pPixmap)
1576747b715Smrg        return FALSE;
1586747b715Smrg
1596747b715Smrg    pScreen = pPixmap->drawable.pScreen;
1606747b715Smrg    pExaScr = ExaGetScreenPriv(pScreen);
1616747b715Smrg    pExaPixmap = ExaGetPixmapPriv(pPixmap);
1626747b715Smrg
1636747b715Smrg    if (pExaPixmap) {
1646747b715Smrg        if (pPixData)
1656747b715Smrg            pExaPixmap->sys_ptr = pPixData;
1666747b715Smrg
1676747b715Smrg        if (devKind > 0)
1686747b715Smrg            pExaPixmap->sys_pitch = devKind;
1696747b715Smrg
1706747b715Smrg	/* Classic EXA:
1716747b715Smrg	 * - Framebuffer.
1726747b715Smrg	 * - Scratch pixmap with gpu memory.
1736747b715Smrg	 */
1746747b715Smrg	if (pExaScr->info->memoryBase && pPixData) {
1756747b715Smrg	    if ((CARD8 *)pPixData >= pExaScr->info->memoryBase &&
1766747b715Smrg		((CARD8 *)pPixData - pExaScr->info->memoryBase) <
1776747b715Smrg				pExaScr->info->memorySize) {
1786747b715Smrg		pExaPixmap->fb_ptr = pPixData;
1796747b715Smrg		pExaPixmap->fb_pitch = devKind;
1806747b715Smrg		pExaPixmap->use_gpu_copy = TRUE;
1816747b715Smrg	    }
1826747b715Smrg	}
1836747b715Smrg
1846747b715Smrg        if (width > 0 && height > 0 && bitsPerPixel > 0) {
1856747b715Smrg            exaSetFbPitch(pExaScr, pExaPixmap,
1866747b715Smrg                          width, height, bitsPerPixel);
1876747b715Smrg
1886747b715Smrg            exaSetAccelBlock(pExaScr, pExaPixmap,
1896747b715Smrg                             width, height, bitsPerPixel);
1906747b715Smrg        }
1916747b715Smrg
1926747b715Smrg	/* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
1936747b715Smrg	 * gpu memory, so there's no need to track damage.
1946747b715Smrg	 */
1956747b715Smrg	if (pExaPixmap->pDamage) {
1966747b715Smrg	    DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
1976747b715Smrg	    DamageDestroy(pExaPixmap->pDamage);
1986747b715Smrg	    pExaPixmap->pDamage = NULL;
1996747b715Smrg	}
2006747b715Smrg    }
2016747b715Smrg
2026747b715Smrg    swap(pExaScr, pScreen, ModifyPixmapHeader);
2036747b715Smrg    ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
2046747b715Smrg					    bitsPerPixel, devKind, pPixData);
2056747b715Smrg    swap(pExaScr, pScreen, ModifyPixmapHeader);
2066747b715Smrg
2076747b715Smrg    /* Always NULL this, we don't want lingering pointers. */
2086747b715Smrg    pPixmap->devPrivate.ptr = NULL;
2096747b715Smrg
2106747b715Smrg    return ret;
2116747b715Smrg}
2126747b715Smrg
2136747b715SmrgBool
2146747b715SmrgexaDestroyPixmap_classic (PixmapPtr pPixmap)
2156747b715Smrg{
2166747b715Smrg    ScreenPtr	pScreen = pPixmap->drawable.pScreen;
2176747b715Smrg    ExaScreenPriv(pScreen);
2186747b715Smrg    Bool ret;
2196747b715Smrg
2206747b715Smrg    if (pPixmap->refcnt == 1)
2216747b715Smrg    {
2226747b715Smrg	ExaPixmapPriv (pPixmap);
2236747b715Smrg
2246747b715Smrg	exaDestroyPixmap(pPixmap);
2256747b715Smrg
2266747b715Smrg	if (pExaPixmap->area)
2276747b715Smrg	{
2286747b715Smrg	    DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
2296747b715Smrg                        (void*)pPixmap->drawable.id,
2306747b715Smrg			 ExaGetPixmapPriv(pPixmap)->area->offset,
2316747b715Smrg			 pPixmap->drawable.width,
2326747b715Smrg			 pPixmap->drawable.height));
2336747b715Smrg	    /* Free the offscreen area */
2346747b715Smrg	    exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
2356747b715Smrg	    pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
2366747b715Smrg	    pPixmap->devKind = pExaPixmap->sys_pitch;
2376747b715Smrg	}
2386747b715Smrg	RegionUninit(&pExaPixmap->validSys);
2396747b715Smrg	RegionUninit(&pExaPixmap->validFB);
2406747b715Smrg    }
2416747b715Smrg
2426747b715Smrg    swap(pExaScr, pScreen, DestroyPixmap);
2436747b715Smrg    ret = pScreen->DestroyPixmap (pPixmap);
2446747b715Smrg    swap(pExaScr, pScreen, DestroyPixmap);
2456747b715Smrg
2466747b715Smrg    return ret;
2476747b715Smrg}
2486747b715Smrg
2496747b715SmrgBool
2506747b715SmrgexaPixmapHasGpuCopy_classic(PixmapPtr pPixmap)
2516747b715Smrg{
2526747b715Smrg    ScreenPtr pScreen = pPixmap->drawable.pScreen;
2536747b715Smrg    ExaScreenPriv(pScreen);
2546747b715Smrg    ExaPixmapPriv(pPixmap);
2556747b715Smrg    Bool ret;
2566747b715Smrg
2576747b715Smrg    if (pExaScr->info->PixmapIsOffscreen) {
2586747b715Smrg	void* old_ptr = pPixmap->devPrivate.ptr;
2596747b715Smrg	pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
2606747b715Smrg	ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
2616747b715Smrg	pPixmap->devPrivate.ptr = old_ptr;
2626747b715Smrg    } else
2636747b715Smrg	ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr);
2646747b715Smrg
2656747b715Smrg    return ret;
2666747b715Smrg}
267