exa_unaccel.c revision 4642e01f
1/* 2 * 3 * Copyright � 1999 Keith Packard 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of Keith Packard not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. Keith Packard makes no 12 * representations about the suitability of this software for any purpose. It 13 * is provided "as is" without express or implied warranty. 14 * 15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24#include "exa_priv.h" 25 26#ifdef RENDER 27#include "mipict.h" 28#endif 29 30/* 31 * These functions wrap the low-level fb rendering functions and 32 * synchronize framebuffer/accelerated drawing by stalling until 33 * the accelerator is idle 34 */ 35 36/** 37 * Calls exaPrepareAccess with EXA_PREPARE_SRC for the tile, if that is the 38 * current fill style. 39 * 40 * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are 41 * 1bpp and never in fb, so we don't worry about them. 42 * We should worry about them for completeness sake and going forward. 43 */ 44void 45exaPrepareAccessGC(GCPtr pGC) 46{ 47 if (pGC->stipple) 48 exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); 49 if (pGC->fillStyle == FillTiled) 50 exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); 51} 52 53/** 54 * Finishes access to the tile in the GC, if used. 55 */ 56void 57exaFinishAccessGC(GCPtr pGC) 58{ 59 if (pGC->fillStyle == FillTiled) 60 exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); 61 if (pGC->stipple) 62 exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); 63} 64 65#if DEBUG_TRACE_FALL 66char 67exaDrawableLocation(DrawablePtr pDrawable) 68{ 69 return exaDrawableIsOffscreen(pDrawable) ? 's' : 'm'; 70} 71#endif /* DEBUG_TRACE_FALL */ 72 73void 74ExaCheckFillSpans (DrawablePtr pDrawable, GCPtr pGC, int nspans, 75 DDXPointPtr ppt, int *pwidth, int fSorted) 76{ 77 EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); 78 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 79 exaPrepareAccessGC (pGC); 80 fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted); 81 exaFinishAccessGC (pGC); 82 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 83} 84 85void 86ExaCheckSetSpans (DrawablePtr pDrawable, GCPtr pGC, char *psrc, 87 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) 88{ 89 EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); 90 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 91 fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); 92 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 93} 94 95void 96ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, 97 int x, int y, int w, int h, int leftPad, int format, 98 char *bits) 99{ 100 ExaPixmapPriv(exaGetDrawablePixmap(pDrawable)); 101 102 EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); 103 if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle, 104 pGC->alu)) 105 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 106 else 107 exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pExaPixmap->pDamage ? 108 DamagePendingRegion(pExaPixmap->pDamage) : NULL); 109 fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); 110 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 111} 112 113RegionPtr 114ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 115 int srcx, int srcy, int w, int h, int dstx, int dsty) 116{ 117 RegionPtr ret; 118 119 EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, 120 exaDrawableLocation(pSrc), exaDrawableLocation(pDst))); 121 exaPrepareAccess (pDst, EXA_PREPARE_DEST); 122 exaPrepareAccess (pSrc, EXA_PREPARE_SRC); 123 ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); 124 exaFinishAccess (pSrc, EXA_PREPARE_SRC); 125 exaFinishAccess (pDst, EXA_PREPARE_DEST); 126 127 return ret; 128} 129 130RegionPtr 131ExaCheckCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 132 int srcx, int srcy, int w, int h, int dstx, int dsty, 133 unsigned long bitPlane) 134{ 135 RegionPtr ret; 136 137 EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, 138 exaDrawableLocation(pSrc), exaDrawableLocation(pDst))); 139 exaPrepareAccess (pDst, EXA_PREPARE_DEST); 140 exaPrepareAccess (pSrc, EXA_PREPARE_SRC); 141 ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 142 bitPlane); 143 exaFinishAccess (pSrc, EXA_PREPARE_SRC); 144 exaFinishAccess (pDst, EXA_PREPARE_DEST); 145 146 return ret; 147} 148 149void 150ExaCheckPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 151 DDXPointPtr pptInit) 152{ 153 EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); 154 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 155 fbPolyPoint (pDrawable, pGC, mode, npt, pptInit); 156 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 157} 158 159void 160ExaCheckPolylines (DrawablePtr pDrawable, GCPtr pGC, 161 int mode, int npt, DDXPointPtr ppt) 162{ 163 EXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n", 164 pDrawable, exaDrawableLocation(pDrawable), 165 pGC->lineWidth, mode, npt)); 166 167 if (pGC->lineWidth == 0) { 168 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 169 exaPrepareAccessGC (pGC); 170 fbPolyLine (pDrawable, pGC, mode, npt, ppt); 171 exaFinishAccessGC (pGC); 172 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 173 return; 174 } 175 /* fb calls mi functions in the lineWidth != 0 case. */ 176 fbPolyLine (pDrawable, pGC, mode, npt, ppt); 177} 178 179void 180ExaCheckPolySegment (DrawablePtr pDrawable, GCPtr pGC, 181 int nsegInit, xSegment *pSegInit) 182{ 183 EXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable, 184 exaDrawableLocation(pDrawable), pGC->lineWidth, nsegInit)); 185 if (pGC->lineWidth == 0) { 186 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 187 exaPrepareAccessGC (pGC); 188 fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); 189 exaFinishAccessGC (pGC); 190 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 191 return; 192 } 193 /* fb calls mi functions in the lineWidth != 0 case. */ 194 fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); 195} 196 197void 198ExaCheckPolyArc (DrawablePtr pDrawable, GCPtr pGC, 199 int narcs, xArc *pArcs) 200{ 201 EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); 202 203 /* Disable this as fbPolyArc can call miZeroPolyArc which in turn 204 * can call accelerated functions, that as yet, haven't been notified 205 * with exaFinishAccess(). 206 */ 207#if 0 208 if (pGC->lineWidth == 0) 209 { 210 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 211 exaPrepareAccessGC (pGC); 212 fbPolyArc (pDrawable, pGC, narcs, pArcs); 213 exaFinishAccessGC (pGC); 214 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 215 return; 216 } 217#endif 218 miPolyArc (pDrawable, pGC, narcs, pArcs); 219} 220 221void 222ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, 223 int nrect, xRectangle *prect) 224{ 225 EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); 226 227 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 228 exaPrepareAccessGC (pGC); 229 fbPolyFillRect (pDrawable, pGC, nrect, prect); 230 exaFinishAccessGC (pGC); 231 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 232} 233 234void 235ExaCheckImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, 236 int x, int y, unsigned int nglyph, 237 CharInfoPtr *ppci, pointer pglyphBase) 238{ 239 EXA_FALLBACK(("to %p (%c)\n", pDrawable, 240 exaDrawableLocation(pDrawable))); 241 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 242 exaPrepareAccessGC (pGC); 243 fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); 244 exaFinishAccessGC (pGC); 245 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 246} 247 248void 249ExaCheckPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, 250 int x, int y, unsigned int nglyph, 251 CharInfoPtr *ppci, pointer pglyphBase) 252{ 253 EXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable, 254 exaDrawableLocation(pDrawable), pGC->fillStyle, pGC->alu)); 255 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 256 exaPrepareAccessGC (pGC); 257 fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); 258 exaFinishAccessGC (pGC); 259 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 260} 261 262void 263ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap, 264 DrawablePtr pDrawable, 265 int w, int h, int x, int y) 266{ 267 EXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable, 268 exaDrawableLocation(&pBitmap->drawable), 269 exaDrawableLocation(pDrawable))); 270 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 271 exaPrepareAccess (&pBitmap->drawable, EXA_PREPARE_SRC); 272 exaPrepareAccessGC (pGC); 273 fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y); 274 exaFinishAccessGC (pGC); 275 exaFinishAccess (&pBitmap->drawable, EXA_PREPARE_SRC); 276 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 277} 278 279void 280ExaCheckGetSpans (DrawablePtr pDrawable, 281 int wMax, 282 DDXPointPtr ppt, 283 int *pwidth, 284 int nspans, 285 char *pdstStart) 286{ 287 EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); 288 exaPrepareAccess (pDrawable, EXA_PREPARE_SRC); 289 fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); 290 exaFinishAccess (pDrawable, EXA_PREPARE_SRC); 291} 292 293void 294ExaCheckComposite (CARD8 op, 295 PicturePtr pSrc, 296 PicturePtr pMask, 297 PicturePtr pDst, 298 INT16 xSrc, 299 INT16 ySrc, 300 INT16 xMask, 301 INT16 yMask, 302 INT16 xDst, 303 INT16 yDst, 304 CARD16 width, 305 CARD16 height) 306{ 307 RegionRec region; 308 int xoff, yoff; 309 310 REGION_NULL(pScreen, ®ion); 311 312 /* We need to prepare access to any separate alpha maps first, in case the 313 * driver doesn't support EXA_PREPARE_AUX*, in which case EXA_PREPARE_SRC 314 * may be used for moving them out. 315 */ 316 if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) 317 exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX2); 318 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) 319 exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX1); 320 321 if (!exaOpReadsDestination(op)) { 322 if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, 323 xSrc, ySrc, xMask, yMask, xDst, yDst, 324 width, height)) 325 return; 326 327 exaGetDrawableDeltas (pDst->pDrawable, 328 exaGetDrawablePixmap(pDst->pDrawable), 329 &xoff, &yoff); 330 331 REGION_TRANSLATE(pScreen, ®ion, xoff, yoff); 332 333 if (pDst->alphaMap && pDst->alphaMap->pDrawable) 334 exaPrepareAccessReg(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0, 335 ®ion); 336 337 exaPrepareAccessReg (pDst->pDrawable, EXA_PREPARE_DEST, ®ion); 338 } else { 339 if (pDst->alphaMap && pDst->alphaMap->pDrawable) 340 exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0); 341 342 exaPrepareAccess (pDst->pDrawable, EXA_PREPARE_DEST); 343 } 344 345 EXA_FALLBACK(("from picts %p/%p to pict %p\n", 346 pSrc, pMask, pDst)); 347 348 if (pSrc->pDrawable != NULL) 349 exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC); 350 if (pMask && pMask->pDrawable != NULL) 351 exaPrepareAccess (pMask->pDrawable, EXA_PREPARE_MASK); 352 fbComposite (op, 353 pSrc, 354 pMask, 355 pDst, 356 xSrc, 357 ySrc, 358 xMask, 359 yMask, 360 xDst, 361 yDst, 362 width, 363 height); 364 if (pMask && pMask->pDrawable != NULL) 365 exaFinishAccess (pMask->pDrawable, EXA_PREPARE_MASK); 366 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) 367 exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX1); 368 if (pSrc->pDrawable != NULL) 369 exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC); 370 if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) 371 exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX2); 372 exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST); 373 if (pDst->alphaMap && pDst->alphaMap->pDrawable) 374 exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0); 375 376 REGION_UNINIT(pScreen, ®ion); 377} 378 379void 380ExaCheckAddTraps (PicturePtr pPicture, 381 INT16 x_off, 382 INT16 y_off, 383 int ntrap, 384 xTrap *traps) 385{ 386 EXA_FALLBACK(("to pict %p (%c)\n", 387 exaDrawableLocation(pPicture->pDrawable))); 388 exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); 389 fbAddTraps (pPicture, x_off, y_off, ntrap, traps); 390 exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); 391} 392 393/** 394 * Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps 395 * that happen to be 1x1. Pixmap must be at least 8bpp. 396 * 397 * XXX This really belongs in fb, so it can be aware of tiling and etc. 398 */ 399CARD32 400exaGetPixmapFirstPixel (PixmapPtr pPixmap) 401{ 402 CARD32 pixel; 403 void *fb; 404 Bool need_finish = FALSE; 405 BoxRec box; 406 RegionRec migration; 407 ExaPixmapPriv (pPixmap); 408 Bool sys_valid = pExaPixmap->pDamage && 409 !miPointInRegion(&pExaPixmap->validSys, 0, 0, &box); 410 Bool damaged = pExaPixmap->pDamage && 411 miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0, &box); 412 Bool offscreen = exaPixmapIsOffscreen(pPixmap); 413 414 fb = pExaPixmap->sys_ptr; 415 416 /* Try to avoid framebuffer readbacks */ 417 if ((!offscreen && !sys_valid && !damaged) || 418 (offscreen && (!sys_valid || damaged))) 419 { 420 box.x1 = 0; 421 box.y1 = 0; 422 box.x2 = 1; 423 box.y2 = 1; 424 REGION_INIT(pScreen, &migration, &box, 1); 425 426 need_finish = TRUE; 427 428 exaPrepareAccessReg(&pPixmap->drawable, EXA_PREPARE_SRC, &migration); 429 fb = pPixmap->devPrivate.ptr; 430 } 431 432 switch (pPixmap->drawable.bitsPerPixel) { 433 case 32: 434 pixel = *(CARD32 *)fb; 435 break; 436 case 16: 437 pixel = *(CARD16 *)fb; 438 break; 439 default: 440 pixel = *(CARD8 *)fb; 441 break; 442 } 443 444 if (need_finish) { 445 exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); 446 REGION_UNINIT(pScreen, &migration); 447 } 448 449 return pixel; 450} 451