xorg_exa.c revision 4322346f3fd03788a79d056ca7bce2db25bc9d88
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 "util/u_rect.h" 47 48#define DEBUG_PRINT 0 49#define ACCEL_ENABLED TRUE 50 51/* 52 * Helper functions 53 */ 54 55static void 56exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp) 57{ 58 switch (depth) { 59 case 32: 60 *format = PIPE_FORMAT_A8R8G8B8_UNORM; 61 assert(*bbp == 32); 62 break; 63 case 24: 64 *format = PIPE_FORMAT_X8R8G8B8_UNORM; 65 assert(*bbp == 32); 66 break; 67 case 16: 68 *format = PIPE_FORMAT_R5G6B5_UNORM; 69 assert(*bbp == 16); 70 break; 71 case 15: 72 *format = PIPE_FORMAT_A1R5G5B5_UNORM; 73 assert(*bbp == 16); 74 break; 75 case 8: 76 *format = PIPE_FORMAT_L8_UNORM; 77 assert(*bbp == 8); 78 break; 79 case 4: 80 case 1: 81 *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */ 82 break; 83 default: 84 assert(0); 85 break; 86 } 87} 88 89static void 90xorg_exa_common_done(struct exa_context *exa) 91{ 92 exa->copy.src = NULL; 93 exa->copy.dst = NULL; 94 exa->transform.has_src = FALSE; 95 exa->transform.has_mask = FALSE; 96 exa->has_solid_color = FALSE; 97 exa->num_bound_samplers = 0; 98} 99 100/* 101 * Static exported EXA functions 102 */ 103 104static void 105ExaWaitMarker(ScreenPtr pScreen, int marker) 106{ 107 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 108 modesettingPtr ms = modesettingPTR(pScrn); 109 struct exa_context *exa = ms->exa; 110 111#if 0 112 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL); 113#else 114 xorg_exa_finish(exa); 115#endif 116} 117 118static int 119ExaMarkSync(ScreenPtr pScreen) 120{ 121 return 1; 122} 123 124static Bool 125ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst, 126 int dst_pitch) 127{ 128 ScreenPtr pScreen = pPix->drawable.pScreen; 129 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 130 modesettingPtr ms = modesettingPTR(pScrn); 131 struct exa_context *exa = ms->exa; 132 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix); 133 struct pipe_transfer *transfer; 134 135 if (!priv || !priv->tex) 136 return FALSE; 137 138 if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) & 139 PIPE_REFERENCED_FOR_WRITE) 140 exa->pipe->flush(exa->pipe, 0, NULL); 141 142 transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, 143 PIPE_TRANSFER_READ, x, y, w, h); 144 if (!transfer) 145 return FALSE; 146 147#if DEBUG_PRINT 148 debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n", 149 x, y, w, h, dst_pitch); 150#endif 151 152 util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0, 153 w, h, exa->scrn->transfer_map(exa->scrn, transfer), 154 transfer->stride, 0, 0); 155 156 exa->scrn->transfer_unmap(exa->scrn, transfer); 157 exa->scrn->tex_transfer_destroy(transfer); 158 159 return TRUE; 160} 161 162static Bool 163ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src, 164 int src_pitch) 165{ 166 ScreenPtr pScreen = pPix->drawable.pScreen; 167 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 168 modesettingPtr ms = modesettingPTR(pScrn); 169 struct exa_context *exa = ms->exa; 170 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix); 171 struct pipe_transfer *transfer; 172 173 if (!priv || !priv->tex) 174 return FALSE; 175 176 transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, 177 PIPE_TRANSFER_WRITE, x, y, w, h); 178 if (!transfer) 179 return FALSE; 180 181#if DEBUG_PRINT 182 debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n", 183 x, y, w, h, src_pitch); 184#endif 185 186 util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer), 187 &priv->tex->block, transfer->stride, 0, 0, w, h, 188 (unsigned char*)src, src_pitch, 0, 0); 189 190 exa->scrn->transfer_unmap(exa->scrn, transfer); 191 exa->scrn->tex_transfer_destroy(transfer); 192 193 return TRUE; 194} 195 196static Bool 197ExaPrepareAccess(PixmapPtr pPix, int index) 198{ 199 ScreenPtr pScreen = pPix->drawable.pScreen; 200 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 201 modesettingPtr ms = modesettingPTR(pScrn); 202 struct exa_context *exa = ms->exa; 203 struct exa_pixmap_priv *priv; 204 205 priv = exaGetPixmapDriverPrivate(pPix); 206 207 if (!priv) 208 return FALSE; 209 210 if (!priv->tex) 211 return FALSE; 212 213 if (priv->map_count == 0) 214 { 215 if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) & 216 PIPE_REFERENCED_FOR_WRITE) 217 exa->pipe->flush(exa->pipe, 0, NULL); 218 219 priv->map_transfer = 220 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, 221#ifdef EXA_MIXED_PIXMAPS 222 PIPE_TRANSFER_MAP_DIRECTLY | 223#endif 224 PIPE_TRANSFER_READ_WRITE, 225 0, 0, priv->tex->width[0], priv->tex->height[0]); 226 if (!priv->map_transfer) 227#ifdef EXA_MIXED_PIXMAPS 228 return FALSE; 229#else 230 FatalError("failed to create transfer\n"); 231#endif 232 233 pPix->devPrivate.ptr = 234 exa->scrn->transfer_map(exa->scrn, priv->map_transfer); 235 pPix->devKind = priv->map_transfer->stride; 236 } 237 238 priv->map_count++; 239 240 return TRUE; 241} 242 243static void 244ExaFinishAccess(PixmapPtr pPix, int index) 245{ 246 ScreenPtr pScreen = pPix->drawable.pScreen; 247 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 248 modesettingPtr ms = modesettingPTR(pScrn); 249 struct exa_context *exa = ms->exa; 250 struct exa_pixmap_priv *priv; 251 priv = exaGetPixmapDriverPrivate(pPix); 252 253 if (!priv) 254 return; 255 256 if (!priv->map_transfer) 257 return; 258 259 if (--priv->map_count == 0) { 260 assert(priv->map_transfer); 261 exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer); 262 exa->scrn->tex_transfer_destroy(priv->map_transfer); 263 priv->map_transfer = NULL; 264 pPix->devPrivate.ptr = NULL; 265 } 266} 267 268static void 269ExaDone(PixmapPtr pPixmap) 270{ 271 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 272 modesettingPtr ms = modesettingPTR(pScrn); 273 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); 274 struct exa_context *exa = ms->exa; 275 276 if (!priv) 277 return; 278 279 renderer_draw_flush(exa->renderer); 280 281 xorg_exa_common_done(exa); 282} 283 284static void 285ExaDoneComposite(PixmapPtr pPixmap) 286{ 287 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 288 modesettingPtr ms = modesettingPTR(pScrn); 289 struct exa_context *exa = ms->exa; 290 291 xorg_exa_common_done(exa); 292} 293 294static Bool 295ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg) 296{ 297 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 298 modesettingPtr ms = modesettingPTR(pScrn); 299 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); 300 struct exa_context *exa = ms->exa; 301 302#if DEBUG_PRINT 303 debug_printf("ExaPrepareSolid(0x%x)\n", fg); 304#endif 305 if (!exa->pipe) 306 XORG_FALLBACK("accle not enabled"); 307 308 if (!priv || !priv->tex) 309 XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex"); 310 311 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask)) 312 XORG_FALLBACK("planeMask is not solid"); 313 314 if (alu != GXcopy) 315 XORG_FALLBACK("not GXcopy"); 316 317 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format, 318 priv->tex->target, 319 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { 320 XORG_FALLBACK("format %s", pf_name(priv->tex->format)); 321 } 322 323 return ACCEL_ENABLED && xorg_solid_bind_state(exa, priv, fg); 324} 325 326static void 327ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1) 328{ 329 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 330 modesettingPtr ms = modesettingPTR(pScrn); 331 struct exa_context *exa = ms->exa; 332 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); 333 334#if DEBUG_PRINT 335 debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1); 336#endif 337 338 xorg_solid(exa, priv, x0, y0, x1, y1) ; 339} 340 341static Bool 342ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, 343 int ydir, int alu, Pixel planeMask) 344{ 345 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 346 modesettingPtr ms = modesettingPTR(pScrn); 347 struct exa_context *exa = ms->exa; 348 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap); 349 struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap); 350 351#if DEBUG_PRINT 352 debug_printf("ExaPrepareCopy\n"); 353#endif 354 if (!exa->pipe) 355 XORG_FALLBACK("accle not enabled"); 356 357 if (!priv || !priv->tex) 358 XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex"); 359 360 if (!src_priv || !src_priv->tex) 361 XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex"); 362 363 if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask)) 364 XORG_FALLBACK("planeMask is not solid"); 365 366 if (alu != GXcopy) 367 XORG_FALLBACK("alu not GXcopy"); 368 369 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format, 370 priv->tex->target, 371 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) 372 XORG_FALLBACK("pDst format %s", pf_name(priv->tex->format)); 373 374 if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format, 375 src_priv->tex->target, 376 PIPE_TEXTURE_USAGE_SAMPLER, 0)) 377 XORG_FALLBACK("pSrc format %s", pf_name(src_priv->tex->format)); 378 379 exa->copy.src = src_priv; 380 exa->copy.dst = priv; 381 382 return ACCEL_ENABLED; 383} 384 385static void 386ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, 387 int width, int height) 388{ 389 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 390 modesettingPtr ms = modesettingPTR(pScrn); 391 struct exa_context *exa = ms->exa; 392 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap); 393 394#if DEBUG_PRINT 395 debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n", 396 srcX, srcY, dstX, dstY, width, height); 397#endif 398 399 debug_assert(priv == exa->copy.dst); 400 401 renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY, 402 exa->copy.src, srcX, srcY, 403 width, height); 404} 405 406static Bool 407ExaPrepareComposite(int op, PicturePtr pSrcPicture, 408 PicturePtr pMaskPicture, PicturePtr pDstPicture, 409 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) 410{ 411 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 412 modesettingPtr ms = modesettingPTR(pScrn); 413 struct exa_context *exa = ms->exa; 414 struct exa_pixmap_priv *priv; 415 416#if DEBUG_PRINT 417 debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n", 418 op, pSrcPicture, pMaskPicture, pDstPicture); 419#endif 420 if (!exa->pipe) 421 XORG_FALLBACK("accle not enabled"); 422 423 priv = exaGetPixmapDriverPrivate(pDst); 424 if (!priv || !priv->tex) 425 XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex"); 426 427 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format, 428 priv->tex->target, 429 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) 430 XORG_FALLBACK("pDst format: %s", pf_name(priv->tex->format)); 431 432 if (pSrc) { 433 priv = exaGetPixmapDriverPrivate(pSrc); 434 if (!priv || !priv->tex) 435 XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex"); 436 437 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format, 438 priv->tex->target, 439 PIPE_TEXTURE_USAGE_SAMPLER, 0)) 440 XORG_FALLBACK("pSrc format: %s", pf_name(priv->tex->format)); 441 } 442 443 if (pMask) { 444 priv = exaGetPixmapDriverPrivate(pMask); 445 if (!priv || !priv->tex) 446 XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex"); 447 448 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format, 449 priv->tex->target, 450 PIPE_TEXTURE_USAGE_SAMPLER, 0)) 451 XORG_FALLBACK("pMask format: %s", pf_name(priv->tex->format)); 452 } 453 454 return ACCEL_ENABLED && 455 xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture, 456 pDstPicture, 457 pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL, 458 pMask ? exaGetPixmapDriverPrivate(pMask) : NULL, 459 exaGetPixmapDriverPrivate(pDst)); 460} 461 462static void 463ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, 464 int dstX, int dstY, int width, int height) 465{ 466 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 467 modesettingPtr ms = modesettingPTR(pScrn); 468 struct exa_context *exa = ms->exa; 469 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst); 470 471#if DEBUG_PRINT 472 debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n", 473 srcX, srcY, maskX, maskY, dstX, dstY, width, height); 474 debug_printf("\t Num bound samplers = %d\n", 475 exa->num_bound_samplers); 476#endif 477 478 xorg_composite(exa, priv, srcX, srcY, maskX, maskY, 479 dstX, dstY, width, height); 480} 481 482static Bool 483ExaCheckComposite(int op, 484 PicturePtr pSrcPicture, PicturePtr pMaskPicture, 485 PicturePtr pDstPicture) 486{ 487 boolean accelerated = xorg_composite_accelerated(op, 488 pSrcPicture, 489 pMaskPicture, 490 pDstPicture); 491#if DEBUG_PRINT 492 debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n", 493 op, pSrcPicture, pMaskPicture, pDstPicture, accelerated); 494#endif 495 return ACCEL_ENABLED && accelerated; 496} 497 498static void * 499ExaCreatePixmap(ScreenPtr pScreen, int size, int align) 500{ 501 struct exa_pixmap_priv *priv; 502 503 priv = xcalloc(1, sizeof(struct exa_pixmap_priv)); 504 if (!priv) 505 return NULL; 506 507 return priv; 508} 509 510static void 511ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv) 512{ 513 struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv; 514 515 if (!priv) 516 return; 517 518 pipe_texture_reference(&priv->tex, NULL); 519 520 xfree(priv); 521} 522 523static Bool 524ExaPixmapIsOffscreen(PixmapPtr pPixmap) 525{ 526 struct exa_pixmap_priv *priv; 527 528 priv = exaGetPixmapDriverPrivate(pPixmap); 529 530 if (!priv) 531 return FALSE; 532 533 if (priv->tex) 534 return TRUE; 535 536 return FALSE; 537} 538 539int 540xorg_exa_set_displayed_usage(PixmapPtr pPixmap) 541{ 542 struct exa_pixmap_priv *priv; 543 priv = exaGetPixmapDriverPrivate(pPixmap); 544 545 if (!priv) { 546 FatalError("NO PIXMAP PRIVATE\n"); 547 return 0; 548 } 549 550 priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY; 551 552 return 0; 553} 554 555int 556xorg_exa_set_shared_usage(PixmapPtr pPixmap) 557{ 558 struct exa_pixmap_priv *priv; 559 priv = exaGetPixmapDriverPrivate(pPixmap); 560 561 if (!priv) { 562 FatalError("NO PIXMAP PRIVATE\n"); 563 return 0; 564 } 565 566 priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; 567 568 return 0; 569} 570 571unsigned 572xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out) 573{ 574 ScreenPtr pScreen = pPixmap->drawable.pScreen; 575 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 576 modesettingPtr ms = modesettingPTR(pScrn); 577 struct exa_pixmap_priv *priv; 578 unsigned handle; 579 unsigned stride; 580 581 if (!ms->exa) { 582 FatalError("NO MS->EXA\n"); 583 return 0; 584 } 585 586 priv = exaGetPixmapDriverPrivate(pPixmap); 587 588 if (!priv) { 589 FatalError("NO PIXMAP PRIVATE\n"); 590 return 0; 591 } 592 593 ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle); 594 if (stride_out) 595 *stride_out = stride; 596 597 return handle; 598} 599 600static Bool 601ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, 602 int depth, int bitsPerPixel, int devKind, 603 pointer pPixData) 604{ 605 ScreenPtr pScreen = pPixmap->drawable.pScreen; 606 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 607 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); 608 modesettingPtr ms = modesettingPTR(pScrn); 609 struct exa_context *exa = ms->exa; 610 611 if (!priv || pPixData) 612 return FALSE; 613 614 if (depth <= 0) 615 depth = pPixmap->drawable.depth; 616 617 if (bitsPerPixel <= 0) 618 bitsPerPixel = pPixmap->drawable.bitsPerPixel; 619 620 if (width <= 0) 621 width = pPixmap->drawable.width; 622 623 if (height <= 0) 624 height = pPixmap->drawable.height; 625 626 if (width <= 0 || height <= 0 || depth <= 0) 627 return FALSE; 628 629 miModifyPixmapHeader(pPixmap, width, height, depth, 630 bitsPerPixel, devKind, NULL); 631 632 /* Deal with screen resize */ 633 if (!priv->tex || 634 (priv->tex->width[0] != width || 635 priv->tex->height[0] != height || 636 priv->tex_flags != priv->flags)) { 637 struct pipe_texture *texture = NULL; 638 struct pipe_texture template; 639 640 memset(&template, 0, sizeof(template)); 641 template.target = PIPE_TEXTURE_2D; 642 exa_get_pipe_format(depth, &template.format, &bitsPerPixel); 643 pf_get_block(template.format, &template.block); 644 template.width[0] = width; 645 template.height[0] = height; 646 template.depth[0] = 1; 647 template.last_level = 0; 648 template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags; 649 priv->tex_flags = priv->flags; 650 texture = exa->scrn->texture_create(exa->scrn, &template); 651 652 if (priv->tex) { 653 struct pipe_surface *dst_surf; 654 struct pipe_surface *src_surf; 655 656 dst_surf = exa->scrn->get_tex_surface( 657 exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); 658 src_surf = xorg_gpu_surface(exa->pipe->screen, priv); 659 if (exa->pipe->surface_copy) { 660 exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf, 661 0, 0, min(width, texture->width[0]), 662 min(height, texture->height[0])); 663 } else { 664 util_surface_copy(exa->pipe, FALSE, dst_surf, 0, 0, src_surf, 665 0, 0, min(width, texture->width[0]), 666 min(height, texture->height[0])); 667 } 668 exa->scrn->tex_surface_destroy(dst_surf); 669 exa->scrn->tex_surface_destroy(src_surf); 670 } 671 672 pipe_texture_reference(&priv->tex, texture); 673 /* the texture we create has one reference */ 674 pipe_texture_reference(&texture, NULL); 675 } 676 677 return TRUE; 678} 679 680struct pipe_texture * 681xorg_exa_get_texture(PixmapPtr pPixmap) 682{ 683 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); 684 struct pipe_texture *tex = NULL; 685 pipe_texture_reference(&tex, priv->tex); 686 return tex; 687} 688 689Bool 690xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex) 691{ 692 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); 693 694 int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET; 695 696 if (!priv) 697 return FALSE; 698 699 if (pPixmap->drawable.width != tex->width[0] || 700 pPixmap->drawable.height != tex->height[0]) 701 return FALSE; 702 703 pipe_texture_reference(&priv->tex, tex); 704 priv->tex_flags = tex->tex_usage & mask; 705 706 return TRUE; 707} 708 709struct pipe_texture * 710xorg_exa_create_root_texture(ScrnInfoPtr pScrn, 711 int width, int height, 712 int depth, int bitsPerPixel) 713{ 714 modesettingPtr ms = modesettingPTR(pScrn); 715 struct exa_context *exa = ms->exa; 716 struct pipe_texture template; 717 718 memset(&template, 0, sizeof(template)); 719 template.target = PIPE_TEXTURE_2D; 720 exa_get_pipe_format(depth, &template.format, &bitsPerPixel); 721 pf_get_block(template.format, &template.block); 722 template.width[0] = width; 723 template.height[0] = height; 724 template.depth[0] = 1; 725 template.last_level = 0; 726 template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; 727 template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; 728 template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; 729 730 return exa->scrn->texture_create(exa->scrn, &template); 731} 732 733void 734xorg_exa_close(ScrnInfoPtr pScrn) 735{ 736 modesettingPtr ms = modesettingPTR(pScrn); 737 struct exa_context *exa = ms->exa; 738 739 renderer_destroy(exa->renderer); 740 741 if (exa->pipe) 742 exa->pipe->destroy(exa->pipe); 743 744 exaDriverFini(pScrn->pScreen); 745 xfree(exa); 746 ms->exa = NULL; 747} 748 749void * 750xorg_exa_init(ScrnInfoPtr pScrn) 751{ 752 modesettingPtr ms = modesettingPTR(pScrn); 753 struct exa_context *exa; 754 ExaDriverPtr pExa; 755 756 exa = xcalloc(1, sizeof(struct exa_context)); 757 if (!exa) 758 return NULL; 759 760 pExa = exaDriverAlloc(); 761 if (!pExa) { 762 goto out_err; 763 } 764 765 memset(pExa, 0, sizeof(*pExa)); 766 767 pExa->exa_major = 2; 768 pExa->exa_minor = 2; 769 pExa->memoryBase = 0; 770 pExa->memorySize = 0; 771 pExa->offScreenBase = 0; 772 pExa->pixmapOffsetAlign = 0; 773 pExa->pixmapPitchAlign = 1; 774 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS; 775#ifdef EXA_SUPPORTS_PREPARE_AUX 776 pExa->flags |= EXA_SUPPORTS_PREPARE_AUX; 777#endif 778#ifdef EXA_MIXED_PIXMAPS 779 pExa->flags |= EXA_MIXED_PIXMAPS; 780#endif 781 pExa->maxX = 8191; /* FIXME */ 782 pExa->maxY = 8191; /* FIXME */ 783 784 pExa->WaitMarker = ExaWaitMarker; 785 pExa->MarkSync = ExaMarkSync; 786 pExa->PrepareSolid = ExaPrepareSolid; 787 pExa->Solid = ExaSolid; 788 pExa->DoneSolid = ExaDone; 789 pExa->PrepareCopy = ExaPrepareCopy; 790 pExa->Copy = ExaCopy; 791 pExa->DoneCopy = ExaDone; 792 pExa->CheckComposite = ExaCheckComposite; 793 pExa->PrepareComposite = ExaPrepareComposite; 794 pExa->Composite = ExaComposite; 795 pExa->DoneComposite = ExaDoneComposite; 796 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen; 797 pExa->DownloadFromScreen = ExaDownloadFromScreen; 798 pExa->UploadToScreen = ExaUploadToScreen; 799 pExa->PrepareAccess = ExaPrepareAccess; 800 pExa->FinishAccess = ExaFinishAccess; 801 pExa->CreatePixmap = ExaCreatePixmap; 802 pExa->DestroyPixmap = ExaDestroyPixmap; 803 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader; 804 805 if (!exaDriverInit(pScrn->pScreen, pExa)) { 806 goto out_err; 807 } 808 809 exa->scrn = ms->screen; 810 exa->pipe = ms->api->create_context(ms->api, exa->scrn); 811 /* Share context with DRI */ 812 ms->ctx = exa->pipe; 813 814 exa->renderer = renderer_create(exa->pipe); 815 816 return (void *)exa; 817 818out_err: 819 xorg_exa_close(pScrn); 820 821 return NULL; 822} 823 824struct pipe_surface * 825xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv) 826{ 827 return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0, 828 PIPE_BUFFER_USAGE_GPU_READ | 829 PIPE_BUFFER_USAGE_GPU_WRITE); 830 831} 832 833void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags, 834 struct pipe_fence_handle **fence) 835{ 836 exa->pipe->flush(exa->pipe, pipeFlushFlags, fence); 837} 838 839void xorg_exa_finish(struct exa_context *exa) 840{ 841 struct pipe_fence_handle *fence = NULL; 842 843 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence); 844 845 exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0); 846 exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL); 847} 848 849