exa_mixed.c revision 6747b715
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 + better initial placement code. 35 */ 36 37static _X_INLINE void* 38ExaGetPixmapAddress(PixmapPtr p) 39{ 40 ExaPixmapPriv(p); 41 42 return pExaPixmap->sys_ptr; 43} 44 45/** 46 * exaCreatePixmap() creates a new pixmap. 47 */ 48PixmapPtr 49exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth, 50 unsigned usage_hint) 51{ 52 PixmapPtr pPixmap; 53 ExaPixmapPrivPtr pExaPixmap; 54 int bpp; 55 size_t paddedWidth; 56 ExaScreenPriv(pScreen); 57 58 if (w > 32767 || h > 32767) 59 return NullPixmap; 60 61 swap(pExaScr, pScreen, CreatePixmap); 62 pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint); 63 swap(pExaScr, pScreen, CreatePixmap); 64 65 if (!pPixmap) 66 return NULL; 67 68 pExaPixmap = ExaGetPixmapPriv(pPixmap); 69 pExaPixmap->driverPriv = NULL; 70 71 bpp = pPixmap->drawable.bitsPerPixel; 72 73 paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); 74 if (paddedWidth / 4 > 32767 || h > 32767) 75 return NullPixmap; 76 77 /* We will allocate the system pixmap later if needed. */ 78 pPixmap->devPrivate.ptr = NULL; 79 pExaPixmap->sys_ptr = NULL; 80 pExaPixmap->sys_pitch = paddedWidth; 81 82 pExaPixmap->area = NULL; 83 pExaPixmap->fb_ptr = NULL; 84 pExaPixmap->pDamage = NULL; 85 86 exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); 87 exaSetAccelBlock(pExaScr, pExaPixmap, 88 w, h, bpp); 89 90 (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0, 91 paddedWidth, NULL); 92 93 /* A scratch pixmap will become a driver pixmap right away. */ 94 if (!w || !h) { 95 exaCreateDriverPixmap_mixed(pPixmap); 96 pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap); 97 } else { 98 pExaPixmap->use_gpu_copy = FALSE; 99 100 if (w == 1 && h == 1) { 101 pExaPixmap->sys_ptr = malloc((pPixmap->drawable.bitsPerPixel + 7) / 8); 102 103 /* Set up damage tracking */ 104 pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL, 105 DamageReportNonEmpty, TRUE, 106 pPixmap->drawable.pScreen, 107 pPixmap); 108 109 DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage); 110 /* This ensures that pending damage reflects the current operation. */ 111 /* This is used by exa to optimize migration. */ 112 DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE); 113 } 114 } 115 116 /* During a fallback we must prepare access. */ 117 if (pExaScr->fallback_counter) 118 exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); 119 120 return pPixmap; 121} 122 123Bool 124exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth, 125 int bitsPerPixel, int devKind, pointer pPixData) 126{ 127 ScreenPtr pScreen; 128 ExaScreenPrivPtr pExaScr; 129 ExaPixmapPrivPtr pExaPixmap; 130 Bool ret, has_gpu_copy; 131 132 if (!pPixmap) 133 return FALSE; 134 135 pScreen = pPixmap->drawable.pScreen; 136 pExaScr = ExaGetScreenPriv(pScreen); 137 pExaPixmap = ExaGetPixmapPriv(pPixmap); 138 139 if (pPixData) { 140 if (pExaPixmap->driverPriv) { 141 if (pExaPixmap->pDamage) { 142 DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage); 143 DamageDestroy(pExaPixmap->pDamage); 144 pExaPixmap->pDamage = NULL; 145 } 146 147 pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); 148 pExaPixmap->driverPriv = NULL; 149 } 150 151 pExaPixmap->use_gpu_copy = FALSE; 152 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 153 } 154 155 has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); 156 157 if (width <= 0) 158 width = pPixmap->drawable.width; 159 160 if (height <= 0) 161 height = pPixmap->drawable.height; 162 163 if (bitsPerPixel <= 0) { 164 if (depth <= 0) 165 bitsPerPixel = pPixmap->drawable.bitsPerPixel; 166 else 167 bitsPerPixel = BitsPerPixel(depth); 168 } 169 170 if (depth <= 0) 171 depth = pPixmap->drawable.depth; 172 173 if (width != pPixmap->drawable.width || 174 height != pPixmap->drawable.height || 175 depth != pPixmap->drawable.depth || 176 bitsPerPixel != pPixmap->drawable.bitsPerPixel) { 177 if (pExaPixmap->driverPriv) { 178 exaSetFbPitch(pExaScr, pExaPixmap, 179 width, height, bitsPerPixel); 180 181 exaSetAccelBlock(pExaScr, pExaPixmap, 182 width, height, bitsPerPixel); 183 RegionEmpty(&pExaPixmap->validFB); 184 } 185 186 /* Need to re-create system copy if there's also a GPU copy */ 187 if (has_gpu_copy && pExaPixmap->sys_ptr) { 188 free(pExaPixmap->sys_ptr); 189 pExaPixmap->sys_ptr = NULL; 190 pExaPixmap->sys_pitch = devKind > 0 ? devKind : 191 PixmapBytePad(width, depth); 192 DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage); 193 DamageDestroy(pExaPixmap->pDamage); 194 pExaPixmap->pDamage = NULL; 195 RegionEmpty(&pExaPixmap->validSys); 196 197 if (pExaScr->deferred_mixed_pixmap == pPixmap) 198 pExaScr->deferred_mixed_pixmap = NULL; 199 } 200 } 201 202 if (has_gpu_copy) { 203 pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; 204 pPixmap->devKind = pExaPixmap->fb_pitch; 205 } else { 206 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 207 pPixmap->devKind = pExaPixmap->sys_pitch; 208 } 209 210 /* Only pass driver pixmaps to the driver. */ 211 if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) { 212 ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth, 213 bitsPerPixel, devKind, pPixData); 214 if (ret == TRUE) 215 goto out; 216 } 217 218 swap(pExaScr, pScreen, ModifyPixmapHeader); 219 ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, 220 bitsPerPixel, devKind, pPixData); 221 swap(pExaScr, pScreen, ModifyPixmapHeader); 222 223out: 224 if (has_gpu_copy) { 225 pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr; 226 pExaPixmap->fb_pitch = pPixmap->devKind; 227 } else { 228 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 229 pExaPixmap->sys_pitch = pPixmap->devKind; 230 } 231 /* Always NULL this, we don't want lingering pointers. */ 232 pPixmap->devPrivate.ptr = NULL; 233 234 return ret; 235} 236 237Bool 238exaDestroyPixmap_mixed(PixmapPtr pPixmap) 239{ 240 ScreenPtr pScreen = pPixmap->drawable.pScreen; 241 ExaScreenPriv(pScreen); 242 Bool ret; 243 244 if (pPixmap->refcnt == 1) 245 { 246 ExaPixmapPriv (pPixmap); 247 248 exaDestroyPixmap(pPixmap); 249 250 if (pExaScr->deferred_mixed_pixmap == pPixmap) 251 pExaScr->deferred_mixed_pixmap = NULL; 252 253 if (pExaPixmap->driverPriv) 254 pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); 255 pExaPixmap->driverPriv = NULL; 256 257 if (pExaPixmap->pDamage) { 258 free(pExaPixmap->sys_ptr); 259 pExaPixmap->sys_ptr = NULL; 260 pExaPixmap->pDamage = NULL; 261 } 262 } 263 264 swap(pExaScr, pScreen, DestroyPixmap); 265 ret = pScreen->DestroyPixmap (pPixmap); 266 swap(pExaScr, pScreen, DestroyPixmap); 267 268 return ret; 269} 270 271Bool 272exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap) 273{ 274 ScreenPtr pScreen = pPixmap->drawable.pScreen; 275 ExaScreenPriv(pScreen); 276 ExaPixmapPriv(pPixmap); 277 pointer saved_ptr; 278 Bool ret; 279 280 if (!pExaPixmap->driverPriv) 281 return FALSE; 282 283 saved_ptr = pPixmap->devPrivate.ptr; 284 pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); 285 ret = pExaScr->info->PixmapIsOffscreen(pPixmap); 286 pPixmap->devPrivate.ptr = saved_ptr; 287 288 return ret; 289} 290