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