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