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 classic exa specific implementation. */ 35 36static _X_INLINE void* 37ExaGetPixmapAddress(PixmapPtr p) 38{ 39 ExaPixmapPriv(p); 40 41 if (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr) 42 return pExaPixmap->fb_ptr; 43 else 44 return pExaPixmap->sys_ptr; 45} 46 47/** 48 * exaCreatePixmap() creates a new pixmap. 49 * 50 * If width and height are 0, this won't be a full-fledged pixmap and it will 51 * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because 52 * ModifyPixmapHeader() would break migration. These types of pixmaps are used 53 * for scratch pixmaps, or to represent the visible screen. 54 */ 55PixmapPtr 56exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth, 57 unsigned usage_hint) 58{ 59 PixmapPtr pPixmap; 60 ExaPixmapPrivPtr pExaPixmap; 61 BoxRec box; 62 int bpp; 63 ExaScreenPriv(pScreen); 64 65 if (w > 32767 || h > 32767) 66 return NullPixmap; 67 68 swap(pExaScr, pScreen, CreatePixmap); 69 pPixmap = pScreen->CreatePixmap (pScreen, w, h, depth, usage_hint); 70 swap(pExaScr, pScreen, CreatePixmap); 71 72 if (!pPixmap) 73 return NULL; 74 75 pExaPixmap = ExaGetPixmapPriv(pPixmap); 76 pExaPixmap->driverPriv = NULL; 77 78 bpp = pPixmap->drawable.bitsPerPixel; 79 80 pExaPixmap->driverPriv = NULL; 81 /* Scratch pixmaps may have w/h equal to zero, and may not be 82 * migrated. 83 */ 84 if (!w || !h) 85 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 86 else 87 pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; 88 89 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 90 pExaPixmap->sys_pitch = pPixmap->devKind; 91 92 pPixmap->devPrivate.ptr = NULL; 93 pExaPixmap->use_gpu_copy = FALSE; 94 95 pExaPixmap->fb_ptr = NULL; 96 exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); 97 pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; 98 99 if (pExaPixmap->fb_pitch > 131071) { 100 swap(pExaScr, pScreen, DestroyPixmap); 101 pScreen->DestroyPixmap (pPixmap); 102 swap(pExaScr, pScreen, DestroyPixmap); 103 return NULL; 104 } 105 106 /* Set up damage tracking */ 107 pExaPixmap->pDamage = DamageCreate (NULL, NULL, 108 DamageReportNone, TRUE, 109 pScreen, pPixmap); 110 111 if (pExaPixmap->pDamage == NULL) { 112 swap(pExaScr, pScreen, DestroyPixmap); 113 pScreen->DestroyPixmap (pPixmap); 114 swap(pExaScr, pScreen, DestroyPixmap); 115 return NULL; 116 } 117 118 DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage); 119 /* This ensures that pending damage reflects the current operation. */ 120 /* This is used by exa to optimize migration. */ 121 DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE); 122 123 pExaPixmap->area = NULL; 124 125 /* We set the initial pixmap as completely valid for a simple reason. 126 * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which 127 * could form single pixel rects as part of a region. Setting the complete region 128 * as valid is a natural defragmentation of the region. 129 */ 130 box.x1 = 0; 131 box.y1 = 0; 132 box.x2 = w; 133 box.y2 = h; 134 RegionInit(&pExaPixmap->validSys, &box, 0); 135 RegionInit(&pExaPixmap->validFB, &box, 0); 136 137 exaSetAccelBlock(pExaScr, pExaPixmap, 138 w, h, bpp); 139 140 /* During a fallback we must prepare access. */ 141 if (pExaScr->fallback_counter) 142 exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); 143 144 return pPixmap; 145} 146 147Bool 148exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, int depth, 149 int bitsPerPixel, int devKind, pointer pPixData) 150{ 151 ScreenPtr pScreen; 152 ExaScreenPrivPtr pExaScr; 153 ExaPixmapPrivPtr pExaPixmap; 154 Bool ret; 155 156 if (!pPixmap) 157 return FALSE; 158 159 pScreen = pPixmap->drawable.pScreen; 160 pExaScr = ExaGetScreenPriv(pScreen); 161 pExaPixmap = ExaGetPixmapPriv(pPixmap); 162 163 if (pExaPixmap) { 164 if (pPixData) 165 pExaPixmap->sys_ptr = pPixData; 166 167 if (devKind > 0) 168 pExaPixmap->sys_pitch = devKind; 169 170 /* Classic EXA: 171 * - Framebuffer. 172 * - Scratch pixmap with gpu memory. 173 */ 174 if (pExaScr->info->memoryBase && pPixData) { 175 if ((CARD8 *)pPixData >= pExaScr->info->memoryBase && 176 ((CARD8 *)pPixData - pExaScr->info->memoryBase) < 177 pExaScr->info->memorySize) { 178 pExaPixmap->fb_ptr = pPixData; 179 pExaPixmap->fb_pitch = devKind; 180 pExaPixmap->use_gpu_copy = TRUE; 181 } 182 } 183 184 if (width > 0 && height > 0 && bitsPerPixel > 0) { 185 exaSetFbPitch(pExaScr, pExaPixmap, 186 width, height, bitsPerPixel); 187 188 exaSetAccelBlock(pExaScr, pExaPixmap, 189 width, height, bitsPerPixel); 190 } 191 192 /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or 193 * gpu memory, so there's no need to track damage. 194 */ 195 if (pExaPixmap->pDamage) { 196 DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage); 197 DamageDestroy(pExaPixmap->pDamage); 198 pExaPixmap->pDamage = NULL; 199 } 200 } 201 202 swap(pExaScr, pScreen, ModifyPixmapHeader); 203 ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, 204 bitsPerPixel, devKind, pPixData); 205 swap(pExaScr, pScreen, ModifyPixmapHeader); 206 207 /* Always NULL this, we don't want lingering pointers. */ 208 pPixmap->devPrivate.ptr = NULL; 209 210 return ret; 211} 212 213Bool 214exaDestroyPixmap_classic (PixmapPtr pPixmap) 215{ 216 ScreenPtr pScreen = pPixmap->drawable.pScreen; 217 ExaScreenPriv(pScreen); 218 Bool ret; 219 220 if (pPixmap->refcnt == 1) 221 { 222 ExaPixmapPriv (pPixmap); 223 224 exaDestroyPixmap(pPixmap); 225 226 if (pExaPixmap->area) 227 { 228 DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", 229 (void*)pPixmap->drawable.id, 230 ExaGetPixmapPriv(pPixmap)->area->offset, 231 pPixmap->drawable.width, 232 pPixmap->drawable.height)); 233 /* Free the offscreen area */ 234 exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area); 235 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 236 pPixmap->devKind = pExaPixmap->sys_pitch; 237 } 238 RegionUninit(&pExaPixmap->validSys); 239 RegionUninit(&pExaPixmap->validFB); 240 } 241 242 swap(pExaScr, pScreen, DestroyPixmap); 243 ret = pScreen->DestroyPixmap (pPixmap); 244 swap(pExaScr, pScreen, DestroyPixmap); 245 246 return ret; 247} 248 249Bool 250exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap) 251{ 252 ScreenPtr pScreen = pPixmap->drawable.pScreen; 253 ExaScreenPriv(pScreen); 254 ExaPixmapPriv(pPixmap); 255 Bool ret; 256 257 if (pExaScr->info->PixmapIsOffscreen) { 258 void* old_ptr = pPixmap->devPrivate.ptr; 259 pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); 260 ret = pExaScr->info->PixmapIsOffscreen(pPixmap); 261 pPixmap->devPrivate.ptr = old_ptr; 262 } else 263 ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr); 264 265 return ret; 266} 267