1/* 2 * Copyright © 2009 Maarten Maathuis 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 */ 24 25#ifdef HAVE_DIX_CONFIG_H 26#include <dix-config.h> 27#endif 28 29#include <string.h> 30 31#include "exa_priv.h" 32#include "exa.h" 33 34/* This file holds the driver allocated pixmaps specific implementation. */ 35 36static _X_INLINE void * 37ExaGetPixmapAddress(PixmapPtr p) 38{ 39 ExaPixmapPriv(p); 40 41 return pExaPixmap->sys_ptr; 42} 43 44/** 45 * exaCreatePixmap() creates a new pixmap. 46 * 47 * Pixmaps are always marked as pinned, because exa has no control over them. 48 */ 49PixmapPtr 50exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth, 51 unsigned usage_hint) 52{ 53 PixmapPtr pPixmap; 54 ExaPixmapPrivPtr pExaPixmap; 55 int bpp; 56 size_t paddedWidth, datasize; 57 58 ExaScreenPriv(pScreen); 59 60 if (w > 32767 || h > 32767) 61 return NullPixmap; 62 63 swap(pExaScr, pScreen, CreatePixmap); 64 pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint); 65 swap(pExaScr, pScreen, CreatePixmap); 66 67 if (!pPixmap) 68 return NULL; 69 70 pExaPixmap = ExaGetPixmapPriv(pPixmap); 71 pExaPixmap->driverPriv = NULL; 72 73 bpp = pPixmap->drawable.bitsPerPixel; 74 75 /* Set this before driver hooks, to allow for driver pixmaps without gpu 76 * memory to back it. These pixmaps have a valid pointer at all times. 77 */ 78 pPixmap->devPrivate.ptr = NULL; 79 80 if (pExaScr->info->CreatePixmap2) { 81 int new_pitch = 0; 82 83 pExaPixmap->driverPriv = 84 pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, 85 &new_pitch); 86 paddedWidth = pExaPixmap->fb_pitch = new_pitch; 87 } 88 else { 89 paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); 90 if (paddedWidth / 4 > 32767 || h > 32767) 91 return NullPixmap; 92 93 exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); 94 95 if (paddedWidth < pExaPixmap->fb_pitch) 96 paddedWidth = pExaPixmap->fb_pitch; 97 datasize = h * paddedWidth; 98 pExaPixmap->driverPriv = 99 pExaScr->info->CreatePixmap(pScreen, datasize, 0); 100 } 101 102 if (!pExaPixmap->driverPriv) { 103 swap(pExaScr, pScreen, DestroyPixmap); 104 pScreen->DestroyPixmap(pPixmap); 105 swap(pExaScr, pScreen, DestroyPixmap); 106 return NULL; 107 } 108 109 /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */ 110 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 111 pExaPixmap->fb_ptr = NULL; 112 pExaPixmap->pDamage = NULL; 113 pExaPixmap->sys_ptr = NULL; 114 115 (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL); 116 117 pExaPixmap->area = NULL; 118 119 exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp); 120 121 pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap); 122 123 /* During a fallback we must prepare access. */ 124 if (pExaScr->fallback_counter) 125 exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); 126 127 return pPixmap; 128} 129 130Bool 131exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, 132 int depth, int bitsPerPixel, int devKind, 133 void *pPixData) 134{ 135 ScreenPtr pScreen; 136 ExaScreenPrivPtr pExaScr; 137 ExaPixmapPrivPtr pExaPixmap; 138 Bool ret; 139 140 if (!pPixmap) 141 return FALSE; 142 143 pScreen = pPixmap->drawable.pScreen; 144 pExaScr = ExaGetScreenPriv(pScreen); 145 pExaPixmap = ExaGetPixmapPriv(pPixmap); 146 147 if (pExaPixmap) { 148 if (pPixData) 149 pExaPixmap->sys_ptr = pPixData; 150 151 if (devKind > 0) 152 pExaPixmap->sys_pitch = devKind; 153 154 if (width > 0 && height > 0 && bitsPerPixel > 0) { 155 exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel); 156 157 exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel); 158 } 159 } 160 161 if (pExaScr->info->ModifyPixmapHeader) { 162 ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth, 163 bitsPerPixel, devKind, 164 pPixData); 165 /* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL. 166 * If pPixmap->devPrivate.ptr is non-NULL, then we've got a 167 * !has_gpu_copy pixmap. We need to store the pointer, 168 * because PrepareAccess won't be called. 169 */ 170 if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) { 171 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 172 pExaPixmap->sys_pitch = pPixmap->devKind; 173 } 174 if (ret == TRUE) 175 goto out; 176 } 177 178 swap(pExaScr, pScreen, ModifyPixmapHeader); 179 ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, 180 bitsPerPixel, devKind, pPixData); 181 swap(pExaScr, pScreen, ModifyPixmapHeader); 182 183 out: 184 /* Always NULL this, we don't want lingering pointers. */ 185 pPixmap->devPrivate.ptr = NULL; 186 187 return ret; 188} 189 190Bool 191exaDestroyPixmap_driver(PixmapPtr pPixmap) 192{ 193 ScreenPtr pScreen = pPixmap->drawable.pScreen; 194 195 ExaScreenPriv(pScreen); 196 Bool ret; 197 198 if (pPixmap->refcnt == 1) { 199 ExaPixmapPriv(pPixmap); 200 201 exaDestroyPixmap(pPixmap); 202 203 if (pExaPixmap->driverPriv) 204 pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); 205 pExaPixmap->driverPriv = NULL; 206 } 207 208 swap(pExaScr, pScreen, DestroyPixmap); 209 ret = pScreen->DestroyPixmap(pPixmap); 210 swap(pExaScr, pScreen, DestroyPixmap); 211 212 return ret; 213} 214 215Bool 216exaPixmapHasGpuCopy_driver(PixmapPtr pPixmap) 217{ 218 ScreenPtr pScreen = pPixmap->drawable.pScreen; 219 220 ExaScreenPriv(pScreen); 221 void *saved_ptr; 222 Bool ret; 223 224 saved_ptr = pPixmap->devPrivate.ptr; 225 pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); 226 ret = pExaScr->info->PixmapIsOffscreen(pPixmap); 227 pPixmap->devPrivate.ptr = saved_ptr; 228 229 return ret; 230} 231