radeon_exa.c revision 68105dcb
1/* 2 * Copyright 2005 Eric Anholt 3 * Copyright 2005 Benjamin Herrenschmidt 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * Authors: 26 * Eric Anholt <anholt@FreeBSD.org> 27 * Zack Rusin <zrusin@trolltech.com> 28 * Benjamin Herrenschmidt <benh@kernel.crashing.org> 29 * 30 */ 31 32#ifdef HAVE_CONFIG_H 33#include "config.h" 34#endif 35 36#include "radeon.h" 37#include "radeon_reg.h" 38#include "r600_reg.h" 39#ifdef XF86DRI 40#include "radeon_drm.h" 41#endif 42#include "radeon_macros.h" 43#include "radeon_probe.h" 44#include "radeon_version.h" 45#include "radeon_exa_shared.h" 46 47#include "xf86.h" 48 49 50/***********************************************************************/ 51#define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn = xf86ScreenToScrn(pScr); \ 52 RADEONInfoPtr info = RADEONPTR(pScrn) 53 54static struct { 55 int rop; 56 int pattern; 57} RADEON_ROP[] = { 58 { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear */ 59 { RADEON_ROP3_DSa, RADEON_ROP3_DPa }, /* Gxand */ 60 { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse */ 61 { RADEON_ROP3_S, RADEON_ROP3_P }, /* GXcopy */ 62 { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted */ 63 { RADEON_ROP3_D, RADEON_ROP3_D }, /* GXnoop */ 64 { RADEON_ROP3_DSx, RADEON_ROP3_DPx }, /* GXxor */ 65 { RADEON_ROP3_DSo, RADEON_ROP3_DPo }, /* GXor */ 66 { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor */ 67 { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv */ 68 { RADEON_ROP3_Dn, RADEON_ROP3_Dn }, /* GXinvert */ 69 { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse */ 70 { RADEON_ROP3_Sn, RADEON_ROP3_Pn }, /* GXcopyInverted */ 71 { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted */ 72 { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand */ 73 { RADEON_ROP3_ONE, RADEON_ROP3_ONE } /* GXset */ 74}; 75 76/* Compute log base 2 of val. */ 77static __inline__ int 78RADEONLog2(int val) 79{ 80 int bits; 81#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__) 82 __asm volatile("bsrl %1, %0" 83 : "=r" (bits) 84 : "c" (val) 85 ); 86 return bits; 87#else 88 for (bits = 0; val != 0; val >>= 1, ++bits) 89 ; 90 return bits - 1; 91#endif 92} 93 94static __inline__ uint32_t F_TO_DW(float val) 95{ 96 union { 97 float f; 98 uint32_t l; 99 } tmp; 100 tmp.f = val; 101 return tmp.l; 102} 103 104 105/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we 106 * require src and dest datatypes to be equal. 107 */ 108Bool RADEONGetDatatypeBpp(int bpp, uint32_t *type) 109{ 110 switch (bpp) { 111 case 8: 112 *type = ATI_DATATYPE_CI8; 113 return TRUE; 114 case 16: 115 *type = ATI_DATATYPE_RGB565; 116 return TRUE; 117 case 24: 118 *type = ATI_DATATYPE_CI8; 119 return TRUE; 120 case 32: 121 *type = ATI_DATATYPE_ARGB8888; 122 return TRUE; 123 default: 124 RADEON_FALLBACK(("Unsupported bpp: %d\n", bpp)); 125 return FALSE; 126 } 127} 128 129static Bool RADEONPixmapIsColortiled(PixmapPtr pPix) 130{ 131 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 132 133#ifdef XF86DRM_MODE 134 if (info->cs) { 135 /* Taken care of by the kernel relocation handling */ 136 return FALSE; 137 } 138#endif 139 140 /* This doesn't account for the back buffer, which we may want to wrap in 141 * a pixmap at some point for the purposes of DRI buffer moves. 142 */ 143 if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0) 144 return TRUE; 145 else 146 return FALSE; 147} 148 149static Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset, 150 unsigned int offset, unsigned int pitch) 151{ 152 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 153 154 if (pitch > 16320 || pitch % info->accel_state->exa->pixmapPitchAlign != 0) 155 RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch)); 156 157 if (offset % info->accel_state->exa->pixmapOffsetAlign != 0) 158 RADEON_FALLBACK(("Bad offset 0x%08x\n", offset)); 159 160 pitch = pitch >> 6; 161 *pitch_offset = (pitch << 22) | (offset >> 10); 162 163 /* If it's the front buffer, we've got to note that it's tiled? */ 164 if (RADEONPixmapIsColortiled(pPix)) 165 *pitch_offset |= RADEON_DST_TILE_MACRO; 166 return TRUE; 167} 168 169Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) 170{ 171 uint32_t pitch, offset; 172 int bpp; 173 174 bpp = pPix->drawable.bitsPerPixel; 175 if (bpp == 24) 176 bpp = 8; 177 178 offset = radeonGetPixmapOffset(pPix); 179 pitch = exaGetPixmapPitch(pPix); 180 181 return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); 182} 183 184/** 185 * Returns whether the provided transform is affine. 186 * 187 * transform may be null. 188 */ 189Bool radeon_transform_is_affine_or_scaled(PictTransformPtr t) 190{ 191 if (t == NULL) 192 return TRUE; 193 /* the shaders don't handle scaling either */ 194 return t->matrix[2][0] == 0 && t->matrix[2][1] == 0 && t->matrix[2][2] == IntToxFixed(1); 195} 196 197#if X_BYTE_ORDER == X_BIG_ENDIAN 198 199static unsigned long swapper_surfaces[6]; 200 201static Bool RADEONPrepareAccess_BE(PixmapPtr pPix, int index) 202{ 203 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 204 unsigned char *RADEONMMIO = info->MMIO; 205 uint32_t offset = exaGetPixmapOffset(pPix); 206 int bpp, soff; 207 uint32_t size, flags; 208 209 /* Front buffer is always set with proper swappers */ 210 if (offset == 0) 211 return TRUE; 212 213 /* If same bpp as front buffer, just do nothing as the main 214 * swappers will apply 215 */ 216 bpp = pPix->drawable.bitsPerPixel; 217 if (bpp == pScrn->bitsPerPixel) 218 return TRUE; 219 220 /* We need to setup a separate swapper, let's request a 221 * surface. We need to align the size first 222 */ 223 size = exaGetPixmapSize(pPix); 224 size = RADEON_ALIGN(size, RADEON_GPU_PAGE_SIZE); 225 226 /* Set surface to tiling disabled with appropriate swapper */ 227 switch (bpp) { 228 case 16: 229 flags = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP; 230 break; 231 case 32: 232 flags = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; 233 break; 234 default: 235 flags = 0; 236 } 237#if defined(XF86DRI) 238 if (info->directRenderingEnabled && info->allowColorTiling) { 239 struct drm_radeon_surface_alloc drmsurfalloc; 240 int rc; 241 242 drmsurfalloc.address = offset; 243 drmsurfalloc.size = size; 244 drmsurfalloc.flags = flags | 1; /* bogus pitch to please DRM */ 245 246 rc = drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_ALLOC, 247 &drmsurfalloc, sizeof(drmsurfalloc)); 248 if (rc < 0) { 249 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 250 "drm: could not allocate surface for access" 251 " swapper, err: %d!\n", rc); 252 return FALSE; 253 } 254 swapper_surfaces[index] = offset; 255 256 return TRUE; 257 } 258#endif 259 soff = (index + 1) * 0x10; 260 OUTREG(RADEON_SURFACE0_INFO + soff, flags); 261 OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset); 262 OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1); 263 swapper_surfaces[index] = offset; 264 return TRUE; 265} 266 267static void RADEONFinishAccess_BE(PixmapPtr pPix, int index) 268{ 269 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 270 unsigned char *RADEONMMIO = info->MMIO; 271 uint32_t offset = exaGetPixmapOffset(pPix); 272 int soff; 273 274 /* Front buffer is always set with proper swappers */ 275 if (offset == 0) 276 return; 277 278 if (swapper_surfaces[index] == 0) 279 return; 280#if defined(XF86DRI) 281 if (info->directRenderingEnabled && info->allowColorTiling) { 282 struct drm_radeon_surface_free drmsurffree; 283 284 drmsurffree.address = offset; 285 drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_FREE, 286 &drmsurffree, sizeof(drmsurffree)); 287 swapper_surfaces[index] = 0; 288 return; 289 } 290#endif 291 soff = (index + 1) * 0x10; 292 OUTREG(RADEON_SURFACE0_INFO + soff, 0); 293 OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0); 294 OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0); 295 swapper_surfaces[index] = 0; 296} 297 298#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ 299 300#ifdef XF86DRM_MODE 301Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index) 302{ 303 ScreenPtr pScreen = pPix->drawable.pScreen; 304 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 305 RADEONInfoPtr info = RADEONPTR(pScrn); 306 struct radeon_exa_pixmap_priv *driver_priv; 307 uint32_t possible_domains = ~0U; 308 uint32_t current_domain = 0; 309#ifdef EXA_MIXED_PIXMAPS 310 Bool can_fail = !(pPix->drawable.bitsPerPixel < 8) && 311 pPix != pScreen->GetScreenPixmap(pScreen) && 312 (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS); 313#else 314 Bool can_fail = FALSE; 315#endif 316 Bool flush = FALSE; 317 int ret; 318 319#if X_BYTE_ORDER == X_BIG_ENDIAN 320 /* May need to handle byte swapping in DownloadFrom/UploadToScreen */ 321 if (can_fail && pPix->drawable.bitsPerPixel > 8) 322 return FALSE; 323#endif 324 325 driver_priv = exaGetPixmapDriverPrivate(pPix); 326 if (!driver_priv) 327 return FALSE; 328 329 /* untile in DFS/UTS */ 330 if (driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO)) 331 return FALSE; 332 333 /* if we have more refs than just the BO then flush */ 334 if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { 335 flush = TRUE; 336 337 if (can_fail) { 338 possible_domains = radeon_bo_get_src_domain(driver_priv->bo); 339 if (possible_domains == RADEON_GEM_DOMAIN_VRAM) 340 return FALSE; /* use DownloadFromScreen */ 341 } 342 } 343 344 /* if the BO might end up in VRAM, prefer DownloadFromScreen */ 345 if (can_fail && (possible_domains & RADEON_GEM_DOMAIN_VRAM)) { 346 radeon_bo_is_busy(driver_priv->bo, ¤t_domain); 347 348 if (current_domain & possible_domains) { 349 if (current_domain == RADEON_GEM_DOMAIN_VRAM) 350 return FALSE; 351 } else if (possible_domains & RADEON_GEM_DOMAIN_VRAM) 352 return FALSE; 353 } 354 355 if (flush) 356 radeon_cs_flush_indirect(pScrn); 357 358 /* flush IB */ 359 ret = radeon_bo_map(driver_priv->bo, 1); 360 if (ret) { 361 FatalError("failed to map pixmap %d\n", ret); 362 return FALSE; 363 } 364 driver_priv->bo_mapped = TRUE; 365 366 pPix->devPrivate.ptr = driver_priv->bo->ptr; 367 368 return TRUE; 369} 370 371void RADEONFinishAccess_CS(PixmapPtr pPix, int index) 372{ 373 struct radeon_exa_pixmap_priv *driver_priv; 374 375 driver_priv = exaGetPixmapDriverPrivate(pPix); 376 if (!driver_priv || !driver_priv->bo_mapped) 377 return; 378 379 radeon_bo_unmap(driver_priv->bo); 380 driver_priv->bo_mapped = FALSE; 381 pPix->devPrivate.ptr = NULL; 382} 383 384 385void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align) 386{ 387 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 388 RADEONInfoPtr info = RADEONPTR(pScrn); 389 struct radeon_exa_pixmap_priv *new_priv; 390 391#ifdef EXA_MIXED_PIXMAPS 392 if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) { 393 if (size != 0 && !info->exa_force_create && 394 info->exa_pixmaps == FALSE) 395 return NULL; 396 } 397#endif 398 399 new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv)); 400 if (!new_priv) 401 return NULL; 402 403 if (size == 0) 404 return new_priv; 405 406 new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, align, 407 RADEON_GEM_DOMAIN_VRAM, 0); 408 if (!new_priv->bo) { 409 free(new_priv); 410 ErrorF("Failed to alloc memory\n"); 411 return NULL; 412 } 413 414 return new_priv; 415 416} 417 418static const unsigned MicroBlockTable[5][3][2] = { 419 /*linear tiled square-tiled */ 420 {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */ 421 {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */ 422 {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */ 423 {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */ 424 {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ 425}; 426 427/* Return true if macrotiling can be enabled */ 428static Bool RADEONMacroSwitch(int width, int height, int bpp, 429 uint32_t flags, Bool rv350_mode) 430{ 431 unsigned tilew, tileh, microtiled, logbpp; 432 433 logbpp = RADEONLog2(bpp / 8); 434 if (logbpp > 4) 435 return 0; 436 437 microtiled = !!(flags & RADEON_TILING_MICRO); 438 tilew = MicroBlockTable[logbpp][microtiled][0] * 8; 439 tileh = MicroBlockTable[logbpp][microtiled][1] * 8; 440 441 /* See TX_FILTER1_n.MACRO_SWITCH. */ 442 if (rv350_mode) { 443 return width >= tilew && height >= tileh; 444 } else { 445 return width > tilew && height > tileh; 446 } 447} 448 449void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, 450 int depth, int usage_hint, int bitsPerPixel, 451 int *new_pitch) 452{ 453 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 454 RADEONInfoPtr info = RADEONPTR(pScrn); 455 struct radeon_exa_pixmap_priv *new_priv; 456 int pitch, base_align; 457 uint32_t size, heighta; 458 uint32_t tiling = 0; 459 int cpp = bitsPerPixel / 8; 460#ifdef XF86DRM_MODE 461 struct radeon_surface surface; 462#endif 463 464#ifdef EXA_MIXED_PIXMAPS 465 if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) { 466 if (width != 0 && height != 0 && !info->exa_force_create && 467 info->exa_pixmaps == FALSE) 468 return NULL; 469 } 470#endif 471 472 if (usage_hint) { 473 if (info->allowColorTiling) { 474 if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO) 475 tiling |= RADEON_TILING_MACRO; 476 if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO) 477 tiling |= RADEON_TILING_MICRO; 478 } 479 if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH) 480 tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO; 481 482 } 483 484 /* Small pixmaps must not be macrotiled on R300, hw cannot sample them 485 * correctly because samplers automatically switch to macrolinear. */ 486 if (info->ChipFamily >= CHIP_FAMILY_R300 && 487 info->ChipFamily <= CHIP_FAMILY_RS740 && 488 (tiling & RADEON_TILING_MACRO) && 489 !RADEONMacroSwitch(width, height, bitsPerPixel, tiling, 490 info->ChipFamily >= CHIP_FAMILY_RV350)) { 491 tiling &= ~RADEON_TILING_MACRO; 492 } 493 494 heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling)); 495 pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp; 496 base_align = drmmode_get_base_align(pScrn, cpp, tiling); 497 size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE); 498 memset(&surface, 0, sizeof(struct radeon_surface)); 499 500#ifdef XF86DRM_MODE 501 if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { 502 if (width) { 503 surface.npix_x = width; 504 /* need to align height to 8 for old kernel */ 505 surface.npix_y = RADEON_ALIGN(height, 8); 506 surface.npix_z = 1; 507 surface.blk_w = 1; 508 surface.blk_h = 1; 509 surface.blk_d = 1; 510 surface.array_size = 1; 511 surface.last_level = 0; 512 surface.bpe = cpp; 513 surface.nsamples = 1; 514 if (height < 64) { 515 /* disable 2d tiling for small surface to work around 516 * the fact that ddx align height to 8 pixel for old 517 * obscure reason i can't remember 518 */ 519 tiling &= ~RADEON_TILING_MACRO; 520 } 521 surface.flags = RADEON_SURF_SCANOUT; 522 surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); 523 surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); 524 if ((tiling & RADEON_TILING_MICRO)) { 525 surface.flags = RADEON_SURF_CLR(surface.flags, MODE); 526 surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 527 } 528 if ((tiling & RADEON_TILING_MACRO)) { 529 surface.flags = RADEON_SURF_CLR(surface.flags, MODE); 530 surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 531 } 532 if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) { 533 surface.flags |= RADEON_SURF_ZBUFFER; 534 surface.flags |= RADEON_SURF_SBUFFER; 535 } 536 if (radeon_surface_best(info->surf_man, &surface)) { 537 return NULL; 538 } 539 if (radeon_surface_init(info->surf_man, &surface)) { 540 return NULL; 541 } 542 size = surface.bo_size; 543 base_align = surface.bo_alignment; 544 pitch = surface.level[0].pitch_bytes; 545 tiling = 0; 546 switch (surface.level[0].mode) { 547 case RADEON_SURF_MODE_2D: 548 tiling |= RADEON_TILING_MACRO; 549 tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; 550 tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; 551 tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; 552 tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT; 553 tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT; 554 break; 555 case RADEON_SURF_MODE_1D: 556 tiling |= RADEON_TILING_MICRO; 557 break; 558 default: 559 break; 560 } 561 } 562 } 563#endif 564 565 new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv)); 566 if (!new_priv) { 567 return NULL; 568 } 569 570 if (size == 0) { 571 return new_priv; 572 } 573 574 *new_pitch = pitch; 575 576 new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, base_align, 577 RADEON_GEM_DOMAIN_VRAM, 0); 578 if (!new_priv->bo) { 579 free(new_priv); 580 ErrorF("Failed to alloc memory\n"); 581 return NULL; 582 } 583 584 if (tiling && !radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch)) 585 new_priv->tiling_flags = tiling; 586 587 new_priv->surface = surface; 588 return new_priv; 589} 590 591void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) 592{ 593 struct radeon_exa_pixmap_priv *driver_priv = driverPriv; 594 595 if (!driverPriv) 596 return; 597 598 if (driver_priv->bo) 599 radeon_bo_unref(driver_priv->bo); 600 free(driverPriv); 601} 602 603struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix) 604{ 605 struct radeon_exa_pixmap_priv *driver_priv; 606 driver_priv = exaGetPixmapDriverPrivate(pPix); 607 return driver_priv->bo; 608} 609 610#if defined(XF86DRM_MODE) 611struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix) 612{ 613 struct radeon_exa_pixmap_priv *driver_priv; 614 driver_priv = exaGetPixmapDriverPrivate(pPix); 615 return &driver_priv->surface; 616} 617#endif 618 619uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix) 620{ 621 struct radeon_exa_pixmap_priv *driver_priv; 622 driver_priv = exaGetPixmapDriverPrivate(pPix); 623 return driver_priv->tiling_flags; 624} 625 626void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) 627{ 628 struct radeon_exa_pixmap_priv *driver_priv; 629 630 driver_priv = exaGetPixmapDriverPrivate(pPix); 631 if (driver_priv) { 632 uint32_t pitch; 633 634 if (driver_priv->bo) 635 radeon_bo_unref(driver_priv->bo); 636 637 radeon_bo_ref(bo); 638 driver_priv->bo = bo; 639 640 radeon_bo_get_tiling(bo, &driver_priv->tiling_flags, &pitch); 641 } 642} 643 644Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix) 645{ 646 struct radeon_exa_pixmap_priv *driver_priv; 647 648 driver_priv = exaGetPixmapDriverPrivate(pPix); 649 650 if (!driver_priv) 651 return FALSE; 652 if (driver_priv->bo) 653 return TRUE; 654 return FALSE; 655} 656#endif 657 658#define ENTER_DRAW(x) TRACE 659#define LEAVE_DRAW(x) TRACE 660/***********************************************************************/ 661 662#define ACCEL_MMIO 663#define ACCEL_PREAMBLE() unsigned char *RADEONMMIO = info->MMIO 664#define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) 665#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) 666#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val)) 667#define OUT_RELOC(x, read, write) do {} while(0) 668#define FINISH_ACCEL() 669 670#ifdef RENDER 671#include "radeon_exa_render.c" 672#endif 673#include "radeon_exa_funcs.c" 674 675#undef ACCEL_MMIO 676#undef ACCEL_PREAMBLE 677#undef BEGIN_ACCEL 678#undef OUT_ACCEL_REG 679#undef OUT_ACCEL_REG_F 680#undef FINISH_ACCEL 681#undef OUT_RELOC 682 683#ifdef XF86DRI 684 685#define ACCEL_CP 686#define ACCEL_PREAMBLE() \ 687 RING_LOCALS; \ 688 RADEONCP_REFRESH(pScrn, info) 689#define BEGIN_ACCEL(n) BEGIN_RING(2*(n)) 690#define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) 691#define FINISH_ACCEL() ADVANCE_RING() 692#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write) 693 694#define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) 695 696#ifdef RENDER 697#include "radeon_exa_render.c" 698#endif 699#include "radeon_exa_funcs.c" 700 701#undef ACCEL_CP 702#undef ACCEL_PREAMBLE 703#undef BEGIN_ACCEL 704#undef OUT_ACCEL_REG 705#undef FINISH_ACCEL 706#undef OUT_RING_F 707 708#endif /* XF86DRI */ 709 710/* 711 * Once screen->off_screen_base is set, this function 712 * allocates the remaining memory appropriately 713 */ 714Bool RADEONSetupMemEXA (ScreenPtr pScreen) 715{ 716 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 717 RADEONInfoPtr info = RADEONPTR(pScrn); 718 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 719 int cpp = info->CurrentLayout.pixel_bytes; 720 int screen_size; 721 int byteStride = pScrn->displayWidth * cpp; 722 723 if (info->accel_state->exa != NULL) { 724 xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n"); 725 return FALSE; 726 } 727 info->accel_state->exa = exaDriverAlloc(); 728 if (info->accel_state->exa == NULL) 729 return FALSE; 730 731 /* Need to adjust screen size for 16 line tiles, and then make it align to. 732 * the buffer alignment requirement. 733 */ 734 if (info->allowColorTiling) 735 screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride; 736 else 737 screen_size = pScrn->virtualY * byteStride; 738 739 info->accel_state->exa->memoryBase = info->FB; 740 info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize; 741 info->accel_state->exa->offScreenBase = screen_size; 742 743 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n", 744 info->accel_state->exa->memorySize / 1024); 745 746 /* Reserve static area for hardware cursor */ 747 if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 748 int cursor_size = 64 * 4 * 64; 749 int align = IS_AVIVO_VARIANT ? 4096 : 256; 750 int c; 751 752 for (c = 0; c < xf86_config->num_crtc; c++) { 753 xf86CrtcPtr crtc = xf86_config->crtc[c]; 754 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 755 756 radeon_crtc->cursor_offset = 757 RADEON_ALIGN(info->accel_state->exa->offScreenBase, align); 758 info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size; 759 760 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 761 "Will use %d kb for hardware cursor %d at offset 0x%08x\n", 762 (cursor_size * xf86_config->num_crtc) / 1024, 763 c, 764 (unsigned int)radeon_crtc->cursor_offset); 765 } 766 } 767 768#if defined(XF86DRI) 769 if (info->directRenderingEnabled) { 770 int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size; 771 772 info->dri->frontOffset = 0; 773 info->dri->frontPitch = pScrn->displayWidth; 774 775 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 776 "Will use %d kb for front buffer at offset 0x%08x\n", 777 screen_size / 1024, info->dri->frontOffset); 778 RADEONDRIAllocatePCIGARTTable(pScreen); 779 780 if (info->cardType==CARD_PCIE) 781 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 782 "Will use %d kb for PCI GART at offset 0x%08x\n", 783 info->dri->pciGartSize / 1024, 784 (int)info->dri->pciGartOffset); 785 786 /* Reserve a static area for the back buffer the same size as the 787 * visible screen. XXX: This would be better initialized in ati_dri.c 788 * when GLX is set up, but the offscreen memory manager's allocations 789 * don't last through VT switches, while the kernel's understanding of 790 * offscreen locations does. 791 */ 792 info->dri->backPitch = pScrn->displayWidth; 793 next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE); 794 if (!info->dri->noBackBuffer && 795 next + screen_size <= info->accel_state->exa->memorySize) 796 { 797 info->dri->backOffset = next; 798 info->accel_state->exa->offScreenBase = next + screen_size; 799 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 800 "Will use %d kb for back buffer at offset 0x%08x\n", 801 screen_size / 1024, info->dri->backOffset); 802 } 803 804 /* Reserve the static depth buffer, and adjust pitch and height to 805 * handle tiling. 806 */ 807 info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); 808 depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp; 809 next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE); 810 if (next + depth_size <= info->accel_state->exa->memorySize) 811 { 812 info->dri->depthOffset = next; 813 info->accel_state->exa->offScreenBase = next + depth_size; 814 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 815 "Will use %d kb for depth buffer at offset 0x%08x\n", 816 depth_size / 1024, info->dri->depthOffset); 817 } 818 819 info->dri->textureSize *= (info->accel_state->exa->memorySize - 820 info->accel_state->exa->offScreenBase) / 100; 821 822 l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS); 823 if (l < RADEON_LOG_TEX_GRANULARITY) 824 l = RADEON_LOG_TEX_GRANULARITY; 825 info->dri->textureSize = (info->dri->textureSize >> l) << l; 826 if (info->dri->textureSize >= 512 * 1024) { 827 info->dri->textureOffset = info->accel_state->exa->offScreenBase; 828 info->accel_state->exa->offScreenBase += info->dri->textureSize; 829 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 830 "Will use %d kb for textures at offset 0x%08x\n", 831 info->dri->textureSize / 1024, info->dri->textureOffset); 832 } else { 833 /* Minimum texture size is for 2 256x256x32bpp textures */ 834 info->dri->textureSize = 0; 835 } 836 } else 837#endif /* XF86DRI */ 838 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 839 "Will use %d kb for front buffer at offset 0x%08x\n", 840 screen_size / 1024, 0); 841 842 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 843 "Will use %ld kb for X Server offscreen at offset 0x%08lx\n", 844 (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) / 845 1024, info->accel_state->exa->offScreenBase); 846 847 return TRUE; 848} 849 850#ifdef XF86DRI 851 852#ifndef ExaOffscreenMarkUsed 853extern void ExaOffscreenMarkUsed(PixmapPtr); 854#endif 855 856unsigned long long 857RADEONTexOffsetStart(PixmapPtr pPix) 858{ 859 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 860 unsigned long long offset; 861 862 if (exaGetPixmapDriverPrivate(pPix)) 863 return -1; 864 865 exaMoveInPixmap(pPix); 866 ExaOffscreenMarkUsed(pPix); 867 868 offset = exaGetPixmapOffset(pPix); 869 870 if (offset > info->FbMapSize) 871 return ~0ULL; 872 else 873 return info->fbLocation + offset; 874} 875#endif 876