16747b715Smrg/* 235c4bbdfSmrg * 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 3635c4bbdfSmrgstatic _X_INLINE void * 376747b715SmrgExaGetPixmapAddress(PixmapPtr p) 386747b715Smrg{ 396747b715Smrg ExaPixmapPriv(p); 406747b715Smrg 416747b715Smrg if (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr) 4235c4bbdfSmrg return pExaPixmap->fb_ptr; 436747b715Smrg else 4435c4bbdfSmrg 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, 5735c4bbdfSmrg unsigned usage_hint) 586747b715Smrg{ 596747b715Smrg PixmapPtr pPixmap; 6035c4bbdfSmrg ExaPixmapPrivPtr pExaPixmap; 616747b715Smrg BoxRec box; 626747b715Smrg int bpp; 6335c4bbdfSmrg 646747b715Smrg ExaScreenPriv(pScreen); 656747b715Smrg 666747b715Smrg if (w > 32767 || h > 32767) 6735c4bbdfSmrg return NullPixmap; 686747b715Smrg 696747b715Smrg swap(pExaScr, pScreen, CreatePixmap); 7035c4bbdfSmrg pPixmap = pScreen->CreatePixmap(pScreen, w, h, depth, usage_hint); 716747b715Smrg swap(pExaScr, pScreen, CreatePixmap); 726747b715Smrg 736747b715Smrg if (!pPixmap) 746747b715Smrg return NULL; 756747b715Smrg 766747b715Smrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 776747b715Smrg pExaPixmap->driverPriv = NULL; 786747b715Smrg 796747b715Smrg bpp = pPixmap->drawable.bitsPerPixel; 806747b715Smrg 816747b715Smrg pExaPixmap->driverPriv = NULL; 826747b715Smrg /* Scratch pixmaps may have w/h equal to zero, and may not be 836747b715Smrg * migrated. 846747b715Smrg */ 856747b715Smrg if (!w || !h) 8635c4bbdfSmrg pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 876747b715Smrg else 8835c4bbdfSmrg pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; 896747b715Smrg 906747b715Smrg pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 916747b715Smrg pExaPixmap->sys_pitch = pPixmap->devKind; 926747b715Smrg 936747b715Smrg pPixmap->devPrivate.ptr = NULL; 946747b715Smrg pExaPixmap->use_gpu_copy = FALSE; 956747b715Smrg 966747b715Smrg pExaPixmap->fb_ptr = NULL; 976747b715Smrg exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); 986747b715Smrg pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; 996747b715Smrg 1006747b715Smrg if (pExaPixmap->fb_pitch > 131071) { 10135c4bbdfSmrg swap(pExaScr, pScreen, DestroyPixmap); 10235c4bbdfSmrg pScreen->DestroyPixmap(pPixmap); 10335c4bbdfSmrg swap(pExaScr, pScreen, DestroyPixmap); 10435c4bbdfSmrg return NULL; 1056747b715Smrg } 1066747b715Smrg 1076747b715Smrg /* Set up damage tracking */ 10835c4bbdfSmrg pExaPixmap->pDamage = DamageCreate(NULL, NULL, 10935c4bbdfSmrg DamageReportNone, TRUE, 11035c4bbdfSmrg pScreen, pPixmap); 1116747b715Smrg 1126747b715Smrg if (pExaPixmap->pDamage == NULL) { 11335c4bbdfSmrg swap(pExaScr, pScreen, DestroyPixmap); 11435c4bbdfSmrg pScreen->DestroyPixmap(pPixmap); 11535c4bbdfSmrg swap(pExaScr, pScreen, DestroyPixmap); 11635c4bbdfSmrg return NULL; 1176747b715Smrg } 1186747b715Smrg 11935c4bbdfSmrg DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage); 1206747b715Smrg /* This ensures that pending damage reflects the current operation. */ 1216747b715Smrg /* This is used by exa to optimize migration. */ 12235c4bbdfSmrg DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE); 1236747b715Smrg 1246747b715Smrg pExaPixmap->area = NULL; 1256747b715Smrg 1266747b715Smrg /* We set the initial pixmap as completely valid for a simple reason. 1276747b715Smrg * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which 1286747b715Smrg * could form single pixel rects as part of a region. Setting the complete region 1296747b715Smrg * as valid is a natural defragmentation of the region. 1306747b715Smrg */ 1316747b715Smrg box.x1 = 0; 1326747b715Smrg box.y1 = 0; 1336747b715Smrg box.x2 = w; 1346747b715Smrg box.y2 = h; 1356747b715Smrg RegionInit(&pExaPixmap->validSys, &box, 0); 1366747b715Smrg RegionInit(&pExaPixmap->validFB, &box, 0); 1376747b715Smrg 13835c4bbdfSmrg exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp); 1396747b715Smrg 1406747b715Smrg /* During a fallback we must prepare access. */ 1416747b715Smrg if (pExaScr->fallback_counter) 14235c4bbdfSmrg exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); 1436747b715Smrg 1446747b715Smrg return pPixmap; 1456747b715Smrg} 1466747b715Smrg 1476747b715SmrgBool 14835c4bbdfSmrgexaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, 14935c4bbdfSmrg int depth, int bitsPerPixel, int devKind, 15035c4bbdfSmrg void *pPixData) 1516747b715Smrg{ 1526747b715Smrg ScreenPtr pScreen; 1536747b715Smrg ExaScreenPrivPtr pExaScr; 1546747b715Smrg ExaPixmapPrivPtr pExaPixmap; 1556747b715Smrg Bool ret; 1566747b715Smrg 1576747b715Smrg if (!pPixmap) 1586747b715Smrg return FALSE; 1596747b715Smrg 1606747b715Smrg pScreen = pPixmap->drawable.pScreen; 1616747b715Smrg pExaScr = ExaGetScreenPriv(pScreen); 1626747b715Smrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 1636747b715Smrg 1646747b715Smrg if (pExaPixmap) { 1656747b715Smrg if (pPixData) 1666747b715Smrg pExaPixmap->sys_ptr = pPixData; 1676747b715Smrg 1686747b715Smrg if (devKind > 0) 1696747b715Smrg pExaPixmap->sys_pitch = devKind; 1706747b715Smrg 17135c4bbdfSmrg /* Classic EXA: 17235c4bbdfSmrg * - Framebuffer. 17335c4bbdfSmrg * - Scratch pixmap with gpu memory. 17435c4bbdfSmrg */ 17535c4bbdfSmrg if (pExaScr->info->memoryBase && pPixData) { 17635c4bbdfSmrg if ((CARD8 *) pPixData >= pExaScr->info->memoryBase && 17735c4bbdfSmrg ((CARD8 *) pPixData - pExaScr->info->memoryBase) < 17835c4bbdfSmrg pExaScr->info->memorySize) { 17935c4bbdfSmrg pExaPixmap->fb_ptr = pPixData; 18035c4bbdfSmrg pExaPixmap->fb_pitch = devKind; 18135c4bbdfSmrg pExaPixmap->use_gpu_copy = TRUE; 18235c4bbdfSmrg } 18335c4bbdfSmrg } 1846747b715Smrg 1856747b715Smrg if (width > 0 && height > 0 && bitsPerPixel > 0) { 18635c4bbdfSmrg exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel); 1876747b715Smrg 18835c4bbdfSmrg exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel); 1896747b715Smrg } 1906747b715Smrg 19135c4bbdfSmrg /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or 19235c4bbdfSmrg * gpu memory, so there's no need to track damage. 19335c4bbdfSmrg */ 19435c4bbdfSmrg if (pExaPixmap->pDamage) { 19535c4bbdfSmrg DamageDestroy(pExaPixmap->pDamage); 19635c4bbdfSmrg pExaPixmap->pDamage = NULL; 19735c4bbdfSmrg } 1986747b715Smrg } 1996747b715Smrg 2006747b715Smrg swap(pExaScr, pScreen, ModifyPixmapHeader); 2016747b715Smrg ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, 20235c4bbdfSmrg bitsPerPixel, devKind, pPixData); 2036747b715Smrg swap(pExaScr, pScreen, ModifyPixmapHeader); 2046747b715Smrg 2056747b715Smrg /* Always NULL this, we don't want lingering pointers. */ 2066747b715Smrg pPixmap->devPrivate.ptr = NULL; 2076747b715Smrg 2086747b715Smrg return ret; 2096747b715Smrg} 2106747b715Smrg 2116747b715SmrgBool 21235c4bbdfSmrgexaDestroyPixmap_classic(PixmapPtr pPixmap) 2136747b715Smrg{ 21435c4bbdfSmrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 21535c4bbdfSmrg 2166747b715Smrg ExaScreenPriv(pScreen); 2176747b715Smrg Bool ret; 2186747b715Smrg 21935c4bbdfSmrg if (pPixmap->refcnt == 1) { 22035c4bbdfSmrg ExaPixmapPriv(pPixmap); 22135c4bbdfSmrg 22235c4bbdfSmrg exaDestroyPixmap(pPixmap); 22335c4bbdfSmrg 22435c4bbdfSmrg if (pExaPixmap->area) { 22535c4bbdfSmrg DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", 22635c4bbdfSmrg (void *) pPixmap->drawable.id, 22735c4bbdfSmrg ExaGetPixmapPriv(pPixmap)->area->offset, 22835c4bbdfSmrg pPixmap->drawable.width, pPixmap->drawable.height)); 22935c4bbdfSmrg /* Free the offscreen area */ 23035c4bbdfSmrg exaOffscreenFree(pPixmap->drawable.pScreen, pExaPixmap->area); 23135c4bbdfSmrg pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 23235c4bbdfSmrg pPixmap->devKind = pExaPixmap->sys_pitch; 23335c4bbdfSmrg } 23435c4bbdfSmrg RegionUninit(&pExaPixmap->validSys); 23535c4bbdfSmrg RegionUninit(&pExaPixmap->validFB); 2366747b715Smrg } 2376747b715Smrg 2386747b715Smrg swap(pExaScr, pScreen, DestroyPixmap); 23935c4bbdfSmrg ret = pScreen->DestroyPixmap(pPixmap); 2406747b715Smrg swap(pExaScr, pScreen, DestroyPixmap); 2416747b715Smrg 2426747b715Smrg return ret; 2436747b715Smrg} 2446747b715Smrg 2456747b715SmrgBool 2466747b715SmrgexaPixmapHasGpuCopy_classic(PixmapPtr pPixmap) 2476747b715Smrg{ 2486747b715Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 24935c4bbdfSmrg 2506747b715Smrg ExaScreenPriv(pScreen); 2516747b715Smrg ExaPixmapPriv(pPixmap); 2526747b715Smrg Bool ret; 2536747b715Smrg 2546747b715Smrg if (pExaScr->info->PixmapIsOffscreen) { 25535c4bbdfSmrg void *old_ptr = pPixmap->devPrivate.ptr; 25635c4bbdfSmrg 25735c4bbdfSmrg pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); 25835c4bbdfSmrg ret = pExaScr->info->PixmapIsOffscreen(pPixmap); 25935c4bbdfSmrg pPixmap->devPrivate.ptr = old_ptr; 26035c4bbdfSmrg } 26135c4bbdfSmrg else 26235c4bbdfSmrg ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr); 2636747b715Smrg 2646747b715Smrg return ret; 2656747b715Smrg} 266