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