radeon_exa.c revision de2362d3
1de2362d3Smrg/* 2de2362d3Smrg * Copyright 2005 Eric Anholt 3de2362d3Smrg * Copyright 2005 Benjamin Herrenschmidt 4de2362d3Smrg * All Rights Reserved. 5de2362d3Smrg * 6de2362d3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7de2362d3Smrg * copy of this software and associated documentation files (the "Software"), 8de2362d3Smrg * to deal in the Software without restriction, including without limitation 9de2362d3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10de2362d3Smrg * and/or sell copies of the Software, and to permit persons to whom the 11de2362d3Smrg * Software is furnished to do so, subject to the following conditions: 12de2362d3Smrg * 13de2362d3Smrg * The above copyright notice and this permission notice (including the next 14de2362d3Smrg * paragraph) shall be included in all copies or substantial portions of the 15de2362d3Smrg * Software. 16de2362d3Smrg * 17de2362d3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18de2362d3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19de2362d3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20de2362d3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21de2362d3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22de2362d3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23de2362d3Smrg * SOFTWARE. 24de2362d3Smrg * 25de2362d3Smrg * Authors: 26de2362d3Smrg * Eric Anholt <anholt@FreeBSD.org> 27de2362d3Smrg * Zack Rusin <zrusin@trolltech.com> 28de2362d3Smrg * Benjamin Herrenschmidt <benh@kernel.crashing.org> 29de2362d3Smrg * 30de2362d3Smrg */ 31de2362d3Smrg 32de2362d3Smrg#ifdef HAVE_CONFIG_H 33de2362d3Smrg#include "config.h" 34de2362d3Smrg#endif 35de2362d3Smrg 36de2362d3Smrg#include "radeon.h" 37de2362d3Smrg#include "radeon_reg.h" 38de2362d3Smrg#include "r600_reg.h" 39de2362d3Smrg#include "radeon_bo_helper.h" 40de2362d3Smrg#include "radeon_probe.h" 41de2362d3Smrg#include "radeon_version.h" 42de2362d3Smrg#include "radeon_exa_shared.h" 43de2362d3Smrg#include "xf86.h" 44de2362d3Smrg 45de2362d3Smrg 46de2362d3Smrg/***********************************************************************/ 47de2362d3Smrg#define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn = xf86ScreenToScrn(pScr); \ 48de2362d3Smrg RADEONInfoPtr info = RADEONPTR(pScrn) 49de2362d3Smrg 50de2362d3Smrgstatic struct { 51de2362d3Smrg int rop; 52de2362d3Smrg int pattern; 53de2362d3Smrg} RADEON_ROP[] = { 54de2362d3Smrg { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear */ 55de2362d3Smrg { RADEON_ROP3_DSa, RADEON_ROP3_DPa }, /* Gxand */ 56de2362d3Smrg { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse */ 57de2362d3Smrg { RADEON_ROP3_S, RADEON_ROP3_P }, /* GXcopy */ 58de2362d3Smrg { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted */ 59de2362d3Smrg { RADEON_ROP3_D, RADEON_ROP3_D }, /* GXnoop */ 60de2362d3Smrg { RADEON_ROP3_DSx, RADEON_ROP3_DPx }, /* GXxor */ 61de2362d3Smrg { RADEON_ROP3_DSo, RADEON_ROP3_DPo }, /* GXor */ 62de2362d3Smrg { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor */ 63de2362d3Smrg { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv */ 64de2362d3Smrg { RADEON_ROP3_Dn, RADEON_ROP3_Dn }, /* GXinvert */ 65de2362d3Smrg { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse */ 66de2362d3Smrg { RADEON_ROP3_Sn, RADEON_ROP3_Pn }, /* GXcopyInverted */ 67de2362d3Smrg { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted */ 68de2362d3Smrg { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand */ 69de2362d3Smrg { RADEON_ROP3_ONE, RADEON_ROP3_ONE } /* GXset */ 70de2362d3Smrg}; 71de2362d3Smrg 72de2362d3Smrgstatic __inline__ uint32_t F_TO_DW(float val) 73de2362d3Smrg{ 74de2362d3Smrg union { 75de2362d3Smrg float f; 76de2362d3Smrg uint32_t l; 77de2362d3Smrg } tmp; 78de2362d3Smrg tmp.f = val; 79de2362d3Smrg return tmp.l; 80de2362d3Smrg} 81de2362d3Smrg 82de2362d3Smrg 83de2362d3Smrg/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we 84de2362d3Smrg * require src and dest datatypes to be equal. 85de2362d3Smrg */ 86de2362d3SmrgBool RADEONGetDatatypeBpp(int bpp, uint32_t *type) 87de2362d3Smrg{ 88de2362d3Smrg switch (bpp) { 89de2362d3Smrg case 8: 90de2362d3Smrg *type = ATI_DATATYPE_CI8; 91de2362d3Smrg return TRUE; 92de2362d3Smrg case 16: 93de2362d3Smrg *type = ATI_DATATYPE_RGB565; 94de2362d3Smrg return TRUE; 95de2362d3Smrg case 24: 96de2362d3Smrg *type = ATI_DATATYPE_CI8; 97de2362d3Smrg return TRUE; 98de2362d3Smrg case 32: 99de2362d3Smrg *type = ATI_DATATYPE_ARGB8888; 100de2362d3Smrg return TRUE; 101de2362d3Smrg default: 102de2362d3Smrg RADEON_FALLBACK(("Unsupported bpp: %d\n", bpp)); 103de2362d3Smrg return FALSE; 104de2362d3Smrg } 105de2362d3Smrg} 106de2362d3Smrg 107de2362d3Smrgstatic Bool RADEONPixmapIsColortiled(PixmapPtr pPix) 108de2362d3Smrg{ 109de2362d3Smrg return FALSE; 110de2362d3Smrg} 111de2362d3Smrg 112de2362d3Smrgstatic Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset, 113de2362d3Smrg unsigned int offset, unsigned int pitch) 114de2362d3Smrg{ 115de2362d3Smrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 116de2362d3Smrg 117de2362d3Smrg if (pitch > 16320 || pitch % info->accel_state->exa->pixmapPitchAlign != 0) 118de2362d3Smrg RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch)); 119de2362d3Smrg 120de2362d3Smrg if (offset % info->accel_state->exa->pixmapOffsetAlign != 0) 121de2362d3Smrg RADEON_FALLBACK(("Bad offset 0x%08x\n", offset)); 122de2362d3Smrg 123de2362d3Smrg pitch = pitch >> 6; 124de2362d3Smrg *pitch_offset = (pitch << 22) | (offset >> 10); 125de2362d3Smrg 126de2362d3Smrg /* If it's the front buffer, we've got to note that it's tiled? */ 127de2362d3Smrg if (RADEONPixmapIsColortiled(pPix)) 128de2362d3Smrg *pitch_offset |= RADEON_DST_TILE_MACRO; 129de2362d3Smrg return TRUE; 130de2362d3Smrg} 131de2362d3Smrg 132de2362d3SmrgBool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) 133de2362d3Smrg{ 134de2362d3Smrg uint32_t pitch; 135de2362d3Smrg int bpp; 136de2362d3Smrg 137de2362d3Smrg bpp = pPix->drawable.bitsPerPixel; 138de2362d3Smrg if (bpp == 24) 139de2362d3Smrg bpp = 8; 140de2362d3Smrg 141de2362d3Smrg pitch = exaGetPixmapPitch(pPix); 142de2362d3Smrg 143de2362d3Smrg return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, 0, pitch); 144de2362d3Smrg} 145de2362d3Smrg 146de2362d3Smrg/** 147de2362d3Smrg * Returns whether the provided transform is affine. 148de2362d3Smrg * 149de2362d3Smrg * transform may be null. 150de2362d3Smrg */ 151de2362d3SmrgBool radeon_transform_is_affine_or_scaled(PictTransformPtr t) 152de2362d3Smrg{ 153de2362d3Smrg if (t == NULL) 154de2362d3Smrg return TRUE; 155de2362d3Smrg /* the shaders don't handle scaling either */ 156de2362d3Smrg return t->matrix[2][0] == 0 && t->matrix[2][1] == 0 && t->matrix[2][2] == IntToxFixed(1); 157de2362d3Smrg} 158de2362d3Smrg 159de2362d3SmrgBool RADEONPrepareAccess_CS(PixmapPtr pPix, int index) 160de2362d3Smrg{ 161de2362d3Smrg ScreenPtr pScreen = pPix->drawable.pScreen; 162de2362d3Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 163de2362d3Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 164de2362d3Smrg struct radeon_exa_pixmap_priv *driver_priv; 165de2362d3Smrg uint32_t possible_domains = ~0U; 166de2362d3Smrg uint32_t current_domain = 0; 167de2362d3Smrg Bool can_fail = !(pPix->drawable.bitsPerPixel < 8) && 168de2362d3Smrg pPix != pScreen->GetScreenPixmap(pScreen); 169de2362d3Smrg Bool flush = FALSE; 170de2362d3Smrg int ret; 171de2362d3Smrg 172de2362d3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 173de2362d3Smrg /* May need to handle byte swapping in DownloadFrom/UploadToScreen */ 174de2362d3Smrg if (pPix->drawable.bitsPerPixel > 8) 175de2362d3Smrg return FALSE; 176de2362d3Smrg#endif 177de2362d3Smrg 178de2362d3Smrg driver_priv = exaGetPixmapDriverPrivate(pPix); 179de2362d3Smrg if (!driver_priv) 180de2362d3Smrg return FALSE; 181de2362d3Smrg 182de2362d3Smrg /* untile in DFS/UTS */ 183de2362d3Smrg if (driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO)) 184de2362d3Smrg return FALSE; 185de2362d3Smrg 186de2362d3Smrg /* if we have more refs than just the BO then flush */ 187de2362d3Smrg if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { 188de2362d3Smrg flush = TRUE; 189de2362d3Smrg 190de2362d3Smrg if (can_fail) { 191de2362d3Smrg possible_domains = radeon_bo_get_src_domain(driver_priv->bo); 192de2362d3Smrg if (possible_domains == RADEON_GEM_DOMAIN_VRAM) 193de2362d3Smrg return FALSE; /* use DownloadFromScreen */ 194de2362d3Smrg } 195de2362d3Smrg } 196de2362d3Smrg 197de2362d3Smrg /* if the BO might end up in VRAM, prefer DownloadFromScreen */ 198de2362d3Smrg if (can_fail && (possible_domains & RADEON_GEM_DOMAIN_VRAM)) { 199de2362d3Smrg radeon_bo_is_busy(driver_priv->bo, ¤t_domain); 200de2362d3Smrg 201de2362d3Smrg if (current_domain & possible_domains) { 202de2362d3Smrg if (current_domain == RADEON_GEM_DOMAIN_VRAM) 203de2362d3Smrg return FALSE; 204de2362d3Smrg } else if (possible_domains & RADEON_GEM_DOMAIN_VRAM) 205de2362d3Smrg return FALSE; 206de2362d3Smrg } 207de2362d3Smrg 208de2362d3Smrg if (flush) 209de2362d3Smrg radeon_cs_flush_indirect(pScrn); 210de2362d3Smrg 211de2362d3Smrg /* flush IB */ 212de2362d3Smrg ret = radeon_bo_map(driver_priv->bo, 1); 213de2362d3Smrg if (ret) { 214de2362d3Smrg FatalError("failed to map pixmap %d\n", ret); 215de2362d3Smrg return FALSE; 216de2362d3Smrg } 217de2362d3Smrg driver_priv->bo_mapped = TRUE; 218de2362d3Smrg 219de2362d3Smrg pPix->devPrivate.ptr = driver_priv->bo->ptr; 220de2362d3Smrg 221de2362d3Smrg return TRUE; 222de2362d3Smrg} 223de2362d3Smrg 224de2362d3Smrgvoid RADEONFinishAccess_CS(PixmapPtr pPix, int index) 225de2362d3Smrg{ 226de2362d3Smrg struct radeon_exa_pixmap_priv *driver_priv; 227de2362d3Smrg 228de2362d3Smrg driver_priv = exaGetPixmapDriverPrivate(pPix); 229de2362d3Smrg if (!driver_priv || !driver_priv->bo_mapped) 230de2362d3Smrg return; 231de2362d3Smrg 232de2362d3Smrg radeon_bo_unmap(driver_priv->bo); 233de2362d3Smrg driver_priv->bo_mapped = FALSE; 234de2362d3Smrg pPix->devPrivate.ptr = NULL; 235de2362d3Smrg} 236de2362d3Smrg 237de2362d3Smrg 238de2362d3Smrgvoid *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align) 239de2362d3Smrg{ 240de2362d3Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 241de2362d3Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 242de2362d3Smrg struct radeon_exa_pixmap_priv *new_priv; 243de2362d3Smrg 244de2362d3Smrg if (size != 0 && !info->exa_force_create && 245de2362d3Smrg info->exa_pixmaps == FALSE) 246de2362d3Smrg return NULL; 247de2362d3Smrg 248de2362d3Smrg new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv)); 249de2362d3Smrg if (!new_priv) 250de2362d3Smrg return NULL; 251de2362d3Smrg 252de2362d3Smrg if (size == 0) 253de2362d3Smrg return new_priv; 254de2362d3Smrg 255de2362d3Smrg new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, align, 256de2362d3Smrg RADEON_GEM_DOMAIN_VRAM, 0); 257de2362d3Smrg if (!new_priv->bo) { 258de2362d3Smrg free(new_priv); 259de2362d3Smrg ErrorF("Failed to alloc memory\n"); 260de2362d3Smrg return NULL; 261de2362d3Smrg } 262de2362d3Smrg 263de2362d3Smrg return new_priv; 264de2362d3Smrg 265de2362d3Smrg} 266de2362d3Smrg 267de2362d3Smrgvoid *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, 268de2362d3Smrg int depth, int usage_hint, int bitsPerPixel, 269de2362d3Smrg int *new_pitch) 270de2362d3Smrg{ 271de2362d3Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 272de2362d3Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 273de2362d3Smrg struct radeon_exa_pixmap_priv *new_priv; 274de2362d3Smrg 275de2362d3Smrg if (width != 0 && height != 0 && !info->exa_force_create && 276de2362d3Smrg info->exa_pixmaps == FALSE) 277de2362d3Smrg return NULL; 278de2362d3Smrg 279de2362d3Smrg new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv)); 280de2362d3Smrg if (!new_priv) { 281de2362d3Smrg return NULL; 282de2362d3Smrg } 283de2362d3Smrg 284de2362d3Smrg if (width == 0 || height == 0) { 285de2362d3Smrg return new_priv; 286de2362d3Smrg } 287de2362d3Smrg 288de2362d3Smrg new_priv->bo = radeon_alloc_pixmap_bo(pScrn, width, height, depth, 289de2362d3Smrg usage_hint, bitsPerPixel, new_pitch, 290de2362d3Smrg &new_priv->surface, 291de2362d3Smrg &new_priv->tiling_flags); 292de2362d3Smrg if (!new_priv->bo) { 293de2362d3Smrg free(new_priv); 294de2362d3Smrg ErrorF("Failed to alloc memory\n"); 295de2362d3Smrg return NULL; 296de2362d3Smrg } 297de2362d3Smrg 298de2362d3Smrg return new_priv; 299de2362d3Smrg} 300de2362d3Smrg 301de2362d3Smrgvoid RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) 302de2362d3Smrg{ 303de2362d3Smrg struct radeon_exa_pixmap_priv *driver_priv = driverPriv; 304de2362d3Smrg 305de2362d3Smrg if (!driverPriv) 306de2362d3Smrg return; 307de2362d3Smrg 308de2362d3Smrg if (driver_priv->bo) 309de2362d3Smrg radeon_bo_unref(driver_priv->bo); 310de2362d3Smrg free(driverPriv); 311de2362d3Smrg} 312de2362d3Smrg 313de2362d3Smrg#ifdef RADEON_PIXMAP_SHARING 314de2362d3SmrgBool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) 315de2362d3Smrg{ 316de2362d3Smrg struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); 317de2362d3Smrg 318de2362d3Smrg if (!radeon_share_pixmap_backing(driver_priv->bo, fd_handle)) 319de2362d3Smrg return FALSE; 320de2362d3Smrg 321de2362d3Smrg driver_priv->shared = TRUE; 322de2362d3Smrg return TRUE; 323de2362d3Smrg} 324de2362d3Smrg 325de2362d3SmrgBool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle) 326de2362d3Smrg{ 327de2362d3Smrg struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); 328de2362d3Smrg 329de2362d3Smrg if (!radeon_set_shared_pixmap_backing(ppix, fd_handle, &driver_priv->surface)) 330de2362d3Smrg return FALSE; 331de2362d3Smrg 332de2362d3Smrg driver_priv->shared = TRUE; 333de2362d3Smrg driver_priv->tiling_flags = 0; 334de2362d3Smrg return TRUE; 335de2362d3Smrg} 336de2362d3Smrg#endif 337de2362d3Smrg 338de2362d3Smrguint32_t radeon_get_pixmap_tiling(PixmapPtr pPix) 339de2362d3Smrg{ 340de2362d3Smrg struct radeon_exa_pixmap_priv *driver_priv; 341de2362d3Smrg driver_priv = exaGetPixmapDriverPrivate(pPix); 342de2362d3Smrg return driver_priv->tiling_flags; 343de2362d3Smrg} 344de2362d3Smrg 345de2362d3SmrgBool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix) 346de2362d3Smrg{ 347de2362d3Smrg struct radeon_exa_pixmap_priv *driver_priv; 348de2362d3Smrg 349de2362d3Smrg driver_priv = exaGetPixmapDriverPrivate(pPix); 350de2362d3Smrg 351de2362d3Smrg if (!driver_priv) 352de2362d3Smrg return FALSE; 353de2362d3Smrg if (driver_priv->bo) 354de2362d3Smrg return TRUE; 355de2362d3Smrg return FALSE; 356de2362d3Smrg} 357de2362d3Smrg 358de2362d3Smrg#define ENTER_DRAW(x) TRACE 359de2362d3Smrg#define LEAVE_DRAW(x) TRACE 360de2362d3Smrg/***********************************************************************/ 361de2362d3Smrg 362de2362d3Smrg#ifdef RENDER 363de2362d3Smrg#include "radeon_exa_render.c" 364de2362d3Smrg#endif 365de2362d3Smrg#include "radeon_exa_funcs.c" 366de2362d3Smrg 367de2362d3Smrg 368de2362d3Smrg 369