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