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 specific implementation. */ 356747b715Smrg 3635c4bbdfSmrgstatic _X_INLINE void * 376747b715SmrgExaGetPixmapAddress(PixmapPtr p) 386747b715Smrg{ 396747b715Smrg ExaPixmapPriv(p); 406747b715Smrg 416747b715Smrg return pExaPixmap->sys_ptr; 426747b715Smrg} 436747b715Smrg 446747b715Smrg/** 456747b715Smrg * exaCreatePixmap() creates a new pixmap. 466747b715Smrg * 476747b715Smrg * Pixmaps are always marked as pinned, because exa has no control over them. 486747b715Smrg */ 496747b715SmrgPixmapPtr 506747b715SmrgexaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth, 5135c4bbdfSmrg unsigned usage_hint) 526747b715Smrg{ 536747b715Smrg PixmapPtr pPixmap; 5435c4bbdfSmrg ExaPixmapPrivPtr pExaPixmap; 556747b715Smrg int bpp; 566747b715Smrg size_t paddedWidth, datasize; 5735c4bbdfSmrg 586747b715Smrg ExaScreenPriv(pScreen); 596747b715Smrg 606747b715Smrg if (w > 32767 || h > 32767) 6135c4bbdfSmrg return NullPixmap; 626747b715Smrg 636747b715Smrg swap(pExaScr, pScreen, CreatePixmap); 646747b715Smrg pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint); 656747b715Smrg swap(pExaScr, pScreen, CreatePixmap); 666747b715Smrg 676747b715Smrg if (!pPixmap) 686747b715Smrg return NULL; 696747b715Smrg 706747b715Smrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 716747b715Smrg pExaPixmap->driverPriv = NULL; 726747b715Smrg 736747b715Smrg bpp = pPixmap->drawable.bitsPerPixel; 746747b715Smrg 756747b715Smrg /* Set this before driver hooks, to allow for driver pixmaps without gpu 766747b715Smrg * memory to back it. These pixmaps have a valid pointer at all times. 776747b715Smrg */ 786747b715Smrg pPixmap->devPrivate.ptr = NULL; 796747b715Smrg 806747b715Smrg if (pExaScr->info->CreatePixmap2) { 8135c4bbdfSmrg int new_pitch = 0; 8235c4bbdfSmrg 8335c4bbdfSmrg pExaPixmap->driverPriv = 8435c4bbdfSmrg pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, 8535c4bbdfSmrg &new_pitch); 8635c4bbdfSmrg paddedWidth = pExaPixmap->fb_pitch = new_pitch; 876747b715Smrg } 886747b715Smrg else { 8935c4bbdfSmrg paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); 9035c4bbdfSmrg if (paddedWidth / 4 > 32767 || h > 32767) 9135c4bbdfSmrg return NullPixmap; 926747b715Smrg 9335c4bbdfSmrg exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); 946747b715Smrg 9535c4bbdfSmrg if (paddedWidth < pExaPixmap->fb_pitch) 9635c4bbdfSmrg paddedWidth = pExaPixmap->fb_pitch; 9735c4bbdfSmrg datasize = h * paddedWidth; 9835c4bbdfSmrg pExaPixmap->driverPriv = 9935c4bbdfSmrg pExaScr->info->CreatePixmap(pScreen, datasize, 0); 1006747b715Smrg } 1016747b715Smrg 1026747b715Smrg if (!pExaPixmap->driverPriv) { 10335c4bbdfSmrg swap(pExaScr, pScreen, DestroyPixmap); 10435c4bbdfSmrg pScreen->DestroyPixmap(pPixmap); 10535c4bbdfSmrg swap(pExaScr, pScreen, DestroyPixmap); 10635c4bbdfSmrg return NULL; 1076747b715Smrg } 1086747b715Smrg 1096747b715Smrg /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */ 1106747b715Smrg pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 1116747b715Smrg pExaPixmap->fb_ptr = NULL; 1126747b715Smrg pExaPixmap->pDamage = NULL; 1136747b715Smrg pExaPixmap->sys_ptr = NULL; 1146747b715Smrg 11535c4bbdfSmrg (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL); 1166747b715Smrg 1176747b715Smrg pExaPixmap->area = NULL; 1186747b715Smrg 11935c4bbdfSmrg exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp); 1206747b715Smrg 1219ace9065Smrg pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap); 1229ace9065Smrg 1236747b715Smrg /* During a fallback we must prepare access. */ 1246747b715Smrg if (pExaScr->fallback_counter) 12535c4bbdfSmrg exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); 1266747b715Smrg 1276747b715Smrg return pPixmap; 1286747b715Smrg} 1296747b715Smrg 1306747b715SmrgBool 13135c4bbdfSmrgexaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, 13235c4bbdfSmrg int depth, int bitsPerPixel, int devKind, 13335c4bbdfSmrg void *pPixData) 1346747b715Smrg{ 1356747b715Smrg ScreenPtr pScreen; 1366747b715Smrg ExaScreenPrivPtr pExaScr; 1376747b715Smrg ExaPixmapPrivPtr pExaPixmap; 1386747b715Smrg Bool ret; 1396747b715Smrg 1406747b715Smrg if (!pPixmap) 1416747b715Smrg return FALSE; 1426747b715Smrg 1436747b715Smrg pScreen = pPixmap->drawable.pScreen; 1446747b715Smrg pExaScr = ExaGetScreenPriv(pScreen); 1456747b715Smrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 1466747b715Smrg 1476747b715Smrg if (pExaPixmap) { 1486747b715Smrg if (pPixData) 1496747b715Smrg pExaPixmap->sys_ptr = pPixData; 1506747b715Smrg 1516747b715Smrg if (devKind > 0) 1526747b715Smrg pExaPixmap->sys_pitch = devKind; 1536747b715Smrg 1546747b715Smrg if (width > 0 && height > 0 && bitsPerPixel > 0) { 15535c4bbdfSmrg exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel); 1566747b715Smrg 15735c4bbdfSmrg exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel); 1586747b715Smrg } 1596747b715Smrg } 1606747b715Smrg 1616747b715Smrg if (pExaScr->info->ModifyPixmapHeader) { 16235c4bbdfSmrg ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth, 16335c4bbdfSmrg bitsPerPixel, devKind, 16435c4bbdfSmrg pPixData); 16535c4bbdfSmrg /* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL. 16635c4bbdfSmrg * If pPixmap->devPrivate.ptr is non-NULL, then we've got a 16735c4bbdfSmrg * !has_gpu_copy pixmap. We need to store the pointer, 16835c4bbdfSmrg * because PrepareAccess won't be called. 16935c4bbdfSmrg */ 17035c4bbdfSmrg if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) { 17135c4bbdfSmrg pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 17235c4bbdfSmrg pExaPixmap->sys_pitch = pPixmap->devKind; 17335c4bbdfSmrg } 17435c4bbdfSmrg if (ret == TRUE) 17535c4bbdfSmrg goto out; 1766747b715Smrg } 1776747b715Smrg 1786747b715Smrg swap(pExaScr, pScreen, ModifyPixmapHeader); 1796747b715Smrg ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, 18035c4bbdfSmrg bitsPerPixel, devKind, pPixData); 1816747b715Smrg swap(pExaScr, pScreen, ModifyPixmapHeader); 1826747b715Smrg 18335c4bbdfSmrg out: 1846747b715Smrg /* Always NULL this, we don't want lingering pointers. */ 1856747b715Smrg pPixmap->devPrivate.ptr = NULL; 1866747b715Smrg 1876747b715Smrg return ret; 1886747b715Smrg} 1896747b715Smrg 1906747b715SmrgBool 19135c4bbdfSmrgexaDestroyPixmap_driver(PixmapPtr pPixmap) 1926747b715Smrg{ 19335c4bbdfSmrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 19435c4bbdfSmrg 1956747b715Smrg ExaScreenPriv(pScreen); 1966747b715Smrg Bool ret; 1976747b715Smrg 19835c4bbdfSmrg if (pPixmap->refcnt == 1) { 19935c4bbdfSmrg ExaPixmapPriv(pPixmap); 2006747b715Smrg 20135c4bbdfSmrg exaDestroyPixmap(pPixmap); 2026747b715Smrg 20335c4bbdfSmrg if (pExaPixmap->driverPriv) 20435c4bbdfSmrg pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); 20535c4bbdfSmrg pExaPixmap->driverPriv = NULL; 2066747b715Smrg } 2076747b715Smrg 2086747b715Smrg swap(pExaScr, pScreen, DestroyPixmap); 20935c4bbdfSmrg ret = pScreen->DestroyPixmap(pPixmap); 2106747b715Smrg swap(pExaScr, pScreen, DestroyPixmap); 2116747b715Smrg 2126747b715Smrg return ret; 2136747b715Smrg} 2146747b715Smrg 2156747b715SmrgBool 2166747b715SmrgexaPixmapHasGpuCopy_driver(PixmapPtr pPixmap) 2176747b715Smrg{ 2186747b715Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 21935c4bbdfSmrg 2206747b715Smrg ExaScreenPriv(pScreen); 22135c4bbdfSmrg void *saved_ptr; 2226747b715Smrg Bool ret; 2236747b715Smrg 2246747b715Smrg saved_ptr = pPixmap->devPrivate.ptr; 2256747b715Smrg pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); 2266747b715Smrg ret = pExaScr->info->PixmapIsOffscreen(pPixmap); 2276747b715Smrg pPixmap->devPrivate.ptr = saved_ptr; 2286747b715Smrg 2296747b715Smrg return ret; 2306747b715Smrg} 231