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