1706f2543Smrg/*
2706f2543Smrg
3706f2543SmrgCopyright 1993, 1998  The Open Group
4706f2543Smrg
5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
7706f2543Smrgthe above copyright notice appear in all copies and that both that
8706f2543Smrgcopyright notice and this permission notice appear in supporting
9706f2543Smrgdocumentation.
10706f2543Smrg
11706f2543SmrgThe above copyright notice and this permission notice shall be included
12706f2543Smrgin all copies or substantial portions of the Software.
13706f2543Smrg
14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17706f2543SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18706f2543SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19706f2543SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20706f2543SmrgOTHER DEALINGS IN THE SOFTWARE.
21706f2543Smrg
22706f2543SmrgExcept as contained in this notice, the name of The Open Group shall
23706f2543Smrgnot be used in advertising or otherwise to promote the sale, use or
24706f2543Smrgother dealings in this Software without prior written authorization
25706f2543Smrgfrom The Open Group.
26706f2543Smrg
27706f2543Smrg*/
28706f2543Smrg
29706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
30706f2543Smrg#include <dix-config.h>
31706f2543Smrg#endif
32706f2543Smrg
33706f2543Smrg#if defined(WIN32)
34706f2543Smrg#include <X11/Xwinsock.h>
35706f2543Smrg#endif
36706f2543Smrg#include <stdio.h>
37706f2543Smrg#include <X11/X.h>
38706f2543Smrg#include <X11/Xproto.h>
39706f2543Smrg#include <X11/Xos.h>
40706f2543Smrg#include "scrnintstr.h"
41706f2543Smrg#include "servermd.h"
42706f2543Smrg#define PSZ 8
43706f2543Smrg#include "fb.h"
44706f2543Smrg#include "mibstore.h"
45706f2543Smrg#include "colormapst.h"
46706f2543Smrg#include "gcstruct.h"
47706f2543Smrg#include "input.h"
48706f2543Smrg#include "mipointer.h"
49706f2543Smrg#include "micmap.h"
50706f2543Smrg#include <sys/types.h>
51706f2543Smrg#ifdef HAS_MMAP
52706f2543Smrg#include <sys/mman.h>
53706f2543Smrg#ifndef MAP_FILE
54706f2543Smrg#define MAP_FILE 0
55706f2543Smrg#endif
56706f2543Smrg#endif /* HAS_MMAP */
57706f2543Smrg#include <sys/stat.h>
58706f2543Smrg#include <errno.h>
59706f2543Smrg#ifndef WIN32
60706f2543Smrg#include <sys/param.h>
61706f2543Smrg#endif
62706f2543Smrg#include <X11/XWDFile.h>
63706f2543Smrg#ifdef HAS_SHM
64706f2543Smrg#include <sys/ipc.h>
65706f2543Smrg#include <sys/shm.h>
66706f2543Smrg#endif /* HAS_SHM */
67706f2543Smrg#include "dix.h"
68706f2543Smrg#include "miline.h"
69706f2543Smrg
70706f2543Smrg#define VFB_DEFAULT_WIDTH      1280
71706f2543Smrg#define VFB_DEFAULT_HEIGHT     1024
72706f2543Smrg#define VFB_DEFAULT_DEPTH         8
73706f2543Smrg#define VFB_DEFAULT_WHITEPIXEL    1
74706f2543Smrg#define VFB_DEFAULT_BLACKPIXEL    0
75706f2543Smrg#define VFB_DEFAULT_LINEBIAS      0
76706f2543Smrg#define XWD_WINDOW_NAME_LEN      60
77706f2543Smrg
78706f2543Smrgtypedef struct
79706f2543Smrg{
80706f2543Smrg    int width;
81706f2543Smrg    int paddedBytesWidth;
82706f2543Smrg    int paddedWidth;
83706f2543Smrg    int height;
84706f2543Smrg    int depth;
85706f2543Smrg    int bitsPerPixel;
86706f2543Smrg    int sizeInBytes;
87706f2543Smrg    int ncolors;
88706f2543Smrg    char *pfbMemory;
89706f2543Smrg    XWDColor *pXWDCmap;
90706f2543Smrg    XWDFileHeader *pXWDHeader;
91706f2543Smrg    Pixel blackPixel;
92706f2543Smrg    Pixel whitePixel;
93706f2543Smrg    unsigned int lineBias;
94706f2543Smrg    CloseScreenProcPtr closeScreen;
95706f2543Smrg
96706f2543Smrg#ifdef HAS_MMAP
97706f2543Smrg    int mmap_fd;
98706f2543Smrg    char mmap_file[MAXPATHLEN];
99706f2543Smrg#endif
100706f2543Smrg
101706f2543Smrg#ifdef HAS_SHM
102706f2543Smrg    int shmid;
103706f2543Smrg#endif
104706f2543Smrg} vfbScreenInfo, *vfbScreenInfoPtr;
105706f2543Smrg
106706f2543Smrgstatic int vfbNumScreens;
107706f2543Smrgstatic vfbScreenInfo *vfbScreens;
108706f2543Smrgstatic vfbScreenInfo defaultScreenInfo = {
109706f2543Smrg    .width  = VFB_DEFAULT_WIDTH,
110706f2543Smrg    .height = VFB_DEFAULT_HEIGHT,
111706f2543Smrg    .depth  = VFB_DEFAULT_DEPTH,
112706f2543Smrg    .blackPixel = VFB_DEFAULT_BLACKPIXEL,
113706f2543Smrg    .whitePixel = VFB_DEFAULT_WHITEPIXEL,
114706f2543Smrg    .lineBias = VFB_DEFAULT_LINEBIAS,
115706f2543Smrg};
116706f2543Smrgstatic Bool vfbPixmapDepths[33];
117706f2543Smrg#ifdef HAS_MMAP
118706f2543Smrgstatic char *pfbdir = NULL;
119706f2543Smrg#endif
120706f2543Smrgtypedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType;
121706f2543Smrgstatic fbMemType fbmemtype = NORMAL_MEMORY_FB;
122706f2543Smrgstatic char needswap = 0;
123706f2543Smrgstatic Bool Render = TRUE;
124706f2543Smrg
125706f2543Smrg#define swapcopy16(_dst, _src) \
126706f2543Smrg    if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \
127706f2543Smrg    else _dst = _src;
128706f2543Smrg
129706f2543Smrg#define swapcopy32(_dst, _src) \
130706f2543Smrg    if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
131706f2543Smrg    else _dst = _src;
132706f2543Smrg
133706f2543Smrg
134706f2543Smrgstatic void
135706f2543SmrgvfbInitializePixmapDepths(void)
136706f2543Smrg{
137706f2543Smrg    int i;
138706f2543Smrg    vfbPixmapDepths[1] = TRUE; /* always need bitmaps */
139706f2543Smrg    for (i = 2; i <= 32; i++)
140706f2543Smrg	vfbPixmapDepths[i] = FALSE;
141706f2543Smrg}
142706f2543Smrg
143706f2543Smrgstatic int
144706f2543SmrgvfbBitsPerPixel(int depth)
145706f2543Smrg{
146706f2543Smrg    if (depth == 1) return 1;
147706f2543Smrg    else if (depth <= 8) return 8;
148706f2543Smrg    else if (depth <= 16) return 16;
149706f2543Smrg    else return 32;
150706f2543Smrg}
151706f2543Smrg
152706f2543Smrgvoid
153706f2543SmrgddxGiveUp(void)
154706f2543Smrg{
155706f2543Smrg    int i;
156706f2543Smrg
157706f2543Smrg    /* clean up the framebuffers */
158706f2543Smrg
159706f2543Smrg    switch (fbmemtype)
160706f2543Smrg    {
161706f2543Smrg#ifdef HAS_MMAP
162706f2543Smrg    case MMAPPED_FILE_FB:
163706f2543Smrg	for (i = 0; i < vfbNumScreens; i++)
164706f2543Smrg	{
165706f2543Smrg	    if (-1 == unlink(vfbScreens[i].mmap_file))
166706f2543Smrg	    {
167706f2543Smrg		perror("unlink");
168706f2543Smrg		ErrorF("unlink %s failed, %s",
169706f2543Smrg		       vfbScreens[i].mmap_file, strerror(errno));
170706f2543Smrg	    }
171706f2543Smrg	}
172706f2543Smrg	break;
173706f2543Smrg#else /* HAS_MMAP */
174706f2543Smrg    case MMAPPED_FILE_FB:
175706f2543Smrg        break;
176706f2543Smrg#endif /* HAS_MMAP */
177706f2543Smrg
178706f2543Smrg#ifdef HAS_SHM
179706f2543Smrg    case SHARED_MEMORY_FB:
180706f2543Smrg	for (i = 0; i < vfbNumScreens; i++)
181706f2543Smrg	{
182706f2543Smrg	    if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader))
183706f2543Smrg	    {
184706f2543Smrg		perror("shmdt");
185706f2543Smrg		ErrorF("shmdt failed, %s", strerror(errno));
186706f2543Smrg	    }
187706f2543Smrg	}
188706f2543Smrg	break;
189706f2543Smrg#else /* HAS_SHM */
190706f2543Smrg    case SHARED_MEMORY_FB:
191706f2543Smrg        break;
192706f2543Smrg#endif /* HAS_SHM */
193706f2543Smrg
194706f2543Smrg    case NORMAL_MEMORY_FB:
195706f2543Smrg	for (i = 0; i < vfbNumScreens; i++)
196706f2543Smrg	{
197706f2543Smrg	    free(vfbScreens[i].pXWDHeader);
198706f2543Smrg	}
199706f2543Smrg	break;
200706f2543Smrg    }
201706f2543Smrg}
202706f2543Smrg
203706f2543Smrgvoid
204706f2543SmrgAbortDDX(void)
205706f2543Smrg{
206706f2543Smrg    ddxGiveUp();
207706f2543Smrg}
208706f2543Smrg
209706f2543Smrg#ifdef __APPLE__
210706f2543Smrgvoid
211706f2543SmrgDarwinHandleGUI(int argc, char *argv[])
212706f2543Smrg{
213706f2543Smrg}
214706f2543Smrg#endif
215706f2543Smrg
216706f2543Smrgvoid
217706f2543SmrgOsVendorInit(void)
218706f2543Smrg{
219706f2543Smrg}
220706f2543Smrg
221706f2543Smrgvoid
222706f2543SmrgOsVendorFatalError(void)
223706f2543Smrg{
224706f2543Smrg}
225706f2543Smrg
226706f2543Smrg#if defined(DDXBEFORERESET)
227706f2543Smrgvoid ddxBeforeReset(void)
228706f2543Smrg{
229706f2543Smrg    return;
230706f2543Smrg}
231706f2543Smrg#endif
232706f2543Smrg
233706f2543Smrgvoid
234706f2543SmrgddxUseMsg(void)
235706f2543Smrg{
236706f2543Smrg    ErrorF("-screen scrn WxHxD     set screen's width, height, depth\n");
237706f2543Smrg    ErrorF("-pixdepths list-of-int support given pixmap depths\n");
238706f2543Smrg    ErrorF("+/-render		   turn on/off RENDER extension support"
239706f2543Smrg	   "(default on)\n");
240706f2543Smrg    ErrorF("-linebias n            adjust thin line pixelization\n");
241706f2543Smrg    ErrorF("-blackpixel n          pixel value for black\n");
242706f2543Smrg    ErrorF("-whitepixel n          pixel value for white\n");
243706f2543Smrg
244706f2543Smrg#ifdef HAS_MMAP
245706f2543Smrg    ErrorF("-fbdir directory       put framebuffers in mmap'ed files in directory\n");
246706f2543Smrg#endif
247706f2543Smrg
248706f2543Smrg#ifdef HAS_SHM
249706f2543Smrg    ErrorF("-shmem                 put framebuffers in shared memory\n");
250706f2543Smrg#endif
251706f2543Smrg}
252706f2543Smrg
253706f2543Smrgint
254706f2543SmrgddxProcessArgument(int argc, char *argv[], int i)
255706f2543Smrg{
256706f2543Smrg    static Bool firstTime = TRUE;
257706f2543Smrg    static int lastScreen = -1;
258706f2543Smrg    vfbScreenInfo *currentScreen;
259706f2543Smrg
260706f2543Smrg    if (firstTime)
261706f2543Smrg    {
262706f2543Smrg	vfbInitializePixmapDepths();
263706f2543Smrg        firstTime = FALSE;
264706f2543Smrg    }
265706f2543Smrg
266706f2543Smrg    if (lastScreen == -1)
267706f2543Smrg	currentScreen = &defaultScreenInfo;
268706f2543Smrg    else
269706f2543Smrg	currentScreen = &vfbScreens[lastScreen];
270706f2543Smrg
271706f2543Smrg#define CHECK_FOR_REQUIRED_ARGUMENTS(num) \
272706f2543Smrg    if (((i + num) >= argc) || (!argv[i + num])) {                      \
273706f2543Smrg      ErrorF("Required argument to %s not specified\n", argv[i]);       \
274706f2543Smrg      UseMsg();                                                         \
275706f2543Smrg      FatalError("Required argument to %s not specified\n", argv[i]);   \
276706f2543Smrg    }
277706f2543Smrg
278706f2543Smrg    if (strcmp (argv[i], "-screen") == 0)	/* -screen n WxHxD */
279706f2543Smrg    {
280706f2543Smrg	int screenNum;
281706f2543Smrg	CHECK_FOR_REQUIRED_ARGUMENTS(2);
282706f2543Smrg	screenNum = atoi(argv[i+1]);
283706f2543Smrg	/* The protocol only has a CARD8 for number of screens in the
284706f2543Smrg	   connection setup block, so don't allow more than that. */
285706f2543Smrg	if ((screenNum < 0) || (screenNum >= 255))
286706f2543Smrg	{
287706f2543Smrg	    ErrorF("Invalid screen number %d\n", screenNum);
288706f2543Smrg	    UseMsg();
289706f2543Smrg	    FatalError("Invalid screen number %d passed to -screen\n",
290706f2543Smrg		       screenNum);
291706f2543Smrg	}
292706f2543Smrg
293706f2543Smrg	if (vfbNumScreens <= screenNum)
294706f2543Smrg	{
295706f2543Smrg	    vfbScreens = realloc(vfbScreens, sizeof(*vfbScreens) * (screenNum + 1));
296706f2543Smrg	    if (!vfbScreens)
297706f2543Smrg		FatalError("Not enough memory for screen %d\n", screenNum);
298706f2543Smrg	    for (; vfbNumScreens <= screenNum; ++vfbNumScreens)
299706f2543Smrg		vfbScreens[vfbNumScreens] = defaultScreenInfo;
300706f2543Smrg	}
301706f2543Smrg
302706f2543Smrg	if (3 != sscanf(argv[i+2], "%dx%dx%d",
303706f2543Smrg			&vfbScreens[screenNum].width,
304706f2543Smrg			&vfbScreens[screenNum].height,
305706f2543Smrg			&vfbScreens[screenNum].depth))
306706f2543Smrg	{
307706f2543Smrg	    ErrorF("Invalid screen configuration %s\n", argv[i+2]);
308706f2543Smrg	    UseMsg();
309706f2543Smrg	    FatalError("Invalid screen configuration %s for -screen %d\n",
310706f2543Smrg		   argv[i+2], screenNum);
311706f2543Smrg	}
312706f2543Smrg
313706f2543Smrg	lastScreen = screenNum;
314706f2543Smrg	return 3;
315706f2543Smrg    }
316706f2543Smrg
317706f2543Smrg    if (strcmp (argv[i], "-pixdepths") == 0)	/* -pixdepths list-of-depth */
318706f2543Smrg    {
319706f2543Smrg	int depth, ret = 1;
320706f2543Smrg
321706f2543Smrg	CHECK_FOR_REQUIRED_ARGUMENTS(1);
322706f2543Smrg	while ((++i < argc) && (depth = atoi(argv[i])) != 0)
323706f2543Smrg	{
324706f2543Smrg	    if (depth < 0 || depth > 32)
325706f2543Smrg	    {
326706f2543Smrg		ErrorF("Invalid pixmap depth %d\n", depth);
327706f2543Smrg		UseMsg();
328706f2543Smrg		FatalError("Invalid pixmap depth %d passed to -pixdepths\n",
329706f2543Smrg			   depth);
330706f2543Smrg	    }
331706f2543Smrg	    vfbPixmapDepths[depth] = TRUE;
332706f2543Smrg	    ret++;
333706f2543Smrg	}
334706f2543Smrg	return ret;
335706f2543Smrg    }
336706f2543Smrg
337706f2543Smrg    if (strcmp (argv[i], "+render") == 0)	/* +render */
338706f2543Smrg    {
339706f2543Smrg	Render = TRUE;
340706f2543Smrg	return 1;
341706f2543Smrg    }
342706f2543Smrg
343706f2543Smrg    if (strcmp (argv[i], "-render") == 0)	/* -render */
344706f2543Smrg    {
345706f2543Smrg	Render = FALSE;
346706f2543Smrg#ifdef COMPOSITE
347706f2543Smrg	noCompositeExtension = TRUE;
348706f2543Smrg#endif
349706f2543Smrg	return 1;
350706f2543Smrg    }
351706f2543Smrg
352706f2543Smrg    if (strcmp (argv[i], "-blackpixel") == 0)	/* -blackpixel n */
353706f2543Smrg    {
354706f2543Smrg	CHECK_FOR_REQUIRED_ARGUMENTS(1);
355706f2543Smrg	currentScreen->blackPixel = atoi(argv[++i]);
356706f2543Smrg	return 2;
357706f2543Smrg    }
358706f2543Smrg
359706f2543Smrg    if (strcmp (argv[i], "-whitepixel") == 0)	/* -whitepixel n */
360706f2543Smrg    {
361706f2543Smrg	CHECK_FOR_REQUIRED_ARGUMENTS(1);
362706f2543Smrg	currentScreen->whitePixel = atoi(argv[++i]);
363706f2543Smrg	return 2;
364706f2543Smrg    }
365706f2543Smrg
366706f2543Smrg    if (strcmp (argv[i], "-linebias") == 0)	/* -linebias n */
367706f2543Smrg    {
368706f2543Smrg	CHECK_FOR_REQUIRED_ARGUMENTS(1);
369706f2543Smrg	currentScreen->lineBias = atoi(argv[++i]);
370706f2543Smrg	return 2;
371706f2543Smrg    }
372706f2543Smrg
373706f2543Smrg#ifdef HAS_MMAP
374706f2543Smrg    if (strcmp (argv[i], "-fbdir") == 0)	/* -fbdir directory */
375706f2543Smrg    {
376706f2543Smrg	CHECK_FOR_REQUIRED_ARGUMENTS(1);
377706f2543Smrg	pfbdir = argv[++i];
378706f2543Smrg	fbmemtype = MMAPPED_FILE_FB;
379706f2543Smrg	return 2;
380706f2543Smrg    }
381706f2543Smrg#endif /* HAS_MMAP */
382706f2543Smrg
383706f2543Smrg#ifdef HAS_SHM
384706f2543Smrg    if (strcmp (argv[i], "-shmem") == 0)	/* -shmem */
385706f2543Smrg    {
386706f2543Smrg	fbmemtype = SHARED_MEMORY_FB;
387706f2543Smrg	return 1;
388706f2543Smrg    }
389706f2543Smrg#endif
390706f2543Smrg
391706f2543Smrg    return 0;
392706f2543Smrg}
393706f2543Smrg
394706f2543Smrgstatic DevPrivateKeyRec cmapScrPrivateKeyRec;
395706f2543Smrg#define cmapScrPrivateKey (&cmapScrPrivateKeyRec)
396706f2543Smrg
397706f2543Smrg#define GetInstalledColormap(s) ((ColormapPtr) dixLookupPrivate(&(s)->devPrivates, cmapScrPrivateKey))
398706f2543Smrg#define SetInstalledColormap(s,c) (dixSetPrivate(&(s)->devPrivates, cmapScrPrivateKey, c))
399706f2543Smrg
400706f2543Smrgstatic int
401706f2543SmrgvfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
402706f2543Smrg{
403706f2543Smrg    /* By the time we are processing requests, we can guarantee that there
404706f2543Smrg     * is always a colormap installed */
405706f2543Smrg    *pmaps = GetInstalledColormap(pScreen)->mid;
406706f2543Smrg    return 1;
407706f2543Smrg}
408706f2543Smrg
409706f2543Smrg
410706f2543Smrgstatic void
411706f2543SmrgvfbInstallColormap(ColormapPtr pmap)
412706f2543Smrg{
413706f2543Smrg    ColormapPtr oldpmap = GetInstalledColormap(pmap->pScreen);
414706f2543Smrg
415706f2543Smrg    if (pmap != oldpmap)
416706f2543Smrg    {
417706f2543Smrg	int entries;
418706f2543Smrg	XWDFileHeader *pXWDHeader;
419706f2543Smrg	XWDColor *pXWDCmap;
420706f2543Smrg	VisualPtr pVisual;
421706f2543Smrg	Pixel *     ppix;
422706f2543Smrg	xrgb *      prgb;
423706f2543Smrg	xColorItem *defs;
424706f2543Smrg	int i;
425706f2543Smrg
426706f2543Smrg	if(oldpmap != (ColormapPtr)None)
427706f2543Smrg	    WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
428706f2543Smrg	/* Install pmap */
429706f2543Smrg	SetInstalledColormap(pmap->pScreen, pmap);
430706f2543Smrg	WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
431706f2543Smrg
432706f2543Smrg	entries = pmap->pVisual->ColormapEntries;
433706f2543Smrg	pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader;
434706f2543Smrg	pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
435706f2543Smrg	pVisual = pmap->pVisual;
436706f2543Smrg
437706f2543Smrg	swapcopy32(pXWDHeader->visual_class, pVisual->class);
438706f2543Smrg	swapcopy32(pXWDHeader->red_mask, pVisual->redMask);
439706f2543Smrg	swapcopy32(pXWDHeader->green_mask, pVisual->greenMask);
440706f2543Smrg	swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask);
441706f2543Smrg	swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue);
442706f2543Smrg	swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries);
443706f2543Smrg
444706f2543Smrg	ppix = (Pixel *)malloc(entries * sizeof(Pixel));
445706f2543Smrg	prgb = (xrgb *)malloc(entries * sizeof(xrgb));
446706f2543Smrg	defs = (xColorItem *)malloc(entries * sizeof(xColorItem));
447706f2543Smrg
448706f2543Smrg	for (i = 0; i < entries; i++)  ppix[i] = i;
449706f2543Smrg	/* XXX truecolor */
450706f2543Smrg	QueryColors(pmap, entries, ppix, prgb, serverClient);
451706f2543Smrg
452706f2543Smrg	for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */
453706f2543Smrg	    defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */
454706f2543Smrg	    defs[i].red = prgb[i].red;
455706f2543Smrg	    defs[i].green = prgb[i].green;
456706f2543Smrg	    defs[i].blue = prgb[i].blue;
457706f2543Smrg	    defs[i].flags =  DoRed|DoGreen|DoBlue;
458706f2543Smrg	}
459706f2543Smrg	(*pmap->pScreen->StoreColors)(pmap, entries, defs);
460706f2543Smrg
461706f2543Smrg	free(ppix);
462706f2543Smrg	free(prgb);
463706f2543Smrg	free(defs);
464706f2543Smrg    }
465706f2543Smrg}
466706f2543Smrg
467706f2543Smrgstatic void
468706f2543SmrgvfbUninstallColormap(ColormapPtr pmap)
469706f2543Smrg{
470706f2543Smrg    ColormapPtr curpmap = GetInstalledColormap(pmap->pScreen);
471706f2543Smrg
472706f2543Smrg    if(pmap == curpmap)
473706f2543Smrg    {
474706f2543Smrg	if (pmap->mid != pmap->pScreen->defColormap)
475706f2543Smrg	{
476706f2543Smrg	    dixLookupResourceByType((pointer *)&curpmap,
477706f2543Smrg				    pmap->pScreen->defColormap,
478706f2543Smrg				    RT_COLORMAP, serverClient,
479706f2543Smrg				    DixInstallAccess);
480706f2543Smrg	    (*pmap->pScreen->InstallColormap)(curpmap);
481706f2543Smrg	}
482706f2543Smrg    }
483706f2543Smrg}
484706f2543Smrg
485706f2543Smrgstatic void
486706f2543SmrgvfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs)
487706f2543Smrg{
488706f2543Smrg    XWDColor *pXWDCmap;
489706f2543Smrg    int i;
490706f2543Smrg
491706f2543Smrg    if (pmap != GetInstalledColormap(pmap->pScreen))
492706f2543Smrg    {
493706f2543Smrg	return;
494706f2543Smrg    }
495706f2543Smrg
496706f2543Smrg    pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
497706f2543Smrg
498706f2543Smrg    if ((pmap->pVisual->class | DynamicClass) == DirectColor)
499706f2543Smrg    {
500706f2543Smrg	return;
501706f2543Smrg    }
502706f2543Smrg
503706f2543Smrg    for (i = 0; i < ndef; i++)
504706f2543Smrg    {
505706f2543Smrg	if (pdefs[i].flags & DoRed)
506706f2543Smrg	{
507706f2543Smrg	    swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red);
508706f2543Smrg	}
509706f2543Smrg	if (pdefs[i].flags & DoGreen)
510706f2543Smrg	{
511706f2543Smrg	    swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green);
512706f2543Smrg	}
513706f2543Smrg	if (pdefs[i].flags & DoBlue)
514706f2543Smrg	{
515706f2543Smrg	    swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue);
516706f2543Smrg	}
517706f2543Smrg    }
518706f2543Smrg}
519706f2543Smrg
520706f2543Smrgstatic Bool
521706f2543SmrgvfbSaveScreen(ScreenPtr pScreen, int on)
522706f2543Smrg{
523706f2543Smrg    return TRUE;
524706f2543Smrg}
525706f2543Smrg
526706f2543Smrg#ifdef HAS_MMAP
527706f2543Smrg
528706f2543Smrg/* this flushes any changes to the screens out to the mmapped file */
529706f2543Smrgstatic void
530706f2543SmrgvfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
531706f2543Smrg{
532706f2543Smrg    int i;
533706f2543Smrg
534706f2543Smrg    for (i = 0; i < vfbNumScreens; i++)
535706f2543Smrg    {
536706f2543Smrg#ifdef MS_ASYNC
537706f2543Smrg	if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
538706f2543Smrg			(size_t)vfbScreens[i].sizeInBytes, MS_ASYNC))
539706f2543Smrg#else
540706f2543Smrg	/* silly NetBSD and who else? */
541706f2543Smrg	if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
542706f2543Smrg			(size_t)vfbScreens[i].sizeInBytes))
543706f2543Smrg#endif
544706f2543Smrg	{
545706f2543Smrg	    perror("msync");
546706f2543Smrg	    ErrorF("msync failed, %s", strerror(errno));
547706f2543Smrg	}
548706f2543Smrg    }
549706f2543Smrg}
550706f2543Smrg
551706f2543Smrg
552706f2543Smrgstatic void
553706f2543SmrgvfbWakeupHandler(pointer blockData, int result, pointer pReadmask)
554706f2543Smrg{
555706f2543Smrg}
556706f2543Smrg
557706f2543Smrg
558706f2543Smrgstatic void
559706f2543SmrgvfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb)
560706f2543Smrg{
561706f2543Smrg#define DUMMY_BUFFER_SIZE 65536
562706f2543Smrg    char dummyBuffer[DUMMY_BUFFER_SIZE];
563706f2543Smrg    int currentFileSize, writeThisTime;
564706f2543Smrg
565706f2543Smrg    sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, (int) (pvfb - vfbScreens));
566706f2543Smrg    if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666)))
567706f2543Smrg    {
568706f2543Smrg	perror("open");
569706f2543Smrg	ErrorF("open %s failed, %s", pvfb->mmap_file, strerror(errno));
570706f2543Smrg	return;
571706f2543Smrg    }
572706f2543Smrg
573706f2543Smrg    /* Extend the file to be the proper size */
574706f2543Smrg
575706f2543Smrg    memset(dummyBuffer, 0, DUMMY_BUFFER_SIZE);
576706f2543Smrg    for (currentFileSize = 0;
577706f2543Smrg	 currentFileSize < pvfb->sizeInBytes;
578706f2543Smrg	 currentFileSize += writeThisTime)
579706f2543Smrg    {
580706f2543Smrg	writeThisTime = min(DUMMY_BUFFER_SIZE,
581706f2543Smrg			    pvfb->sizeInBytes - currentFileSize);
582706f2543Smrg	if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime))
583706f2543Smrg	{
584706f2543Smrg	    perror("write");
585706f2543Smrg	    ErrorF("write %s failed, %s", pvfb->mmap_file, strerror(errno));
586706f2543Smrg	    return;
587706f2543Smrg	}
588706f2543Smrg    }
589706f2543Smrg
590706f2543Smrg    /* try to mmap the file */
591706f2543Smrg
592706f2543Smrg    pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes,
593706f2543Smrg				    PROT_READ|PROT_WRITE,
594706f2543Smrg				    MAP_FILE|MAP_SHARED,
595706f2543Smrg				    pvfb->mmap_fd, 0);
596706f2543Smrg    if (-1 == (long)pvfb->pXWDHeader)
597706f2543Smrg    {
598706f2543Smrg	perror("mmap");
599706f2543Smrg	ErrorF("mmap %s failed, %s", pvfb->mmap_file, strerror(errno));
600706f2543Smrg	pvfb->pXWDHeader = NULL;
601706f2543Smrg	return;
602706f2543Smrg    }
603706f2543Smrg
604706f2543Smrg    if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler,
605706f2543Smrg					NULL))
606706f2543Smrg    {
607706f2543Smrg	pvfb->pXWDHeader = NULL;
608706f2543Smrg    }
609706f2543Smrg}
610706f2543Smrg#endif /* HAS_MMAP */
611706f2543Smrg
612706f2543Smrg
613706f2543Smrg#ifdef HAS_SHM
614706f2543Smrgstatic void
615706f2543SmrgvfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb)
616706f2543Smrg{
617706f2543Smrg    /* create the shared memory segment */
618706f2543Smrg
619706f2543Smrg    pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777);
620706f2543Smrg    if (pvfb->shmid < 0)
621706f2543Smrg    {
622706f2543Smrg	perror("shmget");
623706f2543Smrg	ErrorF("shmget %d bytes failed, %s", pvfb->sizeInBytes, strerror(errno));
624706f2543Smrg	return;
625706f2543Smrg    }
626706f2543Smrg
627706f2543Smrg    /* try to attach it */
628706f2543Smrg
629706f2543Smrg    pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0);
630706f2543Smrg    if (-1 == (long)pvfb->pXWDHeader)
631706f2543Smrg    {
632706f2543Smrg	perror("shmat");
633706f2543Smrg	ErrorF("shmat failed, %s", strerror(errno));
634706f2543Smrg	pvfb->pXWDHeader = NULL;
635706f2543Smrg	return;
636706f2543Smrg    }
637706f2543Smrg
638706f2543Smrg    ErrorF("screen %d shmid %d\n", (int) (pvfb - vfbScreens), pvfb->shmid);
639706f2543Smrg}
640706f2543Smrg#endif /* HAS_SHM */
641706f2543Smrg
642706f2543Smrgstatic char *
643706f2543SmrgvfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb)
644706f2543Smrg{
645706f2543Smrg    if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */
646706f2543Smrg
647706f2543Smrg    pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height;
648706f2543Smrg
649706f2543Smrg    /* Calculate how many entries in colormap.  This is rather bogus, because
650706f2543Smrg     * the visuals haven't even been set up yet, but we need to know because we
651706f2543Smrg     * have to allocate space in the file for the colormap.  The number 10
652706f2543Smrg     * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c.
653706f2543Smrg     */
654706f2543Smrg
655706f2543Smrg    if (pvfb->depth <= 10)
656706f2543Smrg    { /* single index colormaps */
657706f2543Smrg	pvfb->ncolors = 1 << pvfb->depth;
658706f2543Smrg    }
659706f2543Smrg    else
660706f2543Smrg    { /* decomposed colormaps */
661706f2543Smrg	int nplanes_per_color_component = pvfb->depth / 3;
662706f2543Smrg	if (pvfb->depth % 3) nplanes_per_color_component++;
663706f2543Smrg	pvfb->ncolors = 1 << nplanes_per_color_component;
664706f2543Smrg    }
665706f2543Smrg
666706f2543Smrg    /* add extra bytes for XWDFileHeader, window name, and colormap */
667706f2543Smrg
668706f2543Smrg    pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN +
669706f2543Smrg		    pvfb->ncolors * SIZEOF(XWDColor);
670706f2543Smrg
671706f2543Smrg    pvfb->pXWDHeader = NULL;
672706f2543Smrg    switch (fbmemtype)
673706f2543Smrg    {
674706f2543Smrg#ifdef HAS_MMAP
675706f2543Smrg    case MMAPPED_FILE_FB:  vfbAllocateMmappedFramebuffer(pvfb); break;
676706f2543Smrg#else
677706f2543Smrg    case MMAPPED_FILE_FB: break;
678706f2543Smrg#endif
679706f2543Smrg
680706f2543Smrg#ifdef HAS_SHM
681706f2543Smrg    case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break;
682706f2543Smrg#else
683706f2543Smrg    case SHARED_MEMORY_FB: break;
684706f2543Smrg#endif
685706f2543Smrg
686706f2543Smrg    case NORMAL_MEMORY_FB:
687706f2543Smrg	pvfb->pXWDHeader = (XWDFileHeader *)malloc(pvfb->sizeInBytes);
688706f2543Smrg	break;
689706f2543Smrg    }
690706f2543Smrg
691706f2543Smrg    if (pvfb->pXWDHeader)
692706f2543Smrg    {
693706f2543Smrg	pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader
694706f2543Smrg				+ SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN);
695706f2543Smrg	pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors);
696706f2543Smrg
697706f2543Smrg	return pvfb->pfbMemory;
698706f2543Smrg    }
699706f2543Smrg    else
700706f2543Smrg	return NULL;
701706f2543Smrg}
702706f2543Smrg
703706f2543Smrg
704706f2543Smrgstatic void
705706f2543SmrgvfbWriteXWDFileHeader(ScreenPtr pScreen)
706706f2543Smrg{
707706f2543Smrg    vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
708706f2543Smrg    XWDFileHeader *pXWDHeader = pvfb->pXWDHeader;
709706f2543Smrg    char hostname[XWD_WINDOW_NAME_LEN];
710706f2543Smrg    unsigned long swaptest = 1;
711706f2543Smrg    int i;
712706f2543Smrg
713706f2543Smrg    needswap = *(char *) &swaptest;
714706f2543Smrg
715706f2543Smrg    pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader;
716706f2543Smrg    pXWDHeader->file_version = XWD_FILE_VERSION;
717706f2543Smrg
718706f2543Smrg    pXWDHeader->pixmap_format = ZPixmap;
719706f2543Smrg    pXWDHeader->pixmap_depth = pvfb->depth;
720706f2543Smrg    pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height;
721706f2543Smrg    pXWDHeader->xoffset = 0;
722706f2543Smrg    pXWDHeader->byte_order = IMAGE_BYTE_ORDER;
723706f2543Smrg    pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER;
724706f2543Smrg#ifndef INTERNAL_VS_EXTERNAL_PADDING
725706f2543Smrg    pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width;
726706f2543Smrg    pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT;
727706f2543Smrg    pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD;
728706f2543Smrg#else
729706f2543Smrg    pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth;
730706f2543Smrg    pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO;
731706f2543Smrg    pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO;
732706f2543Smrg#endif
733706f2543Smrg    pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel;
734706f2543Smrg    pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth;
735706f2543Smrg    pXWDHeader->ncolors = pvfb->ncolors;
736706f2543Smrg
737706f2543Smrg    /* visual related fields are written when colormap is installed */
738706f2543Smrg
739706f2543Smrg    pXWDHeader->window_x = pXWDHeader->window_y = 0;
740706f2543Smrg    pXWDHeader->window_bdrwidth = 0;
741706f2543Smrg
742706f2543Smrg    /* write xwd "window" name: Xvfb hostname:server.screen */
743706f2543Smrg
744706f2543Smrg    if (-1 == gethostname(hostname, sizeof(hostname)))
745706f2543Smrg	hostname[0] = 0;
746706f2543Smrg    else
747706f2543Smrg	hostname[XWD_WINDOW_NAME_LEN-1] = 0;
748706f2543Smrg    sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display,
749706f2543Smrg	    pScreen->myNum);
750706f2543Smrg
751706f2543Smrg    /* write colormap pixel slot values */
752706f2543Smrg
753706f2543Smrg    for (i = 0; i < pvfb->ncolors; i++)
754706f2543Smrg    {
755706f2543Smrg	pvfb->pXWDCmap[i].pixel = i;
756706f2543Smrg    }
757706f2543Smrg
758706f2543Smrg    /* byte swap to most significant byte first */
759706f2543Smrg
760706f2543Smrg    if (needswap)
761706f2543Smrg    {
762706f2543Smrg	SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4);
763706f2543Smrg	for (i = 0; i < pvfb->ncolors; i++)
764706f2543Smrg	{
765706f2543Smrg	    register char n;
766706f2543Smrg	    swapl(&pvfb->pXWDCmap[i].pixel, n);
767706f2543Smrg	}
768706f2543Smrg    }
769706f2543Smrg}
770706f2543Smrg
771706f2543Smrg
772706f2543Smrgstatic Bool
773706f2543SmrgvfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y)
774706f2543Smrg{
775706f2543Smrg    return FALSE;
776706f2543Smrg}
777706f2543Smrg
778706f2543Smrgstatic void
779706f2543SmrgvfbCrossScreen (ScreenPtr pScreen, Bool entering)
780706f2543Smrg{
781706f2543Smrg}
782706f2543Smrg
783706f2543Smrgstatic miPointerScreenFuncRec vfbPointerCursorFuncs =
784706f2543Smrg{
785706f2543Smrg    vfbCursorOffScreen,
786706f2543Smrg    vfbCrossScreen,
787706f2543Smrg    miPointerWarpCursor
788706f2543Smrg};
789706f2543Smrg
790706f2543Smrgstatic Bool
791706f2543SmrgvfbCloseScreen(int index, ScreenPtr pScreen)
792706f2543Smrg{
793706f2543Smrg    vfbScreenInfoPtr pvfb = &vfbScreens[index];
794706f2543Smrg    int i;
795706f2543Smrg
796706f2543Smrg    pScreen->CloseScreen = pvfb->closeScreen;
797706f2543Smrg
798706f2543Smrg    /*
799706f2543Smrg     * XXX probably lots of stuff to clean.  For now,
800706f2543Smrg     * clear installed colormaps so that server reset works correctly.
801706f2543Smrg     */
802706f2543Smrg    for (i = 0; i < screenInfo.numScreens; i++)
803706f2543Smrg	SetInstalledColormap(screenInfo.screens[i], NULL);
804706f2543Smrg
805706f2543Smrg    return pScreen->CloseScreen(index, pScreen);
806706f2543Smrg}
807706f2543Smrg
808706f2543Smrgstatic Bool
809706f2543SmrgvfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
810706f2543Smrg{
811706f2543Smrg    vfbScreenInfoPtr pvfb = &vfbScreens[index];
812706f2543Smrg    int dpix = monitorResolution, dpiy = monitorResolution;
813706f2543Smrg    int ret;
814706f2543Smrg    char *pbits;
815706f2543Smrg
816706f2543Smrg    if (!dixRegisterPrivateKey(&cmapScrPrivateKeyRec, PRIVATE_SCREEN, 0))
817706f2543Smrg	return FALSE;
818706f2543Smrg
819706f2543Smrg    if (dpix == 0)
820706f2543Smrg      dpix = 100;
821706f2543Smrg
822706f2543Smrg    if (dpiy == 0)
823706f2543Smrg      dpiy = 100;
824706f2543Smrg
825706f2543Smrg    pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth);
826706f2543Smrg    pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
827706f2543Smrg    if (pvfb->bitsPerPixel >= 8 )
828706f2543Smrg	pvfb->paddedWidth = pvfb->paddedBytesWidth / (pvfb->bitsPerPixel / 8);
829706f2543Smrg    else
830706f2543Smrg	pvfb->paddedWidth = pvfb->paddedBytesWidth * 8;
831706f2543Smrg    pbits = vfbAllocateFramebufferMemory(pvfb);
832706f2543Smrg    if (!pbits) return FALSE;
833706f2543Smrg
834706f2543Smrg    switch (pvfb->depth) {
835706f2543Smrg    case 8:
836706f2543Smrg	miSetVisualTypesAndMasks (8,
837706f2543Smrg				  ((1 << StaticGray) |
838706f2543Smrg				   (1 << GrayScale) |
839706f2543Smrg				   (1 << StaticColor) |
840706f2543Smrg				   (1 << PseudoColor) |
841706f2543Smrg				   (1 << TrueColor) |
842706f2543Smrg				   (1 << DirectColor)),
843706f2543Smrg				  8, PseudoColor, 0, 0, 0);
844706f2543Smrg	break;
845706f2543Smrg    case 15:
846706f2543Smrg	miSetVisualTypesAndMasks (15,
847706f2543Smrg				  ((1 << TrueColor) |
848706f2543Smrg				   (1 << DirectColor)),
849706f2543Smrg				  8, TrueColor, 0x7c00, 0x03e0, 0x001f);
850706f2543Smrg	break;
851706f2543Smrg    case 16:
852706f2543Smrg	miSetVisualTypesAndMasks (16,
853706f2543Smrg				  ((1 << TrueColor) |
854706f2543Smrg				   (1 << DirectColor)),
855706f2543Smrg				  8, TrueColor, 0xf800, 0x07e0, 0x001f);
856706f2543Smrg	break;
857706f2543Smrg    case 24:
858706f2543Smrg	miSetVisualTypesAndMasks (24,
859706f2543Smrg				  ((1 << TrueColor) |
860706f2543Smrg				   (1 << DirectColor)),
861706f2543Smrg				  8, TrueColor, 0xff0000, 0x00ff00, 0x0000ff);
862706f2543Smrg	break;
863706f2543Smrg    case 30:
864706f2543Smrg	miSetVisualTypesAndMasks (30,
865706f2543Smrg				  ((1 << TrueColor) |
866706f2543Smrg				   (1 << DirectColor)),
867706f2543Smrg				  10, TrueColor, 0x3ff00000, 0x000ffc00, 0x000003ff);
868706f2543Smrg	break;
869706f2543Smrg    default:
870706f2543Smrg	return FALSE;
871706f2543Smrg    }
872706f2543Smrg
873706f2543Smrg    miSetPixmapDepths ();
874706f2543Smrg
875706f2543Smrg    ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
876706f2543Smrg		       dpix, dpiy, pvfb->paddedWidth,pvfb->bitsPerPixel);
877706f2543Smrg    if (ret && Render)
878706f2543Smrg	fbPictureInit (pScreen, 0, 0);
879706f2543Smrg
880706f2543Smrg    if (!ret) return FALSE;
881706f2543Smrg
882706f2543Smrg    pScreen->InstallColormap = vfbInstallColormap;
883706f2543Smrg    pScreen->UninstallColormap = vfbUninstallColormap;
884706f2543Smrg    pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
885706f2543Smrg
886706f2543Smrg    pScreen->SaveScreen = vfbSaveScreen;
887706f2543Smrg    pScreen->StoreColors = vfbStoreColors;
888706f2543Smrg
889706f2543Smrg    miDCInitialize(pScreen, &vfbPointerCursorFuncs);
890706f2543Smrg
891706f2543Smrg    vfbWriteXWDFileHeader(pScreen);
892706f2543Smrg
893706f2543Smrg    pScreen->blackPixel = pvfb->blackPixel;
894706f2543Smrg    pScreen->whitePixel = pvfb->whitePixel;
895706f2543Smrg
896706f2543Smrg    ret = fbCreateDefColormap(pScreen);
897706f2543Smrg
898706f2543Smrg    miSetZeroLineBias(pScreen, pvfb->lineBias);
899706f2543Smrg
900706f2543Smrg    pvfb->closeScreen = pScreen->CloseScreen;
901706f2543Smrg    pScreen->CloseScreen = vfbCloseScreen;
902706f2543Smrg
903706f2543Smrg    return ret;
904706f2543Smrg
905706f2543Smrg} /* end vfbScreenInit */
906706f2543Smrg
907706f2543Smrg
908706f2543Smrgvoid
909706f2543SmrgInitOutput(ScreenInfo *screenInfo, int argc, char **argv)
910706f2543Smrg{
911706f2543Smrg    int i;
912706f2543Smrg    int NumFormats = 0;
913706f2543Smrg
914706f2543Smrg    /* initialize pixmap formats */
915706f2543Smrg
916706f2543Smrg    /* must have a pixmap depth to match every screen depth */
917706f2543Smrg    for (i = 0; i < vfbNumScreens; i++)
918706f2543Smrg    {
919706f2543Smrg	vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
920706f2543Smrg    }
921706f2543Smrg
922706f2543Smrg    /* RENDER needs a good set of pixmaps. */
923706f2543Smrg    if (Render) {
924706f2543Smrg	vfbPixmapDepths[1] = TRUE;
925706f2543Smrg	vfbPixmapDepths[4] = TRUE;
926706f2543Smrg	vfbPixmapDepths[8] = TRUE;
927706f2543Smrg#if 0
928706f2543Smrg	vfbPixmapDepths[12] = TRUE;
929706f2543Smrg#endif
930706f2543Smrg/*	vfbPixmapDepths[15] = TRUE; */
931706f2543Smrg	vfbPixmapDepths[16] = TRUE;
932706f2543Smrg	vfbPixmapDepths[24] = TRUE;
933706f2543Smrg#if 0
934706f2543Smrg	vfbPixmapDepths[30] = TRUE;
935706f2543Smrg#endif
936706f2543Smrg	vfbPixmapDepths[32] = TRUE;
937706f2543Smrg    }
938706f2543Smrg
939706f2543Smrg    for (i = 1; i <= 32; i++)
940706f2543Smrg    {
941706f2543Smrg	if (vfbPixmapDepths[i])
942706f2543Smrg	{
943706f2543Smrg	    if (NumFormats >= MAXFORMATS)
944706f2543Smrg		FatalError ("MAXFORMATS is too small for this server\n");
945706f2543Smrg	    screenInfo->formats[NumFormats].depth = i;
946706f2543Smrg	    screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
947706f2543Smrg	    screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
948706f2543Smrg	    NumFormats++;
949706f2543Smrg	}
950706f2543Smrg    }
951706f2543Smrg
952706f2543Smrg    screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
953706f2543Smrg    screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
954706f2543Smrg    screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
955706f2543Smrg    screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
956706f2543Smrg    screenInfo->numPixmapFormats = NumFormats;
957706f2543Smrg
958706f2543Smrg    /* initialize screens */
959706f2543Smrg
960706f2543Smrg    if (vfbNumScreens < 1)
961706f2543Smrg    {
962706f2543Smrg	vfbScreens = &defaultScreenInfo;
963706f2543Smrg	vfbNumScreens = 1;
964706f2543Smrg    }
965706f2543Smrg    for (i = 0; i < vfbNumScreens; i++)
966706f2543Smrg    {
967706f2543Smrg	if (-1 == AddScreen(vfbScreenInit, argc, argv))
968706f2543Smrg	{
969706f2543Smrg	    FatalError("Couldn't add screen %d", i);
970706f2543Smrg	}
971706f2543Smrg    }
972706f2543Smrg
973706f2543Smrg} /* end InitOutput */
974