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