radeon_exa_funcs.c revision 39413783
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->bo.radeon, 0, 142 RADEON_GEM_DOMAIN_VRAM); 143 144 ret = radeon_cs_space_check(info->cs); 145 if (ret) 146 RADEON_FALLBACK(("Not enough RAM to hw accel solid operation\n")); 147 148 driver_priv = exaGetPixmapDriverPrivate(pPix); 149 if (driver_priv) { 150 info->state_2d.dst_bo = driver_priv->bo->bo.radeon; 151 info->state_2d.dst_domain = driver_priv->shared ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM; 152 } 153 154 info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX | 155 RADEON_DEFAULT_SC_BOTTOM_MAX); 156 info->state_2d.dp_brush_bkgd_clr = 0x00000000; 157 info->state_2d.dp_src_frgd_clr = 0xffffffff; 158 info->state_2d.dp_src_bkgd_clr = 0x00000000; 159 info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | 160 RADEON_GMC_BRUSH_SOLID_COLOR | 161 (datatype << 8) | 162 RADEON_GMC_SRC_DATATYPE_COLOR | 163 RADEON_ROP[alu].pattern | 164 RADEON_GMC_CLR_CMP_CNTL_DIS); 165 info->state_2d.dp_brush_frgd_clr = fg; 166 info->state_2d.dp_cntl = (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM); 167 info->state_2d.dp_write_mask = pm; 168 info->state_2d.dst_pitch_offset = dst_pitch_offset; 169 info->state_2d.src_pitch_offset = 0; 170 info->state_2d.src_bo = NULL; 171 172 info->accel_state->dst_pix = pPix; 173 174 Emit2DState(pScrn, RADEON_2D_EXA_SOLID); 175 176 return TRUE; 177} 178 179 180static void 181RADEONSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2) 182{ 183 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 184 185 TRACE; 186 187 if (CS_FULL(info->cs)) { 188 RADEONFlush2D(info->accel_state->dst_pix); 189 radeon_cs_flush_indirect(pScrn); 190 } 191 192 if (info->accel_state->vsync) 193 RADEONWaitForVLine(pScrn, pPix, 194 radeon_pick_best_crtc(pScrn, FALSE, x1, x2, y1, y2), 195 y1, y2); 196 197 BEGIN_RING(2*2); 198 OUT_RING_REG(RADEON_DST_Y_X, (y1 << 16) | x1); 199 OUT_RING_REG(RADEON_DST_HEIGHT_WIDTH, ((y2 - y1) << 16) | (x2 - x1)); 200 ADVANCE_RING(); 201} 202 203static void 204RADEONDoPrepareCopy(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, 205 uint32_t dst_pitch_offset, uint32_t datatype, int rop, 206 Pixel planemask) 207{ 208 RADEONInfoPtr info = RADEONPTR(pScrn); 209 210 /* setup 2D state */ 211 info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | 212 RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 213 RADEON_GMC_BRUSH_NONE | 214 (datatype << 8) | 215 RADEON_GMC_SRC_DATATYPE_COLOR | 216 RADEON_ROP[rop].rop | 217 RADEON_DP_SRC_SOURCE_MEMORY | 218 RADEON_GMC_CLR_CMP_CNTL_DIS); 219 info->state_2d.dp_cntl = ((info->accel_state->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) | 220 (info->accel_state->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)); 221 info->state_2d.dp_brush_frgd_clr = 0xffffffff; 222 info->state_2d.dp_brush_bkgd_clr = 0x00000000; 223 info->state_2d.dp_src_frgd_clr = 0xffffffff; 224 info->state_2d.dp_src_bkgd_clr = 0x00000000; 225 info->state_2d.dp_write_mask = planemask; 226 info->state_2d.dst_pitch_offset = dst_pitch_offset; 227 info->state_2d.src_pitch_offset = src_pitch_offset; 228 info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX 229 | RADEON_DEFAULT_SC_BOTTOM_MAX); 230 231 Emit2DState(pScrn, RADEON_2D_EXA_COPY); 232} 233 234static Bool 235RADEONPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, 236 int xdir, int ydir, 237 int rop, 238 Pixel planemask) 239{ 240 RINFO_FROM_SCREEN(pDst->drawable.pScreen); 241 uint32_t datatype, src_pitch_offset, dst_pitch_offset; 242 struct radeon_exa_pixmap_priv *driver_priv; 243 int ret; 244 TRACE; 245 246 if (pDst->drawable.bitsPerPixel == 24) 247 RADEON_FALLBACK(("24bpp unsupported")); 248 if (!RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype)) 249 RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); 250 if (!RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset)) 251 RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n")); 252 if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset)) 253 RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n")); 254 255 RADEON_SWITCH_TO_2D(); 256 257 radeon_cs_space_reset_bos(info->cs); 258 259 driver_priv = exaGetPixmapDriverPrivate(pSrc); 260 radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 261 RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); 262 info->state_2d.src_bo = driver_priv->bo->bo.radeon; 263 264 driver_priv = exaGetPixmapDriverPrivate(pDst); 265 info->state_2d.dst_bo = driver_priv->bo->bo.radeon; 266 info->state_2d.dst_domain = driver_priv->shared ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM; 267 radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0, 268 info->state_2d.dst_domain); 269 270 ret = radeon_cs_space_check(info->cs); 271 if (ret) 272 RADEON_FALLBACK(("Not enough RAM to hw accel copy operation\n")); 273 274 info->accel_state->xdir = xdir; 275 info->accel_state->ydir = ydir; 276 info->accel_state->dst_pix = pDst; 277 278 RADEONDoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, 279 datatype, rop, planemask); 280 281 return TRUE; 282} 283 284static void 285RADEONCopy(PixmapPtr pDst, 286 int srcX, int srcY, 287 int dstX, int dstY, 288 int w, int h) 289{ 290 RINFO_FROM_SCREEN(pDst->drawable.pScreen); 291 292 TRACE; 293 294 if (CS_FULL(info->cs)) { 295 RADEONFlush2D(info->accel_state->dst_pix); 296 radeon_cs_flush_indirect(pScrn); 297 } 298 299 if (info->accel_state->xdir < 0) { 300 srcX += w - 1; 301 dstX += w - 1; 302 } 303 if (info->accel_state->ydir < 0) { 304 srcY += h - 1; 305 dstY += h - 1; 306 } 307 308 if (info->accel_state->vsync) 309 RADEONWaitForVLine(pScrn, pDst, 310 radeon_pick_best_crtc(pScrn, FALSE, dstX, dstX + w, dstY, dstY + h), 311 dstY, dstY + h); 312 313 BEGIN_RING(2*3); 314 315 OUT_RING_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX); 316 OUT_RING_REG(RADEON_DST_Y_X, (dstY << 16) | dstX); 317 OUT_RING_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); 318 319 ADVANCE_RING(); 320} 321 322/* Emit blit with arbitrary source and destination offsets and pitches */ 323static void 324RADEONBlitChunk(ScrnInfoPtr pScrn, struct radeon_bo *src_bo, 325 struct radeon_bo *dst_bo, uint32_t datatype, 326 uint32_t src_pitch_offset, uint32_t dst_pitch_offset, 327 int srcX, int srcY, int dstX, int dstY, int w, int h, 328 uint32_t src_domain, uint32_t dst_domain) 329{ 330 RADEONInfoPtr info = RADEONPTR(pScrn); 331 332 if (src_bo && dst_bo) { 333 BEGIN_ACCEL_RELOC(6, 2); 334 } else if (src_bo && !dst_bo) { 335 BEGIN_ACCEL_RELOC(6, 1); 336 } else { 337 BEGIN_RING(2*6); 338 } 339 OUT_RING_REG(RADEON_DP_GUI_MASTER_CNTL, 340 RADEON_GMC_DST_PITCH_OFFSET_CNTL | 341 RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 342 RADEON_GMC_BRUSH_NONE | 343 (datatype << 8) | 344 RADEON_GMC_SRC_DATATYPE_COLOR | 345 RADEON_ROP3_S | 346 RADEON_DP_SRC_SOURCE_MEMORY | 347 RADEON_GMC_CLR_CMP_CNTL_DIS | 348 RADEON_GMC_WR_MSK_DIS); 349 OUT_RING_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset); 350 if (src_bo) { 351 OUT_RING_RELOC(src_bo, src_domain, 0); 352 } 353 OUT_RING_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); 354 if (dst_bo) { 355 OUT_RING_RELOC(dst_bo, 0, dst_domain); 356 } 357 OUT_RING_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX); 358 OUT_RING_REG(RADEON_DST_Y_X, (dstY << 16) | dstX); 359 OUT_RING_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); 360 ADVANCE_RING(); 361 BEGIN_RING(2*2); 362 OUT_RING_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL); 363 OUT_RING_REG(RADEON_WAIT_UNTIL, 364 RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); 365 ADVANCE_RING(); 366} 367 368static Bool 369RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h, 370 char *src, int src_pitch) 371{ 372 ScreenPtr pScreen = pDst->drawable.pScreen; 373 RINFO_FROM_SCREEN(pScreen); 374 struct radeon_exa_pixmap_priv *driver_priv; 375 struct radeon_bo *scratch = NULL; 376 struct radeon_bo *copy_dst; 377 unsigned char *dst; 378 unsigned size; 379 uint32_t datatype = 0; 380 uint32_t dst_domain; 381 uint32_t dst_pitch_offset; 382 unsigned bpp = pDst->drawable.bitsPerPixel; 383 uint32_t scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64); 384 uint32_t copy_pitch; 385 uint32_t swap = RADEON_HOST_DATA_SWAP_NONE; 386 int ret; 387 Bool flush = TRUE; 388 Bool r; 389 int i; 390 391 if (bpp < 8) 392 return FALSE; 393 394 driver_priv = exaGetPixmapDriverPrivate(pDst); 395 if (!driver_priv || !driver_priv->bo->bo.radeon) 396 return FALSE; 397 398#if X_BYTE_ORDER == X_BIG_ENDIAN 399 switch (bpp) { 400 case 32: 401 swap = RADEON_HOST_DATA_SWAP_32BIT; 402 break; 403 case 16: 404 swap = RADEON_HOST_DATA_SWAP_16BIT; 405 break; 406 } 407#endif 408 409 /* If we know the BO won't be busy / in VRAM, don't bother with a scratch */ 410 copy_dst = driver_priv->bo->bo.radeon; 411 copy_pitch = pDst->devKind; 412 if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { 413 if (!radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) { 414 flush = FALSE; 415 if (!radeon_bo_is_busy(driver_priv->bo->bo.radeon, &dst_domain) && 416 !(dst_domain & RADEON_GEM_DOMAIN_VRAM)) 417 goto copy; 418 } 419 /* use cpu copy for fast fb access */ 420 if (info->is_fast_fb) 421 goto copy; 422 } 423 424 size = scratch_pitch * h; 425 scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); 426 if (!scratch) { 427 goto copy; 428 } 429 radeon_cs_space_reset_bos(info->cs); 430 radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM); 431 radeon_cs_space_add_persistent_bo(info->cs, scratch, RADEON_GEM_DOMAIN_GTT, 0); 432 ret = radeon_cs_space_check(info->cs); 433 if (ret) { 434 goto copy; 435 } 436 copy_dst = scratch; 437 copy_pitch = scratch_pitch; 438 flush = FALSE; 439 440copy: 441 if (flush) 442 radeon_cs_flush_indirect(pScrn); 443 444 ret = radeon_bo_map(copy_dst, 0); 445 if (ret) { 446 r = FALSE; 447 goto out; 448 } 449 r = TRUE; 450 size = w * bpp / 8; 451 dst = copy_dst->ptr; 452 if (copy_dst == driver_priv->bo->bo.radeon) 453 dst += y * copy_pitch + x * bpp / 8; 454 for (i = 0; i < h; i++) { 455 RADEONCopySwap(dst + i * copy_pitch, (uint8_t*)src, size, swap); 456 src += src_pitch; 457 } 458 radeon_bo_unmap(copy_dst); 459 460 if (copy_dst == scratch) { 461 RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype); 462 RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset); 463 RADEON_SWITCH_TO_2D(); 464 RADEONBlitChunk(pScrn, scratch, driver_priv->bo->bo.radeon, datatype, scratch_pitch << 16, 465 dst_pitch_offset, 0, 0, x, y, w, h, 466 RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM); 467 } 468 469out: 470 if (scratch) 471 radeon_bo_unref(scratch); 472 return r; 473} 474 475static Bool 476RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, 477 int h, char *dst, int dst_pitch) 478{ 479 RINFO_FROM_SCREEN(pSrc->drawable.pScreen); 480 struct radeon_exa_pixmap_priv *driver_priv; 481 struct radeon_bo *scratch = NULL; 482 struct radeon_bo *copy_src; 483 unsigned size; 484 uint32_t datatype = 0; 485 uint32_t src_domain = 0; 486 uint32_t src_pitch_offset; 487 unsigned bpp = pSrc->drawable.bitsPerPixel; 488 uint32_t scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64); 489 uint32_t copy_pitch; 490 uint32_t swap = RADEON_HOST_DATA_SWAP_NONE; 491 int ret; 492 Bool flush = FALSE; 493 Bool r; 494 495 if (bpp < 8) 496 return FALSE; 497 498 driver_priv = exaGetPixmapDriverPrivate(pSrc); 499 if (!driver_priv || !driver_priv->bo->bo.radeon) 500 return FALSE; 501 502#if X_BYTE_ORDER == X_BIG_ENDIAN 503 switch (bpp) { 504 case 32: 505 swap = RADEON_HOST_DATA_SWAP_32BIT; 506 break; 507 case 16: 508 swap = RADEON_HOST_DATA_SWAP_16BIT; 509 break; 510 } 511#endif 512 513 /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */ 514 copy_src = driver_priv->bo->bo.radeon; 515 copy_pitch = pSrc->devKind; 516 if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { 517 if (radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) { 518 src_domain = radeon_bo_get_src_domain(driver_priv->bo->bo.radeon); 519 if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == 520 (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) 521 src_domain = 0; 522 else /* A write may be scheduled */ 523 flush = TRUE; 524 } 525 526 if (!src_domain) 527 radeon_bo_is_busy(driver_priv->bo->bo.radeon, &src_domain); 528 529 if (src_domain & ~(uint32_t)RADEON_GEM_DOMAIN_VRAM) 530 goto copy; 531 } 532 size = scratch_pitch * h; 533 scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); 534 if (!scratch) { 535 goto copy; 536 } 537 radeon_cs_space_reset_bos(info->cs); 538 radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); 539 radeon_cs_space_add_persistent_bo(info->cs, scratch, 0, RADEON_GEM_DOMAIN_GTT); 540 ret = radeon_cs_space_check(info->cs); 541 if (ret) { 542 goto copy; 543 } 544 RADEONGetDatatypeBpp(pSrc->drawable.bitsPerPixel, &datatype); 545 RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset); 546 RADEON_SWITCH_TO_2D(); 547 RADEONBlitChunk(pScrn, driver_priv->bo->bo.radeon, scratch, datatype, 548 src_pitch_offset, scratch_pitch << 16, x, y, 0, 0, w, h, 549 RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 550 RADEON_GEM_DOMAIN_GTT); 551 copy_src = scratch; 552 copy_pitch = scratch_pitch; 553 flush = TRUE; 554 555copy: 556 if (flush) 557 FLUSH_RING(); 558 559 ret = radeon_bo_map(copy_src, 0); 560 if (ret) { 561 ErrorF("failed to map pixmap: %d\n", ret); 562 r = FALSE; 563 goto out; 564 } 565 r = TRUE; 566 w *= bpp / 8; 567 if (copy_src == driver_priv->bo->bo.radeon) 568 size = y * copy_pitch + x * bpp / 8; 569 else 570 size = 0; 571 while (h--) { 572 RADEONCopySwap((uint8_t*)dst, copy_src->ptr + size, w, swap); 573 size += copy_pitch; 574 dst += dst_pitch; 575 } 576 radeon_bo_unmap(copy_src); 577out: 578 if (scratch) 579 radeon_bo_unref(scratch); 580 return r; 581} 582 583Bool RADEONDrawInit(ScreenPtr pScreen) 584{ 585 RINFO_FROM_SCREEN(pScreen); 586 587 if (!info->accel_state->exa) { 588 xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map not set up\n"); 589 return FALSE; 590 } 591 592 info->accel_state->exa->exa_major = EXA_VERSION_MAJOR; 593 info->accel_state->exa->exa_minor = EXA_VERSION_MINOR; 594 595 info->accel_state->exa->PrepareSolid = RADEONPrepareSolid; 596 info->accel_state->exa->Solid = RADEONSolid; 597 info->accel_state->exa->DoneSolid = RADEONDone2D; 598 599 info->accel_state->exa->PrepareCopy = RADEONPrepareCopy; 600 info->accel_state->exa->Copy = RADEONCopy; 601 info->accel_state->exa->DoneCopy = RADEONDone2D; 602 603 info->accel_state->exa->MarkSync = RADEONMarkSync; 604 info->accel_state->exa->WaitMarker = RADEONSync; 605 606 info->accel_state->exa->UploadToScreen = &RADEONUploadToScreenCS; 607 info->accel_state->exa->DownloadFromScreen = &RADEONDownloadFromScreenCS; 608 609 info->accel_state->exa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_SUPPORTS_PREPARE_AUX | 610 EXA_SUPPORTS_OFFSCREEN_OVERLAPS | EXA_HANDLES_PIXMAPS | EXA_MIXED_PIXMAPS; 611 info->accel_state->exa->pixmapOffsetAlign = RADEON_GPU_PAGE_SIZE; 612 info->accel_state->exa->pixmapPitchAlign = 64; 613 614#ifdef RENDER 615 if (info->RenderAccel) { 616 if (IS_R300_3D || IS_R500_3D) { 617 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 618 "enabled for R300/R400/R500 type cards.\n"); 619 info->accel_state->exa->CheckComposite = R300CheckComposite; 620 info->accel_state->exa->PrepareComposite = 621 R300PrepareComposite; 622 info->accel_state->exa->Composite = RadeonComposite; 623 info->accel_state->exa->DoneComposite = RadeonDoneComposite; 624 } else if (IS_R200_3D) { 625 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 626 "enabled for R200 type cards.\n"); 627 info->accel_state->exa->CheckComposite = R200CheckComposite; 628 info->accel_state->exa->PrepareComposite = 629 R200PrepareComposite; 630 info->accel_state->exa->Composite = RadeonComposite; 631 info->accel_state->exa->DoneComposite = RadeonDoneComposite; 632 } else { 633 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 634 "enabled for R100 type cards.\n"); 635 info->accel_state->exa->CheckComposite = R100CheckComposite; 636 info->accel_state->exa->PrepareComposite = 637 R100PrepareComposite; 638 info->accel_state->exa->Composite = RadeonComposite; 639 info->accel_state->exa->DoneComposite = RadeonDoneComposite; 640 } 641 } 642#endif 643 644 info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap; 645 info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen; 646 info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS; 647 info->accel_state->exa->FinishAccess = RADEONFinishAccess_CS; 648 info->accel_state->exa->CreatePixmap2 = RADEONEXACreatePixmap2; 649 info->accel_state->exa->SharePixmapBacking = RADEONEXASharePixmapBacking; 650 info->accel_state->exa->SetSharedPixmapBacking = RADEONEXASetSharedPixmapBacking; 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