radeon_exa_funcs.c revision de2362d3
1/* 2 * Copyright 2005 Eric Anholt 3 * Copyright 2005 Benjamin Herrenschmidt 4 * Copyright 2006 Tungsten Graphics, Inc. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the next 15 * paragraph) shall be included in all copies or substantial portions of the 16 * Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 * SOFTWARE. 25 * 26 * Authors: 27 * Eric Anholt <anholt@FreeBSD.org> 28 * Zack Rusin <zrusin@trolltech.com> 29 * Benjamin Herrenschmidt <benh@kernel.crashing.org> 30 * Michel Dänzer <michel@daenzer.net> 31 * 32 */ 33 34#include <errno.h> 35#include <string.h> 36 37#include "radeon.h" 38 39#include "exa.h" 40 41static int 42RADEONMarkSync(ScreenPtr pScreen) 43{ 44 RINFO_FROM_SCREEN(pScreen); 45 46 TRACE; 47 48 return ++info->accel_state->exaSyncMarker; 49} 50 51static void 52RADEONSync(ScreenPtr pScreen, int marker) 53{ 54 55} 56 57static void Emit2DState(ScrnInfoPtr pScrn, int op) 58{ 59 RADEONInfoPtr info = RADEONPTR(pScrn); 60 int has_src; 61 62 /* don't emit if no operation in progress */ 63 if (info->state_2d.op == 0 && op == 0) 64 return; 65 66 has_src = info->state_2d.src_pitch_offset || info->state_2d.src_bo; 67 68 if (has_src) { 69 BEGIN_ACCEL_RELOC(10, 2); 70 } else { 71 BEGIN_ACCEL_RELOC(9, 1); 72 } 73 OUT_RING_REG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right); 74 OUT_RING_REG(RADEON_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl); 75 OUT_RING_REG(RADEON_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr); 76 OUT_RING_REG(RADEON_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr); 77 OUT_RING_REG(RADEON_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr); 78 OUT_RING_REG(RADEON_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr); 79 OUT_RING_REG(RADEON_DP_WRITE_MASK, info->state_2d.dp_write_mask); 80 OUT_RING_REG(RADEON_DP_CNTL, info->state_2d.dp_cntl); 81 82 OUT_RING_REG(RADEON_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset); 83 OUT_RING_RELOC(info->state_2d.dst_bo, 0, info->state_2d.dst_domain); 84 85 if (has_src) { 86 OUT_RING_REG(RADEON_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset); 87 OUT_RING_RELOC(info->state_2d.src_bo, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); 88 } 89 ADVANCE_RING(); 90 91 if (op) 92 info->state_2d.op = op; 93 info->reemit_current2d = Emit2DState; 94} 95 96static void 97RADEONFlush2D(PixmapPtr pPix) 98{ 99 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 100 101 TRACE; 102 103 BEGIN_RING(2*2); 104 OUT_RING_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL); 105 OUT_RING_REG(RADEON_WAIT_UNTIL, 106 RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); 107 ADVANCE_RING(); 108} 109 110static void 111RADEONDone2D(PixmapPtr pPix) 112{ 113 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 114 info->state_2d.op = 0; 115 116 RADEONFlush2D(pPix); 117} 118 119static Bool 120RADEONPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) 121{ 122 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 123 uint32_t datatype, dst_pitch_offset; 124 struct radeon_exa_pixmap_priv *driver_priv; 125 int ret; 126 127 TRACE; 128 129 if (pPix->drawable.bitsPerPixel == 24) 130 RADEON_FALLBACK(("24bpp unsupported\n")); 131 if (!RADEONGetDatatypeBpp(pPix->drawable.bitsPerPixel, &datatype)) 132 RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); 133 if (!RADEONGetPixmapOffsetPitch(pPix, &dst_pitch_offset)) 134 RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n")); 135 136 RADEON_SWITCH_TO_2D(); 137 138 radeon_cs_space_reset_bos(info->cs); 139 140 driver_priv = exaGetPixmapDriverPrivate(pPix); 141 radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); 142 143 ret = radeon_cs_space_check(info->cs); 144 if (ret) 145 RADEON_FALLBACK(("Not enough RAM to hw accel solid operation\n")); 146 147 driver_priv = exaGetPixmapDriverPrivate(pPix); 148 if (driver_priv) { 149 info->state_2d.dst_bo = driver_priv->bo; 150 info->state_2d.dst_domain = driver_priv->shared ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM; 151 } 152 153 info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX | 154 RADEON_DEFAULT_SC_BOTTOM_MAX); 155 info->state_2d.dp_brush_bkgd_clr = 0x00000000; 156 info->state_2d.dp_src_frgd_clr = 0xffffffff; 157 info->state_2d.dp_src_bkgd_clr = 0x00000000; 158 info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | 159 RADEON_GMC_BRUSH_SOLID_COLOR | 160 (datatype << 8) | 161 RADEON_GMC_SRC_DATATYPE_COLOR | 162 RADEON_ROP[alu].pattern | 163 RADEON_GMC_CLR_CMP_CNTL_DIS); 164 info->state_2d.dp_brush_frgd_clr = fg; 165 info->state_2d.dp_cntl = (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM); 166 info->state_2d.dp_write_mask = pm; 167 info->state_2d.dst_pitch_offset = dst_pitch_offset; 168 info->state_2d.src_pitch_offset = 0; 169 info->state_2d.src_bo = NULL; 170 171 info->accel_state->dst_pix = pPix; 172 173 Emit2DState(pScrn, RADEON_2D_EXA_SOLID); 174 175 return TRUE; 176} 177 178 179static void 180RADEONSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2) 181{ 182 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 183 184 TRACE; 185 186 if (CS_FULL(info->cs)) { 187 RADEONFlush2D(info->accel_state->dst_pix); 188 radeon_cs_flush_indirect(pScrn); 189 } 190 191 if (info->accel_state->vsync) 192 RADEONWaitForVLine(pScrn, pPix, 193 radeon_pick_best_crtc(pScrn, FALSE, x1, x2, y1, y2), 194 y1, y2); 195 196 BEGIN_RING(2*2); 197 OUT_RING_REG(RADEON_DST_Y_X, (y1 << 16) | x1); 198 OUT_RING_REG(RADEON_DST_HEIGHT_WIDTH, ((y2 - y1) << 16) | (x2 - x1)); 199 ADVANCE_RING(); 200} 201 202static void 203RADEONDoPrepareCopy(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, 204 uint32_t dst_pitch_offset, uint32_t datatype, int rop, 205 Pixel planemask) 206{ 207 RADEONInfoPtr info = RADEONPTR(pScrn); 208 209 /* setup 2D state */ 210 info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | 211 RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 212 RADEON_GMC_BRUSH_NONE | 213 (datatype << 8) | 214 RADEON_GMC_SRC_DATATYPE_COLOR | 215 RADEON_ROP[rop].rop | 216 RADEON_DP_SRC_SOURCE_MEMORY | 217 RADEON_GMC_CLR_CMP_CNTL_DIS); 218 info->state_2d.dp_cntl = ((info->accel_state->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) | 219 (info->accel_state->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)); 220 info->state_2d.dp_brush_frgd_clr = 0xffffffff; 221 info->state_2d.dp_brush_bkgd_clr = 0x00000000; 222 info->state_2d.dp_src_frgd_clr = 0xffffffff; 223 info->state_2d.dp_src_bkgd_clr = 0x00000000; 224 info->state_2d.dp_write_mask = planemask; 225 info->state_2d.dst_pitch_offset = dst_pitch_offset; 226 info->state_2d.src_pitch_offset = src_pitch_offset; 227 info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX 228 | RADEON_DEFAULT_SC_BOTTOM_MAX); 229 230 Emit2DState(pScrn, RADEON_2D_EXA_COPY); 231} 232 233static Bool 234RADEONPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, 235 int xdir, int ydir, 236 int rop, 237 Pixel planemask) 238{ 239 RINFO_FROM_SCREEN(pDst->drawable.pScreen); 240 uint32_t datatype, src_pitch_offset, dst_pitch_offset; 241 struct radeon_exa_pixmap_priv *driver_priv; 242 int ret; 243 TRACE; 244 245 if (pDst->drawable.bitsPerPixel == 24) 246 RADEON_FALLBACK(("24bpp unsupported")); 247 if (!RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype)) 248 RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); 249 if (!RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset)) 250 RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n")); 251 if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset)) 252 RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n")); 253 254 RADEON_SWITCH_TO_2D(); 255 256 radeon_cs_space_reset_bos(info->cs); 257 258 driver_priv = exaGetPixmapDriverPrivate(pSrc); 259 radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); 260 info->state_2d.src_bo = driver_priv->bo; 261 262 driver_priv = exaGetPixmapDriverPrivate(pDst); 263 info->state_2d.dst_bo = driver_priv->bo; 264 info->state_2d.dst_domain = driver_priv->shared ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM; 265 radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, info->state_2d.dst_domain); 266 267 ret = radeon_cs_space_check(info->cs); 268 if (ret) 269 RADEON_FALLBACK(("Not enough RAM to hw accel copy operation\n")); 270 271 info->accel_state->xdir = xdir; 272 info->accel_state->ydir = ydir; 273 info->accel_state->dst_pix = pDst; 274 275 RADEONDoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, 276 datatype, rop, planemask); 277 278 return TRUE; 279} 280 281static void 282RADEONCopy(PixmapPtr pDst, 283 int srcX, int srcY, 284 int dstX, int dstY, 285 int w, int h) 286{ 287 RINFO_FROM_SCREEN(pDst->drawable.pScreen); 288 289 TRACE; 290 291 if (CS_FULL(info->cs)) { 292 RADEONFlush2D(info->accel_state->dst_pix); 293 radeon_cs_flush_indirect(pScrn); 294 } 295 296 if (info->accel_state->xdir < 0) { 297 srcX += w - 1; 298 dstX += w - 1; 299 } 300 if (info->accel_state->ydir < 0) { 301 srcY += h - 1; 302 dstY += h - 1; 303 } 304 305 if (info->accel_state->vsync) 306 RADEONWaitForVLine(pScrn, pDst, 307 radeon_pick_best_crtc(pScrn, FALSE, dstX, dstX + w, dstY, dstY + h), 308 dstY, dstY + h); 309 310 BEGIN_RING(2*3); 311 312 OUT_RING_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX); 313 OUT_RING_REG(RADEON_DST_Y_X, (dstY << 16) | dstX); 314 OUT_RING_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); 315 316 ADVANCE_RING(); 317} 318 319/* Emit blit with arbitrary source and destination offsets and pitches */ 320static void 321RADEONBlitChunk(ScrnInfoPtr pScrn, struct radeon_bo *src_bo, 322 struct radeon_bo *dst_bo, uint32_t datatype, 323 uint32_t src_pitch_offset, uint32_t dst_pitch_offset, 324 int srcX, int srcY, int dstX, int dstY, int w, int h, 325 uint32_t src_domain, uint32_t dst_domain) 326{ 327 RADEONInfoPtr info = RADEONPTR(pScrn); 328 329 if (src_bo && dst_bo) { 330 BEGIN_ACCEL_RELOC(6, 2); 331 } else if (src_bo && dst_bo == NULL) { 332 BEGIN_ACCEL_RELOC(6, 1); 333 } else { 334 BEGIN_RING(2*6); 335 } 336 OUT_RING_REG(RADEON_DP_GUI_MASTER_CNTL, 337 RADEON_GMC_DST_PITCH_OFFSET_CNTL | 338 RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 339 RADEON_GMC_BRUSH_NONE | 340 (datatype << 8) | 341 RADEON_GMC_SRC_DATATYPE_COLOR | 342 RADEON_ROP3_S | 343 RADEON_DP_SRC_SOURCE_MEMORY | 344 RADEON_GMC_CLR_CMP_CNTL_DIS | 345 RADEON_GMC_WR_MSK_DIS); 346 OUT_RING_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset); 347 if (src_bo) { 348 OUT_RING_RELOC(src_bo, src_domain, 0); 349 } 350 OUT_RING_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); 351 if (dst_bo) { 352 OUT_RING_RELOC(dst_bo, 0, dst_domain); 353 } 354 OUT_RING_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX); 355 OUT_RING_REG(RADEON_DST_Y_X, (dstY << 16) | dstX); 356 OUT_RING_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); 357 ADVANCE_RING(); 358 BEGIN_RING(2*2); 359 OUT_RING_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL); 360 OUT_RING_REG(RADEON_WAIT_UNTIL, 361 RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); 362 ADVANCE_RING(); 363} 364 365static Bool 366RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h, 367 char *src, int src_pitch) 368{ 369 ScreenPtr pScreen = pDst->drawable.pScreen; 370 RINFO_FROM_SCREEN(pScreen); 371 struct radeon_exa_pixmap_priv *driver_priv; 372 struct radeon_bo *scratch = NULL; 373 struct radeon_bo *copy_dst; 374 unsigned char *dst; 375 unsigned size; 376 uint32_t datatype = 0; 377 uint32_t dst_domain; 378 uint32_t dst_pitch_offset; 379 unsigned bpp = pDst->drawable.bitsPerPixel; 380 uint32_t scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64); 381 uint32_t copy_pitch; 382 uint32_t swap = RADEON_HOST_DATA_SWAP_NONE; 383 int ret; 384 Bool flush = TRUE; 385 Bool r; 386 int i; 387 388 if (bpp < 8) 389 return FALSE; 390 391 driver_priv = exaGetPixmapDriverPrivate(pDst); 392 if (!driver_priv || !driver_priv->bo) 393 return FALSE; 394 395#if X_BYTE_ORDER == X_BIG_ENDIAN 396 switch (bpp) { 397 case 32: 398 swap = RADEON_HOST_DATA_SWAP_32BIT; 399 break; 400 case 16: 401 swap = RADEON_HOST_DATA_SWAP_16BIT; 402 break; 403 } 404#endif 405 406 /* If we know the BO won't be busy / in VRAM, don't bother with a scratch */ 407 copy_dst = driver_priv->bo; 408 copy_pitch = pDst->devKind; 409 if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { 410 if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { 411 flush = FALSE; 412 if (!radeon_bo_is_busy(driver_priv->bo, &dst_domain) && 413 !(dst_domain & RADEON_GEM_DOMAIN_VRAM)) 414 goto copy; 415 } 416 /* use cpu copy for fast fb access */ 417 if (info->is_fast_fb) 418 goto copy; 419 } 420 421 size = scratch_pitch * h; 422 scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); 423 if (scratch == NULL) { 424 goto copy; 425 } 426 radeon_cs_space_reset_bos(info->cs); 427 radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM); 428 radeon_cs_space_add_persistent_bo(info->cs, scratch, RADEON_GEM_DOMAIN_GTT, 0); 429 ret = radeon_cs_space_check(info->cs); 430 if (ret) { 431 goto copy; 432 } 433 copy_dst = scratch; 434 copy_pitch = scratch_pitch; 435 flush = FALSE; 436 437copy: 438 if (flush) 439 radeon_cs_flush_indirect(pScrn); 440 441 ret = radeon_bo_map(copy_dst, 0); 442 if (ret) { 443 r = FALSE; 444 goto out; 445 } 446 r = TRUE; 447 size = w * bpp / 8; 448 dst = copy_dst->ptr; 449 if (copy_dst == driver_priv->bo) 450 dst += y * copy_pitch + x * bpp / 8; 451 for (i = 0; i < h; i++) { 452 RADEONCopySwap(dst + i * copy_pitch, (uint8_t*)src, size, swap); 453 src += src_pitch; 454 } 455 radeon_bo_unmap(copy_dst); 456 457 if (copy_dst == scratch) { 458 RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype); 459 RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset); 460 RADEON_SWITCH_TO_2D(); 461 RADEONBlitChunk(pScrn, scratch, driver_priv->bo, datatype, scratch_pitch << 16, 462 dst_pitch_offset, 0, 0, x, y, w, h, 463 RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM); 464 } 465 466out: 467 if (scratch) 468 radeon_bo_unref(scratch); 469 return r; 470} 471 472static Bool 473RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, 474 int h, char *dst, int dst_pitch) 475{ 476 RINFO_FROM_SCREEN(pSrc->drawable.pScreen); 477 struct radeon_exa_pixmap_priv *driver_priv; 478 struct radeon_bo *scratch = NULL; 479 struct radeon_bo *copy_src; 480 unsigned size; 481 uint32_t datatype = 0; 482 uint32_t src_domain = 0; 483 uint32_t src_pitch_offset; 484 unsigned bpp = pSrc->drawable.bitsPerPixel; 485 uint32_t scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64); 486 uint32_t copy_pitch; 487 uint32_t swap = RADEON_HOST_DATA_SWAP_NONE; 488 int ret; 489 Bool flush = FALSE; 490 Bool r; 491 492 if (bpp < 8) 493 return FALSE; 494 495 driver_priv = exaGetPixmapDriverPrivate(pSrc); 496 if (!driver_priv || !driver_priv->bo) 497 return FALSE; 498 499#if X_BYTE_ORDER == X_BIG_ENDIAN 500 switch (bpp) { 501 case 32: 502 swap = RADEON_HOST_DATA_SWAP_32BIT; 503 break; 504 case 16: 505 swap = RADEON_HOST_DATA_SWAP_16BIT; 506 break; 507 } 508#endif 509 510 /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */ 511 copy_src = driver_priv->bo; 512 copy_pitch = pSrc->devKind; 513 if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { 514 if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { 515 src_domain = radeon_bo_get_src_domain(driver_priv->bo); 516 if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == 517 (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) 518 src_domain = 0; 519 else /* A write may be scheduled */ 520 flush = TRUE; 521 } 522 523 if (!src_domain) 524 radeon_bo_is_busy(driver_priv->bo, &src_domain); 525 526 if (src_domain & ~(uint32_t)RADEON_GEM_DOMAIN_VRAM) 527 goto copy; 528 } 529 size = scratch_pitch * h; 530 scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); 531 if (scratch == NULL) { 532 goto copy; 533 } 534 radeon_cs_space_reset_bos(info->cs); 535 radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); 536 radeon_cs_space_add_persistent_bo(info->cs, scratch, 0, RADEON_GEM_DOMAIN_GTT); 537 ret = radeon_cs_space_check(info->cs); 538 if (ret) { 539 goto copy; 540 } 541 RADEONGetDatatypeBpp(pSrc->drawable.bitsPerPixel, &datatype); 542 RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset); 543 RADEON_SWITCH_TO_2D(); 544 RADEONBlitChunk(pScrn, driver_priv->bo, scratch, datatype, src_pitch_offset, 545 scratch_pitch << 16, x, y, 0, 0, w, h, 546 RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 547 RADEON_GEM_DOMAIN_GTT); 548 copy_src = scratch; 549 copy_pitch = scratch_pitch; 550 flush = TRUE; 551 552copy: 553 if (flush) 554 FLUSH_RING(); 555 556 ret = radeon_bo_map(copy_src, 0); 557 if (ret) { 558 ErrorF("failed to map pixmap: %d\n", ret); 559 r = FALSE; 560 goto out; 561 } 562 r = TRUE; 563 w *= bpp / 8; 564 if (copy_src == driver_priv->bo) 565 size = y * copy_pitch + x * bpp / 8; 566 else 567 size = 0; 568 while (h--) { 569 RADEONCopySwap((uint8_t*)dst, copy_src->ptr + size, w, swap); 570 size += copy_pitch; 571 dst += dst_pitch; 572 } 573 radeon_bo_unmap(copy_src); 574out: 575 if (scratch) 576 radeon_bo_unref(scratch); 577 return r; 578} 579 580Bool RADEONDrawInit(ScreenPtr pScreen) 581{ 582 RINFO_FROM_SCREEN(pScreen); 583 584 if (info->accel_state->exa == NULL) { 585 xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map not set up\n"); 586 return FALSE; 587 } 588 589 info->accel_state->exa->exa_major = EXA_VERSION_MAJOR; 590 info->accel_state->exa->exa_minor = EXA_VERSION_MINOR; 591 592 info->accel_state->exa->PrepareSolid = RADEONPrepareSolid; 593 info->accel_state->exa->Solid = RADEONSolid; 594 info->accel_state->exa->DoneSolid = RADEONDone2D; 595 596 info->accel_state->exa->PrepareCopy = RADEONPrepareCopy; 597 info->accel_state->exa->Copy = RADEONCopy; 598 info->accel_state->exa->DoneCopy = RADEONDone2D; 599 600 info->accel_state->exa->MarkSync = RADEONMarkSync; 601 info->accel_state->exa->WaitMarker = RADEONSync; 602 603 info->accel_state->exa->UploadToScreen = &RADEONUploadToScreenCS; 604 info->accel_state->exa->DownloadFromScreen = &RADEONDownloadFromScreenCS; 605 606 info->accel_state->exa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_SUPPORTS_PREPARE_AUX | 607 EXA_SUPPORTS_OFFSCREEN_OVERLAPS | EXA_HANDLES_PIXMAPS | EXA_MIXED_PIXMAPS; 608 info->accel_state->exa->pixmapOffsetAlign = RADEON_GPU_PAGE_SIZE; 609 info->accel_state->exa->pixmapPitchAlign = 64; 610 611#ifdef RENDER 612 if (info->RenderAccel) { 613 if (IS_R300_3D || IS_R500_3D) { 614 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 615 "enabled for R300/R400/R500 type cards.\n"); 616 info->accel_state->exa->CheckComposite = R300CheckComposite; 617 info->accel_state->exa->PrepareComposite = 618 R300PrepareComposite; 619 info->accel_state->exa->Composite = RadeonComposite; 620 info->accel_state->exa->DoneComposite = RadeonDoneComposite; 621 } else if (IS_R200_3D) { 622 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 623 "enabled for R200 type cards.\n"); 624 info->accel_state->exa->CheckComposite = R200CheckComposite; 625 info->accel_state->exa->PrepareComposite = 626 R200PrepareComposite; 627 info->accel_state->exa->Composite = RadeonComposite; 628 info->accel_state->exa->DoneComposite = RadeonDoneComposite; 629 } else { 630 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 631 "enabled for R100 type cards.\n"); 632 info->accel_state->exa->CheckComposite = R100CheckComposite; 633 info->accel_state->exa->PrepareComposite = 634 R100PrepareComposite; 635 info->accel_state->exa->Composite = RadeonComposite; 636 info->accel_state->exa->DoneComposite = RadeonDoneComposite; 637 } 638 } 639#endif 640 641 info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap; 642 info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap; 643 info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen; 644 info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS; 645 info->accel_state->exa->FinishAccess = RADEONFinishAccess_CS; 646 info->accel_state->exa->CreatePixmap2 = RADEONEXACreatePixmap2; 647#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 6) 648 info->accel_state->exa->SharePixmapBacking = RADEONEXASharePixmapBacking; 649 info->accel_state->exa->SetSharedPixmapBacking = RADEONEXASetSharedPixmapBacking; 650#endif 651 652 653 info->accel_state->exa->maxPitchBytes = 16320; 654 info->accel_state->exa->maxX = 8191; 655 info->accel_state->exa->maxY = 8191; 656 657 if (xf86ReturnOptValBool(info->Options, OPTION_EXA_VSYNC, FALSE)) { 658 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA VSync enabled\n"); 659 info->accel_state->vsync = TRUE; 660 } else 661 info->accel_state->vsync = FALSE; 662 663 RADEONEngineInit(pScrn); 664 665 if (!exaDriverInit(pScreen, info->accel_state->exa)) { 666 free(info->accel_state->exa); 667 return FALSE; 668 } 669 exaMarkSync(pScreen); 670 671 return TRUE; 672} 673 674