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 "uxa-priv.h" 25#include "uxa-damage.h" 26 27#ifdef RENDER 28#include "mipict.h" 29#endif 30 31/* 32 * These functions wrap the low-level fb rendering functions and 33 * synchronize framebuffer/accelerated drawing by stalling until 34 * the accelerator is idle 35 */ 36 37/** 38 * Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the 39 * current fill style. 40 * 41 * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are 42 * 1bpp and never in fb, so we don't worry about them. 43 * We should worry about them for completeness sake and going forward. 44 */ 45Bool uxa_prepare_access_gc(GCPtr pGC) 46{ 47 if (pGC->stipple) 48 if (!uxa_prepare_access(&pGC->stipple->drawable, NULL, UXA_ACCESS_RO)) 49 return FALSE; 50 if (pGC->fillStyle == FillTiled) 51 if (!uxa_prepare_access 52 (&pGC->tile.pixmap->drawable, NULL, UXA_ACCESS_RO)) { 53 if (pGC->stipple) 54 uxa_finish_access(&pGC->stipple->drawable); 55 return FALSE; 56 } 57 return TRUE; 58} 59 60/** 61 * Finishes access to the tile in the GC, if used. 62 */ 63void uxa_finish_access_gc(GCPtr pGC) 64{ 65 if (pGC->fillStyle == FillTiled) 66 uxa_finish_access(&pGC->tile.pixmap->drawable); 67 if (pGC->stipple) 68 uxa_finish_access(&pGC->stipple->drawable); 69} 70 71char uxa_drawable_location(DrawablePtr pDrawable) 72{ 73 return uxa_drawable_is_offscreen(pDrawable) ? 's' : 'm'; 74} 75 76void 77uxa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans, 78 DDXPointPtr ppt, int *pwidth, int fSorted) 79{ 80 ScreenPtr screen = pDrawable->pScreen; 81 RegionRec region; 82 83 REGION_INIT (screen, ®ion, (BoxPtr)NULL, 0); 84 uxa_damage_fill_spans (®ion, pDrawable, pGC, nspans, 85 ppt, pwidth, fSorted); 86 87 UXA_FALLBACK(("to %p (%c)\n", pDrawable, 88 uxa_drawable_location(pDrawable))); 89 if (uxa_prepare_access(pDrawable, ®ion, UXA_ACCESS_RW)) { 90 if (uxa_prepare_access_gc(pGC)) { 91 fbFillSpans(pDrawable, pGC, nspans, ppt, pwidth, 92 fSorted); 93 uxa_finish_access_gc(pGC); 94 } 95 uxa_finish_access(pDrawable); 96 } 97 98 REGION_UNINIT (screen, ®ion); 99} 100 101void 102uxa_check_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc, 103 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) 104{ 105 ScreenPtr screen = pDrawable->pScreen; 106 107 UXA_FALLBACK(("to %p (%c)\n", pDrawable, 108 uxa_drawable_location(pDrawable))); 109 if (uxa_prepare_access(pDrawable, NULL, UXA_ACCESS_RW)) { 110 fbSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); 111 uxa_finish_access(pDrawable); 112 } 113} 114 115void 116uxa_check_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, 117 int x, int y, int w, int h, int leftPad, int format, 118 char *bits) 119{ 120 ScreenPtr screen = pDrawable->pScreen; 121 122 UXA_FALLBACK(("to %p (%c)\n", pDrawable, 123 uxa_drawable_location(pDrawable))); 124 if (uxa_prepare_access(pDrawable, NULL, UXA_ACCESS_RW)) { 125 fbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, 126 bits); 127 uxa_finish_access(pDrawable); 128 } 129} 130 131RegionPtr 132uxa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 133 int srcx, int srcy, int w, int h, int dstx, int dsty) 134{ 135 ScreenPtr screen = pSrc->pScreen; 136 RegionPtr ret = NULL; 137 RegionRec src_region; 138 RegionRec dst_region; 139 BoxRec src_box = { srcx, srcy, srcx + w, srcy + h }; 140 BoxRec dst_box = { dstx, dsty, dstx + w, dsty + h }; 141 142 REGION_INIT (screen, &src_region, &src_box, 1); 143 REGION_INIT (screen, &dst_region, &dst_box, 1); 144 145 /* FIXME: Hmm, it's not totally clear what to do in this case. In fact, 146 * all cases where more than one drawable can get prepare_access() called 147 * on it multiple times is kinda bad. 148 */ 149 150 UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, 151 uxa_drawable_location(pSrc), 152 uxa_drawable_location(pDst))); 153 if (uxa_prepare_access(pDst, &dst_region, UXA_ACCESS_RW)) { 154 if (uxa_prepare_access(pSrc, &src_region, UXA_ACCESS_RO)) { 155 ret = 156 fbCopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, 157 dsty); 158 uxa_finish_access(pSrc); 159 } 160 uxa_finish_access(pDst); 161 } 162 163 REGION_UNINIT (screen, &src_region); 164 REGION_UNINIT (screen, &dst_region); 165 166 return ret; 167} 168 169RegionPtr 170uxa_check_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 171 int srcx, int srcy, int w, int h, int dstx, int dsty, 172 unsigned long bitPlane) 173{ 174 ScreenPtr screen = pSrc->pScreen; 175 RegionPtr ret = NULL; 176 177 UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, 178 uxa_drawable_location(pSrc), 179 uxa_drawable_location(pDst))); 180 if (uxa_prepare_access(pDst, NULL, UXA_ACCESS_RW)) { 181 if (uxa_prepare_access(pSrc, NULL, UXA_ACCESS_RO)) { 182 ret = 183 fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, 184 dsty, bitPlane); 185 uxa_finish_access(pSrc); 186 } 187 uxa_finish_access(pDst); 188 } 189 return ret; 190} 191 192void 193uxa_check_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 194 DDXPointPtr pptInit) 195{ 196 ScreenPtr screen = pDrawable->pScreen; 197 198 UXA_FALLBACK(("to %p (%c)\n", pDrawable, 199 uxa_drawable_location(pDrawable))); 200 if (uxa_prepare_access(pDrawable, NULL, UXA_ACCESS_RW)) { 201 fbPolyPoint(pDrawable, pGC, mode, npt, pptInit); 202 uxa_finish_access(pDrawable); 203 } 204} 205 206void 207uxa_check_poly_lines(DrawablePtr pDrawable, GCPtr pGC, 208 int mode, int npt, DDXPointPtr ppt) 209{ 210 ScreenPtr screen = pDrawable->pScreen; 211 RegionRec region; 212 213 REGION_INIT (screen, ®ion, (BoxPtr)NULL, 0); 214 uxa_damage_poly_lines (®ion, pDrawable, pGC, mode, npt, ppt); 215 216 UXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n", 217 pDrawable, uxa_drawable_location(pDrawable), 218 pGC->lineWidth, mode, npt)); 219 220 if (pGC->lineWidth == 0) { 221 if (uxa_prepare_access(pDrawable, ®ion, UXA_ACCESS_RW)) { 222 if (uxa_prepare_access_gc(pGC)) { 223 fbPolyLine(pDrawable, pGC, mode, npt, ppt); 224 uxa_finish_access_gc(pGC); 225 } 226 uxa_finish_access(pDrawable); 227 } 228 goto out; 229 } 230 /* fb calls mi functions in the lineWidth != 0 case. */ 231 fbPolyLine(pDrawable, pGC, mode, npt, ppt); 232 233 out: 234 REGION_UNINIT (screen, ®ion); 235} 236 237void 238uxa_check_poly_segment(DrawablePtr pDrawable, GCPtr pGC, 239 int nsegInit, xSegment * pSegInit) 240{ 241 ScreenPtr screen = pDrawable->pScreen; 242 RegionRec region; 243 244 REGION_INIT (screen, ®ion, (BoxPtr)NULL, 0); 245 uxa_damage_poly_segment (®ion, pDrawable, pGC, nsegInit, pSegInit); 246 247 UXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable, 248 uxa_drawable_location(pDrawable), pGC->lineWidth, 249 nsegInit)); 250 if (pGC->lineWidth == 0) { 251 if (uxa_prepare_access(pDrawable, ®ion, UXA_ACCESS_RW)) { 252 if (uxa_prepare_access_gc(pGC)) { 253 fbPolySegment(pDrawable, pGC, nsegInit, 254 pSegInit); 255 uxa_finish_access_gc(pGC); 256 } 257 uxa_finish_access(pDrawable); 258 } 259 goto out; 260 } 261 262 /* fb calls mi functions in the lineWidth != 0 case. */ 263 fbPolySegment(pDrawable, pGC, nsegInit, pSegInit); 264 265out: 266 REGION_UNINIT (screen, ®ion); 267} 268 269void 270uxa_check_poly_arc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs) 271{ 272 ScreenPtr screen = pDrawable->pScreen; 273 274 UXA_FALLBACK(("to %p (%c)\n", pDrawable, 275 uxa_drawable_location(pDrawable))); 276 277 /* Disable this as fbPolyArc can call miZeroPolyArc which in turn 278 * can call accelerated functions, that as yet, haven't been notified 279 * with uxa_finish_access(). 280 */ 281#if 0 282 if (pGC->lineWidth == 0) { 283 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) { 284 if (uxa_prepare_access_gc(pGC)) { 285 fbPolyArc(pDrawable, pGC, narcs, pArcs); 286 uxa_finish_access_gc(pGC); 287 } 288 uxa_finish_access(pDrawable); 289 } 290 return; 291 } 292#endif 293 miPolyArc(pDrawable, pGC, narcs, pArcs); 294} 295 296void 297uxa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC, 298 int nrect, xRectangle * prect) 299{ 300 ScreenPtr screen = pDrawable->pScreen; 301 RegionRec region; 302 303 REGION_INIT (screen, ®ion, (BoxPtr)NULL, 0); 304 uxa_damage_poly_fill_rect (®ion, pDrawable, pGC, nrect, prect); 305 306 UXA_FALLBACK(("to %p (%c)\n", pDrawable, 307 uxa_drawable_location(pDrawable))); 308 309 if (uxa_prepare_access(pDrawable, ®ion, UXA_ACCESS_RW)) { 310 if (uxa_prepare_access_gc(pGC)) { 311 fbPolyFillRect(pDrawable, pGC, nrect, prect); 312 uxa_finish_access_gc(pGC); 313 } 314 uxa_finish_access(pDrawable); 315 } 316 317 REGION_UNINIT (screen, ®ion); 318} 319 320void 321uxa_check_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, 322 int x, int y, unsigned int nglyph, 323 CharInfoPtr * ppci, pointer pglyphBase) 324{ 325 ScreenPtr screen = pDrawable->pScreen; 326 RegionRec region; 327 328 REGION_INIT (screen, ®ion, (BoxPtr)NULL, 0); 329 uxa_damage_image_glyph_blt (®ion, pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); 330 331 UXA_FALLBACK(("to %p (%c)\n", pDrawable, 332 uxa_drawable_location(pDrawable))); 333 if (uxa_prepare_access(pDrawable, ®ion, UXA_ACCESS_RW)) { 334 if (uxa_prepare_access_gc(pGC)) { 335 fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, 336 pglyphBase); 337 uxa_finish_access_gc(pGC); 338 } 339 uxa_finish_access(pDrawable); 340 } 341 342 REGION_UNINIT (screen, ®ion); 343} 344 345void 346uxa_check_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, 347 int x, int y, unsigned int nglyph, 348 CharInfoPtr * ppci, pointer pglyphBase) 349{ 350 ScreenPtr screen = pDrawable->pScreen; 351 RegionRec region; 352 353 REGION_INIT (screen, ®ion, (BoxPtr)NULL, 0); 354 uxa_damage_poly_glyph_blt (®ion, pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); 355 356 UXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable, 357 uxa_drawable_location(pDrawable), pGC->fillStyle, 358 pGC->alu)); 359 if (uxa_prepare_access(pDrawable, ®ion, UXA_ACCESS_RW)) { 360 if (uxa_prepare_access_gc(pGC)) { 361 fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, 362 pglyphBase); 363 uxa_finish_access_gc(pGC); 364 } 365 uxa_finish_access(pDrawable); 366 } 367 368 REGION_UNINIT (screen, ®ion); 369} 370 371void 372uxa_check_push_pixels(GCPtr pGC, PixmapPtr pBitmap, 373 DrawablePtr pDrawable, int w, int h, int x, int y) 374{ 375 ScreenPtr screen = pDrawable->pScreen; 376 RegionRec region; 377 378 REGION_INIT (screen, ®ion, (BoxPtr)NULL, 0); 379 uxa_damage_push_pixels (®ion, pGC, pBitmap, pDrawable, w, h, x, y); 380 381 UXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable, 382 uxa_drawable_location(&pBitmap->drawable), 383 uxa_drawable_location(pDrawable))); 384 if (uxa_prepare_access(pDrawable, ®ion, UXA_ACCESS_RW)) { 385 if (uxa_prepare_access(&pBitmap->drawable, NULL, UXA_ACCESS_RO)) { 386 if (uxa_prepare_access_gc(pGC)) { 387 fbPushPixels(pGC, pBitmap, pDrawable, w, h, x, 388 y); 389 uxa_finish_access_gc(pGC); 390 } 391 uxa_finish_access(&pBitmap->drawable); 392 } 393 uxa_finish_access(pDrawable); 394 } 395 396 REGION_UNINIT (screen, ®ion); 397} 398 399void 400uxa_check_get_spans(DrawablePtr pDrawable, 401 int wMax, 402 DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart) 403{ 404 ScreenPtr screen = pDrawable->pScreen; 405 406 UXA_FALLBACK(("from %p (%c)\n", pDrawable, 407 uxa_drawable_location(pDrawable))); 408 if (uxa_prepare_access(pDrawable, NULL, UXA_ACCESS_RO)) { 409 fbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart); 410 uxa_finish_access(pDrawable); 411 } 412} 413 414void 415uxa_check_composite(CARD8 op, 416 PicturePtr pSrc, 417 PicturePtr pMask, 418 PicturePtr pDst, 419 INT16 xSrc, INT16 ySrc, 420 INT16 xMask, INT16 yMask, 421 INT16 xDst, INT16 yDst, 422 CARD16 width, CARD16 height) 423{ 424 ScreenPtr screen = pDst->pDrawable->pScreen; 425 RegionRec region; 426 427 UXA_FALLBACK(("from picts %p/%p to pict %p\n", pSrc, pMask, pDst)); 428 429 REGION_INIT (screen, ®ion, (BoxPtr)NULL, 0); 430 uxa_damage_composite (®ion, op, pSrc, pMask, pDst, 431 xSrc, ySrc, xMask, yMask, xDst, yDst, 432 width, height); 433 434#if 0 435 ErrorF ("destination: %p\n", pDst->pDrawable); 436 ErrorF ("source: %p\n", pSrc->pDrawable); 437 ErrorF ("mask: %p\n", pMask? pMask->pDrawable : NULL); 438#endif 439 if (uxa_prepare_access(pDst->pDrawable, ®ion, UXA_ACCESS_RW)) { 440 if (pSrc->pDrawable == NULL || 441 uxa_prepare_access(pSrc->pDrawable, NULL, UXA_ACCESS_RO)) { 442 if (!pMask || pMask->pDrawable == NULL || 443 uxa_prepare_access(pMask->pDrawable, NULL, UXA_ACCESS_RO)) 444 { 445 fbComposite(op, pSrc, pMask, pDst, 446 xSrc, ySrc, 447 xMask, yMask, 448 xDst, yDst, 449 width, height); 450 if (pMask && pMask->pDrawable != NULL) 451 uxa_finish_access(pMask->pDrawable); 452 } 453 if (pSrc->pDrawable != NULL) 454 uxa_finish_access(pSrc->pDrawable); 455 } 456 uxa_finish_access(pDst->pDrawable); 457 } 458} 459 460void 461uxa_check_add_traps(PicturePtr pPicture, 462 INT16 x_off, INT16 y_off, int ntrap, xTrap * traps) 463{ 464 ScreenPtr screen = pPicture->pDrawable->pScreen; 465 466 UXA_FALLBACK(("to pict %p (%c)\n", pPicture, 467 uxa_drawable_location(pPicture->pDrawable))); 468 if (uxa_prepare_access(pPicture->pDrawable, NULL, UXA_ACCESS_RW)) { 469 fbAddTraps(pPicture, x_off, y_off, ntrap, traps); 470 uxa_finish_access(pPicture->pDrawable); 471 } 472} 473 474/** 475 * Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps 476 * that happen to be 1x1. Pixmap must be at least 8bpp. 477 * 478 * XXX This really belongs in fb, so it can be aware of tiling and etc. 479 */ 480CARD32 uxa_get_pixmap_first_pixel(PixmapPtr pPixmap) 481{ 482 CARD32 pixel; 483 void *fb; 484 485 if (!uxa_prepare_access(&pPixmap->drawable, NULL, UXA_ACCESS_RO)) 486 return 0; 487 488 fb = pPixmap->devPrivate.ptr; 489 490 switch (pPixmap->drawable.bitsPerPixel) { 491 case 32: 492 pixel = *(CARD32 *) fb; 493 break; 494 case 16: 495 pixel = *(CARD16 *) fb; 496 break; 497 default: 498 pixel = *(CARD8 *) fb; 499 break; 500 } 501 uxa_finish_access(&pPixmap->drawable); 502 503 return pixel; 504} 505