xf86DGA.c revision b1d344b3
1/* 2 * Copyright (c) 1998-2002 by The XFree86 Project, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Except as contained in this notice, the name of the copyright holder(s) 23 * and author(s) shall not be used in advertising or otherwise to promote 24 * the sale, use or other dealings in this Software without prior written 25 * authorization from the copyright holder(s) and author(s). 26 * 27 * Written by Mark Vojkovich 28 */ 29 30#ifdef HAVE_XORG_CONFIG_H 31#include <xorg-config.h> 32#endif 33 34#include "xf86.h" 35#include "xf86str.h" 36#include "xf86Priv.h" 37#include "dgaproc.h" 38#include <X11/extensions/xf86dgastr.h> 39#include "colormapst.h" 40#include "pixmapstr.h" 41#include "inputstr.h" 42#include "globals.h" 43#include "servermd.h" 44#include "micmap.h" 45#ifdef XKB 46#include <xkbsrv.h> 47#endif 48#include "xf86Xinput.h" 49#include "exglobals.h" 50#include "exevents.h" 51 52#include "mi.h" 53 54static int DGAScreenKeyIndex; 55static DevPrivateKey DGAScreenKey; 56static int mieq_installed = 0; 57 58static Bool DGACloseScreen(int i, ScreenPtr pScreen); 59static void DGADestroyColormap(ColormapPtr pmap); 60static void DGAInstallColormap(ColormapPtr pmap); 61static void DGAUninstallColormap(ColormapPtr pmap); 62static void DGAHandleEvent(int screen_num, xEvent *event, 63 DeviceIntPtr device, int nevents); 64 65static void 66DGACopyModeInfo( 67 DGAModePtr mode, 68 XDGAModePtr xmode 69); 70 71_X_EXPORT int *XDGAEventBase = NULL; 72 73#define DGA_GET_SCREEN_PRIV(pScreen) ((DGAScreenPtr) \ 74 dixLookupPrivate(&(pScreen)->devPrivates, DGAScreenKey)) 75 76 77typedef struct _FakedVisualList{ 78 Bool free; 79 VisualPtr pVisual; 80 struct _FakedVisualList *next; 81} FakedVisualList; 82 83 84typedef struct { 85 ScrnInfoPtr pScrn; 86 int numModes; 87 DGAModePtr modes; 88 CloseScreenProcPtr CloseScreen; 89 DestroyColormapProcPtr DestroyColormap; 90 InstallColormapProcPtr InstallColormap; 91 UninstallColormapProcPtr UninstallColormap; 92 DGADevicePtr current; 93 DGAFunctionPtr funcs; 94 int input; 95 ClientPtr client; 96 int pixmapMode; 97 FakedVisualList *fakedVisuals; 98 ColormapPtr dgaColormap; 99 ColormapPtr savedColormap; 100 Bool grabMouse; 101 Bool grabKeyboard; 102} DGAScreenRec, *DGAScreenPtr; 103 104_X_EXPORT Bool 105DGAInit( 106 ScreenPtr pScreen, 107 DGAFunctionPtr funcs, 108 DGAModePtr modes, 109 int num 110){ 111 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 112 DGAScreenPtr pScreenPriv; 113 int i; 114 115 if(!funcs || !funcs->SetMode || !funcs->OpenFramebuffer) 116 return FALSE; 117 118 if(!modes || num <= 0) 119 return FALSE; 120 121 DGAScreenKey = &DGAScreenKeyIndex; 122 123 pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 124 125 if (!pScreenPriv) 126 { 127 if(!(pScreenPriv = (DGAScreenPtr)xalloc(sizeof(DGAScreenRec)))) 128 return FALSE; 129 dixSetPrivate(&pScreen->devPrivates, DGAScreenKey, pScreenPriv); 130 pScreenPriv->CloseScreen = pScreen->CloseScreen; 131 pScreen->CloseScreen = DGACloseScreen; 132 pScreenPriv->DestroyColormap = pScreen->DestroyColormap; 133 pScreen->DestroyColormap = DGADestroyColormap; 134 pScreenPriv->InstallColormap = pScreen->InstallColormap; 135 pScreen->InstallColormap = DGAInstallColormap; 136 pScreenPriv->UninstallColormap = pScreen->UninstallColormap; 137 pScreen->UninstallColormap = DGAUninstallColormap; 138 } 139 140 pScreenPriv->pScrn = pScrn; 141 pScreenPriv->numModes = num; 142 pScreenPriv->modes = modes; 143 pScreenPriv->current = NULL; 144 145 pScreenPriv->funcs = funcs; 146 pScreenPriv->input = 0; 147 pScreenPriv->client = NULL; 148 pScreenPriv->fakedVisuals = NULL; 149 pScreenPriv->dgaColormap = NULL; 150 pScreenPriv->savedColormap = NULL; 151 pScreenPriv->grabMouse = FALSE; 152 pScreenPriv->grabKeyboard = FALSE; 153 154 for(i = 0; i < num; i++) 155 modes[i].num = i + 1; 156 157#ifdef PANORAMIX 158 if(!noPanoramiXExtension) 159 for(i = 0; i < num; i++) 160 modes[i].flags &= ~DGA_PIXMAP_AVAILABLE; 161#endif 162 163 return TRUE; 164} 165 166/* DGAReInitModes allows the driver to re-initialize 167 * the DGA mode list. 168 */ 169 170_X_EXPORT Bool 171DGAReInitModes( 172 ScreenPtr pScreen, 173 DGAModePtr modes, 174 int num 175){ 176 DGAScreenPtr pScreenPriv; 177 int i; 178 179 /* No DGA? Ignore call (but don't make it look like it failed) */ 180 if(DGAScreenKey == NULL) 181 return TRUE; 182 183 pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 184 185 /* Same as above */ 186 if(!pScreenPriv) 187 return TRUE; 188 189 /* Can't do this while DGA is active */ 190 if(pScreenPriv->current) 191 return FALSE; 192 193 /* Quick sanity check */ 194 if(!num) 195 modes = NULL; 196 else if(!modes) 197 num = 0; 198 199 pScreenPriv->numModes = num; 200 pScreenPriv->modes = modes; 201 202 /* This practically disables DGA. So be it. */ 203 if(!num) 204 return TRUE; 205 206 for(i = 0; i < num; i++) 207 modes[i].num = i + 1; 208 209#ifdef PANORAMIX 210 if(!noPanoramiXExtension) 211 for(i = 0; i < num; i++) 212 modes[i].flags &= ~DGA_PIXMAP_AVAILABLE; 213#endif 214 215 return TRUE; 216} 217 218static void 219FreeMarkedVisuals(ScreenPtr pScreen) 220{ 221 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 222 FakedVisualList *prev, *curr, *tmp; 223 224 if(!pScreenPriv->fakedVisuals) 225 return; 226 227 prev = NULL; 228 curr = pScreenPriv->fakedVisuals; 229 230 while(curr) { 231 if(curr->free) { 232 tmp = curr; 233 curr = curr->next; 234 if(prev) 235 prev->next = curr; 236 else 237 pScreenPriv->fakedVisuals = curr; 238 xfree(tmp->pVisual); 239 xfree(tmp); 240 } else { 241 prev = curr; 242 curr = curr->next; 243 } 244 } 245} 246 247static Bool 248DGACloseScreen(int i, ScreenPtr pScreen) 249{ 250 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 251 252 if (XDGAEventBase) { 253 mieqSetHandler(*XDGAEventBase + MotionNotify, NULL); 254 mieqSetHandler(*XDGAEventBase + ButtonPress, NULL); 255 mieqSetHandler(*XDGAEventBase + ButtonRelease, NULL); 256 mieqSetHandler(*XDGAEventBase + KeyPress, NULL); 257 mieqSetHandler(*XDGAEventBase + KeyRelease, NULL); 258 } 259 260 FreeMarkedVisuals(pScreen); 261 262 pScreen->CloseScreen = pScreenPriv->CloseScreen; 263 pScreen->DestroyColormap = pScreenPriv->DestroyColormap; 264 pScreen->InstallColormap = pScreenPriv->InstallColormap; 265 pScreen->UninstallColormap = pScreenPriv->UninstallColormap; 266 267 /* DGAShutdown() should have ensured that no DGA 268 screen were active by here */ 269 270 xfree(pScreenPriv); 271 272 return((*pScreen->CloseScreen)(i, pScreen)); 273} 274 275 276static void 277DGADestroyColormap(ColormapPtr pmap) 278{ 279 ScreenPtr pScreen = pmap->pScreen; 280 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 281 VisualPtr pVisual = pmap->pVisual; 282 283 if(pScreenPriv->fakedVisuals) { 284 FakedVisualList *curr = pScreenPriv->fakedVisuals; 285 286 while(curr) { 287 if(curr->pVisual == pVisual) { 288 /* We can't get rid of them yet since FreeColormap 289 still needs the pVisual during the cleanup */ 290 curr->free = TRUE; 291 break; 292 } 293 curr = curr->next; 294 } 295 } 296 297 if(pScreenPriv->DestroyColormap) { 298 pScreen->DestroyColormap = pScreenPriv->DestroyColormap; 299 (*pScreen->DestroyColormap)(pmap); 300 pScreen->DestroyColormap = DGADestroyColormap; 301 } 302} 303 304 305static void 306DGAInstallColormap(ColormapPtr pmap) 307{ 308 ScreenPtr pScreen = pmap->pScreen; 309 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 310 311 if(pScreenPriv->current && pScreenPriv->dgaColormap) { 312 if (pmap != pScreenPriv->dgaColormap) { 313 pScreenPriv->savedColormap = pmap; 314 pmap = pScreenPriv->dgaColormap; 315 } 316 } 317 318 pScreen->InstallColormap = pScreenPriv->InstallColormap; 319 (*pScreen->InstallColormap)(pmap); 320 pScreen->InstallColormap = DGAInstallColormap; 321} 322 323static void 324DGAUninstallColormap(ColormapPtr pmap) 325{ 326 ScreenPtr pScreen = pmap->pScreen; 327 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 328 329 if(pScreenPriv->current && pScreenPriv->dgaColormap) { 330 if (pmap == pScreenPriv->dgaColormap) { 331 pScreenPriv->dgaColormap = NULL; 332 } 333 } 334 335 pScreen->UninstallColormap = pScreenPriv->UninstallColormap; 336 (*pScreen->UninstallColormap)(pmap); 337 pScreen->UninstallColormap = DGAUninstallColormap; 338} 339 340int 341xf86SetDGAMode( 342 int index, 343 int num, 344 DGADevicePtr devRet 345){ 346 ScreenPtr pScreen = screenInfo.screens[index]; 347 DGAScreenPtr pScreenPriv; 348 ScrnInfoPtr pScrn; 349 DGADevicePtr device; 350 PixmapPtr pPix = NULL; 351 DGAModePtr pMode = NULL; 352 353 /* First check if DGAInit was successful on this screen */ 354 if (DGAScreenKey == NULL) 355 return BadValue; 356 pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 357 if (!pScreenPriv) 358 return BadValue; 359 pScrn = pScreenPriv->pScrn; 360 361 if(!num) { 362 if(pScreenPriv->current) { 363 PixmapPtr oldPix = pScreenPriv->current->pPix; 364 if(oldPix) { 365 if(oldPix->drawable.id) 366 FreeResource(oldPix->drawable.id, RT_NONE); 367 else 368 (*pScreen->DestroyPixmap)(oldPix); 369 } 370 xfree(pScreenPriv->current); 371 pScreenPriv->current = NULL; 372 pScrn->vtSema = TRUE; 373 (*pScreenPriv->funcs->SetMode)(pScrn, NULL); 374 if(pScreenPriv->savedColormap) { 375 (*pScreen->InstallColormap)(pScreenPriv->savedColormap); 376 pScreenPriv->savedColormap = NULL; 377 } 378 pScreenPriv->dgaColormap = NULL; 379 (*pScrn->EnableDisableFBAccess)(index, TRUE); 380 381 FreeMarkedVisuals(pScreen); 382 } 383 384 pScreenPriv->grabMouse = FALSE; 385 pScreenPriv->grabKeyboard = FALSE; 386 387 return Success; 388 } 389 390 if(!pScrn->vtSema && !pScreenPriv->current) /* Really switched away */ 391 return BadAlloc; 392 393 if((num > 0) && (num <= pScreenPriv->numModes)) 394 pMode = &(pScreenPriv->modes[num - 1]); 395 else 396 return BadValue; 397 398 if(!(device = (DGADevicePtr)xalloc(sizeof(DGADeviceRec)))) 399 return BadAlloc; 400 401 if(!pScreenPriv->current) { 402 Bool oldVTSema = pScrn->vtSema; 403 404 pScrn->vtSema = FALSE; /* kludge until we rewrite VT switching */ 405 (*pScrn->EnableDisableFBAccess)(index, FALSE); 406 pScrn->vtSema = oldVTSema; 407 } 408 409 if(!(*pScreenPriv->funcs->SetMode)(pScrn, pMode)) { 410 xfree(device); 411 return BadAlloc; 412 } 413 414 pScrn->currentMode = pMode->mode; 415 416 if(!pScreenPriv->current && !pScreenPriv->input) { 417 /* if it's multihead we need to warp the cursor off of 418 our screen so it doesn't get trapped */ 419 } 420 421 pScrn->vtSema = FALSE; 422 423 if(pScreenPriv->current) { 424 PixmapPtr oldPix = pScreenPriv->current->pPix; 425 if(oldPix) { 426 if(oldPix->drawable.id) 427 FreeResource(oldPix->drawable.id, RT_NONE); 428 else 429 (*pScreen->DestroyPixmap)(oldPix); 430 } 431 xfree(pScreenPriv->current); 432 pScreenPriv->current = NULL; 433 } 434 435 if(pMode->flags & DGA_PIXMAP_AVAILABLE) { 436 if((pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pMode->depth, 0))) { 437 (*pScreen->ModifyPixmapHeader)(pPix, 438 pMode->pixmapWidth, pMode->pixmapHeight, 439 pMode->depth, pMode->bitsPerPixel, 440 pMode->bytesPerScanline, 441 (pointer)(pMode->address)); 442 } 443 } 444 445 devRet->mode = device->mode = pMode; 446 devRet->pPix = device->pPix = pPix; 447 pScreenPriv->current = device; 448 pScreenPriv->pixmapMode = FALSE; 449 pScreenPriv->grabMouse = TRUE; 450 pScreenPriv->grabKeyboard = TRUE; 451 452 return Success; 453} 454 455 456 457/*********** exported ones ***************/ 458 459_X_EXPORT void 460DGASetInputMode(int index, Bool keyboard, Bool mouse) 461{ 462 ScreenPtr pScreen = screenInfo.screens[index]; 463 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 464 465 if (pScreenPriv) 466 { 467 pScreenPriv->grabMouse = mouse; 468 pScreenPriv->grabKeyboard = keyboard; 469 470 if (!mieq_installed) { 471 mieqSetHandler(*XDGAEventBase + MotionNotify, DGAHandleEvent); 472 mieqSetHandler(*XDGAEventBase + ButtonPress, DGAHandleEvent); 473 mieqSetHandler(*XDGAEventBase + ButtonRelease, DGAHandleEvent); 474 mieqSetHandler(*XDGAEventBase + KeyPress, DGAHandleEvent); 475 mieqSetHandler(*XDGAEventBase + KeyRelease, DGAHandleEvent); 476 mieq_installed = 1; 477 } 478 } 479} 480 481_X_EXPORT Bool 482DGAChangePixmapMode(int index, int *x, int *y, int mode) 483{ 484 DGAScreenPtr pScreenPriv; 485 DGADevicePtr pDev; 486 DGAModePtr pMode; 487 PixmapPtr pPix; 488 489 if(DGAScreenKey == NULL) 490 return FALSE; 491 492 pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 493 494 if(!pScreenPriv || !pScreenPriv->current || !pScreenPriv->current->pPix) 495 return FALSE; 496 497 pDev = pScreenPriv->current; 498 pPix = pDev->pPix; 499 pMode = pDev->mode; 500 501 if(mode) { 502 int shift = 2; 503 504 if(*x > (pMode->pixmapWidth - pMode->viewportWidth)) 505 *x = pMode->pixmapWidth - pMode->viewportWidth; 506 if(*y > (pMode->pixmapHeight - pMode->viewportHeight)) 507 *y = pMode->pixmapHeight - pMode->viewportHeight; 508 509 switch(xf86Screens[index]->bitsPerPixel) { 510 case 16: shift = 1; break; 511 case 32: shift = 0; break; 512 default: break; 513 } 514 515 if(BITMAP_SCANLINE_PAD == 64) 516 shift++; 517 518 *x = (*x >> shift) << shift; 519 520 pPix->drawable.x = *x; 521 pPix->drawable.y = *y; 522 pPix->drawable.width = pMode->viewportWidth; 523 pPix->drawable.height = pMode->viewportHeight; 524 } else { 525 pPix->drawable.x = 0; 526 pPix->drawable.y = 0; 527 pPix->drawable.width = pMode->pixmapWidth; 528 pPix->drawable.height = pMode->pixmapHeight; 529 } 530 pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; 531 pScreenPriv->pixmapMode = mode; 532 533 return TRUE; 534} 535 536_X_EXPORT Bool 537DGAAvailable(int index) 538{ 539 if(DGAScreenKey == NULL) 540 return FALSE; 541 542 if (!xf86NoSharedResources(((ScrnInfoPtr)dixLookupPrivate( 543 &screenInfo.screens[index]->devPrivates, 544 xf86ScreenKey))->scrnIndex, MEM)) 545 return FALSE; 546 547 if(DGA_GET_SCREEN_PRIV(screenInfo.screens[index])) 548 return TRUE; 549 550 return FALSE; 551} 552 553_X_EXPORT Bool 554DGAActive(int index) 555{ 556 DGAScreenPtr pScreenPriv; 557 558 if(DGAScreenKey == NULL) 559 return FALSE; 560 561 pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 562 563 if(pScreenPriv && pScreenPriv->current) 564 return TRUE; 565 566 return FALSE; 567} 568 569 570 571/* Called by the event code in case the server is abruptly terminated */ 572 573void 574DGAShutdown() 575{ 576 ScrnInfoPtr pScrn; 577 int i; 578 579 if(DGAScreenKey == NULL) 580 return; 581 582 for(i = 0; i < screenInfo.numScreens; i++) { 583 pScrn = xf86Screens[i]; 584 585 (void)(*pScrn->SetDGAMode)(pScrn->scrnIndex, 0, NULL); 586 } 587} 588 589/* Called by the extension to initialize a mode */ 590 591_X_EXPORT int 592DGASetMode( 593 int index, 594 int num, 595 XDGAModePtr mode, 596 PixmapPtr *pPix 597){ 598 ScrnInfoPtr pScrn = xf86Screens[index]; 599 DGADeviceRec device; 600 int ret; 601 602 /* We rely on the extension to check that DGA is available */ 603 604 ret = (*pScrn->SetDGAMode)(index, num, &device); 605 if((ret == Success) && num) { 606 DGACopyModeInfo(device.mode, mode); 607 *pPix = device.pPix; 608 } 609 610 return ret; 611} 612 613/* Called from the extension to let the DDX know which events are requested */ 614 615_X_EXPORT void 616DGASelectInput( 617 int index, 618 ClientPtr client, 619 long mask 620){ 621 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 622 623 /* We rely on the extension to check that DGA is available */ 624 pScreenPriv->client = client; 625 pScreenPriv->input = mask; 626} 627 628_X_EXPORT int 629DGAGetViewportStatus(int index) 630{ 631 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 632 633 /* We rely on the extension to check that DGA is active */ 634 635 if (!pScreenPriv->funcs->GetViewport) 636 return 0; 637 638 return (*pScreenPriv->funcs->GetViewport)(pScreenPriv->pScrn); 639} 640 641_X_EXPORT int 642DGASetViewport( 643 int index, 644 int x, int y, 645 int mode 646){ 647 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 648 649 if (pScreenPriv->funcs->SetViewport) 650 (*pScreenPriv->funcs->SetViewport)(pScreenPriv->pScrn, x, y, mode); 651 return Success; 652} 653 654 655static int 656BitsClear(CARD32 data) 657{ 658 int bits = 0; 659 CARD32 mask; 660 661 for(mask = 1; mask; mask <<= 1) { 662 if(!(data & mask)) bits++; 663 else break; 664 } 665 666 return bits; 667} 668 669_X_EXPORT int 670DGACreateColormap(int index, ClientPtr client, int id, int mode, int alloc) 671{ 672 ScreenPtr pScreen = screenInfo.screens[index]; 673 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 674 FakedVisualList *fvlp; 675 VisualPtr pVisual; 676 DGAModePtr pMode; 677 ColormapPtr pmap; 678 679 if(!mode || (mode > pScreenPriv->numModes)) 680 return BadValue; 681 682 if((alloc != AllocNone) && (alloc != AllocAll)) 683 return BadValue; 684 685 pMode = &(pScreenPriv->modes[mode - 1]); 686 687 if(!(pVisual = xalloc(sizeof(VisualRec)))) 688 return BadAlloc; 689 690 pVisual->vid = FakeClientID(0); 691 pVisual->class = pMode->visualClass; 692 pVisual->nplanes = pMode->depth; 693 pVisual->ColormapEntries = 1 << pMode->depth; 694 pVisual->bitsPerRGBValue = (pMode->depth + 2) / 3; 695 696 switch (pVisual->class) { 697 case PseudoColor: 698 case GrayScale: 699 case StaticGray: 700 pVisual->bitsPerRGBValue = 8; /* not quite */ 701 pVisual->redMask = 0; 702 pVisual->greenMask = 0; 703 pVisual->blueMask = 0; 704 pVisual->offsetRed = 0; 705 pVisual->offsetGreen = 0; 706 pVisual->offsetBlue = 0; 707 break; 708 case DirectColor: 709 case TrueColor: 710 pVisual->ColormapEntries = 1 << pVisual->bitsPerRGBValue; 711 /* fall through */ 712 case StaticColor: 713 pVisual->redMask = pMode->red_mask; 714 pVisual->greenMask = pMode->green_mask; 715 pVisual->blueMask = pMode->blue_mask; 716 pVisual->offsetRed = BitsClear(pVisual->redMask); 717 pVisual->offsetGreen = BitsClear(pVisual->greenMask); 718 pVisual->offsetBlue = BitsClear(pVisual->blueMask); 719 } 720 721 if(!(fvlp = xalloc(sizeof(FakedVisualList)))) { 722 xfree(pVisual); 723 return BadAlloc; 724 } 725 726 fvlp->free = FALSE; 727 fvlp->pVisual = pVisual; 728 fvlp->next = pScreenPriv->fakedVisuals; 729 pScreenPriv->fakedVisuals = fvlp; 730 731 LEGAL_NEW_RESOURCE(id, client); 732 733 return CreateColormap(id, pScreen, pVisual, &pmap, alloc, client->index); 734} 735 736/* Called by the extension to install a colormap on DGA active screens */ 737 738_X_EXPORT void 739DGAInstallCmap(ColormapPtr cmap) 740{ 741 ScreenPtr pScreen = cmap->pScreen; 742 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 743 744 /* We rely on the extension to check that DGA is active */ 745 746 if(!pScreenPriv->dgaColormap) 747 pScreenPriv->savedColormap = miInstalledMaps[pScreen->myNum]; 748 749 pScreenPriv->dgaColormap = cmap; 750 751 (*pScreen->InstallColormap)(cmap); 752} 753 754_X_EXPORT int 755DGASync(int index) 756{ 757 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 758 759 /* We rely on the extension to check that DGA is active */ 760 761 if (pScreenPriv->funcs->Sync) 762 (*pScreenPriv->funcs->Sync)(pScreenPriv->pScrn); 763 764 return Success; 765} 766 767_X_EXPORT int 768DGAFillRect( 769 int index, 770 int x, int y, int w, int h, 771 unsigned long color 772){ 773 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 774 775 /* We rely on the extension to check that DGA is active */ 776 777 if(pScreenPriv->funcs->FillRect && 778 (pScreenPriv->current->mode->flags & DGA_FILL_RECT)) { 779 780 (*pScreenPriv->funcs->FillRect)(pScreenPriv->pScrn, x, y, w, h, color); 781 return Success; 782 } 783 return BadMatch; 784} 785 786_X_EXPORT int 787DGABlitRect( 788 int index, 789 int srcx, int srcy, 790 int w, int h, 791 int dstx, int dsty 792){ 793 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 794 795 /* We rely on the extension to check that DGA is active */ 796 797 if(pScreenPriv->funcs->BlitRect && 798 (pScreenPriv->current->mode->flags & DGA_BLIT_RECT)) { 799 800 (*pScreenPriv->funcs->BlitRect)(pScreenPriv->pScrn, 801 srcx, srcy, w, h, dstx, dsty); 802 return Success; 803 } 804 return BadMatch; 805} 806 807_X_EXPORT int 808DGABlitTransRect( 809 int index, 810 int srcx, int srcy, 811 int w, int h, 812 int dstx, int dsty, 813 unsigned long color 814){ 815 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 816 817 /* We rely on the extension to check that DGA is active */ 818 819 if(pScreenPriv->funcs->BlitTransRect && 820 (pScreenPriv->current->mode->flags & DGA_BLIT_RECT_TRANS)) { 821 822 (*pScreenPriv->funcs->BlitTransRect)(pScreenPriv->pScrn, 823 srcx, srcy, w, h, dstx, dsty, color); 824 return Success; 825 } 826 return BadMatch; 827} 828 829 830_X_EXPORT int 831DGAGetModes(int index) 832{ 833 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 834 /* We rely on the extension to check that DGA is available */ 835 836 return pScreenPriv->numModes; 837} 838 839 840_X_EXPORT int 841DGAGetModeInfo( 842 int index, 843 XDGAModePtr mode, 844 int num 845){ 846 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 847 /* We rely on the extension to check that DGA is available */ 848 849 if((num <= 0) || (num > pScreenPriv->numModes)) 850 return BadValue; 851 852 DGACopyModeInfo(&(pScreenPriv->modes[num - 1]), mode); 853 854 return Success; 855} 856 857 858static void 859DGACopyModeInfo( 860 DGAModePtr mode, 861 XDGAModePtr xmode 862){ 863 DisplayModePtr dmode = mode->mode; 864 865 xmode->num = mode->num; 866 xmode->name = dmode->name; 867 xmode->VSync_num = (int)(dmode->VRefresh * 1000.0); 868 xmode->VSync_den = 1000; 869 xmode->flags = mode->flags; 870 xmode->imageWidth = mode->imageWidth; 871 xmode->imageHeight = mode->imageHeight; 872 xmode->pixmapWidth = mode->pixmapWidth; 873 xmode->pixmapHeight = mode->pixmapHeight; 874 xmode->bytesPerScanline = mode->bytesPerScanline; 875 xmode->byteOrder = mode->byteOrder; 876 xmode->depth = mode->depth; 877 xmode->bitsPerPixel = mode->bitsPerPixel; 878 xmode->red_mask = mode->red_mask; 879 xmode->green_mask = mode->green_mask; 880 xmode->blue_mask = mode->blue_mask; 881 xmode->visualClass = mode->visualClass; 882 xmode->viewportWidth = mode->viewportWidth; 883 xmode->viewportHeight = mode->viewportHeight; 884 xmode->xViewportStep = mode->xViewportStep; 885 xmode->yViewportStep = mode->yViewportStep; 886 xmode->maxViewportX = mode->maxViewportX; 887 xmode->maxViewportY = mode->maxViewportY; 888 xmode->viewportFlags = mode->viewportFlags; 889 xmode->reserved1 = mode->reserved1; 890 xmode->reserved2 = mode->reserved2; 891 xmode->offset = mode->offset; 892 893 if(dmode->Flags & V_INTERLACE) xmode->flags |= DGA_INTERLACED; 894 if(dmode->Flags & V_DBLSCAN) xmode->flags |= DGA_DOUBLESCAN; 895} 896 897 898Bool 899DGAVTSwitch(void) 900{ 901 ScreenPtr pScreen; 902 int i; 903 904 for(i = 0; i < screenInfo.numScreens; i++) { 905 pScreen = screenInfo.screens[i]; 906 907 /* Alternatively, this could send events to DGA clients */ 908 909 if(DGAScreenKey) { 910 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 911 912 if(pScreenPriv && pScreenPriv->current) 913 return FALSE; 914 } 915 } 916 917 return TRUE; 918} 919 920Bool 921DGAStealKeyEvent(DeviceIntPtr dev, int index, int key_code, int is_down) 922{ 923 DGAScreenPtr pScreenPriv; 924 dgaEvent de; 925 926 if(DGAScreenKey == NULL) /* no DGA */ 927 return FALSE; 928 929 if (key_code < 8 || key_code > 255) 930 return FALSE; 931 932 pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 933 934 if(!pScreenPriv || !pScreenPriv->grabKeyboard) /* no direct mode */ 935 return FALSE; 936 937 de.u.u.type = *XDGAEventBase + (is_down ? KeyPress : KeyRelease); 938 de.u.u.detail = key_code; 939 de.u.event.time = GetTimeInMillis(); 940 mieqEnqueue (dev, (xEvent *) &de); 941 942 return TRUE; 943} 944 945static int DGAMouseX, DGAMouseY; 946 947Bool 948DGAStealMotionEvent(DeviceIntPtr dev, int index, int dx, int dy) 949{ 950 DGAScreenPtr pScreenPriv; 951 dgaEvent de; 952 953 if(DGAScreenKey == NULL) /* no DGA */ 954 return FALSE; 955 956 pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 957 958 if(!pScreenPriv || !pScreenPriv->grabMouse) /* no direct mode */ 959 return FALSE; 960 961 DGAMouseX += dx; 962 if (DGAMouseX < 0) 963 DGAMouseX = 0; 964 else if (DGAMouseX > screenInfo.screens[index]->width) 965 DGAMouseX = screenInfo.screens[index]->width; 966 DGAMouseY += dy; 967 if (DGAMouseY < 0) 968 DGAMouseY = 0; 969 else if (DGAMouseY > screenInfo.screens[index]->height) 970 DGAMouseY = screenInfo.screens[index]->height; 971 de.u.u.type = *XDGAEventBase + MotionNotify; 972 de.u.u.detail = 0; 973 de.u.event.time = GetTimeInMillis(); 974 de.u.event.dx = dx; 975 de.u.event.dy = dy; 976 de.u.event.pad1 = DGAMouseX; 977 de.u.event.pad2 = DGAMouseY; 978 mieqEnqueue (dev, (xEvent *) &de); 979 return TRUE; 980} 981 982Bool 983DGAStealButtonEvent(DeviceIntPtr dev, int index, int button, int is_down) 984{ 985 DGAScreenPtr pScreenPriv; 986 dgaEvent de; 987 988 if (DGAScreenKey == NULL) 989 return FALSE; 990 991 pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 992 993 if (!pScreenPriv || !pScreenPriv->grabMouse) 994 return FALSE; 995 996 de.u.u.type = *XDGAEventBase + (is_down ? ButtonPress : ButtonRelease); 997 de.u.u.detail = button; 998 de.u.event.time = GetTimeInMillis(); 999 de.u.event.dx = 0; 1000 de.u.event.dy = 0; 1001 de.u.event.pad1 = DGAMouseX; 1002 de.u.event.pad2 = DGAMouseY; 1003 mieqEnqueue (dev, (xEvent *) &de); 1004 1005 return TRUE; 1006} 1007 1008/* We have the power to steal or modify events that are about to get queued */ 1009 1010Bool 1011DGAIsDgaEvent (xEvent *e) 1012{ 1013 int coreEquiv; 1014 if (DGAScreenKey == NULL || XDGAEventBase == 0) 1015 return FALSE; 1016 coreEquiv = e->u.u.type - *XDGAEventBase; 1017 if (KeyPress <= coreEquiv && coreEquiv <= MotionNotify) 1018 return TRUE; 1019 return FALSE; 1020} 1021 1022#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ 1023static Mask filters[] = 1024{ 1025 NoSuchEvent, /* 0 */ 1026 NoSuchEvent, /* 1 */ 1027 KeyPressMask, /* KeyPress */ 1028 KeyReleaseMask, /* KeyRelease */ 1029 ButtonPressMask, /* ButtonPress */ 1030 ButtonReleaseMask, /* ButtonRelease */ 1031 PointerMotionMask, /* MotionNotify (initial state) */ 1032}; 1033 1034static void 1035DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd) 1036{ 1037 int coreEquiv; 1038 xEvent xi; 1039 KeyClassPtr keyc = keybd->key; 1040 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 1041 DeviceIntPtr pointer = GetPairedDevice(keybd); 1042 1043 coreEquiv = de->u.u.type - *XDGAEventBase; 1044 1045 /* 1046 * Fill in remaining event state 1047 */ 1048 de->u.event.dx = 0; 1049 de->u.event.dy = 0; 1050 de->u.event.screen = pScreen->myNum; 1051 de->u.event.state = keyc->state | pointer->button->state; 1052 1053 de->u.u.type = (IEventBase - 1) + coreEquiv; /* change to XI event */ 1054 UpdateDeviceState(keybd, (xEvent*)de, 1); 1055 de->u.u.type = *XDGAEventBase + coreEquiv; /* change back */ 1056 1057 /* 1058 * Deliver the DGA event 1059 */ 1060 if (pScreenPriv->client) 1061 { 1062 /* If the DGA client has selected input, then deliver based on the usual filter */ 1063 TryClientEvents (pScreenPriv->client, keybd, (xEvent *) de, 1, 1064 filters[coreEquiv], pScreenPriv->input, 0); 1065 } 1066 else 1067 { 1068 /* If the keyboard is actively grabbed, deliver a grabbed core event */ 1069 if (keybd->deviceGrab.grab && !keybd->deviceGrab.fromPassiveGrab) 1070 { 1071 xi.u.u.type = (IEventBase - 1) + coreEquiv; 1072 xi.u.u.detail = de->u.u.detail; 1073 xi.u.keyButtonPointer.time = de->u.event.time; 1074 xi.u.keyButtonPointer.eventX = de->u.event.dx; 1075 xi.u.keyButtonPointer.eventY = de->u.event.dy; 1076 xi.u.keyButtonPointer.rootX = de->u.event.dx; 1077 xi.u.keyButtonPointer.rootY = de->u.event.dy; 1078 xi.u.keyButtonPointer.state = de->u.event.state; 1079 ((deviceKeyButtonPointer*)&xi)->deviceid = keybd->id; 1080 DeliverGrabbedEvent (&xi, keybd, FALSE, 1); 1081 } 1082 } 1083} 1084 1085static void 1086DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse) 1087{ 1088 ButtonClassPtr butc = mouse->button; 1089 int coreEquiv; 1090 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 1091 xEvent xi; 1092 1093 coreEquiv = de->u.u.type - *XDGAEventBase; 1094 /* 1095 * Fill in remaining event state 1096 */ 1097 de->u.event.screen = pScreen->myNum; 1098 de->u.event.state = butc->state | GetPairedDevice(mouse)->key->state; 1099 1100 de->u.u.type = (IEventBase - 1) + coreEquiv; /* change to XI event */ 1101 UpdateDeviceState(mouse, (xEvent*)de, 1); 1102 de->u.u.type = *XDGAEventBase + coreEquiv; /* change back */ 1103 1104 /* 1105 * Deliver the DGA event 1106 */ 1107 if (pScreenPriv->client) 1108 { 1109 /* If the DGA client has selected input, then deliver based on the usual filter */ 1110 TryClientEvents (pScreenPriv->client, mouse, (xEvent *) de, 1, 1111 filters[coreEquiv], pScreenPriv->input, 0); 1112 } 1113 else 1114 { 1115 /* If the pointer is actively grabbed, deliver a grabbed core event */ 1116 if (mouse->deviceGrab.grab && !mouse->deviceGrab.fromPassiveGrab) 1117 { 1118 xi.u.u.type = (IEventBase - 1 ) + coreEquiv; 1119 xi.u.u.detail = de->u.u.detail; 1120 xi.u.keyButtonPointer.time = de->u.event.time; 1121 xi.u.keyButtonPointer.eventX = de->u.event.dx; 1122 xi.u.keyButtonPointer.eventY = de->u.event.dy; 1123 xi.u.keyButtonPointer.rootX = de->u.event.dx; 1124 xi.u.keyButtonPointer.rootY = de->u.event.dy; 1125 xi.u.keyButtonPointer.state = de->u.event.state; 1126 DeliverGrabbedEvent (&xi, mouse, FALSE, 1); 1127 } 1128 } 1129} 1130 1131_X_EXPORT Bool 1132DGAOpenFramebuffer( 1133 int index, 1134 char **name, 1135 unsigned char **mem, 1136 int *size, 1137 int *offset, 1138 int *flags 1139){ 1140 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 1141 1142 /* We rely on the extension to check that DGA is available */ 1143 1144 return (*pScreenPriv->funcs->OpenFramebuffer)(pScreenPriv->pScrn, 1145 name, mem, size, offset, flags); 1146} 1147 1148_X_EXPORT void 1149DGACloseFramebuffer(int index) 1150{ 1151 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 1152 1153 /* We rely on the extension to check that DGA is available */ 1154 if(pScreenPriv->funcs->CloseFramebuffer) 1155 (*pScreenPriv->funcs->CloseFramebuffer)(pScreenPriv->pScrn); 1156} 1157 1158/* For DGA 1.0 backwards compatibility only */ 1159 1160_X_EXPORT int 1161DGAGetOldDGAMode(int index) 1162{ 1163 DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); 1164 ScrnInfoPtr pScrn = pScreenPriv->pScrn; 1165 DGAModePtr mode; 1166 int i, w, h, p; 1167 1168 /* We rely on the extension to check that DGA is available */ 1169 1170 w = pScrn->currentMode->HDisplay; 1171 h = pScrn->currentMode->VDisplay; 1172 p = ((pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)) + 3) & ~3L; 1173 1174 for(i = 0; i < pScreenPriv->numModes; i++) { 1175 mode = &(pScreenPriv->modes[i]); 1176 1177 if((mode->viewportWidth == w) && (mode->viewportHeight == h) && 1178 (mode->bytesPerScanline == p) && 1179 (mode->bitsPerPixel == pScrn->bitsPerPixel) && 1180 (mode->depth == pScrn->depth)) { 1181 1182 return mode->num; 1183 } 1184 } 1185 1186 return 0; 1187} 1188 1189static void 1190DGAHandleEvent(int screen_num, xEvent *event, DeviceIntPtr device, int nevents) 1191{ 1192 dgaEvent *de = (dgaEvent *) event; 1193 ScreenPtr pScreen = screenInfo.screens[screen_num]; 1194 DGAScreenPtr pScreenPriv; 1195 int coreEquiv; 1196 1197 /* no DGA */ 1198 if (DGAScreenKey == NULL || XDGAEventBase == 0) 1199 return; 1200 pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); 1201 1202 /* DGA not initialized on this screen */ 1203 if (!pScreenPriv) 1204 return; 1205 1206 coreEquiv = de->u.u.type - *XDGAEventBase; 1207 /* Not a DGA event; shouldn't happen, but you never know. */ 1208 if (coreEquiv < KeyPress || coreEquiv > MotionNotify) 1209 return; 1210 1211 switch (coreEquiv) { 1212 case KeyPress: 1213 case KeyRelease: 1214 DGAProcessKeyboardEvent (pScreen, de, device); 1215 break; 1216 default: 1217 DGAProcessPointerEvent (pScreen, de, device); 1218 break; 1219 } 1220} 1221