radeon_exa_funcs.c revision b7e1c893
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@tungstengraphics.com> 31 * 32 */ 33 34#if defined(ACCEL_MMIO) && defined(ACCEL_CP) 35#error Cannot define both MMIO and CP acceleration! 36#endif 37 38#if !defined(UNIXCPP) || defined(ANSICPP) 39#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix 40#else 41#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix 42#endif 43 44#ifdef ACCEL_MMIO 45#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO) 46#else 47#ifdef ACCEL_CP 48#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP) 49#else 50#error No accel type defined! 51#endif 52#endif 53 54#include <errno.h> 55#include <string.h> 56 57#include "radeon.h" 58 59#include "exa.h" 60 61static int 62FUNC_NAME(RADEONMarkSync)(ScreenPtr pScreen) 63{ 64 RINFO_FROM_SCREEN(pScreen); 65 66 TRACE; 67 68 return ++info->accel_state->exaSyncMarker; 69} 70 71static void 72FUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker) 73{ 74 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 75 RADEONInfoPtr info = RADEONPTR(pScrn); 76 77 TRACE; 78 79 if (info->accel_state->exaMarkerSynced != marker) { 80 FUNC_NAME(RADEONWaitForIdle)(pScrn); 81 info->accel_state->exaMarkerSynced = marker; 82 } 83 84 RADEONPTR(pScrn)->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; 85} 86 87static Bool 88FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) 89{ 90 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 91 uint32_t datatype, dst_pitch_offset; 92 ACCEL_PREAMBLE(); 93 94 TRACE; 95 96 if (pPix->drawable.bitsPerPixel == 24) 97 RADEON_FALLBACK(("24bpp unsupported\n")); 98 if (!RADEONGetDatatypeBpp(pPix->drawable.bitsPerPixel, &datatype)) 99 RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); 100 if (!RADEONGetPixmapOffsetPitch(pPix, &dst_pitch_offset)) 101 RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n")); 102 103 RADEON_SWITCH_TO_2D(); 104 105 BEGIN_ACCEL(5); 106 OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, 107 RADEON_GMC_DST_PITCH_OFFSET_CNTL | 108 RADEON_GMC_BRUSH_SOLID_COLOR | 109 (datatype << 8) | 110 RADEON_GMC_SRC_DATATYPE_COLOR | 111 RADEON_ROP[alu].pattern | 112 RADEON_GMC_CLR_CMP_CNTL_DIS); 113 OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg); 114 OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, pm); 115 OUT_ACCEL_REG(RADEON_DP_CNTL, 116 (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM)); 117 OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); 118 FINISH_ACCEL(); 119 120 return TRUE; 121} 122 123 124static void 125FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2) 126{ 127 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 128 ACCEL_PREAMBLE(); 129 130 TRACE; 131 132 if (info->accel_state->vsync) 133 FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix), y1, y2); 134 135 BEGIN_ACCEL(2); 136 OUT_ACCEL_REG(RADEON_DST_Y_X, (y1 << 16) | x1); 137 OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, ((y2 - y1) << 16) | (x2 - x1)); 138 FINISH_ACCEL(); 139} 140 141static void 142FUNC_NAME(RADEONDoneSolid)(PixmapPtr pPix) 143{ 144 RINFO_FROM_SCREEN(pPix->drawable.pScreen); 145 ACCEL_PREAMBLE(); 146 147 TRACE; 148 149 BEGIN_ACCEL(2); 150 OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL); 151 OUT_ACCEL_REG(RADEON_WAIT_UNTIL, 152 RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); 153 FINISH_ACCEL(); 154} 155 156void 157FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, 158 uint32_t dst_pitch_offset, uint32_t datatype, int rop, 159 Pixel planemask) 160{ 161 RADEONInfoPtr info = RADEONPTR(pScrn); 162 ACCEL_PREAMBLE(); 163 164 RADEON_SWITCH_TO_2D(); 165 166 BEGIN_ACCEL(5); 167 OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, 168 RADEON_GMC_DST_PITCH_OFFSET_CNTL | 169 RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 170 RADEON_GMC_BRUSH_NONE | 171 (datatype << 8) | 172 RADEON_GMC_SRC_DATATYPE_COLOR | 173 RADEON_ROP[rop].rop | 174 RADEON_DP_SRC_SOURCE_MEMORY | 175 RADEON_GMC_CLR_CMP_CNTL_DIS); 176 OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask); 177 OUT_ACCEL_REG(RADEON_DP_CNTL, 178 ((info->accel_state->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) | 179 (info->accel_state->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0))); 180 OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); 181 OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset); 182 FINISH_ACCEL(); 183} 184 185static Bool 186FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, 187 int xdir, int ydir, 188 int rop, 189 Pixel planemask) 190{ 191 RINFO_FROM_SCREEN(pDst->drawable.pScreen); 192 uint32_t datatype, src_pitch_offset, dst_pitch_offset; 193 194 TRACE; 195 196 info->accel_state->xdir = xdir; 197 info->accel_state->ydir = ydir; 198 199 if (pDst->drawable.bitsPerPixel == 24) 200 RADEON_FALLBACK(("24bpp unsupported")); 201 if (!RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype)) 202 RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); 203 if (!RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset)) 204 RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n")); 205 if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset)) 206 RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n")); 207 208 FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset, 209 datatype, rop, planemask); 210 211 return TRUE; 212} 213 214void 215FUNC_NAME(RADEONCopy)(PixmapPtr pDst, 216 int srcX, int srcY, 217 int dstX, int dstY, 218 int w, int h) 219{ 220 RINFO_FROM_SCREEN(pDst->drawable.pScreen); 221 ACCEL_PREAMBLE(); 222 223 TRACE; 224 225 if (info->accel_state->xdir < 0) { 226 srcX += w - 1; 227 dstX += w - 1; 228 } 229 if (info->accel_state->ydir < 0) { 230 srcY += h - 1; 231 dstY += h - 1; 232 } 233 234 if (info->accel_state->vsync) 235 FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), dstY, dstY + h); 236 237 BEGIN_ACCEL(3); 238 239 OUT_ACCEL_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX); 240 OUT_ACCEL_REG(RADEON_DST_Y_X, (dstY << 16) | dstX); 241 OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); 242 243 FINISH_ACCEL(); 244} 245 246static void 247FUNC_NAME(RADEONDoneCopy)(PixmapPtr pDst) 248{ 249 RINFO_FROM_SCREEN(pDst->drawable.pScreen); 250 ACCEL_PREAMBLE(); 251 252 TRACE; 253 254 BEGIN_ACCEL(2); 255 OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL); 256 OUT_ACCEL_REG(RADEON_WAIT_UNTIL, 257 RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); 258 FINISH_ACCEL(); 259} 260 261 262#ifdef ACCEL_CP 263 264static Bool 265RADEONUploadToScreenCP(PixmapPtr pDst, int x, int y, int w, int h, 266 char *src, int src_pitch) 267{ 268 RINFO_FROM_SCREEN(pDst->drawable.pScreen); 269 unsigned int bpp = pDst->drawable.bitsPerPixel; 270 unsigned int hpass; 271 uint32_t buf_pitch, dst_pitch_off; 272 273 TRACE; 274 275 if (bpp < 8) 276 return FALSE; 277 278 if (info->directRenderingEnabled && 279 RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_off)) { 280 uint8_t *buf; 281 int cpp = bpp / 8; 282 ACCEL_PREAMBLE(); 283 284 RADEON_SWITCH_TO_2D(); 285 286 if (info->accel_state->vsync) 287 FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), y, y + h); 288 289 while ((buf = RADEONHostDataBlit(pScrn, 290 cpp, w, dst_pitch_off, &buf_pitch, 291 x, &y, (unsigned int*)&h, &hpass)) != 0) { 292 RADEONHostDataBlitCopyPass(pScrn, cpp, buf, (uint8_t *)src, 293 hpass, buf_pitch, src_pitch); 294 src += hpass * src_pitch; 295 } 296 297 exaMarkSync(pDst->drawable.pScreen); 298 return TRUE; 299 } 300 301 return FALSE; 302} 303 304/* Emit blit with arbitrary source and destination offsets and pitches */ 305static void 306RADEONBlitChunk(ScrnInfoPtr pScrn, uint32_t datatype, uint32_t src_pitch_offset, 307 uint32_t dst_pitch_offset, int srcX, int srcY, int dstX, int dstY, 308 int w, int h) 309{ 310 RADEONInfoPtr info = RADEONPTR(pScrn); 311 ACCEL_PREAMBLE(); 312 313 BEGIN_ACCEL(6); 314 OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, 315 RADEON_GMC_DST_PITCH_OFFSET_CNTL | 316 RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 317 RADEON_GMC_BRUSH_NONE | 318 (datatype << 8) | 319 RADEON_GMC_SRC_DATATYPE_COLOR | 320 RADEON_ROP3_S | 321 RADEON_DP_SRC_SOURCE_MEMORY | 322 RADEON_GMC_CLR_CMP_CNTL_DIS | 323 RADEON_GMC_WR_MSK_DIS); 324 OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset); 325 OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); 326 OUT_ACCEL_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX); 327 OUT_ACCEL_REG(RADEON_DST_Y_X, (dstY << 16) | dstX); 328 OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); 329 FINISH_ACCEL(); 330 BEGIN_ACCEL(2); 331 OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL); 332 OUT_ACCEL_REG(RADEON_WAIT_UNTIL, 333 RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); 334 FINISH_ACCEL(); 335} 336 337 338static Bool 339RADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h, 340 char *dst, int dst_pitch) 341{ 342 RINFO_FROM_SCREEN(pSrc->drawable.pScreen); 343 uint8_t *src = info->FB + exaGetPixmapOffset(pSrc); 344 int bpp = pSrc->drawable.bitsPerPixel; 345 uint32_t datatype, src_pitch_offset, scratch_pitch = (w * bpp/8 + 63) & ~63, scratch_off = 0; 346 drmBufPtr scratch; 347 348 TRACE; 349 350 /* 351 * Try to accelerate download. Use an indirect buffer as scratch space, 352 * blitting the bits to one half while copying them out of the other one and 353 * then swapping the halves. 354 */ 355 if (bpp != 24 && RADEONGetDatatypeBpp(bpp, &datatype) && 356 RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset) && 357 (scratch = RADEONCPGetBuffer(pScrn))) 358 { 359 int swap = RADEON_HOST_DATA_SWAP_NONE, wpass = w * bpp / 8; 360 int hpass = min(h, scratch->total/2 / scratch_pitch); 361 uint32_t scratch_pitch_offset = scratch_pitch << 16 362 | (info->gartLocation + info->dri->bufStart 363 + scratch->idx * scratch->total) >> 10; 364 drm_radeon_indirect_t indirect; 365 ACCEL_PREAMBLE(); 366 367 RADEON_SWITCH_TO_2D(); 368 369 /* Kick the first blit as early as possible */ 370 RADEONBlitChunk(pScrn, datatype, src_pitch_offset, scratch_pitch_offset, 371 x, y, 0, 0, w, hpass); 372 FLUSH_RING(); 373 374#if X_BYTE_ORDER == X_BIG_ENDIAN 375 switch (bpp) { 376 case 16: 377 swap = RADEON_HOST_DATA_SWAP_16BIT; 378 break; 379 case 32: 380 swap = RADEON_HOST_DATA_SWAP_32BIT; 381 break; 382 } 383#endif 384 385 while (h) { 386 int oldhpass = hpass, i = 0; 387 388 src = (uint8_t*)scratch->address + scratch_off; 389 390 y += oldhpass; 391 h -= oldhpass; 392 hpass = min(h, scratch->total/2 / scratch_pitch); 393 394 /* Prepare next blit if anything's left */ 395 if (hpass) { 396 scratch_off = scratch->total/2 - scratch_off; 397 RADEONBlitChunk(pScrn, datatype, src_pitch_offset, scratch_pitch_offset + (scratch_off >> 10), 398 x, y, 0, 0, w, hpass); 399 } 400 401 /* 402 * Wait for previous blit to complete. 403 * 404 * XXX: Doing here essentially the same things this ioctl does in 405 * the DRM results in corruption with 'small' transfers, apparently 406 * because the data doesn't actually land in system RAM before the 407 * memcpy. I suspect the ioctl helps mostly due to its latency; what 408 * we'd really need is a way to reliably wait for the host interface 409 * to be done with pushing the data to the host. 410 */ 411 while ((drmCommandNone(info->dri->drmFD, DRM_RADEON_CP_IDLE) == -EBUSY) 412 && (i++ < RADEON_TIMEOUT)) 413 ; 414 415 /* Kick next blit */ 416 if (hpass) 417 FLUSH_RING(); 418 419 /* Copy out data from previous blit */ 420 if (wpass == scratch_pitch && wpass == dst_pitch) { 421 RADEONCopySwap((uint8_t*)dst, src, wpass * oldhpass, swap); 422 dst += dst_pitch * oldhpass; 423 } else while (oldhpass--) { 424 RADEONCopySwap((uint8_t*)dst, src, wpass, swap); 425 src += scratch_pitch; 426 dst += dst_pitch; 427 } 428 } 429 430 indirect.idx = scratch->idx; 431 indirect.start = indirect.end = 0; 432 indirect.discard = 1; 433 434 drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INDIRECT, 435 &indirect, sizeof(drm_radeon_indirect_t)); 436 437 info->accel_state->exaMarkerSynced = info->accel_state->exaSyncMarker; 438 439 return TRUE; 440 } 441 442 return FALSE; 443} 444 445#endif /* def ACCEL_CP */ 446 447 448Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) 449{ 450 RINFO_FROM_SCREEN(pScreen); 451 452 if (info->accel_state->exa == NULL) { 453 xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map not set up\n"); 454 return FALSE; 455 } 456 457 info->accel_state->exa->exa_major = EXA_VERSION_MAJOR; 458 info->accel_state->exa->exa_minor = EXA_VERSION_MINOR; 459 460 info->accel_state->exa->PrepareSolid = FUNC_NAME(RADEONPrepareSolid); 461 info->accel_state->exa->Solid = FUNC_NAME(RADEONSolid); 462 info->accel_state->exa->DoneSolid = FUNC_NAME(RADEONDoneSolid); 463 464 info->accel_state->exa->PrepareCopy = FUNC_NAME(RADEONPrepareCopy); 465 info->accel_state->exa->Copy = FUNC_NAME(RADEONCopy); 466 info->accel_state->exa->DoneCopy = FUNC_NAME(RADEONDoneCopy); 467 468 info->accel_state->exa->MarkSync = FUNC_NAME(RADEONMarkSync); 469 info->accel_state->exa->WaitMarker = FUNC_NAME(RADEONSync); 470#ifdef ACCEL_CP 471 info->accel_state->exa->UploadToScreen = RADEONUploadToScreenCP; 472 if (info->accelDFS) 473 info->accel_state->exa->DownloadFromScreen = RADEONDownloadFromScreenCP; 474#endif 475 476#if X_BYTE_ORDER == X_BIG_ENDIAN 477 info->accel_state->exa->PrepareAccess = RADEONPrepareAccess; 478 info->accel_state->exa->FinishAccess = RADEONFinishAccess; 479#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ 480 481 info->accel_state->exa->flags = EXA_OFFSCREEN_PIXMAPS; 482#ifdef EXA_SUPPORTS_PREPARE_AUX 483 info->accel_state->exa->flags |= EXA_SUPPORTS_PREPARE_AUX; 484#endif 485 info->accel_state->exa->pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1; 486 info->accel_state->exa->pixmapPitchAlign = 64; 487 488#ifdef RENDER 489 if (info->RenderAccel) { 490 if (info->ChipFamily >= CHIP_FAMILY_R600) 491 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 492 "unsupported on R600 and newer cards.\n"); 493 else if (IS_R300_3D || IS_R500_3D) { 494 if ((info->ChipFamily < CHIP_FAMILY_RS400) 495#ifdef XF86DRI 496 || (info->directRenderingEnabled) 497#endif 498 ) { 499 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 500 "enabled for R300/R400/R500 type cards.\n"); 501 info->accel_state->exa->CheckComposite = R300CheckComposite; 502 info->accel_state->exa->PrepareComposite = 503 FUNC_NAME(R300PrepareComposite); 504 info->accel_state->exa->Composite = FUNC_NAME(RadeonComposite); 505 info->accel_state->exa->DoneComposite = FUNC_NAME(RadeonDoneComposite); 506 } else 507 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA Composite requires CP on R5xx/IGP\n"); 508 } else if ((info->ChipFamily == CHIP_FAMILY_RV250) || 509 (info->ChipFamily == CHIP_FAMILY_RV280) || 510 (info->ChipFamily == CHIP_FAMILY_RS300) || 511 (info->ChipFamily == CHIP_FAMILY_R200)) { 512 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 513 "enabled for R200 type cards.\n"); 514 info->accel_state->exa->CheckComposite = R200CheckComposite; 515 info->accel_state->exa->PrepareComposite = 516 FUNC_NAME(R200PrepareComposite); 517 info->accel_state->exa->Composite = FUNC_NAME(RadeonComposite); 518 info->accel_state->exa->DoneComposite = FUNC_NAME(RadeonDoneComposite); 519 } else { 520 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 521 "enabled for R100 type cards.\n"); 522 info->accel_state->exa->CheckComposite = R100CheckComposite; 523 info->accel_state->exa->PrepareComposite = 524 FUNC_NAME(R100PrepareComposite); 525 info->accel_state->exa->Composite = FUNC_NAME(RadeonComposite); 526 info->accel_state->exa->DoneComposite = FUNC_NAME(RadeonDoneComposite); 527 } 528 } 529#endif 530 531#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3) 532 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting EXA maxPitchBytes\n"); 533 534 info->accel_state->exa->maxPitchBytes = 16320; 535 info->accel_state->exa->maxX = 8192; 536#else 537 info->accel_state->exa->maxX = 16320 / 4; 538#endif 539 info->accel_state->exa->maxY = 8192; 540 541 if (xf86ReturnOptValBool(info->Options, OPTION_EXA_VSYNC, FALSE)) { 542 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA VSync enabled\n"); 543 info->accel_state->vsync = TRUE; 544 } else 545 info->accel_state->vsync = FALSE; 546 547 RADEONEngineInit(pScrn); 548 549 if (!exaDriverInit(pScreen, info->accel_state->exa)) { 550 xfree(info->accel_state->exa); 551 return FALSE; 552 } 553 exaMarkSync(pScreen); 554 555 return TRUE; 556} 557 558#undef FUNC_NAME 559