r128_dri.c revision c582b7e3
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 = xf86Screens[pScreen->myNum]; 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*)xcalloc(sizeof(__GLXvisualConfig), 109 numConfigs))) { 110 return FALSE; 111 } 112 if (!(pR128Configs 113 = (R128ConfigPrivPtr)xcalloc(sizeof(R128ConfigPrivRec), 114 numConfigs))) { 115 xfree(pConfigs); 116 return FALSE; 117 } 118 if (!(pR128ConfigPtrs 119 = (R128ConfigPrivPtr*)xcalloc(sizeof(R128ConfigPrivPtr), 120 numConfigs))) { 121 xfree(pConfigs); 122 xfree(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*)xcalloc(sizeof(__GLXvisualConfig), 192 numConfigs))) { 193 return FALSE; 194 } 195 if (!(pR128Configs 196 = (R128ConfigPrivPtr)xcalloc(sizeof(R128ConfigPrivRec), 197 numConfigs))) { 198 xfree(pConfigs); 199 return FALSE; 200 } 201 if (!(pR128ConfigPtrs 202 = (R128ConfigPrivPtr*)xcalloc(sizeof(R128ConfigPrivPtr), 203 numConfigs))) { 204 xfree(pConfigs); 205 xfree(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 = xf86Screens[pScreen->myNum]; 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 = xf86Screens[pScreen->myNum]; 305 R128InfoPtr info = R128PTR(pScrn); 306 307 if (info->accel) info->accel->NeedToSync = TRUE; 308} 309 310/* Called when the X server goes to sleep to allow the X server's 311 context to be saved and the last client's context to be loaded. This 312 is not necessary for the Rage 128 since the client detects when it's 313 context is not currently loaded and then load's it itself. Since the 314 registers to start and stop the CCE are privileged, only the X server 315 can start/stop the engine. */ 316static void R128LeaveServer(ScreenPtr pScreen) 317{ 318 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 319 R128InfoPtr info = R128PTR(pScrn); 320 unsigned char *R128MMIO = info->MMIO; 321 322 if (!info->directRenderingEnabled) { 323 /* Save all hardware scissors */ 324 info->sc_left = INREG(R128_SC_LEFT); 325 info->sc_right = INREG(R128_SC_RIGHT); 326 info->sc_top = INREG(R128_SC_TOP); 327 info->sc_bottom = INREG(R128_SC_BOTTOM); 328 info->aux_sc_cntl = INREG(R128_SC_BOTTOM); 329 } else if (info->CCEInUse) { 330 R128CCEReleaseIndirect(pScrn); 331 332 info->CCEInUse = FALSE; 333 } 334} 335 336/* Contexts can be swapped by the X server if necessary. This callback 337 is currently only used to perform any functions necessary when 338 entering or leaving the X server, and in the future might not be 339 necessary. */ 340static void R128DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 341 DRIContextType oldContextType, void *oldContext, 342 DRIContextType newContextType, void *newContext) 343{ 344 if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) && 345 (newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */ 346 R128EnterServer(pScreen); 347 } 348 if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) && 349 (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */ 350 R128LeaveServer(pScreen); 351 } 352} 353 354/* Initialize the state of the back and depth buffers. */ 355static void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx) 356{ 357 /* FIXME: This routine needs to have acceleration turned on */ 358 ScreenPtr pScreen = pWin->drawable.pScreen; 359 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 360 R128InfoPtr info = R128PTR(pScrn); 361 BoxPtr pbox, pboxSave; 362 int nbox, nboxSave; 363 int depth; 364 365 /* FIXME: Use accel when CCE 2D code is written 366 * EA: What is this code kept for? Radeon doesn't have it and 367 * has a comment: "There's no need for the 2d driver to be clearing 368 * buffers for the 3d client. It knows how to do that on its own." 369 */ 370 if (info->directRenderingEnabled) 371 return; 372 373 /* FIXME: This should be based on the __GLXvisualConfig info */ 374 switch (pScrn->bitsPerPixel) { 375 case 8: depth = 0x000000ff; break; 376 case 16: depth = 0x0000ffff; break; 377 case 24: depth = 0x00ffffff; break; 378 case 32: depth = 0xffffffff; break; 379 default: depth = 0x00000000; break; 380 } 381 382 /* FIXME: Copy XAAPaintWindow() and use REGION_TRANSLATE() */ 383 /* FIXME: Only initialize the back and depth buffers for contexts 384 that request them */ 385 386 pboxSave = pbox = REGION_RECTS(prgn); 387 nboxSave = nbox = REGION_NUM_RECTS(prgn); 388 389 (*info->accel->SetupForSolidFill)(pScrn, 0, GXcopy, (CARD32)(-1)); 390 for (; nbox; nbox--, pbox++) { 391 (*info->accel->SubsequentSolidFillRect)(pScrn, 392 pbox->x1 + info->fbX, 393 pbox->y1 + info->fbY, 394 pbox->x2 - pbox->x1, 395 pbox->y2 - pbox->y1); 396 (*info->accel->SubsequentSolidFillRect)(pScrn, 397 pbox->x1 + info->backX, 398 pbox->y1 + info->backY, 399 pbox->x2 - pbox->x1, 400 pbox->y2 - pbox->y1); 401 } 402 403 pbox = pboxSave; 404 nbox = nboxSave; 405 406 /* FIXME: this needs to consider depth tiling. */ 407 (*info->accel->SetupForSolidFill)(pScrn, depth, GXcopy, (CARD32)(-1)); 408 for (; nbox; nbox--, pbox++) 409 (*info->accel->SubsequentSolidFillRect)(pScrn, 410 pbox->x1 + info->depthX, 411 pbox->y1 + info->depthY, 412 pbox->x2 - pbox->x1, 413 pbox->y2 - pbox->y1); 414 415 info->accel->NeedToSync = TRUE; 416} 417 418/* Copy the back and depth buffers when the X server moves a window. */ 419static void R128DRIMoveBuffers(WindowPtr pWin, DDXPointRec ptOldOrg, 420 RegionPtr prgnSrc, CARD32 indx) 421{ 422 ScreenPtr pScreen = pWin->drawable.pScreen; 423 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 424 R128InfoPtr info = R128PTR(pScrn); 425 426 /* FIXME: This routine needs to have acceleration turned on */ 427 /* FIXME: Copy XAACopyWindow() and use REGION_TRANSLATE() */ 428 /* FIXME: Only initialize the back and depth buffers for contexts 429 that request them */ 430 431 /* FIXME: Use accel when CCE 2D code is written */ 432 if (info->directRenderingEnabled) 433 return; 434} 435 436/* Initialize the AGP state. Request memory for use in AGP space, and 437 initialize the Rage 128 registers to point to that memory. */ 438static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen) 439{ 440 unsigned char *R128MMIO = info->MMIO; 441 unsigned long mode; 442 unsigned int vendor, device; 443 int ret; 444 unsigned long cntl, chunk; 445 int s, l; 446 int flags; 447 unsigned long agpBase; 448 449 if (drmAgpAcquire(info->drmFD) < 0) { 450 xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] AGP not available\n"); 451 return FALSE; 452 } 453 454 /* Modify the mode if the default mode is 455 not appropriate for this particular 456 combination of graphics card and AGP 457 chipset. */ 458 459 mode = drmAgpGetMode(info->drmFD); /* Default mode */ 460 vendor = drmAgpVendorId(info->drmFD); 461 device = drmAgpDeviceId(info->drmFD); 462 463 mode &= ~R128_AGP_MODE_MASK; 464 switch (info->agpMode) { 465 case 4: mode |= R128_AGP_4X_MODE; 466 case 2: mode |= R128_AGP_2X_MODE; 467 case 1: default: mode |= R128_AGP_1X_MODE; 468 } 469 470 xf86DrvMsg(pScreen->myNum, X_INFO, 471 "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", 472 mode, vendor, device, 473 PCI_DEV_VENDOR_ID(info->PciInfo), 474 PCI_DEV_DEVICE_ID(info->PciInfo)); 475 476 if (drmAgpEnable(info->drmFD, mode) < 0) { 477 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n"); 478 drmAgpRelease(info->drmFD); 479 return FALSE; 480 } 481 482 info->agpOffset = 0; 483 484 if ((ret = drmAgpAlloc(info->drmFD, info->agpSize*1024*1024, 0, NULL, 485 &info->agpMemHandle)) < 0) { 486 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret); 487 drmAgpRelease(info->drmFD); 488 return FALSE; 489 } 490 xf86DrvMsg(pScreen->myNum, X_INFO, 491 "[agp] %d kB allocated with handle 0x%08x\n", 492 info->agpSize*1024, info->agpMemHandle); 493 494 if (drmAgpBind(info->drmFD, info->agpMemHandle, info->agpOffset) < 0) { 495 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n"); 496 drmAgpFree(info->drmFD, info->agpMemHandle); 497 drmAgpRelease(info->drmFD); 498 return FALSE; 499 } 500 501 /* Initialize the CCE ring buffer data */ 502 info->ringStart = info->agpOffset; 503 info->ringMapSize = info->ringSize*1024*1024 + r128_drm_page_size; 504 info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1; 505 506 info->ringReadOffset = info->ringStart + info->ringMapSize; 507 info->ringReadMapSize = r128_drm_page_size; 508 509 /* Reserve space for vertex/indirect buffers */ 510 info->bufStart = info->ringReadOffset + info->ringReadMapSize; 511 info->bufMapSize = info->bufSize*1024*1024; 512 513 /* Reserve the rest for AGP textures */ 514 info->agpTexStart = info->bufStart + info->bufMapSize; 515 s = (info->agpSize*1024*1024 - info->agpTexStart); 516 l = R128MinBits((s-1) / R128_NR_TEX_REGIONS); 517 if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; 518 info->agpTexMapSize = (s >> l) << l; 519 info->log2AGPTexGran = l; 520 521 if (info->CCESecure) flags = DRM_READ_ONLY; 522 else flags = 0; 523 524 if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize, 525 DRM_AGP, flags, &info->ringHandle) < 0) { 526 xf86DrvMsg(pScreen->myNum, X_ERROR, 527 "[agp] Could not add ring mapping\n"); 528 return FALSE; 529 } 530 xf86DrvMsg(pScreen->myNum, X_INFO, 531 "[agp] ring handle = 0x%08x\n", info->ringHandle); 532 533 if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, 534 &info->ring) < 0) { 535 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n"); 536 return FALSE; 537 } 538 xf86DrvMsg(pScreen->myNum, X_INFO, 539 "[agp] Ring mapped at 0x%08lx\n", 540 (unsigned long)info->ring); 541 542 if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize, 543 DRM_AGP, flags, &info->ringReadPtrHandle) < 0) { 544 xf86DrvMsg(pScreen->myNum, X_ERROR, 545 "[agp] Could not add ring read ptr mapping\n"); 546 return FALSE; 547 } 548 xf86DrvMsg(pScreen->myNum, X_INFO, 549 "[agp] ring read ptr handle = 0x%08x\n", 550 info->ringReadPtrHandle); 551 552 if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, 553 &info->ringReadPtr) < 0) { 554 xf86DrvMsg(pScreen->myNum, X_ERROR, 555 "[agp] Could not map ring read ptr\n"); 556 return FALSE; 557 } 558 xf86DrvMsg(pScreen->myNum, X_INFO, 559 "[agp] Ring read ptr mapped at 0x%08lx\n", 560 (unsigned long)info->ringReadPtr); 561 562 if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize, 563 DRM_AGP, 0, &info->bufHandle) < 0) { 564 xf86DrvMsg(pScreen->myNum, X_ERROR, 565 "[agp] Could not add vertex/indirect buffers mapping\n"); 566 return FALSE; 567 } 568 xf86DrvMsg(pScreen->myNum, X_INFO, 569 "[agp] vertex/indirect buffers handle = 0x%08x\n", 570 info->bufHandle); 571 572 if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize, 573 &info->buf) < 0) { 574 xf86DrvMsg(pScreen->myNum, X_ERROR, 575 "[agp] Could not map vertex/indirect buffers\n"); 576 return FALSE; 577 } 578 xf86DrvMsg(pScreen->myNum, X_INFO, 579 "[agp] Vertex/indirect buffers mapped at 0x%08lx\n", 580 (unsigned long)info->buf); 581 582 if (drmAddMap(info->drmFD, info->agpTexStart, info->agpTexMapSize, 583 DRM_AGP, 0, &info->agpTexHandle) < 0) { 584 xf86DrvMsg(pScreen->myNum, X_ERROR, 585 "[agp] Could not add AGP texture map mapping\n"); 586 return FALSE; 587 } 588 xf86DrvMsg(pScreen->myNum, X_INFO, 589 "[agp] AGP texture map handle = 0x%08x\n", 590 info->agpTexHandle); 591 592 if (drmMap(info->drmFD, info->agpTexHandle, info->agpTexMapSize, 593 &info->agpTex) < 0) { 594 xf86DrvMsg(pScreen->myNum, X_ERROR, 595 "[agp] Could not map AGP texture map\n"); 596 return FALSE; 597 } 598 xf86DrvMsg(pScreen->myNum, X_INFO, 599 "[agp] AGP Texture map mapped at 0x%08lx\n", 600 (unsigned long)info->agpTex); 601 602 /* Initialize Rage 128's AGP registers */ 603 cntl = INREG(R128_AGP_CNTL); 604 cntl &= ~R128_AGP_APER_SIZE_MASK; 605 switch (info->agpSize) { 606 case 256: cntl |= R128_AGP_APER_SIZE_256MB; break; 607 case 128: cntl |= R128_AGP_APER_SIZE_128MB; break; 608 case 64: cntl |= R128_AGP_APER_SIZE_64MB; break; 609 case 32: cntl |= R128_AGP_APER_SIZE_32MB; break; 610 case 16: cntl |= R128_AGP_APER_SIZE_16MB; break; 611 case 8: cntl |= R128_AGP_APER_SIZE_8MB; break; 612 case 4: cntl |= R128_AGP_APER_SIZE_4MB; break; 613 default: 614 xf86DrvMsg(pScreen->myNum, X_ERROR, 615 "[agp] Illegal aperture size %d kB\n", 616 info->agpSize*1024); 617 return FALSE; 618 } 619 agpBase = drmAgpBase(info->drmFD); 620 OUTREG(R128_AGP_BASE, agpBase); 621 OUTREG(R128_AGP_CNTL, cntl); 622 623 /* Disable Rage 128's PCIGART registers */ 624 chunk = INREG(R128_BM_CHUNK_0_VAL); 625 chunk &= ~(R128_BM_PTR_FORCE_TO_PCI | 626 R128_BM_PM4_RD_FORCE_TO_PCI | 627 R128_BM_GLOBAL_FORCE_TO_PCI); 628 OUTREG(R128_BM_CHUNK_0_VAL, chunk); 629 630 OUTREG(R128_PCI_GART_PAGE, 1); /* Ensure AGP GART is used (for now) */ 631 632 return TRUE; 633} 634 635static Bool R128DRIPciInit(R128InfoPtr info, ScreenPtr pScreen) 636{ 637 unsigned char *R128MMIO = info->MMIO; 638 CARD32 chunk; 639 int ret; 640 int flags; 641 642 info->agpOffset = 0; 643 644 ret = drmScatterGatherAlloc(info->drmFD, info->agpSize*1024*1024, 645 &info->pciMemHandle); 646 if (ret < 0) { 647 xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Out of memory (%d)\n", ret); 648 return FALSE; 649 } 650 xf86DrvMsg(pScreen->myNum, X_INFO, 651 "[pci] %d kB allocated with handle 0x%08x\n", 652 info->agpSize*1024, info->pciMemHandle); 653 654 /* Initialize the CCE ring buffer data */ 655 info->ringStart = info->agpOffset; 656 info->ringMapSize = info->ringSize*1024*1024 + r128_drm_page_size; 657 info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1; 658 659 info->ringReadOffset = info->ringStart + info->ringMapSize; 660 info->ringReadMapSize = r128_drm_page_size; 661 662 /* Reserve space for vertex/indirect buffers */ 663 info->bufStart = info->ringReadOffset + info->ringReadMapSize; 664 info->bufMapSize = info->bufSize*1024*1024; 665 666 flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL; 667 668 if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize, 669 DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) { 670 xf86DrvMsg(pScreen->myNum, X_ERROR, 671 "[pci] Could not add ring mapping\n"); 672 return FALSE; 673 } 674 xf86DrvMsg(pScreen->myNum, X_INFO, 675 "[pci] ring handle = 0x%08x\n", info->ringHandle); 676 677 if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, 678 &info->ring) < 0) { 679 xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n"); 680 return FALSE; 681 } 682 xf86DrvMsg(pScreen->myNum, X_INFO, 683 "[pci] Ring mapped at 0x%08lx\n", 684 (unsigned long)info->ring); 685 xf86DrvMsg(pScreen->myNum, X_INFO, 686 "[pci] Ring contents 0x%08lx\n", 687 *(unsigned long *)(pointer)info->ring); 688 689 if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize, 690 DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) { 691 xf86DrvMsg(pScreen->myNum, X_ERROR, 692 "[pci] Could not add ring read ptr mapping\n"); 693 return FALSE; 694 } 695 xf86DrvMsg(pScreen->myNum, X_INFO, 696 "[pci] ring read ptr handle = 0x%08x\n", 697 info->ringReadPtrHandle); 698 699 if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, 700 &info->ringReadPtr) < 0) { 701 xf86DrvMsg(pScreen->myNum, X_ERROR, 702 "[pci] Could not map ring read ptr\n"); 703 return FALSE; 704 } 705 xf86DrvMsg(pScreen->myNum, X_INFO, 706 "[pci] Ring read ptr mapped at 0x%08lx\n", 707 (unsigned long)info->ringReadPtr); 708 xf86DrvMsg(pScreen->myNum, X_INFO, 709 "[pci] Ring read ptr contents 0x%08lx\n", 710 *(unsigned long *)(pointer)info->ringReadPtr); 711 712 if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize, 713 DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) { 714 xf86DrvMsg(pScreen->myNum, X_ERROR, 715 "[pci] Could not add vertex/indirect buffers mapping\n"); 716 return FALSE; 717 } 718 xf86DrvMsg(pScreen->myNum, X_INFO, 719 "[pci] vertex/indirect buffers handle = 0x%08x\n", 720 info->bufHandle); 721 722 if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize, 723 &info->buf) < 0) { 724 xf86DrvMsg(pScreen->myNum, X_ERROR, 725 "[pci] Could not map vertex/indirect buffers\n"); 726 return FALSE; 727 } 728 xf86DrvMsg(pScreen->myNum, X_INFO, 729 "[pci] Vertex/indirect buffers mapped at 0x%08lx\n", 730 (unsigned long)info->buf); 731 xf86DrvMsg(pScreen->myNum, X_INFO, 732 "[pci] Vertex/indirect buffers contents 0x%08lx\n", 733 *(unsigned long *)(pointer)info->buf); 734 735 switch (info->Chipset) { 736 case PCI_CHIP_RAGE128LE: 737 case PCI_CHIP_RAGE128RE: 738 case PCI_CHIP_RAGE128RK: 739 case PCI_CHIP_RAGE128PD: 740 case PCI_CHIP_RAGE128PP: 741 case PCI_CHIP_RAGE128PR: 742 /* This is a PCI card, do nothing */ 743 break; 744 745 case PCI_CHIP_RAGE128LF: 746 case PCI_CHIP_RAGE128MF: 747 case PCI_CHIP_RAGE128ML: 748 case PCI_CHIP_RAGE128RF: 749 case PCI_CHIP_RAGE128RG: 750 case PCI_CHIP_RAGE128RL: 751 case PCI_CHIP_RAGE128SM: 752 case PCI_CHIP_RAGE128PF: 753 case PCI_CHIP_RAGE128TF: 754 case PCI_CHIP_RAGE128TL: 755 case PCI_CHIP_RAGE128TR: 756 /* FIXME: ATI documentation does not specify if the following chips are 757 * AGP or PCI, it just mentions their PCI IDs. I'm assuming they're AGP 758 * until I get more correct information. <mharris@redhat.com> 759 */ 760 case PCI_CHIP_RAGE128PA: 761 case PCI_CHIP_RAGE128PB: 762 case PCI_CHIP_RAGE128PC: 763 case PCI_CHIP_RAGE128PE: 764 case PCI_CHIP_RAGE128PG: 765 case PCI_CHIP_RAGE128PH: 766 case PCI_CHIP_RAGE128PI: 767 case PCI_CHIP_RAGE128PJ: 768 case PCI_CHIP_RAGE128PK: 769 case PCI_CHIP_RAGE128PL: 770 case PCI_CHIP_RAGE128PM: 771 case PCI_CHIP_RAGE128PN: 772 case PCI_CHIP_RAGE128PO: 773 case PCI_CHIP_RAGE128PQ: 774 case PCI_CHIP_RAGE128PS: 775 case PCI_CHIP_RAGE128PT: 776 case PCI_CHIP_RAGE128PU: 777 case PCI_CHIP_RAGE128PV: 778 case PCI_CHIP_RAGE128PW: 779 case PCI_CHIP_RAGE128PX: 780 case PCI_CHIP_RAGE128SE: 781 case PCI_CHIP_RAGE128SF: 782 case PCI_CHIP_RAGE128SG: 783 case PCI_CHIP_RAGE128SH: 784 case PCI_CHIP_RAGE128SK: 785 case PCI_CHIP_RAGE128SL: 786 case PCI_CHIP_RAGE128SN: 787 case PCI_CHIP_RAGE128TS: 788 case PCI_CHIP_RAGE128TT: 789 case PCI_CHIP_RAGE128TU: 790 default: 791 /* This is really an AGP card, force PCI GART mode */ 792 chunk = INREG(R128_BM_CHUNK_0_VAL); 793 chunk |= (R128_BM_PTR_FORCE_TO_PCI | 794 R128_BM_PM4_RD_FORCE_TO_PCI | 795 R128_BM_GLOBAL_FORCE_TO_PCI); 796 OUTREG(R128_BM_CHUNK_0_VAL, chunk); 797 OUTREG(R128_PCI_GART_PAGE, 0); /* Ensure PCI GART is used */ 798 break; 799 } 800 801 return TRUE; 802} 803 804/* Add a map for the MMIO registers that will be accessed by any 805 DRI-based clients. */ 806static Bool R128DRIMapInit(R128InfoPtr info, ScreenPtr pScreen) 807{ 808 int flags; 809 810 if (info->CCESecure) flags = DRM_READ_ONLY; 811 else flags = 0; 812 813 /* Map registers */ 814 info->registerSize = R128_MMIOSIZE; 815 if (drmAddMap(info->drmFD, info->MMIOAddr, info->registerSize, 816 DRM_REGISTERS, flags, &info->registerHandle) < 0) { 817 return FALSE; 818 } 819 xf86DrvMsg(pScreen->myNum, X_INFO, 820 "[drm] register handle = 0x%08x\n", info->registerHandle); 821 822 return TRUE; 823} 824 825/* Initialize the kernel data structures. */ 826static int R128DRIKernelInit(R128InfoPtr info, ScreenPtr pScreen) 827{ 828 drmR128Init drmInfo; 829 830 memset( &drmInfo, 0, sizeof(drmR128Init) ); 831 832 drmInfo.func = DRM_R128_INIT_CCE; 833 drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); 834 drmInfo.is_pci = info->IsPCI; 835 drmInfo.cce_mode = info->CCEMode; 836 drmInfo.cce_secure = info->CCESecure; 837 drmInfo.ring_size = info->ringSize*1024*1024; 838 drmInfo.usec_timeout = info->CCEusecTimeout; 839 840 drmInfo.fb_bpp = info->CurrentLayout.pixel_code; 841 drmInfo.depth_bpp = info->CurrentLayout.pixel_code; 842 843 drmInfo.front_offset = info->frontOffset; 844 drmInfo.front_pitch = info->frontPitch; 845 846 drmInfo.back_offset = info->backOffset; 847 drmInfo.back_pitch = info->backPitch; 848 849 drmInfo.depth_offset = info->depthOffset; 850 drmInfo.depth_pitch = info->depthPitch; 851 drmInfo.span_offset = info->spanOffset; 852 853 drmInfo.fb_offset = info->fbHandle; 854 drmInfo.mmio_offset = info->registerHandle; 855 drmInfo.ring_offset = info->ringHandle; 856 drmInfo.ring_rptr_offset = info->ringReadPtrHandle; 857 drmInfo.buffers_offset = info->bufHandle; 858 drmInfo.agp_textures_offset = info->agpTexHandle; 859 860 if (drmCommandWrite(info->drmFD, DRM_R128_INIT, 861 &drmInfo, sizeof(drmR128Init)) < 0) 862 return FALSE; 863 864 return TRUE; 865} 866 867/* Add a map for the vertex buffers that will be accessed by any 868 DRI-based clients. */ 869static Bool R128DRIBufInit(R128InfoPtr info, ScreenPtr pScreen) 870{ 871 /* Initialize vertex buffers */ 872 if (info->IsPCI) { 873 info->bufNumBufs = drmAddBufs(info->drmFD, 874 info->bufMapSize / R128_BUFFER_SIZE, 875 R128_BUFFER_SIZE, 876 DRM_SG_BUFFER, 877 info->bufStart); 878 } else { 879 info->bufNumBufs = drmAddBufs(info->drmFD, 880 info->bufMapSize / R128_BUFFER_SIZE, 881 R128_BUFFER_SIZE, 882 DRM_AGP_BUFFER, 883 info->bufStart); 884 } 885 if (info->bufNumBufs <= 0) { 886 xf86DrvMsg(pScreen->myNum, X_ERROR, 887 "[drm] Could not create vertex/indirect buffers list\n"); 888 return FALSE; 889 } 890 xf86DrvMsg(pScreen->myNum, X_INFO, 891 "[drm] Added %d %d byte vertex/indirect buffers\n", 892 info->bufNumBufs, R128_BUFFER_SIZE); 893 894 if (!(info->buffers = drmMapBufs(info->drmFD))) { 895 xf86DrvMsg(pScreen->myNum, X_ERROR, 896 "[drm] Failed to map vertex/indirect buffers list\n"); 897 return FALSE; 898 } 899 xf86DrvMsg(pScreen->myNum, X_INFO, 900 "[drm] Mapped %d vertex/indirect buffers\n", 901 info->buffers->count); 902 903 return TRUE; 904} 905 906static void R128DRIIrqInit(R128InfoPtr info, ScreenPtr pScreen) 907{ 908 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 909 910 if (!info->irq) { 911 info->irq = drmGetInterruptFromBusID( 912 info->drmFD, 913 PCI_CFG_BUS(info->PciInfo), 914 PCI_CFG_DEV(info->PciInfo), 915 PCI_CFG_FUNC(info->PciInfo)); 916 917 if((drmCtlInstHandler(info->drmFD, info->irq)) != 0) { 918 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 919 "[drm] failure adding irq handler, " 920 "there is a device already using that irq\n" 921 "[drm] falling back to irq-free operation\n"); 922 info->irq = 0; 923 } else { 924 unsigned char *R128MMIO = info->MMIO; 925 info->gen_int_cntl = INREG( R128_GEN_INT_CNTL ); 926 } 927 } 928 929 if (info->irq) 930 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 931 "[drm] dma control initialized, using IRQ %d\n", 932 info->irq); 933} 934 935/* Initialize the CCE state, and start the CCE (if used by the X server) */ 936static void R128DRICCEInit(ScrnInfoPtr pScrn) 937{ 938 R128InfoPtr info = R128PTR(pScrn); 939 940 /* Turn on bus mastering */ 941 info->BusCntl &= ~R128_BUS_MASTER_DIS; 942 943 /* CCEMode is initialized in r128_driver.c */ 944 switch (info->CCEMode) { 945 case R128_PM4_NONPM4: info->CCEFifoSize = 0; break; 946 case R128_PM4_192PIO: info->CCEFifoSize = 192; break; 947 case R128_PM4_192BM: info->CCEFifoSize = 192; break; 948 case R128_PM4_128PIO_64INDBM: info->CCEFifoSize = 128; break; 949 case R128_PM4_128BM_64INDBM: info->CCEFifoSize = 128; break; 950 case R128_PM4_64PIO_128INDBM: info->CCEFifoSize = 64; break; 951 case R128_PM4_64BM_128INDBM: info->CCEFifoSize = 64; break; 952 case R128_PM4_64PIO_64VCBM_64INDBM: info->CCEFifoSize = 64; break; 953 case R128_PM4_64BM_64VCBM_64INDBM: info->CCEFifoSize = 64; break; 954 case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64; break; 955 } 956 957 if (info->directRenderingEnabled) { 958 /* Make sure the CCE is on for the X server */ 959 R128CCE_START(pScrn, info); 960 } else { 961 /* Make sure the CCE is off for the X server */ 962 R128CCE_STOP(pScrn, info); 963 } 964} 965 966/* Initialize the screen-specific data structures for the DRI and the 967 Rage 128. This is the main entry point to the device-specific 968 initialization code. It calls device-independent DRI functions to 969 create the DRI data structures and initialize the DRI state. */ 970Bool R128DRIScreenInit(ScreenPtr pScreen) 971{ 972 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 973 R128InfoPtr info = R128PTR(pScrn); 974 DRIInfoPtr pDRIInfo; 975 R128DRIPtr pR128DRI; 976 int major, minor, patch; 977 drmVersionPtr version; 978 979 /* Check that the GLX, DRI, and DRM modules have been loaded by testing 980 * for known symbols in each module. */ 981 if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE; 982 if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE; 983 if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { 984 xf86DrvMsg(pScreen->myNum, X_ERROR, 985 "[dri] R128DRIScreenInit failed (libdri.a too old)\n"); 986 return FALSE; 987 } 988 989 /* Check the DRI version */ 990 DRIQueryVersion(&major, &minor, &patch); 991 if (major != DRIINFO_MAJOR_VERSION || minor < 0) { 992 xf86DrvMsg(pScreen->myNum, X_ERROR, 993 "[dri] R128DRIScreenInit failed because of a version mismatch.\n" 994 "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n" 995 "[dri] Disabling the DRI.\n", 996 major, minor, patch, 997 DRIINFO_MAJOR_VERSION, 0); 998 return FALSE; 999 } 1000 1001 switch (info->CurrentLayout.pixel_code) { 1002 case 8: 1003 /* These modes are not supported (yet). */ 1004 case 15: 1005 case 24: 1006 xf86DrvMsg(pScreen->myNum, X_ERROR, 1007 "[dri] R128DRIScreenInit failed (depth %d not supported). " 1008 "[dri] Disabling DRI.\n", info->CurrentLayout.pixel_code); 1009 return FALSE; 1010 1011 /* Only 16 and 32 color depths are supports currently. */ 1012 case 16: 1013 case 32: 1014 break; 1015 } 1016 1017 r128_drm_page_size = getpagesize(); 1018 1019 /* Create the DRI data structure, and fill it in before calling the 1020 DRIScreenInit(). */ 1021 if (!(pDRIInfo = DRICreateInfoRec())) return FALSE; 1022 1023 info->pDRIInfo = pDRIInfo; 1024 pDRIInfo->drmDriverName = R128_DRIVER_NAME; 1025 pDRIInfo->clientDriverName = R128_DRIVER_NAME; 1026 if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { 1027 pDRIInfo->busIdString = DRICreatePCIBusID(info->PciInfo); 1028 } else { 1029 pDRIInfo->busIdString = xalloc(64); 1030 sprintf(pDRIInfo->busIdString, 1031 "PCI:%d:%d:%d", 1032 PCI_DEV_BUS(info->PciInfo), 1033 PCI_DEV_DEV(info->PciInfo), 1034 PCI_DEV_FUNC(info->PciInfo)); 1035 } 1036 pDRIInfo->ddxDriverMajorVersion = R128_VERSION_MAJOR; 1037 pDRIInfo->ddxDriverMinorVersion = R128_VERSION_MINOR; 1038 pDRIInfo->ddxDriverPatchVersion = R128_VERSION_PATCH; 1039 pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr; 1040 pDRIInfo->frameBufferSize = info->FbMapSize; 1041 pDRIInfo->frameBufferStride = (pScrn->displayWidth * 1042 info->CurrentLayout.pixel_bytes); 1043 pDRIInfo->ddxDrawableTableEntry = R128_MAX_DRAWABLES; 1044 pDRIInfo->maxDrawableTableEntry = (SAREA_MAX_DRAWABLES 1045 < R128_MAX_DRAWABLES 1046 ? SAREA_MAX_DRAWABLES 1047 : R128_MAX_DRAWABLES); 1048 1049#ifdef NOT_DONE 1050 /* FIXME: Need to extend DRI protocol to pass this size back to 1051 * client for SAREA mapping that includes a device private record 1052 */ 1053 pDRIInfo->SAREASize = 1054 ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */ 1055 /* + shared memory device private rec */ 1056#else 1057 /* For now the mapping works by using a fixed size defined 1058 * in the SAREA header 1059 */ 1060 if (sizeof(XF86DRISAREARec)+sizeof(R128SAREAPriv)>SAREA_MAX) { 1061 xf86DrvMsg(pScreen->myNum, X_ERROR, 1062 "[dri] Data does not fit in SAREA. Disabling DRI.\n"); 1063 return FALSE; 1064 } 1065 pDRIInfo->SAREASize = SAREA_MAX; 1066#endif 1067 1068 if (!(pR128DRI = (R128DRIPtr)xcalloc(sizeof(R128DRIRec),1))) { 1069 DRIDestroyInfoRec(info->pDRIInfo); 1070 info->pDRIInfo = NULL; 1071 return FALSE; 1072 } 1073 pDRIInfo->devPrivate = pR128DRI; 1074 pDRIInfo->devPrivateSize = sizeof(R128DRIRec); 1075 pDRIInfo->contextSize = sizeof(R128DRIContextRec); 1076 1077 pDRIInfo->CreateContext = R128CreateContext; 1078 pDRIInfo->DestroyContext = R128DestroyContext; 1079 pDRIInfo->SwapContext = R128DRISwapContext; 1080 pDRIInfo->InitBuffers = R128DRIInitBuffers; 1081 pDRIInfo->MoveBuffers = R128DRIMoveBuffers; 1082 pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; 1083 pDRIInfo->TransitionTo2d = R128DRITransitionTo2d; 1084 pDRIInfo->TransitionTo3d = R128DRITransitionTo3d; 1085 pDRIInfo->TransitionSingleToMulti3D = R128DRITransitionSingleToMulti3d; 1086 pDRIInfo->TransitionMultiToSingle3D = R128DRITransitionMultiToSingle3d; 1087 1088 pDRIInfo->createDummyCtx = TRUE; 1089 pDRIInfo->createDummyCtxPriv = FALSE; 1090 1091 if (!DRIScreenInit(pScreen, pDRIInfo, &info->drmFD)) { 1092 xf86DrvMsg(pScreen->myNum, X_ERROR, 1093 "[dri] DRIScreenInit failed. Disabling DRI.\n"); 1094 xfree(pDRIInfo->devPrivate); 1095 pDRIInfo->devPrivate = NULL; 1096 DRIDestroyInfoRec(pDRIInfo); 1097 pDRIInfo = NULL; 1098 return FALSE; 1099 } 1100 1101 /* Check the DRM lib version. 1102 drmGetLibVersion was not supported in version 1.0, so check for 1103 symbol first to avoid possible crash or hang. 1104 */ 1105 if (xf86LoaderCheckSymbol("drmGetLibVersion")) { 1106 version = drmGetLibVersion(info->drmFD); 1107 } 1108 else { 1109 /* drmlib version 1.0.0 didn't have the drmGetLibVersion 1110 entry point. Fake it by allocating a version record 1111 via drmGetVersion and changing it to version 1.0.0 1112 */ 1113 version = drmGetVersion(info->drmFD); 1114 version->version_major = 1; 1115 version->version_minor = 0; 1116 version->version_patchlevel = 0; 1117 } 1118 1119 if (version) { 1120 if (version->version_major != 1 || 1121 version->version_minor < 1) { 1122 /* incompatible drm library version */ 1123 xf86DrvMsg(pScreen->myNum, X_ERROR, 1124 "[dri] R128DRIScreenInit failed because of a version mismatch.\n" 1125 "[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n" 1126 "[dri] Disabling DRI.\n", 1127 version->version_major, 1128 version->version_minor, 1129 version->version_patchlevel); 1130 drmFreeVersion(version); 1131 R128DRICloseScreen(pScreen); 1132 return FALSE; 1133 } 1134 drmFreeVersion(version); 1135 } 1136 1137 /* Check the r128 DRM version */ 1138 version = drmGetVersion(info->drmFD); 1139 if (version) { 1140 if (version->version_major != 2 || 1141 version->version_minor < 2) { 1142 /* incompatible drm version */ 1143 xf86DrvMsg(pScreen->myNum, X_ERROR, 1144 "[dri] R128DRIScreenInit failed because of a version mismatch.\n" 1145 "[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n" 1146 "[dri] Disabling the DRI.\n", 1147 version->version_major, 1148 version->version_minor, 1149 version->version_patchlevel); 1150 drmFreeVersion(version); 1151 R128DRICloseScreen(pScreen); 1152 return FALSE; 1153 } 1154 info->drmMinor = version->version_minor; 1155 drmFreeVersion(version); 1156 } 1157 1158 /* Initialize AGP */ 1159 if (!info->IsPCI && !R128DRIAgpInit(info, pScreen)) { 1160 info->IsPCI = TRUE; 1161 xf86DrvMsg(pScreen->myNum, X_WARNING, 1162 "[agp] AGP failed to initialize -- falling back to PCI mode.\n"); 1163 xf86DrvMsg(pScreen->myNum, X_WARNING, 1164 "[agp] Make sure you have the agpgart kernel module loaded.\n"); 1165 } 1166 1167 /* Initialize PCIGART */ 1168 if (info->IsPCI && !R128DRIPciInit(info, pScreen)) { 1169 R128DRICloseScreen(pScreen); 1170 return FALSE; 1171 } 1172 1173 /* DRIScreenInit doesn't add all the 1174 common mappings. Add additional 1175 mappings here. */ 1176 if (!R128DRIMapInit(info, pScreen)) { 1177 R128DRICloseScreen(pScreen); 1178 return FALSE; 1179 } 1180 1181 /* DRIScreenInit adds the frame buffer 1182 map, but we need it as well */ 1183 { 1184 void *scratch_ptr; 1185 int scratch_int; 1186 1187 DRIGetDeviceInfo(pScreen, &info->fbHandle, 1188 &scratch_int, &scratch_int, 1189 &scratch_int, &scratch_int, 1190 &scratch_ptr); 1191 } 1192 1193 /* FIXME: When are these mappings unmapped? */ 1194 1195 if (!R128InitVisualConfigs(pScreen)) { 1196 R128DRICloseScreen(pScreen); 1197 return FALSE; 1198 } 1199 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n"); 1200 1201 return TRUE; 1202} 1203 1204/* Finish initializing the device-dependent DRI state, and call 1205 DRIFinishScreenInit() to complete the device-independent DRI 1206 initialization. */ 1207Bool R128DRIFinishScreenInit(ScreenPtr pScreen) 1208{ 1209 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1210 R128InfoPtr info = R128PTR(pScrn); 1211 R128SAREAPrivPtr pSAREAPriv; 1212 R128DRIPtr pR128DRI; 1213 1214 info->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; 1215 /* info->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */ 1216 1217 /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit 1218 because *DRIKernelInit requires that the hardware lock is held by 1219 the X server, and the first time the hardware lock is grabbed is 1220 in DRIFinishScreenInit. */ 1221 if (!DRIFinishScreenInit(pScreen)) { 1222 R128DRICloseScreen(pScreen); 1223 return FALSE; 1224 } 1225 1226 /* Initialize the kernel data structures */ 1227 if (!R128DRIKernelInit(info, pScreen)) { 1228 R128DRICloseScreen(pScreen); 1229 return FALSE; 1230 } 1231 1232 /* Initialize the vertex buffers list */ 1233 if (!R128DRIBufInit(info, pScreen)) { 1234 R128DRICloseScreen(pScreen); 1235 return FALSE; 1236 } 1237 1238 /* Initialize IRQ */ 1239 R128DRIIrqInit(info, pScreen); 1240 1241 /* Initialize and start the CCE if required */ 1242 R128DRICCEInit(pScrn); 1243 1244 pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScreen); 1245 memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); 1246 1247 pR128DRI = (R128DRIPtr)info->pDRIInfo->devPrivate; 1248 1249 pR128DRI->deviceID = info->Chipset; 1250 pR128DRI->width = pScrn->virtualX; 1251 pR128DRI->height = pScrn->virtualY; 1252 pR128DRI->depth = pScrn->depth; 1253 pR128DRI->bpp = pScrn->bitsPerPixel; 1254 1255 pR128DRI->IsPCI = info->IsPCI; 1256 pR128DRI->AGPMode = info->agpMode; 1257 1258 pR128DRI->frontOffset = info->frontOffset; 1259 pR128DRI->frontPitch = info->frontPitch; 1260 pR128DRI->backOffset = info->backOffset; 1261 pR128DRI->backPitch = info->backPitch; 1262 pR128DRI->depthOffset = info->depthOffset; 1263 pR128DRI->depthPitch = info->depthPitch; 1264 pR128DRI->spanOffset = info->spanOffset; 1265 pR128DRI->textureOffset = info->textureOffset; 1266 pR128DRI->textureSize = info->textureSize; 1267 pR128DRI->log2TexGran = info->log2TexGran; 1268 1269 pR128DRI->registerHandle = info->registerHandle; 1270 pR128DRI->registerSize = info->registerSize; 1271 1272 pR128DRI->agpTexHandle = info->agpTexHandle; 1273 pR128DRI->agpTexMapSize = info->agpTexMapSize; 1274 pR128DRI->log2AGPTexGran = info->log2AGPTexGran; 1275 pR128DRI->agpTexOffset = info->agpTexStart; 1276 pR128DRI->sarea_priv_offset = sizeof(XF86DRISAREARec); 1277 1278 /* Have shadowfb run only while there is 3d active. */ 1279 if (info->allowPageFlip && info->drmMinor >= 5 ) { 1280 ShadowFBInit( pScreen, R128DRIRefreshArea ); 1281 } else if (info->allowPageFlip) { 1282 xf86DrvMsg(pScreen->myNum, X_WARNING, 1283 "[dri] Kernel module version 2.5.0 or newer is required for pageflipping.\n"); 1284 info->allowPageFlip = 0; 1285 } 1286 1287 return TRUE; 1288} 1289 1290/* The screen is being closed, so clean up any state and free any 1291 resources used by the DRI. */ 1292void R128DRICloseScreen(ScreenPtr pScreen) 1293{ 1294 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1295 R128InfoPtr info = R128PTR(pScrn); 1296 drmR128Init drmInfo; 1297 1298 /* Stop the CCE if it is still in use */ 1299 if (info->directRenderingEnabled) { 1300 R128CCE_STOP(pScrn, info); 1301 } 1302 1303 if (info->irq) { 1304 drmCtlUninstHandler(info->drmFD); 1305 info->irq = 0; 1306 info->gen_int_cntl = 0; 1307 } 1308 1309 /* De-allocate vertex buffers */ 1310 if (info->buffers) { 1311 drmUnmapBufs(info->buffers); 1312 info->buffers = NULL; 1313 } 1314 1315 /* De-allocate all kernel resources */ 1316 memset(&drmInfo, 0, sizeof(drmR128Init)); 1317 drmInfo.func = DRM_R128_CLEANUP_CCE; 1318 drmCommandWrite(info->drmFD, DRM_R128_INIT, 1319 &drmInfo, sizeof(drmR128Init)); 1320 1321 /* De-allocate all AGP resources */ 1322 if (info->agpTex) { 1323 drmUnmap(info->agpTex, info->agpTexMapSize); 1324 info->agpTex = NULL; 1325 } 1326 if (info->buf) { 1327 drmUnmap(info->buf, info->bufMapSize); 1328 info->buf = NULL; 1329 } 1330 if (info->ringReadPtr) { 1331 drmUnmap(info->ringReadPtr, info->ringReadMapSize); 1332 info->ringReadPtr = NULL; 1333 } 1334 if (info->ring) { 1335 drmUnmap(info->ring, info->ringMapSize); 1336 info->ring = NULL; 1337 } 1338 if (info->agpMemHandle != DRM_AGP_NO_HANDLE) { 1339 drmAgpUnbind(info->drmFD, info->agpMemHandle); 1340 drmAgpFree(info->drmFD, info->agpMemHandle); 1341 info->agpMemHandle = DRM_AGP_NO_HANDLE; 1342 drmAgpRelease(info->drmFD); 1343 } 1344 if (info->pciMemHandle) { 1345 drmScatterGatherFree(info->drmFD, info->pciMemHandle); 1346 info->pciMemHandle = 0; 1347 } 1348 1349 /* De-allocate all DRI resources */ 1350 DRICloseScreen(pScreen); 1351 1352 /* De-allocate all DRI data structures */ 1353 if (info->pDRIInfo) { 1354 if (info->pDRIInfo->devPrivate) { 1355 xfree(info->pDRIInfo->devPrivate); 1356 info->pDRIInfo->devPrivate = NULL; 1357 } 1358 DRIDestroyInfoRec(info->pDRIInfo); 1359 info->pDRIInfo = NULL; 1360 } 1361 if (info->pVisualConfigs) { 1362 xfree(info->pVisualConfigs); 1363 info->pVisualConfigs = NULL; 1364 } 1365 if (info->pVisualConfigsPriv) { 1366 xfree(info->pVisualConfigsPriv); 1367 info->pVisualConfigsPriv = NULL; 1368 } 1369} 1370 1371/* Use callbacks from dri.c to support pageflipping mode for a single 1372 * 3d context without need for any specific full-screen extension. 1373 */ 1374 1375/* Use the shadowfb module to maintain a list of dirty rectangles. 1376 * These are blitted to the back buffer to keep both buffers clean 1377 * during page-flipping when the 3d application isn't fullscreen. 1378 * 1379 * Unlike most use of the shadowfb code, both buffers are in video memory. 1380 * 1381 * An alternative to this would be to organize for all on-screen drawing 1382 * operations to be duplicated for the two buffers. That might be 1383 * faster, but seems like a lot more work... 1384 */ 1385 1386 1387static void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) 1388{ 1389 R128InfoPtr info = R128PTR(pScrn); 1390 int i; 1391 R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); 1392 1393 /* Don't want to do this when no 3d is active and pages are 1394 * right-way-round 1395 */ 1396 if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) 1397 return; 1398 1399 (*info->accel->SetupForScreenToScreenCopy)(pScrn, 1400 1, 1, GXcopy, 1401 (CARD32)(-1), -1); 1402 1403 for (i = 0 ; i < num ; i++, pbox++) { 1404 int xa = max(pbox->x1, 0), xb = min(pbox->x2, pScrn->virtualX-1); 1405 int ya = max(pbox->y1, 0), yb = min(pbox->y2, pScrn->virtualY-1); 1406 1407 if (xa <= xb && ya <= yb) { 1408 (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, 1409 xa + info->backX, 1410 ya + info->backY, 1411 xb - xa + 1, 1412 yb - ya + 1); 1413 } 1414 } 1415} 1416 1417static void R128EnablePageFlip(ScreenPtr pScreen) 1418{ 1419 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1420 R128InfoPtr info = R128PTR(pScrn); 1421 R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); 1422 1423 if (info->allowPageFlip) { 1424 /* Duplicate the frontbuffer to the backbuffer */ 1425 (*info->accel->SetupForScreenToScreenCopy)(pScrn, 1426 1, 1, GXcopy, 1427 (CARD32)(-1), -1); 1428 1429 (*info->accel->SubsequentScreenToScreenCopy)(pScrn, 1430 0, 1431 0, 1432 info->backX, 1433 info->backY, 1434 pScrn->virtualX, 1435 pScrn->virtualY); 1436 1437 pSAREAPriv->pfAllowPageFlip = 1; 1438 } 1439} 1440 1441static void R128DisablePageFlip(ScreenPtr pScreen) 1442{ 1443 /* Tell the clients not to pageflip. How? 1444 * -- Field in sarea, plus bumping the window counters. 1445 * -- DRM needs to cope with Front-to-Back swapbuffers. 1446 */ 1447 R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); 1448 1449 pSAREAPriv->pfAllowPageFlip = 0; 1450} 1451 1452static void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen) 1453{ 1454 R128DisablePageFlip(pScreen); 1455} 1456 1457static void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen) 1458{ 1459 /* Let the remaining 3d app start page flipping again */ 1460 R128EnablePageFlip(pScreen); 1461} 1462 1463static void R128DRITransitionTo3d(ScreenPtr pScreen) 1464{ 1465 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1466 R128InfoPtr info = R128PTR(pScrn); 1467 1468 R128EnablePageFlip(pScreen); 1469 1470 info->have3DWindows = 1; 1471 1472 if (info->cursor_start) 1473 xf86ForceHWCursor(pScreen, TRUE); 1474} 1475 1476static void R128DRITransitionTo2d(ScreenPtr pScreen) 1477{ 1478 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1479 R128InfoPtr info = R128PTR(pScrn); 1480 R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); 1481 1482 /* Try flipping back to the front page if necessary */ 1483 if (pSAREAPriv->pfCurrentPage == 1) 1484 drmCommandNone(info->drmFD, DRM_R128_FLIP); 1485 1486 /* Shut down shadowing if we've made it back to the front page */ 1487 if (pSAREAPriv->pfCurrentPage == 0) { 1488 R128DisablePageFlip(pScreen); 1489 } else { 1490 xf86DrvMsg(pScreen->myNum, X_WARNING, 1491 "[dri] R128DRITransitionTo2d: " 1492 "kernel failed to unflip buffers.\n"); 1493 } 1494 1495 info->have3DWindows = 0; 1496 1497 if (info->cursor_start) 1498 xf86ForceHWCursor(pScreen, FALSE); 1499} 1500