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