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 driver allocated pixmaps + better initial placement code. 356747b715Smrg */ 366747b715Smrg 3735c4bbdfSmrgstatic _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, 5035c4bbdfSmrg unsigned usage_hint) 516747b715Smrg{ 526747b715Smrg PixmapPtr pPixmap; 5335c4bbdfSmrg ExaPixmapPrivPtr pExaPixmap; 546747b715Smrg int bpp; 556747b715Smrg size_t paddedWidth; 5635c4bbdfSmrg 576747b715Smrg ExaScreenPriv(pScreen); 586747b715Smrg 596747b715Smrg if (w > 32767 || h > 32767) 6035c4bbdfSmrg return NullPixmap; 616747b715Smrg 626747b715Smrg swap(pExaScr, pScreen, CreatePixmap); 636747b715Smrg pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint); 646747b715Smrg swap(pExaScr, pScreen, CreatePixmap); 656747b715Smrg 666747b715Smrg if (!pPixmap) 676747b715Smrg return NULL; 686747b715Smrg 696747b715Smrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 706747b715Smrg pExaPixmap->driverPriv = NULL; 716747b715Smrg 726747b715Smrg bpp = pPixmap->drawable.bitsPerPixel; 736747b715Smrg 746747b715Smrg paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); 756747b715Smrg if (paddedWidth / 4 > 32767 || h > 32767) 766747b715Smrg return NullPixmap; 776747b715Smrg 786747b715Smrg /* We will allocate the system pixmap later if needed. */ 796747b715Smrg pPixmap->devPrivate.ptr = NULL; 806747b715Smrg pExaPixmap->sys_ptr = NULL; 816747b715Smrg pExaPixmap->sys_pitch = paddedWidth; 826747b715Smrg 836747b715Smrg pExaPixmap->area = NULL; 846747b715Smrg pExaPixmap->fb_ptr = NULL; 856747b715Smrg pExaPixmap->pDamage = NULL; 866747b715Smrg 876747b715Smrg exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); 8835c4bbdfSmrg exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp); 896747b715Smrg 9035c4bbdfSmrg (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL); 916747b715Smrg 926747b715Smrg /* A scratch pixmap will become a driver pixmap right away. */ 936747b715Smrg if (!w || !h) { 9435c4bbdfSmrg exaCreateDriverPixmap_mixed(pPixmap); 9535c4bbdfSmrg pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap); 9635c4bbdfSmrg } 9735c4bbdfSmrg else { 9835c4bbdfSmrg pExaPixmap->use_gpu_copy = FALSE; 9935c4bbdfSmrg 10035c4bbdfSmrg if (w == 1 && h == 1) { 10135c4bbdfSmrg pExaPixmap->sys_ptr = malloc(paddedWidth); 10235c4bbdfSmrg 10335c4bbdfSmrg /* Set up damage tracking */ 10435c4bbdfSmrg pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL, 10535c4bbdfSmrg DamageReportNonEmpty, TRUE, 10635c4bbdfSmrg pPixmap->drawable.pScreen, 10735c4bbdfSmrg pPixmap); 10835c4bbdfSmrg 10935c4bbdfSmrg if (pExaPixmap->pDamage) { 11035c4bbdfSmrg DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage); 11135c4bbdfSmrg /* This ensures that pending damage reflects the current 11235c4bbdfSmrg * operation. This is used by exa to optimize migration. 11335c4bbdfSmrg */ 11435c4bbdfSmrg DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE); 11535c4bbdfSmrg } 11635c4bbdfSmrg } 1176747b715Smrg } 1186747b715Smrg 1196747b715Smrg /* During a fallback we must prepare access. */ 1206747b715Smrg if (pExaScr->fallback_counter) 12135c4bbdfSmrg exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); 1226747b715Smrg 1236747b715Smrg return pPixmap; 1246747b715Smrg} 1256747b715Smrg 1266747b715SmrgBool 1276747b715SmrgexaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth, 12835c4bbdfSmrg int bitsPerPixel, int devKind, void *pPixData) 1296747b715Smrg{ 1306747b715Smrg ScreenPtr pScreen; 1316747b715Smrg ExaScreenPrivPtr pExaScr; 1326747b715Smrg ExaPixmapPrivPtr pExaPixmap; 1336747b715Smrg Bool ret, has_gpu_copy; 1346747b715Smrg 1356747b715Smrg if (!pPixmap) 1366747b715Smrg return FALSE; 1376747b715Smrg 1386747b715Smrg pScreen = pPixmap->drawable.pScreen; 1396747b715Smrg pExaScr = ExaGetScreenPriv(pScreen); 1406747b715Smrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 1416747b715Smrg 1426747b715Smrg if (pPixData) { 14335c4bbdfSmrg if (pExaPixmap->driverPriv) { 14435c4bbdfSmrg if (pExaPixmap->pDamage) { 14535c4bbdfSmrg DamageDestroy(pExaPixmap->pDamage); 14635c4bbdfSmrg pExaPixmap->pDamage = NULL; 14735c4bbdfSmrg } 14835c4bbdfSmrg 14935c4bbdfSmrg pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); 15035c4bbdfSmrg pExaPixmap->driverPriv = NULL; 15135c4bbdfSmrg } 15235c4bbdfSmrg 15335c4bbdfSmrg pExaPixmap->use_gpu_copy = FALSE; 15435c4bbdfSmrg pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 1556747b715Smrg } 1566747b715Smrg 1576747b715Smrg has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); 1586747b715Smrg 1596747b715Smrg if (width <= 0) 16035c4bbdfSmrg width = pPixmap->drawable.width; 1616747b715Smrg 1626747b715Smrg if (height <= 0) 16335c4bbdfSmrg height = pPixmap->drawable.height; 1646747b715Smrg 1656747b715Smrg if (bitsPerPixel <= 0) { 16635c4bbdfSmrg if (depth <= 0) 16735c4bbdfSmrg bitsPerPixel = pPixmap->drawable.bitsPerPixel; 16835c4bbdfSmrg else 16935c4bbdfSmrg bitsPerPixel = BitsPerPixel(depth); 1706747b715Smrg } 1716747b715Smrg 1726747b715Smrg if (depth <= 0) 17335c4bbdfSmrg depth = pPixmap->drawable.depth; 1746747b715Smrg 1756747b715Smrg if (width != pPixmap->drawable.width || 17635c4bbdfSmrg height != pPixmap->drawable.height || 17735c4bbdfSmrg depth != pPixmap->drawable.depth || 17835c4bbdfSmrg bitsPerPixel != pPixmap->drawable.bitsPerPixel) { 17935c4bbdfSmrg if (pExaPixmap->driverPriv) { 18035c4bbdfSmrg if (devKind > 0) 18135c4bbdfSmrg pExaPixmap->fb_pitch = devKind; 18235c4bbdfSmrg else 18335c4bbdfSmrg exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel); 18435c4bbdfSmrg 18535c4bbdfSmrg exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel); 1866747b715Smrg RegionEmpty(&pExaPixmap->validFB); 1876747b715Smrg } 1886747b715Smrg 18935c4bbdfSmrg /* Need to re-create system copy if there's also a GPU copy */ 19035c4bbdfSmrg if (has_gpu_copy) { 19135c4bbdfSmrg if (pExaPixmap->sys_ptr) { 19235c4bbdfSmrg free(pExaPixmap->sys_ptr); 19335c4bbdfSmrg pExaPixmap->sys_ptr = NULL; 19435c4bbdfSmrg DamageDestroy(pExaPixmap->pDamage); 19535c4bbdfSmrg pExaPixmap->pDamage = NULL; 19635c4bbdfSmrg RegionEmpty(&pExaPixmap->validSys); 19735c4bbdfSmrg 19835c4bbdfSmrg if (pExaScr->deferred_mixed_pixmap == pPixmap) 19935c4bbdfSmrg pExaScr->deferred_mixed_pixmap = NULL; 20035c4bbdfSmrg } 20135c4bbdfSmrg 20235c4bbdfSmrg pExaPixmap->sys_pitch = PixmapBytePad(width, depth); 20335c4bbdfSmrg } 2046747b715Smrg } 2056747b715Smrg 2066747b715Smrg if (has_gpu_copy) { 20735c4bbdfSmrg pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; 20835c4bbdfSmrg pPixmap->devKind = pExaPixmap->fb_pitch; 20935c4bbdfSmrg } 21035c4bbdfSmrg else { 21135c4bbdfSmrg pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 21235c4bbdfSmrg pPixmap->devKind = pExaPixmap->sys_pitch; 2136747b715Smrg } 2146747b715Smrg 2156747b715Smrg /* Only pass driver pixmaps to the driver. */ 2166747b715Smrg if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) { 21735c4bbdfSmrg ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth, 21835c4bbdfSmrg bitsPerPixel, devKind, 21935c4bbdfSmrg pPixData); 22035c4bbdfSmrg if (ret == TRUE) 22135c4bbdfSmrg goto out; 2226747b715Smrg } 2236747b715Smrg 2246747b715Smrg swap(pExaScr, pScreen, ModifyPixmapHeader); 2256747b715Smrg ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, 22635c4bbdfSmrg bitsPerPixel, devKind, pPixData); 2276747b715Smrg swap(pExaScr, pScreen, ModifyPixmapHeader); 2286747b715Smrg 22935c4bbdfSmrg out: 2306747b715Smrg if (has_gpu_copy) { 23135c4bbdfSmrg pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr; 23235c4bbdfSmrg pExaPixmap->fb_pitch = pPixmap->devKind; 23335c4bbdfSmrg } 23435c4bbdfSmrg else { 23535c4bbdfSmrg pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 23635c4bbdfSmrg pExaPixmap->sys_pitch = pPixmap->devKind; 2376747b715Smrg } 2386747b715Smrg /* Always NULL this, we don't want lingering pointers. */ 2396747b715Smrg pPixmap->devPrivate.ptr = NULL; 2406747b715Smrg 2416747b715Smrg return ret; 2426747b715Smrg} 2436747b715Smrg 2446747b715SmrgBool 2456747b715SmrgexaDestroyPixmap_mixed(PixmapPtr pPixmap) 2466747b715Smrg{ 24735c4bbdfSmrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 24835c4bbdfSmrg 2496747b715Smrg ExaScreenPriv(pScreen); 2506747b715Smrg Bool ret; 2516747b715Smrg 25235c4bbdfSmrg if (pPixmap->refcnt == 1) { 25335c4bbdfSmrg ExaPixmapPriv(pPixmap); 2546747b715Smrg 25535c4bbdfSmrg exaDestroyPixmap(pPixmap); 2566747b715Smrg 25735c4bbdfSmrg if (pExaScr->deferred_mixed_pixmap == pPixmap) 25835c4bbdfSmrg pExaScr->deferred_mixed_pixmap = NULL; 2596747b715Smrg 26035c4bbdfSmrg if (pExaPixmap->driverPriv) 26135c4bbdfSmrg pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); 26235c4bbdfSmrg pExaPixmap->driverPriv = NULL; 2636747b715Smrg 26435c4bbdfSmrg if (pExaPixmap->pDamage) { 26535c4bbdfSmrg free(pExaPixmap->sys_ptr); 26635c4bbdfSmrg pExaPixmap->sys_ptr = NULL; 26735c4bbdfSmrg pExaPixmap->pDamage = NULL; 26835c4bbdfSmrg } 2696747b715Smrg } 2706747b715Smrg 2716747b715Smrg swap(pExaScr, pScreen, DestroyPixmap); 27235c4bbdfSmrg ret = pScreen->DestroyPixmap(pPixmap); 2736747b715Smrg swap(pExaScr, pScreen, DestroyPixmap); 2746747b715Smrg 2756747b715Smrg return ret; 2766747b715Smrg} 2776747b715Smrg 2786747b715SmrgBool 2796747b715SmrgexaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap) 2806747b715Smrg{ 2816747b715Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 28235c4bbdfSmrg 2836747b715Smrg ExaScreenPriv(pScreen); 2846747b715Smrg ExaPixmapPriv(pPixmap); 28535c4bbdfSmrg void *saved_ptr; 2866747b715Smrg Bool ret; 2876747b715Smrg 2886747b715Smrg if (!pExaPixmap->driverPriv) 28935c4bbdfSmrg return FALSE; 2906747b715Smrg 2916747b715Smrg saved_ptr = pPixmap->devPrivate.ptr; 2926747b715Smrg pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); 2936747b715Smrg ret = pExaScr->info->PixmapIsOffscreen(pPixmap); 2946747b715Smrg pPixmap->devPrivate.ptr = saved_ptr; 2956747b715Smrg 2966747b715Smrg return ret; 2976747b715Smrg} 29835c4bbdfSmrg 29935c4bbdfSmrgBool 300ed6184dfSmrgexaSharePixmapBacking_mixed(PixmapPtr pPixmap, ScreenPtr secondary, void **handle_p) 30135c4bbdfSmrg{ 30235c4bbdfSmrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 30335c4bbdfSmrg ExaScreenPriv(pScreen); 30435c4bbdfSmrg Bool ret = FALSE; 30535c4bbdfSmrg 30635c4bbdfSmrg exaMoveInPixmap(pPixmap); 30735c4bbdfSmrg /* get the driver to give us a handle */ 30835c4bbdfSmrg if (pExaScr->info->SharePixmapBacking) 309ed6184dfSmrg ret = pExaScr->info->SharePixmapBacking(pPixmap, secondary, handle_p); 31035c4bbdfSmrg 31135c4bbdfSmrg return ret; 31235c4bbdfSmrg} 31335c4bbdfSmrg 31435c4bbdfSmrgBool 31535c4bbdfSmrgexaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap, void *handle) 31635c4bbdfSmrg{ 31735c4bbdfSmrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 31835c4bbdfSmrg ExaScreenPriv(pScreen); 31935c4bbdfSmrg Bool ret = FALSE; 32035c4bbdfSmrg 32135c4bbdfSmrg if (pExaScr->info->SetSharedPixmapBacking) 32235c4bbdfSmrg ret = pExaScr->info->SetSharedPixmapBacking(pPixmap, handle); 32335c4bbdfSmrg 32435c4bbdfSmrg if (ret == TRUE) 32535c4bbdfSmrg exaMoveInPixmap(pPixmap); 32635c4bbdfSmrg 32735c4bbdfSmrg return ret; 32835c4bbdfSmrg} 32935c4bbdfSmrg 33035c4bbdfSmrg 331