xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

InitOutput.c (28299B)


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