radeon_exa.c revision 2f39173d
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 46#include "xf86.h" 47 48 49/***********************************************************************/ 50#define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn = xf86Screens[pScr->myNum]; \ 51 RADEONInfoPtr info = RADEONPTR(pScrn) 52 53#define RADEON_TRACE_FALL 0 54#define RADEON_TRACE_DRAW 0 55 56#if RADEON_TRACE_FALL 57#define RADEON_FALLBACK(x) \ 58do { \ 59 ErrorF("%s: ", __FUNCTION__); \ 60 ErrorF x; \ 61 return FALSE; \ 62} while (0) 63#else 64#define RADEON_FALLBACK(x) return FALSE 65#endif 66 67#if RADEON_TRACE_DRAW 68#define TRACE do { ErrorF("TRACE: %s\n", __FUNCTION__); } while(0) 69#else 70#define TRACE 71#endif 72 73static struct { 74 int rop; 75 int pattern; 76} RADEON_ROP[] = { 77 { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear */ 78 { RADEON_ROP3_DSa, RADEON_ROP3_DPa }, /* Gxand */ 79 { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse */ 80 { RADEON_ROP3_S, RADEON_ROP3_P }, /* GXcopy */ 81 { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted */ 82 { RADEON_ROP3_D, RADEON_ROP3_D }, /* GXnoop */ 83 { RADEON_ROP3_DSx, RADEON_ROP3_DPx }, /* GXxor */ 84 { RADEON_ROP3_DSo, RADEON_ROP3_DPo }, /* GXor */ 85 { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor */ 86 { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv */ 87 { RADEON_ROP3_Dn, RADEON_ROP3_Dn }, /* GXinvert */ 88 { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse */ 89 { RADEON_ROP3_Sn, RADEON_ROP3_Pn }, /* GXcopyInverted */ 90 { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted */ 91 { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand */ 92 { RADEON_ROP3_ONE, RADEON_ROP3_ONE } /* GXset */ 93}; 94 95/* Compute log base 2 of val. */ 96static __inline__ int 97RADEONLog2(int val) 98{ 99 int bits; 100#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__) 101 __asm volatile("bsrl %1, %0" 102 : "=r" (bits) 103 : "c" (val) 104 ); 105 return bits; 106#else 107 for (bits = 0; val != 0; val >>= 1, ++bits) 108 ; 109 return bits - 1; 110#endif 111} 112 113static __inline__ uint32_t F_TO_DW(float val) 114{ 115 union { 116 float f; 117 uint32_t l; 118 } tmp; 119 tmp.f = val; 120 return tmp.l; 121} 122 123 124#ifdef XF86DRM_MODE 125 126static inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int read_domains, int write_domain) 127{ 128 struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix); 129 130 radeon_cs_space_add_persistent_bo(cs, driver_priv->bo, read_domains, write_domain); 131} 132 133#endif /* XF86DRM_MODE */ 134 135 136/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we 137 * require src and dest datatypes to be equal. 138 */ 139Bool RADEONGetDatatypeBpp(int bpp, uint32_t *type) 140{ 141 switch (bpp) { 142 case 8: 143 *type = ATI_DATATYPE_CI8; 144 return TRUE; 145 case 16: 146 *type = ATI_DATATYPE_RGB565; 147 return TRUE; 148 case 24: 149 *type = ATI_DATATYPE_CI8; 150 return TRUE; 151 case 32: 152 *type = ATI_DATATYPE_ARGB8888; 153 return TRUE; 154 default: 155 RADEON_FALLBACK(("Unsupported bpp: %d\n", bpp)); 156 return FALSE; 157 } 158} 159 160static Bool RADEONPixmapIsColortiled(PixmapPtr pPix) 161{ 162 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 163 164 /* This doesn't account for the back buffer, which we may want to wrap in 165 * a pixmap at some point for the purposes of DRI buffer moves. 166 */ 167 if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0) 168 return TRUE; 169 else 170 return FALSE; 171} 172 173static Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset, 174 unsigned int offset, unsigned int pitch) 175{ 176 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 177 178 if (pitch > 16320 || pitch % info->accel_state->exa->pixmapPitchAlign != 0) 179 RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch)); 180 181 if (offset % info->accel_state->exa->pixmapOffsetAlign != 0) 182 RADEON_FALLBACK(("Bad offset 0x%08x\n", offset)); 183 184 pitch = pitch >> 6; 185 *pitch_offset = (pitch << 22) | (offset >> 10); 186 187 /* If it's the front buffer, we've got to note that it's tiled? */ 188 if (RADEONPixmapIsColortiled(pPix)) 189 *pitch_offset |= RADEON_DST_TILE_MACRO; 190 return TRUE; 191} 192 193Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) 194{ 195 uint32_t pitch, offset; 196 int bpp; 197 198 bpp = pPix->drawable.bitsPerPixel; 199 if (bpp == 24) 200 bpp = 8; 201 202 offset = radeonGetPixmapOffset(pPix); 203 pitch = exaGetPixmapPitch(pPix); 204 205 return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); 206} 207 208#if X_BYTE_ORDER == X_BIG_ENDIAN 209 210static unsigned long swapper_surfaces[6]; 211 212static Bool RADEONPrepareAccess_BE(PixmapPtr pPix, int index) 213{ 214 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 215 unsigned char *RADEONMMIO = info->MMIO; 216 uint32_t offset = exaGetPixmapOffset(pPix); 217 int bpp, soff; 218 uint32_t size, flags; 219 220 /* Front buffer is always set with proper swappers */ 221 if (offset == 0) 222 return TRUE; 223 224 /* If same bpp as front buffer, just do nothing as the main 225 * swappers will apply 226 */ 227 bpp = pPix->drawable.bitsPerPixel; 228 if (bpp == pScrn->bitsPerPixel) 229 return TRUE; 230 231 /* We need to setup a separate swapper, let's request a 232 * surface. We need to align the size first 233 */ 234 size = exaGetPixmapSize(pPix); 235 size = RADEON_ALIGN(size, RADEON_GPU_PAGE_SIZE); 236 237 /* Set surface to tiling disabled with appropriate swapper */ 238 switch (bpp) { 239 case 16: 240 flags = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP; 241 break; 242 case 32: 243 flags = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; 244 break; 245 default: 246 flags = 0; 247 } 248#if defined(XF86DRI) 249 if (info->directRenderingEnabled && info->allowColorTiling) { 250 struct drm_radeon_surface_alloc drmsurfalloc; 251 int rc; 252 253 drmsurfalloc.address = offset; 254 drmsurfalloc.size = size; 255 drmsurfalloc.flags = flags | 1; /* bogus pitch to please DRM */ 256 257 rc = drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_ALLOC, 258 &drmsurfalloc, sizeof(drmsurfalloc)); 259 if (rc < 0) { 260 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 261 "drm: could not allocate surface for access" 262 " swapper, err: %d!\n", rc); 263 return FALSE; 264 } 265 swapper_surfaces[index] = offset; 266 267 return TRUE; 268 } 269#endif 270 soff = (index + 1) * 0x10; 271 OUTREG(RADEON_SURFACE0_INFO + soff, flags); 272 OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset); 273 OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1); 274 swapper_surfaces[index] = offset; 275 return TRUE; 276} 277 278static void RADEONFinishAccess_BE(PixmapPtr pPix, int index) 279{ 280 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 281 unsigned char *RADEONMMIO = info->MMIO; 282 uint32_t offset = exaGetPixmapOffset(pPix); 283 int soff; 284 285 /* Front buffer is always set with proper swappers */ 286 if (offset == 0) 287 return; 288 289 if (swapper_surfaces[index] == 0) 290 return; 291#if defined(XF86DRI) 292 if (info->directRenderingEnabled && info->allowColorTiling) { 293 struct drm_radeon_surface_free drmsurffree; 294 295 drmsurffree.address = offset; 296 drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_FREE, 297 &drmsurffree, sizeof(drmsurffree)); 298 swapper_surfaces[index] = 0; 299 return; 300 } 301#endif 302 soff = (index + 1) * 0x10; 303 OUTREG(RADEON_SURFACE0_INFO + soff, 0); 304 OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0); 305 OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0); 306 swapper_surfaces[index] = 0; 307} 308 309#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ 310 311#ifdef XF86DRM_MODE 312Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index) 313{ 314 ScreenPtr pScreen = pPix->drawable.pScreen; 315 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 316 RADEONInfoPtr info = RADEONPTR(pScrn); 317 struct radeon_exa_pixmap_priv *driver_priv; 318 int ret; 319 320#if X_BYTE_ORDER == X_BIG_ENDIAN 321 /* May need to handle byte swapping in DownloadFrom/UploadToScreen */ 322 if (pPix->drawable.bitsPerPixel > 8 && 323 pPix != pScreen->GetScreenPixmap(pScreen)) 324 return FALSE; 325#endif 326 327 driver_priv = exaGetPixmapDriverPrivate(pPix); 328 if (!driver_priv) 329 return FALSE; 330 331 /* if we have more refs than just the BO then flush */ 332 if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) 333 radeon_cs_flush_indirect(pScrn); 334 335 /* flush IB */ 336 ret = radeon_bo_map(driver_priv->bo, 1); 337 if (ret) { 338 FatalError("failed to map pixmap %d\n", ret); 339 return FALSE; 340 } 341 driver_priv->bo_mapped = TRUE; 342 343 pPix->devPrivate.ptr = driver_priv->bo->ptr; 344 345 return TRUE; 346} 347 348void RADEONFinishAccess_CS(PixmapPtr pPix, int index) 349{ 350 struct radeon_exa_pixmap_priv *driver_priv; 351 352 driver_priv = exaGetPixmapDriverPrivate(pPix); 353 if (!driver_priv || !driver_priv->bo_mapped) 354 return; 355 356 radeon_bo_unmap(driver_priv->bo); 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 (tiling) { 465 height = RADEON_ALIGN(height, 16); 466 pixmap_align = 256; 467 } else 468 pixmap_align = 64; 469 470 padded_width = ((width * bitsPerPixel + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); 471 padded_width = RADEON_ALIGN(padded_width, pixmap_align); 472 size = height * padded_width; 473 474 new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv)); 475 if (!new_priv) 476 return NULL; 477 478 if (size == 0) 479 return new_priv; 480 481 *new_pitch = padded_width; 482 483 new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, 0, 484 RADEON_GEM_DOMAIN_VRAM, 0); 485 if (!new_priv->bo) { 486 free(new_priv); 487 ErrorF("Failed to alloc memory\n"); 488 return NULL; 489 } 490 491 if (tiling) 492 radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch); 493 494 return new_priv; 495} 496 497void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) 498{ 499 struct radeon_exa_pixmap_priv *driver_priv = driverPriv; 500 501 if (!driverPriv) 502 return; 503 504 if (driver_priv->bo) 505 radeon_bo_unref(driver_priv->bo); 506 free(driverPriv); 507} 508 509struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix) 510{ 511 struct radeon_exa_pixmap_priv *driver_priv; 512 driver_priv = exaGetPixmapDriverPrivate(pPix); 513 return driver_priv->bo; 514} 515 516void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) 517{ 518 struct radeon_exa_pixmap_priv *driver_priv; 519 520 driver_priv = exaGetPixmapDriverPrivate(pPix); 521 if (driver_priv) { 522 if (driver_priv->bo) 523 radeon_bo_unref(driver_priv->bo); 524 525 radeon_bo_ref(bo); 526 driver_priv->bo = bo; 527 } 528} 529 530Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix) 531{ 532 struct radeon_exa_pixmap_priv *driver_priv; 533 534 driver_priv = exaGetPixmapDriverPrivate(pPix); 535 536 if (!driver_priv) 537 return FALSE; 538 if (driver_priv->bo) 539 return TRUE; 540 return FALSE; 541} 542#endif 543 544#define ENTER_DRAW(x) TRACE 545#define LEAVE_DRAW(x) TRACE 546/***********************************************************************/ 547 548#define ACCEL_MMIO 549#define ACCEL_PREAMBLE() unsigned char *RADEONMMIO = info->MMIO 550#define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) 551#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) 552#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val)) 553#define OUT_RELOC(x, read, write) do {} while(0) 554#define FINISH_ACCEL() 555 556#ifdef RENDER 557#include "radeon_exa_render.c" 558#endif 559#include "radeon_exa_funcs.c" 560 561#undef ACCEL_MMIO 562#undef ACCEL_PREAMBLE 563#undef BEGIN_ACCEL 564#undef OUT_ACCEL_REG 565#undef OUT_ACCEL_REG_F 566#undef FINISH_ACCEL 567#undef OUT_RELOC 568 569#ifdef XF86DRI 570 571#define ACCEL_CP 572#define ACCEL_PREAMBLE() \ 573 RING_LOCALS; \ 574 RADEONCP_REFRESH(pScrn, info) 575#define BEGIN_ACCEL(n) BEGIN_RING(2*(n)) 576#define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) 577#define FINISH_ACCEL() ADVANCE_RING() 578#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write) 579 580#define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) 581 582#ifdef RENDER 583#include "radeon_exa_render.c" 584#endif 585#include "radeon_exa_funcs.c" 586 587#undef ACCEL_CP 588#undef ACCEL_PREAMBLE 589#undef BEGIN_ACCEL 590#undef OUT_ACCEL_REG 591#undef FINISH_ACCEL 592#undef OUT_RING_F 593 594#endif /* XF86DRI */ 595 596/* 597 * Once screen->off_screen_base is set, this function 598 * allocates the remaining memory appropriately 599 */ 600Bool RADEONSetupMemEXA (ScreenPtr pScreen) 601{ 602 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 603 RADEONInfoPtr info = RADEONPTR(pScrn); 604 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 605 int cpp = info->CurrentLayout.pixel_bytes; 606 int screen_size; 607 int byteStride = pScrn->displayWidth * cpp; 608 609 if (info->accel_state->exa != NULL) { 610 xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n"); 611 return FALSE; 612 } 613 info->accel_state->exa = exaDriverAlloc(); 614 if (info->accel_state->exa == NULL) 615 return FALSE; 616 617 /* Need to adjust screen size for 16 line tiles, and then make it align to. 618 * the buffer alignment requirement. 619 */ 620 if (info->allowColorTiling) 621 screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride; 622 else 623 screen_size = pScrn->virtualY * byteStride; 624 625 info->accel_state->exa->memoryBase = info->FB; 626 info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize; 627 info->accel_state->exa->offScreenBase = screen_size; 628 629 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n", 630 info->accel_state->exa->memorySize / 1024); 631 632 /* Reserve static area for hardware cursor */ 633 if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 634 int cursor_size = 64 * 4 * 64; 635 int align = IS_AVIVO_VARIANT ? 4096 : 256; 636 int c; 637 638 for (c = 0; c < xf86_config->num_crtc; c++) { 639 xf86CrtcPtr crtc = xf86_config->crtc[c]; 640 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 641 642 radeon_crtc->cursor_offset = 643 RADEON_ALIGN(info->accel_state->exa->offScreenBase, align); 644 info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size; 645 646 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 647 "Will use %d kb for hardware cursor %d at offset 0x%08x\n", 648 (cursor_size * xf86_config->num_crtc) / 1024, 649 c, 650 (unsigned int)radeon_crtc->cursor_offset); 651 } 652 } 653 654#if defined(XF86DRI) 655 if (info->directRenderingEnabled) { 656 int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size; 657 658 info->dri->frontOffset = 0; 659 info->dri->frontPitch = pScrn->displayWidth; 660 661 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 662 "Will use %d kb for front buffer at offset 0x%08x\n", 663 screen_size / 1024, info->dri->frontOffset); 664 RADEONDRIAllocatePCIGARTTable(pScreen); 665 666 if (info->cardType==CARD_PCIE) 667 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 668 "Will use %d kb for PCI GART at offset 0x%08x\n", 669 info->dri->pciGartSize / 1024, 670 (int)info->dri->pciGartOffset); 671 672 /* Reserve a static area for the back buffer the same size as the 673 * visible screen. XXX: This would be better initialized in ati_dri.c 674 * when GLX is set up, but the offscreen memory manager's allocations 675 * don't last through VT switches, while the kernel's understanding of 676 * offscreen locations does. 677 */ 678 info->dri->backPitch = pScrn->displayWidth; 679 next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE); 680 if (!info->dri->noBackBuffer && 681 next + screen_size <= info->accel_state->exa->memorySize) 682 { 683 info->dri->backOffset = next; 684 info->accel_state->exa->offScreenBase = next + screen_size; 685 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 686 "Will use %d kb for back buffer at offset 0x%08x\n", 687 screen_size / 1024, info->dri->backOffset); 688 } 689 690 /* Reserve the static depth buffer, and adjust pitch and height to 691 * handle tiling. 692 */ 693 info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); 694 depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp; 695 next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE); 696 if (next + depth_size <= info->accel_state->exa->memorySize) 697 { 698 info->dri->depthOffset = next; 699 info->accel_state->exa->offScreenBase = next + depth_size; 700 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 701 "Will use %d kb for depth buffer at offset 0x%08x\n", 702 depth_size / 1024, info->dri->depthOffset); 703 } 704 705 info->dri->textureSize *= (info->accel_state->exa->memorySize - 706 info->accel_state->exa->offScreenBase) / 100; 707 708 l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS); 709 if (l < RADEON_LOG_TEX_GRANULARITY) 710 l = RADEON_LOG_TEX_GRANULARITY; 711 info->dri->textureSize = (info->dri->textureSize >> l) << l; 712 if (info->dri->textureSize >= 512 * 1024) { 713 info->dri->textureOffset = info->accel_state->exa->offScreenBase; 714 info->accel_state->exa->offScreenBase += info->dri->textureSize; 715 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 716 "Will use %d kb for textures at offset 0x%08x\n", 717 info->dri->textureSize / 1024, info->dri->textureOffset); 718 } else { 719 /* Minimum texture size is for 2 256x256x32bpp textures */ 720 info->dri->textureSize = 0; 721 } 722 } else 723#endif /* XF86DRI */ 724 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 725 "Will use %d kb for front buffer at offset 0x%08x\n", 726 screen_size / 1024, 0); 727 728 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 729 "Will use %ld kb for X Server offscreen at offset 0x%08lx\n", 730 (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) / 731 1024, info->accel_state->exa->offScreenBase); 732 733 return TRUE; 734} 735 736#ifdef XF86DRI 737 738#ifndef ExaOffscreenMarkUsed 739extern void ExaOffscreenMarkUsed(PixmapPtr); 740#endif 741 742unsigned long long 743RADEONTexOffsetStart(PixmapPtr pPix) 744{ 745 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 746 unsigned long long offset; 747 748 if (exaGetPixmapDriverPrivate(pPix)) 749 return -1; 750 751 exaMoveInPixmap(pPix); 752 ExaOffscreenMarkUsed(pPix); 753 754 offset = exaGetPixmapOffset(pPix); 755 756 if (offset > info->FbMapSize) 757 return ~0ULL; 758 else 759 return info->fbLocation + offset; 760} 761#endif 762