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