xorg_exa.c revision 1e9eb69f835e35116b8ada0fc2f05561fd8956d1
1/* 2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 3 * 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 * 26 * Author: Alan Hourihane <alanh@tungstengraphics.com> 27 * Author: Jakob Bornecrantz <wallbraker@gmail.com> 28 * 29 */ 30 31#include "xorg_exa.h" 32#include "xorg_tracker.h" 33#include "xorg_composite.h" 34#include "xorg_exa_tgsi.h" 35 36#include <xorg-server.h> 37#include <xf86.h> 38#include <picturestr.h> 39#include <picture.h> 40 41#include "pipe/p_format.h" 42#include "pipe/p_context.h" 43#include "pipe/p_state.h" 44#include "pipe/p_inlines.h" 45 46#include "cso_cache/cso_context.h" 47 48#include "util/u_rect.h" 49 50/* 51 * Helper functions 52 */ 53 54static void 55exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp) 56{ 57 switch (depth) { 58 case 32: 59 *format = PIPE_FORMAT_A8R8G8B8_UNORM; 60 assert(*bbp == 32); 61 break; 62 case 24: 63 *format = PIPE_FORMAT_X8R8G8B8_UNORM; 64 assert(*bbp == 32); 65 break; 66 case 16: 67 *format = PIPE_FORMAT_R5G6B5_UNORM; 68 assert(*bbp == 16); 69 break; 70 case 15: 71 *format = PIPE_FORMAT_A1R5G5B5_UNORM; 72 assert(*bbp == 16); 73 break; 74 case 8: 75 case 4: 76 case 1: 77 *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */ 78 break; 79 default: 80 assert(0); 81 break; 82 } 83} 84 85/* 86 * Static exported EXA functions 87 */ 88 89static void 90ExaWaitMarker(ScreenPtr pScreen, int marker) 91{ 92} 93 94static int 95ExaMarkSync(ScreenPtr pScreen) 96{ 97 return 1; 98} 99 100static Bool 101ExaPrepareAccess(PixmapPtr pPix, int index) 102{ 103 ScreenPtr pScreen = pPix->drawable.pScreen; 104 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 105 modesettingPtr ms = modesettingPTR(pScrn); 106 struct exa_context *exa = ms->exa; 107 struct exa_pixmap_priv *priv; 108 109 priv = exaGetPixmapDriverPrivate(pPix); 110 111 if (!priv) 112 return FALSE; 113 114 if (!priv->tex) 115 return FALSE; 116 117 if (priv->map_count++ == 0) 118 { 119 if (exa->ctx->is_texture_referenced(exa->ctx, priv->tex, 0, 0) & 120 PIPE_REFERENCED_FOR_WRITE) 121 exa->ctx->flush(exa->ctx, 0, NULL); 122 123 priv->map_transfer = 124 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, 125 PIPE_TRANSFER_READ_WRITE, 126 0, 0, priv->tex->width[0], priv->tex->height[0]); 127 128 pPix->devPrivate.ptr = 129 exa->scrn->transfer_map(exa->scrn, priv->map_transfer); 130 pPix->devKind = priv->map_transfer->stride; 131 } 132 133 return TRUE; 134} 135 136static void 137ExaFinishAccess(PixmapPtr pPix, int index) 138{ 139 ScreenPtr pScreen = pPix->drawable.pScreen; 140 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 141 modesettingPtr ms = modesettingPTR(pScrn); 142 struct exa_context *exa = ms->exa; 143 struct exa_pixmap_priv *priv; 144 priv = exaGetPixmapDriverPrivate(pPix); 145 146 if (!priv) 147 return; 148 149 if (!priv->map_transfer) 150 return; 151 152 if (--priv->map_count == 0) { 153 assert(priv->map_transfer); 154 exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer); 155 exa->scrn->tex_transfer_destroy(priv->map_transfer); 156 priv->map_transfer = NULL; 157 pPix->devPrivate.ptr = NULL; 158 } 159} 160 161static void 162ExaDone(PixmapPtr pPixmap) 163{ 164 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 165 modesettingPtr ms = modesettingPTR(pScrn); 166 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); 167 struct exa_context *exa = ms->exa; 168 169 if (!priv) 170 return; 171 172 if (priv->src_surf) 173 exa->scrn->tex_surface_destroy(priv->src_surf); 174 priv->src_surf = NULL; 175} 176 177static void 178ExaDoneComposite(PixmapPtr pPixmap) 179{ 180 181} 182 183static Bool 184ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg) 185{ 186 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 187 modesettingPtr ms = modesettingPTR(pScrn); 188 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); 189 struct exa_context *exa = ms->exa; 190 191 if (1) 192 return FALSE; 193 194 if (pPixmap->drawable.depth < 15) 195 return FALSE; 196 197 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask)) 198 return FALSE; 199 200 if (!priv || !priv->tex) 201 return FALSE; 202 203 if (alu != GXcopy) 204 return FALSE; 205 206 if (!exa->ctx || !exa->ctx->surface_fill) 207 return FALSE; 208 209 priv->color = fg; 210 211 return TRUE; 212} 213 214static void 215ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1) 216{ 217 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 218 modesettingPtr ms = modesettingPTR(pScrn); 219 struct exa_context *exa = ms->exa; 220 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); 221 struct pipe_surface *surf = exa_gpu_surface(exa, priv); 222 223 exa->ctx->surface_fill(exa->ctx, surf, x0, y0, x1 - x0, y1 - y0, 224 priv->color); 225 226 exa->scrn->tex_surface_destroy(surf); 227} 228 229static Bool 230ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, 231 int ydir, int alu, Pixel planeMask) 232{ 233 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 234 modesettingPtr ms = modesettingPTR(pScrn); 235 struct exa_context *exa = ms->exa; 236 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap); 237 struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap); 238 239 if (alu != GXcopy) 240 return FALSE; 241 242 if (pSrcPixmap->drawable.depth < 15 || pDstPixmap->drawable.depth < 15) 243 return FALSE; 244 245 if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask)) 246 return FALSE; 247 248 if (!priv || !src_priv) 249 return FALSE; 250 251 if (!priv->tex || !src_priv->tex) 252 return FALSE; 253 254 if (!exa->ctx || !exa->ctx->surface_copy) 255 return FALSE; 256 257 priv->src_surf = exa_gpu_surface(exa, src_priv); 258 259 return TRUE; 260} 261 262static void 263ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, 264 int width, int height) 265{ 266 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 267 modesettingPtr ms = modesettingPTR(pScrn); 268 struct exa_context *exa = ms->exa; 269 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap); 270 struct pipe_surface *surf = exa_gpu_surface(exa, priv); 271 272 exa->ctx->surface_copy(exa->ctx, surf, dstX, dstY, priv->src_surf, 273 srcX, srcY, width, height); 274 exa->scrn->tex_surface_destroy(surf); 275} 276 277static Bool 278ExaPrepareComposite(int op, PicturePtr pSrcPicture, 279 PicturePtr pMaskPicture, PicturePtr pDstPicture, 280 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) 281{ 282 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 283 modesettingPtr ms = modesettingPTR(pScrn); 284 struct exa_context *exa = ms->exa; 285 286 return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture, 287 pDstPicture, 288 exaGetPixmapDriverPrivate(pSrc), 289 exaGetPixmapDriverPrivate(pMask), 290 exaGetPixmapDriverPrivate(pDst)); 291} 292 293static void 294ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, 295 int dstX, int dstY, int width, int height) 296{ 297 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 298 modesettingPtr ms = modesettingPTR(pScrn); 299 struct exa_context *exa = ms->exa; 300 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst); 301 302 xorg_composite(exa, priv, srcX, srcY, maskX, maskY, 303 dstX, dstY, width, height); 304} 305 306static Bool 307ExaCheckComposite(int op, 308 PicturePtr pSrcPicture, PicturePtr pMaskPicture, 309 PicturePtr pDstPicture) 310{ 311 return xorg_composite_accelerated(op, 312 pSrcPicture, 313 pMaskPicture, 314 pDstPicture); 315} 316 317static void * 318ExaCreatePixmap(ScreenPtr pScreen, int size, int align) 319{ 320 struct exa_pixmap_priv *priv; 321 322 priv = xcalloc(1, sizeof(struct exa_pixmap_priv)); 323 if (!priv) 324 return NULL; 325 326 return priv; 327} 328 329static void 330ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv) 331{ 332 struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv; 333 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 334 modesettingPtr ms = modesettingPTR(pScrn); 335 336 if (!priv) 337 return; 338 339 if (priv->tex) 340 ms->screen->texture_destroy(priv->tex); 341 342 xfree(priv); 343} 344 345static Bool 346ExaPixmapIsOffscreen(PixmapPtr pPixmap) 347{ 348 struct exa_pixmap_priv *priv; 349 350 priv = exaGetPixmapDriverPrivate(pPixmap); 351 352 if (!priv) 353 return FALSE; 354 355 if (priv->tex) 356 return TRUE; 357 358 return FALSE; 359} 360 361int 362xorg_exa_set_displayed_usage(PixmapPtr pPixmap) 363{ 364 struct exa_pixmap_priv *priv; 365 priv = exaGetPixmapDriverPrivate(pPixmap); 366 367 if (!priv) { 368 FatalError("NO PIXMAP PRIVATE\n"); 369 return 0; 370 } 371 372 priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY; 373 374 return 0; 375} 376 377int 378xorg_exa_set_shared_usage(PixmapPtr pPixmap) 379{ 380 struct exa_pixmap_priv *priv; 381 priv = exaGetPixmapDriverPrivate(pPixmap); 382 383 if (!priv) { 384 FatalError("NO PIXMAP PRIVATE\n"); 385 return 0; 386 } 387 388 priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; 389 390 return 0; 391} 392 393unsigned 394xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out) 395{ 396 ScreenPtr pScreen = pPixmap->drawable.pScreen; 397 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 398 modesettingPtr ms = modesettingPTR(pScrn); 399 struct exa_pixmap_priv *priv; 400 unsigned handle; 401 unsigned stride; 402 403 if (!ms->exa) { 404 FatalError("NO MS->EXA\n"); 405 return 0; 406 } 407 408 priv = exaGetPixmapDriverPrivate(pPixmap); 409 410 if (!priv) { 411 FatalError("NO PIXMAP PRIVATE\n"); 412 return 0; 413 } 414 415 ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle); 416 if (stride_out) 417 *stride_out = stride; 418 419 return handle; 420} 421 422static Bool 423ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, 424 int depth, int bitsPerPixel, int devKind, 425 pointer pPixData) 426{ 427 ScreenPtr pScreen = pPixmap->drawable.pScreen; 428 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 429 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); 430 modesettingPtr ms = modesettingPTR(pScrn); 431 struct exa_context *exa = ms->exa; 432 433 if (!priv) 434 return FALSE; 435 436 if (depth <= 0) 437 depth = pPixmap->drawable.depth; 438 439 if (bitsPerPixel <= 0) 440 bitsPerPixel = pPixmap->drawable.bitsPerPixel; 441 442 if (width <= 0) 443 width = pPixmap->drawable.width; 444 445 if (height <= 0) 446 height = pPixmap->drawable.height; 447 448 if (width <= 0 || height <= 0 || depth <= 0) 449 return FALSE; 450 451 miModifyPixmapHeader(pPixmap, width, height, depth, 452 bitsPerPixel, devKind, NULL); 453 454 /* Deal with screen resize */ 455 if (priv->tex && (priv->tex->width[0] != width || 456 priv->tex->height[0] != height || 457 priv->tex_flags != priv->flags)) { 458 pipe_texture_reference(&priv->tex, NULL); 459 } 460 461 if (!priv->tex 462#ifdef DRM_MODE_FEATURE_DIRTYFB 463 && priv->flags 464#endif 465 ) { 466 struct pipe_texture template; 467 468 memset(&template, 0, sizeof(template)); 469 template.target = PIPE_TEXTURE_2D; 470 exa_get_pipe_format(depth, &template.format, &bitsPerPixel); 471 pf_get_block(template.format, &template.block); 472 template.width[0] = width; 473 template.height[0] = height; 474 template.depth[0] = 1; 475 template.last_level = 0; 476 template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags; 477 priv->tex_flags = priv->flags; 478 priv->tex = exa->scrn->texture_create(exa->scrn, &template); 479 } 480 481#ifdef DRM_MODE_FEATURE_DIRTYFB 482 if (!priv->tex) { 483 if (pPixData) 484 pPixmap->devPrivate.ptr = pPixData; 485 else 486 pPixmap->devPrivate.ptr = xalloc(pPixmap->drawable.height * pPixmap->devKind); 487 } else 488#endif 489 if (pPixData) { 490 struct pipe_transfer *transfer = 491 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, 492 PIPE_TRANSFER_WRITE, 493 0, 0, width, height); 494 util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer), 495 &priv->tex->block, transfer->stride, 0, 0, 496 width, height, pPixData, pPixmap->devKind, 0, 0); 497 exa->scrn->transfer_unmap(exa->scrn, transfer); 498 exa->scrn->tex_transfer_destroy(transfer); 499 } else if (priv->tex && pPixmap->devPrivate.ptr) { 500 struct pipe_transfer *transfer; 501 502 if (priv->map_count != 0) 503 FatalError("doing ExaModifyPixmapHeader on mapped buffer\n"); 504 505 transfer = 506 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, 507 PIPE_TRANSFER_WRITE, 508 0, 0, width, height); 509 util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer), 510 &priv->tex->block, transfer->stride, 0, 0, 511 width, height, pPixmap->devPrivate.ptr, pPixmap->devKind, 0, 0); 512 exa->scrn->transfer_unmap(exa->scrn, transfer); 513 exa->scrn->tex_transfer_destroy(transfer); 514 } 515 516 return TRUE; 517} 518 519struct pipe_texture * 520xorg_exa_get_texture(PixmapPtr pPixmap) 521{ 522 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); 523 struct pipe_texture *tex = NULL; 524 pipe_texture_reference(&tex, priv->tex); 525 return tex; 526} 527 528void 529xorg_exa_close(ScrnInfoPtr pScrn) 530{ 531 modesettingPtr ms = modesettingPTR(pScrn); 532 struct exa_context *exa = ms->exa; 533 struct pipe_constant_buffer *vsbuf = &exa->vs_const_buffer; 534 struct pipe_constant_buffer *fsbuf = &exa->fs_const_buffer; 535 536 if (exa->shaders) { 537 xorg_shaders_destroy(exa->shaders); 538 } 539 540 if (vsbuf && vsbuf->buffer) 541 pipe_buffer_reference(&vsbuf->buffer, NULL); 542 543 if (fsbuf && fsbuf->buffer) 544 pipe_buffer_reference(&fsbuf->buffer, NULL); 545 546 if (exa->cso) { 547 cso_release_all(exa->cso); 548 cso_destroy_context(exa->cso); 549 } 550 551 if (exa->ctx) 552 exa->ctx->destroy(exa->ctx); 553 554 exaDriverFini(pScrn->pScreen); 555 xfree(exa); 556 ms->exa = NULL; 557} 558 559void * 560xorg_exa_init(ScrnInfoPtr pScrn) 561{ 562 modesettingPtr ms = modesettingPTR(pScrn); 563 struct exa_context *exa; 564 ExaDriverPtr pExa; 565 566 exa = xcalloc(1, sizeof(struct exa_context)); 567 if (!exa) 568 return NULL; 569 570 pExa = exaDriverAlloc(); 571 if (!pExa) { 572 goto out_err; 573 } 574 575 memset(pExa, 0, sizeof(*pExa)); 576 577 pExa->exa_major = 2; 578 pExa->exa_minor = 2; 579 pExa->memoryBase = 0; 580 pExa->memorySize = 0; 581 pExa->offScreenBase = 0; 582 pExa->pixmapOffsetAlign = 0; 583 pExa->pixmapPitchAlign = 1; 584 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS; 585 pExa->maxX = 8191; /* FIXME */ 586 pExa->maxY = 8191; /* FIXME */ 587 588 pExa->WaitMarker = ExaWaitMarker; 589 pExa->MarkSync = ExaMarkSync; 590 pExa->PrepareSolid = ExaPrepareSolid; 591 pExa->Solid = ExaSolid; 592 pExa->DoneSolid = ExaDone; 593 pExa->PrepareCopy = ExaPrepareCopy; 594 pExa->Copy = ExaCopy; 595 pExa->DoneCopy = ExaDone; 596 pExa->CheckComposite = ExaCheckComposite; 597 pExa->PrepareComposite = ExaPrepareComposite; 598 pExa->Composite = ExaComposite; 599 pExa->DoneComposite = ExaDoneComposite; 600 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen; 601 pExa->PrepareAccess = ExaPrepareAccess; 602 pExa->FinishAccess = ExaFinishAccess; 603 pExa->CreatePixmap = ExaCreatePixmap; 604 pExa->DestroyPixmap = ExaDestroyPixmap; 605 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader; 606 607 if (!exaDriverInit(pScrn->pScreen, pExa)) { 608 goto out_err; 609 } 610 611 exa->scrn = ms->screen; 612 exa->ctx = ms->api->create_context(ms->api, exa->scrn); 613 /* Share context with DRI */ 614 ms->ctx = exa->ctx; 615 616 exa->cso = cso_create_context(exa->ctx); 617 exa->shaders = xorg_shaders_create(exa); 618 619 return (void *)exa; 620 621out_err: 622 xorg_exa_close(pScrn); 623 624 return NULL; 625} 626 627struct pipe_surface * 628exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv) 629{ 630 return exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0, 631 PIPE_BUFFER_USAGE_GPU_READ | 632 PIPE_BUFFER_USAGE_GPU_WRITE); 633 634} 635 636