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