r128_dri.c revision 42a55b46
1/* 2 * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, 3 * Precision Insight, Inc., Cedar Park, Texas, and 4 * VA Linux Systems Inc., Fremont, California. 5 * 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining 9 * a copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation on the rights to use, copy, modify, merge, 12 * publish, distribute, sublicense, and/or sell copies of the Software, 13 * and to permit persons to whom the Software is furnished to do so, 14 * subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial 18 * portions of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX 24 * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 * OTHER DEALINGS IN THE SOFTWARE. 28 */ 29 30#ifdef HAVE_CONFIG_H 31#include "config.h" 32#endif 33 34#include <string.h> 35#include <stdio.h> 36 37/* 38 * Authors: 39 * Kevin E. Martin <martin@valinux.com> 40 * Rickard E. Faith <faith@valinux.com> 41 * Daryll Strauss <daryll@valinux.com> 42 * Gareth Hughes <gareth@valinux.com> 43 * 44 */ 45 46 /* Driver data structures */ 47#include "r128.h" 48#include "r128_dri.h" 49#include "r128_common.h" 50#include "r128_reg.h" 51#include "r128_sarea.h" 52#include "r128_version.h" 53 54 /* X and server generic header files */ 55#include "xf86.h" 56#include "xf86PciInfo.h" 57#include "windowstr.h" 58 59#include "shadowfb.h" 60 /* GLX/DRI/DRM definitions */ 61#define _XF86DRI_SERVER_ 62#include "GL/glxtokens.h" 63#include "sarea.h" 64 65static size_t r128_drm_page_size; 66 67static void R128DRITransitionTo2d(ScreenPtr pScreen); 68static void R128DRITransitionTo3d(ScreenPtr pScreen); 69static void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen); 70static void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen); 71 72static void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); 73 74/* Initialize the visual configs that are supported by the hardware. 75 These are combined with the visual configs that the indirect 76 rendering core supports, and the intersection is exported to the 77 client. */ 78static Bool R128InitVisualConfigs(ScreenPtr pScreen) 79{ 80 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 81 R128InfoPtr info = R128PTR(pScrn); 82 int numConfigs = 0; 83 __GLXvisualConfig *pConfigs = NULL; 84 R128ConfigPrivPtr pR128Configs = NULL; 85 R128ConfigPrivPtr *pR128ConfigPtrs = NULL; 86 int i, accum, stencil, db; 87 88 switch (info->CurrentLayout.pixel_code) { 89 case 8: /* 8bpp mode is not support */ 90 case 15: /* FIXME */ 91 case 24: /* FIXME */ 92 xf86DrvMsg(pScreen->myNum, X_ERROR, 93 "[dri] R128DRIScreenInit failed (depth %d not supported). " 94 "Disabling DRI.\n", info->CurrentLayout.pixel_code); 95 return FALSE; 96 97#define R128_USE_ACCUM 1 98#define R128_USE_STENCIL 1 99#define R128_USE_DB 1 100 101 case 16: 102 numConfigs = 1; 103 if (R128_USE_ACCUM) numConfigs *= 2; 104 if (R128_USE_STENCIL) numConfigs *= 2; 105 if (R128_USE_DB) numConfigs *= 2; 106 107 if (!(pConfigs 108 = (__GLXvisualConfig*)calloc(sizeof(__GLXvisualConfig), 109 numConfigs))) { 110 return FALSE; 111 } 112 if (!(pR128Configs 113 = (R128ConfigPrivPtr)calloc(sizeof(R128ConfigPrivRec), 114 numConfigs))) { 115 free(pConfigs); 116 return FALSE; 117 } 118 if (!(pR128ConfigPtrs 119 = (R128ConfigPrivPtr*)calloc(sizeof(R128ConfigPrivPtr), 120 numConfigs))) { 121 free(pConfigs); 122 free(pR128Configs); 123 return FALSE; 124 } 125 126 i = 0; 127 for (db = 0; db <= R128_USE_DB; db++) { 128 for (accum = 0; accum <= R128_USE_ACCUM; accum++) { 129 for (stencil = 0; stencil <= R128_USE_STENCIL; stencil++) { 130 pR128ConfigPtrs[i] = &pR128Configs[i]; 131 132 pConfigs[i].vid = (VisualID)(-1); 133 pConfigs[i].class = -1; 134 pConfigs[i].rgba = TRUE; 135 pConfigs[i].redSize = 5; 136 pConfigs[i].greenSize = 6; 137 pConfigs[i].blueSize = 5; 138 pConfigs[i].alphaSize = 0; 139 pConfigs[i].redMask = 0x0000F800; 140 pConfigs[i].greenMask = 0x000007E0; 141 pConfigs[i].blueMask = 0x0000001F; 142 pConfigs[i].alphaMask = 0x00000000; 143 if (accum) { /* Simulated in software */ 144 pConfigs[i].accumRedSize = 16; 145 pConfigs[i].accumGreenSize = 16; 146 pConfigs[i].accumBlueSize = 16; 147 pConfigs[i].accumAlphaSize = 0; 148 } else { 149 pConfigs[i].accumRedSize = 0; 150 pConfigs[i].accumGreenSize = 0; 151 pConfigs[i].accumBlueSize = 0; 152 pConfigs[i].accumAlphaSize = 0; 153 } 154 if (db) 155 pConfigs[i].doubleBuffer = TRUE; 156 else 157 pConfigs[i].doubleBuffer = FALSE; 158 pConfigs[i].stereo = FALSE; 159 pConfigs[i].bufferSize = 16; 160 pConfigs[i].depthSize = 16; 161 if (stencil) 162 pConfigs[i].stencilSize = 8; /* Simulated in software */ 163 else 164 pConfigs[i].stencilSize = 0; 165 pConfigs[i].auxBuffers = 0; 166 pConfigs[i].level = 0; 167 if (accum || stencil) { 168 pConfigs[i].visualRating = GLX_SLOW_CONFIG; 169 } else { 170 pConfigs[i].visualRating = GLX_NONE; 171 } 172 pConfigs[i].transparentPixel = GLX_NONE; 173 pConfigs[i].transparentRed = 0; 174 pConfigs[i].transparentGreen = 0; 175 pConfigs[i].transparentBlue = 0; 176 pConfigs[i].transparentAlpha = 0; 177 pConfigs[i].transparentIndex = 0; 178 i++; 179 } 180 } 181 } 182 break; 183 184 case 32: 185 numConfigs = 1; 186 if (R128_USE_ACCUM) numConfigs *= 2; 187 if (R128_USE_STENCIL) numConfigs *= 2; 188 if (R128_USE_DB) numConfigs *= 2; 189 190 if (!(pConfigs 191 = (__GLXvisualConfig*)calloc(sizeof(__GLXvisualConfig), 192 numConfigs))) { 193 return FALSE; 194 } 195 if (!(pR128Configs 196 = (R128ConfigPrivPtr)calloc(sizeof(R128ConfigPrivRec), 197 numConfigs))) { 198 free(pConfigs); 199 return FALSE; 200 } 201 if (!(pR128ConfigPtrs 202 = (R128ConfigPrivPtr*)calloc(sizeof(R128ConfigPrivPtr), 203 numConfigs))) { 204 free(pConfigs); 205 free(pR128Configs); 206 return FALSE; 207 } 208 209 i = 0; 210 for (db = 0; db <= R128_USE_DB; db++) { 211 for (accum = 0; accum <= R128_USE_ACCUM; accum++) { 212 for (stencil = 0; stencil <= R128_USE_STENCIL; stencil++) { 213 pR128ConfigPtrs[i] = &pR128Configs[i]; 214 215 pConfigs[i].vid = (VisualID)(-1); 216 pConfigs[i].class = -1; 217 pConfigs[i].rgba = TRUE; 218 pConfigs[i].redSize = 8; 219 pConfigs[i].greenSize = 8; 220 pConfigs[i].blueSize = 8; 221 pConfigs[i].alphaSize = 0; 222 pConfigs[i].redMask = 0x00FF0000; 223 pConfigs[i].greenMask = 0x0000FF00; 224 pConfigs[i].blueMask = 0x000000FF; 225 pConfigs[i].alphaMask = 0x00000000; 226 if (accum) { /* Simulated in software */ 227 pConfigs[i].accumRedSize = 16; 228 pConfigs[i].accumGreenSize = 16; 229 pConfigs[i].accumBlueSize = 16; 230 pConfigs[i].accumAlphaSize = 0; 231 } else { 232 pConfigs[i].accumRedSize = 0; 233 pConfigs[i].accumGreenSize = 0; 234 pConfigs[i].accumBlueSize = 0; 235 pConfigs[i].accumAlphaSize = 0; 236 } 237 if (db) 238 pConfigs[i].doubleBuffer = TRUE; 239 else 240 pConfigs[i].doubleBuffer = FALSE; 241 pConfigs[i].stereo = FALSE; 242 pConfigs[i].bufferSize = 24; 243 if (stencil) { 244 pConfigs[i].depthSize = 24; 245 pConfigs[i].stencilSize = 8; 246 } else { 247 pConfigs[i].depthSize = 24; 248 pConfigs[i].stencilSize = 0; 249 } 250 pConfigs[i].auxBuffers = 0; 251 pConfigs[i].level = 0; 252 if (accum) { 253 pConfigs[i].visualRating = GLX_SLOW_CONFIG; 254 } else { 255 pConfigs[i].visualRating = GLX_NONE; 256 } 257 pConfigs[i].transparentPixel = GLX_NONE; 258 pConfigs[i].transparentRed = 0; 259 pConfigs[i].transparentGreen = 0; 260 pConfigs[i].transparentBlue = 0; 261 pConfigs[i].transparentAlpha = 0; 262 pConfigs[i].transparentIndex = 0; 263 i++; 264 } 265 } 266 } 267 break; 268 } 269 270 info->numVisualConfigs = numConfigs; 271 info->pVisualConfigs = pConfigs; 272 info->pVisualConfigsPriv = pR128Configs; 273 GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pR128ConfigPtrs); 274 return TRUE; 275} 276 277/* Create the Rage 128-specific context information */ 278static Bool R128CreateContext(ScreenPtr pScreen, VisualPtr visual, 279 drm_context_t hwContext, void *pVisualConfigPriv, 280 DRIContextType contextStore) 281{ 282 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 283 R128InfoPtr info = R128PTR(pScrn); 284 285 info->drmCtx = hwContext; 286 return TRUE; 287} 288 289/* Destroy the Rage 128-specific context information */ 290static void R128DestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 291 DRIContextType contextStore) 292{ 293 /* Nothing yet */ 294} 295 296/* Called when the X server is woken up to allow the last client's 297 context to be saved and the X server's context to be loaded. This is 298 not necessary for the Rage 128 since the client detects when it's 299 context is not currently loaded and then load's it itself. Since the 300 registers to start and stop the CCE are privileged, only the X server 301 can start/stop the engine. */ 302static void R128EnterServer(ScreenPtr pScreen) 303{ 304 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 305 R128InfoPtr info = R128PTR(pScrn); 306 307#ifdef HAVE_XAA_H 308 if (info->accel) info->accel->NeedToSync = TRUE; 309#endif 310#ifdef USE_EXA 311 if (info->ExaDriver) exaMarkSync(pScreen); 312 info->state_2d.composite_setup = FALSE; 313#endif 314} 315 316/* Called when the X server goes to sleep to allow the X server's 317 context to be saved and the last client's context to be loaded. This 318 is not necessary for the Rage 128 since the client detects when it's 319 context is not currently loaded and then load's it itself. Since the 320 registers to start and stop the CCE are privileged, only the X server 321 can start/stop the engine. */ 322static void R128LeaveServer(ScreenPtr pScreen) 323{ 324 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 325 R128InfoPtr info = R128PTR(pScrn); 326 unsigned char *R128MMIO = info->MMIO; 327 328 if (!info->directRenderingEnabled) { 329 /* Save all hardware scissors */ 330 info->sc_left = INREG(R128_SC_LEFT); 331 info->sc_right = INREG(R128_SC_RIGHT); 332 info->sc_top = INREG(R128_SC_TOP); 333 info->sc_bottom = INREG(R128_SC_BOTTOM); 334 info->aux_sc_cntl = INREG(R128_SC_BOTTOM); 335 } else if (info->CCEInUse) { 336 R128CCEReleaseIndirect(pScrn); 337 338 info->CCEInUse = FALSE; 339 } 340} 341 342/* Contexts can be swapped by the X server if necessary. This callback 343 is currently only used to perform any functions necessary when 344 entering or leaving the X server, and in the future might not be 345 necessary. */ 346static void R128DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 347 DRIContextType oldContextType, void *oldContext, 348 DRIContextType newContextType, void *newContext) 349{ 350 if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) && 351 (newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */ 352 R128EnterServer(pScreen); 353 } 354 if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) && 355 (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */ 356 R128LeaveServer(pScreen); 357 } 358} 359 360/* Initialize the state of the back and depth buffers. */ 361static void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx) 362{ 363 /* FIXME: This routine needs to have acceleration turned on */ 364 ScreenPtr pScreen = pWin->drawable.pScreen; 365 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 366 R128InfoPtr info = R128PTR(pScrn); 367#ifdef HAVE_XAA_H 368 BoxPtr pbox, pboxSave; 369 int nbox, nboxSave; 370 int depth; 371#endif 372 373 /* FIXME: Use accel when CCE 2D code is written 374 * EA: What is this code kept for? Radeon doesn't have it and 375 * has a comment: "There's no need for the 2d driver to be clearing 376 * buffers for the 3d client. It knows how to do that on its own." 377 */ 378 if (info->directRenderingEnabled) 379 return; 380#ifdef HAVE_XAA_H 381 /* FIXME: This should be based on the __GLXvisualConfig info */ 382 switch (pScrn->bitsPerPixel) { 383 case 8: depth = 0x000000ff; break; 384 case 16: depth = 0x0000ffff; break; 385 case 24: depth = 0x00ffffff; break; 386 case 32: depth = 0xffffffff; break; 387 default: depth = 0x00000000; break; 388 } 389 390 /* FIXME: Copy XAAPaintWindow() and use REGION_TRANSLATE() */ 391 /* FIXME: Only initialize the back and depth buffers for contexts 392 that request them */ 393 394 pboxSave = pbox = REGION_RECTS(prgn); 395 nboxSave = nbox = REGION_NUM_RECTS(prgn); 396 397 (*info->accel->SetupForSolidFill)(pScrn, 0, GXcopy, (CARD32)(-1)); 398 for (; nbox; nbox--, pbox++) { 399 (*info->accel->SubsequentSolidFillRect)(pScrn, 400 pbox->x1 + info->fbX, 401 pbox->y1 + info->fbY, 402 pbox->x2 - pbox->x1, 403 pbox->y2 - pbox->y1); 404 (*info->accel->SubsequentSolidFillRect)(pScrn, 405 pbox->x1 + info->backX, 406 pbox->y1 + info->backY, 407 pbox->x2 - pbox->x1, 408 pbox->y2 - pbox->y1); 409 } 410 411 pbox = pboxSave; 412 nbox = nboxSave; 413 414 /* FIXME: this needs to consider depth tiling. */ 415 (*info->accel->SetupForSolidFill)(pScrn, depth, GXcopy, (CARD32)(-1)); 416 for (; nbox; nbox--, pbox++) 417 (*info->accel->SubsequentSolidFillRect)(pScrn, 418 pbox->x1 + info->depthX, 419 pbox->y1 + info->depthY, 420 pbox->x2 - pbox->x1, 421 pbox->y2 - pbox->y1); 422 423 info->accel->NeedToSync = TRUE; 424#endif 425} 426 427/* Copy the back and depth buffers when the X server moves a window. */ 428static void R128DRIMoveBuffers(WindowPtr pWin, DDXPointRec ptOldOrg, 429 RegionPtr prgnSrc, CARD32 indx) 430{ 431 ScreenPtr pScreen = pWin->drawable.pScreen; 432 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 433 R128InfoPtr info = R128PTR(pScrn); 434 435 /* FIXME: This routine needs to have acceleration turned on */ 436 /* FIXME: Copy XAACopyWindow() and use REGION_TRANSLATE() */ 437 /* FIXME: Only initialize the back and depth buffers for contexts 438 that request them */ 439 440 /* FIXME: Use accel when CCE 2D code is written */ 441 if (info->directRenderingEnabled) 442 return; 443} 444 445/* Initialize the AGP state. Request memory for use in AGP space, and 446 initialize the Rage 128 registers to point to that memory. */ 447static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen) 448{ 449 unsigned char *R128MMIO = info->MMIO; 450 unsigned long mode; 451 unsigned int vendor, device; 452 int ret; 453 unsigned long cntl, chunk; 454 int s, l; 455 int flags; 456 unsigned long agpBase; 457 458 if (drmAgpAcquire(info->drmFD) < 0) { 459 xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] AGP not available\n"); 460 return FALSE; 461 } 462 463 /* Modify the mode if the default mode is 464 not appropriate for this particular 465 combination of graphics card and AGP 466 chipset. */ 467 468 mode = drmAgpGetMode(info->drmFD); /* Default mode */ 469 vendor = drmAgpVendorId(info->drmFD); 470 device = drmAgpDeviceId(info->drmFD); 471 472 mode &= ~R128_AGP_MODE_MASK; 473 switch (info->agpMode) { 474 case 4: mode |= R128_AGP_4X_MODE; 475 case 2: mode |= R128_AGP_2X_MODE; 476 case 1: default: mode |= R128_AGP_1X_MODE; 477 } 478 479 xf86DrvMsg(pScreen->myNum, X_INFO, 480 "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", 481 mode, vendor, device, 482 PCI_DEV_VENDOR_ID(info->PciInfo), 483 PCI_DEV_DEVICE_ID(info->PciInfo)); 484 485 if (drmAgpEnable(info->drmFD, mode) < 0) { 486 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n"); 487 drmAgpRelease(info->drmFD); 488 return FALSE; 489 } 490 491 info->agpOffset = 0; 492 493 if ((ret = drmAgpAlloc(info->drmFD, info->agpSize*1024*1024, 0, NULL, 494 &info->agpMemHandle)) < 0) { 495 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret); 496 drmAgpRelease(info->drmFD); 497 return FALSE; 498 } 499 xf86DrvMsg(pScreen->myNum, X_INFO, 500 "[agp] %d kB allocated with handle 0x%08x\n", 501 info->agpSize*1024, info->agpMemHandle); 502 503 if (drmAgpBind(info->drmFD, info->agpMemHandle, info->agpOffset) < 0) { 504 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n"); 505 drmAgpFree(info->drmFD, info->agpMemHandle); 506 drmAgpRelease(info->drmFD); 507 return FALSE; 508 } 509 510 /* Initialize the CCE ring buffer data */ 511 info->ringStart = info->agpOffset; 512 info->ringMapSize = info->ringSize*1024*1024 + r128_drm_page_size; 513 info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1; 514 515 info->ringReadOffset = info->ringStart + info->ringMapSize; 516 info->ringReadMapSize = r128_drm_page_size; 517 518 /* Reserve space for vertex/indirect buffers */ 519 info->bufStart = info->ringReadOffset + info->ringReadMapSize; 520 info->bufMapSize = info->bufSize*1024*1024; 521 522 /* Reserve the rest for AGP textures */ 523 info->agpTexStart = info->bufStart + info->bufMapSize; 524 s = (info->agpSize*1024*1024 - info->agpTexStart); 525 l = R128MinBits((s-1) / R128_NR_TEX_REGIONS); 526 if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; 527 info->agpTexMapSize = (s >> l) << l; 528 info->log2AGPTexGran = l; 529 530 if (info->CCESecure) flags = DRM_READ_ONLY; 531 else flags = 0; 532 533 if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize, 534 DRM_AGP, flags, &info->ringHandle) < 0) { 535 xf86DrvMsg(pScreen->myNum, X_ERROR, 536 "[agp] Could not add ring mapping\n"); 537 return FALSE; 538 } 539 xf86DrvMsg(pScreen->myNum, X_INFO, 540 "[agp] ring handle = 0x%08x\n", info->ringHandle); 541 542 if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, 543 &info->ring) < 0) { 544 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n"); 545 return FALSE; 546 } 547 xf86DrvMsg(pScreen->myNum, X_INFO, 548 "[agp] Ring mapped at 0x%08lx\n", 549 (unsigned long)info->ring); 550 551 if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize, 552 DRM_AGP, flags, &info->ringReadPtrHandle) < 0) { 553 xf86DrvMsg(pScreen->myNum, X_ERROR, 554 "[agp] Could not add ring read ptr mapping\n"); 555 return FALSE; 556 } 557 xf86DrvMsg(pScreen->myNum, X_INFO, 558 "[agp] ring read ptr handle = 0x%08x\n", 559 info->ringReadPtrHandle); 560 561 if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, 562 &info->ringReadPtr) < 0) { 563 xf86DrvMsg(pScreen->myNum, X_ERROR, 564 "[agp] Could not map ring read ptr\n"); 565 return FALSE; 566 } 567 xf86DrvMsg(pScreen->myNum, X_INFO, 568 "[agp] Ring read ptr mapped at 0x%08lx\n", 569 (unsigned long)info->ringReadPtr); 570 571 if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize, 572 DRM_AGP, 0, &info->bufHandle) < 0) { 573 xf86DrvMsg(pScreen->myNum, X_ERROR, 574 "[agp] Could not add vertex/indirect buffers mapping\n"); 575 return FALSE; 576 } 577 xf86DrvMsg(pScreen->myNum, X_INFO, 578 "[agp] vertex/indirect buffers handle = 0x%08x\n", 579 info->bufHandle); 580 581 if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize, 582 &info->buf) < 0) { 583 xf86DrvMsg(pScreen->myNum, X_ERROR, 584 "[agp] Could not map vertex/indirect buffers\n"); 585 return FALSE; 586 } 587 xf86DrvMsg(pScreen->myNum, X_INFO, 588 "[agp] Vertex/indirect buffers mapped at 0x%08lx\n", 589 (unsigned long)info->buf); 590 591 if (drmAddMap(info->drmFD, info->agpTexStart, info->agpTexMapSize, 592 DRM_AGP, 0, &info->agpTexHandle) < 0) { 593 xf86DrvMsg(pScreen->myNum, X_ERROR, 594 "[agp] Could not add AGP texture map mapping\n"); 595 return FALSE; 596 } 597 xf86DrvMsg(pScreen->myNum, X_INFO, 598 "[agp] AGP texture map handle = 0x%08x\n", 599 info->agpTexHandle); 600 601 if (drmMap(info->drmFD, info->agpTexHandle, info->agpTexMapSize, 602 &info->agpTex) < 0) { 603 xf86DrvMsg(pScreen->myNum, X_ERROR, 604 "[agp] Could not map AGP texture map\n"); 605 return FALSE; 606 } 607 xf86DrvMsg(pScreen->myNum, X_INFO, 608 "[agp] AGP Texture map mapped at 0x%08lx\n", 609 (unsigned long)info->agpTex); 610 611 /* Initialize Rage 128's AGP registers */ 612 cntl = INREG(R128_AGP_CNTL); 613 cntl &= ~R128_AGP_APER_SIZE_MASK; 614 switch (info->agpSize) { 615 case 256: cntl |= R128_AGP_APER_SIZE_256MB; break; 616 case 128: cntl |= R128_AGP_APER_SIZE_128MB; break; 617 case 64: cntl |= R128_AGP_APER_SIZE_64MB; break; 618 case 32: cntl |= R128_AGP_APER_SIZE_32MB; break; 619 case 16: cntl |= R128_AGP_APER_SIZE_16MB; break; 620 case 8: cntl |= R128_AGP_APER_SIZE_8MB; break; 621 case 4: cntl |= R128_AGP_APER_SIZE_4MB; break; 622 default: 623 xf86DrvMsg(pScreen->myNum, X_ERROR, 624 "[agp] Illegal aperture size %d kB\n", 625 info->agpSize*1024); 626 return FALSE; 627 } 628 agpBase = drmAgpBase(info->drmFD); 629 OUTREG(R128_AGP_BASE, agpBase); 630 OUTREG(R128_AGP_CNTL, cntl); 631 632 /* Disable Rage 128's PCIGART registers */ 633 chunk = INREG(R128_BM_CHUNK_0_VAL); 634 chunk &= ~(R128_BM_PTR_FORCE_TO_PCI | 635 R128_BM_PM4_RD_FORCE_TO_PCI | 636 R128_BM_GLOBAL_FORCE_TO_PCI); 637 OUTREG(R128_BM_CHUNK_0_VAL, chunk); 638 639 OUTREG(R128_PCI_GART_PAGE, 1); /* Ensure AGP GART is used (for now) */ 640 641 return TRUE; 642} 643 644static Bool R128DRIPciInit(R128InfoPtr info, ScreenPtr pScreen) 645{ 646 unsigned char *R128MMIO = info->MMIO; 647 CARD32 chunk; 648 int ret; 649 int flags; 650 651 info->agpOffset = 0; 652 653 ret = drmScatterGatherAlloc(info->drmFD, info->agpSize*1024*1024, 654 &info->pciMemHandle); 655 if (ret < 0) { 656 xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Out of memory (%d)\n", ret); 657 return FALSE; 658 } 659 xf86DrvMsg(pScreen->myNum, X_INFO, 660 "[pci] %d kB allocated with handle 0x%08x\n", 661 info->agpSize*1024, info->pciMemHandle); 662 663 /* Initialize the CCE ring buffer data */ 664 info->ringStart = info->agpOffset; 665 info->ringMapSize = info->ringSize*1024*1024 + r128_drm_page_size; 666 info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1; 667 668 info->ringReadOffset = info->ringStart + info->ringMapSize; 669 info->ringReadMapSize = r128_drm_page_size; 670 671 /* Reserve space for vertex/indirect buffers */ 672 info->bufStart = info->ringReadOffset + info->ringReadMapSize; 673 info->bufMapSize = info->bufSize*1024*1024; 674 675 flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL; 676 677 if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize, 678 DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) { 679 xf86DrvMsg(pScreen->myNum, X_ERROR, 680 "[pci] Could not add ring mapping\n"); 681 return FALSE; 682 } 683 xf86DrvMsg(pScreen->myNum, X_INFO, 684 "[pci] ring handle = 0x%08x\n", info->ringHandle); 685 686 if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, 687 &info->ring) < 0) { 688 xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n"); 689 return FALSE; 690 } 691 xf86DrvMsg(pScreen->myNum, X_INFO, 692 "[pci] Ring mapped at 0x%08lx\n", 693 (unsigned long)info->ring); 694 xf86DrvMsg(pScreen->myNum, X_INFO, 695 "[pci] Ring contents 0x%08lx\n", 696 *(unsigned long *)(pointer)info->ring); 697 698 if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize, 699 DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) { 700 xf86DrvMsg(pScreen->myNum, X_ERROR, 701 "[pci] Could not add ring read ptr mapping\n"); 702 return FALSE; 703 } 704 xf86DrvMsg(pScreen->myNum, X_INFO, 705 "[pci] ring read ptr handle = 0x%08x\n", 706 info->ringReadPtrHandle); 707 708 if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, 709 &info->ringReadPtr) < 0) { 710 xf86DrvMsg(pScreen->myNum, X_ERROR, 711 "[pci] Could not map ring read ptr\n"); 712 return FALSE; 713 } 714 xf86DrvMsg(pScreen->myNum, X_INFO, 715 "[pci] Ring read ptr mapped at 0x%08lx\n", 716 (unsigned long)info->ringReadPtr); 717 xf86DrvMsg(pScreen->myNum, X_INFO, 718 "[pci] Ring read ptr contents 0x%08lx\n", 719 *(unsigned long *)(pointer)info->ringReadPtr); 720 721 if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize, 722 DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) { 723 xf86DrvMsg(pScreen->myNum, X_ERROR, 724 "[pci] Could not add vertex/indirect buffers mapping\n"); 725 return FALSE; 726 } 727 xf86DrvMsg(pScreen->myNum, X_INFO, 728 "[pci] vertex/indirect buffers handle = 0x%08x\n", 729 info->bufHandle); 730 731 if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize, 732 &info->buf) < 0) { 733 xf86DrvMsg(pScreen->myNum, X_ERROR, 734 "[pci] Could not map vertex/indirect buffers\n"); 735 return FALSE; 736 } 737 xf86DrvMsg(pScreen->myNum, X_INFO, 738 "[pci] Vertex/indirect buffers mapped at 0x%08lx\n", 739 (unsigned long)info->buf); 740 xf86DrvMsg(pScreen->myNum, X_INFO, 741 "[pci] Vertex/indirect buffers contents 0x%08lx\n", 742 *(unsigned long *)(pointer)info->buf); 743 744 switch (info->Chipset) { 745 case PCI_CHIP_RAGE128LE: 746 case PCI_CHIP_RAGE128RE: 747 case PCI_CHIP_RAGE128RK: 748 case PCI_CHIP_RAGE128PD: 749 case PCI_CHIP_RAGE128PP: 750 case PCI_CHIP_RAGE128PR: 751 /* This is a PCI card, do nothing */ 752 break; 753 754 case PCI_CHIP_RAGE128LF: 755 case PCI_CHIP_RAGE128MF: 756 case PCI_CHIP_RAGE128ML: 757 case PCI_CHIP_RAGE128RF: 758 case PCI_CHIP_RAGE128RG: 759 case PCI_CHIP_RAGE128RL: 760 case PCI_CHIP_RAGE128SM: 761 case PCI_CHIP_RAGE128PF: 762 case PCI_CHIP_RAGE128TF: 763 case PCI_CHIP_RAGE128TL: 764 case PCI_CHIP_RAGE128TR: 765 /* FIXME: ATI documentation does not specify if the following chips are 766 * AGP or PCI, it just mentions their PCI IDs. I'm assuming they're AGP 767 * until I get more correct information. <mharris@redhat.com> 768 */ 769 case PCI_CHIP_RAGE128PA: 770 case PCI_CHIP_RAGE128PB: 771 case PCI_CHIP_RAGE128PC: 772 case PCI_CHIP_RAGE128PE: 773 case PCI_CHIP_RAGE128PG: 774 case PCI_CHIP_RAGE128PH: 775 case PCI_CHIP_RAGE128PI: 776 case PCI_CHIP_RAGE128PJ: 777 case PCI_CHIP_RAGE128PK: 778 case PCI_CHIP_RAGE128PL: 779 case PCI_CHIP_RAGE128PM: 780 case PCI_CHIP_RAGE128PN: 781 case PCI_CHIP_RAGE128PO: 782 case PCI_CHIP_RAGE128PQ: 783 case PCI_CHIP_RAGE128PS: 784 case PCI_CHIP_RAGE128PT: 785 case PCI_CHIP_RAGE128PU: 786 case PCI_CHIP_RAGE128PV: 787 case PCI_CHIP_RAGE128PW: 788 case PCI_CHIP_RAGE128PX: 789 case PCI_CHIP_RAGE128SE: 790 case PCI_CHIP_RAGE128SF: 791 case PCI_CHIP_RAGE128SG: 792 case PCI_CHIP_RAGE128SH: 793 case PCI_CHIP_RAGE128SK: 794 case PCI_CHIP_RAGE128SL: 795 case PCI_CHIP_RAGE128SN: 796 case PCI_CHIP_RAGE128TS: 797 case PCI_CHIP_RAGE128TT: 798 case PCI_CHIP_RAGE128TU: 799 default: 800 /* This is really an AGP card, force PCI GART mode */ 801 chunk = INREG(R128_BM_CHUNK_0_VAL); 802 chunk |= (R128_BM_PTR_FORCE_TO_PCI | 803 R128_BM_PM4_RD_FORCE_TO_PCI | 804 R128_BM_GLOBAL_FORCE_TO_PCI); 805 OUTREG(R128_BM_CHUNK_0_VAL, chunk); 806 OUTREG(R128_PCI_GART_PAGE, 0); /* Ensure PCI GART is used */ 807 break; 808 } 809 810 return TRUE; 811} 812 813/* Add a map for the MMIO registers that will be accessed by any 814 DRI-based clients. */ 815static Bool R128DRIMapInit(R128InfoPtr info, ScreenPtr pScreen) 816{ 817 int flags; 818 819 if (info->CCESecure) flags = DRM_READ_ONLY; 820 else flags = 0; 821 822 /* Map registers */ 823 info->registerSize = R128_MMIOSIZE; 824 if (drmAddMap(info->drmFD, info->MMIOAddr, info->registerSize, 825 DRM_REGISTERS, flags, &info->registerHandle) < 0) { 826 return FALSE; 827 } 828 xf86DrvMsg(pScreen->myNum, X_INFO, 829 "[drm] register handle = 0x%08x\n", info->registerHandle); 830 831 return TRUE; 832} 833 834/* Initialize the kernel data structures. */ 835static int R128DRIKernelInit(R128InfoPtr info, ScreenPtr pScreen) 836{ 837 drmR128Init drmInfo; 838 839 memset( &drmInfo, 0, sizeof(drmR128Init) ); 840 841 drmInfo.func = DRM_R128_INIT_CCE; 842 drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); 843 drmInfo.is_pci = info->IsPCI; 844 drmInfo.cce_mode = info->CCEMode; 845 drmInfo.cce_secure = info->CCESecure; 846 drmInfo.ring_size = info->ringSize*1024*1024; 847 drmInfo.usec_timeout = info->CCEusecTimeout; 848 849 drmInfo.fb_bpp = info->CurrentLayout.pixel_code; 850 drmInfo.depth_bpp = info->CurrentLayout.pixel_code; 851 852 drmInfo.front_offset = info->frontOffset; 853 drmInfo.front_pitch = info->frontPitch; 854 855 drmInfo.back_offset = info->backOffset; 856 drmInfo.back_pitch = info->backPitch; 857 858 drmInfo.depth_offset = info->depthOffset; 859 drmInfo.depth_pitch = info->depthPitch; 860 drmInfo.span_offset = info->spanOffset; 861 862 drmInfo.fb_offset = info->fbHandle; 863 drmInfo.mmio_offset = info->registerHandle; 864 drmInfo.ring_offset = info->ringHandle; 865 drmInfo.ring_rptr_offset = info->ringReadPtrHandle; 866 drmInfo.buffers_offset = info->bufHandle; 867 drmInfo.agp_textures_offset = info->agpTexHandle; 868 869 if (drmCommandWrite(info->drmFD, DRM_R128_INIT, 870 &drmInfo, sizeof(drmR128Init)) < 0) 871 return FALSE; 872 873 return TRUE; 874} 875 876/* Add a map for the vertex buffers that will be accessed by any 877 DRI-based clients. */ 878static Bool R128DRIBufInit(R128InfoPtr info, ScreenPtr pScreen) 879{ 880 /* Initialize vertex buffers */ 881 if (info->IsPCI) { 882 info->bufNumBufs = drmAddBufs(info->drmFD, 883 info->bufMapSize / R128_BUFFER_SIZE, 884 R128_BUFFER_SIZE, 885 DRM_SG_BUFFER, 886 info->bufStart); 887 } else { 888 info->bufNumBufs = drmAddBufs(info->drmFD, 889 info->bufMapSize / R128_BUFFER_SIZE, 890 R128_BUFFER_SIZE, 891 DRM_AGP_BUFFER, 892 info->bufStart); 893 } 894 if (info->bufNumBufs <= 0) { 895 xf86DrvMsg(pScreen->myNum, X_ERROR, 896 "[drm] Could not create vertex/indirect buffers list\n"); 897 return FALSE; 898 } 899 xf86DrvMsg(pScreen->myNum, X_INFO, 900 "[drm] Added %d %d byte vertex/indirect buffers\n", 901 info->bufNumBufs, R128_BUFFER_SIZE); 902 903 if (!(info->buffers = drmMapBufs(info->drmFD))) { 904 xf86DrvMsg(pScreen->myNum, X_ERROR, 905 "[drm] Failed to map vertex/indirect buffers list\n"); 906 return FALSE; 907 } 908 xf86DrvMsg(pScreen->myNum, X_INFO, 909 "[drm] Mapped %d vertex/indirect buffers\n", 910 info->buffers->count); 911 912 return TRUE; 913} 914 915static void R128DRIIrqInit(R128InfoPtr info, ScreenPtr pScreen) 916{ 917 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 918 919 if (!info->irq) { 920 info->irq = drmGetInterruptFromBusID( 921 info->drmFD, 922 PCI_CFG_BUS(info->PciInfo), 923 PCI_CFG_DEV(info->PciInfo), 924 PCI_CFG_FUNC(info->PciInfo)); 925 926 if((drmCtlInstHandler(info->drmFD, info->irq)) != 0) { 927 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 928 "[drm] failure adding irq handler, " 929 "there is a device already using that irq\n" 930 "[drm] falling back to irq-free operation\n"); 931 info->irq = 0; 932 } else { 933 unsigned char *R128MMIO = info->MMIO; 934 info->gen_int_cntl = INREG( R128_GEN_INT_CNTL ); 935 } 936 } 937 938 if (info->irq) 939 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 940 "[drm] dma control initialized, using IRQ %d\n", 941 info->irq); 942} 943 944/* Initialize the CCE state, and start the CCE (if used by the X server) */ 945static void R128DRICCEInit(ScrnInfoPtr pScrn) 946{ 947 R128InfoPtr info = R128PTR(pScrn); 948 949 /* Turn on bus mastering */ 950 info->BusCntl &= ~R128_BUS_MASTER_DIS; 951 952 /* CCEMode is initialized in r128_driver.c */ 953 switch (info->CCEMode) { 954 case R128_PM4_NONPM4: info->CCEFifoSize = 0; break; 955 case R128_PM4_192PIO: info->CCEFifoSize = 192; break; 956 case R128_PM4_192BM: info->CCEFifoSize = 192; break; 957 case R128_PM4_128PIO_64INDBM: info->CCEFifoSize = 128; break; 958 case R128_PM4_128BM_64INDBM: info->CCEFifoSize = 128; break; 959 case R128_PM4_64PIO_128INDBM: info->CCEFifoSize = 64; break; 960 case R128_PM4_64BM_128INDBM: info->CCEFifoSize = 64; break; 961 case R128_PM4_64PIO_64VCBM_64INDBM: info->CCEFifoSize = 64; break; 962 case R128_PM4_64BM_64VCBM_64INDBM: info->CCEFifoSize = 64; break; 963 case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64; break; 964 } 965 966 if (info->directRenderingEnabled) { 967 /* Make sure the CCE is on for the X server */ 968 R128CCE_START(pScrn, info); 969 } else { 970 /* Make sure the CCE is off for the X server */ 971 R128CCE_STOP(pScrn, info); 972 } 973} 974 975/* Initialize the screen-specific data structures for the DRI and the 976 Rage 128. This is the main entry point to the device-specific 977 initialization code. It calls device-independent DRI functions to 978 create the DRI data structures and initialize the DRI state. */ 979Bool R128DRIScreenInit(ScreenPtr pScreen) 980{ 981 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 982 R128InfoPtr info = R128PTR(pScrn); 983 DRIInfoPtr pDRIInfo; 984 R128DRIPtr pR128DRI; 985 int major, minor, patch; 986 drmVersionPtr version; 987 988 /* Check that the GLX, DRI, and DRM modules have been loaded by testing 989 * for known symbols in each module. */ 990 if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE; 991 if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE; 992 if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { 993 xf86DrvMsg(pScreen->myNum, X_ERROR, 994 "[dri] R128DRIScreenInit failed (libdri.a too old)\n"); 995 return FALSE; 996 } 997 998 /* Check the DRI version */ 999 DRIQueryVersion(&major, &minor, &patch); 1000 if (major != DRIINFO_MAJOR_VERSION || minor < 0) { 1001 xf86DrvMsg(pScreen->myNum, X_ERROR, 1002 "[dri] R128DRIScreenInit failed because of a version mismatch.\n" 1003 "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n" 1004 "[dri] Disabling the DRI.\n", 1005 major, minor, patch, 1006 DRIINFO_MAJOR_VERSION, 0); 1007 return FALSE; 1008 } 1009 1010 switch (info->CurrentLayout.pixel_code) { 1011 case 8: 1012 /* These modes are not supported (yet). */ 1013 case 15: 1014 case 24: 1015 xf86DrvMsg(pScreen->myNum, X_ERROR, 1016 "[dri] R128DRIScreenInit failed (depth %d not supported). " 1017 "[dri] Disabling DRI.\n", info->CurrentLayout.pixel_code); 1018 return FALSE; 1019 1020 /* Only 16 and 32 color depths are supports currently. */ 1021 case 16: 1022 case 32: 1023 break; 1024 } 1025 1026 r128_drm_page_size = getpagesize(); 1027 1028 /* Create the DRI data structure, and fill it in before calling the 1029 DRIScreenInit(). */ 1030 if (!(pDRIInfo = DRICreateInfoRec())) return FALSE; 1031 1032 info->pDRIInfo = pDRIInfo; 1033 pDRIInfo->drmDriverName = R128_DRIVER_NAME; 1034 pDRIInfo->clientDriverName = R128_DRIVER_NAME; 1035 if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { 1036 pDRIInfo->busIdString = DRICreatePCIBusID(info->PciInfo); 1037 } else { 1038 pDRIInfo->busIdString = malloc(64); 1039 sprintf(pDRIInfo->busIdString, 1040 "PCI:%d:%d:%d", 1041 PCI_DEV_BUS(info->PciInfo), 1042 PCI_DEV_DEV(info->PciInfo), 1043 PCI_DEV_FUNC(info->PciInfo)); 1044 } 1045 pDRIInfo->ddxDriverMajorVersion = R128_VERSION_MAJOR; 1046 pDRIInfo->ddxDriverMinorVersion = R128_VERSION_MINOR; 1047 pDRIInfo->ddxDriverPatchVersion = R128_VERSION_PATCH; 1048 pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr; 1049 pDRIInfo->frameBufferSize = info->FbMapSize; 1050 pDRIInfo->frameBufferStride = (pScrn->displayWidth * 1051 info->CurrentLayout.pixel_bytes); 1052 pDRIInfo->ddxDrawableTableEntry = R128_MAX_DRAWABLES; 1053 pDRIInfo->maxDrawableTableEntry = (SAREA_MAX_DRAWABLES 1054 < R128_MAX_DRAWABLES 1055 ? SAREA_MAX_DRAWABLES 1056 : R128_MAX_DRAWABLES); 1057 1058#ifdef NOT_DONE 1059 /* FIXME: Need to extend DRI protocol to pass this size back to 1060 * client for SAREA mapping that includes a device private record 1061 */ 1062 pDRIInfo->SAREASize = 1063 ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */ 1064 /* + shared memory device private rec */ 1065#else 1066 /* For now the mapping works by using a fixed size defined 1067 * in the SAREA header 1068 */ 1069 if (sizeof(XF86DRISAREARec)+sizeof(R128SAREAPriv)>SAREA_MAX) { 1070 xf86DrvMsg(pScreen->myNum, X_ERROR, 1071 "[dri] Data does not fit in SAREA. Disabling DRI.\n"); 1072 return FALSE; 1073 } 1074 pDRIInfo->SAREASize = SAREA_MAX; 1075#endif 1076 1077 if (!(pR128DRI = (R128DRIPtr)calloc(sizeof(R128DRIRec),1))) { 1078 DRIDestroyInfoRec(info->pDRIInfo); 1079 info->pDRIInfo = NULL; 1080 return FALSE; 1081 } 1082 pDRIInfo->devPrivate = pR128DRI; 1083 pDRIInfo->devPrivateSize = sizeof(R128DRIRec); 1084 pDRIInfo->contextSize = sizeof(R128DRIContextRec); 1085 1086 pDRIInfo->CreateContext = R128CreateContext; 1087 pDRIInfo->DestroyContext = R128DestroyContext; 1088 pDRIInfo->SwapContext = R128DRISwapContext; 1089 pDRIInfo->InitBuffers = R128DRIInitBuffers; 1090 pDRIInfo->MoveBuffers = R128DRIMoveBuffers; 1091 pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; 1092 pDRIInfo->TransitionTo2d = R128DRITransitionTo2d; 1093 pDRIInfo->TransitionTo3d = R128DRITransitionTo3d; 1094 pDRIInfo->TransitionSingleToMulti3D = R128DRITransitionSingleToMulti3d; 1095 pDRIInfo->TransitionMultiToSingle3D = R128DRITransitionMultiToSingle3d; 1096 1097 pDRIInfo->createDummyCtx = TRUE; 1098 pDRIInfo->createDummyCtxPriv = FALSE; 1099 1100 if (!DRIScreenInit(pScreen, pDRIInfo, &info->drmFD)) { 1101 xf86DrvMsg(pScreen->myNum, X_ERROR, 1102 "[dri] DRIScreenInit failed. Disabling DRI.\n"); 1103 free(pDRIInfo->devPrivate); 1104 pDRIInfo->devPrivate = NULL; 1105 DRIDestroyInfoRec(pDRIInfo); 1106 pDRIInfo = NULL; 1107 return FALSE; 1108 } 1109 1110 /* Check the DRM lib version. 1111 drmGetLibVersion was not supported in version 1.0, so check for 1112 symbol first to avoid possible crash or hang. 1113 */ 1114 if (xf86LoaderCheckSymbol("drmGetLibVersion")) { 1115 version = drmGetLibVersion(info->drmFD); 1116 } 1117 else { 1118 /* drmlib version 1.0.0 didn't have the drmGetLibVersion 1119 entry point. Fake it by allocating a version record 1120 via drmGetVersion and changing it to version 1.0.0 1121 */ 1122 version = drmGetVersion(info->drmFD); 1123 version->version_major = 1; 1124 version->version_minor = 0; 1125 version->version_patchlevel = 0; 1126 } 1127 1128 if (version) { 1129 if (version->version_major != 1 || 1130 version->version_minor < 1) { 1131 /* incompatible drm library version */ 1132 xf86DrvMsg(pScreen->myNum, X_ERROR, 1133 "[dri] R128DRIScreenInit failed because of a version mismatch.\n" 1134 "[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n" 1135 "[dri] Disabling DRI.\n", 1136 version->version_major, 1137 version->version_minor, 1138 version->version_patchlevel); 1139 drmFreeVersion(version); 1140 R128DRICloseScreen(pScreen); 1141 return FALSE; 1142 } 1143 drmFreeVersion(version); 1144 } 1145 1146 /* Check the r128 DRM version */ 1147 version = drmGetVersion(info->drmFD); 1148 if (version) { 1149 if (version->version_major != 2 || 1150 version->version_minor < 2) { 1151 /* incompatible drm version */ 1152 xf86DrvMsg(pScreen->myNum, X_ERROR, 1153 "[dri] R128DRIScreenInit failed because of a version mismatch.\n" 1154 "[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n" 1155 "[dri] Disabling the DRI.\n", 1156 version->version_major, 1157 version->version_minor, 1158 version->version_patchlevel); 1159 drmFreeVersion(version); 1160 R128DRICloseScreen(pScreen); 1161 return FALSE; 1162 } 1163 info->drmMinor = version->version_minor; 1164 drmFreeVersion(version); 1165 } 1166 1167 /* Initialize AGP */ 1168 if (!info->IsPCI && !R128DRIAgpInit(info, pScreen)) { 1169 info->IsPCI = TRUE; 1170 xf86DrvMsg(pScreen->myNum, X_WARNING, 1171 "[agp] AGP failed to initialize -- falling back to PCI mode.\n"); 1172 xf86DrvMsg(pScreen->myNum, X_WARNING, 1173 "[agp] Make sure you have the agpgart kernel module loaded.\n"); 1174 } 1175 1176 /* Initialize PCIGART */ 1177 if (info->IsPCI && !R128DRIPciInit(info, pScreen)) { 1178 R128DRICloseScreen(pScreen); 1179 return FALSE; 1180 } 1181 1182 /* DRIScreenInit doesn't add all the 1183 common mappings. Add additional 1184 mappings here. */ 1185 if (!R128DRIMapInit(info, pScreen)) { 1186 R128DRICloseScreen(pScreen); 1187 return FALSE; 1188 } 1189 1190 /* DRIScreenInit adds the frame buffer 1191 map, but we need it as well */ 1192 { 1193 void *scratch_ptr; 1194 int scratch_int; 1195 1196 DRIGetDeviceInfo(pScreen, &info->fbHandle, 1197 &scratch_int, &scratch_int, 1198 &scratch_int, &scratch_int, 1199 &scratch_ptr); 1200 } 1201 1202 /* FIXME: When are these mappings unmapped? */ 1203 1204 if (!R128InitVisualConfigs(pScreen)) { 1205 R128DRICloseScreen(pScreen); 1206 return FALSE; 1207 } 1208 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n"); 1209 1210 return TRUE; 1211} 1212 1213/* Finish initializing the device-dependent DRI state, and call 1214 DRIFinishScreenInit() to complete the device-independent DRI 1215 initialization. */ 1216Bool R128DRIFinishScreenInit(ScreenPtr pScreen) 1217{ 1218 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1219 R128InfoPtr info = R128PTR(pScrn); 1220 R128SAREAPrivPtr pSAREAPriv; 1221 R128DRIPtr pR128DRI; 1222 1223 info->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; 1224 /* info->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */ 1225 1226 /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit 1227 because *DRIKernelInit requires that the hardware lock is held by 1228 the X server, and the first time the hardware lock is grabbed is 1229 in DRIFinishScreenInit. */ 1230 if (!DRIFinishScreenInit(pScreen)) { 1231 R128DRICloseScreen(pScreen); 1232 return FALSE; 1233 } 1234 1235 /* Initialize the kernel data structures */ 1236 if (!R128DRIKernelInit(info, pScreen)) { 1237 R128DRICloseScreen(pScreen); 1238 return FALSE; 1239 } 1240 1241 /* Initialize the vertex buffers list */ 1242 if (!R128DRIBufInit(info, pScreen)) { 1243 R128DRICloseScreen(pScreen); 1244 return FALSE; 1245 } 1246 1247 /* Initialize IRQ */ 1248 R128DRIIrqInit(info, pScreen); 1249 1250 /* Initialize and start the CCE if required */ 1251 R128DRICCEInit(pScrn); 1252 1253 pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScreen); 1254 memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); 1255 1256 pR128DRI = (R128DRIPtr)info->pDRIInfo->devPrivate; 1257 1258 pR128DRI->deviceID = info->Chipset; 1259 pR128DRI->width = pScrn->virtualX; 1260 pR128DRI->height = pScrn->virtualY; 1261 pR128DRI->depth = pScrn->depth; 1262 pR128DRI->bpp = pScrn->bitsPerPixel; 1263 1264 pR128DRI->IsPCI = info->IsPCI; 1265 pR128DRI->AGPMode = info->agpMode; 1266 1267 pR128DRI->frontOffset = info->frontOffset; 1268 pR128DRI->frontPitch = info->frontPitch; 1269 pR128DRI->backOffset = info->backOffset; 1270 pR128DRI->backPitch = info->backPitch; 1271 pR128DRI->depthOffset = info->depthOffset; 1272 pR128DRI->depthPitch = info->depthPitch; 1273 pR128DRI->spanOffset = info->spanOffset; 1274 pR128DRI->textureOffset = info->textureOffset; 1275 pR128DRI->textureSize = info->textureSize; 1276 pR128DRI->log2TexGran = info->log2TexGran; 1277 1278 pR128DRI->registerHandle = info->registerHandle; 1279 pR128DRI->registerSize = info->registerSize; 1280 1281 pR128DRI->agpTexHandle = info->agpTexHandle; 1282 pR128DRI->agpTexMapSize = info->agpTexMapSize; 1283 pR128DRI->log2AGPTexGran = info->log2AGPTexGran; 1284 pR128DRI->agpTexOffset = info->agpTexStart; 1285 pR128DRI->sarea_priv_offset = sizeof(XF86DRISAREARec); 1286 1287 /* Have shadowfb run only while there is 3d active. */ 1288 if (info->allowPageFlip && info->drmMinor >= 5 ) { 1289 ShadowFBInit( pScreen, R128DRIRefreshArea ); 1290 } else if (info->allowPageFlip) { 1291 xf86DrvMsg(pScreen->myNum, X_WARNING, 1292 "[dri] Kernel module version 2.5.0 or newer is required for pageflipping.\n"); 1293 info->allowPageFlip = 0; 1294 } 1295 1296 return TRUE; 1297} 1298 1299/* The screen is being closed, so clean up any state and free any 1300 resources used by the DRI. */ 1301void R128DRICloseScreen(ScreenPtr pScreen) 1302{ 1303 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1304 R128InfoPtr info = R128PTR(pScrn); 1305 drmR128Init drmInfo; 1306 1307 /* Stop the CCE if it is still in use */ 1308 if (info->directRenderingEnabled) { 1309 R128CCE_STOP(pScrn, info); 1310 } 1311 1312 if (info->irq) { 1313 drmCtlUninstHandler(info->drmFD); 1314 info->irq = 0; 1315 info->gen_int_cntl = 0; 1316 } 1317 1318 /* De-allocate vertex buffers */ 1319 if (info->buffers) { 1320 drmUnmapBufs(info->buffers); 1321 info->buffers = NULL; 1322 } 1323 1324 /* De-allocate all kernel resources */ 1325 memset(&drmInfo, 0, sizeof(drmR128Init)); 1326 drmInfo.func = DRM_R128_CLEANUP_CCE; 1327 drmCommandWrite(info->drmFD, DRM_R128_INIT, 1328 &drmInfo, sizeof(drmR128Init)); 1329 1330 /* De-allocate all AGP resources */ 1331 if (info->agpTex) { 1332 drmUnmap(info->agpTex, info->agpTexMapSize); 1333 info->agpTex = NULL; 1334 } 1335 if (info->buf) { 1336 drmUnmap(info->buf, info->bufMapSize); 1337 info->buf = NULL; 1338 } 1339 if (info->ringReadPtr) { 1340 drmUnmap(info->ringReadPtr, info->ringReadMapSize); 1341 info->ringReadPtr = NULL; 1342 } 1343 if (info->ring) { 1344 drmUnmap(info->ring, info->ringMapSize); 1345 info->ring = NULL; 1346 } 1347 if (info->agpMemHandle != DRM_AGP_NO_HANDLE) { 1348 drmAgpUnbind(info->drmFD, info->agpMemHandle); 1349 drmAgpFree(info->drmFD, info->agpMemHandle); 1350 info->agpMemHandle = DRM_AGP_NO_HANDLE; 1351 drmAgpRelease(info->drmFD); 1352 } 1353 if (info->pciMemHandle) { 1354 drmScatterGatherFree(info->drmFD, info->pciMemHandle); 1355 info->pciMemHandle = 0; 1356 } 1357 1358 /* De-allocate all DRI resources */ 1359 DRICloseScreen(pScreen); 1360 1361 /* De-allocate all DRI data structures */ 1362 if (info->pDRIInfo) { 1363 if (info->pDRIInfo->devPrivate) { 1364 free(info->pDRIInfo->devPrivate); 1365 info->pDRIInfo->devPrivate = NULL; 1366 } 1367 DRIDestroyInfoRec(info->pDRIInfo); 1368 info->pDRIInfo = NULL; 1369 } 1370 if (info->pVisualConfigs) { 1371 free(info->pVisualConfigs); 1372 info->pVisualConfigs = NULL; 1373 } 1374 if (info->pVisualConfigsPriv) { 1375 free(info->pVisualConfigsPriv); 1376 info->pVisualConfigsPriv = NULL; 1377 } 1378} 1379 1380/* Use callbacks from dri.c to support pageflipping mode for a single 1381 * 3d context without need for any specific full-screen extension. 1382 */ 1383 1384/* Use the shadowfb module to maintain a list of dirty rectangles. 1385 * These are blitted to the back buffer to keep both buffers clean 1386 * during page-flipping when the 3d application isn't fullscreen. 1387 * 1388 * Unlike most use of the shadowfb code, both buffers are in video memory. 1389 * 1390 * An alternative to this would be to organize for all on-screen drawing 1391 * operations to be duplicated for the two buffers. That might be 1392 * faster, but seems like a lot more work... 1393 */ 1394 1395 1396static void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) 1397{ 1398 R128InfoPtr info = R128PTR(pScrn); 1399 int i; 1400 R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); 1401 PixmapPtr pPix = pScrn->pScreen->GetScreenPixmap(pScrn->pScreen); 1402 1403 /* Don't want to do this when no 3d is active and pages are 1404 * right-way-round 1405 */ 1406 if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) 1407 return; 1408 1409#ifdef HAVE_XAA_H 1410 if (!info->useEXA) { 1411 (*info->accel->SetupForScreenToScreenCopy)(pScrn, 1412 1, 1, GXcopy, 1413 (CARD32)(-1), -1); 1414 } 1415#endif 1416#ifdef USE_EXA 1417 if (info->useEXA) { 1418 CARD32 src_pitch_offset, dst_pitch_offset, datatype; 1419 1420 R128GetPixmapOffsetPitch(pPix, &src_pitch_offset); 1421 dst_pitch_offset = src_pitch_offset + (info->backOffset >> 5); 1422 R128GetDatatypeBpp(pScrn->bitsPerPixel, &datatype); 1423 info->xdir = info->ydir = 1; 1424 1425 R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, GXcopy, ~0); 1426 } 1427#endif 1428 1429 for (i = 0 ; i < num ; i++, pbox++) { 1430 int xa = max(pbox->x1, 0), xb = min(pbox->x2, pScrn->virtualX-1); 1431 int ya = max(pbox->y1, 0), yb = min(pbox->y2, pScrn->virtualY-1); 1432 1433 if (xa <= xb && ya <= yb) { 1434#ifdef HAVE_XAA_H 1435 if (!info->useEXA) { 1436 (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, 1437 xa + info->backX, 1438 ya + info->backY, 1439 xb - xa + 1, 1440 yb - ya + 1); 1441 } 1442#endif 1443#ifdef USE_EXA 1444 if (info->useEXA) { 1445 (*info->ExaDriver->Copy)(pPix, xa, ya, xa, ya, xb - xa + 1, yb - ya + 1); 1446 } 1447#endif 1448 } 1449 } 1450} 1451 1452static void R128EnablePageFlip(ScreenPtr pScreen) 1453{ 1454 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1455 R128InfoPtr info = R128PTR(pScrn); 1456 R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); 1457 PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); 1458 1459 if (info->allowPageFlip) { 1460 /* Duplicate the frontbuffer to the backbuffer */ 1461#ifdef HAVE_XAA_H 1462 if (!info->useEXA) { 1463 (*info->accel->SetupForScreenToScreenCopy)(pScrn, 1464 1, 1, GXcopy, 1465 (CARD32)(-1), -1); 1466 1467 (*info->accel->SubsequentScreenToScreenCopy)(pScrn, 1468 0, 1469 0, 1470 info->backX, 1471 info->backY, 1472 pScrn->virtualX, 1473 pScrn->virtualY); 1474 } 1475#endif 1476#ifdef USE_EXA 1477 if (info->useEXA) { 1478 CARD32 src_pitch_offset, dst_pitch_offset, datatype; 1479 1480 R128GetPixmapOffsetPitch(pPix, &src_pitch_offset); 1481 dst_pitch_offset = src_pitch_offset + (info->backOffset >> 5); 1482 R128GetDatatypeBpp(pScrn->bitsPerPixel, &datatype); 1483 info->xdir = info->ydir = 1; 1484 1485 R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, GXcopy, ~0); 1486 1487 (*info->ExaDriver->Copy)(pPix, 0, 0, 0, 0, pScrn->virtualX, pScrn->virtualY); 1488 } 1489#endif 1490 1491 pSAREAPriv->pfAllowPageFlip = 1; 1492 } 1493} 1494 1495static void R128DisablePageFlip(ScreenPtr pScreen) 1496{ 1497 /* Tell the clients not to pageflip. How? 1498 * -- Field in sarea, plus bumping the window counters. 1499 * -- DRM needs to cope with Front-to-Back swapbuffers. 1500 */ 1501 R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); 1502 1503 pSAREAPriv->pfAllowPageFlip = 0; 1504} 1505 1506static void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen) 1507{ 1508 R128DisablePageFlip(pScreen); 1509} 1510 1511static void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen) 1512{ 1513 /* Let the remaining 3d app start page flipping again */ 1514 R128EnablePageFlip(pScreen); 1515} 1516 1517static void R128DRITransitionTo3d(ScreenPtr pScreen) 1518{ 1519 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1520 R128InfoPtr info = R128PTR(pScrn); 1521 1522 R128EnablePageFlip(pScreen); 1523 1524 info->have3DWindows = 1; 1525 1526 if (info->cursor_start) 1527 xf86ForceHWCursor(pScreen, TRUE); 1528} 1529 1530static void R128DRITransitionTo2d(ScreenPtr pScreen) 1531{ 1532 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1533 R128InfoPtr info = R128PTR(pScrn); 1534 R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); 1535 1536 /* Try flipping back to the front page if necessary */ 1537 if (pSAREAPriv->pfCurrentPage == 1) 1538 drmCommandNone(info->drmFD, DRM_R128_FLIP); 1539 1540 /* Shut down shadowing if we've made it back to the front page */ 1541 if (pSAREAPriv->pfCurrentPage == 0) { 1542 R128DisablePageFlip(pScreen); 1543 } else { 1544 xf86DrvMsg(pScreen->myNum, X_WARNING, 1545 "[dri] R128DRITransitionTo2d: " 1546 "kernel failed to unflip buffers.\n"); 1547 } 1548 1549 info->have3DWindows = 0; 1550 1551 if (info->cursor_start) 1552 xf86ForceHWCursor(pScreen, FALSE); 1553} 1554