1706f2543Smrg/* 2706f2543Smrg * Copyright � 2009 Maarten Maathuis 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice (including the next 12706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the 13706f2543Smrg * Software. 14706f2543Smrg * 15706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20706f2543Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21706f2543Smrg * SOFTWARE. 22706f2543Smrg * 23706f2543Smrg */ 24706f2543Smrg 25706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 26706f2543Smrg#include <dix-config.h> 27706f2543Smrg#endif 28706f2543Smrg 29706f2543Smrg#include <string.h> 30706f2543Smrg 31706f2543Smrg#include "exa_priv.h" 32706f2543Smrg#include "exa.h" 33706f2543Smrg 34706f2543Smrg/* This file holds the driver allocated pixmaps specific implementation. */ 35706f2543Smrg 36706f2543Smrgstatic _X_INLINE void* 37706f2543SmrgExaGetPixmapAddress(PixmapPtr p) 38706f2543Smrg{ 39706f2543Smrg ExaPixmapPriv(p); 40706f2543Smrg 41706f2543Smrg return pExaPixmap->sys_ptr; 42706f2543Smrg} 43706f2543Smrg 44706f2543Smrg/** 45706f2543Smrg * exaCreatePixmap() creates a new pixmap. 46706f2543Smrg * 47706f2543Smrg * Pixmaps are always marked as pinned, because exa has no control over them. 48706f2543Smrg */ 49706f2543SmrgPixmapPtr 50706f2543SmrgexaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth, 51706f2543Smrg unsigned usage_hint) 52706f2543Smrg{ 53706f2543Smrg PixmapPtr pPixmap; 54706f2543Smrg ExaPixmapPrivPtr pExaPixmap; 55706f2543Smrg int bpp; 56706f2543Smrg size_t paddedWidth, datasize; 57706f2543Smrg ExaScreenPriv(pScreen); 58706f2543Smrg 59706f2543Smrg if (w > 32767 || h > 32767) 60706f2543Smrg return NullPixmap; 61706f2543Smrg 62706f2543Smrg swap(pExaScr, pScreen, CreatePixmap); 63706f2543Smrg pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint); 64706f2543Smrg swap(pExaScr, pScreen, CreatePixmap); 65706f2543Smrg 66706f2543Smrg if (!pPixmap) 67706f2543Smrg return NULL; 68706f2543Smrg 69706f2543Smrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 70706f2543Smrg pExaPixmap->driverPriv = NULL; 71706f2543Smrg 72706f2543Smrg bpp = pPixmap->drawable.bitsPerPixel; 73706f2543Smrg 74706f2543Smrg /* Set this before driver hooks, to allow for driver pixmaps without gpu 75706f2543Smrg * memory to back it. These pixmaps have a valid pointer at all times. 76706f2543Smrg */ 77706f2543Smrg pPixmap->devPrivate.ptr = NULL; 78706f2543Smrg 79706f2543Smrg if (pExaScr->info->CreatePixmap2) { 80706f2543Smrg int new_pitch = 0; 81706f2543Smrg pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, &new_pitch); 82706f2543Smrg paddedWidth = pExaPixmap->fb_pitch = new_pitch; 83706f2543Smrg } 84706f2543Smrg else { 85706f2543Smrg paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); 86706f2543Smrg if (paddedWidth / 4 > 32767 || h > 32767) 87706f2543Smrg return NullPixmap; 88706f2543Smrg 89706f2543Smrg exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); 90706f2543Smrg 91706f2543Smrg if (paddedWidth < pExaPixmap->fb_pitch) 92706f2543Smrg paddedWidth = pExaPixmap->fb_pitch; 93706f2543Smrg datasize = h * paddedWidth; 94706f2543Smrg pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0); 95706f2543Smrg } 96706f2543Smrg 97706f2543Smrg if (!pExaPixmap->driverPriv) { 98706f2543Smrg swap(pExaScr, pScreen, DestroyPixmap); 99706f2543Smrg pScreen->DestroyPixmap (pPixmap); 100706f2543Smrg swap(pExaScr, pScreen, DestroyPixmap); 101706f2543Smrg return NULL; 102706f2543Smrg } 103706f2543Smrg 104706f2543Smrg /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */ 105706f2543Smrg pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 106706f2543Smrg pExaPixmap->fb_ptr = NULL; 107706f2543Smrg pExaPixmap->pDamage = NULL; 108706f2543Smrg pExaPixmap->sys_ptr = NULL; 109706f2543Smrg 110706f2543Smrg (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0, 111706f2543Smrg paddedWidth, NULL); 112706f2543Smrg 113706f2543Smrg pExaPixmap->area = NULL; 114706f2543Smrg 115706f2543Smrg exaSetAccelBlock(pExaScr, pExaPixmap, 116706f2543Smrg w, h, bpp); 117706f2543Smrg 118706f2543Smrg pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap); 119706f2543Smrg 120706f2543Smrg /* During a fallback we must prepare access. */ 121706f2543Smrg if (pExaScr->fallback_counter) 122706f2543Smrg exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); 123706f2543Smrg 124706f2543Smrg return pPixmap; 125706f2543Smrg} 126706f2543Smrg 127706f2543SmrgBool 128706f2543SmrgexaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, int depth, 129706f2543Smrg int bitsPerPixel, int devKind, pointer pPixData) 130706f2543Smrg{ 131706f2543Smrg ScreenPtr pScreen; 132706f2543Smrg ExaScreenPrivPtr pExaScr; 133706f2543Smrg ExaPixmapPrivPtr pExaPixmap; 134706f2543Smrg Bool ret; 135706f2543Smrg 136706f2543Smrg if (!pPixmap) 137706f2543Smrg return FALSE; 138706f2543Smrg 139706f2543Smrg pScreen = pPixmap->drawable.pScreen; 140706f2543Smrg pExaScr = ExaGetScreenPriv(pScreen); 141706f2543Smrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 142706f2543Smrg 143706f2543Smrg if (pExaPixmap) { 144706f2543Smrg if (pPixData) 145706f2543Smrg pExaPixmap->sys_ptr = pPixData; 146706f2543Smrg 147706f2543Smrg if (devKind > 0) 148706f2543Smrg pExaPixmap->sys_pitch = devKind; 149706f2543Smrg 150706f2543Smrg if (width > 0 && height > 0 && bitsPerPixel > 0) { 151706f2543Smrg exaSetFbPitch(pExaScr, pExaPixmap, 152706f2543Smrg width, height, bitsPerPixel); 153706f2543Smrg 154706f2543Smrg exaSetAccelBlock(pExaScr, pExaPixmap, 155706f2543Smrg width, height, bitsPerPixel); 156706f2543Smrg } 157706f2543Smrg } 158706f2543Smrg 159706f2543Smrg if (pExaScr->info->ModifyPixmapHeader) { 160706f2543Smrg ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth, 161706f2543Smrg bitsPerPixel, devKind, pPixData); 162706f2543Smrg /* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL. 163706f2543Smrg * If pPixmap->devPrivate.ptr is non-NULL, then we've got a 164706f2543Smrg * !has_gpu_copy pixmap. We need to store the pointer, 165706f2543Smrg * because PrepareAccess won't be called. 166706f2543Smrg */ 167706f2543Smrg if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) { 168706f2543Smrg pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 169706f2543Smrg pExaPixmap->sys_pitch = pPixmap->devKind; 170706f2543Smrg } 171706f2543Smrg if (ret == TRUE) 172706f2543Smrg goto out; 173706f2543Smrg } 174706f2543Smrg 175706f2543Smrg swap(pExaScr, pScreen, ModifyPixmapHeader); 176706f2543Smrg ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, 177706f2543Smrg bitsPerPixel, devKind, pPixData); 178706f2543Smrg swap(pExaScr, pScreen, ModifyPixmapHeader); 179706f2543Smrg 180706f2543Smrgout: 181706f2543Smrg /* Always NULL this, we don't want lingering pointers. */ 182706f2543Smrg pPixmap->devPrivate.ptr = NULL; 183706f2543Smrg 184706f2543Smrg return ret; 185706f2543Smrg} 186706f2543Smrg 187706f2543SmrgBool 188706f2543SmrgexaDestroyPixmap_driver (PixmapPtr pPixmap) 189706f2543Smrg{ 190706f2543Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 191706f2543Smrg ExaScreenPriv(pScreen); 192706f2543Smrg Bool ret; 193706f2543Smrg 194706f2543Smrg if (pPixmap->refcnt == 1) 195706f2543Smrg { 196706f2543Smrg ExaPixmapPriv (pPixmap); 197706f2543Smrg 198706f2543Smrg exaDestroyPixmap(pPixmap); 199706f2543Smrg 200706f2543Smrg if (pExaPixmap->driverPriv) 201706f2543Smrg pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); 202706f2543Smrg pExaPixmap->driverPriv = NULL; 203706f2543Smrg } 204706f2543Smrg 205706f2543Smrg swap(pExaScr, pScreen, DestroyPixmap); 206706f2543Smrg ret = pScreen->DestroyPixmap (pPixmap); 207706f2543Smrg swap(pExaScr, pScreen, DestroyPixmap); 208706f2543Smrg 209706f2543Smrg return ret; 210706f2543Smrg} 211706f2543Smrg 212706f2543SmrgBool 213706f2543SmrgexaPixmapHasGpuCopy_driver(PixmapPtr pPixmap) 214706f2543Smrg{ 215706f2543Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 216706f2543Smrg ExaScreenPriv(pScreen); 217706f2543Smrg pointer saved_ptr; 218706f2543Smrg Bool ret; 219706f2543Smrg 220706f2543Smrg saved_ptr = pPixmap->devPrivate.ptr; 221706f2543Smrg pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); 222706f2543Smrg ret = pExaScr->info->PixmapIsOffscreen(pPixmap); 223706f2543Smrg pPixmap->devPrivate.ptr = saved_ptr; 224706f2543Smrg 225706f2543Smrg return ret; 226706f2543Smrg} 227