InitOutput.c revision 05b261ec
1/* 2 3Copyright 1993, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29#ifdef HAVE_DIX_CONFIG_H 30#include <dix-config.h> 31#endif 32 33#if defined(WIN32) 34#include <X11/Xwinsock.h> 35#endif 36#include <stdio.h> 37#include <X11/X.h> 38#define NEED_EVENTS 39#include <X11/Xproto.h> 40#include <X11/Xos.h> 41#include "scrnintstr.h" 42#include "servermd.h" 43#define PSZ 8 44#include "fb.h" 45#include "mibstore.h" 46#include "colormapst.h" 47#include "gcstruct.h" 48#include "input.h" 49#include "mipointer.h" 50#include "micmap.h" 51#include <sys/types.h> 52#ifdef HAS_MMAP 53#include <sys/mman.h> 54#ifndef MAP_FILE 55#define MAP_FILE 0 56#endif 57#endif /* HAS_MMAP */ 58#include <sys/stat.h> 59#include <errno.h> 60#ifndef WIN32 61#include <sys/param.h> 62#endif 63#include <X11/XWDFile.h> 64#ifdef HAS_SHM 65#include <sys/ipc.h> 66#include <sys/shm.h> 67#endif /* HAS_SHM */ 68#include "dix.h" 69#include "miline.h" 70 71#define VFB_DEFAULT_WIDTH 1280 72#define VFB_DEFAULT_HEIGHT 1024 73#define VFB_DEFAULT_DEPTH 8 74#define VFB_DEFAULT_WHITEPIXEL 1 75#define VFB_DEFAULT_BLACKPIXEL 0 76#define VFB_DEFAULT_LINEBIAS 0 77#define XWD_WINDOW_NAME_LEN 60 78 79typedef struct 80{ 81 int scrnum; 82 int width; 83 int paddedBytesWidth; 84 int paddedWidth; 85 int height; 86 int depth; 87 int bitsPerPixel; 88 int sizeInBytes; 89 int ncolors; 90 char *pfbMemory; 91 XWDColor *pXWDCmap; 92 XWDFileHeader *pXWDHeader; 93 Pixel blackPixel; 94 Pixel whitePixel; 95 unsigned int lineBias; 96 CloseScreenProcPtr closeScreen; 97 98#ifdef HAS_MMAP 99 int mmap_fd; 100 char mmap_file[MAXPATHLEN]; 101#endif 102 103#ifdef HAS_SHM 104 int shmid; 105#endif 106} vfbScreenInfo, *vfbScreenInfoPtr; 107 108static int vfbNumScreens; 109static vfbScreenInfo vfbScreens[MAXSCREENS]; 110static Bool vfbPixmapDepths[33]; 111#ifdef HAS_MMAP 112static char *pfbdir = NULL; 113#endif 114typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType; 115static fbMemType fbmemtype = NORMAL_MEMORY_FB; 116static char needswap = 0; 117static int lastScreen = -1; 118static Bool Render = TRUE; 119 120#define swapcopy16(_dst, _src) \ 121 if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \ 122 else _dst = _src; 123 124#define swapcopy32(_dst, _src) \ 125 if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \ 126 else _dst = _src; 127 128 129static void 130vfbInitializePixmapDepths(void) 131{ 132 int i; 133 vfbPixmapDepths[1] = TRUE; /* always need bitmaps */ 134 for (i = 2; i <= 32; i++) 135 vfbPixmapDepths[i] = FALSE; 136} 137 138static void 139vfbInitializeDefaultScreens(void) 140{ 141 int i; 142 143 for (i = 0; i < MAXSCREENS; i++) 144 { 145 vfbScreens[i].scrnum = i; 146 vfbScreens[i].width = VFB_DEFAULT_WIDTH; 147 vfbScreens[i].height = VFB_DEFAULT_HEIGHT; 148 vfbScreens[i].depth = VFB_DEFAULT_DEPTH; 149 vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL; 150 vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL; 151 vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS; 152 vfbScreens[i].pfbMemory = NULL; 153 } 154 vfbNumScreens = 1; 155} 156 157static int 158vfbBitsPerPixel(int depth) 159{ 160 if (depth == 1) return 1; 161 else if (depth <= 8) return 8; 162 else if (depth <= 16) return 16; 163 else return 32; 164} 165 166void 167ddxGiveUp() 168{ 169 int i; 170 171 /* clean up the framebuffers */ 172 173 switch (fbmemtype) 174 { 175#ifdef HAS_MMAP 176 case MMAPPED_FILE_FB: 177 for (i = 0; i < vfbNumScreens; i++) 178 { 179 if (-1 == unlink(vfbScreens[i].mmap_file)) 180 { 181 perror("unlink"); 182 ErrorF("unlink %s failed, errno %d", 183 vfbScreens[i].mmap_file, errno); 184 } 185 } 186 break; 187#else /* HAS_MMAP */ 188 case MMAPPED_FILE_FB: 189 break; 190#endif /* HAS_MMAP */ 191 192#ifdef HAS_SHM 193 case SHARED_MEMORY_FB: 194 for (i = 0; i < vfbNumScreens; i++) 195 { 196 if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader)) 197 { 198 perror("shmdt"); 199 ErrorF("shmdt failed, errno %d", errno); 200 } 201 } 202 break; 203#else /* HAS_SHM */ 204 case SHARED_MEMORY_FB: 205 break; 206#endif /* HAS_SHM */ 207 208 case NORMAL_MEMORY_FB: 209 for (i = 0; i < vfbNumScreens; i++) 210 { 211 Xfree(vfbScreens[i].pXWDHeader); 212 } 213 break; 214 } 215} 216 217void 218AbortDDX() 219{ 220 ddxGiveUp(); 221} 222 223#ifdef __DARWIN__ 224void 225DarwinHandleGUI(int argc, char *argv[]) 226{ 227} 228 229void GlxExtensionInit(); 230void GlxWrapInitVisuals(void *procPtr); 231 232void 233DarwinGlxExtensionInit() 234{ 235 GlxExtensionInit(); 236} 237 238void 239DarwinGlxWrapInitVisuals( 240 void *procPtr) 241{ 242 GlxWrapInitVisuals(procPtr); 243} 244#endif 245 246void 247OsVendorInit() 248{ 249} 250 251void 252OsVendorFatalError() 253{ 254} 255 256#if defined(DDXBEFORERESET) 257void ddxBeforeReset(void) 258{ 259 return; 260} 261#endif 262 263void 264ddxUseMsg() 265{ 266 ErrorF("-screen scrn WxHxD set screen's width, height, depth\n"); 267 ErrorF("-pixdepths list-of-int support given pixmap depths\n"); 268#ifdef RENDER 269 ErrorF("+/-render turn on/of RENDER extension support" 270 "(default on)\n"); 271#endif 272 ErrorF("-linebias n adjust thin line pixelization\n"); 273 ErrorF("-blackpixel n pixel value for black\n"); 274 ErrorF("-whitepixel n pixel value for white\n"); 275 276#ifdef HAS_MMAP 277 ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n"); 278#endif 279 280#ifdef HAS_SHM 281 ErrorF("-shmem put framebuffers in shared memory\n"); 282#endif 283} 284 285/* ddxInitGlobals - called by |InitGlobals| from os/util.c */ 286void ddxInitGlobals(void) 287{ 288} 289 290int 291ddxProcessArgument(int argc, char *argv[], int i) 292{ 293 static Bool firstTime = TRUE; 294 295 if (firstTime) 296 { 297 vfbInitializeDefaultScreens(); 298 vfbInitializePixmapDepths(); 299 firstTime = FALSE; 300 } 301 302#define CHECK_FOR_REQUIRED_ARGUMENTS(num) \ 303 if (((i + num) >= argc) || (!argv[i + num])) { \ 304 ErrorF("Required argument to %s not specified\n", argv[i]); \ 305 UseMsg(); \ 306 FatalError("Required argument to %s not specified\n", argv[i]); \ 307 } 308 309 if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */ 310 { 311 int screenNum; 312 CHECK_FOR_REQUIRED_ARGUMENTS(2); 313 screenNum = atoi(argv[i+1]); 314 if (screenNum < 0 || screenNum >= MAXSCREENS) 315 { 316 ErrorF("Invalid screen number %d\n", screenNum); 317 UseMsg(); 318 FatalError("Invalid screen number %d passed to -screen\n", 319 screenNum); 320 } 321 if (3 != sscanf(argv[i+2], "%dx%dx%d", 322 &vfbScreens[screenNum].width, 323 &vfbScreens[screenNum].height, 324 &vfbScreens[screenNum].depth)) 325 { 326 ErrorF("Invalid screen configuration %s\n", argv[i+2]); 327 UseMsg(); 328 FatalError("Invalid screen configuration %s for -screen %d\n", 329 argv[i+2], screenNum); 330 } 331 332 if (screenNum >= vfbNumScreens) 333 vfbNumScreens = screenNum + 1; 334 lastScreen = screenNum; 335 return 3; 336 } 337 338 if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */ 339 { 340 int depth, ret = 1; 341 342 CHECK_FOR_REQUIRED_ARGUMENTS(1); 343 while ((++i < argc) && (depth = atoi(argv[i])) != 0) 344 { 345 if (depth < 0 || depth > 32) 346 { 347 ErrorF("Invalid pixmap depth %d\n", depth); 348 UseMsg(); 349 FatalError("Invalid pixmap depth %d passed to -pixdepths\n", 350 depth); 351 } 352 vfbPixmapDepths[depth] = TRUE; 353 ret++; 354 } 355 return ret; 356 } 357 358 if (strcmp (argv[i], "+render") == 0) /* +render */ 359 { 360 Render = TRUE; 361 return 1; 362 } 363 364 if (strcmp (argv[i], "-render") == 0) /* -render */ 365 { 366 Render = FALSE; 367#ifdef COMPOSITE 368 noCompositeExtension = TRUE; 369#endif 370 return 1; 371 } 372 373 if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */ 374 { 375 Pixel pix; 376 CHECK_FOR_REQUIRED_ARGUMENTS(1); 377 pix = atoi(argv[++i]); 378 if (-1 == lastScreen) 379 { 380 int i; 381 for (i = 0; i < MAXSCREENS; i++) 382 { 383 vfbScreens[i].blackPixel = pix; 384 } 385 } 386 else 387 { 388 vfbScreens[lastScreen].blackPixel = pix; 389 } 390 return 2; 391 } 392 393 if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */ 394 { 395 Pixel pix; 396 CHECK_FOR_REQUIRED_ARGUMENTS(1); 397 pix = atoi(argv[++i]); 398 if (-1 == lastScreen) 399 { 400 int i; 401 for (i = 0; i < MAXSCREENS; i++) 402 { 403 vfbScreens[i].whitePixel = pix; 404 } 405 } 406 else 407 { 408 vfbScreens[lastScreen].whitePixel = pix; 409 } 410 return 2; 411 } 412 413 if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */ 414 { 415 unsigned int linebias; 416 CHECK_FOR_REQUIRED_ARGUMENTS(1); 417 linebias = atoi(argv[++i]); 418 if (-1 == lastScreen) 419 { 420 int i; 421 for (i = 0; i < MAXSCREENS; i++) 422 { 423 vfbScreens[i].lineBias = linebias; 424 } 425 } 426 else 427 { 428 vfbScreens[lastScreen].lineBias = linebias; 429 } 430 return 2; 431 } 432 433#ifdef HAS_MMAP 434 if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */ 435 { 436 CHECK_FOR_REQUIRED_ARGUMENTS(1); 437 pfbdir = argv[++i]; 438 fbmemtype = MMAPPED_FILE_FB; 439 return 2; 440 } 441#endif /* HAS_MMAP */ 442 443#ifdef HAS_SHM 444 if (strcmp (argv[i], "-shmem") == 0) /* -shmem */ 445 { 446 fbmemtype = SHARED_MEMORY_FB; 447 return 1; 448 } 449#endif 450 451 return 0; 452} 453 454static ColormapPtr InstalledMaps[MAXSCREENS]; 455 456static int 457vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) 458{ 459 /* By the time we are processing requests, we can guarantee that there 460 * is always a colormap installed */ 461 *pmaps = InstalledMaps[pScreen->myNum]->mid; 462 return (1); 463} 464 465 466static void 467vfbInstallColormap(ColormapPtr pmap) 468{ 469 int index = pmap->pScreen->myNum; 470 ColormapPtr oldpmap = InstalledMaps[index]; 471 472 if (pmap != oldpmap) 473 { 474 int entries; 475 XWDFileHeader *pXWDHeader; 476 XWDColor *pXWDCmap; 477 VisualPtr pVisual; 478 Pixel * ppix; 479 xrgb * prgb; 480 xColorItem *defs; 481 int i; 482 483 if(oldpmap != (ColormapPtr)None) 484 WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); 485 /* Install pmap */ 486 InstalledMaps[index] = pmap; 487 WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); 488 489 entries = pmap->pVisual->ColormapEntries; 490 pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader; 491 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; 492 pVisual = pmap->pVisual; 493 494 swapcopy32(pXWDHeader->visual_class, pVisual->class); 495 swapcopy32(pXWDHeader->red_mask, pVisual->redMask); 496 swapcopy32(pXWDHeader->green_mask, pVisual->greenMask); 497 swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask); 498 swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue); 499 swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries); 500 501 ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel)); 502 prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb)); 503 defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem)); 504 505 for (i = 0; i < entries; i++) ppix[i] = i; 506 /* XXX truecolor */ 507 QueryColors(pmap, entries, ppix, prgb); 508 509 for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */ 510 defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */ 511 defs[i].red = prgb[i].red; 512 defs[i].green = prgb[i].green; 513 defs[i].blue = prgb[i].blue; 514 defs[i].flags = DoRed|DoGreen|DoBlue; 515 } 516 (*pmap->pScreen->StoreColors)(pmap, entries, defs); 517 518 DEALLOCATE_LOCAL(ppix); 519 DEALLOCATE_LOCAL(prgb); 520 DEALLOCATE_LOCAL(defs); 521 } 522} 523 524static void 525vfbUninstallColormap(ColormapPtr pmap) 526{ 527 ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum]; 528 529 if(pmap == curpmap) 530 { 531 if (pmap->mid != pmap->pScreen->defColormap) 532 { 533 curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, 534 RT_COLORMAP); 535 (*pmap->pScreen->InstallColormap)(curpmap); 536 } 537 } 538} 539 540static void 541vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs) 542{ 543 XWDColor *pXWDCmap; 544 int i; 545 546 if (pmap != InstalledMaps[pmap->pScreen->myNum]) 547 { 548 return; 549 } 550 551 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; 552 553 if ((pmap->pVisual->class | DynamicClass) == DirectColor) 554 { 555 return; 556 } 557 558 for (i = 0; i < ndef; i++) 559 { 560 if (pdefs[i].flags & DoRed) 561 { 562 swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red); 563 } 564 if (pdefs[i].flags & DoGreen) 565 { 566 swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green); 567 } 568 if (pdefs[i].flags & DoBlue) 569 { 570 swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue); 571 } 572 } 573} 574 575static Bool 576vfbSaveScreen(ScreenPtr pScreen, int on) 577{ 578 return TRUE; 579} 580 581#ifdef HAS_MMAP 582 583/* this flushes any changes to the screens out to the mmapped file */ 584static void 585vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) 586{ 587 int i; 588 589 for (i = 0; i < vfbNumScreens; i++) 590 { 591#ifdef MS_ASYNC 592 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, 593 (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC)) 594#else 595 /* silly NetBSD and who else? */ 596 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, 597 (size_t)vfbScreens[i].sizeInBytes)) 598#endif 599 { 600 perror("msync"); 601 ErrorF("msync failed, errno %d", errno); 602 } 603 } 604} 605 606 607static void 608vfbWakeupHandler(pointer blockData, int result, pointer pReadmask) 609{ 610} 611 612 613static void 614vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb) 615{ 616#define DUMMY_BUFFER_SIZE 65536 617 char dummyBuffer[DUMMY_BUFFER_SIZE]; 618 int currentFileSize, writeThisTime; 619 620 sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum); 621 if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666))) 622 { 623 perror("open"); 624 ErrorF("open %s failed, errno %d", pvfb->mmap_file, errno); 625 return; 626 } 627 628 /* Extend the file to be the proper size */ 629 630 bzero(dummyBuffer, DUMMY_BUFFER_SIZE); 631 for (currentFileSize = 0; 632 currentFileSize < pvfb->sizeInBytes; 633 currentFileSize += writeThisTime) 634 { 635 writeThisTime = min(DUMMY_BUFFER_SIZE, 636 pvfb->sizeInBytes - currentFileSize); 637 if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime)) 638 { 639 perror("write"); 640 ErrorF("write %s failed, errno %d", pvfb->mmap_file, errno); 641 return; 642 } 643 } 644 645 /* try to mmap the file */ 646 647 pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes, 648 PROT_READ|PROT_WRITE, 649 MAP_FILE|MAP_SHARED, 650 pvfb->mmap_fd, 0); 651 if (-1 == (long)pvfb->pXWDHeader) 652 { 653 perror("mmap"); 654 ErrorF("mmap %s failed, errno %d", pvfb->mmap_file, errno); 655 pvfb->pXWDHeader = NULL; 656 return; 657 } 658 659 if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler, 660 NULL)) 661 { 662 pvfb->pXWDHeader = NULL; 663 } 664} 665#endif /* HAS_MMAP */ 666 667 668#ifdef HAS_SHM 669static void 670vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb) 671{ 672 /* create the shared memory segment */ 673 674 pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777); 675 if (pvfb->shmid < 0) 676 { 677 perror("shmget"); 678 ErrorF("shmget %d bytes failed, errno %d", pvfb->sizeInBytes, errno); 679 return; 680 } 681 682 /* try to attach it */ 683 684 pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0); 685 if (-1 == (long)pvfb->pXWDHeader) 686 { 687 perror("shmat"); 688 ErrorF("shmat failed, errno %d", errno); 689 pvfb->pXWDHeader = NULL; 690 return; 691 } 692 693 ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid); 694} 695#endif /* HAS_SHM */ 696 697static char * 698vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb) 699{ 700 if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */ 701 702 pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height; 703 704 /* Calculate how many entries in colormap. This is rather bogus, because 705 * the visuals haven't even been set up yet, but we need to know because we 706 * have to allocate space in the file for the colormap. The number 10 707 * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c. 708 */ 709 710 if (pvfb->depth <= 10) 711 { /* single index colormaps */ 712 pvfb->ncolors = 1 << pvfb->depth; 713 } 714 else 715 { /* decomposed colormaps */ 716 int nplanes_per_color_component = pvfb->depth / 3; 717 if (pvfb->depth % 3) nplanes_per_color_component++; 718 pvfb->ncolors = 1 << nplanes_per_color_component; 719 } 720 721 /* add extra bytes for XWDFileHeader, window name, and colormap */ 722 723 pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN + 724 pvfb->ncolors * SIZEOF(XWDColor); 725 726 pvfb->pXWDHeader = NULL; 727 switch (fbmemtype) 728 { 729#ifdef HAS_MMAP 730 case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break; 731#else 732 case MMAPPED_FILE_FB: break; 733#endif 734 735#ifdef HAS_SHM 736 case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break; 737#else 738 case SHARED_MEMORY_FB: break; 739#endif 740 741 case NORMAL_MEMORY_FB: 742 pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes); 743 break; 744 } 745 746 if (pvfb->pXWDHeader) 747 { 748 pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader 749 + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN); 750 pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors); 751 752 return pvfb->pfbMemory; 753 } 754 else 755 return NULL; 756} 757 758 759static void 760vfbWriteXWDFileHeader(ScreenPtr pScreen) 761{ 762 vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum]; 763 XWDFileHeader *pXWDHeader = pvfb->pXWDHeader; 764 char hostname[XWD_WINDOW_NAME_LEN]; 765 unsigned long swaptest = 1; 766 int i; 767 768 needswap = *(char *) &swaptest; 769 770 pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader; 771 pXWDHeader->file_version = XWD_FILE_VERSION; 772 773 pXWDHeader->pixmap_format = ZPixmap; 774 pXWDHeader->pixmap_depth = pvfb->depth; 775 pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height; 776 pXWDHeader->xoffset = 0; 777 pXWDHeader->byte_order = IMAGE_BYTE_ORDER; 778 pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER; 779#ifndef INTERNAL_VS_EXTERNAL_PADDING 780 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width; 781 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT; 782 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD; 783#else 784 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth; 785 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO; 786 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO; 787#endif 788 pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel; 789 pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth; 790 pXWDHeader->ncolors = pvfb->ncolors; 791 792 /* visual related fields are written when colormap is installed */ 793 794 pXWDHeader->window_x = pXWDHeader->window_y = 0; 795 pXWDHeader->window_bdrwidth = 0; 796 797 /* write xwd "window" name: Xvfb hostname:server.screen */ 798 799 if (-1 == gethostname(hostname, sizeof(hostname))) 800 hostname[0] = 0; 801 else 802 hostname[XWD_WINDOW_NAME_LEN-1] = 0; 803 sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display, 804 pScreen->myNum); 805 806 /* write colormap pixel slot values */ 807 808 for (i = 0; i < pvfb->ncolors; i++) 809 { 810 pvfb->pXWDCmap[i].pixel = i; 811 } 812 813 /* byte swap to most significant byte first */ 814 815 if (needswap) 816 { 817 SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4); 818 for (i = 0; i < pvfb->ncolors; i++) 819 { 820 register char n; 821 swapl(&pvfb->pXWDCmap[i].pixel, n); 822 } 823 } 824} 825 826 827static Bool 828vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y) 829{ 830 return FALSE; 831} 832 833static void 834vfbCrossScreen (ScreenPtr pScreen, Bool entering) 835{ 836} 837 838static miPointerScreenFuncRec vfbPointerCursorFuncs = 839{ 840 vfbCursorOffScreen, 841 vfbCrossScreen, 842 miPointerWarpCursor 843}; 844 845static Bool 846vfbCloseScreen(int index, ScreenPtr pScreen) 847{ 848 vfbScreenInfoPtr pvfb = &vfbScreens[index]; 849 int i; 850 851 pScreen->CloseScreen = pvfb->closeScreen; 852 853 /* 854 * XXX probably lots of stuff to clean. For now, 855 * clear InstalledMaps[] so that server reset works correctly. 856 */ 857 for (i = 0; i < MAXSCREENS; i++) 858 InstalledMaps[i] = NULL; 859 860 return pScreen->CloseScreen(index, pScreen); 861} 862 863static Bool 864vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) 865{ 866 vfbScreenInfoPtr pvfb = &vfbScreens[index]; 867 int dpix = monitorResolution, dpiy = monitorResolution; 868 int ret; 869 char *pbits; 870 871 if (dpix == 0) 872 dpix = 100; 873 874 if (dpiy == 0) 875 dpiy = 100; 876 877 pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth); 878 pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth); 879 if (pvfb->bitsPerPixel >= 8 ) 880 pvfb->paddedWidth = pvfb->paddedBytesWidth / (pvfb->bitsPerPixel / 8); 881 else 882 pvfb->paddedWidth = pvfb->paddedBytesWidth * 8; 883 pbits = vfbAllocateFramebufferMemory(pvfb); 884 if (!pbits) return FALSE; 885 886 miSetPixmapDepths (); 887 888 switch (pvfb->depth) { 889 case 8: 890 miSetVisualTypesAndMasks (8, 891 ((1 << StaticGray) | 892 (1 << GrayScale) | 893 (1 << StaticColor) | 894 (1 << PseudoColor) | 895 (1 << TrueColor) | 896 (1 << DirectColor)), 897 8, PseudoColor, 0, 0, 0); 898 break; 899#if 0 900 /* 12bit PseudoColor with 12bit color resolution 901 * (to simulate SGI hardware and the 12bit PseudoColor emulation layer) */ 902 case 12: 903 miSetVisualTypesAndMasks (12, 904 ((1 << StaticGray) | 905 (1 << GrayScale) | 906 (1 << StaticColor) | 907 (1 << PseudoColor) | 908 (1 << TrueColor) | 909 (1 << DirectColor)), 910 12, PseudoColor, 0, 0, 0); 911 break; 912#endif 913 case 15: 914 miSetVisualTypesAndMasks (15, 915 ((1 << TrueColor) | 916 (1 << DirectColor)), 917 8, TrueColor, 0x7c00, 0x03e0, 0x001f); 918 break; 919 case 16: 920 miSetVisualTypesAndMasks (16, 921 ((1 << TrueColor) | 922 (1 << DirectColor)), 923 8, TrueColor, 0xf800, 0x07e0, 0x001f); 924 break; 925 case 24: 926 miSetVisualTypesAndMasks (24, 927 ((1 << TrueColor) | 928 (1 << DirectColor)), 929 8, TrueColor, 0xff0000, 0x00ff00, 0x0000ff); 930 break; 931#if 0 932 /* 30bit TrueColor (to simulate Sun's XVR-1000/-4000 high quality 933 * framebuffer series) */ 934 case 30: 935 miSetVisualTypesAndMasks (30, 936 ((1 << TrueColor) | 937 (1 << DirectColor)), 938 10, TrueColor, 0x3ff00000, 0x000ffc00, 0x000003ff); 939 break; 940#endif 941 } 942 943 ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height, 944 dpix, dpiy, pvfb->paddedWidth,pvfb->bitsPerPixel); 945#ifdef RENDER 946 if (ret && Render) 947 fbPictureInit (pScreen, 0, 0); 948#endif 949 950 if (!ret) return FALSE; 951 952 miInitializeBackingStore(pScreen); 953 954 /* 955 * Circumvent the backing store that was just initialised. This amounts 956 * to a truely bizarre way of initialising SaveDoomedAreas and friends. 957 */ 958 959 pScreen->InstallColormap = vfbInstallColormap; 960 pScreen->UninstallColormap = vfbUninstallColormap; 961 pScreen->ListInstalledColormaps = vfbListInstalledColormaps; 962 963 pScreen->SaveScreen = vfbSaveScreen; 964 pScreen->StoreColors = vfbStoreColors; 965 966 miDCInitialize(pScreen, &vfbPointerCursorFuncs); 967 968 vfbWriteXWDFileHeader(pScreen); 969 970 pScreen->blackPixel = pvfb->blackPixel; 971 pScreen->whitePixel = pvfb->whitePixel; 972 973 ret = fbCreateDefColormap(pScreen); 974 975 miSetZeroLineBias(pScreen, pvfb->lineBias); 976 977 pvfb->closeScreen = pScreen->CloseScreen; 978 pScreen->CloseScreen = vfbCloseScreen; 979 980 return ret; 981 982} /* end vfbScreenInit */ 983 984 985void 986InitOutput(ScreenInfo *screenInfo, int argc, char **argv) 987{ 988 int i; 989 int NumFormats = 0; 990 991 /* initialize pixmap formats */ 992 993 /* must have a pixmap depth to match every screen depth */ 994 for (i = 0; i < vfbNumScreens; i++) 995 { 996 vfbPixmapDepths[vfbScreens[i].depth] = TRUE; 997 } 998 999 /* RENDER needs a good set of pixmaps. */ 1000 if (Render) { 1001 vfbPixmapDepths[1] = TRUE; 1002 vfbPixmapDepths[4] = TRUE; 1003 vfbPixmapDepths[8] = TRUE; 1004#if 0 1005 vfbPixmapDepths[12] = TRUE; 1006#endif 1007/* vfbPixmapDepths[15] = TRUE; */ 1008 vfbPixmapDepths[16] = TRUE; 1009 vfbPixmapDepths[24] = TRUE; 1010#if 0 1011 vfbPixmapDepths[30] = TRUE; 1012#endif 1013 vfbPixmapDepths[32] = TRUE; 1014 } 1015 1016 for (i = 1; i <= 32; i++) 1017 { 1018 if (vfbPixmapDepths[i]) 1019 { 1020 if (NumFormats >= MAXFORMATS) 1021 FatalError ("MAXFORMATS is too small for this server\n"); 1022 screenInfo->formats[NumFormats].depth = i; 1023 screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i); 1024 screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD; 1025 NumFormats++; 1026 } 1027 } 1028 1029 screenInfo->imageByteOrder = IMAGE_BYTE_ORDER; 1030 screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; 1031 screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; 1032 screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; 1033 screenInfo->numPixmapFormats = NumFormats; 1034 1035 /* initialize screens */ 1036 1037 for (i = 0; i < vfbNumScreens; i++) 1038 { 1039 if (-1 == AddScreen(vfbScreenInit, argc, argv)) 1040 { 1041 FatalError("Couldn't add screen %d", i); 1042 } 1043 } 1044 1045} /* end InitOutput */ 1046 1047/* this is just to get the server to link on AIX */ 1048#ifdef AIXV3 1049int SelectWaitTime = 10000; /* usec */ 1050#endif 1051