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