radeon_exa.c revision ad43ddac
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" 45209ff23fSmrg 46209ff23fSmrg#include "xf86.h" 47209ff23fSmrg 48209ff23fSmrg 49209ff23fSmrg/***********************************************************************/ 50209ff23fSmrg#define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn = xf86Screens[pScr->myNum]; \ 51209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn) 52209ff23fSmrg 53209ff23fSmrg#define RADEON_TRACE_FALL 0 54209ff23fSmrg#define RADEON_TRACE_DRAW 0 55209ff23fSmrg 56209ff23fSmrg#if RADEON_TRACE_FALL 57209ff23fSmrg#define RADEON_FALLBACK(x) \ 58209ff23fSmrgdo { \ 59209ff23fSmrg ErrorF("%s: ", __FUNCTION__); \ 60209ff23fSmrg ErrorF x; \ 61209ff23fSmrg return FALSE; \ 62209ff23fSmrg} while (0) 63209ff23fSmrg#else 64209ff23fSmrg#define RADEON_FALLBACK(x) return FALSE 65209ff23fSmrg#endif 66209ff23fSmrg 67209ff23fSmrg#if RADEON_TRACE_DRAW 68209ff23fSmrg#define TRACE do { ErrorF("TRACE: %s\n", __FUNCTION__); } while(0) 69209ff23fSmrg#else 70209ff23fSmrg#define TRACE 71209ff23fSmrg#endif 72209ff23fSmrg 73209ff23fSmrgstatic struct { 74209ff23fSmrg int rop; 75209ff23fSmrg int pattern; 76209ff23fSmrg} RADEON_ROP[] = { 77209ff23fSmrg { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear */ 78209ff23fSmrg { RADEON_ROP3_DSa, RADEON_ROP3_DPa }, /* Gxand */ 79209ff23fSmrg { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse */ 80209ff23fSmrg { RADEON_ROP3_S, RADEON_ROP3_P }, /* GXcopy */ 81209ff23fSmrg { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted */ 82209ff23fSmrg { RADEON_ROP3_D, RADEON_ROP3_D }, /* GXnoop */ 83209ff23fSmrg { RADEON_ROP3_DSx, RADEON_ROP3_DPx }, /* GXxor */ 84209ff23fSmrg { RADEON_ROP3_DSo, RADEON_ROP3_DPo }, /* GXor */ 85209ff23fSmrg { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor */ 86209ff23fSmrg { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv */ 87209ff23fSmrg { RADEON_ROP3_Dn, RADEON_ROP3_Dn }, /* GXinvert */ 88209ff23fSmrg { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse */ 89209ff23fSmrg { RADEON_ROP3_Sn, RADEON_ROP3_Pn }, /* GXcopyInverted */ 90209ff23fSmrg { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted */ 91209ff23fSmrg { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand */ 92209ff23fSmrg { RADEON_ROP3_ONE, RADEON_ROP3_ONE } /* GXset */ 93209ff23fSmrg}; 94209ff23fSmrg 95209ff23fSmrg/* Compute log base 2 of val. */ 96209ff23fSmrgstatic __inline__ int 97209ff23fSmrgRADEONLog2(int val) 98209ff23fSmrg{ 99209ff23fSmrg int bits; 100209ff23fSmrg#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__) 101209ff23fSmrg __asm volatile("bsrl %1, %0" 102209ff23fSmrg : "=r" (bits) 103209ff23fSmrg : "c" (val) 104209ff23fSmrg ); 105209ff23fSmrg return bits; 106209ff23fSmrg#else 107209ff23fSmrg for (bits = 0; val != 0; val >>= 1, ++bits) 108209ff23fSmrg ; 109209ff23fSmrg return bits - 1; 110209ff23fSmrg#endif 111209ff23fSmrg} 112209ff23fSmrg 113209ff23fSmrgstatic __inline__ uint32_t F_TO_DW(float val) 114209ff23fSmrg{ 115209ff23fSmrg union { 116209ff23fSmrg float f; 117209ff23fSmrg uint32_t l; 118209ff23fSmrg } tmp; 119209ff23fSmrg tmp.f = val; 120209ff23fSmrg return tmp.l; 121209ff23fSmrg} 122209ff23fSmrg 123ad43ddacSmrg 124ad43ddacSmrg#ifdef XF86DRM_MODE 125ad43ddacSmrg 126ad43ddacSmrgstatic inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int read_domains, int write_domain) 127ad43ddacSmrg{ 128ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix); 129ad43ddacSmrg 130ad43ddacSmrg radeon_cs_space_add_persistent_bo(cs, driver_priv->bo, read_domains, write_domain); 131ad43ddacSmrg} 132ad43ddacSmrg 133ad43ddacSmrg#endif /* XF86DRM_MODE */ 134ad43ddacSmrg 135ad43ddacSmrg 136209ff23fSmrg/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we 137209ff23fSmrg * require src and dest datatypes to be equal. 138209ff23fSmrg */ 139209ff23fSmrgBool RADEONGetDatatypeBpp(int bpp, uint32_t *type) 140209ff23fSmrg{ 141209ff23fSmrg switch (bpp) { 142209ff23fSmrg case 8: 143209ff23fSmrg *type = ATI_DATATYPE_CI8; 144209ff23fSmrg return TRUE; 145209ff23fSmrg case 16: 146209ff23fSmrg *type = ATI_DATATYPE_RGB565; 147209ff23fSmrg return TRUE; 148209ff23fSmrg case 24: 149209ff23fSmrg *type = ATI_DATATYPE_CI8; 150209ff23fSmrg return TRUE; 151209ff23fSmrg case 32: 152209ff23fSmrg *type = ATI_DATATYPE_ARGB8888; 153209ff23fSmrg return TRUE; 154209ff23fSmrg default: 155209ff23fSmrg RADEON_FALLBACK(("Unsupported bpp: %d\n", bpp)); 156209ff23fSmrg return FALSE; 157209ff23fSmrg } 158209ff23fSmrg} 159209ff23fSmrg 160209ff23fSmrgstatic Bool RADEONPixmapIsColortiled(PixmapPtr pPix) 161209ff23fSmrg{ 162209ff23fSmrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 163209ff23fSmrg 164209ff23fSmrg /* This doesn't account for the back buffer, which we may want to wrap in 165209ff23fSmrg * a pixmap at some point for the purposes of DRI buffer moves. 166209ff23fSmrg */ 167209ff23fSmrg if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0) 168209ff23fSmrg return TRUE; 169209ff23fSmrg else 170209ff23fSmrg return FALSE; 171209ff23fSmrg} 172209ff23fSmrg 173209ff23fSmrgstatic Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset, 174209ff23fSmrg unsigned int offset, unsigned int pitch) 175209ff23fSmrg{ 176209ff23fSmrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 177209ff23fSmrg 178b7e1c893Smrg if (pitch > 16320 || pitch % info->accel_state->exa->pixmapPitchAlign != 0) 179209ff23fSmrg RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch)); 180209ff23fSmrg 181b7e1c893Smrg if (offset % info->accel_state->exa->pixmapOffsetAlign != 0) 182209ff23fSmrg RADEON_FALLBACK(("Bad offset 0x%08x\n", offset)); 183209ff23fSmrg 184209ff23fSmrg pitch = pitch >> 6; 185209ff23fSmrg *pitch_offset = (pitch << 22) | (offset >> 10); 186209ff23fSmrg 187209ff23fSmrg /* If it's the front buffer, we've got to note that it's tiled? */ 188209ff23fSmrg if (RADEONPixmapIsColortiled(pPix)) 189209ff23fSmrg *pitch_offset |= RADEON_DST_TILE_MACRO; 190209ff23fSmrg return TRUE; 191209ff23fSmrg} 192209ff23fSmrg 193209ff23fSmrgBool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) 194209ff23fSmrg{ 195209ff23fSmrg uint32_t pitch, offset; 196209ff23fSmrg int bpp; 197209ff23fSmrg 198209ff23fSmrg bpp = pPix->drawable.bitsPerPixel; 199209ff23fSmrg if (bpp == 24) 200209ff23fSmrg bpp = 8; 201209ff23fSmrg 202ad43ddacSmrg offset = radeonGetPixmapOffset(pPix); 203209ff23fSmrg pitch = exaGetPixmapPitch(pPix); 204209ff23fSmrg 205209ff23fSmrg return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); 206209ff23fSmrg} 207209ff23fSmrg 208209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 209209ff23fSmrg 210b7e1c893Smrgstatic unsigned long swapper_surfaces[6]; 211209ff23fSmrg 212ad43ddacSmrgstatic Bool RADEONPrepareAccess_BE(PixmapPtr pPix, int index) 213209ff23fSmrg{ 214209ff23fSmrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 215209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 216209ff23fSmrg uint32_t offset = exaGetPixmapOffset(pPix); 217209ff23fSmrg int bpp, soff; 218209ff23fSmrg uint32_t size, flags; 219209ff23fSmrg 220209ff23fSmrg /* Front buffer is always set with proper swappers */ 221209ff23fSmrg if (offset == 0) 222209ff23fSmrg return TRUE; 223209ff23fSmrg 224209ff23fSmrg /* If same bpp as front buffer, just do nothing as the main 225209ff23fSmrg * swappers will apply 226209ff23fSmrg */ 227209ff23fSmrg bpp = pPix->drawable.bitsPerPixel; 228209ff23fSmrg if (bpp == pScrn->bitsPerPixel) 229209ff23fSmrg return TRUE; 230209ff23fSmrg 231209ff23fSmrg /* We need to setup a separate swapper, let's request a 232209ff23fSmrg * surface. We need to align the size first 233209ff23fSmrg */ 234209ff23fSmrg size = exaGetPixmapSize(pPix); 235ad43ddacSmrg size = RADEON_ALIGN(size, RADEON_GPU_PAGE_SIZE); 236209ff23fSmrg 237209ff23fSmrg /* Set surface to tiling disabled with appropriate swapper */ 238209ff23fSmrg switch (bpp) { 239209ff23fSmrg case 16: 240209ff23fSmrg flags = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP; 241209ff23fSmrg break; 242209ff23fSmrg case 32: 243209ff23fSmrg flags = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; 244209ff23fSmrg break; 245209ff23fSmrg default: 246209ff23fSmrg flags = 0; 247209ff23fSmrg } 248209ff23fSmrg#if defined(XF86DRI) 249209ff23fSmrg if (info->directRenderingEnabled && info->allowColorTiling) { 250b7e1c893Smrg struct drm_radeon_surface_alloc drmsurfalloc; 251209ff23fSmrg int rc; 252209ff23fSmrg 253209ff23fSmrg drmsurfalloc.address = offset; 254209ff23fSmrg drmsurfalloc.size = size; 255209ff23fSmrg drmsurfalloc.flags = flags | 1; /* bogus pitch to please DRM */ 256209ff23fSmrg 257b7e1c893Smrg rc = drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_ALLOC, 258209ff23fSmrg &drmsurfalloc, sizeof(drmsurfalloc)); 259209ff23fSmrg if (rc < 0) { 260209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 261209ff23fSmrg "drm: could not allocate surface for access" 262209ff23fSmrg " swapper, err: %d!\n", rc); 263209ff23fSmrg return FALSE; 264209ff23fSmrg } 265209ff23fSmrg swapper_surfaces[index] = offset; 266209ff23fSmrg 267209ff23fSmrg return TRUE; 268209ff23fSmrg } 269209ff23fSmrg#endif 270209ff23fSmrg soff = (index + 1) * 0x10; 271209ff23fSmrg OUTREG(RADEON_SURFACE0_INFO + soff, flags); 272209ff23fSmrg OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset); 273209ff23fSmrg OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1); 274209ff23fSmrg swapper_surfaces[index] = offset; 275209ff23fSmrg return TRUE; 276209ff23fSmrg} 277209ff23fSmrg 278ad43ddacSmrgstatic void RADEONFinishAccess_BE(PixmapPtr pPix, int index) 279209ff23fSmrg{ 280209ff23fSmrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 281209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 282209ff23fSmrg uint32_t offset = exaGetPixmapOffset(pPix); 283209ff23fSmrg int soff; 284209ff23fSmrg 285209ff23fSmrg /* Front buffer is always set with proper swappers */ 286209ff23fSmrg if (offset == 0) 287209ff23fSmrg return; 288209ff23fSmrg 289209ff23fSmrg if (swapper_surfaces[index] == 0) 290209ff23fSmrg return; 291209ff23fSmrg#if defined(XF86DRI) 292209ff23fSmrg if (info->directRenderingEnabled && info->allowColorTiling) { 293b7e1c893Smrg struct drm_radeon_surface_free drmsurffree; 294209ff23fSmrg 295209ff23fSmrg drmsurffree.address = offset; 296b7e1c893Smrg drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_FREE, 297209ff23fSmrg &drmsurffree, sizeof(drmsurffree)); 298209ff23fSmrg swapper_surfaces[index] = 0; 299209ff23fSmrg return; 300209ff23fSmrg } 301209ff23fSmrg#endif 302209ff23fSmrg soff = (index + 1) * 0x10; 303209ff23fSmrg OUTREG(RADEON_SURFACE0_INFO + soff, 0); 304209ff23fSmrg OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0); 305209ff23fSmrg OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0); 306209ff23fSmrg swapper_surfaces[index] = 0; 307209ff23fSmrg} 308209ff23fSmrg 309209ff23fSmrg#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ 310209ff23fSmrg 311ad43ddacSmrg#ifdef XF86DRM_MODE 312ad43ddacSmrgBool RADEONPrepareAccess_CS(PixmapPtr pPix, int index) 313ad43ddacSmrg{ 314ad43ddacSmrg ScreenPtr pScreen = pPix->drawable.pScreen; 315ad43ddacSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 316ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 317ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv; 318ad43ddacSmrg int ret; 319ad43ddacSmrg 320ad43ddacSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 321ad43ddacSmrg /* May need to handle byte swapping in DownloadFrom/UploadToScreen */ 322ad43ddacSmrg if (pPix->drawable.bitsPerPixel > 8 && 323ad43ddacSmrg pPix != pScreen->GetScreenPixmap(pScreen)) 324ad43ddacSmrg return FALSE; 325ad43ddacSmrg#endif 326ad43ddacSmrg 327ad43ddacSmrg driver_priv = exaGetPixmapDriverPrivate(pPix); 328ad43ddacSmrg if (!driver_priv) 329ad43ddacSmrg return FALSE; 330ad43ddacSmrg 331ad43ddacSmrg /* if we have more refs than just the BO then flush */ 332ad43ddacSmrg if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) 333ad43ddacSmrg radeon_cs_flush_indirect(pScrn); 334ad43ddacSmrg 335ad43ddacSmrg /* flush IB */ 336ad43ddacSmrg ret = radeon_bo_map(driver_priv->bo, 1); 337ad43ddacSmrg if (ret) { 338ad43ddacSmrg FatalError("failed to map pixmap %d\n", ret); 339ad43ddacSmrg return FALSE; 340ad43ddacSmrg } 341ad43ddacSmrg driver_priv->bo_mapped = TRUE; 342ad43ddacSmrg 343ad43ddacSmrg pPix->devPrivate.ptr = driver_priv->bo->ptr; 344ad43ddacSmrg 345ad43ddacSmrg return TRUE; 346ad43ddacSmrg} 347ad43ddacSmrg 348ad43ddacSmrgvoid RADEONFinishAccess_CS(PixmapPtr pPix, int index) 349ad43ddacSmrg{ 350ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv; 351ad43ddacSmrg 352ad43ddacSmrg driver_priv = exaGetPixmapDriverPrivate(pPix); 353ad43ddacSmrg if (!driver_priv || !driver_priv->bo_mapped) 354ad43ddacSmrg return; 355ad43ddacSmrg 356ad43ddacSmrg radeon_bo_unmap(driver_priv->bo); 357ad43ddacSmrg pPix->devPrivate.ptr = NULL; 358ad43ddacSmrg} 359ad43ddacSmrg 360ad43ddacSmrg 361ad43ddacSmrgvoid *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align) 362ad43ddacSmrg{ 363ad43ddacSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 364ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 365ad43ddacSmrg struct radeon_exa_pixmap_priv *new_priv; 366ad43ddacSmrg 367ad43ddacSmrg#ifdef EXA_MIXED_PIXMAPS 368ad43ddacSmrg if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) { 369ad43ddacSmrg if (size != 0 && !info->exa_force_create && 370ad43ddacSmrg info->exa_pixmaps == FALSE) 371ad43ddacSmrg return NULL; 372ad43ddacSmrg } 373ad43ddacSmrg#endif 374ad43ddacSmrg 375ad43ddacSmrg new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv)); 376ad43ddacSmrg if (!new_priv) 377ad43ddacSmrg return NULL; 378ad43ddacSmrg 379ad43ddacSmrg if (size == 0) 380ad43ddacSmrg return new_priv; 381ad43ddacSmrg 382ad43ddacSmrg new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, align, 383ad43ddacSmrg RADEON_GEM_DOMAIN_VRAM, 0); 384ad43ddacSmrg if (!new_priv->bo) { 385ad43ddacSmrg xfree(new_priv); 386ad43ddacSmrg ErrorF("Failed to alloc memory\n"); 387ad43ddacSmrg return NULL; 388ad43ddacSmrg } 389ad43ddacSmrg 390ad43ddacSmrg return new_priv; 391ad43ddacSmrg 392ad43ddacSmrg} 393ad43ddacSmrg 394ad43ddacSmrgvoid *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, 395ad43ddacSmrg int depth, int usage_hint, int bitsPerPixel, 396ad43ddacSmrg int *new_pitch) 397ad43ddacSmrg{ 398ad43ddacSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 399ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 400ad43ddacSmrg struct radeon_exa_pixmap_priv *new_priv; 401ad43ddacSmrg int padded_width; 402ad43ddacSmrg uint32_t size; 403ad43ddacSmrg uint32_t tiling = 0; 404ad43ddacSmrg int pixmap_align; 405ad43ddacSmrg 406ad43ddacSmrg#ifdef EXA_MIXED_PIXMAPS 407ad43ddacSmrg if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) { 408ad43ddacSmrg if (width != 0 && height != 0 && !info->exa_force_create && 409ad43ddacSmrg info->exa_pixmaps == FALSE) 410ad43ddacSmrg return NULL; 411ad43ddacSmrg } 412ad43ddacSmrg#endif 413ad43ddacSmrg 414ad43ddacSmrg if (usage_hint) { 415ad43ddacSmrg if (info->allowColorTiling) { 416ad43ddacSmrg if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO) 417ad43ddacSmrg tiling |= RADEON_TILING_MACRO; 418ad43ddacSmrg if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO) 419ad43ddacSmrg tiling |= RADEON_TILING_MICRO; 420ad43ddacSmrg } 421ad43ddacSmrg } 422ad43ddacSmrg 423ad43ddacSmrg if (tiling) { 424ad43ddacSmrg height = RADEON_ALIGN(height, 16); 425ad43ddacSmrg pixmap_align = 256; 426ad43ddacSmrg } else 427ad43ddacSmrg pixmap_align = 64; 428ad43ddacSmrg 429ad43ddacSmrg padded_width = ((width * bitsPerPixel + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); 430ad43ddacSmrg padded_width = RADEON_ALIGN(padded_width, pixmap_align); 431ad43ddacSmrg size = height * padded_width; 432ad43ddacSmrg 433ad43ddacSmrg new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv)); 434ad43ddacSmrg if (!new_priv) 435ad43ddacSmrg return NULL; 436ad43ddacSmrg 437ad43ddacSmrg if (size == 0) 438ad43ddacSmrg return new_priv; 439ad43ddacSmrg 440ad43ddacSmrg *new_pitch = padded_width; 441ad43ddacSmrg 442ad43ddacSmrg new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, 0, 443ad43ddacSmrg RADEON_GEM_DOMAIN_VRAM, 0); 444ad43ddacSmrg if (!new_priv->bo) { 445ad43ddacSmrg xfree(new_priv); 446ad43ddacSmrg ErrorF("Failed to alloc memory\n"); 447ad43ddacSmrg return NULL; 448ad43ddacSmrg } 449ad43ddacSmrg 450ad43ddacSmrg if (tiling) 451ad43ddacSmrg radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch); 452ad43ddacSmrg 453ad43ddacSmrg return new_priv; 454ad43ddacSmrg} 455ad43ddacSmrg 456ad43ddacSmrgvoid RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) 457ad43ddacSmrg{ 458ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv = driverPriv; 459ad43ddacSmrg 460ad43ddacSmrg if (!driverPriv) 461ad43ddacSmrg return; 462ad43ddacSmrg 463ad43ddacSmrg if (driver_priv->bo) 464ad43ddacSmrg radeon_bo_unref(driver_priv->bo); 465ad43ddacSmrg xfree(driverPriv); 466ad43ddacSmrg} 467ad43ddacSmrg 468ad43ddacSmrgstruct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix) 469ad43ddacSmrg{ 470ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv; 471ad43ddacSmrg driver_priv = exaGetPixmapDriverPrivate(pPix); 472ad43ddacSmrg return driver_priv->bo; 473ad43ddacSmrg} 474ad43ddacSmrg 475ad43ddacSmrgvoid radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) 476ad43ddacSmrg{ 477ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv; 478ad43ddacSmrg 479ad43ddacSmrg driver_priv = exaGetPixmapDriverPrivate(pPix); 480ad43ddacSmrg if (driver_priv) { 481ad43ddacSmrg if (driver_priv->bo) 482ad43ddacSmrg radeon_bo_unref(driver_priv->bo); 483ad43ddacSmrg 484ad43ddacSmrg radeon_bo_ref(bo); 485ad43ddacSmrg driver_priv->bo = bo; 486ad43ddacSmrg } 487ad43ddacSmrg} 488ad43ddacSmrg 489ad43ddacSmrgBool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix) 490ad43ddacSmrg{ 491ad43ddacSmrg struct radeon_exa_pixmap_priv *driver_priv; 492ad43ddacSmrg 493ad43ddacSmrg driver_priv = exaGetPixmapDriverPrivate(pPix); 494ad43ddacSmrg 495ad43ddacSmrg if (!driver_priv) 496ad43ddacSmrg return FALSE; 497ad43ddacSmrg if (driver_priv->bo) 498ad43ddacSmrg return TRUE; 499ad43ddacSmrg return FALSE; 500ad43ddacSmrg} 501ad43ddacSmrg#endif 502ad43ddacSmrg 503209ff23fSmrg#define ENTER_DRAW(x) TRACE 504209ff23fSmrg#define LEAVE_DRAW(x) TRACE 505209ff23fSmrg/***********************************************************************/ 506209ff23fSmrg 507209ff23fSmrg#define ACCEL_MMIO 508209ff23fSmrg#define ACCEL_PREAMBLE() unsigned char *RADEONMMIO = info->MMIO 509209ff23fSmrg#define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) 510209ff23fSmrg#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) 511209ff23fSmrg#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val)) 512ad43ddacSmrg#define OUT_RELOC(x, read, write) do {} while(0) 513209ff23fSmrg#define FINISH_ACCEL() 514209ff23fSmrg 515209ff23fSmrg#ifdef RENDER 516209ff23fSmrg#include "radeon_exa_render.c" 517209ff23fSmrg#endif 518209ff23fSmrg#include "radeon_exa_funcs.c" 519209ff23fSmrg 520209ff23fSmrg#undef ACCEL_MMIO 521209ff23fSmrg#undef ACCEL_PREAMBLE 522209ff23fSmrg#undef BEGIN_ACCEL 523209ff23fSmrg#undef OUT_ACCEL_REG 524b7e1c893Smrg#undef OUT_ACCEL_REG_F 525209ff23fSmrg#undef FINISH_ACCEL 526ad43ddacSmrg#undef OUT_RELOC 527209ff23fSmrg 528209ff23fSmrg#ifdef XF86DRI 529209ff23fSmrg 530209ff23fSmrg#define ACCEL_CP 531209ff23fSmrg#define ACCEL_PREAMBLE() \ 532209ff23fSmrg RING_LOCALS; \ 533209ff23fSmrg RADEONCP_REFRESH(pScrn, info) 534209ff23fSmrg#define BEGIN_ACCEL(n) BEGIN_RING(2*(n)) 535209ff23fSmrg#define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) 536209ff23fSmrg#define FINISH_ACCEL() ADVANCE_RING() 537ad43ddacSmrg#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write) 538209ff23fSmrg 539209ff23fSmrg#define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) 540209ff23fSmrg 541209ff23fSmrg#ifdef RENDER 542209ff23fSmrg#include "radeon_exa_render.c" 543209ff23fSmrg#endif 544209ff23fSmrg#include "radeon_exa_funcs.c" 545209ff23fSmrg 546b7e1c893Smrg#undef ACCEL_CP 547b7e1c893Smrg#undef ACCEL_PREAMBLE 548b7e1c893Smrg#undef BEGIN_ACCEL 549b7e1c893Smrg#undef OUT_ACCEL_REG 550b7e1c893Smrg#undef FINISH_ACCEL 551b7e1c893Smrg#undef OUT_RING_F 552b7e1c893Smrg 553209ff23fSmrg#endif /* XF86DRI */ 554209ff23fSmrg 555209ff23fSmrg/* 556209ff23fSmrg * Once screen->off_screen_base is set, this function 557209ff23fSmrg * allocates the remaining memory appropriately 558209ff23fSmrg */ 559209ff23fSmrgBool RADEONSetupMemEXA (ScreenPtr pScreen) 560209ff23fSmrg{ 561209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 562209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 563209ff23fSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 564209ff23fSmrg int cpp = info->CurrentLayout.pixel_bytes; 565209ff23fSmrg int screen_size; 566209ff23fSmrg int byteStride = pScrn->displayWidth * cpp; 567209ff23fSmrg 568b7e1c893Smrg if (info->accel_state->exa != NULL) { 569209ff23fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n"); 570209ff23fSmrg return FALSE; 571209ff23fSmrg } 572b7e1c893Smrg info->accel_state->exa = exaDriverAlloc(); 573b7e1c893Smrg if (info->accel_state->exa == NULL) 574209ff23fSmrg return FALSE; 575209ff23fSmrg 576209ff23fSmrg /* Need to adjust screen size for 16 line tiles, and then make it align to. 577209ff23fSmrg * the buffer alignment requirement. 578209ff23fSmrg */ 579209ff23fSmrg if (info->allowColorTiling) 580209ff23fSmrg screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride; 581209ff23fSmrg else 582209ff23fSmrg screen_size = pScrn->virtualY * byteStride; 583209ff23fSmrg 584b7e1c893Smrg info->accel_state->exa->memoryBase = info->FB; 585b7e1c893Smrg info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize; 586b7e1c893Smrg info->accel_state->exa->offScreenBase = screen_size; 587209ff23fSmrg 588209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n", 589b7e1c893Smrg info->accel_state->exa->memorySize / 1024); 590209ff23fSmrg 591209ff23fSmrg /* Reserve static area for hardware cursor */ 592209ff23fSmrg if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 593b7e1c893Smrg int cursor_size = 64 * 4 * 64; 594b7e1c893Smrg int align = IS_AVIVO_VARIANT ? 4096 : 256; 595b7e1c893Smrg int c; 596b7e1c893Smrg 597b7e1c893Smrg for (c = 0; c < xf86_config->num_crtc; c++) { 598b7e1c893Smrg xf86CrtcPtr crtc = xf86_config->crtc[c]; 599b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 600b7e1c893Smrg 601b7e1c893Smrg radeon_crtc->cursor_offset = 602b7e1c893Smrg RADEON_ALIGN(info->accel_state->exa->offScreenBase, align); 603b7e1c893Smrg info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size; 604b7e1c893Smrg 605b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 606b7e1c893Smrg "Will use %d kb for hardware cursor %d at offset 0x%08x\n", 607b7e1c893Smrg (cursor_size * xf86_config->num_crtc) / 1024, 608b7e1c893Smrg c, 609b7e1c893Smrg (unsigned int)radeon_crtc->cursor_offset); 610b7e1c893Smrg } 611209ff23fSmrg } 612209ff23fSmrg 613209ff23fSmrg#if defined(XF86DRI) 614209ff23fSmrg if (info->directRenderingEnabled) { 615b7e1c893Smrg int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size; 616209ff23fSmrg 617b7e1c893Smrg info->dri->frontOffset = 0; 618b7e1c893Smrg info->dri->frontPitch = pScrn->displayWidth; 619209ff23fSmrg 620209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 621209ff23fSmrg "Will use %d kb for front buffer at offset 0x%08x\n", 622b7e1c893Smrg screen_size / 1024, info->dri->frontOffset); 623209ff23fSmrg RADEONDRIAllocatePCIGARTTable(pScreen); 624209ff23fSmrg 625209ff23fSmrg if (info->cardType==CARD_PCIE) 626209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 627209ff23fSmrg "Will use %d kb for PCI GART at offset 0x%08x\n", 628b7e1c893Smrg info->dri->pciGartSize / 1024, 629b7e1c893Smrg (int)info->dri->pciGartOffset); 630209ff23fSmrg 631209ff23fSmrg /* Reserve a static area for the back buffer the same size as the 632209ff23fSmrg * visible screen. XXX: This would be better initialized in ati_dri.c 633209ff23fSmrg * when GLX is set up, but the offscreen memory manager's allocations 634209ff23fSmrg * don't last through VT switches, while the kernel's understanding of 635209ff23fSmrg * offscreen locations does. 636209ff23fSmrg */ 637b7e1c893Smrg info->dri->backPitch = pScrn->displayWidth; 638ad43ddacSmrg next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE); 639b7e1c893Smrg if (!info->dri->noBackBuffer && 640b7e1c893Smrg next + screen_size <= info->accel_state->exa->memorySize) 641209ff23fSmrg { 642b7e1c893Smrg info->dri->backOffset = next; 643b7e1c893Smrg info->accel_state->exa->offScreenBase = next + screen_size; 644209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 645209ff23fSmrg "Will use %d kb for back buffer at offset 0x%08x\n", 646b7e1c893Smrg screen_size / 1024, info->dri->backOffset); 647209ff23fSmrg } 648209ff23fSmrg 649209ff23fSmrg /* Reserve the static depth buffer, and adjust pitch and height to 650209ff23fSmrg * handle tiling. 651209ff23fSmrg */ 652b7e1c893Smrg info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); 653b7e1c893Smrg depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp; 654ad43ddacSmrg next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE); 655b7e1c893Smrg if (next + depth_size <= info->accel_state->exa->memorySize) 656209ff23fSmrg { 657b7e1c893Smrg info->dri->depthOffset = next; 658b7e1c893Smrg info->accel_state->exa->offScreenBase = next + depth_size; 659209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 660209ff23fSmrg "Will use %d kb for depth buffer at offset 0x%08x\n", 661b7e1c893Smrg depth_size / 1024, info->dri->depthOffset); 662209ff23fSmrg } 663209ff23fSmrg 664b7e1c893Smrg info->dri->textureSize *= (info->accel_state->exa->memorySize - 665b7e1c893Smrg info->accel_state->exa->offScreenBase) / 100; 666209ff23fSmrg 667b7e1c893Smrg l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS); 668209ff23fSmrg if (l < RADEON_LOG_TEX_GRANULARITY) 669209ff23fSmrg l = RADEON_LOG_TEX_GRANULARITY; 670b7e1c893Smrg info->dri->textureSize = (info->dri->textureSize >> l) << l; 671b7e1c893Smrg if (info->dri->textureSize >= 512 * 1024) { 672b7e1c893Smrg info->dri->textureOffset = info->accel_state->exa->offScreenBase; 673b7e1c893Smrg info->accel_state->exa->offScreenBase += info->dri->textureSize; 674209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 675209ff23fSmrg "Will use %d kb for textures at offset 0x%08x\n", 676b7e1c893Smrg info->dri->textureSize / 1024, info->dri->textureOffset); 677209ff23fSmrg } else { 678209ff23fSmrg /* Minimum texture size is for 2 256x256x32bpp textures */ 679b7e1c893Smrg info->dri->textureSize = 0; 680209ff23fSmrg } 681209ff23fSmrg } else 682209ff23fSmrg#endif /* XF86DRI */ 683209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 684209ff23fSmrg "Will use %d kb for front buffer at offset 0x%08x\n", 685209ff23fSmrg screen_size / 1024, 0); 686209ff23fSmrg 687209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 688209ff23fSmrg "Will use %ld kb for X Server offscreen at offset 0x%08lx\n", 689b7e1c893Smrg (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) / 690b7e1c893Smrg 1024, info->accel_state->exa->offScreenBase); 691209ff23fSmrg 692209ff23fSmrg return TRUE; 693209ff23fSmrg} 694209ff23fSmrg 695209ff23fSmrg#ifdef XF86DRI 696209ff23fSmrg 697209ff23fSmrg#ifndef ExaOffscreenMarkUsed 698209ff23fSmrgextern void ExaOffscreenMarkUsed(PixmapPtr); 699209ff23fSmrg#endif 700209ff23fSmrg 701209ff23fSmrgunsigned long long 702209ff23fSmrgRADEONTexOffsetStart(PixmapPtr pPix) 703209ff23fSmrg{ 704b7e1c893Smrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 705b7e1c893Smrg unsigned long long offset; 706ad43ddacSmrg 707ad43ddacSmrg if (exaGetPixmapDriverPrivate(pPix)) 708ad43ddacSmrg return -1; 709ad43ddacSmrg 710209ff23fSmrg exaMoveInPixmap(pPix); 711209ff23fSmrg ExaOffscreenMarkUsed(pPix); 712209ff23fSmrg 713b7e1c893Smrg offset = exaGetPixmapOffset(pPix); 714b7e1c893Smrg 715b7e1c893Smrg if (offset > info->FbMapSize) 716b7e1c893Smrg return ~0ULL; 717b7e1c893Smrg else 718b7e1c893Smrg return info->fbLocation + offset; 719209ff23fSmrg} 720209ff23fSmrg#endif 721