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