InitOutput.c revision 4642e01f
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, %s", 183 vfbScreens[i].mmap_file, strerror(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, %s", strerror(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 __APPLE__ 224void 225DarwinHandleGUI(int argc, char *argv[]) 226{ 227} 228#endif 229 230void 231OsVendorInit() 232{ 233} 234 235void 236OsVendorFatalError() 237{ 238} 239 240#if defined(DDXBEFORERESET) 241void ddxBeforeReset(void) 242{ 243 return; 244} 245#endif 246 247void 248ddxUseMsg() 249{ 250 ErrorF("-screen scrn WxHxD set screen's width, height, depth\n"); 251 ErrorF("-pixdepths list-of-int support given pixmap depths\n"); 252#ifdef RENDER 253 ErrorF("+/-render turn on/of RENDER extension support" 254 "(default on)\n"); 255#endif 256 ErrorF("-linebias n adjust thin line pixelization\n"); 257 ErrorF("-blackpixel n pixel value for black\n"); 258 ErrorF("-whitepixel n pixel value for white\n"); 259 260#ifdef HAS_MMAP 261 ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n"); 262#endif 263 264#ifdef HAS_SHM 265 ErrorF("-shmem put framebuffers in shared memory\n"); 266#endif 267} 268 269int 270ddxProcessArgument(int argc, char *argv[], int i) 271{ 272 static Bool firstTime = TRUE; 273 274 if (firstTime) 275 { 276 vfbInitializeDefaultScreens(); 277 vfbInitializePixmapDepths(); 278 firstTime = FALSE; 279 } 280 281#define CHECK_FOR_REQUIRED_ARGUMENTS(num) \ 282 if (((i + num) >= argc) || (!argv[i + num])) { \ 283 ErrorF("Required argument to %s not specified\n", argv[i]); \ 284 UseMsg(); \ 285 FatalError("Required argument to %s not specified\n", argv[i]); \ 286 } 287 288 if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */ 289 { 290 int screenNum; 291 CHECK_FOR_REQUIRED_ARGUMENTS(2); 292 screenNum = atoi(argv[i+1]); 293 if (screenNum < 0 || screenNum >= MAXSCREENS) 294 { 295 ErrorF("Invalid screen number %d\n", screenNum); 296 UseMsg(); 297 FatalError("Invalid screen number %d passed to -screen\n", 298 screenNum); 299 } 300 if (3 != sscanf(argv[i+2], "%dx%dx%d", 301 &vfbScreens[screenNum].width, 302 &vfbScreens[screenNum].height, 303 &vfbScreens[screenNum].depth)) 304 { 305 ErrorF("Invalid screen configuration %s\n", argv[i+2]); 306 UseMsg(); 307 FatalError("Invalid screen configuration %s for -screen %d\n", 308 argv[i+2], screenNum); 309 } 310 311 if (screenNum >= vfbNumScreens) 312 vfbNumScreens = screenNum + 1; 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 Pixel pix; 355 CHECK_FOR_REQUIRED_ARGUMENTS(1); 356 pix = atoi(argv[++i]); 357 if (-1 == lastScreen) 358 { 359 int i; 360 for (i = 0; i < MAXSCREENS; i++) 361 { 362 vfbScreens[i].blackPixel = pix; 363 } 364 } 365 else 366 { 367 vfbScreens[lastScreen].blackPixel = pix; 368 } 369 return 2; 370 } 371 372 if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */ 373 { 374 Pixel pix; 375 CHECK_FOR_REQUIRED_ARGUMENTS(1); 376 pix = atoi(argv[++i]); 377 if (-1 == lastScreen) 378 { 379 int i; 380 for (i = 0; i < MAXSCREENS; i++) 381 { 382 vfbScreens[i].whitePixel = pix; 383 } 384 } 385 else 386 { 387 vfbScreens[lastScreen].whitePixel = pix; 388 } 389 return 2; 390 } 391 392 if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */ 393 { 394 unsigned int linebias; 395 CHECK_FOR_REQUIRED_ARGUMENTS(1); 396 linebias = atoi(argv[++i]); 397 if (-1 == lastScreen) 398 { 399 int i; 400 for (i = 0; i < MAXSCREENS; i++) 401 { 402 vfbScreens[i].lineBias = linebias; 403 } 404 } 405 else 406 { 407 vfbScreens[lastScreen].lineBias = linebias; 408 } 409 return 2; 410 } 411 412#ifdef HAS_MMAP 413 if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */ 414 { 415 CHECK_FOR_REQUIRED_ARGUMENTS(1); 416 pfbdir = argv[++i]; 417 fbmemtype = MMAPPED_FILE_FB; 418 return 2; 419 } 420#endif /* HAS_MMAP */ 421 422#ifdef HAS_SHM 423 if (strcmp (argv[i], "-shmem") == 0) /* -shmem */ 424 { 425 fbmemtype = SHARED_MEMORY_FB; 426 return 1; 427 } 428#endif 429 430 return 0; 431} 432 433static ColormapPtr InstalledMaps[MAXSCREENS]; 434 435static int 436vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) 437{ 438 /* By the time we are processing requests, we can guarantee that there 439 * is always a colormap installed */ 440 *pmaps = InstalledMaps[pScreen->myNum]->mid; 441 return (1); 442} 443 444 445static void 446vfbInstallColormap(ColormapPtr pmap) 447{ 448 int index = pmap->pScreen->myNum; 449 ColormapPtr oldpmap = InstalledMaps[index]; 450 451 if (pmap != oldpmap) 452 { 453 int entries; 454 XWDFileHeader *pXWDHeader; 455 XWDColor *pXWDCmap; 456 VisualPtr pVisual; 457 Pixel * ppix; 458 xrgb * prgb; 459 xColorItem *defs; 460 int i; 461 462 if(oldpmap != (ColormapPtr)None) 463 WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); 464 /* Install pmap */ 465 InstalledMaps[index] = pmap; 466 WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); 467 468 entries = pmap->pVisual->ColormapEntries; 469 pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader; 470 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; 471 pVisual = pmap->pVisual; 472 473 swapcopy32(pXWDHeader->visual_class, pVisual->class); 474 swapcopy32(pXWDHeader->red_mask, pVisual->redMask); 475 swapcopy32(pXWDHeader->green_mask, pVisual->greenMask); 476 swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask); 477 swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue); 478 swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries); 479 480 ppix = (Pixel *)xalloc(entries * sizeof(Pixel)); 481 prgb = (xrgb *)xalloc(entries * sizeof(xrgb)); 482 defs = (xColorItem *)xalloc(entries * sizeof(xColorItem)); 483 484 for (i = 0; i < entries; i++) ppix[i] = i; 485 /* XXX truecolor */ 486 QueryColors(pmap, entries, ppix, prgb); 487 488 for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */ 489 defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */ 490 defs[i].red = prgb[i].red; 491 defs[i].green = prgb[i].green; 492 defs[i].blue = prgb[i].blue; 493 defs[i].flags = DoRed|DoGreen|DoBlue; 494 } 495 (*pmap->pScreen->StoreColors)(pmap, entries, defs); 496 497 xfree(ppix); 498 xfree(prgb); 499 xfree(defs); 500 } 501} 502 503static void 504vfbUninstallColormap(ColormapPtr pmap) 505{ 506 ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum]; 507 508 if(pmap == curpmap) 509 { 510 if (pmap->mid != pmap->pScreen->defColormap) 511 { 512 curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, 513 RT_COLORMAP); 514 (*pmap->pScreen->InstallColormap)(curpmap); 515 } 516 } 517} 518 519static void 520vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs) 521{ 522 XWDColor *pXWDCmap; 523 int i; 524 525 if (pmap != InstalledMaps[pmap->pScreen->myNum]) 526 { 527 return; 528 } 529 530 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; 531 532 if ((pmap->pVisual->class | DynamicClass) == DirectColor) 533 { 534 return; 535 } 536 537 for (i = 0; i < ndef; i++) 538 { 539 if (pdefs[i].flags & DoRed) 540 { 541 swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red); 542 } 543 if (pdefs[i].flags & DoGreen) 544 { 545 swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green); 546 } 547 if (pdefs[i].flags & DoBlue) 548 { 549 swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue); 550 } 551 } 552} 553 554static Bool 555vfbSaveScreen(ScreenPtr pScreen, int on) 556{ 557 return TRUE; 558} 559 560#ifdef HAS_MMAP 561 562/* this flushes any changes to the screens out to the mmapped file */ 563static void 564vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) 565{ 566 int i; 567 568 for (i = 0; i < vfbNumScreens; i++) 569 { 570#ifdef MS_ASYNC 571 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, 572 (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC)) 573#else 574 /* silly NetBSD and who else? */ 575 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, 576 (size_t)vfbScreens[i].sizeInBytes)) 577#endif 578 { 579 perror("msync"); 580 ErrorF("msync failed, %s", strerror(errno)); 581 } 582 } 583} 584 585 586static void 587vfbWakeupHandler(pointer blockData, int result, pointer pReadmask) 588{ 589} 590 591 592static void 593vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb) 594{ 595#define DUMMY_BUFFER_SIZE 65536 596 char dummyBuffer[DUMMY_BUFFER_SIZE]; 597 int currentFileSize, writeThisTime; 598 599 sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum); 600 if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666))) 601 { 602 perror("open"); 603 ErrorF("open %s failed, %s", pvfb->mmap_file, strerror(errno)); 604 return; 605 } 606 607 /* Extend the file to be the proper size */ 608 609 bzero(dummyBuffer, DUMMY_BUFFER_SIZE); 610 for (currentFileSize = 0; 611 currentFileSize < pvfb->sizeInBytes; 612 currentFileSize += writeThisTime) 613 { 614 writeThisTime = min(DUMMY_BUFFER_SIZE, 615 pvfb->sizeInBytes - currentFileSize); 616 if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime)) 617 { 618 perror("write"); 619 ErrorF("write %s failed, %s", pvfb->mmap_file, strerror(errno)); 620 return; 621 } 622 } 623 624 /* try to mmap the file */ 625 626 pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes, 627 PROT_READ|PROT_WRITE, 628 MAP_FILE|MAP_SHARED, 629 pvfb->mmap_fd, 0); 630 if (-1 == (long)pvfb->pXWDHeader) 631 { 632 perror("mmap"); 633 ErrorF("mmap %s failed, %s", pvfb->mmap_file, strerror(errno)); 634 pvfb->pXWDHeader = NULL; 635 return; 636 } 637 638 if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler, 639 NULL)) 640 { 641 pvfb->pXWDHeader = NULL; 642 } 643} 644#endif /* HAS_MMAP */ 645 646 647#ifdef HAS_SHM 648static void 649vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb) 650{ 651 /* create the shared memory segment */ 652 653 pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777); 654 if (pvfb->shmid < 0) 655 { 656 perror("shmget"); 657 ErrorF("shmget %d bytes failed, %s", pvfb->sizeInBytes, strerror(errno)); 658 return; 659 } 660 661 /* try to attach it */ 662 663 pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0); 664 if (-1 == (long)pvfb->pXWDHeader) 665 { 666 perror("shmat"); 667 ErrorF("shmat failed, %s", strerror(errno)); 668 pvfb->pXWDHeader = NULL; 669 return; 670 } 671 672 ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid); 673} 674#endif /* HAS_SHM */ 675 676static char * 677vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb) 678{ 679 if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */ 680 681 pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height; 682 683 /* Calculate how many entries in colormap. This is rather bogus, because 684 * the visuals haven't even been set up yet, but we need to know because we 685 * have to allocate space in the file for the colormap. The number 10 686 * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c. 687 */ 688 689 if (pvfb->depth <= 10) 690 { /* single index colormaps */ 691 pvfb->ncolors = 1 << pvfb->depth; 692 } 693 else 694 { /* decomposed colormaps */ 695 int nplanes_per_color_component = pvfb->depth / 3; 696 if (pvfb->depth % 3) nplanes_per_color_component++; 697 pvfb->ncolors = 1 << nplanes_per_color_component; 698 } 699 700 /* add extra bytes for XWDFileHeader, window name, and colormap */ 701 702 pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN + 703 pvfb->ncolors * SIZEOF(XWDColor); 704 705 pvfb->pXWDHeader = NULL; 706 switch (fbmemtype) 707 { 708#ifdef HAS_MMAP 709 case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break; 710#else 711 case MMAPPED_FILE_FB: break; 712#endif 713 714#ifdef HAS_SHM 715 case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break; 716#else 717 case SHARED_MEMORY_FB: break; 718#endif 719 720 case NORMAL_MEMORY_FB: 721 pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes); 722 break; 723 } 724 725 if (pvfb->pXWDHeader) 726 { 727 pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader 728 + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN); 729 pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors); 730 731 return pvfb->pfbMemory; 732 } 733 else 734 return NULL; 735} 736 737 738static void 739vfbWriteXWDFileHeader(ScreenPtr pScreen) 740{ 741 vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum]; 742 XWDFileHeader *pXWDHeader = pvfb->pXWDHeader; 743 char hostname[XWD_WINDOW_NAME_LEN]; 744 unsigned long swaptest = 1; 745 int i; 746 747 needswap = *(char *) &swaptest; 748 749 pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader; 750 pXWDHeader->file_version = XWD_FILE_VERSION; 751 752 pXWDHeader->pixmap_format = ZPixmap; 753 pXWDHeader->pixmap_depth = pvfb->depth; 754 pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height; 755 pXWDHeader->xoffset = 0; 756 pXWDHeader->byte_order = IMAGE_BYTE_ORDER; 757 pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER; 758#ifndef INTERNAL_VS_EXTERNAL_PADDING 759 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width; 760 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT; 761 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD; 762#else 763 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth; 764 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO; 765 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO; 766#endif 767 pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel; 768 pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth; 769 pXWDHeader->ncolors = pvfb->ncolors; 770 771 /* visual related fields are written when colormap is installed */ 772 773 pXWDHeader->window_x = pXWDHeader->window_y = 0; 774 pXWDHeader->window_bdrwidth = 0; 775 776 /* write xwd "window" name: Xvfb hostname:server.screen */ 777 778 if (-1 == gethostname(hostname, sizeof(hostname))) 779 hostname[0] = 0; 780 else 781 hostname[XWD_WINDOW_NAME_LEN-1] = 0; 782 sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display, 783 pScreen->myNum); 784 785 /* write colormap pixel slot values */ 786 787 for (i = 0; i < pvfb->ncolors; i++) 788 { 789 pvfb->pXWDCmap[i].pixel = i; 790 } 791 792 /* byte swap to most significant byte first */ 793 794 if (needswap) 795 { 796 SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4); 797 for (i = 0; i < pvfb->ncolors; i++) 798 { 799 register char n; 800 swapl(&pvfb->pXWDCmap[i].pixel, n); 801 } 802 } 803} 804 805 806static Bool 807vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y) 808{ 809 return FALSE; 810} 811 812static void 813vfbCrossScreen (ScreenPtr pScreen, Bool entering) 814{ 815} 816 817static miPointerScreenFuncRec vfbPointerCursorFuncs = 818{ 819 vfbCursorOffScreen, 820 vfbCrossScreen, 821 miPointerWarpCursor 822}; 823 824static Bool 825vfbCloseScreen(int index, ScreenPtr pScreen) 826{ 827 vfbScreenInfoPtr pvfb = &vfbScreens[index]; 828 int i; 829 830 pScreen->CloseScreen = pvfb->closeScreen; 831 832 /* 833 * XXX probably lots of stuff to clean. For now, 834 * clear InstalledMaps[] so that server reset works correctly. 835 */ 836 for (i = 0; i < MAXSCREENS; i++) 837 InstalledMaps[i] = NULL; 838 839 return pScreen->CloseScreen(index, pScreen); 840} 841 842static Bool 843vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) 844{ 845 vfbScreenInfoPtr pvfb = &vfbScreens[index]; 846 int dpix = monitorResolution, dpiy = monitorResolution; 847 int ret; 848 char *pbits; 849 850 if (dpix == 0) 851 dpix = 100; 852 853 if (dpiy == 0) 854 dpiy = 100; 855 856 pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth); 857 pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth); 858 if (pvfb->bitsPerPixel >= 8 ) 859 pvfb->paddedWidth = pvfb->paddedBytesWidth / (pvfb->bitsPerPixel / 8); 860 else 861 pvfb->paddedWidth = pvfb->paddedBytesWidth * 8; 862 pbits = vfbAllocateFramebufferMemory(pvfb); 863 if (!pbits) return FALSE; 864 865 miSetPixmapDepths (); 866 867 switch (pvfb->depth) { 868 case 8: 869 miSetVisualTypesAndMasks (8, 870 ((1 << StaticGray) | 871 (1 << GrayScale) | 872 (1 << StaticColor) | 873 (1 << PseudoColor) | 874 (1 << TrueColor) | 875 (1 << DirectColor)), 876 8, PseudoColor, 0, 0, 0); 877 break; 878#if 0 879 /* 12bit PseudoColor with 12bit color resolution 880 * (to simulate SGI hardware and the 12bit PseudoColor emulation layer) */ 881 case 12: 882 miSetVisualTypesAndMasks (12, 883 ((1 << StaticGray) | 884 (1 << GrayScale) | 885 (1 << StaticColor) | 886 (1 << PseudoColor) | 887 (1 << TrueColor) | 888 (1 << DirectColor)), 889 12, PseudoColor, 0, 0, 0); 890 break; 891#endif 892 case 15: 893 miSetVisualTypesAndMasks (15, 894 ((1 << TrueColor) | 895 (1 << DirectColor)), 896 8, TrueColor, 0x7c00, 0x03e0, 0x001f); 897 break; 898 case 16: 899 miSetVisualTypesAndMasks (16, 900 ((1 << TrueColor) | 901 (1 << DirectColor)), 902 8, TrueColor, 0xf800, 0x07e0, 0x001f); 903 break; 904 case 24: 905 miSetVisualTypesAndMasks (24, 906 ((1 << TrueColor) | 907 (1 << DirectColor)), 908 8, TrueColor, 0xff0000, 0x00ff00, 0x0000ff); 909 break; 910#if 0 911 /* 30bit TrueColor (to simulate Sun's XVR-1000/-4000 high quality 912 * framebuffer series) */ 913 case 30: 914 miSetVisualTypesAndMasks (30, 915 ((1 << TrueColor) | 916 (1 << DirectColor)), 917 10, TrueColor, 0x3ff00000, 0x000ffc00, 0x000003ff); 918 break; 919#endif 920 } 921 922 ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height, 923 dpix, dpiy, pvfb->paddedWidth,pvfb->bitsPerPixel); 924#ifdef RENDER 925 if (ret && Render) 926 fbPictureInit (pScreen, 0, 0); 927#endif 928 929 if (!ret) return FALSE; 930 931 miInitializeBackingStore(pScreen); 932 933 /* 934 * Circumvent the backing store that was just initialised. This amounts 935 * to a truely bizarre way of initialising SaveDoomedAreas and friends. 936 */ 937 938 pScreen->InstallColormap = vfbInstallColormap; 939 pScreen->UninstallColormap = vfbUninstallColormap; 940 pScreen->ListInstalledColormaps = vfbListInstalledColormaps; 941 942 pScreen->SaveScreen = vfbSaveScreen; 943 pScreen->StoreColors = vfbStoreColors; 944 945 miDCInitialize(pScreen, &vfbPointerCursorFuncs); 946 947 vfbWriteXWDFileHeader(pScreen); 948 949 pScreen->blackPixel = pvfb->blackPixel; 950 pScreen->whitePixel = pvfb->whitePixel; 951 952 ret = fbCreateDefColormap(pScreen); 953 954 miSetZeroLineBias(pScreen, pvfb->lineBias); 955 956 pvfb->closeScreen = pScreen->CloseScreen; 957 pScreen->CloseScreen = vfbCloseScreen; 958 959 return ret; 960 961} /* end vfbScreenInit */ 962 963 964void 965InitOutput(ScreenInfo *screenInfo, int argc, char **argv) 966{ 967 int i; 968 int NumFormats = 0; 969 970 /* initialize pixmap formats */ 971 972 /* must have a pixmap depth to match every screen depth */ 973 for (i = 0; i < vfbNumScreens; i++) 974 { 975 vfbPixmapDepths[vfbScreens[i].depth] = TRUE; 976 } 977 978 /* RENDER needs a good set of pixmaps. */ 979 if (Render) { 980 vfbPixmapDepths[1] = TRUE; 981 vfbPixmapDepths[4] = TRUE; 982 vfbPixmapDepths[8] = TRUE; 983#if 0 984 vfbPixmapDepths[12] = TRUE; 985#endif 986/* vfbPixmapDepths[15] = TRUE; */ 987 vfbPixmapDepths[16] = TRUE; 988 vfbPixmapDepths[24] = TRUE; 989#if 0 990 vfbPixmapDepths[30] = TRUE; 991#endif 992 vfbPixmapDepths[32] = TRUE; 993 } 994 995 for (i = 1; i <= 32; i++) 996 { 997 if (vfbPixmapDepths[i]) 998 { 999 if (NumFormats >= MAXFORMATS) 1000 FatalError ("MAXFORMATS is too small for this server\n"); 1001 screenInfo->formats[NumFormats].depth = i; 1002 screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i); 1003 screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD; 1004 NumFormats++; 1005 } 1006 } 1007 1008 screenInfo->imageByteOrder = IMAGE_BYTE_ORDER; 1009 screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; 1010 screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; 1011 screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; 1012 screenInfo->numPixmapFormats = NumFormats; 1013 1014 /* initialize screens */ 1015 1016 for (i = 0; i < vfbNumScreens; i++) 1017 { 1018 if (-1 == AddScreen(vfbScreenInit, argc, argv)) 1019 { 1020 FatalError("Couldn't add screen %d", i); 1021 } 1022 } 1023 1024} /* end InitOutput */ 1025