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