os: if inet_ntop() is available, use it for IPv4 addresses as well
[xserver.git] / hw / vfb / InitOutput.c
blob4a448a5ae847c7ecdb2ff8a835278d2cacc20320
1 /*
3 Copyright 1993, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from The Open Group.
29 #include <dix-config.h>
31 #if defined(WIN32)
32 #include <X11/Xwinsock.h>
33 #endif
34 #include <stdio.h>
35 #include <X11/X.h>
36 #include <X11/Xproto.h>
37 #include <X11/Xos.h>
39 #include "dix/colormap_priv.h"
40 #include "dix/dix_priv.h"
41 #include "dix/screenint_priv.h"
42 #include "os/cmdline.h"
43 #include "os/ddx_priv.h"
44 #include "os/osdep.h"
46 #include "scrnintstr.h"
47 #include "servermd.h"
48 #define PSZ 8
49 #include "fb.h"
50 #include "colormapst.h"
51 #include "gcstruct.h"
52 #include "input.h"
53 #include "mipointer.h"
54 #include "micmap.h"
55 #include <sys/types.h>
56 #ifdef HAVE_MMAP
57 #include <sys/mman.h>
58 #ifndef MAP_FILE
59 #define MAP_FILE 0
60 #endif
61 #endif /* HAVE_MMAP */
62 #include <sys/stat.h>
63 #include <errno.h>
64 #ifndef WIN32
65 #include <sys/param.h>
66 #endif
67 #include <X11/XWDFile.h>
68 #ifdef MITSHM
69 #include <sys/ipc.h>
70 #include <sys/shm.h>
71 #endif /* MITSHM */
72 #include "dix.h"
73 #include "miline.h"
74 #include "glx_extinit.h"
75 #include "randrstr.h"
77 #define VFB_DEFAULT_WIDTH 1280
78 #define VFB_DEFAULT_HEIGHT 1024
79 #define VFB_DEFAULT_DEPTH 24
80 #define VFB_DEFAULT_WHITEPIXEL 1
81 #define VFB_DEFAULT_BLACKPIXEL 0
82 #define VFB_DEFAULT_LINEBIAS 0
83 #define XWD_WINDOW_NAME_LEN 60
85 typedef struct {
86 int width;
87 int paddedBytesWidth;
88 int paddedWidth;
89 int height;
90 int depth;
91 int bitsPerPixel;
92 int sizeInBytes;
93 int ncolors;
94 char *pfbMemory;
95 XWDColor *pXWDCmap;
96 XWDFileHeader *pXWDHeader;
97 Pixel blackPixel;
98 Pixel whitePixel;
99 unsigned int lineBias;
100 CloseScreenProcPtr closeScreen;
102 #ifdef HAVE_MMAP
103 int mmap_fd;
104 char mmap_file[MAXPATHLEN];
105 #endif
107 #ifdef MITSHM
108 int shmid;
109 #endif
110 } vfbScreenInfo, *vfbScreenInfoPtr;
112 static int vfbNumScreens;
113 static vfbScreenInfo *vfbScreens;
115 static vfbScreenInfo defaultScreenInfo = {
116 .width = VFB_DEFAULT_WIDTH,
117 .height = VFB_DEFAULT_HEIGHT,
118 .depth = VFB_DEFAULT_DEPTH,
119 .blackPixel = VFB_DEFAULT_BLACKPIXEL,
120 .whitePixel = VFB_DEFAULT_WHITEPIXEL,
121 .lineBias = VFB_DEFAULT_LINEBIAS,
124 static Bool vfbPixmapDepths[33];
126 #ifdef HAVE_MMAP
127 static char *pfbdir = NULL;
128 #endif
129 typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType;
130 static fbMemType fbmemtype = NORMAL_MEMORY_FB;
131 static char needswap = 0;
132 static Bool Render = TRUE;
134 #define swapcopy16(_dst, _src) \
135 if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \
136 else _dst = _src;
138 #define swapcopy32(_dst, _src) \
139 if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
140 else _dst = _src;
142 static void
143 vfbInitializePixmapDepths(void)
145 int i;
147 vfbPixmapDepths[1] = TRUE; /* always need bitmaps */
148 for (i = 2; i <= 32; i++)
149 vfbPixmapDepths[i] = FALSE;
152 static int
153 vfbBitsPerPixel(int depth)
155 if (depth == 1)
156 return 1;
157 else if (depth <= 8)
158 return 8;
159 else if (depth <= 16)
160 return 16;
161 else
162 return 32;
165 static void
166 freeScreenInfo(vfbScreenInfoPtr pvfb)
168 switch (fbmemtype) {
169 #ifdef HAVE_MMAP
170 case MMAPPED_FILE_FB:
171 if (-1 == unlink(pvfb->mmap_file)) {
172 perror("unlink");
173 ErrorF("unlink %s failed, %s",
174 pvfb->mmap_file, strerror(errno));
176 break;
177 #else /* HAVE_MMAP */
178 case MMAPPED_FILE_FB:
179 break;
180 #endif /* HAVE_MMAP */
182 #ifdef MITSHM
183 case SHARED_MEMORY_FB:
184 if (-1 == shmdt((char *) pvfb->pXWDHeader)) {
185 perror("shmdt");
186 ErrorF("shmdt failed, %s", strerror(errno));
188 break;
189 #else /* MITSHM */
190 case SHARED_MEMORY_FB:
191 break;
192 #endif /* MITSHM */
194 case NORMAL_MEMORY_FB:
195 free(pvfb->pXWDHeader);
196 break;
200 void
201 ddxGiveUp(enum ExitCode error)
203 int i;
205 /* clean up the framebuffers */
206 for (i = 0; i < vfbNumScreens; i++) {
207 freeScreenInfo(&vfbScreens[i]);
211 #ifdef __APPLE__
212 void
213 DarwinHandleGUI(int argc, char *argv[])
216 #endif
218 void
219 OsVendorInit(void)
223 void
224 OsVendorFatalError(const char *f, va_list args)
228 #if defined(DDXBEFORERESET)
229 void
230 ddxBeforeReset(void)
232 return;
234 #endif
236 #if INPUTTHREAD
237 /** This function is called in Xserver/os/inputthread.c when starting
238 the input thread. */
239 void
240 ddxInputThreadInit(void)
243 #endif
245 void
246 ddxUseMsg(void)
248 ErrorF("-screen scrn WxHxD set screen's width, height, depth\n");
249 ErrorF("-pixdepths list-of-int support given pixmap depths\n");
250 ErrorF("+/-render turn on/off RENDER extension support"
251 "(default on)\n");
252 ErrorF("-linebias n adjust thin line pixelization\n");
253 ErrorF("-blackpixel n pixel value for black\n");
254 ErrorF("-whitepixel n pixel value for white\n");
256 #ifdef HAVE_MMAP
257 ErrorF
258 ("-fbdir directory put framebuffers in mmap'ed files in directory\n");
259 #endif
261 #ifdef MITSHM
262 ErrorF("-shmem put framebuffers in shared memory\n");
263 #endif
267 ddxProcessArgument(int argc, char *argv[], int i)
269 static Bool firstTime = TRUE;
270 static int lastScreen = -1;
271 vfbScreenInfo *currentScreen;
273 if (firstTime) {
274 vfbInitializePixmapDepths();
275 firstTime = FALSE;
278 if (lastScreen == -1)
279 currentScreen = &defaultScreenInfo;
280 else
281 currentScreen = &vfbScreens[lastScreen];
283 if (strcmp(argv[i], "-screen") == 0) { /* -screen n WxHxD */
284 int screenNum;
286 CHECK_FOR_REQUIRED_ARGUMENTS(2);
287 screenNum = atoi(argv[i + 1]);
288 /* The protocol only has a CARD8 for number of screens in the
289 connection setup block, so don't allow more than that. */
290 if ((screenNum < 0) || (screenNum >= 255)) {
291 ErrorF("Invalid screen number %d\n", screenNum);
292 UseMsg();
293 FatalError("Invalid screen number %d passed to -screen\n",
294 screenNum);
297 if (vfbNumScreens <= screenNum) {
298 vfbScreens =
299 reallocarray(vfbScreens, screenNum + 1, sizeof(*vfbScreens));
300 if (!vfbScreens)
301 FatalError("Not enough memory for screen %d\n", screenNum);
302 for (; vfbNumScreens <= screenNum; ++vfbNumScreens)
303 vfbScreens[vfbNumScreens] = defaultScreenInfo;
306 if (3 != sscanf(argv[i + 2], "%dx%dx%d",
307 &vfbScreens[screenNum].width,
308 &vfbScreens[screenNum].height,
309 &vfbScreens[screenNum].depth)) {
310 ErrorF("Invalid screen configuration %s\n", argv[i + 2]);
311 UseMsg();
312 FatalError("Invalid screen configuration %s for -screen %d\n",
313 argv[i + 2], screenNum);
316 lastScreen = screenNum;
317 return 3;
320 if (strcmp(argv[i], "-pixdepths") == 0) { /* -pixdepths list-of-depth */
321 int depth, ret = 1;
323 CHECK_FOR_REQUIRED_ARGUMENTS(1);
324 while ((++i < argc) && (depth = atoi(argv[i])) != 0) {
325 if (depth < 0 || depth > 32) {
326 ErrorF("Invalid pixmap depth %d\n", depth);
327 UseMsg();
328 FatalError("Invalid pixmap depth %d passed to -pixdepths\n",
329 depth);
331 vfbPixmapDepths[depth] = TRUE;
332 ret++;
334 return ret;
337 if (strcmp(argv[i], "+render") == 0) { /* +render */
338 Render = TRUE;
339 return 1;
342 if (strcmp(argv[i], "-render") == 0) { /* -render */
343 Render = FALSE;
344 #ifdef COMPOSITE
345 noCompositeExtension = TRUE;
346 #endif
347 return 1;
350 if (strcmp(argv[i], "-blackpixel") == 0) { /* -blackpixel n */
351 CHECK_FOR_REQUIRED_ARGUMENTS(1);
352 currentScreen->blackPixel = atoi(argv[++i]);
353 return 2;
356 if (strcmp(argv[i], "-whitepixel") == 0) { /* -whitepixel n */
357 CHECK_FOR_REQUIRED_ARGUMENTS(1);
358 currentScreen->whitePixel = atoi(argv[++i]);
359 return 2;
362 if (strcmp(argv[i], "-linebias") == 0) { /* -linebias n */
363 CHECK_FOR_REQUIRED_ARGUMENTS(1);
364 currentScreen->lineBias = atoi(argv[++i]);
365 return 2;
368 #ifdef HAVE_MMAP
369 if (strcmp(argv[i], "-fbdir") == 0) { /* -fbdir directory */
370 CHECK_FOR_REQUIRED_ARGUMENTS(1);
371 pfbdir = argv[++i];
372 fbmemtype = MMAPPED_FILE_FB;
373 return 2;
375 #endif /* HAVE_MMAP */
377 #ifdef MITSHM
378 if (strcmp(argv[i], "-shmem") == 0) { /* -shmem */
379 fbmemtype = SHARED_MEMORY_FB;
380 return 1;
382 #endif
384 return 0;
387 static void
388 vfbInstallColormap(ColormapPtr pmap)
390 ColormapPtr oldpmap = GetInstalledmiColormap(pmap->pScreen);
392 if (pmap != oldpmap) {
393 int entries;
394 XWDFileHeader *pXWDHeader;
395 VisualPtr pVisual;
396 Pixel *ppix;
397 xrgb *prgb;
398 xColorItem *defs;
399 int i;
401 miInstallColormap(pmap);
403 entries = pmap->pVisual->ColormapEntries;
404 pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader;
405 pVisual = pmap->pVisual;
407 swapcopy32(pXWDHeader->visual_class, pVisual->class);
408 swapcopy32(pXWDHeader->red_mask, pVisual->redMask);
409 swapcopy32(pXWDHeader->green_mask, pVisual->greenMask);
410 swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask);
411 swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue);
412 swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries);
414 ppix = xallocarray(entries, sizeof(Pixel));
415 prgb = xallocarray(entries, sizeof(xrgb));
416 defs = xallocarray(entries, sizeof(xColorItem));
418 for (i = 0; i < entries; i++)
419 ppix[i] = i;
420 /* XXX truecolor */
421 QueryColors(pmap, entries, ppix, prgb, serverClient);
423 for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */
424 defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */
425 defs[i].red = prgb[i].red;
426 defs[i].green = prgb[i].green;
427 defs[i].blue = prgb[i].blue;
428 defs[i].flags = DoRed | DoGreen | DoBlue;
430 (*pmap->pScreen->StoreColors) (pmap, entries, defs);
432 free(ppix);
433 free(prgb);
434 free(defs);
438 static void
439 vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem * pdefs)
441 XWDColor *pXWDCmap;
442 int i;
444 if (pmap != GetInstalledmiColormap(pmap->pScreen)) {
445 return;
448 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
450 if ((pmap->pVisual->class | DynamicClass) == DirectColor) {
451 return;
454 for (i = 0; i < ndef; i++) {
455 if (pdefs[i].flags & DoRed) {
456 swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red);
458 if (pdefs[i].flags & DoGreen) {
459 swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green);
461 if (pdefs[i].flags & DoBlue) {
462 swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue);
467 #ifdef HAVE_MMAP
469 /* this flushes any changes to the screens out to the mmapped file */
470 static void
471 vfbBlockHandler(void *blockData, void *timeout)
473 int i;
475 for (i = 0; i < vfbNumScreens; i++) {
476 #ifdef MS_ASYNC
477 if (-1 == msync((caddr_t) vfbScreens[i].pXWDHeader,
478 (size_t) vfbScreens[i].sizeInBytes, MS_ASYNC))
479 #else
480 /* silly NetBSD and who else? */
481 if (-1 == msync((caddr_t) vfbScreens[i].pXWDHeader,
482 (size_t) vfbScreens[i].sizeInBytes))
483 #endif
485 perror("msync");
486 ErrorF("msync failed, %s", strerror(errno));
491 static void
492 vfbWakeupHandler(void *blockData, int result)
496 static void
497 vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb)
499 #define DUMMY_BUFFER_SIZE 65536
500 char dummyBuffer[DUMMY_BUFFER_SIZE];
501 int currentFileSize, writeThisTime;
503 snprintf(pvfb->mmap_file, sizeof(pvfb->mmap_file), "%s/Xvfb_screen%d",
504 pfbdir, (int) (pvfb - vfbScreens));
505 if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT | O_RDWR, 0666))) {
506 perror("open");
507 ErrorF("open %s failed, %s", pvfb->mmap_file, strerror(errno));
508 return;
511 /* Extend the file to be the proper size */
513 memset(dummyBuffer, 0, DUMMY_BUFFER_SIZE);
514 for (currentFileSize = 0;
515 currentFileSize < pvfb->sizeInBytes;
516 currentFileSize += writeThisTime) {
517 writeThisTime = min(DUMMY_BUFFER_SIZE,
518 pvfb->sizeInBytes - currentFileSize);
519 if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime)) {
520 perror("write");
521 ErrorF("write %s failed, %s", pvfb->mmap_file, strerror(errno));
522 return;
526 /* try to mmap the file */
528 pvfb->pXWDHeader = (XWDFileHeader *) mmap((caddr_t) NULL, pvfb->sizeInBytes,
529 PROT_READ | PROT_WRITE,
530 MAP_FILE | MAP_SHARED,
531 pvfb->mmap_fd, 0);
532 if (-1 == (long) pvfb->pXWDHeader) {
533 perror("mmap");
534 ErrorF("mmap %s failed, %s", pvfb->mmap_file, strerror(errno));
535 pvfb->pXWDHeader = NULL;
536 return;
539 if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler,
540 NULL)) {
541 pvfb->pXWDHeader = NULL;
544 #endif /* HAVE_MMAP */
546 #ifdef MITSHM
547 static void
548 vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb)
550 /* create the shared memory segment */
552 pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT | 0777);
553 if (pvfb->shmid < 0) {
554 perror("shmget");
555 ErrorF("shmget %d bytes failed, %s", pvfb->sizeInBytes,
556 strerror(errno));
557 return;
560 /* try to attach it */
562 pvfb->pXWDHeader = (XWDFileHeader *) shmat(pvfb->shmid, 0, 0);
563 if (-1 == (long) pvfb->pXWDHeader) {
564 perror("shmat");
565 ErrorF("shmat failed, %s", strerror(errno));
566 pvfb->pXWDHeader = NULL;
567 return;
570 ErrorF("screen %d shmid %d\n", (int) (pvfb - vfbScreens), pvfb->shmid);
572 #endif /* MITSHM */
574 static char *
575 vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb)
577 if (pvfb->pfbMemory)
578 return pvfb->pfbMemory; /* already done */
580 pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height;
582 /* Calculate how many entries in colormap. This is rather bogus, because
583 * the visuals haven't even been set up yet, but we need to know because we
584 * have to allocate space in the file for the colormap. The number 10
585 * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c.
588 if (pvfb->depth <= 10) { /* single index colormaps */
589 pvfb->ncolors = 1 << pvfb->depth;
591 else { /* decomposed colormaps */
592 int nplanes_per_color_component = pvfb->depth / 3;
594 if (pvfb->depth % 3)
595 nplanes_per_color_component++;
596 pvfb->ncolors = 1 << nplanes_per_color_component;
599 /* add extra bytes for XWDFileHeader, window name, and colormap */
601 pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN +
602 pvfb->ncolors * SIZEOF(XWDColor);
604 pvfb->pXWDHeader = NULL;
605 switch (fbmemtype) {
606 #ifdef HAVE_MMAP
607 case MMAPPED_FILE_FB:
608 vfbAllocateMmappedFramebuffer(pvfb);
609 break;
610 #else
611 case MMAPPED_FILE_FB:
612 break;
613 #endif
615 #ifdef MITSHM
616 case SHARED_MEMORY_FB:
617 vfbAllocateSharedMemoryFramebuffer(pvfb);
618 break;
619 #else
620 case SHARED_MEMORY_FB:
621 break;
622 #endif
624 case NORMAL_MEMORY_FB:
625 pvfb->pXWDHeader = (XWDFileHeader *) malloc(pvfb->sizeInBytes);
626 break;
629 if (pvfb->pXWDHeader) {
630 pvfb->pXWDCmap = (XWDColor *) ((char *) pvfb->pXWDHeader
631 + SIZEOF(XWDheader) +
632 XWD_WINDOW_NAME_LEN);
633 pvfb->pfbMemory = (char *) (pvfb->pXWDCmap + pvfb->ncolors);
635 return pvfb->pfbMemory;
638 return NULL;
641 static void
642 vfbWriteXWDFileHeader(ScreenPtr pScreen)
644 vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
645 XWDFileHeader *pXWDHeader = pvfb->pXWDHeader;
646 char hostname[XWD_WINDOW_NAME_LEN];
647 unsigned long swaptest = 1;
648 int i;
650 needswap = *(char *) &swaptest;
652 pXWDHeader->header_size =
653 (char *) pvfb->pXWDCmap - (char *) pvfb->pXWDHeader;
654 pXWDHeader->file_version = XWD_FILE_VERSION;
656 pXWDHeader->pixmap_format = ZPixmap;
657 pXWDHeader->pixmap_depth = pvfb->depth;
658 pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height;
659 pXWDHeader->xoffset = 0;
660 pXWDHeader->byte_order = IMAGE_BYTE_ORDER;
661 pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER;
662 #ifndef INTERNAL_VS_EXTERNAL_PADDING
663 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width;
664 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT;
665 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD;
666 #else
667 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth;
668 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO;
669 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO;
670 #endif
671 pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel;
672 pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth;
673 pXWDHeader->ncolors = pvfb->ncolors;
675 /* visual related fields are written when colormap is installed */
677 pXWDHeader->window_x = pXWDHeader->window_y = 0;
678 pXWDHeader->window_bdrwidth = 0;
680 /* write xwd "window" name: Xvfb hostname:server.screen */
682 if (-1 == gethostname(hostname, sizeof(hostname)))
683 hostname[0] = 0;
684 else
685 hostname[XWD_WINDOW_NAME_LEN - 1] = 0;
686 sprintf((char *) (pXWDHeader + 1), "Xvfb %s:%s.%d", hostname, display,
687 pScreen->myNum);
689 /* write colormap pixel slot values */
691 for (i = 0; i < pvfb->ncolors; i++) {
692 pvfb->pXWDCmap[i].pixel = i;
695 /* byte swap to most significant byte first */
697 if (needswap) {
698 SwapLongs((CARD32 *) pXWDHeader, SIZEOF(XWDheader) / 4);
699 for (i = 0; i < pvfb->ncolors; i++) {
700 swapl(&pvfb->pXWDCmap[i].pixel);
705 static Bool
706 vfbCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
708 return FALSE;
711 static void
712 vfbCrossScreen(ScreenPtr pScreen, Bool entering)
716 static miPointerScreenFuncRec vfbPointerCursorFuncs = {
717 vfbCursorOffScreen,
718 vfbCrossScreen,
719 miPointerWarpCursor
722 static Bool
723 vfbCloseScreen(ScreenPtr pScreen)
725 vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
727 pScreen->CloseScreen = pvfb->closeScreen;
730 * fb overwrites miCloseScreen, so do this here
732 if (pScreen->devPrivate)
733 (*pScreen->DestroyPixmap) (pScreen->devPrivate);
734 pScreen->devPrivate = NULL;
736 return pScreen->CloseScreen(pScreen);
739 static Bool
740 vfbRROutputValidateMode(ScreenPtr pScreen,
741 RROutputPtr output,
742 RRModePtr mode)
744 rrScrPriv(pScreen);
746 if (pScrPriv->minWidth <= mode->mode.width &&
747 pScrPriv->maxWidth >= mode->mode.width &&
748 pScrPriv->minHeight <= mode->mode.height &&
749 pScrPriv->maxHeight >= mode->mode.height)
750 return TRUE;
751 else
752 return FALSE;
755 static Bool
756 vfbRRScreenSetSize(ScreenPtr pScreen,
757 CARD16 width,
758 CARD16 height,
759 CARD32 mmWidth,
760 CARD32 mmHeight)
762 rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
764 // Prevent screen updates while we change things around
765 SetRootClip(pScreen, ROOT_CLIP_NONE);
767 pScreen->width = width;
768 pScreen->height = height;
769 pScreen->mmWidth = mmWidth;
770 pScreen->mmHeight = mmHeight;
772 // Restore the ability to update screen, now with new dimensions
773 SetRootClip(pScreen, ROOT_CLIP_FULL);
775 RRScreenSizeNotify (pScreen);
776 RRTellChanged(pScreen);
778 return RROutputSetPhysicalSize(pScrPriv->outputs[pScreen->myNum], mmWidth, mmHeight);
781 static Bool
782 vfbRRCrtcSet(ScreenPtr pScreen,
783 RRCrtcPtr crtc,
784 RRModePtr mode,
785 int x,
786 int y,
787 Rotation rotation,
788 int numOutput,
789 RROutputPtr *outputs)
791 return RRCrtcNotify(crtc, mode, x, y, rotation, NULL, numOutput, outputs);
794 static Bool
795 vfbRRGetInfo(ScreenPtr pScreen, Rotation *rotations)
797 /* Don't support rotations */
798 *rotations = RR_Rotate_0;
800 return TRUE;
803 static Bool
804 vfbRandRInit(ScreenPtr pScreen)
806 rrScrPrivPtr pScrPriv;
807 #if RANDR_12_INTERFACE
808 RRModePtr mode;
809 RRCrtcPtr crtc;
810 RROutputPtr output;
811 xRRModeInfo modeInfo;
812 char name[64];
813 #endif
814 int mmWidth, mmHeight;
816 if (!RRScreenInit (pScreen))
817 return FALSE;
818 pScrPriv = rrGetScrPriv(pScreen);
819 pScrPriv->rrGetInfo = vfbRRGetInfo;
820 #if RANDR_12_INTERFACE
821 pScrPriv->rrCrtcSet = vfbRRCrtcSet;
822 pScrPriv->rrScreenSetSize = vfbRRScreenSetSize;
823 pScrPriv->rrOutputSetProperty = NULL;
824 #if RANDR_13_INTERFACE
825 pScrPriv->rrOutputGetProperty = NULL;
826 #endif
827 pScrPriv->rrOutputValidateMode = vfbRROutputValidateMode;
828 pScrPriv->rrModeDestroy = NULL;
830 mmWidth = pScreen->width * 25.4 / monitorResolution;
831 mmHeight = pScreen->height * 25.4 / monitorResolution;
833 RRScreenSetSizeRange (pScreen,
834 1, 1,
835 pScreen->width, pScreen->height);
837 sprintf (name, "%dx%d", pScreen->width, pScreen->height);
838 memset (&modeInfo, '\0', sizeof (modeInfo));
839 modeInfo.width = pScreen->width;
840 modeInfo.height = pScreen->height;
841 modeInfo.nameLength = strlen (name);
843 mode = RRModeGet (&modeInfo, name);
844 if (!mode)
845 return FALSE;
847 crtc = RRCrtcCreate (pScreen, NULL);
848 if (!crtc)
849 return FALSE;
851 /* This is to avoid xrandr to complain about the gamma missing */
852 RRCrtcGammaSetSize (crtc, 256);
854 output = RROutputCreate (pScreen, "screen", 6, NULL);
855 if (!output)
856 return FALSE;
857 if (!RROutputSetClones (output, NULL, 0))
858 return FALSE;
859 if (!RROutputSetModes (output, &mode, 1, 0))
860 return FALSE;
861 if (!RROutputSetCrtcs (output, &crtc, 1))
862 return FALSE;
863 if (!RROutputSetConnection (output, RR_Connected))
864 return FALSE;
865 if (!RROutputSetPhysicalSize (output, mmWidth, mmHeight))
866 return FALSE;
867 RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, NULL, 1, &output);
868 #endif
869 return TRUE;
872 static Bool
873 vfbScreenInit(ScreenPtr pScreen, int argc, char **argv)
875 vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
876 int dpix = monitorResolution, dpiy = monitorResolution;
877 int ret;
878 char *pbits;
880 if (dpix == 0)
881 dpix = 100;
883 if (dpiy == 0)
884 dpiy = 100;
886 pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth);
887 pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
888 if (pvfb->bitsPerPixel >= 8)
889 pvfb->paddedWidth = pvfb->paddedBytesWidth / (pvfb->bitsPerPixel / 8);
890 else
891 pvfb->paddedWidth = pvfb->paddedBytesWidth * 8;
892 pbits = vfbAllocateFramebufferMemory(pvfb);
893 if (!pbits)
894 return FALSE;
896 switch (pvfb->depth) {
897 case 8:
898 miSetVisualTypesAndMasks(8,
899 ((1 << StaticGray) |
900 (1 << GrayScale) |
901 (1 << StaticColor) |
902 (1 << PseudoColor) |
903 (1 << TrueColor) |
904 (1 << DirectColor)), 8, PseudoColor, 0, 0, 0);
905 break;
906 case 15:
907 miSetVisualTypesAndMasks(15,
908 ((1 << TrueColor) |
909 (1 << DirectColor)),
910 8, TrueColor, 0x7c00, 0x03e0, 0x001f);
911 break;
912 case 16:
913 miSetVisualTypesAndMasks(16,
914 ((1 << TrueColor) |
915 (1 << DirectColor)),
916 8, TrueColor, 0xf800, 0x07e0, 0x001f);
917 break;
918 case 24:
919 miSetVisualTypesAndMasks(24,
920 ((1 << TrueColor) |
921 (1 << DirectColor)),
922 8, TrueColor, 0xff0000, 0x00ff00, 0x0000ff);
923 break;
924 case 30:
925 miSetVisualTypesAndMasks(30,
926 ((1 << TrueColor) |
927 (1 << DirectColor)),
928 10, TrueColor, 0x3ff00000, 0x000ffc00,
929 0x000003ff);
930 break;
931 default:
932 return FALSE;
935 miSetPixmapDepths();
937 ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
938 dpix, dpiy, pvfb->paddedWidth, pvfb->bitsPerPixel);
939 if (ret && Render)
940 fbPictureInit(pScreen, 0, 0);
942 if (!ret)
943 return FALSE;
945 if (!vfbRandRInit(pScreen))
946 return FALSE;
948 pScreen->InstallColormap = vfbInstallColormap;
949 pScreen->StoreColors = vfbStoreColors;
951 miDCInitialize(pScreen, &vfbPointerCursorFuncs);
953 vfbWriteXWDFileHeader(pScreen);
955 pScreen->blackPixel = pvfb->blackPixel;
956 pScreen->whitePixel = pvfb->whitePixel;
958 ret = fbCreateDefColormap(pScreen);
960 miSetZeroLineBias(pScreen, pvfb->lineBias);
962 pvfb->closeScreen = pScreen->CloseScreen;
963 pScreen->CloseScreen = vfbCloseScreen;
965 return ret;
967 } /* end vfbScreenInit */
969 void
970 InitOutput(ScreenInfo * screen_info, int argc, char **argv)
972 int i;
973 int NumFormats = 0;
975 if (!monitorResolution)
976 monitorResolution = 96;
978 /* initialize pixmap formats */
980 /* must have a pixmap depth to match every screen depth */
981 for (i = 0; i < vfbNumScreens; i++) {
982 vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
985 /* RENDER needs a good set of pixmaps. */
986 if (Render) {
987 vfbPixmapDepths[1] = TRUE;
988 vfbPixmapDepths[4] = TRUE;
989 vfbPixmapDepths[8] = TRUE;
990 #if 0
991 vfbPixmapDepths[12] = TRUE;
992 #endif
993 /* vfbPixmapDepths[15] = TRUE; */
994 vfbPixmapDepths[16] = TRUE;
995 vfbPixmapDepths[24] = TRUE;
996 #if 0
997 vfbPixmapDepths[30] = TRUE;
998 #endif
999 vfbPixmapDepths[32] = TRUE;
1002 xorgGlxCreateVendor();
1004 for (i = 1; i <= 32; i++) {
1005 if (vfbPixmapDepths[i]) {
1006 if (NumFormats >= MAXFORMATS)
1007 FatalError("MAXFORMATS is too small for this server\n");
1008 screen_info->formats[NumFormats].depth = i;
1009 screen_info->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
1010 screen_info->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
1011 NumFormats++;
1015 screen_info->imageByteOrder = IMAGE_BYTE_ORDER;
1016 screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
1017 screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
1018 screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
1019 screen_info->numPixmapFormats = NumFormats;
1021 /* initialize screens */
1023 if (vfbNumScreens < 1) {
1024 vfbScreens = &defaultScreenInfo;
1025 vfbNumScreens = 1;
1027 for (i = 0; i < vfbNumScreens; i++) {
1028 if (-1 == AddScreen(vfbScreenInit, argc, argv)) {
1029 FatalError("Couldn't add screen %d", i);
1033 } /* end InitOutput */