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