intel_uxa.c revision 42542f5f
1/************************************************************************** 2 3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 4All Rights Reserved. 5Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org> 6 Based on code from i830_xaa.c. 7 8Permission is hereby granted, free of charge, to any person obtaining a 9copy of this software and associated documentation files (the 10"Software"), to deal in the Software without restriction, including 11without limitation the rights to use, copy, modify, merge, publish, 12distribute, sub license, and/or sell copies of the Software, and to 13permit persons to whom the Software is furnished to do so, subject to 14the following conditions: 15 16The above copyright notice and this permission notice (including the 17next paragraph) shall be included in all copies or substantial portions 18of the Software. 19 20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 24ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28**************************************************************************/ 29 30#ifdef HAVE_CONFIG_H 31#include "config.h" 32#endif 33 34#include "xorg-server.h" 35#include <xf86.h> 36#include <xf86drm.h> 37#include <xaarop.h> 38#include <string.h> 39#include <errno.h> 40#include <unistd.h> 41 42#include "intel.h" 43#include "intel_glamor.h" 44#include "uxa.h" 45 46#include "i830_reg.h" 47#include "i915_drm.h" 48#include "brw_defines.h" 49 50static const int I830CopyROP[16] = { 51 ROP_0, /* GXclear */ 52 ROP_DSa, /* GXand */ 53 ROP_SDna, /* GXandReverse */ 54 ROP_S, /* GXcopy */ 55 ROP_DSna, /* GXandInverted */ 56 ROP_D, /* GXnoop */ 57 ROP_DSx, /* GXxor */ 58 ROP_DSo, /* GXor */ 59 ROP_DSon, /* GXnor */ 60 ROP_DSxn, /* GXequiv */ 61 ROP_Dn, /* GXinvert */ 62 ROP_SDno, /* GXorReverse */ 63 ROP_Sn, /* GXcopyInverted */ 64 ROP_DSno, /* GXorInverted */ 65 ROP_DSan, /* GXnand */ 66 ROP_1 /* GXset */ 67}; 68 69static const int I830PatternROP[16] = { 70 ROP_0, 71 ROP_DPa, 72 ROP_PDna, 73 ROP_P, 74 ROP_DPna, 75 ROP_D, 76 ROP_DPx, 77 ROP_DPo, 78 ROP_DPon, 79 ROP_PDxn, 80 ROP_Dn, 81 ROP_PDno, 82 ROP_Pn, 83 ROP_DPno, 84 ROP_DPan, 85 ROP_1 86}; 87 88#if HAS_DEVPRIVATEKEYREC 89DevPrivateKeyRec uxa_pixmap_index; 90#else 91int uxa_pixmap_index; 92#endif 93 94static void 95gen6_context_switch(intel_screen_private *intel, 96 int new_mode) 97{ 98 intel_batch_submit(intel->scrn); 99} 100 101static void 102gen5_context_switch(intel_screen_private *intel, 103 int new_mode) 104{ 105 /* Ironlake has a limitation that a 3D or Media command can't 106 * be the first command after a BLT, unless it's 107 * non-pipelined. Instead of trying to track it and emit a 108 * command at the right time, we just emit a dummy 109 * non-pipelined 3D instruction after each blit. 110 */ 111 112 if (new_mode == I915_EXEC_BLT) { 113 OUT_BATCH(MI_FLUSH | 114 MI_STATE_INSTRUCTION_CACHE_FLUSH | 115 MI_INHIBIT_RENDER_CACHE_FLUSH); 116 } else { 117 OUT_BATCH(CMD_POLY_STIPPLE_OFFSET << 16); 118 OUT_BATCH(0); 119 } 120} 121 122static void 123gen4_context_switch(intel_screen_private *intel, 124 int new_mode) 125{ 126 if (new_mode == I915_EXEC_BLT) { 127 OUT_BATCH(MI_FLUSH | 128 MI_STATE_INSTRUCTION_CACHE_FLUSH | 129 MI_INHIBIT_RENDER_CACHE_FLUSH); 130 } 131} 132 133Bool 134intel_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, 135 int num_bos) 136{ 137 intel_screen_private *intel = intel_get_screen_private(scrn); 138 139 if (intel->batch_bo == NULL) { 140 intel_debug_fallback(scrn, "VT inactive\n"); 141 return FALSE; 142 } 143 144 bo_table[0] = intel->batch_bo; 145 if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) { 146 intel_batch_submit(scrn); 147 bo_table[0] = intel->batch_bo; 148 if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 149 0) { 150 intel_debug_fallback(scrn, "Couldn't get aperture " 151 "space for BOs\n"); 152 return FALSE; 153 } 154 } 155 return TRUE; 156} 157 158static unsigned int 159intel_uxa_compute_size(struct intel_screen_private *intel, 160 int w, int h, int bpp, unsigned usage, 161 uint32_t *tiling, int *stride) 162{ 163 int pitch, size; 164 165 if (*tiling != I915_TILING_NONE) { 166 /* First check whether tiling is necessary. */ 167 pitch = (w * bpp + 7) / 8; 168 pitch = ALIGN(pitch, 64); 169 size = pitch * ALIGN (h, 2); 170 if (INTEL_INFO(intel)->gen < 040) { 171 /* Gen 2/3 has a maximum stride for tiling of 172 * 8192 bytes. 173 */ 174 if (pitch > KB(8)) 175 *tiling = I915_TILING_NONE; 176 177 /* Narrower than half a tile? */ 178 if (pitch < 256) 179 *tiling = I915_TILING_NONE; 180 181 /* Older hardware requires fences to be pot size 182 * aligned with a minimum of 1 MiB, so causes 183 * massive overallocation for small textures. 184 */ 185 if (size < 1024*1024/2 && !intel->has_relaxed_fencing) 186 *tiling = I915_TILING_NONE; 187 } else if (!(usage & INTEL_CREATE_PIXMAP_DRI2) && size <= 4096) { 188 /* Disable tiling beneath a page size, we will not see 189 * any benefit from reducing TLB misses and instead 190 * just incur extra cost when we require a fence. 191 */ 192 *tiling = I915_TILING_NONE; 193 } 194 } 195 196 pitch = (w * bpp + 7) / 8; 197 if (!(usage & INTEL_CREATE_PIXMAP_DRI2) && pitch <= 256) 198 *tiling = I915_TILING_NONE; 199 200 if (*tiling != I915_TILING_NONE) { 201 int aligned_h, tile_height; 202 203 if (IS_GEN2(intel)) 204 tile_height = 16; 205 else if (*tiling == I915_TILING_X) 206 tile_height = 8; 207 else 208 tile_height = 32; 209 aligned_h = ALIGN(h, 2*tile_height); 210 211 *stride = intel_get_fence_pitch(intel, 212 ALIGN(pitch, 512), 213 *tiling); 214 215 /* Round the object up to the size of the fence it will live in 216 * if necessary. We could potentially make the kernel allocate 217 * a larger aperture space and just bind the subset of pages in, 218 * but this is easier and also keeps us out of trouble (as much) 219 * with drm_intel_bufmgr_check_aperture(). 220 */ 221 size = intel_get_fence_size(intel, *stride * aligned_h); 222 223 if (size > intel->max_tiling_size) 224 *tiling = I915_TILING_NONE; 225 } 226 227 if (*tiling == I915_TILING_NONE) { 228 /* We only require a 64 byte alignment for scanouts, but 229 * a 256 byte alignment for sharing with PRIME. 230 */ 231 *stride = ALIGN(pitch, 256); 232 /* Round the height up so that the GPU's access to a 2x2 aligned 233 * subspan doesn't address an invalid page offset beyond the 234 * end of the GTT. 235 */ 236 size = *stride * ALIGN(h, 2); 237 } 238 239 return size; 240} 241 242drm_intel_bo *intel_allocate_framebuffer(ScrnInfoPtr scrn, 243 int width, int height, int cpp, 244 int *out_stride, 245 uint32_t *out_tiling) 246{ 247 intel_screen_private *intel = intel_get_screen_private(scrn); 248 uint32_t tiling; 249 int stride, size; 250 drm_intel_bo *bo; 251 252 if (intel->tiling & INTEL_TILING_FB) 253 tiling = I915_TILING_X; 254 else 255 tiling = I915_TILING_NONE; 256 257retry: 258 size = intel_uxa_compute_size(intel, 259 width, height, 260 intel->cpp*8, 0, 261 &tiling, &stride); 262 if (!intel_check_display_stride(scrn, stride, tiling)) { 263 if (tiling != I915_TILING_NONE) { 264 tiling = I915_TILING_NONE; 265 goto retry; 266 } 267 268 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 269 "Front buffer stride %d kB " 270 "exceeds display limit\n", stride / 1024); 271 return NULL; 272 } 273 274 bo = drm_intel_bo_alloc(intel->bufmgr, "front buffer", size, 0); 275 if (bo == NULL) 276 return FALSE; 277 278 if (tiling != I915_TILING_NONE) 279 drm_intel_bo_set_tiling(bo, &tiling, stride); 280 281 xf86DrvMsg(scrn->scrnIndex, X_INFO, 282 "Allocated new frame buffer %dx%d stride %d, %s\n", 283 width, height, stride, 284 tiling == I915_TILING_NONE ? "untiled" : "tiled"); 285 286 drm_intel_bo_disable_reuse(bo); 287 288 intel_set_gem_max_sizes(scrn); 289 *out_stride = stride; 290 *out_tiling = tiling; 291 return bo; 292} 293 294static Bool 295intel_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask) 296{ 297 ScrnInfoPtr scrn = xf86ScreenToScrn(drawable->pScreen); 298 299 if (!UXA_PM_IS_SOLID(drawable, planemask)) { 300 intel_debug_fallback(scrn, "planemask is not solid\n"); 301 return FALSE; 302 } 303 304 switch (drawable->bitsPerPixel) { 305 case 8: 306 case 16: 307 case 32: 308 break; 309 default: 310 return FALSE; 311 } 312 313 return TRUE; 314} 315 316/** 317 * Sets up hardware state for a series of solid fills. 318 */ 319static Bool 320intel_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) 321{ 322 ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 323 intel_screen_private *intel = intel_get_screen_private(scrn); 324 drm_intel_bo *bo_table[] = { 325 NULL, /* batch_bo */ 326 intel_get_pixmap_bo(pixmap), 327 }; 328 329 if (!intel_check_pitch_2d(pixmap)) 330 return FALSE; 331 332 if (!intel_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 333 return FALSE; 334 335 intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16; 336 switch (pixmap->drawable.bitsPerPixel) { 337 case 8: 338 break; 339 case 16: 340 /* RGB565 */ 341 intel->BR[13] |= (1 << 24); 342 break; 343 case 32: 344 /* RGB8888 */ 345 intel->BR[13] |= ((1 << 24) | (1 << 25)); 346 break; 347 } 348 intel->BR[16] = fg; 349 350 return TRUE; 351} 352 353static void intel_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2) 354{ 355 ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 356 intel_screen_private *intel = intel_get_screen_private(scrn); 357 unsigned long pitch; 358 uint32_t cmd; 359 360 if (x1 < 0) 361 x1 = 0; 362 if (y1 < 0) 363 y1 = 0; 364 if (x2 > pixmap->drawable.width) 365 x2 = pixmap->drawable.width; 366 if (y2 > pixmap->drawable.height) 367 y2 = pixmap->drawable.height; 368 369 if (x2 <= x1 || y2 <= y1) 370 return; 371 372 pitch = intel_pixmap_pitch(pixmap); 373 374 { 375 int len = INTEL_INFO(intel)->gen >= 0100 ? 7 : 6; 376 BEGIN_BATCH_BLT(len); 377 378 cmd = XY_COLOR_BLT_CMD | (len - 2); 379 380 if (pixmap->drawable.bitsPerPixel == 32) 381 cmd |= 382 XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB; 383 384 if (INTEL_INFO(intel)->gen >= 040 && intel_pixmap_tiled(pixmap)) { 385 assert((pitch % 512) == 0); 386 pitch >>= 2; 387 cmd |= XY_COLOR_BLT_TILED; 388 } 389 390 OUT_BATCH(cmd); 391 392 OUT_BATCH(intel->BR[13] | pitch); 393 OUT_BATCH((y1 << 16) | (x1 & 0xffff)); 394 OUT_BATCH((y2 << 16) | (x2 & 0xffff)); 395 OUT_RELOC_PIXMAP_FENCED(pixmap, I915_GEM_DOMAIN_RENDER, 396 I915_GEM_DOMAIN_RENDER, 0); 397 OUT_BATCH(intel->BR[16]); 398 ADVANCE_BATCH(); 399 } 400} 401 402/** 403 * TODO: 404 * - support planemask using FULL_BLT_CMD? 405 */ 406static Bool 407intel_uxa_check_copy(PixmapPtr source, PixmapPtr dest, 408 int alu, Pixel planemask) 409{ 410 ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 411 412 if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) { 413 intel_debug_fallback(scrn, "planemask is not solid"); 414 return FALSE; 415 } 416 417 if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) { 418 intel_debug_fallback(scrn, "mixed bpp copies unsupported\n"); 419 return FALSE; 420 } 421 switch (source->drawable.bitsPerPixel) { 422 case 8: 423 case 16: 424 case 32: 425 break; 426 default: 427 return FALSE; 428 } 429 430 if (!intel_check_pitch_2d(source)) 431 return FALSE; 432 if (!intel_check_pitch_2d(dest)) 433 return FALSE; 434 435 return TRUE; 436} 437 438static Bool 439intel_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, 440 int ydir, int alu, Pixel planemask) 441{ 442 ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 443 intel_screen_private *intel = intel_get_screen_private(scrn); 444 drm_intel_bo *bo_table[] = { 445 NULL, /* batch_bo */ 446 intel_get_pixmap_bo(source), 447 intel_get_pixmap_bo(dest), 448 }; 449 450 if (!intel_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 451 return FALSE; 452 453 intel->render_source = source; 454 455 intel->BR[13] = I830CopyROP[alu] << 16; 456 switch (source->drawable.bitsPerPixel) { 457 case 8: 458 break; 459 case 16: 460 intel->BR[13] |= (1 << 24); 461 break; 462 case 32: 463 intel->BR[13] |= ((1 << 25) | (1 << 24)); 464 break; 465 } 466 467 return TRUE; 468} 469 470static void 471intel_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1, 472 int dst_y1, int w, int h) 473{ 474 ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 475 intel_screen_private *intel = intel_get_screen_private(scrn); 476 uint32_t cmd; 477 int dst_x2, dst_y2, src_x2, src_y2; 478 unsigned int dst_pitch, src_pitch; 479 480 dst_x2 = dst_x1 + w; 481 dst_y2 = dst_y1 + h; 482 483 /* XXX Fixup extents as a lamentable workaround for missing 484 * source clipping in the upper layers. 485 */ 486 if (dst_x1 < 0) 487 src_x1 -= dst_x1, dst_x1 = 0; 488 if (dst_y1 < 0) 489 src_y1 -= dst_y1, dst_y1 = 0; 490 if (dst_x2 > dest->drawable.width) 491 dst_x2 = dest->drawable.width; 492 if (dst_y2 > dest->drawable.height) 493 dst_y2 = dest->drawable.height; 494 495 src_x2 = src_x1 + (dst_x2 - dst_x1); 496 src_y2 = src_y1 + (dst_y2 - dst_y1); 497 498 if (src_x1 < 0) 499 dst_x1 -= src_x1, src_x1 = 0; 500 if (src_y1 < 0) 501 dst_y1 -= src_y1, src_y1 = 0; 502 if (src_x2 > intel->render_source->drawable.width) 503 dst_x2 -= src_x2 - intel->render_source->drawable.width; 504 if (src_y2 > intel->render_source->drawable.height) 505 dst_y2 -= src_y2 - intel->render_source->drawable.height; 506 507 if (dst_x2 <= dst_x1 || dst_y2 <= dst_y1) 508 return; 509 510 dst_pitch = intel_pixmap_pitch(dest); 511 src_pitch = intel_pixmap_pitch(intel->render_source); 512 513 { 514 int len = INTEL_INFO(intel)->gen >= 0100 ? 10 : 8; 515 BEGIN_BATCH_BLT(len); 516 517 cmd = XY_SRC_COPY_BLT_CMD | (len - 2); 518 519 if (dest->drawable.bitsPerPixel == 32) 520 cmd |= 521 XY_SRC_COPY_BLT_WRITE_ALPHA | 522 XY_SRC_COPY_BLT_WRITE_RGB; 523 524 if (INTEL_INFO(intel)->gen >= 040) { 525 if (intel_pixmap_tiled(dest)) { 526 assert((dst_pitch % 512) == 0); 527 dst_pitch >>= 2; 528 cmd |= XY_SRC_COPY_BLT_DST_TILED; 529 } 530 531 if (intel_pixmap_tiled(intel->render_source)) { 532 assert((src_pitch % 512) == 0); 533 src_pitch >>= 2; 534 cmd |= XY_SRC_COPY_BLT_SRC_TILED; 535 } 536 } 537 538 OUT_BATCH(cmd); 539 540 OUT_BATCH(intel->BR[13] | dst_pitch); 541 OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff)); 542 OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff)); 543 OUT_RELOC_PIXMAP_FENCED(dest, 544 I915_GEM_DOMAIN_RENDER, 545 I915_GEM_DOMAIN_RENDER, 546 0); 547 OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff)); 548 OUT_BATCH(src_pitch); 549 OUT_RELOC_PIXMAP_FENCED(intel->render_source, 550 I915_GEM_DOMAIN_RENDER, 0, 551 0); 552 553 ADVANCE_BATCH(); 554 } 555} 556 557static void intel_uxa_done(PixmapPtr pixmap) 558{ 559 ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 560 intel_screen_private *intel = intel_get_screen_private(scrn); 561 562 if (INTEL_INFO(intel)->gen >= 060) { 563 /* workaround a random BLT hang */ 564 BEGIN_BATCH_BLT(3); 565 OUT_BATCH(XY_SETUP_CLIP_BLT_CMD | (3 - 2)); 566 OUT_BATCH(0); 567 OUT_BATCH(0); 568 ADVANCE_BATCH(); 569 } 570 571 intel_debug_flush(scrn); 572} 573 574/** 575 * Do any cleanup from the Composite operation. 576 * 577 * This is shared between i830 through i965. 578 */ 579static void i830_done_composite(PixmapPtr dest) 580{ 581 ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 582 intel_screen_private *intel = intel_get_screen_private(scrn); 583 584 if (intel->vertex_flush) 585 intel->vertex_flush(intel); 586 587 intel_debug_flush(scrn); 588} 589 590#define xFixedToFloat(val) \ 591 ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0)) 592 593static Bool 594_intel_transform_point(PictTransformPtr transform, 595 float x, float y, float result[3]) 596{ 597 int j; 598 599 for (j = 0; j < 3; j++) { 600 result[j] = (xFixedToFloat(transform->matrix[j][0]) * x + 601 xFixedToFloat(transform->matrix[j][1]) * y + 602 xFixedToFloat(transform->matrix[j][2])); 603 } 604 if (!result[2]) 605 return FALSE; 606 return TRUE; 607} 608 609/** 610 * Returns the floating-point coordinates transformed by the given transform. 611 * 612 * transform may be null. 613 */ 614Bool 615intel_get_transformed_coordinates(int x, int y, PictTransformPtr transform, 616 float *x_out, float *y_out) 617{ 618 if (transform == NULL) { 619 *x_out = x; 620 *y_out = y; 621 } else { 622 float result[3]; 623 624 if (!_intel_transform_point(transform, 625 x, y, 626 result)) 627 return FALSE; 628 *x_out = result[0] / result[2]; 629 *y_out = result[1] / result[2]; 630 } 631 return TRUE; 632} 633 634/** 635 * Returns the un-normalized floating-point coordinates transformed by the given transform. 636 * 637 * transform may be null. 638 */ 639Bool 640intel_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform, 641 float *x_out, float *y_out, float *w_out) 642{ 643 if (transform == NULL) { 644 *x_out = x; 645 *y_out = y; 646 *w_out = 1; 647 } else { 648 float result[3]; 649 650 if (!_intel_transform_point(transform, 651 x, y, 652 result)) 653 return FALSE; 654 *x_out = result[0]; 655 *y_out = result[1]; 656 *w_out = result[2]; 657 } 658 return TRUE; 659} 660 661/** 662 * Returns whether the provided transform is affine. 663 * 664 * transform may be null. 665 */ 666Bool intel_transform_is_affine(PictTransformPtr t) 667{ 668 if (t == NULL) 669 return TRUE; 670 return t->matrix[2][0] == 0 && t->matrix[2][1] == 0; 671} 672 673dri_bo *intel_get_pixmap_bo(PixmapPtr pixmap) 674{ 675 struct intel_pixmap *intel; 676 677 intel = intel_get_pixmap_private(pixmap); 678 if (intel == NULL) 679 return NULL; 680 681 return intel->bo; 682} 683 684static unsigned intel_get_tile_width(intel_screen_private *intel, int tiling, int pitch) 685{ 686 unsigned long tile_width; 687 688 if (tiling == I915_TILING_NONE) 689 return 4; 690 691 tile_width = (tiling == I915_TILING_Y) ? 128 : 512; 692 if (INTEL_INFO(intel)->gen >= 040) 693 return tile_width; 694 695 while (tile_width < pitch) 696 tile_width <<= 1; 697 698 return tile_width; 699} 700 701void intel_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) 702{ 703 ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 704 intel_screen_private *intel = intel_get_screen_private(scrn); 705 struct intel_pixmap *priv; 706 707 priv = intel_get_pixmap_private(pixmap); 708 if (priv == NULL && bo == NULL) 709 return; 710 711 if (priv != NULL) { 712 if (priv->bo == bo) 713 return; 714 715free_priv: 716 dri_bo_unreference(priv->bo); 717 list_del(&priv->batch); 718 719 free(priv); 720 priv = NULL; 721 } 722 723 if (bo != NULL) { 724 uint32_t tiling, swizzle_mode; 725 unsigned tile_width; 726 int size, stride; 727 728 priv = calloc(1, sizeof (struct intel_pixmap)); 729 if (priv == NULL) 730 goto BAIL; 731 732 list_init(&priv->batch); 733 734 dri_bo_reference(bo); 735 priv->bo = bo; 736 priv->stride = intel_pixmap_pitch(pixmap); 737 738 if (drm_intel_bo_get_tiling(bo, &tiling, &swizzle_mode)) { 739 bo = NULL; 740 goto free_priv; 741 } 742 743 priv->tiling = tiling; 744 priv->busy = -1; 745 priv->offscreen = 1; 746 747 stride = (pixmap->drawable.width * pixmap->drawable.bitsPerPixel + 7) / 8; 748 tile_width = intel_get_tile_width(intel, tiling, stride); 749 stride = ALIGN(stride, tile_width); 750 751 if (priv->stride < stride || 752 priv->stride & (tile_width - 1) || 753 priv->stride >= KB(32)) { 754 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 755 "%s: stride on buffer object does not match constraints: stride=%d, must be greater than %d, but less than %d, and have alignment at least %d\n", 756 __FUNCTION__, priv->stride, stride, KB(32), tile_width); 757 bo = NULL; 758 goto free_priv; 759 } 760 761 if (tiling != I915_TILING_NONE) { 762 int height; 763 764 if (IS_GEN2(intel)) 765 height = 16; 766 else if (tiling == I915_TILING_X) 767 height = 8; 768 else 769 height = 32; 770 771 height = ALIGN(pixmap->drawable.height, 2*height); 772 size = intel_get_fence_size(intel, priv->stride * height); 773 } else 774 size = priv->stride * pixmap->drawable.height; 775 776 if (bo->size < size || bo->size > intel->max_bo_size) { 777 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 778 "%s: size of buffer object does not match constraints: size=%ld, must be greater than %d, but less than %d\n", 779 __FUNCTION__, (long)bo->size, size, intel->max_bo_size); 780 bo = NULL; 781 goto free_priv; 782 } 783 } 784 785 BAIL: 786 intel_set_pixmap_private(pixmap, priv); 787} 788 789static Bool intel_uxa_pixmap_is_offscreen(PixmapPtr pixmap) 790{ 791 return intel_pixmap_is_offscreen(pixmap); 792} 793 794static Bool intel_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access) 795{ 796 ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 797 intel_screen_private *intel = intel_get_screen_private(scrn); 798 struct intel_pixmap *priv = intel_get_pixmap_private(pixmap); 799 dri_bo *bo = priv->bo; 800 int ret; 801 802 /* Transitioning to glamor acceleration, we need to flush all pending 803 * usage by UXA. */ 804 if (access == UXA_GLAMOR_ACCESS_RW || access == UXA_GLAMOR_ACCESS_RO) { 805 if (!list_is_empty(&priv->batch)) 806 intel_batch_submit(scrn); 807 return TRUE; 808 } 809 810 /* When falling back to swrast, flush all pending operations */ 811 intel_glamor_flush(intel); 812 if (access == UXA_ACCESS_RW || priv->dirty) 813 intel_batch_submit(scrn); 814 815 assert(bo->size <= intel->max_gtt_map_size); 816 ret = drm_intel_gem_bo_map_gtt(bo); 817 if (ret) { 818 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 819 "%s: bo map (use gtt? %d, access %d) failed: %s\n", 820 __FUNCTION__, 821 priv->tiling || bo->size <= intel->max_gtt_map_size, 822 access, 823 strerror(-ret)); 824 return FALSE; 825 } 826 827 pixmap->devPrivate.ptr = bo->virtual; 828 priv->busy = 0; 829 830 return TRUE; 831} 832 833static void intel_uxa_finish_access(PixmapPtr pixmap, uxa_access_t access) 834{ 835 struct intel_pixmap *priv; 836 837 if (access == UXA_GLAMOR_ACCESS_RW || access == UXA_GLAMOR_ACCESS_RO) 838 return; 839 840 priv = intel_get_pixmap_private(pixmap); 841 if (priv == NULL) 842 return; 843 844 drm_intel_gem_bo_unmap_gtt(priv->bo); 845 pixmap->devPrivate.ptr = NULL; 846} 847 848static Bool intel_uxa_pixmap_put_image(PixmapPtr pixmap, 849 char *src, int src_pitch, 850 int x, int y, int w, int h) 851{ 852 struct intel_pixmap *priv = intel_get_pixmap_private(pixmap); 853 int stride = intel_pixmap_pitch(pixmap); 854 int cpp = pixmap->drawable.bitsPerPixel/8; 855 int ret = FALSE; 856 857 if (priv == NULL || priv->bo == NULL) 858 return FALSE; 859 860 if (priv->tiling == I915_TILING_NONE && 861 (h == 1 || (src_pitch == stride && w == pixmap->drawable.width))) { 862 return drm_intel_bo_subdata(priv->bo, y*stride + x*cpp, stride*(h-1) + w*cpp, src) == 0; 863 } else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) { 864 char *dst = priv->bo->virtual; 865 int row_length = w * cpp; 866 int num_rows = h; 867 if (row_length == src_pitch && src_pitch == stride) 868 num_rows = 1, row_length *= h; 869 dst += y * stride + x * cpp; 870 do { 871 memcpy (dst, src, row_length); 872 src += src_pitch; 873 dst += stride; 874 } while (--num_rows); 875 drm_intel_gem_bo_unmap_gtt(priv->bo); 876 ret = TRUE; 877 } 878 879 return ret; 880} 881 882static Bool intel_uxa_put_image(PixmapPtr pixmap, 883 int x, int y, 884 int w, int h, 885 char *src, int src_pitch) 886{ 887 struct intel_pixmap *priv; 888 889 priv = intel_get_pixmap_private(pixmap); 890 if (!intel_pixmap_is_busy(priv)) { 891 /* bo is not busy so can be replaced without a stall, upload in-place. */ 892 return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h); 893 } else { 894 ScreenPtr screen = pixmap->drawable.pScreen; 895 896 if (!priv->pinned && 897 x == 0 && y == 0 && 898 w == pixmap->drawable.width && 899 h == pixmap->drawable.height) 900 { 901 intel_screen_private *intel = intel_get_screen_private(xf86ScreenToScrn(screen)); 902 uint32_t tiling = priv->tiling; 903 int size, stride; 904 dri_bo *bo; 905 906 /* Replace busy bo. */ 907 size = intel_uxa_compute_size(intel, 908 w, h, 909 pixmap->drawable.bitsPerPixel, pixmap->usage_hint, 910 &tiling, &stride); 911 if (size > intel->max_gtt_map_size) 912 return FALSE; 913 914 bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); 915 if (bo == NULL) 916 return FALSE; 917 918 if (tiling != I915_TILING_NONE) 919 drm_intel_bo_set_tiling(bo, &tiling, stride); 920 priv->stride = stride; 921 priv->tiling = tiling; 922 923 screen->ModifyPixmapHeader(pixmap, 924 w, h, 925 0, 0, 926 stride, NULL); 927 intel_set_pixmap_bo(pixmap, bo); 928 dri_bo_unreference(bo); 929 930 return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h); 931 } 932 else 933 { 934 PixmapPtr scratch; 935 Bool ret; 936 937 /* Upload to a linear buffer and queue a blit. */ 938 scratch = (*screen->CreatePixmap)(screen, w, h, 939 pixmap->drawable.depth, 940 UXA_CREATE_PIXMAP_FOR_MAP); 941 if (!scratch) 942 return FALSE; 943 944 if (!intel_uxa_pixmap_is_offscreen(scratch)) { 945 screen->DestroyPixmap(scratch); 946 return FALSE; 947 } 948 949 ret = intel_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h); 950 if (ret) { 951 GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); 952 if (gc) { 953 ValidateGC(&pixmap->drawable, gc); 954 955 (*gc->ops->CopyArea)(&scratch->drawable, 956 &pixmap->drawable, 957 gc, 0, 0, w, h, x, y); 958 959 FreeScratchGC(gc); 960 } else 961 ret = FALSE; 962 } 963 964 (*screen->DestroyPixmap)(scratch); 965 return ret; 966 } 967 } 968} 969 970static Bool intel_uxa_pixmap_get_image(PixmapPtr pixmap, 971 int x, int y, int w, int h, 972 char *dst, int dst_pitch) 973{ 974 struct intel_pixmap *priv = intel_get_pixmap_private(pixmap); 975 int stride = intel_pixmap_pitch(pixmap); 976 int cpp = pixmap->drawable.bitsPerPixel/8; 977 978 /* assert(priv->tiling == I915_TILING_NONE); */ 979 if (h == 1 || (dst_pitch == stride && w == pixmap->drawable.width)) { 980 return drm_intel_bo_get_subdata(priv->bo, y*stride + x*cpp, (h-1)*stride + w*cpp, dst) == 0; 981 } else { 982 char *src; 983 984 if (drm_intel_gem_bo_map_gtt(priv->bo)) 985 return FALSE; 986 987 src = (char *) priv->bo->virtual + y * stride + x * cpp; 988 w *= cpp; 989 do { 990 memcpy(dst, src, w); 991 src += stride; 992 dst += dst_pitch; 993 } while (--h); 994 995 drm_intel_gem_bo_unmap_gtt(priv->bo); 996 997 return TRUE; 998 } 999} 1000 1001static Bool intel_uxa_get_image(PixmapPtr pixmap, 1002 int x, int y, 1003 int w, int h, 1004 char *dst, int dst_pitch) 1005{ 1006 struct intel_pixmap *priv; 1007 PixmapPtr scratch = NULL; 1008 Bool ret; 1009 1010 /* The presumption is that we wish to keep the target hot, so 1011 * copy to a new bo and move that to the CPU in preference to 1012 * causing ping-pong of the original. 1013 * 1014 * Also the gpu is much faster at detiling. 1015 */ 1016 1017 priv = intel_get_pixmap_private(pixmap); 1018 if (intel_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) { 1019 ScreenPtr screen = pixmap->drawable.pScreen; 1020 GCPtr gc; 1021 1022 /* Copy to a linear buffer and pull. */ 1023 scratch = screen->CreatePixmap(screen, w, h, 1024 pixmap->drawable.depth, 1025 INTEL_CREATE_PIXMAP_TILING_NONE); 1026 if (!scratch) 1027 return FALSE; 1028 1029 if (!intel_uxa_pixmap_is_offscreen(scratch)) { 1030 screen->DestroyPixmap(scratch); 1031 return FALSE; 1032 } 1033 1034 gc = GetScratchGC(pixmap->drawable.depth, screen); 1035 if (!gc) { 1036 screen->DestroyPixmap(scratch); 1037 return FALSE; 1038 } 1039 1040 ValidateGC(&pixmap->drawable, gc); 1041 1042 gc->ops->CopyArea(&pixmap->drawable, 1043 &scratch->drawable, 1044 gc, x, y, w, h, 0, 0); 1045 1046 FreeScratchGC(gc); 1047 1048 intel_batch_submit(xf86ScreenToScrn(screen)); 1049 1050 x = y = 0; 1051 pixmap = scratch; 1052 } 1053 1054 ret = intel_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch); 1055 1056 if (scratch) 1057 scratch->drawable.pScreen->DestroyPixmap(scratch); 1058 1059 return ret; 1060} 1061 1062static CARD32 intel_cache_expire(OsTimerPtr timer, CARD32 now, pointer data) 1063{ 1064 intel_screen_private *intel = data; 1065 1066 /* We just want to create and destroy a bo as this causes libdrm 1067 * to reap its caches. However, since we can't remove that buffer 1068 * from the cache due to its own activity, we want to use something 1069 * that we know we will reuse later. The most frequently reused buffer 1070 * we have is the batchbuffer, and the best way to trigger its 1071 * reallocation is to submit a flush. 1072 */ 1073 intel_batch_emit_flush(intel->scrn); 1074 intel_batch_submit(intel->scrn); 1075 1076 return 0; 1077} 1078 1079static void intel_flush_rendering(intel_screen_private *intel) 1080{ 1081 if (intel->needs_flush == 0) 1082 return; 1083 1084 if (intel->has_kernel_flush) { 1085 intel_batch_submit(intel->scrn); 1086 drm_intel_bo_busy(intel->front_buffer); 1087 } else { 1088 intel_batch_emit_flush(intel->scrn); 1089 intel_batch_submit(intel->scrn); 1090 } 1091 1092 intel->cache_expire = TimerSet(intel->cache_expire, 0, 3000, 1093 intel_cache_expire, intel); 1094 1095 intel->needs_flush = 0; 1096} 1097 1098static void intel_throttle(intel_screen_private *intel) 1099{ 1100 drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE); 1101} 1102 1103void intel_uxa_block_handler(intel_screen_private *intel) 1104{ 1105 /* Emit a flush of the rendering cache, or on the 965 1106 * and beyond rendering results may not hit the 1107 * framebuffer until significantly later. 1108 */ 1109 intel_glamor_flush(intel); 1110 intel_flush_rendering(intel); 1111 intel_throttle(intel); 1112} 1113 1114static PixmapPtr 1115intel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, 1116 unsigned usage) 1117{ 1118 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1119 intel_screen_private *intel = intel_get_screen_private(scrn); 1120 struct intel_pixmap *priv; 1121 PixmapPtr pixmap, new_pixmap = NULL; 1122 1123 if (!(usage & INTEL_CREATE_PIXMAP_DRI2)) { 1124 pixmap = intel_glamor_create_pixmap(screen, w, h, depth, usage); 1125 if (pixmap) 1126 return pixmap; 1127 } 1128 1129 if (w > 32767 || h > 32767) 1130 return NullPixmap; 1131 1132 if (depth == 1 || intel->force_fallback) 1133 return fbCreatePixmap(screen, w, h, depth, usage); 1134 1135 if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32) 1136 return fbCreatePixmap(screen, w, h, depth, usage); 1137 1138 pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); 1139 if (pixmap == NullPixmap) 1140 return pixmap; 1141 1142 if (w && h) { 1143 unsigned int size, tiling; 1144 int stride; 1145 1146 /* Always attempt to tile, compute_size() will remove the 1147 * tiling for pixmaps that are either too large or too small 1148 * to be effectively tiled. 1149 */ 1150 tiling = I915_TILING_X; 1151 if (usage & INTEL_CREATE_PIXMAP_TILING_Y) 1152 tiling = I915_TILING_Y; 1153 if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage & INTEL_CREATE_PIXMAP_TILING_NONE) 1154 tiling = I915_TILING_NONE; 1155 1156#ifdef CREATE_PIXMAP_USAGE_SHARED 1157 if (usage == CREATE_PIXMAP_USAGE_SHARED) 1158 tiling = I915_TILING_NONE; 1159#endif 1160 /* if tiling is off force to none */ 1161 if (!intel->tiling) 1162 tiling = I915_TILING_NONE; 1163 1164 if (tiling != I915_TILING_NONE && !(usage & INTEL_CREATE_PIXMAP_DRI2)) { 1165 if (h <= 4) 1166 tiling = I915_TILING_NONE; 1167 if (h <= 16 && tiling == I915_TILING_Y) 1168 tiling = I915_TILING_X; 1169 } 1170 size = intel_uxa_compute_size(intel, 1171 w, h, pixmap->drawable.bitsPerPixel, usage, 1172 &tiling, &stride); 1173 1174 /* Fail very large allocations. Large BOs will tend to hit SW fallbacks 1175 * frequently, and also will tend to fail to successfully map when doing 1176 * SW fallbacks because we overcommit address space for BO access. 1177 */ 1178 if (size > intel->max_bo_size || stride >= KB(32)) 1179 goto fallback_pixmap; 1180 1181 priv = calloc(1, sizeof (struct intel_pixmap)); 1182 if (priv == NULL) 1183 goto fallback_pixmap; 1184 1185 if (usage == UXA_CREATE_PIXMAP_FOR_MAP) { 1186 priv->busy = 0; 1187 priv->bo = drm_intel_bo_alloc(intel->bufmgr, 1188 "pixmap", size, 0); 1189 } else { 1190 priv->busy = -1; 1191 priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr, 1192 "pixmap", 1193 size, 0); 1194 } 1195 if (!priv->bo) 1196 goto fallback_priv; 1197 1198 if (tiling != I915_TILING_NONE) 1199 drm_intel_bo_set_tiling(priv->bo, &tiling, stride); 1200 priv->stride = stride; 1201 priv->tiling = tiling; 1202 priv->offscreen = 1; 1203 1204 list_init(&priv->batch); 1205 intel_set_pixmap_private(pixmap, priv); 1206 1207 screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); 1208 1209 if (!intel_glamor_create_textured_pixmap(pixmap)) 1210 goto fallback_glamor; 1211 } 1212 1213 return pixmap; 1214 1215fallback_glamor: 1216 if (usage & INTEL_CREATE_PIXMAP_DRI2) { 1217 /* XXX need further work to handle the DRI2 failure case. 1218 * Glamor don't know how to handle a BO only pixmap. Put 1219 * a warning indicator here. 1220 */ 1221 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1222 "Failed to create textured DRI2 pixmap."); 1223 return pixmap; 1224 } 1225 /* Create textured pixmap failed means glamor failed to 1226 * create a texture from current BO for some reasons. We turn 1227 * to create a new glamor pixmap and clean up current one. 1228 * One thing need to be noted, this new pixmap doesn't 1229 * has a priv and bo attached to it. It's glamor's responsbility 1230 * to take care of it. Glamor will mark this new pixmap as a 1231 * texture only pixmap and will never fallback to DDX layer 1232 * afterwards. 1233 */ 1234 new_pixmap = intel_glamor_create_pixmap(screen, w, h, 1235 depth, usage); 1236 dri_bo_unreference(priv->bo); 1237fallback_priv: 1238 free(priv); 1239fallback_pixmap: 1240 fbDestroyPixmap(pixmap); 1241 if (new_pixmap) 1242 return new_pixmap; 1243 else 1244 return fbCreatePixmap(screen, w, h, depth, usage); 1245} 1246 1247static Bool intel_uxa_destroy_pixmap(PixmapPtr pixmap) 1248{ 1249 if (pixmap->refcnt == 1) { 1250 intel_glamor_destroy_pixmap(pixmap); 1251 intel_set_pixmap_bo(pixmap, NULL); 1252 } 1253 fbDestroyPixmap(pixmap); 1254 return TRUE; 1255} 1256 1257Bool intel_uxa_create_screen_resources(ScreenPtr screen) 1258{ 1259 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1260 PixmapPtr pixmap; 1261 intel_screen_private *intel = intel_get_screen_private(scrn); 1262 dri_bo *bo = intel->front_buffer; 1263 int old_width, old_height, old_pitch; 1264 1265 if (!uxa_resources_init(screen)) 1266 return FALSE; 1267 1268 if (drm_intel_gem_bo_map_gtt(bo)) 1269 return FALSE; 1270 1271 pixmap = screen->GetScreenPixmap(screen); 1272 old_width = pixmap->drawable.width; 1273 old_height = pixmap->drawable.height; 1274 old_pitch = pixmap->devKind; 1275 1276 if (!screen->ModifyPixmapHeader(pixmap, 1277 scrn->virtualX, 1278 scrn->virtualY, 1279 -1, -1, 1280 intel->front_pitch, 1281 NULL)) 1282 return FALSE; 1283 1284 intel_set_pixmap_bo(pixmap, bo); 1285 if (intel_get_pixmap_private(pixmap) == NULL) 1286 goto err; 1287 1288 if (!intel_glamor_create_screen_resources(screen)) 1289 goto err; 1290 1291 intel_get_pixmap_private(pixmap)->pinned |= PIN_SCANOUT; 1292 scrn->displayWidth = intel->front_pitch / intel->cpp; 1293 1294 return TRUE; 1295 1296err: 1297 screen->ModifyPixmapHeader(pixmap, 1298 old_width, old_height, -1, -1, old_pitch, NULL); 1299 return FALSE; 1300} 1301 1302#ifdef CREATE_PIXMAP_USAGE_SHARED 1303static Bool 1304intel_uxa_share_pixmap_backing(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) 1305{ 1306 ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 1307 intel_screen_private *intel = intel_get_screen_private(scrn); 1308 struct intel_pixmap *priv = intel_get_pixmap_private(ppix); 1309 unsigned int size, tiling, swizzle; 1310 dri_bo *bo = intel_get_pixmap_bo(ppix), *newbo; 1311 int stride; 1312 int handle; 1313 1314 if (drm_intel_bo_references(intel->batch_bo, bo)) 1315 intel_batch_submit(intel->scrn); 1316 1317 drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 1318 1319 if (tiling == I915_TILING_X) { 1320 if (priv->pinned) 1321 return FALSE; 1322 1323 tiling = I915_TILING_NONE; 1324 1325 size = intel_uxa_compute_size(intel, 1326 ppix->drawable.width, ppix->drawable.height, 1327 ppix->drawable.bitsPerPixel, INTEL_CREATE_PIXMAP_DRI2, 1328 &tiling, &stride); 1329 1330 newbo = drm_intel_bo_alloc_for_render(intel->bufmgr, 1331 "pixmap", 1332 size, 0); 1333 1334 if (tiling != I915_TILING_NONE) 1335 drm_intel_bo_set_tiling(newbo, &tiling, stride); 1336 priv->stride = stride; 1337 priv->tiling = tiling; 1338 intel_set_pixmap_bo(ppix, newbo); 1339 1340 ppix->drawable.pScreen->ModifyPixmapHeader(ppix, ppix->drawable.width, 1341 ppix->drawable.height, 0, 0, 1342 stride, NULL); 1343 bo = newbo; 1344 } 1345 drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 1346 drm_intel_bo_gem_export_to_prime(bo, &handle); 1347 priv->pinned |= PIN_PRIME; 1348 1349 *fd_handle = (void *)(long)handle; 1350 return TRUE; 1351} 1352 1353static Bool 1354intel_uxa_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle) 1355{ 1356 ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 1357 intel_screen_private *intel = intel_get_screen_private(scrn); 1358 dri_bo *bo; 1359 int ihandle = (int)(long)fd_handle; 1360 1361 /* force untiled for now */ 1362 bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, ihandle, 0); 1363 if (!bo) 1364 return FALSE; 1365 1366 intel_set_pixmap_bo(ppix, bo); 1367 close(ihandle); 1368 return TRUE; 1369} 1370#endif 1371 1372static void 1373intel_limits_init(intel_screen_private *intel) 1374{ 1375 /* Limits are described in the BLT engine chapter under Graphics Data Size 1376 * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO, 1377 * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO. 1378 * 1379 * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768. 1380 * 1381 * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled. 1382 * i965 limits 3D surface to 4kB-aligned offset if tiled. 1383 * i965 limits 3D surfaces to w,h of ?,8192. 1384 * i965 limits 3D surface to pitch of 1B - 128kB. 1385 * i965 limits 3D surface pitch alignment to 1 or 2 times the element size. 1386 * i965 limits 3D surface pitch alignment to 512B if tiled. 1387 * i965 limits 3D destination drawing rect to w,h of 8192,8192. 1388 * 1389 * i915 limits 3D textures to 4B-aligned offset if un-tiled. 1390 * i915 limits 3D textures to ~4kB-aligned offset if tiled. 1391 * i915 limits 3D textures to width,height of 2048,2048. 1392 * i915 limits 3D textures to pitch of 16B - 8kB, in dwords. 1393 * i915 limits 3D destination to ~4kB-aligned offset if tiled. 1394 * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled. 1395 * i915 limits 3D destination to pitch 64B-aligned if used with depth. 1396 * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled. 1397 * i915 limits 3D destination to POT aligned pitch if tiled. 1398 * i915 limits 3D destination drawing rect to w,h of 2048,2048. 1399 * 1400 * i845 limits 3D textures to 4B-aligned offset if un-tiled. 1401 * i845 limits 3D textures to ~4kB-aligned offset if tiled. 1402 * i845 limits 3D textures to width,height of 2048,2048. 1403 * i845 limits 3D textures to pitch of 4B - 8kB, in dwords. 1404 * i845 limits 3D destination to 4B-aligned offset if un-tiled. 1405 * i845 limits 3D destination to ~4kB-aligned offset if tiled. 1406 * i845 limits 3D destination to pitch of 8B - 8kB, in dwords. 1407 * i845 limits 3D destination drawing rect to w,h of 2048,2048. 1408 * 1409 * For the tiled issues, the only tiled buffer we draw to should be 1410 * the front, which will have an appropriate pitch/offset already set up, 1411 * so UXA doesn't need to worry. 1412 */ 1413 if (INTEL_INFO(intel)->gen >= 040) { 1414 intel->accel_pixmap_offset_alignment = 4 * 2; 1415 intel->accel_max_x = 8192; 1416 intel->accel_max_y = 8192; 1417 } else { 1418 intel->accel_pixmap_offset_alignment = 4; 1419 intel->accel_max_x = 2048; 1420 intel->accel_max_y = 2048; 1421 } 1422} 1423 1424static Bool intel_option_accel_none(intel_screen_private *intel) 1425{ 1426 const char *s; 1427 1428 s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD); 1429 if (s == NULL) 1430 return IS_DEFAULT_ACCEL_METHOD(NOACCEL); 1431 1432 return strcasecmp(s, "none") == 0; 1433} 1434 1435static Bool intel_option_accel_blt(intel_screen_private *intel) 1436{ 1437 const char *s; 1438 1439 s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD); 1440 if (s == NULL) 1441 return FALSE; 1442 1443 return strcasecmp(s, "blt") == 0; 1444} 1445 1446Bool intel_uxa_init(ScreenPtr screen) 1447{ 1448 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1449 intel_screen_private *intel = intel_get_screen_private(scrn); 1450 1451#if HAS_DIXREGISTERPRIVATEKEY 1452 if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0)) 1453#else 1454 if (!dixRequestPrivate(&uxa_pixmap_index, 0)) 1455#endif 1456 return FALSE; 1457 1458 intel_limits_init(intel); 1459 1460 intel->uxa_driver = uxa_driver_alloc(); 1461 if (intel->uxa_driver == NULL) 1462 return FALSE; 1463 1464 memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver)); 1465 1466 intel->uxa_driver->uxa_major = 1; 1467 intel->uxa_driver->uxa_minor = 0; 1468 1469 intel->prim_offset = 0; 1470 intel->vertex_count = 0; 1471 intel->vertex_offset = 0; 1472 intel->vertex_used = 0; 1473 intel->floats_per_vertex = 0; 1474 intel->last_floats_per_vertex = 0; 1475 intel->vertex_bo = NULL; 1476 intel->surface_used = 0; 1477 intel->surface_reloc = 0; 1478 1479 /* Solid fill */ 1480 intel->uxa_driver->check_solid = intel_uxa_check_solid; 1481 intel->uxa_driver->prepare_solid = intel_uxa_prepare_solid; 1482 intel->uxa_driver->solid = intel_uxa_solid; 1483 intel->uxa_driver->done_solid = intel_uxa_done; 1484 1485 /* Copy */ 1486 intel->uxa_driver->check_copy = intel_uxa_check_copy; 1487 intel->uxa_driver->prepare_copy = intel_uxa_prepare_copy; 1488 intel->uxa_driver->copy = intel_uxa_copy; 1489 intel->uxa_driver->done_copy = intel_uxa_done; 1490 1491 /* Composite */ 1492 if (intel_option_accel_blt(intel)) { 1493 } else if (INTEL_INFO(intel)->gen < 030) { 1494 intel->uxa_driver->check_composite = i830_check_composite; 1495 intel->uxa_driver->check_composite_target = i830_check_composite_target; 1496 intel->uxa_driver->check_composite_texture = i830_check_composite_texture; 1497 intel->uxa_driver->prepare_composite = i830_prepare_composite; 1498 intel->uxa_driver->composite = i830_composite; 1499 intel->uxa_driver->done_composite = i830_done_composite; 1500 1501 intel->vertex_flush = i830_vertex_flush; 1502 intel->batch_commit_notify = i830_batch_commit_notify; 1503 } else if (INTEL_INFO(intel)->gen < 040) { 1504 intel->uxa_driver->check_composite = i915_check_composite; 1505 intel->uxa_driver->check_composite_target = i915_check_composite_target; 1506 intel->uxa_driver->check_composite_texture = i915_check_composite_texture; 1507 intel->uxa_driver->prepare_composite = i915_prepare_composite; 1508 intel->uxa_driver->composite = i915_composite; 1509 intel->uxa_driver->done_composite = i830_done_composite; 1510 1511 intel->vertex_flush = i915_vertex_flush; 1512 intel->batch_commit_notify = i915_batch_commit_notify; 1513 } else if (INTEL_INFO(intel)->gen < 0100) { 1514 intel->uxa_driver->check_composite = i965_check_composite; 1515 intel->uxa_driver->check_composite_texture = i965_check_composite_texture; 1516 intel->uxa_driver->prepare_composite = i965_prepare_composite; 1517 intel->uxa_driver->composite = i965_composite; 1518 intel->uxa_driver->done_composite = i830_done_composite; 1519 1520 intel->vertex_flush = i965_vertex_flush; 1521 intel->batch_flush = i965_batch_flush; 1522 intel->batch_commit_notify = i965_batch_commit_notify; 1523 1524 if (INTEL_INFO(intel)->gen < 050) { 1525 intel->context_switch = gen4_context_switch; 1526 } else if (INTEL_INFO(intel)->gen < 060) { 1527 intel->context_switch = gen5_context_switch; 1528 } else { 1529 intel->context_switch = gen6_context_switch; 1530 } 1531 } 1532 1533 /* PutImage */ 1534 intel->uxa_driver->put_image = intel_uxa_put_image; 1535 intel->uxa_driver->get_image = intel_uxa_get_image; 1536 1537 intel->uxa_driver->prepare_access = intel_uxa_prepare_access; 1538 intel->uxa_driver->finish_access = intel_uxa_finish_access; 1539 intel->uxa_driver->pixmap_is_offscreen = intel_uxa_pixmap_is_offscreen; 1540 1541 screen->CreatePixmap = intel_uxa_create_pixmap; 1542 screen->DestroyPixmap = intel_uxa_destroy_pixmap; 1543 1544#ifdef CREATE_PIXMAP_USAGE_SHARED 1545 screen->SharePixmapBacking = intel_uxa_share_pixmap_backing; 1546 screen->SetSharedPixmapBacking = intel_uxa_set_shared_pixmap_backing; 1547#endif 1548 1549 if (!uxa_driver_init(screen, intel->uxa_driver)) { 1550 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1551 "UXA initialization failed\n"); 1552 free(intel->uxa_driver); 1553 return FALSE; 1554 } 1555 1556 if (intel_option_accel_none(intel)) 1557 intel->force_fallback = 1; 1558 1559 uxa_set_fallback_debug(screen, intel->fallback_debug); 1560 uxa_set_force_fallback(screen, intel->force_fallback); 1561 1562 intel->flush_rendering = intel_flush_rendering; 1563 return TRUE; 1564} 1565