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