1/* 2 * Copyright © 2001 Keith Packard 3 * 2010 Intel Corporation 4 * 2012,2015 Advanced Micro Devices, Inc. 5 * 6 * Partly based on code Copyright © 2008 Red Hat, Inc. 7 * Partly based on code Copyright © 2000 SuSE, Inc. 8 * 9 * Partly based on code that is Copyright © The XFree86 Project Inc. 10 * 11 * Permission to use, copy, modify, distribute, and sell this software and its 12 * documentation for any purpose is hereby granted without fee, provided that 13 * the above copyright notice appear in all copies and that both that 14 * copyright notice and this permission notice appear in supporting 15 * documentation, and that the name of the opyright holders not be used in 16 * advertising or publicity pertaining to distribution of the software without 17 * specific, written prior permission. The copyright holders make no 18 * representations about the suitability of this software for any purpose. It 19 * is provided "as is" without express or implied warranty. 20 * 21 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 22 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 23 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 25 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 26 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 27 * PERFORMANCE OF THIS SOFTWARE. 28 */ 29 30 31#ifdef HAVE_CONFIG_H 32#include <config.h> 33#endif 34 35#ifdef USE_GLAMOR 36 37#include "radeon.h" 38#include "radeon_bo_helper.h" 39#include "radeon_glamor.h" 40 41 42/* Are there any outstanding GPU operations for this pixmap? */ 43static Bool 44radeon_glamor_gpu_pending(uint_fast32_t gpu_synced, uint_fast32_t gpu_access) 45{ 46 return (int_fast32_t)(gpu_access - gpu_synced) > 0; 47} 48 49/* 50 * Pixmap CPU access wrappers 51 */ 52 53static Bool 54radeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info, 55 PixmapPtr pixmap, struct radeon_pixmap *priv, 56 Bool need_sync) 57{ 58 struct radeon_buffer *bo = priv->bo; 59 int ret; 60 61 if (!pixmap->devPrivate.ptr) { 62 /* When falling back to swrast, flush all pending operations */ 63 if (need_sync) { 64 glamor_block_handler(scrn->pScreen); 65 info->gpu_flushed++; 66 } 67 68 ret = radeon_bo_map(bo->bo.radeon, 1); 69 if (ret) { 70 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 71 "%s: bo map (tiling_flags %d) failed: %s\n", 72 __FUNCTION__, 73 priv->tiling_flags, 74 strerror(-ret)); 75 return FALSE; 76 } 77 78 pixmap->devPrivate.ptr = bo->bo.radeon->ptr; 79 } else if (need_sync) 80 radeon_finish(scrn, bo); 81 82 info->gpu_synced = info->gpu_flushed; 83 84 return TRUE; 85} 86 87static Bool 88radeon_glamor_prepare_access_cpu_ro(ScrnInfoPtr scrn, PixmapPtr pixmap, 89 struct radeon_pixmap *priv) 90{ 91 RADEONInfoPtr info; 92 Bool need_sync; 93 94 if (!priv) 95 return TRUE; 96 97 info = RADEONPTR(scrn); 98 need_sync = radeon_glamor_gpu_pending(info->gpu_synced, priv->gpu_write); 99 return radeon_glamor_prepare_access_cpu(scrn, RADEONPTR(scrn), pixmap, 100 priv, need_sync); 101} 102 103static Bool 104radeon_glamor_prepare_access_cpu_rw(ScrnInfoPtr scrn, PixmapPtr pixmap, 105 struct radeon_pixmap *priv) 106{ 107 RADEONInfoPtr info; 108 uint_fast32_t gpu_synced; 109 Bool need_sync; 110 111 if (!priv) 112 return TRUE; 113 114 info = RADEONPTR(scrn); 115 gpu_synced = info->gpu_synced; 116 need_sync = radeon_glamor_gpu_pending(gpu_synced, priv->gpu_write) | 117 radeon_glamor_gpu_pending(gpu_synced, priv->gpu_read); 118 return radeon_glamor_prepare_access_cpu(scrn, info, pixmap, priv, 119 need_sync); 120} 121 122static void 123radeon_glamor_finish_access_cpu(PixmapPtr pixmap) 124{ 125 /* Nothing to do */ 126} 127 128/* 129 * Pixmap GPU access wrappers 130 */ 131 132static Bool 133radeon_glamor_prepare_access_gpu(struct radeon_pixmap *priv) 134{ 135 return !!priv; 136} 137 138static void 139radeon_glamor_finish_access_gpu_ro(RADEONInfoPtr info, 140 struct radeon_pixmap *priv) 141{ 142 priv->gpu_read = info->gpu_flushed + 1; 143} 144 145static void 146radeon_glamor_finish_access_gpu_rw(RADEONInfoPtr info, 147 struct radeon_pixmap *priv) 148{ 149 priv->gpu_write = priv->gpu_read = info->gpu_flushed + 1; 150} 151 152/* 153 * GC CPU access wrappers 154 */ 155 156static Bool 157radeon_glamor_prepare_access_gc(ScrnInfoPtr scrn, GCPtr pGC) 158{ 159 struct radeon_pixmap *priv; 160 161 if (pGC->stipple) { 162 priv = radeon_get_pixmap_private(pGC->stipple); 163 if (!radeon_glamor_prepare_access_cpu_ro(scrn, pGC->stipple, priv)) 164 return FALSE; 165 } 166 if (pGC->fillStyle == FillTiled) { 167 priv = radeon_get_pixmap_private(pGC->tile.pixmap); 168 if (!radeon_glamor_prepare_access_cpu_ro(scrn, pGC->tile.pixmap, 169 priv)) { 170 if (pGC->stipple) 171 radeon_glamor_finish_access_cpu(pGC->stipple); 172 return FALSE; 173 } 174 } 175 return TRUE; 176} 177 178static void 179radeon_glamor_finish_access_gc(GCPtr pGC) 180{ 181 if (pGC->fillStyle == FillTiled) 182 radeon_glamor_finish_access_cpu(pGC->tile.pixmap); 183 if (pGC->stipple) 184 radeon_glamor_finish_access_cpu(pGC->stipple); 185} 186 187/* 188 * Picture CPU access wrappers 189 */ 190 191static void 192radeon_glamor_picture_finish_access_cpu(PicturePtr picture) 193{ 194 /* Nothing to do */ 195} 196 197static Bool 198radeon_glamor_picture_prepare_access_cpu_ro(ScrnInfoPtr scrn, 199 PicturePtr picture) 200{ 201 PixmapPtr pixmap; 202 struct radeon_pixmap *priv; 203 204 if (!picture->pDrawable) 205 return TRUE; 206 207 pixmap = get_drawable_pixmap(picture->pDrawable); 208 priv = radeon_get_pixmap_private(pixmap); 209 if (!radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) 210 return FALSE; 211 212 if (picture->alphaMap) { 213 pixmap = get_drawable_pixmap(picture->alphaMap->pDrawable); 214 priv = radeon_get_pixmap_private(pixmap); 215 if (!radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) { 216 radeon_glamor_picture_finish_access_cpu(picture); 217 return FALSE; 218 } 219 } 220 221 return TRUE; 222} 223 224static Bool 225radeon_glamor_picture_prepare_access_cpu_rw(ScrnInfoPtr scrn, 226 PicturePtr picture) 227{ 228 PixmapPtr pixmap; 229 struct radeon_pixmap *priv; 230 231 pixmap = get_drawable_pixmap(picture->pDrawable); 232 priv = radeon_get_pixmap_private(pixmap); 233 if (!radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) 234 return FALSE; 235 236 if (picture->alphaMap) { 237 pixmap = get_drawable_pixmap(picture->alphaMap->pDrawable); 238 priv = radeon_get_pixmap_private(pixmap); 239 if (!radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 240 radeon_glamor_picture_finish_access_cpu(picture); 241 return FALSE; 242 } 243 } 244 245 return TRUE; 246} 247 248/* 249 * GC rendering wrappers 250 */ 251 252static void 253radeon_glamor_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans, 254 DDXPointPtr ppt, int *pwidth, int fSorted) 255{ 256 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 257 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 258 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 259 260 if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 261 if (radeon_glamor_prepare_access_gc(scrn, pGC)) { 262 fbFillSpans(pDrawable, pGC, nspans, ppt, pwidth, 263 fSorted); 264 radeon_glamor_finish_access_gc(pGC); 265 } 266 radeon_glamor_finish_access_cpu(pixmap); 267 } 268} 269 270static void 271radeon_glamor_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc, 272 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) 273{ 274 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 275 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 276 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 277 278 if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 279 fbSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); 280 radeon_glamor_finish_access_cpu(pixmap); 281 } 282} 283 284static void 285radeon_glamor_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, 286 int x, int y, int w, int h, int leftPad, int format, 287 char *bits) 288{ 289 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 290 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 291 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 292 293 if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 294 fbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, 295 bits); 296 radeon_glamor_finish_access_cpu(pixmap); 297 } 298} 299 300static RegionPtr 301radeon_glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 302 int srcx, int srcy, int w, int h, int dstx, int dsty, 303 unsigned long bitPlane) 304{ 305 ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pScreen); 306 PixmapPtr dst_pix = get_drawable_pixmap(pDst); 307 struct radeon_pixmap *dst_priv = radeon_get_pixmap_private(dst_pix); 308 RegionPtr ret = NULL; 309 310 if (radeon_glamor_prepare_access_cpu_rw(scrn, dst_pix, dst_priv)) { 311 PixmapPtr src_pix = get_drawable_pixmap(pSrc); 312 struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pix); 313 if (radeon_glamor_prepare_access_cpu_ro(scrn, src_pix, src_priv)) { 314 ret = 315 fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, 316 dsty, bitPlane); 317 radeon_glamor_finish_access_cpu(src_pix); 318 } 319 radeon_glamor_finish_access_cpu(dst_pix); 320 } 321 return ret; 322} 323 324static RegionPtr 325radeon_glamor_copy_plane_nodstbo(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 326 int srcx, int srcy, int w, int h, 327 int dstx, int dsty, unsigned long bitPlane) 328{ 329 ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pScreen); 330 PixmapPtr src_pix = get_drawable_pixmap(pSrc); 331 struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pix); 332 RegionPtr ret = NULL; 333 334 if (radeon_glamor_prepare_access_cpu_ro(scrn, src_pix, src_priv)) { 335 ret = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, 336 dstx, dsty, bitPlane); 337 radeon_glamor_finish_access_cpu(src_pix); 338 } 339 return ret; 340} 341 342static void 343radeon_glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 344 DDXPointPtr pptInit) 345{ 346 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 347 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 348 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 349 350 if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 351 fbPolyPoint(pDrawable, pGC, mode, npt, pptInit); 352 radeon_glamor_finish_access_cpu(pixmap); 353 } 354} 355 356static void 357radeon_glamor_poly_lines(DrawablePtr pDrawable, GCPtr pGC, 358 int mode, int npt, DDXPointPtr ppt) 359{ 360 if (pGC->lineWidth == 0) { 361 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 362 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 363 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 364 365 if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 366 if (radeon_glamor_prepare_access_gc(scrn, pGC)) { 367 fbPolyLine(pDrawable, pGC, mode, npt, ppt); 368 radeon_glamor_finish_access_gc(pGC); 369 } 370 radeon_glamor_finish_access_cpu(pixmap); 371 } 372 return; 373 } 374 /* fb calls mi functions in the lineWidth != 0 case. */ 375 fbPolyLine(pDrawable, pGC, mode, npt, ppt); 376} 377 378static void 379radeon_glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, 380 int nsegInit, xSegment *pSegInit) 381{ 382 if (pGC->lineWidth == 0) { 383 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 384 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 385 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 386 387 if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 388 if (radeon_glamor_prepare_access_gc(scrn, pGC)) { 389 fbPolySegment(pDrawable, pGC, nsegInit, 390 pSegInit); 391 radeon_glamor_finish_access_gc(pGC); 392 } 393 radeon_glamor_finish_access_cpu(pixmap); 394 } 395 return; 396 } 397 /* fb calls mi functions in the lineWidth != 0 case. */ 398 fbPolySegment(pDrawable, pGC, nsegInit, pSegInit); 399} 400 401static void 402radeon_glamor_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC, 403 int nrect, xRectangle *prect) 404{ 405 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 406 RADEONInfoPtr info = RADEONPTR(scrn); 407 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 408 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 409 410 if ((info->accel_state->force || (priv && !priv->bo)) && 411 radeon_glamor_prepare_access_gpu(priv)) { 412 info->glamor.SavedPolyFillRect(pDrawable, pGC, nrect, prect); 413 radeon_glamor_finish_access_gpu_rw(info, priv); 414 return; 415 } 416 417 if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 418 if (radeon_glamor_prepare_access_gc(scrn, pGC)) { 419 fbPolyFillRect(pDrawable, pGC, nrect, prect); 420 radeon_glamor_finish_access_gc(pGC); 421 } 422 radeon_glamor_finish_access_cpu(pixmap); 423 } 424} 425 426static void 427radeon_glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, 428 int x, int y, unsigned int nglyph, 429 CharInfoPtr *ppci, pointer pglyphBase) 430{ 431 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 432 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 433 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 434 435 if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 436 if (radeon_glamor_prepare_access_gc(scrn, pGC)) { 437 fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, 438 pglyphBase); 439 radeon_glamor_finish_access_gc(pGC); 440 } 441 radeon_glamor_finish_access_cpu(pixmap); 442 } 443} 444 445static void 446radeon_glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, 447 int x, int y, unsigned int nglyph, 448 CharInfoPtr *ppci, pointer pglyphBase) 449{ 450 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 451 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 452 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 453 454 if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 455 if (radeon_glamor_prepare_access_gc(scrn, pGC)) { 456 fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, 457 pglyphBase); 458 radeon_glamor_finish_access_gc(pGC); 459 } 460 radeon_glamor_finish_access_cpu(pixmap); 461 } 462} 463 464static void 465radeon_glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, 466 DrawablePtr pDrawable, int w, int h, int x, int y) 467{ 468 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 469 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 470 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 471 472 if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 473 priv = radeon_get_pixmap_private(pBitmap); 474 if (radeon_glamor_prepare_access_cpu_ro(scrn, pBitmap, priv)) { 475 if (radeon_glamor_prepare_access_gc(scrn, pGC)) { 476 fbPushPixels(pGC, pBitmap, pDrawable, w, h, x, 477 y); 478 radeon_glamor_finish_access_gc(pGC); 479 } 480 radeon_glamor_finish_access_cpu(pBitmap); 481 } 482 radeon_glamor_finish_access_cpu(pixmap); 483 } 484} 485 486static void 487radeon_glamor_push_pixels_nodstbo(GCPtr pGC, PixmapPtr pBitmap, 488 DrawablePtr pDrawable, int w, int h, 489 int x, int y) 490{ 491 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 492 struct radeon_pixmap *priv = radeon_get_pixmap_private(pBitmap); 493 494 if (radeon_glamor_prepare_access_cpu_ro(scrn, pBitmap, priv)) { 495 fbPushPixels(pGC, pBitmap, pDrawable, w, h, x, y); 496 radeon_glamor_finish_access_cpu(pBitmap); 497 } 498} 499 500static RegionPtr 501radeon_glamor_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, 502 GCPtr pGC, int srcx, int srcy, int width, int height, 503 int dstx, int dsty) 504{ 505 ScreenPtr screen = pDstDrawable->pScreen; 506 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 507 RADEONInfoPtr info = RADEONPTR(scrn); 508 PixmapPtr src_pixmap = get_drawable_pixmap(pSrcDrawable); 509 PixmapPtr dst_pixmap = get_drawable_pixmap(pDstDrawable); 510 struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pixmap); 511 struct radeon_pixmap *dst_priv = radeon_get_pixmap_private(dst_pixmap); 512 RegionPtr ret = NULL; 513 514 if (info->accel_state->force || (src_priv && !src_priv->bo) || 515 (dst_priv && !dst_priv->bo)) { 516 if (!radeon_glamor_prepare_access_gpu(dst_priv)) 517 goto fallback; 518 if (src_priv != dst_priv && 519 !radeon_glamor_prepare_access_gpu(src_priv)) 520 goto fallback; 521 522 ret = info->glamor.SavedCopyArea(pSrcDrawable, pDstDrawable, 523 pGC, srcx, srcy, 524 width, height, dstx, dsty); 525 radeon_glamor_finish_access_gpu_rw(info, dst_priv); 526 if (src_priv != dst_priv) 527 radeon_glamor_finish_access_gpu_ro(info, src_priv); 528 529 return ret; 530 } 531 532fallback: 533 if (radeon_glamor_prepare_access_cpu_rw(scrn, dst_pixmap, dst_priv)) { 534 if (pSrcDrawable == pDstDrawable || 535 radeon_glamor_prepare_access_cpu_ro(scrn, src_pixmap, 536 src_priv)) { 537 ret = fbCopyArea(pSrcDrawable, pDstDrawable, pGC, 538 srcx, srcy, width, height, dstx, dsty); 539 if (pSrcDrawable != pDstDrawable) 540 radeon_glamor_finish_access_cpu(src_pixmap); 541 } 542 radeon_glamor_finish_access_cpu(dst_pixmap); 543 } 544 545 return ret; 546} 547 548static RegionPtr 549radeon_glamor_copy_area_nodstbo(DrawablePtr pSrcDrawable, 550 DrawablePtr pDstDrawable, GCPtr pGC, 551 int srcx, int srcy, int width, int height, 552 int dstx, int dsty) 553{ 554 ScreenPtr screen = pDstDrawable->pScreen; 555 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 556 PixmapPtr src_pixmap = get_drawable_pixmap(pSrcDrawable); 557 PixmapPtr dst_pixmap = get_drawable_pixmap(pDstDrawable); 558 struct radeon_pixmap *src_priv; 559 RegionPtr ret = NULL; 560 561 if (src_pixmap != dst_pixmap) { 562 src_priv = radeon_get_pixmap_private(src_pixmap); 563 564 if (!radeon_glamor_prepare_access_cpu_ro(scrn, src_pixmap, 565 src_priv)) 566 return ret; 567 } 568 569 ret = fbCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, 570 width, height, dstx, dsty); 571 572 if (src_pixmap != dst_pixmap) 573 radeon_glamor_finish_access_cpu(src_pixmap); 574 575 return ret; 576} 577 578static const GCOps radeon_glamor_ops = { 579 radeon_glamor_fill_spans, 580 radeon_glamor_set_spans, 581 radeon_glamor_put_image, 582 radeon_glamor_copy_area, 583 radeon_glamor_copy_plane, 584 radeon_glamor_poly_point, 585 radeon_glamor_poly_lines, 586 radeon_glamor_poly_segment, 587 miPolyRectangle, 588 miPolyArc, 589 miFillPolygon, 590 radeon_glamor_poly_fill_rect, 591 miPolyFillArc, 592 miPolyText8, 593 miPolyText16, 594 miImageText8, 595 miImageText16, 596 radeon_glamor_image_glyph_blt, 597 radeon_glamor_poly_glyph_blt, 598 radeon_glamor_push_pixels, 599}; 600 601static GCOps radeon_glamor_nodstbo_ops; 602 603/** 604 * radeon_glamor_validate_gc() sets the ops to our implementations, which may be 605 * accelerated or may sync the card and fall back to fb. 606 */ 607static void 608radeon_glamor_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 609{ 610 ScrnInfoPtr scrn = xf86ScreenToScrn(pGC->pScreen); 611 RADEONInfoPtr info = RADEONPTR(scrn); 612 613 glamor_validate_gc(pGC, changes, pDrawable); 614 info->glamor.SavedCopyArea = pGC->ops->CopyArea; 615 info->glamor.SavedPolyFillRect = pGC->ops->PolyFillRect; 616 617 if (radeon_get_pixmap_private(get_drawable_pixmap(pDrawable)) || 618 (pGC->stipple && radeon_get_pixmap_private(pGC->stipple)) || 619 (pGC->fillStyle == FillTiled && 620 radeon_get_pixmap_private(pGC->tile.pixmap))) 621 pGC->ops = (GCOps *)&radeon_glamor_ops; 622 else 623 pGC->ops = &radeon_glamor_nodstbo_ops; 624} 625 626static GCFuncs glamorGCFuncs = { 627 radeon_glamor_validate_gc, 628 miChangeGC, 629 miCopyGC, 630 miDestroyGC, 631 miChangeClip, 632 miDestroyClip, 633 miCopyClip 634}; 635 636/** 637 * radeon_glamor_create_gc makes a new GC and hooks up its funcs handler, so that 638 * radeon_glamor_validate_gc() will get called. 639 */ 640static int 641radeon_glamor_create_gc(GCPtr pGC) 642{ 643 static Bool nodstbo_ops_initialized; 644 645 if (!fbCreateGC(pGC)) 646 return FALSE; 647 648 if (!nodstbo_ops_initialized) { 649 radeon_glamor_nodstbo_ops = radeon_glamor_ops; 650 651 radeon_glamor_nodstbo_ops.FillSpans = pGC->ops->FillSpans; 652 radeon_glamor_nodstbo_ops.SetSpans = pGC->ops->SetSpans; 653 radeon_glamor_nodstbo_ops.PutImage = pGC->ops->PutImage; 654 radeon_glamor_nodstbo_ops.CopyArea = radeon_glamor_copy_area_nodstbo; 655 radeon_glamor_nodstbo_ops.CopyPlane = radeon_glamor_copy_plane_nodstbo; 656 radeon_glamor_nodstbo_ops.PolyPoint = pGC->ops->PolyPoint; 657 radeon_glamor_nodstbo_ops.Polylines = pGC->ops->Polylines; 658 radeon_glamor_nodstbo_ops.PolySegment = pGC->ops->PolySegment; 659 radeon_glamor_nodstbo_ops.PolyFillRect = pGC->ops->PolyFillRect; 660 radeon_glamor_nodstbo_ops.ImageGlyphBlt = pGC->ops->ImageGlyphBlt; 661 radeon_glamor_nodstbo_ops.PolyGlyphBlt = pGC->ops->PolyGlyphBlt; 662 radeon_glamor_nodstbo_ops.PushPixels = radeon_glamor_push_pixels_nodstbo; 663 664 nodstbo_ops_initialized = TRUE; 665 } 666 667 pGC->funcs = &glamorGCFuncs; 668 669 return TRUE; 670} 671 672/* 673 * Screen rendering wrappers 674 */ 675 676static RegionPtr 677radeon_glamor_bitmap_to_region(PixmapPtr pPix) 678{ 679 ScrnInfoPtr scrn = xf86ScreenToScrn(pPix->drawable.pScreen); 680 struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix); 681 RegionPtr ret; 682 683 if (!radeon_glamor_prepare_access_cpu_ro(scrn, pPix, priv)) 684 return NULL; 685 ret = fbPixmapToRegion(pPix); 686 radeon_glamor_finish_access_cpu(pPix); 687 return ret; 688} 689 690static void 691radeon_glamor_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, 692 RegionPtr prgnSrc) 693{ 694 ScrnInfoPtr scrn = xf86ScreenToScrn(pWin->drawable.pScreen); 695 PixmapPtr pixmap = get_drawable_pixmap(&pWin->drawable); 696 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 697 698 if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) { 699 fbCopyWindow(pWin, ptOldOrg, prgnSrc); 700 radeon_glamor_finish_access_cpu(pixmap); 701 } 702} 703 704static void 705radeon_glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, 706 unsigned int format, unsigned long planeMask, char *d) 707{ 708 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 709 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 710 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 711 712 if (radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) { 713 fbGetImage(pDrawable, x, y, w, h, format, planeMask, d); 714 radeon_glamor_finish_access_cpu(pixmap); 715 } 716} 717 718static void 719radeon_glamor_get_spans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, 720 int *pwidth, int nspans, char *pdstStart) 721{ 722 ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen); 723 PixmapPtr pixmap = get_drawable_pixmap(pDrawable); 724 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 725 726 if (radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) { 727 fbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart); 728 radeon_glamor_finish_access_cpu(pixmap); 729 } 730} 731 732/* 733 * Picture screen rendering wrappers 734 */ 735 736#ifdef RENDER 737 738static void 739radeon_glamor_composite(CARD8 op, 740 PicturePtr pSrc, 741 PicturePtr pMask, 742 PicturePtr pDst, 743 INT16 xSrc, INT16 ySrc, 744 INT16 xMask, INT16 yMask, 745 INT16 xDst, INT16 yDst, 746 CARD16 width, CARD16 height) 747{ 748 ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pDrawable->pScreen); 749 RADEONInfoPtr info; 750 PixmapPtr pixmap; 751 struct radeon_pixmap *dst_priv, *src_priv = NULL, *mask_priv = NULL; 752 Bool gpu_done = FALSE; 753 754 if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) 755 goto fallback; 756 757 pixmap = get_drawable_pixmap(pDst->pDrawable); 758 if (&pixmap->drawable != pDst->pDrawable || 759 pixmap->usage_hint != RADEON_CREATE_PIXMAP_SCANOUT) 760 goto fallback; 761 762 dst_priv = radeon_get_pixmap_private(pixmap); 763 if (!radeon_glamor_prepare_access_gpu(dst_priv)) 764 goto fallback; 765 766 info = RADEONPTR(scrn); 767 if (!pSrc->pDrawable || 768 ((pixmap = get_drawable_pixmap(pSrc->pDrawable)) && 769 (src_priv = radeon_get_pixmap_private(pixmap)) && 770 radeon_glamor_prepare_access_gpu(src_priv))) { 771 if (!pMask || !pMask->pDrawable || 772 ((pixmap = get_drawable_pixmap(pMask->pDrawable)) && 773 (mask_priv = radeon_get_pixmap_private(pixmap)) && 774 radeon_glamor_prepare_access_gpu(mask_priv))) { 775 info->glamor.SavedComposite(op, pSrc, pMask, pDst, 776 xSrc, ySrc, xMask, yMask, 777 xDst, yDst, width, height); 778 gpu_done = TRUE; 779 780 if (mask_priv) 781 radeon_glamor_finish_access_gpu_ro(info, mask_priv); 782 } 783 784 if (src_priv) 785 radeon_glamor_finish_access_gpu_ro(info, src_priv); 786 } 787 radeon_glamor_finish_access_gpu_rw(info, dst_priv); 788 789 if (gpu_done) 790 return; 791 792fallback: 793 if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, pDst)) { 794 if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, pSrc)) { 795 if (!pMask || 796 radeon_glamor_picture_prepare_access_cpu_ro(scrn, pMask)) { 797 fbComposite(op, pSrc, pMask, pDst, 798 xSrc, ySrc, 799 xMask, yMask, 800 xDst, yDst, 801 width, height); 802 if (pMask) 803 radeon_glamor_picture_finish_access_cpu(pMask); 804 } 805 radeon_glamor_picture_finish_access_cpu(pSrc); 806 } 807 radeon_glamor_picture_finish_access_cpu(pDst); 808 } 809} 810 811static void 812radeon_glamor_add_traps(PicturePtr pPicture, 813 INT16 x_off, INT16 y_off, int ntrap, xTrap *traps) 814{ 815 ScrnInfoPtr scrn = xf86ScreenToScrn(pPicture->pDrawable->pScreen); 816 817 if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, pPicture)) { 818 fbAddTraps(pPicture, x_off, y_off, ntrap, traps); 819 radeon_glamor_picture_finish_access_cpu(pPicture); 820 } 821} 822 823static void 824radeon_glamor_glyphs(CARD8 op, 825 PicturePtr src, 826 PicturePtr dst, 827 PictFormatPtr maskFormat, 828 INT16 xSrc, 829 INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs) 830{ 831 ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen); 832 833 if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) { 834 if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) { 835 RADEONInfoPtr info = RADEONPTR(scrn); 836 837 info->glamor.SavedGlyphs(op, src, dst, maskFormat, xSrc, 838 ySrc, nlist, list, glyphs); 839 radeon_glamor_picture_finish_access_cpu(src); 840 } 841 radeon_glamor_picture_finish_access_cpu(dst); 842 } 843} 844 845static void 846radeon_glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, 847 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 848 int ntrap, xTrapezoid *traps) 849{ 850 ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen); 851 852 if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) { 853 if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) { 854 RADEONInfoPtr info = RADEONPTR(scrn); 855 856 info->glamor.SavedTrapezoids(op, src, dst, maskFormat, 857 xSrc, ySrc, ntrap, traps); 858 radeon_glamor_picture_finish_access_cpu(src); 859 } 860 radeon_glamor_picture_finish_access_cpu(dst); 861 } 862} 863 864static void 865radeon_glamor_triangles(CARD8 op, PicturePtr src, PicturePtr dst, 866 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 867 int ntri, xTriangle *tri) 868{ 869 ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen); 870 871 if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) { 872 if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) { 873 RADEONInfoPtr info = RADEONPTR(scrn); 874 875 info->glamor.SavedTriangles(op, src, dst, maskFormat, 876 xSrc, ySrc, ntri, tri); 877 radeon_glamor_picture_finish_access_cpu(src); 878 } 879 radeon_glamor_picture_finish_access_cpu(dst); 880 } 881} 882 883#endif /* RENDER */ 884 885 886/** 887 * radeon_glamor_close_screen() unwraps its wrapped screen functions and tears 888 * down our screen private, before calling down to the next CloseScreen. 889 */ 890static Bool 891radeon_glamor_close_screen(ScreenPtr pScreen) 892{ 893 RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pScreen)); 894#ifdef RENDER 895 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 896#endif 897 898 pScreen->CreateGC = info->glamor.SavedCreateGC; 899 pScreen->CloseScreen = info->glamor.SavedCloseScreen; 900 pScreen->GetImage = info->glamor.SavedGetImage; 901 pScreen->GetSpans = info->glamor.SavedGetSpans; 902 pScreen->CopyWindow = info->glamor.SavedCopyWindow; 903 pScreen->ChangeWindowAttributes = 904 info->glamor.SavedChangeWindowAttributes; 905 pScreen->BitmapToRegion = info->glamor.SavedBitmapToRegion; 906#ifdef RENDER 907 if (ps) { 908 ps->Composite = info->glamor.SavedComposite; 909 ps->Glyphs = info->glamor.SavedGlyphs; 910 ps->UnrealizeGlyph = info->glamor.SavedUnrealizeGlyph; 911 ps->Trapezoids = info->glamor.SavedTrapezoids; 912 ps->AddTraps = info->glamor.SavedAddTraps; 913 ps->Triangles = info->glamor.SavedTriangles; 914 915 ps->UnrealizeGlyph = info->glamor.SavedUnrealizeGlyph; 916 } 917#endif 918 919 return pScreen->CloseScreen(pScreen); 920} 921 922/** 923 * @param screen screen being initialized 924 */ 925void 926radeon_glamor_screen_init(ScreenPtr screen) 927{ 928 RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen)); 929 930 /* 931 * Replace various fb screen functions 932 */ 933 info->glamor.SavedCloseScreen = screen->CloseScreen; 934 screen->CloseScreen = radeon_glamor_close_screen; 935 936 info->glamor.SavedCreateGC = screen->CreateGC; 937 screen->CreateGC = radeon_glamor_create_gc; 938 939 info->glamor.SavedGetImage = screen->GetImage; 940 screen->GetImage = radeon_glamor_get_image; 941 942 info->glamor.SavedGetSpans = screen->GetSpans; 943 screen->GetSpans = radeon_glamor_get_spans; 944 945 info->glamor.SavedCopyWindow = screen->CopyWindow; 946 screen->CopyWindow = radeon_glamor_copy_window; 947 948 info->glamor.SavedBitmapToRegion = screen->BitmapToRegion; 949 screen->BitmapToRegion = radeon_glamor_bitmap_to_region; 950 951#ifdef RENDER 952 { 953 PictureScreenPtr ps = GetPictureScreenIfSet(screen); 954 if (ps) { 955 info->glamor.SavedComposite = ps->Composite; 956 ps->Composite = radeon_glamor_composite; 957 958 info->glamor.SavedUnrealizeGlyph = ps->UnrealizeGlyph; 959 960 ps->Glyphs = radeon_glamor_glyphs; 961 ps->Triangles = radeon_glamor_triangles; 962 ps->Trapezoids = radeon_glamor_trapezoids; 963 964 info->glamor.SavedAddTraps = ps->AddTraps; 965 ps->AddTraps = radeon_glamor_add_traps; 966 } 967 } 968#endif 969} 970 971#endif /* USE_GLAMOR */ 972