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