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