radeon_exa.c revision 0974d292
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 = xf86Screens[pScr->myNum]; \ 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 /* This doesn't account for the back buffer, which we may want to wrap in 134 * a pixmap at some point for the purposes of DRI buffer moves. 135 */ 136 if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0) 137 return TRUE; 138 else 139 return FALSE; 140} 141 142static Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset, 143 unsigned int offset, unsigned int pitch) 144{ 145 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 146 147 if (pitch > 16320 || pitch % info->accel_state->exa->pixmapPitchAlign != 0) 148 RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch)); 149 150 if (offset % info->accel_state->exa->pixmapOffsetAlign != 0) 151 RADEON_FALLBACK(("Bad offset 0x%08x\n", offset)); 152 153 pitch = pitch >> 6; 154 *pitch_offset = (pitch << 22) | (offset >> 10); 155 156 /* If it's the front buffer, we've got to note that it's tiled? */ 157 if (RADEONPixmapIsColortiled(pPix)) 158 *pitch_offset |= RADEON_DST_TILE_MACRO; 159 return TRUE; 160} 161 162Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) 163{ 164 uint32_t pitch, offset; 165 int bpp; 166 167 bpp = pPix->drawable.bitsPerPixel; 168 if (bpp == 24) 169 bpp = 8; 170 171 offset = radeonGetPixmapOffset(pPix); 172 pitch = exaGetPixmapPitch(pPix); 173 174 return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); 175} 176 177#if X_BYTE_ORDER == X_BIG_ENDIAN 178 179static unsigned long swapper_surfaces[6]; 180 181static Bool RADEONPrepareAccess_BE(PixmapPtr pPix, int index) 182{ 183 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 184 unsigned char *RADEONMMIO = info->MMIO; 185 uint32_t offset = exaGetPixmapOffset(pPix); 186 int bpp, soff; 187 uint32_t size, flags; 188 189 /* Front buffer is always set with proper swappers */ 190 if (offset == 0) 191 return TRUE; 192 193 /* If same bpp as front buffer, just do nothing as the main 194 * swappers will apply 195 */ 196 bpp = pPix->drawable.bitsPerPixel; 197 if (bpp == pScrn->bitsPerPixel) 198 return TRUE; 199 200 /* We need to setup a separate swapper, let's request a 201 * surface. We need to align the size first 202 */ 203 size = exaGetPixmapSize(pPix); 204 size = RADEON_ALIGN(size, RADEON_GPU_PAGE_SIZE); 205 206 /* Set surface to tiling disabled with appropriate swapper */ 207 switch (bpp) { 208 case 16: 209 flags = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP; 210 break; 211 case 32: 212 flags = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; 213 break; 214 default: 215 flags = 0; 216 } 217#if defined(XF86DRI) 218 if (info->directRenderingEnabled && info->allowColorTiling) { 219 struct drm_radeon_surface_alloc drmsurfalloc; 220 int rc; 221 222 drmsurfalloc.address = offset; 223 drmsurfalloc.size = size; 224 drmsurfalloc.flags = flags | 1; /* bogus pitch to please DRM */ 225 226 rc = drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_ALLOC, 227 &drmsurfalloc, sizeof(drmsurfalloc)); 228 if (rc < 0) { 229 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 230 "drm: could not allocate surface for access" 231 " swapper, err: %d!\n", rc); 232 return FALSE; 233 } 234 swapper_surfaces[index] = offset; 235 236 return TRUE; 237 } 238#endif 239 soff = (index + 1) * 0x10; 240 OUTREG(RADEON_SURFACE0_INFO + soff, flags); 241 OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset); 242 OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1); 243 swapper_surfaces[index] = offset; 244 return TRUE; 245} 246 247static void RADEONFinishAccess_BE(PixmapPtr pPix, int index) 248{ 249 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 250 unsigned char *RADEONMMIO = info->MMIO; 251 uint32_t offset = exaGetPixmapOffset(pPix); 252 int soff; 253 254 /* Front buffer is always set with proper swappers */ 255 if (offset == 0) 256 return; 257 258 if (swapper_surfaces[index] == 0) 259 return; 260#if defined(XF86DRI) 261 if (info->directRenderingEnabled && info->allowColorTiling) { 262 struct drm_radeon_surface_free drmsurffree; 263 264 drmsurffree.address = offset; 265 drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_FREE, 266 &drmsurffree, sizeof(drmsurffree)); 267 swapper_surfaces[index] = 0; 268 return; 269 } 270#endif 271 soff = (index + 1) * 0x10; 272 OUTREG(RADEON_SURFACE0_INFO + soff, 0); 273 OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0); 274 OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0); 275 swapper_surfaces[index] = 0; 276} 277 278#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ 279 280#ifdef XF86DRM_MODE 281Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index) 282{ 283 ScreenPtr pScreen = pPix->drawable.pScreen; 284 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 285 RADEONInfoPtr info = RADEONPTR(pScrn); 286 struct radeon_exa_pixmap_priv *driver_priv; 287 uint32_t possible_domains = ~0U; 288 uint32_t current_domain = 0; 289#ifdef EXA_MIXED_PIXMAPS 290 Bool can_fail = !(pPix->drawable.bitsPerPixel < 8) && 291 pPix != pScreen->GetScreenPixmap(pScreen) && 292 (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS); 293#else 294 Bool can_fail = FALSE; 295#endif 296 Bool flush = FALSE; 297 int ret; 298 299#if X_BYTE_ORDER == X_BIG_ENDIAN 300 /* May need to handle byte swapping in DownloadFrom/UploadToScreen */ 301 if (can_fail && pPix->drawable.bitsPerPixel > 8) 302 return FALSE; 303#endif 304 305 driver_priv = exaGetPixmapDriverPrivate(pPix); 306 if (!driver_priv) 307 return FALSE; 308 309 /* if we have more refs than just the BO then flush */ 310 if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { 311 flush = TRUE; 312 313 if (can_fail) { 314 possible_domains = radeon_bo_get_src_domain(driver_priv->bo); 315 if (possible_domains == RADEON_GEM_DOMAIN_VRAM) 316 return FALSE; /* use DownloadFromScreen */ 317 } 318 } 319 320 /* if the BO might end up in VRAM, prefer DownloadFromScreen */ 321 if (can_fail && (possible_domains & RADEON_GEM_DOMAIN_VRAM)) { 322 radeon_bo_is_busy(driver_priv->bo, ¤t_domain); 323 324 if (current_domain & possible_domains) { 325 if (current_domain == RADEON_GEM_DOMAIN_VRAM) 326 return FALSE; 327 } else if (possible_domains & RADEON_GEM_DOMAIN_VRAM) 328 return FALSE; 329 } 330 331 if (flush) 332 radeon_cs_flush_indirect(pScrn); 333 334 /* flush IB */ 335 ret = radeon_bo_map(driver_priv->bo, 1); 336 if (ret) { 337 FatalError("failed to map pixmap %d\n", ret); 338 return FALSE; 339 } 340 driver_priv->bo_mapped = TRUE; 341 342 pPix->devPrivate.ptr = driver_priv->bo->ptr; 343 344 return TRUE; 345} 346 347void RADEONFinishAccess_CS(PixmapPtr pPix, int index) 348{ 349 struct radeon_exa_pixmap_priv *driver_priv; 350 351 driver_priv = exaGetPixmapDriverPrivate(pPix); 352 if (!driver_priv || !driver_priv->bo_mapped) 353 return; 354 355 radeon_bo_unmap(driver_priv->bo); 356 driver_priv->bo_mapped = FALSE; 357 pPix->devPrivate.ptr = NULL; 358} 359 360 361void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align) 362{ 363 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 364 RADEONInfoPtr info = RADEONPTR(pScrn); 365 struct radeon_exa_pixmap_priv *new_priv; 366 367#ifdef EXA_MIXED_PIXMAPS 368 if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) { 369 if (size != 0 && !info->exa_force_create && 370 info->exa_pixmaps == FALSE) 371 return NULL; 372 } 373#endif 374 375 new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv)); 376 if (!new_priv) 377 return NULL; 378 379 if (size == 0) 380 return new_priv; 381 382 new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, align, 383 RADEON_GEM_DOMAIN_VRAM, 0); 384 if (!new_priv->bo) { 385 free(new_priv); 386 ErrorF("Failed to alloc memory\n"); 387 return NULL; 388 } 389 390 return new_priv; 391 392} 393 394static const unsigned MicroBlockTable[5][3][2] = { 395 /*linear tiled square-tiled */ 396 {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */ 397 {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */ 398 {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */ 399 {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */ 400 {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ 401}; 402 403/* Return true if macrotiling can be enabled */ 404static Bool RADEONMacroSwitch(int width, int height, int bpp, 405 uint32_t flags, Bool rv350_mode) 406{ 407 unsigned tilew, tileh, microtiled, logbpp; 408 409 logbpp = RADEONLog2(bpp / 8); 410 if (logbpp > 4) 411 return 0; 412 413 microtiled = !!(flags & RADEON_TILING_MICRO); 414 tilew = MicroBlockTable[logbpp][microtiled][0] * 8; 415 tileh = MicroBlockTable[logbpp][microtiled][1] * 8; 416 417 /* See TX_FILTER1_n.MACRO_SWITCH. */ 418 if (rv350_mode) { 419 return width >= tilew && height >= tileh; 420 } else { 421 return width > tilew && height > tileh; 422 } 423} 424 425void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, 426 int depth, int usage_hint, int bitsPerPixel, 427 int *new_pitch) 428{ 429 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 430 RADEONInfoPtr info = RADEONPTR(pScrn); 431 struct radeon_exa_pixmap_priv *new_priv; 432 int padded_width; 433 uint32_t size; 434 uint32_t tiling = 0; 435 int pixmap_align; 436 437#ifdef EXA_MIXED_PIXMAPS 438 if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) { 439 if (width != 0 && height != 0 && !info->exa_force_create && 440 info->exa_pixmaps == FALSE) 441 return NULL; 442 } 443#endif 444 445 if (usage_hint) { 446 if (info->allowColorTiling) { 447 if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO) 448 tiling |= RADEON_TILING_MACRO; 449 if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO) 450 tiling |= RADEON_TILING_MICRO; 451 } 452 } 453 454 /* Small pixmaps must not be macrotiled on R300, hw cannot sample them 455 * correctly because samplers automatically switch to macrolinear. */ 456 if (info->ChipFamily >= CHIP_FAMILY_R300 && 457 info->ChipFamily <= CHIP_FAMILY_RS740 && 458 (tiling & RADEON_TILING_MACRO) && 459 !RADEONMacroSwitch(width, height, bitsPerPixel, tiling, 460 info->ChipFamily >= CHIP_FAMILY_RV350)) { 461 tiling &= ~RADEON_TILING_MACRO; 462 } 463 464 if (info->ChipFamily >= CHIP_FAMILY_R600) { 465 int bpe = bitsPerPixel / 8; 466 467 if (tiling & RADEON_TILING_MACRO) { 468 height = RADEON_ALIGN(height, info->num_banks * 8); 469 pixmap_align = MAX(info->num_banks, 470 (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8 * bpe; 471 } else if (tiling & RADEON_TILING_MICRO) { 472 height = RADEON_ALIGN(height, 8); 473 pixmap_align = MAX(8, (info->group_bytes / (8 * bpe))) * bpe; 474 } else { 475 height = RADEON_ALIGN(height, 8); 476 pixmap_align = 256; /* 8 * bpe */ 477 } 478 } else { 479 if (tiling) { 480 height = RADEON_ALIGN(height, 16); 481 pixmap_align = 256; 482 } else 483 pixmap_align = 64; 484 } 485 486 padded_width = ((width * bitsPerPixel + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); 487 padded_width = RADEON_ALIGN(padded_width, pixmap_align); 488 size = height * padded_width; 489 490 new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv)); 491 if (!new_priv) 492 return NULL; 493 494 if (size == 0) 495 return new_priv; 496 497 *new_pitch = padded_width; 498 499 new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, 0, 500 RADEON_GEM_DOMAIN_VRAM, 0); 501 if (!new_priv->bo) { 502 free(new_priv); 503 ErrorF("Failed to alloc memory\n"); 504 return NULL; 505 } 506 507 if (tiling) 508 radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch); 509 510 return new_priv; 511} 512 513void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) 514{ 515 struct radeon_exa_pixmap_priv *driver_priv = driverPriv; 516 517 if (!driverPriv) 518 return; 519 520 if (driver_priv->bo) 521 radeon_bo_unref(driver_priv->bo); 522 free(driverPriv); 523} 524 525struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix) 526{ 527 struct radeon_exa_pixmap_priv *driver_priv; 528 driver_priv = exaGetPixmapDriverPrivate(pPix); 529 return driver_priv->bo; 530} 531 532void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) 533{ 534 struct radeon_exa_pixmap_priv *driver_priv; 535 536 driver_priv = exaGetPixmapDriverPrivate(pPix); 537 if (driver_priv) { 538 if (driver_priv->bo) 539 radeon_bo_unref(driver_priv->bo); 540 541 radeon_bo_ref(bo); 542 driver_priv->bo = bo; 543 } 544} 545 546Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix) 547{ 548 struct radeon_exa_pixmap_priv *driver_priv; 549 550 driver_priv = exaGetPixmapDriverPrivate(pPix); 551 552 if (!driver_priv) 553 return FALSE; 554 if (driver_priv->bo) 555 return TRUE; 556 return FALSE; 557} 558#endif 559 560#define ENTER_DRAW(x) TRACE 561#define LEAVE_DRAW(x) TRACE 562/***********************************************************************/ 563 564#define ACCEL_MMIO 565#define ACCEL_PREAMBLE() unsigned char *RADEONMMIO = info->MMIO 566#define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) 567#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) 568#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val)) 569#define OUT_RELOC(x, read, write) do {} while(0) 570#define FINISH_ACCEL() 571 572#ifdef RENDER 573#include "radeon_exa_render.c" 574#endif 575#include "radeon_exa_funcs.c" 576 577#undef ACCEL_MMIO 578#undef ACCEL_PREAMBLE 579#undef BEGIN_ACCEL 580#undef OUT_ACCEL_REG 581#undef OUT_ACCEL_REG_F 582#undef FINISH_ACCEL 583#undef OUT_RELOC 584 585#ifdef XF86DRI 586 587#define ACCEL_CP 588#define ACCEL_PREAMBLE() \ 589 RING_LOCALS; \ 590 RADEONCP_REFRESH(pScrn, info) 591#define BEGIN_ACCEL(n) BEGIN_RING(2*(n)) 592#define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) 593#define FINISH_ACCEL() ADVANCE_RING() 594#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write) 595 596#define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) 597 598#ifdef RENDER 599#include "radeon_exa_render.c" 600#endif 601#include "radeon_exa_funcs.c" 602 603#undef ACCEL_CP 604#undef ACCEL_PREAMBLE 605#undef BEGIN_ACCEL 606#undef OUT_ACCEL_REG 607#undef FINISH_ACCEL 608#undef OUT_RING_F 609 610#endif /* XF86DRI */ 611 612/* 613 * Once screen->off_screen_base is set, this function 614 * allocates the remaining memory appropriately 615 */ 616Bool RADEONSetupMemEXA (ScreenPtr pScreen) 617{ 618 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 619 RADEONInfoPtr info = RADEONPTR(pScrn); 620 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 621 int cpp = info->CurrentLayout.pixel_bytes; 622 int screen_size; 623 int byteStride = pScrn->displayWidth * cpp; 624 625 if (info->accel_state->exa != NULL) { 626 xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n"); 627 return FALSE; 628 } 629 info->accel_state->exa = exaDriverAlloc(); 630 if (info->accel_state->exa == NULL) 631 return FALSE; 632 633 /* Need to adjust screen size for 16 line tiles, and then make it align to. 634 * the buffer alignment requirement. 635 */ 636 if (info->allowColorTiling) 637 screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride; 638 else 639 screen_size = pScrn->virtualY * byteStride; 640 641 info->accel_state->exa->memoryBase = info->FB; 642 info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize; 643 info->accel_state->exa->offScreenBase = screen_size; 644 645 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n", 646 info->accel_state->exa->memorySize / 1024); 647 648 /* Reserve static area for hardware cursor */ 649 if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 650 int cursor_size = 64 * 4 * 64; 651 int align = IS_AVIVO_VARIANT ? 4096 : 256; 652 int c; 653 654 for (c = 0; c < xf86_config->num_crtc; c++) { 655 xf86CrtcPtr crtc = xf86_config->crtc[c]; 656 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 657 658 radeon_crtc->cursor_offset = 659 RADEON_ALIGN(info->accel_state->exa->offScreenBase, align); 660 info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size; 661 662 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 663 "Will use %d kb for hardware cursor %d at offset 0x%08x\n", 664 (cursor_size * xf86_config->num_crtc) / 1024, 665 c, 666 (unsigned int)radeon_crtc->cursor_offset); 667 } 668 } 669 670#if defined(XF86DRI) 671 if (info->directRenderingEnabled) { 672 int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size; 673 674 info->dri->frontOffset = 0; 675 info->dri->frontPitch = pScrn->displayWidth; 676 677 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 678 "Will use %d kb for front buffer at offset 0x%08x\n", 679 screen_size / 1024, info->dri->frontOffset); 680 RADEONDRIAllocatePCIGARTTable(pScreen); 681 682 if (info->cardType==CARD_PCIE) 683 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 684 "Will use %d kb for PCI GART at offset 0x%08x\n", 685 info->dri->pciGartSize / 1024, 686 (int)info->dri->pciGartOffset); 687 688 /* Reserve a static area for the back buffer the same size as the 689 * visible screen. XXX: This would be better initialized in ati_dri.c 690 * when GLX is set up, but the offscreen memory manager's allocations 691 * don't last through VT switches, while the kernel's understanding of 692 * offscreen locations does. 693 */ 694 info->dri->backPitch = pScrn->displayWidth; 695 next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE); 696 if (!info->dri->noBackBuffer && 697 next + screen_size <= info->accel_state->exa->memorySize) 698 { 699 info->dri->backOffset = next; 700 info->accel_state->exa->offScreenBase = next + screen_size; 701 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 702 "Will use %d kb for back buffer at offset 0x%08x\n", 703 screen_size / 1024, info->dri->backOffset); 704 } 705 706 /* Reserve the static depth buffer, and adjust pitch and height to 707 * handle tiling. 708 */ 709 info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); 710 depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp; 711 next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE); 712 if (next + depth_size <= info->accel_state->exa->memorySize) 713 { 714 info->dri->depthOffset = next; 715 info->accel_state->exa->offScreenBase = next + depth_size; 716 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 717 "Will use %d kb for depth buffer at offset 0x%08x\n", 718 depth_size / 1024, info->dri->depthOffset); 719 } 720 721 info->dri->textureSize *= (info->accel_state->exa->memorySize - 722 info->accel_state->exa->offScreenBase) / 100; 723 724 l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS); 725 if (l < RADEON_LOG_TEX_GRANULARITY) 726 l = RADEON_LOG_TEX_GRANULARITY; 727 info->dri->textureSize = (info->dri->textureSize >> l) << l; 728 if (info->dri->textureSize >= 512 * 1024) { 729 info->dri->textureOffset = info->accel_state->exa->offScreenBase; 730 info->accel_state->exa->offScreenBase += info->dri->textureSize; 731 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 732 "Will use %d kb for textures at offset 0x%08x\n", 733 info->dri->textureSize / 1024, info->dri->textureOffset); 734 } else { 735 /* Minimum texture size is for 2 256x256x32bpp textures */ 736 info->dri->textureSize = 0; 737 } 738 } else 739#endif /* XF86DRI */ 740 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 741 "Will use %d kb for front buffer at offset 0x%08x\n", 742 screen_size / 1024, 0); 743 744 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 745 "Will use %ld kb for X Server offscreen at offset 0x%08lx\n", 746 (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) / 747 1024, info->accel_state->exa->offScreenBase); 748 749 return TRUE; 750} 751 752#ifdef XF86DRI 753 754#ifndef ExaOffscreenMarkUsed 755extern void ExaOffscreenMarkUsed(PixmapPtr); 756#endif 757 758unsigned long long 759RADEONTexOffsetStart(PixmapPtr pPix) 760{ 761 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 762 unsigned long long offset; 763 764 if (exaGetPixmapDriverPrivate(pPix)) 765 return -1; 766 767 exaMoveInPixmap(pPix); 768 ExaOffscreenMarkUsed(pPix); 769 770 offset = exaGetPixmapOffset(pPix); 771 772 if (offset > info->FbMapSize) 773 return ~0ULL; 774 else 775 return info->fbLocation + offset; 776} 777#endif 778