saa_unaccel.c revision 591e32d7
1/* 2 * Copyright © 1999 Keith Packard 3 * Copyright 2011 VMWare, Inc. All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Author: Based on "exa_unaccel.c" 26 * Author: Thomas Hellstrom <thellstrom@vmware.com> 27 */ 28 29#include "saa_priv.h" 30#include "saa.h" 31#include "mipict.h" 32 33/** 34 * Calls saa_prepare_access with SAA_ACCESS_R for the tile, if that is the 35 * current fill style. 36 * 37 * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are 38 * 1bpp and never in fb, so we don't worry about them. 39 * We should worry about them for completeness sake and going forward. 40 */ 41static Bool 42saa_prepare_access_gc(GCPtr pGC) 43{ 44 if (pGC->stipple) 45 if (!saa_pad_read(&pGC->stipple->drawable)) 46 return FALSE; 47 if (pGC->fillStyle == FillTiled) 48 if (!saa_pad_read(&pGC->tile.pixmap->drawable)) { 49 if (pGC->stipple) 50 saa_fad_read(&pGC->stipple->drawable); 51 return FALSE; 52 } 53 return TRUE; 54} 55 56/** 57 * Finishes access to the tile in the GC, if used. 58 */ 59static void 60saa_finish_access_gc(GCPtr pGC) 61{ 62 if (pGC->fillStyle == FillTiled) 63 saa_fad_read(&pGC->tile.pixmap->drawable); 64 if (pGC->stipple) 65 saa_fad_read(&pGC->stipple->drawable); 66} 67 68void 69saa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans, 70 DDXPointPtr ppt, int *pwidth, int fSorted) 71{ 72 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 73 struct saa_gc_priv *sgc = saa_gc(pGC); 74 saa_access_t access; 75 76 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_location(pDrawable))); 77 78 sscreen->fallback_count++; 79 if (saa_pad_write(pDrawable, NULL, FALSE, &access)) { 80 if (saa_prepare_access_gc(pGC)) { 81 saa_swap(sgc, pGC, ops); 82 pGC->ops->FillSpans(pDrawable, pGC, nspans, ppt, pwidth, fSorted); 83 saa_swap(sgc, pGC, ops); 84 saa_finish_access_gc(pGC); 85 } 86 saa_fad_write(pDrawable, access); 87 } 88 sscreen->fallback_count--; 89} 90 91static void 92saa_check_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc, 93 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) 94{ 95 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 96 struct saa_gc_priv *sgc = saa_gc(pGC); 97 saa_access_t access 98 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); 99 100 sscreen->fallback_count++; 101 if (saa_pad_write(pDrawable, NULL, FALSE, &access)) { 102 saa_swap(sgc, pGC, ops); 103 pGC->ops->SetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); 104 saa_swap(sgc, pGC, ops); 105 saa_fad_write(pDrawable, access); 106 } 107 sscreen->fallback_count--; 108} 109 110static void 111saa_check_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, 112 int x, int y, int w, int h, int leftPad, int format, 113 char *bits) 114{ 115 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 116 struct saa_gc_priv *sgc = saa_gc(pGC); 117 saa_access_t access; 118 119 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); 120 sscreen->fallback_count++; 121 if (saa_pad_write(pDrawable, pGC, TRUE, &access)) { 122 saa_swap(sgc, pGC, ops); 123 pGC->ops->PutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, 124 format, bits); 125 saa_swap(sgc, pGC, ops); 126 saa_fad_write(pDrawable, access); 127 } 128 sscreen->fallback_count--; 129} 130 131RegionPtr 132saa_boxes_to_region(ScreenPtr pScreen, int nbox, BoxPtr pbox, int ordering) 133{ 134 xRectangle *rects = malloc(nbox * sizeof(*rects)); 135 int i; 136 RegionPtr reg; 137 138 if (!rects) 139 return NULL; 140 141 for (i = 0; i < nbox; i++) { 142 rects[i].x = pbox[i].x1; 143 rects[i].y = pbox[i].y1; 144 rects[i].width = pbox[i].x2 - pbox[i].x1; 145 rects[i].height = pbox[i].y2 - pbox[i].y1; 146 } 147 148 reg = RECTS_TO_REGION(pScreen, nbox, rects, ordering); 149 free(rects); 150 return reg; 151} 152 153void 154saa_check_copy_nton(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 155 BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, 156 Bool upsidedown, Pixel bitplane, void *closure) 157{ 158 ScreenPtr pScreen = pSrc->pScreen; 159 struct saa_screen_priv *sscreen = saa_screen(pScreen); 160 RegionPtr reg, readback; 161 int src_xoff, src_yoff, dst_xoff, dst_yoff; 162 struct saa_gc_priv *sgc = saa_gc(pGC); 163 PixmapPtr src_pixmap; 164 PixmapPtr dst_pixmap; 165 saa_access_t access = SAA_ACCESS_R; 166 int ordering; 167 168 sscreen->fallback_count++; 169 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, 170 saa_drawable_loc(pSrc), saa_drawable_loc(pDst))); 171 172 src_pixmap = saa_get_pixmap(pSrc, &src_xoff, &src_yoff); 173 dst_pixmap = saa_get_pixmap(pDst, &dst_xoff, &dst_yoff); 174 175 ordering = (nbox == 1 || (dx > 0 && dy > 0) || 176 (pDst != pSrc && 177 (pDst->type != DRAWABLE_WINDOW || 178 pSrc->type != DRAWABLE_WINDOW))) ? CT_YXBANDED : CT_UNSORTED; 179 180 reg = saa_boxes_to_region(pScreen, nbox, pbox, ordering); 181 if (!reg) 182 return; 183 184 REGION_TRANSLATE(pScreen, reg, src_xoff + dx, src_yoff + dy); 185 if (!saa_prepare_access_pixmap(src_pixmap, SAA_ACCESS_R, reg)) 186 goto out_no_access; 187 188 REGION_TRANSLATE(pScreen, reg, dst_xoff - dx - src_xoff, 189 dst_yoff - dy - src_yoff); 190 191 if (saa_gc_reads_destination(pDst, pGC)) { 192 readback = reg; 193 access = SAA_ACCESS_RW; 194 } else { 195 readback = NULL; 196 access = SAA_ACCESS_W; 197 } 198 199 if (!saa_prepare_access_pixmap(dst_pixmap, access, readback)) 200 goto out_no_dst; 201 202 saa_swap(sgc, pGC, ops); 203 while (nbox--) { 204 pGC->ops->CopyArea(pSrc, pDst, pGC, pbox->x1 - pSrc->x + dx, 205 pbox->y1 - pSrc->y + dy, 206 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, 207 pbox->x1 - pDst->x, pbox->y1 - pDst->y); 208 pbox++; 209 } 210 211 saa_swap(sgc, pGC, ops); 212 saa_finish_access_pixmap(dst_pixmap, access); 213 saa_pixmap_dirty(dst_pixmap, FALSE, reg); 214 out_no_dst: 215 saa_fad_read(pSrc); 216 out_no_access: 217 sscreen->fallback_count--; 218 REGION_DESTROY(pScreen, reg); 219} 220 221RegionPtr 222saa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 223 int srcx, int srcy, int w, int h, int dstx, int dsty) 224{ 225 RegionPtr ret = NULL; 226 struct saa_gc_priv *sgc = saa_gc(pGC); 227 saa_access_t access; 228 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 229 230 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, 231 saa_drawable_loc(pSrc), saa_drawable_loc(pDst))); 232 sscreen->fallback_count++; 233 if (!saa_pad_read_box(pSrc, srcx, srcy, w, h)) 234 goto out_no_access; 235 if (!saa_pad_write(pDst, pGC, TRUE, &access)) 236 goto out_no_dst; 237 238 saa_swap(sgc, pGC, ops); 239 ret = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); 240 saa_swap(sgc, pGC, ops); 241 242 saa_fad_write(pDst, access); 243 out_no_dst: 244 saa_fad_read(pSrc); 245 out_no_access: 246 sscreen->fallback_count--; 247 248 return ret; 249} 250 251static RegionPtr 252saa_check_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 253 int srcx, int srcy, int w, int h, int dstx, int dsty, 254 unsigned long bitplane) 255{ 256 RegionPtr ret = NULL; 257 struct saa_gc_priv *sgc = saa_gc(pGC); 258 saa_access_t access; 259 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 260 261 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, 262 saa_drawable_loc(pSrc), saa_drawable_loc(pDst))); 263 sscreen->fallback_count++; 264 if (!saa_pad_read_box(pSrc, srcx, srcy, w, h)) 265 goto out_no_src; 266 if (!saa_pad_write(pDst, pGC, TRUE, &access)) 267 goto out_no_dst; 268 269 saa_swap(sgc, pGC, ops); 270 ret = pGC->ops->CopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 271 bitplane); 272 saa_swap(sgc, pGC, ops); 273 274 saa_fad_write(pDst, access); 275 out_no_dst: 276 saa_fad_read(pSrc); 277 out_no_src: 278 sscreen->fallback_count--; 279 280 return ret; 281} 282 283static void 284saa_check_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 285 DDXPointPtr pptInit) 286{ 287 struct saa_gc_priv *sgc = saa_gc(pGC); 288 saa_access_t access; 289 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 290 291 sscreen->fallback_count++; 292 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); 293 if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) 294 goto out_no_access; 295 saa_swap(sgc, pGC, ops); 296 pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, pptInit); 297 saa_swap(sgc, pGC, ops); 298 saa_fad_write(pDrawable, access); 299 300 out_no_access: 301 sscreen->fallback_count--; 302} 303 304static void 305saa_check_poly_lines(DrawablePtr pDrawable, GCPtr pGC, 306 int mode, int npt, DDXPointPtr ppt) 307{ 308 struct saa_gc_priv *sgc = saa_gc(pGC); 309 saa_access_t access; 310 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 311 312 SAA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n", 313 pDrawable, saa_drawable_loc(pDrawable), 314 pGC->lineWidth, mode, npt)); 315 316 sscreen->fallback_count++; 317 if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) 318 goto out_no_access; 319 if (!saa_prepare_access_gc(pGC)) 320 goto out_no_gc; 321 saa_swap(sgc, pGC, ops); 322 pGC->ops->Polylines(pDrawable, pGC, mode, npt, ppt); 323 saa_swap(sgc, pGC, ops); 324 saa_finish_access_gc(pGC); 325 out_no_gc: 326 saa_fad_write(pDrawable, access); 327 out_no_access: 328 sscreen->fallback_count--; 329} 330 331static void 332saa_check_poly_segment(DrawablePtr pDrawable, GCPtr pGC, 333 int nsegInit, xSegment * pSegInit) 334{ 335 struct saa_gc_priv *sgc = saa_gc(pGC); 336 saa_access_t access; 337 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 338 339 SAA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable, 340 saa_drawable_loc(pDrawable), pGC->lineWidth, nsegInit)); 341 342 sscreen->fallback_count++; 343 if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) 344 goto out_no_access;; 345 if (!saa_prepare_access_gc(pGC)) 346 goto out_no_gc; 347 saa_swap(sgc, pGC, ops); 348 pGC->ops->PolySegment(pDrawable, pGC, nsegInit, pSegInit); 349 saa_swap(sgc, pGC, ops); 350 saa_finish_access_gc(pGC); 351 out_no_gc: 352 saa_fad_write(pDrawable, access); 353 out_no_access: 354 sscreen->fallback_count--; 355} 356 357static void 358saa_check_poly_arc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs) 359{ 360 struct saa_gc_priv *sgc = saa_gc(pGC); 361 saa_access_t access; 362 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 363 364 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); 365 366 sscreen->fallback_count++; 367 if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) 368 goto out_no_access;; 369 if (!saa_prepare_access_gc(pGC)) 370 goto out_no_gc; 371 saa_swap(sgc, pGC, ops); 372 pGC->ops->PolyArc(pDrawable, pGC, narcs, pArcs); 373 saa_swap(sgc, pGC, ops); 374 saa_finish_access_gc(pGC); 375 out_no_gc: 376 saa_fad_write(pDrawable, access); 377 out_no_access: 378 sscreen->fallback_count--; 379} 380 381 382/** 383 * saa_check_poly_fill_rect_noreadback - PolyFillRect avoiding unnecessary readbacks. 384 * 385 * @pDrawable: The drawable on which to fill. 386 * @pGC: Pointer to the GC to use. 387 * @nrect: Number of rectangles to fill. 388 * @xRectangle: Pointer to rectangles to fill. 389 * 390 * During a standard saa polyFillRect, the damage region is usually the bounding 391 * box of all rectangles. Since we mark the software pixmap dirty based on that 392 * damage region, we need to read all of it back first, even if the fill operation 393 * itself doesn't read anything. This version of polyFillRect improves on that by 394 * only damaging the area we actually fill. If it's a non-reading fill we thus don't 395 * need to read back anything, but this may come at the cost of increased dirty 396 * region fragmentation. In any case, this greatly improves on the performance of 397 * shaped windows on top of accelerated contents, for example unscaled OSD in xine. 398 */ 399static Bool 400saa_check_poly_fill_rect_noreadback(DrawablePtr pDrawable, GCPtr pGC, 401 int nrect, xRectangle *prect) 402{ 403 struct saa_gc_priv *sgc = saa_gc(pGC); 404 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 405 RegionPtr region; 406 saa_access_t access; 407 Bool ret; 408 PixmapPtr pPixmap; 409 xRectangle *prect_save = prect; 410 int xoff, yoff; 411 struct saa_pixmap *spix; 412 413 if (!nrect) 414 return TRUE; 415 416 sscreen->fallback_count++; 417 418 pPixmap = saa_get_pixmap(pDrawable, &xoff, &yoff); 419 spix = saa_get_saa_pixmap(pPixmap); 420 region = RECTS_TO_REGION(pGC->pScreen, nrect, prect, CT_UNSORTED); 421 if (!region) 422 goto out_no_region; 423 424 REGION_TRANSLATE(pGC->pScreen, region, pDrawable->x, pDrawable->y); 425 REGION_INTERSECT(pGC->pScreen, region, fbGetCompositeClip(pGC), region); 426 REGION_TRANSLATE(pGC->pScreen, region, xoff, yoff); 427 428 access = SAA_ACCESS_W; 429 if (saa_gc_reads_destination(pDrawable, pGC)) { 430 /* 431 * We need to do a readback anyway. In case of more than an 432 * ad hoc number of say 4 rectangles, we might as well do a 433 * readback of the whole damage area to avoid fragmentation. 434 */ 435 if (REGION_NUM_RECTS(region) > 4) 436 goto out_no_access; 437 438 access |= SAA_ACCESS_R; 439 ret = saa_prepare_access_pixmap(pPixmap, access, region); 440 } else 441 ret = saa_prepare_access_pixmap(pPixmap, access, NULL); 442 443 if (!ret) 444 goto out_no_access; 445 446 if (!saa_prepare_access_gc(pGC)) 447 goto out_no_gc; 448 449 saa_swap(sgc, pGC, ops); 450 pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect_save); 451 saa_swap(sgc, pGC, ops); 452 453 saa_finish_access_gc(pGC); 454 saa_finish_access_pixmap(pPixmap, access); 455 456 if (spix->damage) { 457 REGION_INTERSECT(pGC->pScreen, region, region, 458 saa_pix_damage_pending(spix)); 459 saa_pixmap_dirty(pPixmap, FALSE, region); 460 } 461 462 REGION_DESTROY(pGC->pScreen, region); 463 464 sscreen->fallback_count--; 465 466 return TRUE; 467 468 out_no_gc: 469 saa_finish_access_pixmap(pPixmap, access); 470 out_no_access: 471 REGION_DESTROY(pGC->pScreen, region); 472 out_no_region: 473 sscreen->fallback_count--; 474 475 return FALSE; 476} 477 478void 479saa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC, 480 int nrect, xRectangle * prect) 481{ 482 struct saa_gc_priv *sgc = saa_gc(pGC); 483 saa_access_t access; 484 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 485 486 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); 487 488 if (saa_check_poly_fill_rect_noreadback(pDrawable, pGC, nrect, prect)) 489 return; 490 491 sscreen->fallback_count++; 492 493 /* 494 * TODO: Use @prect for readback / damaging instead of 495 * the damage region. This may fragment the dirty regions more 496 * but should avoid unnecessary readbacks. 497 */ 498 if (!saa_pad_write(pDrawable, pGC, FALSE, &access)) 499 goto out_no_access;; 500 if (!saa_prepare_access_gc(pGC)) 501 goto out_no_gc; 502 saa_swap(sgc, pGC, ops); 503 pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect); 504 saa_swap(sgc, pGC, ops); 505 saa_finish_access_gc(pGC); 506 out_no_gc: 507 saa_fad_write(pDrawable, access); 508 out_no_access: 509 sscreen->fallback_count--; 510} 511 512static void 513saa_check_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, 514 int x, int y, unsigned int nglyph, 515 CharInfoPtr * ppci, pointer pglyphBase) 516{ 517 struct saa_gc_priv *sgc = saa_gc(pGC); 518 saa_access_t access; 519 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 520 521 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); 522 523 sscreen->fallback_count++; 524 if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) 525 goto out_no_access;; 526 if (!saa_prepare_access_gc(pGC)) 527 goto out_no_gc; 528 saa_swap(sgc, pGC, ops); 529 pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); 530 saa_swap(sgc, pGC, ops); 531 saa_finish_access_gc(pGC); 532 out_no_gc: 533 saa_fad_write(pDrawable, access); 534 out_no_access: 535 sscreen->fallback_count--; 536} 537 538static void 539saa_check_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, 540 int x, int y, unsigned int nglyph, 541 CharInfoPtr * ppci, pointer pglyphBase) 542{ 543 struct saa_gc_priv *sgc = saa_gc(pGC); 544 saa_access_t access; 545 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 546 547 SAA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable, 548 saa_drawable_loc(pDrawable), pGC->fillStyle, pGC->alu)); 549 550 sscreen->fallback_count++; 551 if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) 552 goto out_no_access;; 553 if (!saa_prepare_access_gc(pGC)) 554 goto out_no_gc; 555 saa_swap(sgc, pGC, ops); 556 pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); 557 saa_swap(sgc, pGC, ops); 558 saa_finish_access_gc(pGC); 559 out_no_gc: 560 saa_fad_write(pDrawable, access); 561 out_no_access: 562 sscreen->fallback_count--; 563} 564 565static void 566saa_check_push_pixels(GCPtr pGC, PixmapPtr pBitmap, 567 DrawablePtr pDrawable, int w, int h, int x, int y) 568{ 569 struct saa_gc_priv *sgc = saa_gc(pGC); 570 saa_access_t access; 571 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); 572 573 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable, 574 saa_drawable_loc(&pBitmap->drawable), 575 saa_drawable_loc(pDrawable))); 576 577 sscreen->fallback_count++; 578 if (!saa_pad_write(pDrawable, pGC, TRUE, &access)) 579 goto out_no_access;; 580 if (!saa_pad_read_box(&pBitmap->drawable, 0, 0, w, h)) 581 goto out_no_src; 582 if (!saa_prepare_access_gc(pGC)) 583 goto out_no_gc; 584 saa_swap(sgc, pGC, ops); 585 pGC->ops->PushPixels(pGC, pBitmap, pDrawable, w, h, x, y); 586 saa_swap(sgc, pGC, ops); 587 saa_finish_access_gc(pGC); 588 out_no_gc: 589 saa_fad_read(&pBitmap->drawable); 590 out_no_src: 591 saa_fad_write(pDrawable, access); 592 out_no_access: 593 sscreen->fallback_count--; 594} 595 596static void 597saa_check_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 598{ 599 DrawablePtr pDrawable = &pWin->drawable; 600 ScreenPtr pScreen = pDrawable->pScreen; 601 struct saa_screen_priv *sscreen = saa_screen(pScreen); 602 int xoff, yoff; 603 PixmapPtr pPixmap = saa_get_pixmap(&pWin->drawable, &xoff, &yoff); 604 Bool ret; 605 606 SAA_FALLBACK(("from %p\n", pWin)); 607 608 /* Only need the source bits, the destination region will be overwritten */ 609 610 sscreen->fallback_count++; 611 REGION_TRANSLATE(pScreen, prgnSrc, xoff, yoff); 612 ret = saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_R, prgnSrc); 613 REGION_TRANSLATE(pScreen, prgnSrc, -xoff, -yoff); 614 if (!ret) 615 goto out_no_access;; 616 617 if (saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_W, NULL)) { 618 struct saa_pixmap *spix; 619 RegionRec rgnDst; 620 621 REGION_NULL(pScreen, &rgnDst); 622 REGION_COPY(pScreen, &rgnDst, prgnSrc); 623 624 saa_swap(sscreen, pScreen, CopyWindow); 625 pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc); 626 saa_swap(sscreen, pScreen, CopyWindow); 627 saa_finish_access_pixmap(pPixmap, SAA_ACCESS_W); 628 629 spix = saa_get_saa_pixmap(pPixmap); 630 if (spix->damage) { 631 int dx, dy; 632 633 dx = ptOldOrg.x - pWin->drawable.x; 634 dy = ptOldOrg.y - pWin->drawable.y; 635 REGION_TRANSLATE(pScreen, &rgnDst, -dx, -dy); 636 REGION_INTERSECT(pSreen, &rgnDst, &pWin->borderClip, &rgnDst); 637 REGION_TRANSLATE(pScreen, &rgnDst, xoff, yoff); 638 639 REGION_INTERSECT(pScreen, &rgnDst, &rgnDst, 640 saa_pix_damage_pending(spix)); 641 saa_pixmap_dirty(pPixmap, FALSE, &rgnDst); 642 } 643 REGION_UNINIT(pScreen, &rgnDst); 644 } 645 saa_fad_read(pDrawable); 646 out_no_access: 647 sscreen->fallback_count--; 648} 649 650#ifdef RENDER 651 652#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10) 653static void 654saa_src_validate(DrawablePtr pDrawable, 655 int x, 656 int y, int width, int height, unsigned int subWindowMode) 657#else 658static void 659saa_src_validate(DrawablePtr pDrawable, int x, int y, int width, int height) 660#endif 661{ 662 ScreenPtr pScreen = pDrawable->pScreen; 663 struct saa_screen_priv *sscreen = saa_screen(pScreen); 664 int xoff, yoff; 665 BoxRec box; 666 RegionRec reg; 667 RegionPtr dst; 668 669 (void) saa_get_pixmap(pDrawable, &xoff, &yoff); 670 box.x1 = x + xoff; 671 box.y1 = y + yoff; 672 box.x2 = box.x1 + width; 673 box.y2 = box.y1 + height; 674 675 dst = (sscreen->srcDraw == pDrawable) ? 676 &sscreen->srcReg : &sscreen->maskReg; 677 678 REGION_INIT(pScreen, ®, &box, 1); 679 REGION_UNION(pScreen, dst, dst, ®); 680 REGION_UNINIT(pScreen, ®); 681 682 if (sscreen->saved_SourceValidate) { 683 saa_swap(sscreen, pScreen, SourceValidate); 684 pScreen->SourceValidate(pDrawable, x, y, width, height 685#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10) 686 , subWindowMode 687#endif 688 ); 689 saa_swap(sscreen, pScreen, SourceValidate); 690 } 691} 692 693static void 694saa_check_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, 695 unsigned int format, unsigned long planeMask, char *d) 696{ 697 ScreenPtr pScreen = pDrawable->pScreen; 698 struct saa_screen_priv *sscreen = saa_screen(pScreen); 699 700 SAA_FALLBACK(("from %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); 701 702 sscreen->fallback_count++; 703 if (!saa_pad_read_box(pDrawable, x, y, w, h)) 704 goto out_no_access;; 705 saa_swap(sscreen, pScreen, GetImage); 706 pScreen->GetImage(pDrawable, x, y, w, h, format, planeMask, d); 707 saa_swap(sscreen, pScreen, GetImage); 708 saa_fad_read(pDrawable); 709 out_no_access: 710 sscreen->fallback_count--; 711} 712 713static void 714saa_check_get_spans(DrawablePtr pDrawable, 715 int wMax, 716 DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart) 717{ 718 ScreenPtr pScreen = pDrawable->pScreen; 719 struct saa_screen_priv *sscreen = saa_screen(pScreen); 720 721 SAA_FALLBACK(("from %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); 722 723 sscreen->fallback_count++; 724 if (!saa_pad_read(pDrawable)) 725 goto out_no_access;; 726 saa_swap(sscreen, pScreen, GetSpans); 727 pScreen->GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart); 728 saa_swap(sscreen, pScreen, GetSpans); 729 saa_fad_read(pDrawable); 730 out_no_access: 731 sscreen->fallback_count--; 732} 733 734/* 735 * Compute composite regions taking transforms into account. 736 * The caller must provide a pointer to an initialized dst_reg, 737 * and the function returns pointers to set up source- and mask regions. 738 * The source and mask regions must be uninitialized after use. 739 */ 740 741Bool 742saa_compute_composite_regions(ScreenPtr pScreen, 743 PicturePtr pSrc, 744 PicturePtr pMask, 745 PicturePtr pDst, 746 INT16 xSrc, INT16 ySrc, INT16 xMask, 747 INT16 yMask, INT16 xDst, 748 INT16 yDst, INT16 width, INT16 height, 749 RegionPtr dst_reg, 750 RegionPtr *src_reg, 751 RegionPtr *mask_reg) 752{ 753 struct saa_screen_priv *sscreen = saa_screen(pScreen); 754 RegionPtr srcReg = NULL; 755 RegionPtr maskReg = NULL; 756 Bool ret; 757 int xoff, yoff; 758 759 *src_reg = NULL; 760 *mask_reg = NULL; 761 762 if (pSrc->pDrawable) { 763 REGION_NULL(pScreen, &sscreen->srcReg); 764 srcReg = &sscreen->srcReg; 765 sscreen->srcDraw = pSrc->pDrawable; 766 if (pSrc != pDst) 767 REGION_TRANSLATE(pScreen, pSrc->pCompositeClip, 768 -pSrc->pDrawable->x, -pSrc->pDrawable->y); 769 } 770 771 if (pMask && pMask->pDrawable) { 772 REGION_NULL(pScreen, &sscreen->maskReg); 773 maskReg = &sscreen->maskReg; 774 if (pMask != pDst && pMask != pSrc) 775 REGION_TRANSLATE(pScreen, pMask->pCompositeClip, 776 -pMask->pDrawable->x, -pMask->pDrawable->y); 777 } 778 779 REGION_TRANSLATE(pScreen, pDst->pCompositeClip, 780 -pDst->pDrawable->x, -pDst->pDrawable->y); 781 782 sscreen->saved_SourceValidate = saa_src_validate; 783 saa_swap(sscreen, pScreen, SourceValidate); 784 ret = miComputeCompositeRegion(dst_reg, pSrc, pMask, pDst, 785 xSrc, ySrc, xMask, yMask, 786 xDst, yDst, width, height); 787 saa_swap(sscreen, pScreen, SourceValidate); 788 789 REGION_TRANSLATE(pScreen, pDst->pCompositeClip, 790 pDst->pDrawable->x, pDst->pDrawable->y); 791 if (pSrc->pDrawable && pSrc != pDst) 792 REGION_TRANSLATE(pScreen, pSrc->pCompositeClip, 793 pSrc->pDrawable->x, pSrc->pDrawable->y); 794 if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc) 795 REGION_TRANSLATE(pScreen, pMask->pCompositeClip, 796 pMask->pDrawable->x, pMask->pDrawable->y); 797 798 if (!ret) { 799 if (srcReg) 800 REGION_UNINIT(pScreen, srcReg); 801 if (maskReg) 802 REGION_UNINIT(pScreen, maskReg); 803 804 return FALSE; 805 } 806 807 *src_reg = srcReg; 808 *mask_reg = maskReg; 809 810 /* 811 * Translate dst region to pixmap space. 812 */ 813 (void) saa_get_pixmap(pDst->pDrawable, &xoff, &yoff); 814 REGION_TRANSLATE(pScreen, dst_reg, pDst->pDrawable->x + xoff, 815 pDst->pDrawable->y + yoff); 816 817 818 return TRUE; 819} 820 821static Bool 822saa_prepare_composite_reg(ScreenPtr pScreen, 823 CARD8 op, 824 PicturePtr pSrc, 825 PicturePtr pMask, 826 PicturePtr pDst, 827 INT16 xSrc, 828 INT16 ySrc, 829 INT16 xMask, 830 INT16 yMask, 831 INT16 xDst, 832 INT16 yDst, 833 CARD16 width, 834 CARD16 height, 835 RegionPtr src_region, 836 RegionPtr mask_region, 837 RegionPtr dst_region, 838 saa_access_t * access) 839{ 840 RegionPtr dstReg = NULL; 841 PixmapPtr pSrcPix = NULL; 842 PixmapPtr pMaskPix = NULL; 843 PixmapPtr pDstPix; 844 struct saa_pixmap *dst_spix; 845 846 *access = SAA_ACCESS_W; 847 848 if (pSrc->pDrawable) 849 pSrcPix = saa_get_drawable_pixmap(pSrc->pDrawable); 850 if (pMask && pMask->pDrawable) 851 pMaskPix = saa_get_drawable_pixmap(pMask->pDrawable); 852 853 /* 854 * Don't limit alphamaps readbacks for now until we've figured out how that 855 * should be done. 856 */ 857 858 if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) 859 if (!saa_pad_read(pSrc->alphaMap->pDrawable)) 860 goto out_no_src_alpha; 861 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) 862 if (!saa_pad_read(pMask->alphaMap->pDrawable)) 863 goto out_no_mask_alpha; 864 if (pSrcPix) 865 if (!saa_prepare_access_pixmap(pSrcPix, SAA_ACCESS_R, src_region)) 866 goto out_no_src; 867 if (pMaskPix) 868 if (!saa_prepare_access_pixmap(pMaskPix, SAA_ACCESS_R, mask_region)) 869 goto out_no_mask; 870 871 pDstPix = saa_get_drawable_pixmap(pDst->pDrawable); 872 dst_spix = saa_get_saa_pixmap(pDstPix); 873 874 if (dst_spix->damage && saa_op_reads_destination(op)) { 875 dstReg = dst_region; 876 *access |= SAA_ACCESS_R; 877 } 878 879 if (pDst->alphaMap && pDst->alphaMap->pDrawable) 880 if (!saa_prepare_access_pixmap 881 (saa_get_drawable_pixmap(pDst->alphaMap->pDrawable), 882 *access, dstReg)) 883 goto out_no_dst_alpha; 884 885 if (!saa_prepare_access_pixmap(pDstPix, *access, dstReg)) 886 goto out_no_dst; 887 888 return TRUE; 889 890 out_no_dst: 891 LogMessage(X_ERROR, "No dst\n"); 892 saa_finish_access_pixmap 893 (saa_get_drawable_pixmap(pDst->alphaMap->pDrawable), *access); 894 out_no_dst_alpha: 895 LogMessage(X_ERROR, "No dst alpha\n"); 896 if (pMaskPix) 897 saa_finish_access_pixmap(pMaskPix, SAA_ACCESS_R); 898 out_no_mask: 899 LogMessage(X_ERROR, "No mask\n"); 900 if (pSrcPix) 901 saa_finish_access_pixmap(pSrcPix, SAA_ACCESS_R); 902 out_no_src: 903 LogMessage(X_ERROR, "No src\n"); 904 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) 905 saa_fad_read(pMask->alphaMap->pDrawable); 906 out_no_mask_alpha: 907 LogMessage(X_ERROR, "No mask alpha\n"); 908 if (pSrc && pSrc->alphaMap && pSrc->alphaMap->pDrawable) 909 saa_fad_read(pSrc->alphaMap->pDrawable); 910 out_no_src_alpha: 911 LogMessage(X_ERROR, "No src alpha\n"); 912 return FALSE; 913 914} 915 916void 917saa_check_composite(CARD8 op, 918 PicturePtr pSrc, 919 PicturePtr pMask, 920 PicturePtr pDst, 921 INT16 xSrc, 922 INT16 ySrc, 923 INT16 xMask, 924 INT16 yMask, 925 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height, 926 RegionPtr src_region, 927 RegionPtr mask_region, 928 RegionPtr dst_region) 929{ 930 ScreenPtr pScreen = pDst->pDrawable->pScreen; 931 PictureScreenPtr ps = GetPictureScreen(pScreen); 932 struct saa_screen_priv *sscreen = saa_screen(pScreen); 933 saa_access_t access; 934 PixmapPtr pixmap; 935 936 sscreen->fallback_count++; 937 if (!saa_prepare_composite_reg(pScreen, op, pSrc, pMask, pDst, xSrc, 938 ySrc, xMask, yMask, xDst, yDst, width, 939 height, 940 src_region, 941 mask_region, 942 dst_region, 943 &access)) { 944 goto out_no_access;; 945 } 946 947 saa_swap(sscreen, ps, Composite); 948 ps->Composite(op, 949 pSrc, 950 pMask, 951 pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); 952 saa_swap(sscreen, ps, Composite); 953 if (pMask && pMask->pDrawable != NULL) 954 saa_fad_read(pMask->pDrawable); 955 if (pSrc->pDrawable != NULL) 956 saa_fad_read(pSrc->pDrawable); 957 pixmap = saa_get_drawable_pixmap(pDst->pDrawable); 958 saa_finish_access_pixmap(pixmap, access); 959 saa_pixmap_dirty(pixmap, FALSE, dst_region); 960 if (pDst->alphaMap && pDst->alphaMap->pDrawable) { 961 pixmap = saa_get_drawable_pixmap(pDst->alphaMap->pDrawable); 962 saa_finish_access_pixmap(pixmap, access); 963 saa_pixmap_dirty(pixmap, FALSE, dst_region); 964 } 965 if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) 966 saa_fad_read(pSrc->alphaMap->pDrawable); 967 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) 968 saa_fad_read(pMask->alphaMap->pDrawable); 969 out_no_access: 970 sscreen->fallback_count--; 971} 972 973static void 974saa_check_add_traps(PicturePtr pPicture, 975 INT16 x_off, INT16 y_off, int ntrap, xTrap * traps) 976{ 977 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 978 PictureScreenPtr ps = GetPictureScreen(pScreen); 979 struct saa_screen_priv *sscreen = saa_screen(pScreen); 980 saa_access_t access; 981 982 SAA_FALLBACK(("to pict %p (%c)\n", saa_drawable_loc(pPicture->pDrawable))); 983 984 sscreen->fallback_count++; 985 if (!saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) 986 goto out_no_access; 987 saa_swap(sscreen, ps, AddTraps); 988 ps->AddTraps(pPicture, x_off, y_off, ntrap, traps); 989 saa_swap(sscreen, ps, AddTraps); 990 saa_fad_write(pPicture->pDrawable, access); 991 out_no_access: 992 sscreen->fallback_count--; 993} 994 995#endif 996 997void 998saa_unaccel_setup(ScreenPtr pScreen) 999{ 1000#ifdef RENDER 1001 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 1002#endif 1003 struct saa_screen_priv *sscreen = saa_screen(pScreen); 1004 1005 saa_wrap(sscreen, pScreen, GetImage, saa_check_get_image); 1006 saa_wrap(sscreen, pScreen, GetSpans, saa_check_get_spans); 1007 saa_wrap(sscreen, pScreen, CopyWindow, saa_check_copy_window); 1008 1009#ifdef RENDER 1010 if (ps) { 1011 saa_wrap(sscreen, ps, AddTraps, saa_check_add_traps); 1012 } 1013#endif 1014} 1015 1016void 1017saa_unaccel_takedown(ScreenPtr pScreen) 1018{ 1019#ifdef RENDER 1020 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 1021#endif 1022 struct saa_screen_priv *sscreen = saa_screen(pScreen); 1023 1024 saa_unwrap(sscreen, pScreen, GetImage); 1025 saa_unwrap(sscreen, pScreen, GetSpans); 1026 saa_unwrap(sscreen, pScreen, CopyWindow); 1027 1028#ifdef RENDER 1029 if (ps) { 1030 saa_unwrap(sscreen, ps, AddTraps); 1031 } 1032#endif 1033} 1034 1035GCOps saa_gc_ops = { 1036 saa_check_fill_spans, 1037 saa_check_set_spans, 1038 saa_check_put_image, 1039 saa_copy_area, 1040 saa_check_copy_plane, 1041 saa_check_poly_point, 1042 saa_check_poly_lines, 1043 saa_check_poly_segment, 1044 miPolyRectangle, 1045 saa_check_poly_arc, 1046 miFillPolygon, 1047 saa_check_poly_fill_rect, 1048 miPolyFillArc, 1049 miPolyText8, 1050 miPolyText16, 1051 miImageText8, 1052 miImageText16, 1053 saa_check_image_glyph_blt, 1054 saa_check_poly_glyph_blt, 1055 saa_check_push_pixels, 1056}; 1057