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