1209ff23fSmrg/* 2209ff23fSmrg * Copyright 2005 Eric Anholt 3209ff23fSmrg * Copyright 2005 Benjamin Herrenschmidt 4209ff23fSmrg * All Rights Reserved. 5209ff23fSmrg * 6209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 7209ff23fSmrg * copy of this software and associated documentation files (the "Software"), 8209ff23fSmrg * to deal in the Software without restriction, including without limitation 9209ff23fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10209ff23fSmrg * and/or sell copies of the Software, and to permit persons to whom the 11209ff23fSmrg * Software is furnished to do so, subject to the following conditions: 12209ff23fSmrg * 13209ff23fSmrg * The above copyright notice and this permission notice (including the next 14209ff23fSmrg * paragraph) shall be included in all copies or substantial portions of the 15209ff23fSmrg * Software. 16209ff23fSmrg * 17209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18209ff23fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19209ff23fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20209ff23fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21209ff23fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22209ff23fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23209ff23fSmrg * SOFTWARE. 24209ff23fSmrg * 25209ff23fSmrg * Authors: 26209ff23fSmrg * Eric Anholt <anholt@FreeBSD.org> 27209ff23fSmrg * Zack Rusin <zrusin@trolltech.com> 28209ff23fSmrg * Benjamin Herrenschmidt <benh@kernel.crashing.org> 29209ff23fSmrg * 30209ff23fSmrg */ 31209ff23fSmrg 32209ff23fSmrg#ifdef HAVE_CONFIG_H 33209ff23fSmrg#include "config.h" 34209ff23fSmrg#endif 35209ff23fSmrg 36209ff23fSmrg#include "radeon.h" 37209ff23fSmrg#include "radeon_reg.h" 38b7e1c893Smrg#include "r600_reg.h" 39209ff23fSmrg#ifdef XF86DRI 40b7e1c893Smrg#include "radeon_drm.h" 41209ff23fSmrg#endif 42209ff23fSmrg#include "radeon_macros.h" 43209ff23fSmrg#include "radeon_probe.h" 44209ff23fSmrg#include "radeon_version.h" 450974d292Smrg#include "radeon_exa_shared.h" 46209ff23fSmrg 47209ff23fSmrg#include "xf86.h" 48209ff23fSmrg 49209ff23fSmrg 50209ff23fSmrg/***********************************************************************/ 5168105dcbSveego#define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn = xf86ScreenToScrn(pScr); \ 52209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn) 53209ff23fSmrg 54209ff23fSmrgstatic struct { 55209ff23fSmrg int rop; 56209ff23fSmrg int pattern; 57209ff23fSmrg} RADEON_ROP[] = { 58209ff23fSmrg { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear */ 59209ff23fSmrg { RADEON_ROP3_DSa, RADEON_ROP3_DPa }, /* Gxand */ 60209ff23fSmrg { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse */ 61209ff23fSmrg { RADEON_ROP3_S, RADEON_ROP3_P }, /* GXcopy */ 62209ff23fSmrg { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted */ 63209ff23fSmrg { RADEON_ROP3_D, RADEON_ROP3_D }, /* GXnoop */ 64209ff23fSmrg { RADEON_ROP3_DSx, RADEON_ROP3_DPx }, /* GXxor */ 65209ff23fSmrg { RADEON_ROP3_DSo, RADEON_ROP3_DPo }, /* GXor */ 66209ff23fSmrg { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor */ 67209ff23fSmrg { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv */ 68209ff23fSmrg { RADEON_ROP3_Dn, RADEON_ROP3_Dn }, /* GXinvert */ 69209ff23fSmrg { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse */ 70209ff23fSmrg { RADEON_ROP3_Sn, RADEON_ROP3_Pn }, /* GXcopyInverted */ 71209ff23fSmrg { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted */ 72209ff23fSmrg { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand */ 73209ff23fSmrg { RADEON_ROP3_ONE, RADEON_ROP3_ONE } /* GXset */ 74209ff23fSmrg}; 75209ff23fSmrg 76209ff23fSmrg/* Compute log base 2 of val. */ 77209ff23fSmrgstatic __inline__ int 78209ff23fSmrgRADEONLog2(int val) 79209ff23fSmrg{ 80209ff23fSmrg int bits; 81209ff23fSmrg#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__) 82209ff23fSmrg __asm volatile("bsrl %1, %0" 83209ff23fSmrg : "=r" (bits) 84209ff23fSmrg : "c" (val) 85209ff23fSmrg ); 86209ff23fSmrg return bits; 87209ff23fSmrg#else 88209ff23fSmrg for (bits = 0; val != 0; val >>= 1, ++bits) 89209ff23fSmrg ; 90209ff23fSmrg return bits - 1; 91209ff23fSmrg#endif 92209ff23fSmrg} 93209ff23fSmrg 94209ff23fSmrgstatic __inline__ uint32_t F_TO_DW(float val) 95209ff23fSmrg{ 96209ff23fSmrg union { 97209ff23fSmrg float f; 98209ff23fSmrg uint32_t l; 99209ff23fSmrg } tmp; 100209ff23fSmrg tmp.f = val; 101209ff23fSmrg return tmp.l; 102209ff23fSmrg} 103209ff23fSmrg 104ad43ddacSmrg 105209ff23fSmrg/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we 106209ff23fSmrg * require src and dest datatypes to be equal. 107209ff23fSmrg */ 108209ff23fSmrgBool RADEONGetDatatypeBpp(int bpp, uint32_t *type) 109209ff23fSmrg{ 110209ff23fSmrg switch (bpp) { 111209ff23fSmrg case 8: 112209ff23fSmrg *type = ATI_DATATYPE_CI8; 113209ff23fSmrg return TRUE; 114209ff23fSmrg case 16: 115209ff23fSmrg *type = ATI_DATATYPE_RGB565; 116209ff23fSmrg return TRUE; 117209ff23fSmrg case 24: 118209ff23fSmrg *type = ATI_DATATYPE_CI8; 119209ff23fSmrg return TRUE; 120209ff23fSmrg case 32: 121209ff23fSmrg *type = ATI_DATATYPE_ARGB8888; 122209ff23fSmrg return TRUE; 123209ff23fSmrg default: 124209ff23fSmrg RADEON_FALLBACK(("Unsupported bpp: %d\n", bpp)); 125209ff23fSmrg return FALSE; 126209ff23fSmrg } 127209ff23fSmrg} 128209ff23fSmrg 129209ff23fSmrgstatic Bool RADEONPixmapIsColortiled(PixmapPtr pPix) 130209ff23fSmrg{ 131209ff23fSmrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 132209ff23fSmrg 133c4ae5be6Smrg#ifdef XF86DRM_MODE 134c4ae5be6Smrg if (info->cs) { 135c4ae5be6Smrg /* Taken care of by the kernel relocation handling */ 136c4ae5be6Smrg return FALSE; 137c4ae5be6Smrg } 138c4ae5be6Smrg#endif 139c4ae5be6Smrg 140209ff23fSmrg /* This doesn't account for the back buffer, which we may want to wrap in 141209ff23fSmrg * a pixmap at some point for the purposes of DRI buffer moves. 142209ff23fSmrg */ 143209ff23fSmrg if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0) 144209ff23fSmrg return TRUE; 145209ff23fSmrg else 146209ff23fSmrg return FALSE; 147209ff23fSmrg} 148209ff23fSmrg 149209ff23fSmrgstatic Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset, 150209ff23fSmrg unsigned int offset, unsigned int pitch) 151209ff23fSmrg{ 152209ff23fSmrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 153209ff23fSmrg 154b7e1c893Smrg if (pitch > 16320 || pitch % info->accel_state->exa->pixmapPitchAlign != 0) 155209ff23fSmrg RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch)); 156209ff23fSmrg 157b7e1c893Smrg if (offset % info->accel_state->exa->pixmapOffsetAlign != 0) 158209ff23fSmrg RADEON_FALLBACK(("Bad offset 0x%08x\n", offset)); 159209ff23fSmrg 160209ff23fSmrg pitch = pitch >> 6; 161209ff23fSmrg *pitch_offset = (pitch << 22) | (offset >> 10); 162209ff23fSmrg 163209ff23fSmrg /* If it's the front buffer, we've got to note that it's tiled? */ 164209ff23fSmrg if (RADEONPixmapIsColortiled(pPix)) 165209ff23fSmrg *pitch_offset |= RADEON_DST_TILE_MACRO; 166209ff23fSmrg return TRUE; 167209ff23fSmrg} 168209ff23fSmrg 169209ff23fSmrgBool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) 170209ff23fSmrg{ 171209ff23fSmrg uint32_t pitch, offset; 172209ff23fSmrg int bpp; 173209ff23fSmrg 174209ff23fSmrg bpp = pPix->drawable.bitsPerPixel; 175209ff23fSmrg if (bpp == 24) 176209ff23fSmrg bpp = 8; 177209ff23fSmrg 178ad43ddacSmrg offset = radeonGetPixmapOffset(pPix); 179209ff23fSmrg pitch = exaGetPixmapPitch(pPix); 180209ff23fSmrg 181209ff23fSmrg return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); 182209ff23fSmrg} 183209ff23fSmrg 184921a55d8Smrg/** 185921a55d8Smrg * Returns whether the provided transform is affine. 186921a55d8Smrg * 187921a55d8Smrg * transform may be null. 188921a55d8Smrg */ 189b13dfe66SmrgBool radeon_transform_is_affine_or_scaled(PictTransformPtr t) 190921a55d8Smrg{ 191921a55d8Smrg if (t == NULL) 192921a55d8Smrg return TRUE; 193b13dfe66Smrg /* the shaders don't handle scaling either */ 194b13dfe66Smrg return t->matrix[2][0] == 0 && t->matrix[2][1] == 0 && t->matrix[2][2] == IntToxFixed(1); 195921a55d8Smrg} 196921a55d8Smrg 197209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 198209ff23fSmrg 199b7e1c893Smrgstatic unsigned long swapper_surfaces[6]; 200209ff23fSmrg 201ad43ddacSmrgstatic Bool RADEONPrepareAccess_BE(PixmapPtr pPix, int index) 202209ff23fSmrg{ 203209ff23fSmrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 204209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 205209ff23fSmrg uint32_t offset = exaGetPixmapOffset(pPix); 206209ff23fSmrg int bpp, soff; 207209ff23fSmrg uint32_t size, flags; 208209ff23fSmrg 209209ff23fSmrg /* Front buffer is always set with proper swappers */ 210209ff23fSmrg if (offset == 0) 211209ff23fSmrg return TRUE; 212209ff23fSmrg 213209ff23fSmrg /* If same bpp as front buffer, just do nothing as the main 214209ff23fSmrg * swappers will apply 215209ff23fSmrg */ 216209ff23fSmrg bpp = pPix->drawable.bitsPerPixel; 217209ff23fSmrg if (bpp == pScrn->bitsPerPixel) 218209ff23fSmrg return TRUE; 219209ff23fSmrg 220209ff23fSmrg /* We need to setup a separate swapper, let's request a 221209ff23fSmrg * surface. We need to align the size first 222209ff23fSmrg */ 223209ff23fSmrg size = exaGetPixmapSize(pPix); 224ad43ddacSmrg size = RADEON_ALIGN(size, RADEON_GPU_PAGE_SIZE); 225209ff23fSmrg 226209ff23fSmrg /* Set surface to tiling disabled with appropriate swapper */ 227209ff23fSmrg switch (bpp) { 228209ff23fSmrg case 16: 229209ff23fSmrg flags = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP; 230209ff23fSmrg break; 231209ff23fSmrg case 32: 232209ff23fSmrg flags = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; 233209ff23fSmrg break; 234209ff23fSmrg default: 235209ff23fSmrg flags = 0; 236209ff23fSmrg } 237209ff23fSmrg#if defined(XF86DRI) 238209ff23fSmrg if (info->directRenderingEnabled && info->allowColorTiling) { 239b7e1c893Smrg struct drm_radeon_surface_alloc drmsurfalloc; 240209ff23fSmrg int rc; 241209ff23fSmrg 242209ff23fSmrg drmsurfalloc.address = offset; 243209ff23fSmrg drmsurfalloc.size = size; 244209ff23fSmrg drmsurfalloc.flags = flags | 1; /* bogus pitch to please DRM */ 245209ff23fSmrg 246b7e1c893Smrg rc = drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_ALLOC, 247209ff23fSmrg &drmsurfalloc, sizeof(drmsurfalloc)); 248209ff23fSmrg if (rc < 0) { 249209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 250209ff23fSmrg "drm: could not allocate surface for access" 251209ff23fSmrg " swapper, err: %d!\n", rc); 252209ff23fSmrg return FALSE; 253209ff23fSmrg } 254209ff23fSmrg swapper_surfaces[index] = offset; 255209ff23fSmrg 256209ff23fSmrg return TRUE; 257209ff23fSmrg } 258209ff23fSmrg#endif 259209ff23fSmrg soff = (index + 1) * 0x10; 260209ff23fSmrg OUTREG(RADEON_SURFACE0_INFO + soff, flags); 261209ff23fSmrg OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset); 262209ff23fSmrg OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1); 263209ff23fSmrg swapper_surfaces[index] = offset; 264209ff23fSmrg return TRUE; 265209ff23fSmrg} 266209ff23fSmrg 267ad43ddacSmrgstatic void RADEONFinishAccess_BE(PixmapPtr pPix, int index) 268209ff23fSmrg{ 269209ff23fSmrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 270209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 271209ff23fSmrg uint32_t offset = exaGetPixmapOffset(pPix); 272209ff23fSmrg int soff; 273209ff23fSmrg 274209ff23fSmrg /* Front buffer is always set with proper swappers */ 275209ff23fSmrg if (offset == 0) 276209ff23fSmrg return; 277209ff23fSmrg 278209ff23fSmrg if (swapper_surfaces[index] == 0) 279209ff23fSmrg return; 280209ff23fSmrg#if defined(XF86DRI) 281209ff23fSmrg if (info->directRenderingEnabled && info->allowColorTiling) { 282b7e1c893Smrg struct drm_radeon_surface_free drmsurffree; 283209ff23fSmrg 284209ff23fSmrg drmsurffree.address = offset; 285b7e1c893Smrg drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_FREE, 286209ff23fSmrg &drmsurffree, sizeof(drmsurffree)); 287209ff23fSmrg swapper_surfaces[index] = 0; 288209ff23fSmrg return; 289209ff23fSmrg } 290209ff23fSmrg#endif 291209ff23fSmrg soff = (index + 1) * 0x10; 292209ff23fSmrg OUTREG(RADEON_SURFACE0_INFO + soff, 0); 293209ff23fSmrg OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0); 294209ff23fSmrg OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0); 295209ff23fSmrg swapper_surfaces[index] = 0; 296209ff23fSmrg} 297209ff23fSmrg 298209ff23fSmrg#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ 299209ff23fSmrg 300ad43ddacSmrg#ifdef XF86DRM_MODE 301ad43ddacSmrgBool RADEONPrepareAccess_CS(PixmapPtr pPix, int index) 302ad43ddacSmrg{ 303ad43ddacSmrg ScreenPtr pScreen = pPix->drawable.pScreen; 30468105dcbSveego ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 305ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 306ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv; 3070974d292Smrg uint32_t possible_domains = ~0U; 3080974d292Smrg uint32_t current_domain = 0; 3090974d292Smrg#ifdef EXA_MIXED_PIXMAPS 3100974d292Smrg Bool can_fail = !(pPix->drawable.bitsPerPixel < 8) && 3110974d292Smrg pPix != pScreen->GetScreenPixmap(pScreen) && 3120974d292Smrg (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS); 3130974d292Smrg#else 3140974d292Smrg Bool can_fail = FALSE; 3150974d292Smrg#endif 3160974d292Smrg Bool flush = FALSE; 317ad43ddacSmrg int ret; 318ad43ddacSmrg 319ad43ddacSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 320ad43ddacSmrg /* May need to handle byte swapping in DownloadFrom/UploadToScreen */ 3210974d292Smrg if (can_fail && pPix->drawable.bitsPerPixel > 8) 322ad43ddacSmrg return FALSE; 323ad43ddacSmrg#endif 324ad43ddacSmrg 325ad43ddacSmrg driver_priv = exaGetPixmapDriverPrivate(pPix); 326ad43ddacSmrg if (!driver_priv) 327ad43ddacSmrg return FALSE; 328ad43ddacSmrg 329921a55d8Smrg /* untile in DFS/UTS */ 330c4ae5be6Smrg if (driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO)) 331921a55d8Smrg return FALSE; 332921a55d8Smrg 333ad43ddacSmrg /* if we have more refs than just the BO then flush */ 3340974d292Smrg if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { 3350974d292Smrg flush = TRUE; 3360974d292Smrg 3370974d292Smrg if (can_fail) { 3380974d292Smrg possible_domains = radeon_bo_get_src_domain(driver_priv->bo); 3390974d292Smrg if (possible_domains == RADEON_GEM_DOMAIN_VRAM) 3400974d292Smrg return FALSE; /* use DownloadFromScreen */ 3410974d292Smrg } 3420974d292Smrg } 3430974d292Smrg 3440974d292Smrg /* if the BO might end up in VRAM, prefer DownloadFromScreen */ 3450974d292Smrg if (can_fail && (possible_domains & RADEON_GEM_DOMAIN_VRAM)) { 3460974d292Smrg radeon_bo_is_busy(driver_priv->bo, ¤t_domain); 3470974d292Smrg 3480974d292Smrg if (current_domain & possible_domains) { 3490974d292Smrg if (current_domain == RADEON_GEM_DOMAIN_VRAM) 3500974d292Smrg return FALSE; 3510974d292Smrg } else if (possible_domains & RADEON_GEM_DOMAIN_VRAM) 3520974d292Smrg return FALSE; 3530974d292Smrg } 3540974d292Smrg 3550974d292Smrg if (flush) 356ad43ddacSmrg radeon_cs_flush_indirect(pScrn); 357ad43ddacSmrg 358ad43ddacSmrg /* flush IB */ 359ad43ddacSmrg ret = radeon_bo_map(driver_priv->bo, 1); 360ad43ddacSmrg if (ret) { 361ad43ddacSmrg FatalError("failed to map pixmap %d\n", ret); 362ad43ddacSmrg return FALSE; 363ad43ddacSmrg } 364ad43ddacSmrg driver_priv->bo_mapped = TRUE; 365ad43ddacSmrg 366ad43ddacSmrg pPix->devPrivate.ptr = driver_priv->bo->ptr; 367ad43ddacSmrg 368ad43ddacSmrg return TRUE; 369ad43ddacSmrg} 370ad43ddacSmrg 371ad43ddacSmrgvoid RADEONFinishAccess_CS(PixmapPtr pPix, int index) 372ad43ddacSmrg{ 373ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv; 374ad43ddacSmrg 375ad43ddacSmrg driver_priv = exaGetPixmapDriverPrivate(pPix); 376ad43ddacSmrg if (!driver_priv || !driver_priv->bo_mapped) 377ad43ddacSmrg return; 378ad43ddacSmrg 379ad43ddacSmrg radeon_bo_unmap(driver_priv->bo); 3800974d292Smrg driver_priv->bo_mapped = FALSE; 381ad43ddacSmrg pPix->devPrivate.ptr = NULL; 382ad43ddacSmrg} 383ad43ddacSmrg 384ad43ddacSmrg 385ad43ddacSmrgvoid *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align) 386ad43ddacSmrg{ 38768105dcbSveego ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 388ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 389ad43ddacSmrg struct radeon_exa_pixmap_priv *new_priv; 390ad43ddacSmrg 391ad43ddacSmrg#ifdef EXA_MIXED_PIXMAPS 392ad43ddacSmrg if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) { 393ad43ddacSmrg if (size != 0 && !info->exa_force_create && 394ad43ddacSmrg info->exa_pixmaps == FALSE) 395ad43ddacSmrg return NULL; 396ad43ddacSmrg } 397ad43ddacSmrg#endif 398ad43ddacSmrg 3992f39173dSmrg new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv)); 400ad43ddacSmrg if (!new_priv) 401ad43ddacSmrg return NULL; 402ad43ddacSmrg 403ad43ddacSmrg if (size == 0) 404ad43ddacSmrg return new_priv; 405ad43ddacSmrg 406ad43ddacSmrg new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, align, 407ad43ddacSmrg RADEON_GEM_DOMAIN_VRAM, 0); 408ad43ddacSmrg if (!new_priv->bo) { 4092f39173dSmrg free(new_priv); 410ad43ddacSmrg ErrorF("Failed to alloc memory\n"); 411ad43ddacSmrg return NULL; 412ad43ddacSmrg } 413ad43ddacSmrg 414ad43ddacSmrg return new_priv; 415ad43ddacSmrg 416ad43ddacSmrg} 417ad43ddacSmrg 4182f39173dSmrgstatic const unsigned MicroBlockTable[5][3][2] = { 4192f39173dSmrg /*linear tiled square-tiled */ 4202f39173dSmrg {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */ 4212f39173dSmrg {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */ 4222f39173dSmrg {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */ 4232f39173dSmrg {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */ 4242f39173dSmrg {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ 4252f39173dSmrg}; 4262f39173dSmrg 4272f39173dSmrg/* Return true if macrotiling can be enabled */ 4282f39173dSmrgstatic Bool RADEONMacroSwitch(int width, int height, int bpp, 4292f39173dSmrg uint32_t flags, Bool rv350_mode) 4302f39173dSmrg{ 4312f39173dSmrg unsigned tilew, tileh, microtiled, logbpp; 4322f39173dSmrg 4332f39173dSmrg logbpp = RADEONLog2(bpp / 8); 4342f39173dSmrg if (logbpp > 4) 4352f39173dSmrg return 0; 4362f39173dSmrg 4372f39173dSmrg microtiled = !!(flags & RADEON_TILING_MICRO); 4382f39173dSmrg tilew = MicroBlockTable[logbpp][microtiled][0] * 8; 4392f39173dSmrg tileh = MicroBlockTable[logbpp][microtiled][1] * 8; 4402f39173dSmrg 4412f39173dSmrg /* See TX_FILTER1_n.MACRO_SWITCH. */ 4422f39173dSmrg if (rv350_mode) { 4432f39173dSmrg return width >= tilew && height >= tileh; 4442f39173dSmrg } else { 4452f39173dSmrg return width > tilew && height > tileh; 4462f39173dSmrg } 4472f39173dSmrg} 4482f39173dSmrg 449ad43ddacSmrgvoid *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, 450ad43ddacSmrg int depth, int usage_hint, int bitsPerPixel, 451ad43ddacSmrg int *new_pitch) 452ad43ddacSmrg{ 45368105dcbSveego ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 454ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 455ad43ddacSmrg struct radeon_exa_pixmap_priv *new_priv; 456921a55d8Smrg int pitch, base_align; 45740732134Srjs uint32_t size, heighta; 458ad43ddacSmrg uint32_t tiling = 0; 459921a55d8Smrg int cpp = bitsPerPixel / 8; 46040732134Srjs#ifdef XF86DRM_MODE 46140732134Srjs struct radeon_surface surface; 46240732134Srjs#endif 463ad43ddacSmrg 464ad43ddacSmrg#ifdef EXA_MIXED_PIXMAPS 465ad43ddacSmrg if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) { 466ad43ddacSmrg if (width != 0 && height != 0 && !info->exa_force_create && 467ad43ddacSmrg info->exa_pixmaps == FALSE) 468ad43ddacSmrg return NULL; 469ad43ddacSmrg } 470ad43ddacSmrg#endif 471ad43ddacSmrg 472ad43ddacSmrg if (usage_hint) { 473ad43ddacSmrg if (info->allowColorTiling) { 474ad43ddacSmrg if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO) 475ad43ddacSmrg tiling |= RADEON_TILING_MACRO; 476ad43ddacSmrg if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO) 477ad43ddacSmrg tiling |= RADEON_TILING_MICRO; 478ad43ddacSmrg } 47940732134Srjs if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH) 48040732134Srjs tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO; 48140732134Srjs 482ad43ddacSmrg } 483ad43ddacSmrg 4842f39173dSmrg /* Small pixmaps must not be macrotiled on R300, hw cannot sample them 4852f39173dSmrg * correctly because samplers automatically switch to macrolinear. */ 4862f39173dSmrg if (info->ChipFamily >= CHIP_FAMILY_R300 && 4872f39173dSmrg info->ChipFamily <= CHIP_FAMILY_RS740 && 4882f39173dSmrg (tiling & RADEON_TILING_MACRO) && 4892f39173dSmrg !RADEONMacroSwitch(width, height, bitsPerPixel, tiling, 4902f39173dSmrg info->ChipFamily >= CHIP_FAMILY_RV350)) { 4912f39173dSmrg tiling &= ~RADEON_TILING_MACRO; 4922f39173dSmrg } 4932f39173dSmrg 49440732134Srjs heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling)); 495921a55d8Smrg pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp; 496921a55d8Smrg base_align = drmmode_get_base_align(pScrn, cpp, tiling); 49740732134Srjs size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE); 49840732134Srjs memset(&surface, 0, sizeof(struct radeon_surface)); 49940732134Srjs 50040732134Srjs#ifdef XF86DRM_MODE 501c73da4dbSmrg if (info->cs && info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { 50240732134Srjs if (width) { 50340732134Srjs surface.npix_x = width; 50440732134Srjs /* need to align height to 8 for old kernel */ 50540732134Srjs surface.npix_y = RADEON_ALIGN(height, 8); 50640732134Srjs surface.npix_z = 1; 50740732134Srjs surface.blk_w = 1; 50840732134Srjs surface.blk_h = 1; 50940732134Srjs surface.blk_d = 1; 51040732134Srjs surface.array_size = 1; 51140732134Srjs surface.last_level = 0; 51240732134Srjs surface.bpe = cpp; 51340732134Srjs surface.nsamples = 1; 51468105dcbSveego if (height < 64) { 51568105dcbSveego /* disable 2d tiling for small surface to work around 51668105dcbSveego * the fact that ddx align height to 8 pixel for old 51768105dcbSveego * obscure reason i can't remember 51868105dcbSveego */ 51968105dcbSveego tiling &= ~RADEON_TILING_MACRO; 52068105dcbSveego } 52140732134Srjs surface.flags = RADEON_SURF_SCANOUT; 52240732134Srjs surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); 52340732134Srjs surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); 52440732134Srjs if ((tiling & RADEON_TILING_MICRO)) { 52540732134Srjs surface.flags = RADEON_SURF_CLR(surface.flags, MODE); 52640732134Srjs surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 52740732134Srjs } 52840732134Srjs if ((tiling & RADEON_TILING_MACRO)) { 52940732134Srjs surface.flags = RADEON_SURF_CLR(surface.flags, MODE); 53040732134Srjs surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 53140732134Srjs } 53240732134Srjs if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) { 53340732134Srjs surface.flags |= RADEON_SURF_ZBUFFER; 53440732134Srjs surface.flags |= RADEON_SURF_SBUFFER; 53540732134Srjs } 53640732134Srjs if (radeon_surface_best(info->surf_man, &surface)) { 53740732134Srjs return NULL; 53840732134Srjs } 53940732134Srjs if (radeon_surface_init(info->surf_man, &surface)) { 54040732134Srjs return NULL; 54140732134Srjs } 54240732134Srjs size = surface.bo_size; 54340732134Srjs base_align = surface.bo_alignment; 54440732134Srjs pitch = surface.level[0].pitch_bytes; 54540732134Srjs tiling = 0; 54640732134Srjs switch (surface.level[0].mode) { 54740732134Srjs case RADEON_SURF_MODE_2D: 54840732134Srjs tiling |= RADEON_TILING_MACRO; 54940732134Srjs tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; 55040732134Srjs tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; 55140732134Srjs tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; 55240732134Srjs tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT; 55340732134Srjs tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT; 55440732134Srjs break; 55540732134Srjs case RADEON_SURF_MODE_1D: 55640732134Srjs tiling |= RADEON_TILING_MICRO; 55740732134Srjs break; 55840732134Srjs default: 55940732134Srjs break; 56040732134Srjs } 56140732134Srjs } 56240732134Srjs } 56340732134Srjs#endif 564ad43ddacSmrg 5652f39173dSmrg new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv)); 56640732134Srjs if (!new_priv) { 567ad43ddacSmrg return NULL; 56840732134Srjs } 569ad43ddacSmrg 57040732134Srjs if (size == 0) { 571ad43ddacSmrg return new_priv; 57240732134Srjs } 573ad43ddacSmrg 574921a55d8Smrg *new_pitch = pitch; 575ad43ddacSmrg 576921a55d8Smrg new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, base_align, 577ad43ddacSmrg RADEON_GEM_DOMAIN_VRAM, 0); 578ad43ddacSmrg if (!new_priv->bo) { 5792f39173dSmrg free(new_priv); 580ad43ddacSmrg ErrorF("Failed to alloc memory\n"); 581ad43ddacSmrg return NULL; 582ad43ddacSmrg } 583ad43ddacSmrg 584c4ae5be6Smrg if (tiling && !radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch)) 585c4ae5be6Smrg new_priv->tiling_flags = tiling; 586ad43ddacSmrg 58740732134Srjs new_priv->surface = surface; 588ad43ddacSmrg return new_priv; 589ad43ddacSmrg} 590ad43ddacSmrg 591ad43ddacSmrgvoid RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) 592ad43ddacSmrg{ 593ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv = driverPriv; 594ad43ddacSmrg 595ad43ddacSmrg if (!driverPriv) 596ad43ddacSmrg return; 597ad43ddacSmrg 598ad43ddacSmrg if (driver_priv->bo) 599ad43ddacSmrg radeon_bo_unref(driver_priv->bo); 6002f39173dSmrg free(driverPriv); 601ad43ddacSmrg} 602ad43ddacSmrg 603ad43ddacSmrgstruct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix) 604ad43ddacSmrg{ 605ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv; 606ad43ddacSmrg driver_priv = exaGetPixmapDriverPrivate(pPix); 607ad43ddacSmrg return driver_priv->bo; 608ad43ddacSmrg} 609ad43ddacSmrg 61040732134Srjs#if defined(XF86DRM_MODE) 61140732134Srjsstruct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix) 61240732134Srjs{ 61340732134Srjs struct radeon_exa_pixmap_priv *driver_priv; 61440732134Srjs driver_priv = exaGetPixmapDriverPrivate(pPix); 61540732134Srjs return &driver_priv->surface; 61640732134Srjs} 61740732134Srjs#endif 61840732134Srjs 619c4ae5be6Smrguint32_t radeon_get_pixmap_tiling(PixmapPtr pPix) 620c4ae5be6Smrg{ 621c4ae5be6Smrg struct radeon_exa_pixmap_priv *driver_priv; 622c4ae5be6Smrg driver_priv = exaGetPixmapDriverPrivate(pPix); 623c4ae5be6Smrg return driver_priv->tiling_flags; 624c4ae5be6Smrg} 625c4ae5be6Smrg 626ad43ddacSmrgvoid radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) 627ad43ddacSmrg{ 628ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv; 629ad43ddacSmrg 630ad43ddacSmrg driver_priv = exaGetPixmapDriverPrivate(pPix); 631ad43ddacSmrg if (driver_priv) { 632c4ae5be6Smrg uint32_t pitch; 633c4ae5be6Smrg 634ad43ddacSmrg if (driver_priv->bo) 635ad43ddacSmrg radeon_bo_unref(driver_priv->bo); 636ad43ddacSmrg 637ad43ddacSmrg radeon_bo_ref(bo); 638ad43ddacSmrg driver_priv->bo = bo; 639c4ae5be6Smrg 640c4ae5be6Smrg radeon_bo_get_tiling(bo, &driver_priv->tiling_flags, &pitch); 641ad43ddacSmrg } 642ad43ddacSmrg} 643ad43ddacSmrg 644ad43ddacSmrgBool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix) 645ad43ddacSmrg{ 646ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv; 647ad43ddacSmrg 648ad43ddacSmrg driver_priv = exaGetPixmapDriverPrivate(pPix); 649ad43ddacSmrg 650ad43ddacSmrg if (!driver_priv) 651ad43ddacSmrg return FALSE; 652ad43ddacSmrg if (driver_priv->bo) 653ad43ddacSmrg return TRUE; 654ad43ddacSmrg return FALSE; 655ad43ddacSmrg} 656ad43ddacSmrg#endif 657ad43ddacSmrg 658209ff23fSmrg#define ENTER_DRAW(x) TRACE 659209ff23fSmrg#define LEAVE_DRAW(x) TRACE 660209ff23fSmrg/***********************************************************************/ 661209ff23fSmrg 662209ff23fSmrg#define ACCEL_MMIO 663209ff23fSmrg#define ACCEL_PREAMBLE() unsigned char *RADEONMMIO = info->MMIO 664209ff23fSmrg#define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) 665209ff23fSmrg#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) 666209ff23fSmrg#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val)) 667ad43ddacSmrg#define OUT_RELOC(x, read, write) do {} while(0) 668209ff23fSmrg#define FINISH_ACCEL() 669209ff23fSmrg 670209ff23fSmrg#ifdef RENDER 671209ff23fSmrg#include "radeon_exa_render.c" 672209ff23fSmrg#endif 673209ff23fSmrg#include "radeon_exa_funcs.c" 674209ff23fSmrg 675209ff23fSmrg#undef ACCEL_MMIO 676209ff23fSmrg#undef ACCEL_PREAMBLE 677209ff23fSmrg#undef BEGIN_ACCEL 678209ff23fSmrg#undef OUT_ACCEL_REG 679b7e1c893Smrg#undef OUT_ACCEL_REG_F 680209ff23fSmrg#undef FINISH_ACCEL 681ad43ddacSmrg#undef OUT_RELOC 682209ff23fSmrg 683209ff23fSmrg#ifdef XF86DRI 684209ff23fSmrg 685209ff23fSmrg#define ACCEL_CP 686209ff23fSmrg#define ACCEL_PREAMBLE() \ 687209ff23fSmrg RING_LOCALS; \ 688209ff23fSmrg RADEONCP_REFRESH(pScrn, info) 689209ff23fSmrg#define BEGIN_ACCEL(n) BEGIN_RING(2*(n)) 690209ff23fSmrg#define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) 691209ff23fSmrg#define FINISH_ACCEL() ADVANCE_RING() 692ad43ddacSmrg#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write) 693209ff23fSmrg 694209ff23fSmrg#define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) 695209ff23fSmrg 696209ff23fSmrg#ifdef RENDER 697209ff23fSmrg#include "radeon_exa_render.c" 698209ff23fSmrg#endif 699209ff23fSmrg#include "radeon_exa_funcs.c" 700209ff23fSmrg 701b7e1c893Smrg#undef ACCEL_CP 702b7e1c893Smrg#undef ACCEL_PREAMBLE 703b7e1c893Smrg#undef BEGIN_ACCEL 704b7e1c893Smrg#undef OUT_ACCEL_REG 705b7e1c893Smrg#undef FINISH_ACCEL 706b7e1c893Smrg#undef OUT_RING_F 707b7e1c893Smrg 708209ff23fSmrg#endif /* XF86DRI */ 709209ff23fSmrg 710209ff23fSmrg/* 711209ff23fSmrg * Once screen->off_screen_base is set, this function 712209ff23fSmrg * allocates the remaining memory appropriately 713209ff23fSmrg */ 714209ff23fSmrgBool RADEONSetupMemEXA (ScreenPtr pScreen) 715209ff23fSmrg{ 71668105dcbSveego ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 717209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 718209ff23fSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 719209ff23fSmrg int cpp = info->CurrentLayout.pixel_bytes; 720209ff23fSmrg int screen_size; 721209ff23fSmrg int byteStride = pScrn->displayWidth * cpp; 722209ff23fSmrg 723b7e1c893Smrg if (info->accel_state->exa != NULL) { 724209ff23fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n"); 725209ff23fSmrg return FALSE; 726209ff23fSmrg } 727b7e1c893Smrg info->accel_state->exa = exaDriverAlloc(); 728b7e1c893Smrg if (info->accel_state->exa == NULL) 729209ff23fSmrg return FALSE; 730209ff23fSmrg 731209ff23fSmrg /* Need to adjust screen size for 16 line tiles, and then make it align to. 732209ff23fSmrg * the buffer alignment requirement. 733209ff23fSmrg */ 734209ff23fSmrg if (info->allowColorTiling) 735209ff23fSmrg screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride; 736209ff23fSmrg else 737209ff23fSmrg screen_size = pScrn->virtualY * byteStride; 738209ff23fSmrg 739b7e1c893Smrg info->accel_state->exa->memoryBase = info->FB; 740b7e1c893Smrg info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize; 741b7e1c893Smrg info->accel_state->exa->offScreenBase = screen_size; 742209ff23fSmrg 743209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n", 744b7e1c893Smrg info->accel_state->exa->memorySize / 1024); 745209ff23fSmrg 746209ff23fSmrg /* Reserve static area for hardware cursor */ 747209ff23fSmrg if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 748b7e1c893Smrg int cursor_size = 64 * 4 * 64; 749b7e1c893Smrg int align = IS_AVIVO_VARIANT ? 4096 : 256; 750b7e1c893Smrg int c; 751b7e1c893Smrg 752b7e1c893Smrg for (c = 0; c < xf86_config->num_crtc; c++) { 753b7e1c893Smrg xf86CrtcPtr crtc = xf86_config->crtc[c]; 754b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 755b7e1c893Smrg 756b7e1c893Smrg radeon_crtc->cursor_offset = 757b7e1c893Smrg RADEON_ALIGN(info->accel_state->exa->offScreenBase, align); 758b7e1c893Smrg info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size; 759b7e1c893Smrg 760b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 761b7e1c893Smrg "Will use %d kb for hardware cursor %d at offset 0x%08x\n", 762b7e1c893Smrg (cursor_size * xf86_config->num_crtc) / 1024, 763b7e1c893Smrg c, 764b7e1c893Smrg (unsigned int)radeon_crtc->cursor_offset); 765b7e1c893Smrg } 766209ff23fSmrg } 767209ff23fSmrg 768209ff23fSmrg#if defined(XF86DRI) 769209ff23fSmrg if (info->directRenderingEnabled) { 770b7e1c893Smrg int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size; 771209ff23fSmrg 772b7e1c893Smrg info->dri->frontOffset = 0; 773b7e1c893Smrg info->dri->frontPitch = pScrn->displayWidth; 774209ff23fSmrg 775209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 776209ff23fSmrg "Will use %d kb for front buffer at offset 0x%08x\n", 777b7e1c893Smrg screen_size / 1024, info->dri->frontOffset); 778209ff23fSmrg RADEONDRIAllocatePCIGARTTable(pScreen); 779209ff23fSmrg 780209ff23fSmrg if (info->cardType==CARD_PCIE) 781209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 782209ff23fSmrg "Will use %d kb for PCI GART at offset 0x%08x\n", 783b7e1c893Smrg info->dri->pciGartSize / 1024, 784b7e1c893Smrg (int)info->dri->pciGartOffset); 785209ff23fSmrg 786209ff23fSmrg /* Reserve a static area for the back buffer the same size as the 787209ff23fSmrg * visible screen. XXX: This would be better initialized in ati_dri.c 788209ff23fSmrg * when GLX is set up, but the offscreen memory manager's allocations 789209ff23fSmrg * don't last through VT switches, while the kernel's understanding of 790209ff23fSmrg * offscreen locations does. 791209ff23fSmrg */ 792b7e1c893Smrg info->dri->backPitch = pScrn->displayWidth; 793ad43ddacSmrg next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE); 794b7e1c893Smrg if (!info->dri->noBackBuffer && 795b7e1c893Smrg next + screen_size <= info->accel_state->exa->memorySize) 796209ff23fSmrg { 797b7e1c893Smrg info->dri->backOffset = next; 798b7e1c893Smrg info->accel_state->exa->offScreenBase = next + screen_size; 799209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 800209ff23fSmrg "Will use %d kb for back buffer at offset 0x%08x\n", 801b7e1c893Smrg screen_size / 1024, info->dri->backOffset); 802209ff23fSmrg } 803209ff23fSmrg 804209ff23fSmrg /* Reserve the static depth buffer, and adjust pitch and height to 805209ff23fSmrg * handle tiling. 806209ff23fSmrg */ 807b7e1c893Smrg info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); 808b7e1c893Smrg depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp; 809ad43ddacSmrg next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE); 810b7e1c893Smrg if (next + depth_size <= info->accel_state->exa->memorySize) 811209ff23fSmrg { 812b7e1c893Smrg info->dri->depthOffset = next; 813b7e1c893Smrg info->accel_state->exa->offScreenBase = next + depth_size; 814209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 815209ff23fSmrg "Will use %d kb for depth buffer at offset 0x%08x\n", 816b7e1c893Smrg depth_size / 1024, info->dri->depthOffset); 817209ff23fSmrg } 818209ff23fSmrg 819b7e1c893Smrg info->dri->textureSize *= (info->accel_state->exa->memorySize - 820b7e1c893Smrg info->accel_state->exa->offScreenBase) / 100; 821209ff23fSmrg 822b7e1c893Smrg l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS); 823209ff23fSmrg if (l < RADEON_LOG_TEX_GRANULARITY) 824209ff23fSmrg l = RADEON_LOG_TEX_GRANULARITY; 825b7e1c893Smrg info->dri->textureSize = (info->dri->textureSize >> l) << l; 826b7e1c893Smrg if (info->dri->textureSize >= 512 * 1024) { 827b7e1c893Smrg info->dri->textureOffset = info->accel_state->exa->offScreenBase; 828b7e1c893Smrg info->accel_state->exa->offScreenBase += info->dri->textureSize; 829209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 830209ff23fSmrg "Will use %d kb for textures at offset 0x%08x\n", 831b7e1c893Smrg info->dri->textureSize / 1024, info->dri->textureOffset); 832209ff23fSmrg } else { 833209ff23fSmrg /* Minimum texture size is for 2 256x256x32bpp textures */ 834b7e1c893Smrg info->dri->textureSize = 0; 835209ff23fSmrg } 836209ff23fSmrg } else 837209ff23fSmrg#endif /* XF86DRI */ 838209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 839209ff23fSmrg "Will use %d kb for front buffer at offset 0x%08x\n", 840209ff23fSmrg screen_size / 1024, 0); 841209ff23fSmrg 842209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 843209ff23fSmrg "Will use %ld kb for X Server offscreen at offset 0x%08lx\n", 844b7e1c893Smrg (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) / 845b7e1c893Smrg 1024, info->accel_state->exa->offScreenBase); 846209ff23fSmrg 847209ff23fSmrg return TRUE; 848209ff23fSmrg} 849209ff23fSmrg 850209ff23fSmrg#ifdef XF86DRI 851209ff23fSmrg 852209ff23fSmrg#ifndef ExaOffscreenMarkUsed 853209ff23fSmrgextern void ExaOffscreenMarkUsed(PixmapPtr); 854209ff23fSmrg#endif 855209ff23fSmrg 856209ff23fSmrgunsigned long long 857209ff23fSmrgRADEONTexOffsetStart(PixmapPtr pPix) 858209ff23fSmrg{ 859b7e1c893Smrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 860b7e1c893Smrg unsigned long long offset; 861ad43ddacSmrg 862ad43ddacSmrg if (exaGetPixmapDriverPrivate(pPix)) 863ad43ddacSmrg return -1; 864ad43ddacSmrg 865209ff23fSmrg exaMoveInPixmap(pPix); 866209ff23fSmrg ExaOffscreenMarkUsed(pPix); 867209ff23fSmrg 868b7e1c893Smrg offset = exaGetPixmapOffset(pPix); 869b7e1c893Smrg 870b7e1c893Smrg if (offset > info->FbMapSize) 871b7e1c893Smrg return ~0ULL; 872b7e1c893Smrg else 873b7e1c893Smrg return info->fbLocation + offset; 874209ff23fSmrg} 875209ff23fSmrg#endif 876