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" 3918781e08Smrg#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{ 10918781e08Smrg 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{ 13418781e08Smrg 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 14318781e08Smrg 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{ 15339413783Smrg if (!t) 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) && 16818781e08Smrg 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 */ 17418781e08Smrg 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 */ 18739413783Smrg if (radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) { 188de2362d3Smrg flush = TRUE; 189de2362d3Smrg 190de2362d3Smrg if (can_fail) { 19139413783Smrg possible_domains = radeon_bo_get_src_domain(driver_priv->bo->bo.radeon); 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)) { 19939413783Smrg radeon_bo_is_busy(driver_priv->bo->bo.radeon, ¤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 */ 21239413783Smrg ret = radeon_bo_map(driver_priv->bo->bo.radeon, 1); 213de2362d3Smrg if (ret) { 214de2362d3Smrg FatalError("failed to map pixmap %d\n", ret); 215de2362d3Smrg return FALSE; 216de2362d3Smrg } 217de2362d3Smrg driver_priv->bo_mapped = TRUE; 218de2362d3Smrg 21939413783Smrg pPix->devPrivate.ptr = driver_priv->bo->bo.radeon->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 23239413783Smrg radeon_bo_unmap(driver_priv->bo->bo.radeon); 233de2362d3Smrg driver_priv->bo_mapped = FALSE; 234de2362d3Smrg pPix->devPrivate.ptr = NULL; 235de2362d3Smrg} 236de2362d3Smrg 237de2362d3Smrg 238de2362d3Smrgvoid *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, 239de2362d3Smrg int depth, int usage_hint, int bitsPerPixel, 240de2362d3Smrg int *new_pitch) 241de2362d3Smrg{ 242de2362d3Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 243de2362d3Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 244de2362d3Smrg struct radeon_exa_pixmap_priv *new_priv; 245de2362d3Smrg 24618781e08Smrg if (width != 0 && height != 0 && !info->exa_force_create && 24718781e08Smrg info->exa_pixmaps == FALSE) 24818781e08Smrg return NULL; 249de2362d3Smrg 250de2362d3Smrg new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv)); 251de2362d3Smrg if (!new_priv) { 252de2362d3Smrg return NULL; 253de2362d3Smrg } 254de2362d3Smrg 25518781e08Smrg if (width == 0 || height == 0) { 256de2362d3Smrg return new_priv; 257de2362d3Smrg } 258de2362d3Smrg 25918781e08Smrg new_priv->bo = radeon_alloc_pixmap_bo(pScrn, width, height, depth, 26018781e08Smrg usage_hint, bitsPerPixel, new_pitch, 26118781e08Smrg &new_priv->surface, 26218781e08Smrg &new_priv->tiling_flags); 263de2362d3Smrg if (!new_priv->bo) { 264de2362d3Smrg free(new_priv); 265de2362d3Smrg ErrorF("Failed to alloc memory\n"); 266de2362d3Smrg return NULL; 267de2362d3Smrg } 268de2362d3Smrg 269de2362d3Smrg return new_priv; 270de2362d3Smrg} 271de2362d3Smrg 272de2362d3Smrgvoid RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) 273de2362d3Smrg{ 2748bf5c682Smrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(xf86ScreenToScrn(pScreen)); 275de2362d3Smrg struct radeon_exa_pixmap_priv *driver_priv = driverPriv; 276de2362d3Smrg 277de2362d3Smrg if (!driverPriv) 278de2362d3Smrg return; 279de2362d3Smrg 28039413783Smrg radeon_buffer_unref(&driver_priv->bo); 2818bf5c682Smrg drmmode_fb_reference(pRADEONEnt->fd, &driver_priv->fb, NULL); 282de2362d3Smrg free(driverPriv); 283de2362d3Smrg} 284de2362d3Smrg 2850a1d3ae0SmrgBool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr seconndary, void **fd_handle) 286de2362d3Smrg{ 28718781e08Smrg struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); 28818781e08Smrg 28939413783Smrg if (!radeon_share_pixmap_backing(driver_priv->bo->bo.radeon, fd_handle)) 29018781e08Smrg return FALSE; 29118781e08Smrg 29218781e08Smrg driver_priv->shared = TRUE; 29318781e08Smrg return TRUE; 294de2362d3Smrg} 295de2362d3Smrg 29618781e08SmrgBool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle) 297de2362d3Smrg{ 29818781e08Smrg struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); 29939413783Smrg int ihandle = (int)(long)fd_handle; 30018781e08Smrg 30118781e08Smrg if (!radeon_set_shared_pixmap_backing(ppix, fd_handle, &driver_priv->surface)) 30218781e08Smrg return FALSE; 30318781e08Smrg 30439413783Smrg driver_priv->shared = ihandle != -1; 30518781e08Smrg return TRUE; 306de2362d3Smrg} 307de2362d3Smrg 308de2362d3Smrguint32_t radeon_get_pixmap_tiling(PixmapPtr pPix) 309de2362d3Smrg{ 310de2362d3Smrg struct radeon_exa_pixmap_priv *driver_priv; 311de2362d3Smrg driver_priv = exaGetPixmapDriverPrivate(pPix); 312de2362d3Smrg return driver_priv->tiling_flags; 313de2362d3Smrg} 314de2362d3Smrg 315de2362d3SmrgBool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix) 316de2362d3Smrg{ 317de2362d3Smrg struct radeon_exa_pixmap_priv *driver_priv; 318de2362d3Smrg 319de2362d3Smrg driver_priv = exaGetPixmapDriverPrivate(pPix); 320de2362d3Smrg 321de2362d3Smrg if (!driver_priv) 322de2362d3Smrg return FALSE; 323de2362d3Smrg if (driver_priv->bo) 324de2362d3Smrg return TRUE; 325de2362d3Smrg return FALSE; 326de2362d3Smrg} 327de2362d3Smrg 328de2362d3Smrg#define ENTER_DRAW(x) TRACE 329de2362d3Smrg#define LEAVE_DRAW(x) TRACE 330de2362d3Smrg/***********************************************************************/ 331de2362d3Smrg 332de2362d3Smrg#ifdef RENDER 333de2362d3Smrg#include "radeon_exa_render.c" 334de2362d3Smrg#endif 335de2362d3Smrg#include "radeon_exa_funcs.c" 336de2362d3Smrg 337de2362d3Smrg 338de2362d3Smrg 339