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