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