diff options
Diffstat (limited to 'hw/xgl/glx')
-rw-r--r-- | hw/xgl/glx/Makefile.am | 42 | ||||
-rw-r--r-- | hw/xgl/glx/module/Makefile.am | 9 | ||||
-rw-r--r-- | hw/xgl/glx/xglx.c | 792 | ||||
-rw-r--r-- | hw/xgl/glx/xglx.h | 74 | ||||
-rw-r--r-- | hw/xgl/glx/xglxinit.c | 43 | ||||
-rw-r--r-- | hw/xgl/glx/xglxorg.c | 676 |
6 files changed, 1480 insertions, 156 deletions
diff --git a/hw/xgl/glx/Makefile.am b/hw/xgl/glx/Makefile.am index 0198d0906..4bc0189a4 100644 --- a/hw/xgl/glx/Makefile.am +++ b/hw/xgl/glx/Makefile.am @@ -10,6 +10,11 @@ SUBDIRS = \ AM_CFLAGS = \ -I$(srcdir)/.. \ + -I$(srcdir)/../glxext \ + -I$(top_srcdir)/GL/glx \ + -I$(top_srcdir)/GL/include \ + -I@MESA_SOURCE@/include \ + -I@MESA_SOURCE@/src/mesa/glapi \ @SERVER_DEFINES@ \ -DHAVE_XGL_CONFIG_H \ -DHAVE_DIX_CONFIG_H \ @@ -19,24 +24,25 @@ noinst_LTLIBRARIES = libxglx.la libxglx_la_SOURCES = \ xglx.h \ - xglx.c + xglx.c \ + xglxorg.c -Xglx_DEPENDENCIES = @XGLX_LIBS@ -Xglx_LDFLAGS = -export-dynamic -Xglx_SOURCES = \ - xglxinit.c \ - $(top_srcdir)/mi/miinitext.c \ - $(top_srcdir)/Xext/dpmsstubs.c \ - $(top_srcdir)/Xi/stubs.c \ - $(top_srcdir)/fb/fbcmap.c -Xglx_LDADD = \ - libxglx.la \ - ../libxgl.a \ - $(XORG_CORE_LIBS) \ - $(XGLX_LIBS) \ - $(XSERVER_LIBS) \ - $(EXTENSION_LIBS) \ - $(XGLXMODULES_LIBS) -Xglx_programs = Xglx +# Xglx_DEPENDENCIES = @XGLX_LIBS@ +# Xglx_LDFLAGS = -export-dynamic +# Xglx_SOURCES = \ +# xglxinit.c \ +# $(top_srcdir)/mi/miinitext.c \ +# $(top_srcdir)/Xext/dpmsstubs.c \ +# $(top_srcdir)/Xi/stubs.c \ +# $(top_srcdir)/fb/fbcmap.c +#Xglx_LDADD = \ +# libxglx.la \ +# ../libxgl.a \ +# $(XORG_CORE_LIBS) \ +# $(XGLX_LIBS) \ +# $(EXTENSION_LIBS) \ +# $(XGLXMODULES_LIBS) \ +# -lXrandr +#Xglx_programs = Xglx bin_PROGRAMS = $(Xglx_programs) diff --git a/hw/xgl/glx/module/Makefile.am b/hw/xgl/glx/module/Makefile.am index e2d1de74e..846942a43 100644 --- a/hw/xgl/glx/module/Makefile.am +++ b/hw/xgl/glx/module/Makefile.am @@ -1,13 +1,20 @@ +if GLX +GLX_LIB = $(top_builddir)/hw/xgl/glxext/libxglglxext.la +endif + AM_CFLAGS = \ -I$(srcdir)/.. \ -I$(srcdir)/../.. \ $(XGLXMODULES_CFLAGS) +libxglx_la_DEPENDENCIES = $(GLX_LIB) libxglx_la_LDFLAGS = -avoid-version libxglx_la_SOURCES = xglxmodule.c libxglx_la_LIBADD = \ $(top_builddir)/hw/xgl/glx/libxglx.la \ - $(XGLXMODULES_LIBS) + $(GLX_LIB) \ + $(XGLXMODULES_LIBS) \ + -lXrandr moduledir = @xglmoduledir@ diff --git a/hw/xgl/glx/xglx.c b/hw/xgl/glx/xglx.c index 842ab19ec..cff3821dd 100644 --- a/hw/xgl/glx/xglx.c +++ b/hw/xgl/glx/xglx.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,23 +12,24 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: David Reveman <davidr@novell.com> */ -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <glitz-glx.h> - #include "xglx.h" +#include <X11/extensions/Xrandr.h> +#include <X11/cursorfont.h> + +#include <glitz-glx.h> + #ifdef GLXEXT #include "xglglxext.h" #endif @@ -37,25 +38,77 @@ #include "cursorstr.h" #include "mipointer.h" +#ifdef RANDR +#include "randrstr.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <math.h> +#ifdef XKB +#include <X11/extensions/XKB.h> +#include <X11/extensions/XKBsrv.h> +#include <X11/extensions/XKBconfig.h> + +extern Bool +XkbQueryExtension (Display *dpy, + int *opcodeReturn, + int *eventBaseReturn, + int *errorBaseReturn, + int *majorRtrn, + int *minorRtrn); + +extern XkbDescPtr +XkbGetKeyboard (Display *dpy, + unsigned int which, + unsigned int deviceSpec); + +extern Status +XkbGetControls (Display *dpy, + unsigned long which, + XkbDescPtr desc); + +#ifndef XKB_BASE_DIRECTORY +#define XKB_BASE_DIRECTORY "/usr/lib/X11/xkb/" +#endif +#ifndef XKB_CONFIG_FILE +#define XKB_CONFIG_FILE "X0-config.keyboard" +#endif +#ifndef XKB_DFLT_RULES_FILE +#define XKB_DFLT_RULES_FILE "xorg" +#endif +#ifndef XKB_DFLT_KB_LAYOUT +#define XKB_DFLT_KB_LAYOUT "us" +#endif +#ifndef XKB_DFLT_KB_MODEL +#define XKB_DFLT_KB_MODEL "pc101" +#endif +#ifndef XKB_DFLT_KB_VARIANT +#define XKB_DFLT_KB_VARIANT NULL +#endif +#ifndef XKB_DFLT_KB_OPTIONS +#define XKB_DFLT_KB_OPTIONS NULL +#endif + +#endif + #define XGLX_DEFAULT_SCREEN_WIDTH 800 #define XGLX_DEFAULT_SCREEN_HEIGHT 600 typedef struct _xglxScreen { - Window win; + Window win, root; Colormap colormap; + Bool fullscreen; CloseScreenProcPtr CloseScreen; } xglxScreenRec, *xglxScreenPtr; int xglxScreenGeneration = -1; int xglxScreenPrivateIndex; -#define XGLX_GET_SCREEN_PRIV(pScreen) \ +#define XGLX_GET_SCREEN_PRIV(pScreen) \ ((xglxScreenPtr) (pScreen)->devPrivates[xglxScreenPrivateIndex].ptr) #define XGLX_SET_SCREEN_PRIV(pScreen, v) \ @@ -83,7 +136,12 @@ static int xscreen; static CARD32 lastEventTime = 0; static ScreenPtr currentScreen = 0; static Bool softCursor = FALSE; -static Bool fullscreen = FALSE; +static Bool fullscreen = TRUE; + +static Bool randrExtension = FALSE; +static int randrEvent, randrError; + +static glitz_drawable_format_t *xglxScreenFormat = 0; static Bool xglxAllocatePrivates (ScreenPtr pScreen) @@ -95,19 +153,232 @@ xglxAllocatePrivates (ScreenPtr pScreen) xglxScreenPrivateIndex = AllocateScreenPrivateIndex (); if (xglxScreenPrivateIndex < 0) return FALSE; - - xglxScreenGeneration = serverGeneration; + + xglxScreenGeneration = serverGeneration; } pScreenPriv = xalloc (sizeof (xglxScreenRec)); if (!pScreenPriv) return FALSE; - + XGLX_SET_SCREEN_PRIV (pScreen, pScreenPriv); - + + return TRUE; +} + +#ifdef RANDR + +#define DEFAULT_REFRESH_RATE 50 + +static Bool +xglxRandRGetInfo (ScreenPtr pScreen, + Rotation *rotations) +{ + RRScreenSizePtr pSize; + + *rotations = RR_Rotate_0; + + if (randrExtension) + { + XRRScreenConfiguration *xconfig; + XRRScreenSize *sizes; + int nSizes, currentSize = 0; + short *rates, currentRate; + int nRates, i, j; + + XGLX_SCREEN_PRIV (pScreen); + + xconfig = XRRGetScreenInfo (xdisplay, pScreenPriv->root); + sizes = XRRConfigSizes (xconfig, &nSizes); + currentRate = XRRConfigCurrentRate (xconfig); + + if (pScreenPriv->fullscreen) + { + Rotation rotation; + + currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation); + + for (i = 0; i < nSizes; i++) + { + pSize = RRRegisterSize (pScreen, + sizes[i].width, + sizes[i].height, + sizes[i].mwidth, + sizes[i].mheight); + + rates = XRRConfigRates (xconfig, i, &nRates); + + for (j = 0; j < nRates; j++) + { + RRRegisterRate (pScreen, pSize, rates[j]); + + if (i == currentSize && rates[j] == currentRate) + RRSetCurrentConfig (pScreen, RR_Rotate_0, currentRate, + pSize); + } + } + } + else + { + pSize = RRRegisterSize (pScreen, + pScreen->width, + pScreen->height, + pScreen->mmWidth, + pScreen->mmHeight); + + for (i = 0; i < nSizes; i++) + { + rates = XRRConfigRates (xconfig, i, &nRates); + + for (j = 0; j < nRates; j++) + { + RRRegisterRate (pScreen, pSize, rates[j]); + + if (rates[j] == currentRate) + RRSetCurrentConfig (pScreen, RR_Rotate_0, currentRate, + pSize); + } + } + } + + XRRFreeScreenConfigInfo (xconfig); + } + else + { + pSize = RRRegisterSize (pScreen, + pScreen->width, + pScreen->height, + pScreen->mmWidth, + pScreen->mmHeight); + + RRRegisterRate (pScreen, pSize, DEFAULT_REFRESH_RATE); + RRSetCurrentConfig (pScreen, RR_Rotate_0, DEFAULT_REFRESH_RATE, pSize); + } + return TRUE; } +static Bool +xglxRandRSetConfig (ScreenPtr pScreen, + Rotation rotations, + int rate, + RRScreenSizePtr pSize) +{ + if (randrExtension) + { + XRRScreenConfiguration *xconfig; + XRRScreenSize *sizes; + int nSizes, currentSize; + int i, size = -1; + int status = RRSetConfigFailed; + Rotation rotation; + + XGLX_SCREEN_PRIV (pScreen); + + xconfig = XRRGetScreenInfo (xdisplay, pScreenPriv->root); + sizes = XRRConfigSizes (xconfig, &nSizes); + currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation); + + for (i = 0; i < nSizes; i++) + { + if (pScreenPriv->fullscreen) + { + if (sizes[i].width == pSize->width && + sizes[i].height == pSize->height && + sizes[i].mwidth == pSize->mmWidth && + sizes[i].mheight == pSize->mmHeight) + { + size = i; + break; + } + } + else + { + short *rates; + int nRates, j; + + rates = XRRConfigRates (xconfig, i, &nRates); + + for (j = 0; j < nRates; j++) + { + if (rates[j] == rate) + { + size = i; + if (i >= currentSize) + break; + } + } + } + } + + if (size >= 0) + status = XRRSetScreenConfigAndRate (xdisplay, + xconfig, + pScreenPriv->root, + size, + RR_Rotate_0, + rate, + CurrentTime); + + XRRFreeScreenConfigInfo (xconfig); + + if (status == RRSetConfigSuccess) + { + PixmapPtr pPixmap; + + pPixmap = (*pScreen->GetScreenPixmap) (pScreen); + + if (pScreenPriv->fullscreen) + { + XGL_PIXMAP_PRIV (pPixmap); + + xglSetRootClip (pScreen, FALSE); + + XResizeWindow (xdisplay, pScreenPriv->win, + pSize->width, pSize->height); + + glitz_drawable_update_size (pPixmapPriv->drawable, + pSize->width, pSize->height); + + pScreen->width = pSize->width; + pScreen->height = pSize->height; + pScreen->mmWidth = pSize->mmWidth; + pScreen->mmHeight = pSize->mmHeight; + + (*pScreen->ModifyPixmapHeader) (pPixmap, + pScreen->width, + pScreen->height, + pPixmap->drawable.depth, + pPixmap->drawable.bitsPerPixel, + 0, 0); + + xglSetRootClip (pScreen, TRUE); + } + + return TRUE; + } + } + + return FALSE; +} + +static Bool +xglxRandRInit (ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (!RRScreenInit (pScreen)) + return FALSE; + + pScrPriv = rrGetScrPriv (pScreen); + pScrPriv->rrGetInfo = xglxRandRGetInfo; + pScrPriv->rrSetConfig = xglxRandRSetConfig; + + return TRUE; +} + +#endif + static void xglxConstrainCursor (ScreenPtr pScreen, BoxPtr pBox) @@ -120,7 +391,7 @@ xglxCursorLimits (ScreenPtr pScreen, BoxPtr pHotBox, BoxPtr pTopLeftBox) { - *pTopLeftBox = *pHotBox; + *pTopLeftBox = *pHotBox; } static Bool @@ -129,9 +400,9 @@ xglxDisplayCursor (ScreenPtr pScreen, { XGLX_SCREEN_PRIV (pScreen); XGLX_CURSOR_PRIV (pCursor, pScreen); - + XDefineCursor (xdisplay, pScreenPriv->win, pCursorPriv->cursor); - + return TRUE; } @@ -154,7 +425,7 @@ xglxRealizeCursor (ScreenPtr pScreen, XImage *ximage; Pixmap source, mask; XColor fgColor, bgColor; - GC xgc; + XlibGC xgc; unsigned long valuemask; XGCValues values; @@ -180,20 +451,20 @@ xglxRealizeCursor (ScreenPtr pScreen, } #endif - source = XCreatePixmap (xdisplay, + source = XCreatePixmap (xdisplay, pScreenPriv->win, pCursor->bits->width, pCursor->bits->height, 1); - - mask = XCreatePixmap (xdisplay, + + mask = XCreatePixmap (xdisplay, pScreenPriv->win, pCursor->bits->width, pCursor->bits->height, 1); - + xgc = XCreateGC (xdisplay, source, valuemask, &values); - + ximage = XCreateImage (xdisplay, DefaultVisual (xdisplay, xscreen), 1, XYBitmap, 0, @@ -201,41 +472,41 @@ xglxRealizeCursor (ScreenPtr pScreen, pCursor->bits->width, pCursor->bits->height, BitmapPad (xdisplay), 0); - + XPutImage (xdisplay, source, xgc, ximage, 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); - + XFree (ximage); - - ximage = XCreateImage (xdisplay, + + ximage = XCreateImage (xdisplay, DefaultVisual (xdisplay, xscreen), - 1, XYBitmap, 0, + 1, XYBitmap, 0, (char *) pCursor->bits->mask, pCursor->bits->width, pCursor->bits->height, BitmapPad (xdisplay), 0); - + XPutImage (xdisplay, mask, xgc, ximage, 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); - + XFree (ximage); XFreeGC (xdisplay, xgc); - + fgColor.red = pCursor->foreRed; fgColor.green = pCursor->foreGreen; fgColor.blue = pCursor->foreBlue; - + bgColor.red = pCursor->backRed; bgColor.green = pCursor->backGreen; bgColor.blue = pCursor->backBlue; - - pCursorPriv->cursor = + + pCursorPriv->cursor = XCreatePixmapCursor (xdisplay, source, mask, &fgColor, &bgColor, pCursor->bits->xhot, pCursor->bits->yhot); XFreePixmap (xdisplay, mask); XFreePixmap (xdisplay, source); - + return TRUE; } @@ -244,10 +515,10 @@ xglxUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) { XGLX_CURSOR_PRIV (pCursor, pScreen); - + XFreeCursor (xdisplay, pCursorPriv->cursor); xfree (pCursorPriv); - + return TRUE; } @@ -259,15 +530,15 @@ xglxRecolorCursor (ScreenPtr pScreen, XColor fgColor, bgColor; XGLX_CURSOR_PRIV (pCursor, pScreen); - + fgColor.red = pCursor->foreRed; fgColor.green = pCursor->foreGreen; fgColor.blue = pCursor->foreBlue; - + bgColor.red = pCursor->backRed; bgColor.green = pCursor->backGreen; bgColor.blue = pCursor->backBlue; - + XRecolorCursor (xdisplay, pCursorPriv->cursor, &fgColor, &bgColor); } @@ -278,10 +549,10 @@ xglxSetCursorPosition (ScreenPtr pScreen, Bool generateEvent) { XGLX_SCREEN_PRIV (pScreen); - + XWarpPointer (xdisplay, pScreenPriv->win, pScreenPriv->win, 0, 0, 0, 0, x, y); - + return TRUE; } @@ -290,7 +561,7 @@ xglxCloseScreen (int index, ScreenPtr pScreen) { glitz_drawable_t *drawable; - + XGLX_SCREEN_PRIV (pScreen); drawable = XGL_GET_SCREEN_PRIV (pScreen)->drawable; @@ -304,10 +575,10 @@ xglxCloseScreen (int index, if (pScreenPriv->colormap) XFreeColormap (xdisplay, pScreenPriv->colormap); - + XGL_SCREEN_UNWRAP (CloseScreen); xfree (pScreenPriv); - + return (*pScreen->CloseScreen) (index, pScreen); } @@ -345,14 +616,13 @@ xglxScreenInit (int index, XSizeHints *normalHints; XClassHint *classHint; xglxScreenPtr pScreenPriv; - Window root; XVisualInfo *vinfo; XEvent xevent; glitz_drawable_format_t *format; glitz_drawable_t *drawable; - - format = xglVisuals[0].format; - + + format = xglxScreenFormat; + if (!xglxAllocatePrivates (pScreen)) return FALSE; @@ -360,7 +630,8 @@ xglxScreenInit (int index, pScreenPriv = XGLX_GET_SCREEN_PRIV (pScreen); - root = RootWindow (xdisplay, xscreen); + pScreenPriv->root = RootWindow (xdisplay, xscreen); + pScreenPriv->fullscreen = fullscreen; vinfo = glitz_glx_get_visual_info_from_format (xdisplay, xscreen, format); if (!vinfo) @@ -370,7 +641,11 @@ xglxScreenInit (int index, } pScreenPriv->colormap = - XCreateColormap (xdisplay, root, vinfo->visual, AllocNone); + XCreateColormap (xdisplay, pScreenPriv->root, vinfo->visual, + AllocNone); + + if (XRRQueryExtension (xdisplay, &randrEvent, &randrError)) + randrExtension = TRUE; if (fullscreen) { @@ -378,6 +653,25 @@ xglxScreenInit (int index, xglScreenInfo.height = DisplayHeight (xdisplay, xscreen); xglScreenInfo.widthMm = DisplayWidthMM (xdisplay, xscreen); xglScreenInfo.heightMm = DisplayHeightMM (xdisplay, xscreen); + + if (randrExtension) + { + XRRScreenConfiguration *xconfig; + Rotation rotation; + XRRScreenSize *sizes; + int nSizes, currentSize; + + xconfig = XRRGetScreenInfo (xdisplay, pScreenPriv->root); + currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation); + sizes = XRRConfigSizes (xconfig, &nSizes); + + xglScreenInfo.width = sizes[currentSize].width; + xglScreenInfo.height = sizes[currentSize].height; + xglScreenInfo.widthMm = sizes[currentSize].mwidth; + xglScreenInfo.heightMm = sizes[currentSize].mheight; + + XRRFreeScreenConfigInfo (xconfig); + } } else if (xglScreenInfo.width == 0 || xglScreenInfo.height == 0) { @@ -386,13 +680,13 @@ xglxScreenInit (int index, } xswa.colormap = pScreenPriv->colormap; - + pScreenPriv->win = - XCreateWindow (xdisplay, root, 0, 0, + XCreateWindow (xdisplay, pScreenPriv->root, 0, 0, xglScreenInfo.width, xglScreenInfo.height, 0, vinfo->depth, InputOutput, vinfo->visual, CWColormap, &xswa); - + XFree (vinfo); normalHints = XAllocSizeHints (); @@ -412,14 +706,14 @@ xglxScreenInit (int index, classHint = XAllocClassHint (); classHint->res_name = "xglx"; classHint->res_class = "Xglx"; - + wmHints = XAllocWMHints (); wmHints->flags = InputHint; wmHints->input = TRUE; - - Xutf8SetWMProperties (xdisplay, pScreenPriv->win, "Xglx", "Xglx", 0, 0, + + Xutf8SetWMProperties (xdisplay, pScreenPriv->win, "Xglx", "Xglx", 0, 0, normalHints, wmHints, classHint); - + XFree (wmHints); XFree (classHint); XFree (normalHints); @@ -438,15 +732,15 @@ xglxScreenInit (int index, ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | PointerMotionMask | ExposureMask); - + XMapWindow (xdisplay, pScreenPriv->win); if (fullscreen) { XClientMessageEvent xev; - + memset (&xev, 0, sizeof (xev)); - + xev.type = ClientMessage; xev.message_type = XInternAtom (xdisplay, "_NET_WM_STATE", FALSE); xev.display = xdisplay; @@ -455,13 +749,13 @@ xglxScreenInit (int index, xev.data.l[0] = 1; xev.data.l[1] = XInternAtom (xdisplay, "_NET_WM_STATE_FULLSCREEN", FALSE); - - XSendEvent (xdisplay, root, FALSE, SubstructureRedirectMask, - (XEvent *) &xev); + + XSendEvent (xdisplay, pScreenPriv->root, FALSE, + SubstructureRedirectMask, (XEvent *) &xev); } xglScreenInfo.drawable = drawable; - + if (!xglScreenInit (pScreen)) return FALSE; @@ -476,28 +770,28 @@ xglxScreenInit (int index, if (!xglxARGBCursorSupport ()) softCursor = TRUE; #endif - + if (softCursor) { static char data = 0; XColor black, dummy; Pixmap bitmap; Cursor cursor; - + if (!XAllocNamedColor (xdisplay, pScreenPriv->colormap, "black", &black, &dummy)) return FALSE; - + bitmap = XCreateBitmapFromData (xdisplay, pScreenPriv->win, &data, 1, 1); if (!bitmap) return FALSE; - + cursor = XCreatePixmapCursor (xdisplay, bitmap, bitmap, &black, &black, 0, 0); if (!cursor) return FALSE; - + XDefineCursor (xdisplay, pScreenPriv->win, cursor); XFreeCursor (xdisplay, cursor); @@ -519,7 +813,12 @@ xglxScreenInit (int index, if (!xglFinishScreenInit (pScreen)) return FALSE; - + +#ifdef RANDR + if (!xglxRandRInit (pScreen)) + return FALSE; +#endif + while (XNextEvent (xdisplay, &xevent)) if (xevent.type == Expose) break; @@ -535,34 +834,67 @@ xglxInitOutput (ScreenInfo *pScreenInfo, glitz_drawable_format_t *format, templ; int i; unsigned long mask; + unsigned long extraMask[] = { + GLITZ_FORMAT_DOUBLEBUFFER_MASK | GLITZ_FORMAT_ALPHA_SIZE_MASK, + GLITZ_FORMAT_DOUBLEBUFFER_MASK, + GLITZ_FORMAT_ALPHA_SIZE_MASK, + 0 + }; + + xglClearVisualTypes (); xglSetPixmapFormats (pScreenInfo); - + if (!xdisplay) { - xdisplay = XOpenDisplay (xDisplayName); + char *name = xDisplayName; + + if (!name) + name = xglxInitXorg (); + + xdisplay = XOpenDisplay (name); if (!xdisplay) - FatalError ("can't open display"); + FatalError ("can't open display: %s\n", name ? name : "NULL"); xscreen = DefaultScreen (xdisplay); + + if (!xDisplayName) + XDefineCursor (xdisplay, RootWindow (xdisplay, xscreen), + XCreateFontCursor (xdisplay, XC_watch)); } templ.samples = 1; templ.doublebuffer = 1; + templ.color.fourcc = GLITZ_FOURCC_RGB; templ.color.alpha_size = 8; - - mask = GLITZ_FORMAT_SAMPLES_MASK; - format = glitz_glx_find_window_format (xdisplay, xscreen, - mask, &templ, 0); - + mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_FOURCC_MASK; + + for (i = 0; i < sizeof (extraMask) / sizeof (extraMask[0]); i++) + { + format = glitz_glx_find_window_format (xdisplay, xscreen, + mask | extraMask[i], + &templ, 0); + if (format) + break; + } + if (!format) FatalError ("no visual format found"); - xglSetVisualTypesAndMasks (pScreenInfo, format, (1 << TrueColor)); - - xglInitVisuals (pScreenInfo); - + xglScreenInfo.depth = + format->color.red_size + + format->color.green_size + + format->color.blue_size; + + xglSetVisualTypes (xglScreenInfo.depth, + (1 << TrueColor), + format->color.red_size, + format->color.green_size, + format->color.blue_size); + + xglxScreenFormat = format; + AddScreen (xglxScreenInit, argc, argv); } @@ -591,15 +923,15 @@ xglxWindowExposures (WindowPtr pWin, if (HasBorder (pWin)) { - REGION_NULL (pScreen, &ClipList); + REGION_INIT (pScreen, &ClipList, NullBox, 0); REGION_SUBTRACT (pScreen, &ClipList, &pWin->borderClip, &pWin->winSize); REGION_INTERSECT (pScreen, &ClipList, &ClipList, (RegionPtr) pReg); (*pScreen->PaintWindowBorder) (pWin, &ClipList, PW_BORDER); REGION_UNINIT (pScreen, &ClipList); } - - REGION_NULL (pScreen, &ClipList); + + REGION_INIT (pScreen, &ClipList, NullBox, 0); REGION_INTERSECT (pScreen, &ClipList, &pWin->clipList, (RegionPtr) pReg); (*pScreen->WindowExposures) (pWin, &ClipList, NullRegion); REGION_UNINIT (pScreen, &ClipList); @@ -621,25 +953,25 @@ xglxBlockHandler (pointer blockData, while (XCheckIfEvent (xdisplay, &X, xglxExposurePredicate, NULL)) { ScreenPtr pScreen = currentScreen; - + box.x1 = X.xexpose.x; box.y1 = X.xexpose.y; box.x2 = box.x1 + X.xexpose.width; box.y2 = box.y1 + X.xexpose.height; - + REGION_INIT (currentScreen, ®ion, &box, 1); WalkTree (pScreen, xglxWindowExposures, ®ion); - + REGION_UNINIT (pScreen, ®ion); } - + if (!xglSyncSurface (&pScreenPriv->pScreenPixmap->drawable)) FatalError (XGL_SW_FAILURE_STRING); - + glitz_surface_flush (pScreenPriv->surface); glitz_drawable_flush (pScreenPriv->drawable); - + XFlush (xdisplay); } @@ -681,6 +1013,7 @@ xglxWakeupHandler (pointer blockData, break; case MotionNotify: x.u.u.type = MotionNotify; + x.u.u.detail = 0; x.u.keyButtonPointer.rootX = X.xmotion.x; x.u.keyButtonPointer.rootY = X.xmotion.y; x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis (); @@ -692,6 +1025,7 @@ xglxWakeupHandler (pointer blockData, if (pScreen) { NewCurrentScreen (pScreen, X.xcrossing.x, X.xcrossing.y); x.u.u.type = MotionNotify; + x.u.u.detail = 0; x.u.keyButtonPointer.rootX = X.xcrossing.x; x.u.keyButtonPointer.rootY = X.xcrossing.y; x.u.keyButtonPointer.time = lastEventTime = @@ -699,7 +1033,7 @@ xglxWakeupHandler (pointer blockData, mieqEnqueue (&x); } } - break; + break; default: break; } @@ -715,16 +1049,48 @@ xglxBell (int volume, XBell (xdisplay, volume); } +static void +xglxKbdCtrl (DeviceIntPtr pDev, + KeybdCtrl *ctrl) +{ + unsigned long valueMask; + XKeyboardControl values; + int i; + + valueMask = KBKeyClickPercent | KBBellPercent | KBBellPitch | + KBBellDuration | KBAutoRepeatMode; + + values.key_click_percent = ctrl->click; + values.bell_percent = ctrl->bell; + values.bell_pitch = ctrl->bell_pitch; + values.bell_duration = ctrl->bell_duration; + values.auto_repeat_mode = (ctrl->autoRepeat) ? AutoRepeatModeOn : + AutoRepeatModeOff; + + XChangeKeyboardControl (xdisplay, valueMask, &values); + + valueMask = KBLed | KBLedMode; + + for (i = 1; i <= 32; i++) + { + values.led = i; + values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn : + LedModeOff; + + XChangeKeyboardControl (xdisplay, valueMask, &values); + } +} + static int xglxKeybdProc (DeviceIntPtr pDevice, int onoff) { - Bool ret; + Bool ret = FALSE; DevicePtr pDev = (DevicePtr) pDevice; if (!pDev) return BadImplementation; - + switch (onoff) { case DEVICE_INIT: { XModifierKeymap *xmodMap; @@ -734,18 +1100,44 @@ xglxKeybdProc (DeviceIntPtr pDevice, CARD8 xglxModMap[256]; XKeyboardState values; +#ifdef _XSERVER64 + KeySym64 *xkeyMap64; + int len; +#endif + +#ifdef XKB + Bool xkbExtension = FALSE; + int xkbOp, xkbEvent, xkbError, xkbMajor, xkbMinor; +#endif + if (pDev != LookupKeyboardDevice ()) - return !Success; - + return !Success; + xmodMap = XGetModifierMapping (xdisplay); + XDisplayKeycodes (xdisplay, &minKeyCode, &maxKeyCode); - xkeyMap = XGetKeyboardMapping (xdisplay, + +#ifdef _XSERVER64 + xkeyMap64 = XGetKeyboardMapping (xdisplay, + minKeyCode, + maxKeyCode - minKeyCode + 1, + &mapWidth); + + len = (maxKeyCode - minKeyCode + 1) * mapWidth; + xkeyMap = (KeySym *) xalloc (len * sizeof (KeySym)); + for (i = 0; i < len; ++i) + xkeyMap[i] = xkeyMap64[i]; + + XFree (xkeyMap64); +#else + xkeyMap = XGetKeyboardMapping (xdisplay, minKeyCode, maxKeyCode - minKeyCode + 1, &mapWidth); - +#endif + memset (xglxModMap, 0, 256); - + for (j = 0; j < 8; j++) { for (i = 0; i < xmodMap->max_keypermod; i++) @@ -757,39 +1149,124 @@ xglxKeybdProc (DeviceIntPtr pDevice, xglxModMap[keyCode] |= 1 << j; } } - + XFreeModifiermap (xmodMap); - + xglxKeySyms.minKeyCode = minKeyCode; xglxKeySyms.maxKeyCode = maxKeyCode; xglxKeySyms.mapWidth = mapWidth; xglxKeySyms.map = xkeyMap; - XGetKeyboardControl (xdisplay, &values); +#ifdef XKB + if (!noXkbExtension) + xkbExtension = XkbQueryExtension (xdisplay, + &xkbOp, &xkbEvent, &xkbError, + &xkbMajor, &xkbMinor); + + if (xkbExtension) + { + XkbDescPtr desc; + char *rules, *model, *layout, *variants, *options; + + desc = XkbGetKeyboard (xdisplay, + XkbGBN_AllComponentsMask, + XkbUseCoreKbd); + + if (desc && desc->geom) + { + XkbComponentNamesRec names; + FILE *file; + + rules = XKB_DFLT_RULES_FILE; + model = XKB_DFLT_KB_MODEL; + layout = XKB_DFLT_KB_LAYOUT; + variants = XKB_DFLT_KB_VARIANT; + options = XKB_DFLT_KB_OPTIONS; + + XkbGetControls (xdisplay, XkbAllControlsMask, desc); + + memset (&names, 0, sizeof (XkbComponentNamesRec)); + + if (XkbInitialMap) + { + if ((names.keymap = strchr (XkbInitialMap, '/')) != NULL) + names.keymap++; + else + names.keymap = XkbInitialMap; + } + + file = fopen (XKB_BASE_DIRECTORY XKB_CONFIG_FILE, "r"); + if (file) + { + XkbConfigRtrnRec config; + + if (XkbCFParse (file, XkbCFDflts, desc, &config)) + { + if (config.rules_file) + rules = config.rules_file; + if (config.model) + model = config.model; + if (config.layout) + layout = config.layout; + if (config.variant) + variants = config.variant; + if (config.options) + options = config.options; + } + fclose (file); + } + + XkbSetRulesDflts (rules, model, layout, variants, options); + + ret = XkbInitKeyboardDeviceStruct ((pointer) pDev, + &names, + &xglxKeySyms, + xglxModMap, + xglxBell, + xglxKbdCtrl); + + if (ret) + XkbDDXChangeControls ((pointer) pDev, desc->ctrls, + desc->ctrls); + + XkbFreeKeyboard (desc, 0, False); + } + } +#endif - memmove (defaultKeyboardControl.autoRepeats, - values.auto_repeats, sizeof (values.auto_repeats)); + if (!ret) + { + XGetKeyboardControl (xdisplay, &values); - ret = InitKeyboardDeviceStruct (pDev, - &xglxKeySyms, - xglxModMap, - xglxBell, - xglKbdCtrl); + memmove (defaultKeyboardControl.autoRepeats, + values.auto_repeats, sizeof (values.auto_repeats)); + + ret = InitKeyboardDeviceStruct (pDev, + &xglxKeySyms, + xglxModMap, + xglxBell, + xglxKbdCtrl); + } +#ifdef _XSERVER64 + xfree (xkeyMap); +#else XFree (xkeyMap); +#endif if (!ret) return BadImplementation; + } break; - case DEVICE_ON: + case DEVICE_ON: pDev->on = TRUE; break; - case DEVICE_OFF: + case DEVICE_OFF: case DEVICE_CLOSE: pDev->on = FALSE; break; } - + return Success; } @@ -812,16 +1289,16 @@ xglxInitInput (int argc, char **argv) { DeviceIntPtr pKeyboard, pPointer; - + pPointer = AddInputDevice (xglMouseProc, TRUE); pKeyboard = AddInputDevice (xglxKeybdProc, TRUE); - + RegisterPointerDevice (pPointer); RegisterKeyboardDevice (pKeyboard); - + miRegisterPointerDevice (screenInfo.screens[0], pPointer); mieqInit (&pKeyboard->public, &pPointer->public); - + AddEnabledDevice (XConnectionNumber (xdisplay)); RegisterBlockAndWakeupHandlers (xglxBlockHandler, @@ -837,6 +1314,9 @@ xglxUseMsg (void) ErrorF ("-fullscreen run fullscreen\n"); ErrorF ("-display string display name of the real server\n"); ErrorF ("-softcursor force software cursor\n"); + + if (!xDisplayName) + xglxUseXorgMsg (); } int @@ -844,6 +1324,46 @@ xglxProcessArgument (int argc, char **argv, int i) { + static Bool checkDisplayName = FALSE; + + if (!checkDisplayName) + { + char *display = ":0"; + int j; + + for (j = i; j < argc; j++) + { + if (!strcmp (argv[j], "-display")) + { + if (++j < argc) + xDisplayName = argv[j]; + + break; + } + else if (argv[j][0] == ':') + { + display = argv[j]; + } + } + + if (!xDisplayName) + xDisplayName = getenv ("DISPLAY"); + + if (xDisplayName) + { + int n; + + n = strspn (xDisplayName, ":0123456789"); + if (strncmp (xDisplayName, display, n) == 0) + xDisplayName = 0; + } + + if (xDisplayName) + fullscreen = FALSE; + + checkDisplayName = TRUE; + } + if (!strcmp (argv[i], "-screen")) { if ((i + 1) < argc) @@ -860,12 +1380,11 @@ xglxProcessArgument (int argc, fullscreen = TRUE; return 1; } - if (!strcmp (argv[i], "-display")) + else if (!strcmp (argv[i], "-display")) { - if (++i < argc) { - xDisplayName = argv[i]; + if (++i < argc) return 2; - } + return 0; } else if (!strcmp (argv[i], "-softcursor")) @@ -873,6 +1392,10 @@ xglxProcessArgument (int argc, softCursor = TRUE; return 1; } + else if (!xDisplayName) + { + return xglxProcessXorgArgument (argc, argv, i); + } return 0; } @@ -880,10 +1403,11 @@ xglxProcessArgument (int argc, void xglxAbort (void) { + xglxAbortXorg (); } void -xglxGiveUp () +xglxGiveUp (void) { AbortDDX (); } @@ -901,34 +1425,34 @@ static Bool xglxARGBCursorSupport (void) { int renderMajor, renderMinor; - + if (!XRenderQueryVersion (xdisplay, &renderMajor, &renderMinor)) renderMajor = renderMinor = -1; return (renderMajor > 0 || renderMinor > 4); -} +} static Cursor xglxCreateARGBCursor (ScreenPtr pScreen, CursorPtr pCursor) { Pixmap xpixmap; - GC xgc; + XlibGC xgc; XImage *ximage; XRenderPictFormat *xformat; Picture xpicture; Cursor cursor; XGLX_SCREEN_PRIV (pScreen); - - xpixmap = XCreatePixmap (xdisplay, + + xpixmap = XCreatePixmap (xdisplay, pScreenPriv->win, pCursor->bits->width, pCursor->bits->height, 32); - + xgc = XCreateGC (xdisplay, xpixmap, 0, NULL); - + ximage = XCreateImage (xdisplay, DefaultVisual (xdisplay, xscreen), 32, ZPixmap, 0, @@ -936,23 +1460,23 @@ xglxCreateARGBCursor (ScreenPtr pScreen, pCursor->bits->width, pCursor->bits->height, 32, pCursor->bits->width * 4); - + XPutImage (xdisplay, xpixmap, xgc, ximage, 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); - + XFree (ximage); XFreeGC (xdisplay, xgc); - + xformat = XRenderFindStandardFormat (xdisplay, PictStandardARGB32); xpicture = XRenderCreatePicture (xdisplay, xpixmap, xformat, 0, 0); cursor = XRenderCreateCursor (xdisplay, xpicture, pCursor->bits->xhot, pCursor->bits->yhot); - + XRenderFreePicture (xdisplay, xpicture); XFreePixmap (xdisplay, xpixmap); - + return cursor; } diff --git a/hw/xgl/glx/xglx.h b/hw/xgl/glx/xglx.h index cb2ea2af1..b0c5d3d70 100644 --- a/hw/xgl/glx/xglx.h +++ b/hw/xgl/glx/xglx.h @@ -28,6 +28,62 @@ #include "xgl.h" +#ifdef _XSERVER64 +#define _XSERVER64_tmp +#undef _XSERVER64 +typedef unsigned long XID64; +typedef unsigned long Mask64; +typedef unsigned long Atom64; +typedef unsigned long VisualID64; +typedef unsigned long Time64; +#define XID XID64 +#define Mask Mask64 +#define Atom Atom64 +#define VisualID VisualID64 +#define Time Time64 +typedef XID Window64; +typedef XID Drawable64; +typedef XID Font64; +typedef XID Pixmap64; +typedef XID Cursor64; +typedef XID Colormap64; +typedef XID GContext64; +typedef XID KeySym64; +#define Window Window64 +#define Drawable Drawable64 +#define Font Font64 +#define Pixmap Pixmap64 +#define Cursor Cursor64 +#define Colormap Colormap64 +#define GContext GContext64 +#define KeySym KeySym64 +#endif + +#define GC XlibGC +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#undef GC + +#ifdef _XSERVER64_tmp +#ifndef _XSERVER64 +#define _XSERVER64 +#endif +#undef _XSERVER64_tmp +#undef XID +#undef Mask +#undef Atom +#undef VisualID +#undef Time +#undef Window +#undef Drawable +#undef Font +#undef Pixmap +#undef Cursor +#undef Colormap +#undef GContext +#undef KeySym +#endif + void xglxInitOutput (ScreenInfo *pScreenInfo, int argc, @@ -61,4 +117,22 @@ xglxGiveUp (void); void xglxOsVendorInit (void); +#ifndef NXGLXORG + +void +xglxUseXorgMsg (void); + +int +xglxProcessXorgArgument (int argc, + char **argv, + int i); + +void +xglxAbortXorg (void); + +char * +xglxInitXorg (void); + +#endif + #endif /* _XGLX_H_ */ diff --git a/hw/xgl/glx/xglxinit.c b/hw/xgl/glx/xglxinit.c index 0376133bb..50bbca52b 100644 --- a/hw/xgl/glx/xglxinit.c +++ b/hw/xgl/glx/xglxinit.c @@ -24,19 +24,30 @@ */ #include "xglx.h" +#include "xglglx.h" xglScreenInfoRec xglScreenInfo = { - NULL, 0, 0, 0, 0, + NULL, 0, 0, 0, 0, 0, DEFAULT_GEOMETRY_DATA_TYPE, DEFAULT_GEOMETRY_USAGE, FALSE, XGL_DEFAULT_PBO_MASK, FALSE, - FALSE + { + { FALSE, FALSE, { 0, 0, 0, 0 } }, + { FALSE, FALSE, { 0, 0, 0, 0 } }, + { FALSE, FALSE, { 0, 0, 0, 0 } }, + { FALSE, FALSE, { 0, 0, 0, 0 } } + } }; #ifdef GLXEXT static Bool loadGlx = TRUE; + +#ifndef NGLXEXTLOG +static char *glxExtLogFile = 0; +#endif + #endif void @@ -50,6 +61,18 @@ InitOutput (ScreenInfo *pScreenInfo, { if (!xglLoadGLXModules ()) FatalError ("No GLX modules loaded"); + +#ifndef NGLXEXTLOG + if (glxExtLogFile) + { + __xglGLXLogFp = fopen (glxExtLogFile, "w"); + if (!__xglGLXLogFp) + perror ("InitOutput"); + } + else + __xglGLXLogFp = 0; +#endif + } #endif @@ -83,6 +106,11 @@ ddxUseMsg (void) #ifdef GLXEXT ErrorF ("-noglx don't load glx extension\n"); + +#ifndef NGLXEXTLOG + ErrorF ("-glxlog file glx extension log file\n"); +#endif + #endif xglUseMsg (); @@ -103,6 +131,15 @@ ddxProcessArgument (int argc, loadGlx = FALSE; return 1; } + +#ifndef NGLXEXTLOG + else if (!strcmp (argv[i], "-glxlog")) + { + if (++i < argc) + glxExtLogFile = argv[i]; + } +#endif + #endif skip = xglProcessArgument (argc, argv, i); @@ -130,6 +167,6 @@ OsVendorInit (void) xglxOsVendorInit (); } -void ddxInitGlobals(void) +void ddxInitGlobals() { } diff --git a/hw/xgl/glx/xglxorg.c b/hw/xgl/glx/xglxorg.c new file mode 100644 index 000000000..984c50ee2 --- /dev/null +++ b/hw/xgl/glx/xglxorg.c @@ -0,0 +1,676 @@ +/* + * Copyright © 2005 Novell, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: David Reveman <davidr@novell.com> + * Matthias Hopf <mhopf@suse.de> + */ + +#include "xglx.h" + +#ifndef NXGLXORG + +#include <X11/Xauth.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <ctype.h> +#include <signal.h> +#include <setjmp.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <libgen.h> + +typedef void (*sighandler_t) (int); + +#define XORG_DIE_TIMEOUT 3 +#define XORG_DEV_RANDOM "/dev/urandom" + +static char xorgAuthBuf[256]; +static char *xorgAuthTempl = "/tmp/.Xgl-auth-XXXXXX"; +static char *xorgAuth = NULL; + +static char *xorgProgs[] = { "/usr/bin/Xorg", "/usr/X11R6/bin/Xorg" }; +static char *xorgProg = NULL; + +static char *xorgDisplay = ":93"; +static char *xorgTerminate = "-terminate"; + +static pid_t xorgPid = 0; +static int receivedUsr1 = 0; +static jmp_buf jumpbuf; + +static Bool waitAndExit = FALSE; + +static char **xorgArgv = 0; +static int nXorgArgv = 0; + +typedef struct _xglxArg *xglxArgPtr; + +typedef int (*xglxProcessArgumentProc) (xglxArgPtr, int, char **, int); + +typedef struct _xglxArg { + xglxProcessArgumentProc processArgument; + const char *name; + const char *usage; +} xglxArgRec; + +static int +xglxAddXorgArguments (char **argv, + int n) +{ + char **newArgv; + int i; + + newArgv = xrealloc (xorgArgv, sizeof (char *) * (nXorgArgv + n)); + if (!newArgv) + return 0; + + for (i = 0; i < n; i++) + newArgv[nXorgArgv + i] = argv[i]; + + xorgArgv = newArgv; + nXorgArgv += n; + + return n; +} + +static int +xglxProcessCommonXorgArgument (xglxArgPtr pArg, + int n, + int argc, + char **argv, + int i) +{ + if (strcmp (argv[i], pArg->name) == 0) + { + if (i + n - 1 < argc) + return xglxAddXorgArguments (&argv[i], n); + } + + return 0; +} + +#define PROCESS_COMMON_XORG_ARGUMENT_IMP(args) \ + static int \ + xglxProcess ## args ## CommonXorgArgument (xglxArgPtr pArg, \ + int argc, \ + char **argv, \ + int i) \ + { \ + return xglxProcessCommonXorgArgument (pArg, args, argc, argv, i); \ + } + +PROCESS_COMMON_XORG_ARGUMENT_IMP (1) +PROCESS_COMMON_XORG_ARGUMENT_IMP (2) + +static int +xglxProcessXorgVTArgument (xglxArgPtr pArg, + int argc, + char **argv, + int i) +{ + if (argv[i][0] == 'v' && argv[i][1] == 't' && + strspn (&argv[i][2], "0123456789") == strlen (&argv[i][2])) + return xglxAddXorgArguments (&argv[i], 1); + + return 0; +} + +static int +xglxProcessXorgAcArgument (xglxArgPtr pArg, + int argc, + char **argv, + int i) +{ + static char *ac = "-ac"; + + if (strcmp (argv[i], pArg->name) == 0) + { + if (xglxAddXorgArguments (&ac, 1)) + return 1; + } + + return 0; +} + +static int +xglxProcessXorgVersionArgument (xglxArgPtr pArg, + int argc, + char **argv, + int i) +{ + static char *version = "-version"; + + if (strcmp (argv[i], pArg->name) == 0) + { + if (xglxAddXorgArguments (&version, 1)) + { + waitAndExit = TRUE; + return 1; + } + } + + return 0; +} + +static int +xglxProcessXorgProgArgument (xglxArgPtr pArg, + int argc, + char **argv, + int i) +{ + if (strcmp (argv[i], pArg->name) == 0) + { + if (i + 1 < argc) + { + xorgProg = argv[i + 1]; + return 2; + } + } + + return 0; +} + +static int +xglxProcessXorgDisplayArgument (xglxArgPtr pArg, + int argc, + char **argv, + int i) +{ + if (strcmp (argv[i], pArg->name) == 0) + { + if (i + 1 < argc) + { + xorgDisplay = argv[i + 1]; + return 2; + } + } + + return 0; +} + +static int +xglxProcessXorgWaitExitArgument (xglxArgPtr pArg, + int argc, + char **argv, + int i) +{ + if (xglxProcessCommonXorgArgument (pArg, 1, argc, argv, i)) + { + waitAndExit = TRUE; + return 1; + } + + return 0; +} + +#define ARG(processArgument, name, usage) \ + { processArgument, name, usage } + +#define XORG_ARG(name, args) \ + ARG (xglxProcess ## args ## CommonXorgArgument, name, 0) + +#define XORG_UARG(name, usage, args) \ + ARG (xglxProcess ## args ## CommonXorgArgument, name, usage) + +xglxArgRec xorgUid0Args[] = { + XORG_UARG ("-modulepath", " paths specify the module search path", 2), + XORG_UARG ("-logfile", " file specify a log file name", 2), + ARG (xglxProcessXorgWaitExitArgument, "-configure", + " probe for devices and write an Xorg config") +}; + +xglxArgRec xorgUidArgs[] = { + XORG_UARG ("-config", + " file specify configuration file, relative to the\n" + " Xorg config search path, " + "only root can use absolute", 2) +}; + +xglxArgRec xorgArgs[] = { + ARG (xglxProcessXorgWaitExitArgument, "-probeonly", + " probe for devices, then exit"), + ARG (xglxProcessXorgWaitExitArgument, "-scanpci", + " execute the scanpci module and exit"), + XORG_UARG ("-verbose", " [n] verbose startup messages", 2), + XORG_UARG ("-logverbose", " [n] verbose log messages", 2), + XORG_UARG ("-quiet", " minimal startup messages", 1), + XORG_UARG ("-depth", " n set colour depth. Default: 8", 2), + XORG_UARG ("-gamma", + " f set gamma value (0.1 < f < 10.0) " + "Default: 1.0", 2), + XORG_UARG ("-rgamma", " f set gamma value for red phase", 2), + XORG_UARG ("-ggamma", " f set gamma value for green phase", + 2), + XORG_UARG ("-bgamma", " f set gamma value for blue phase", 2), + XORG_UARG ("-layout", + " name specify the ServerLayout section name", 2), + XORG_UARG ("-screen", + " name specify the Screen section name", 2), + XORG_UARG ("-keyboard", + " name specify the core keyboard InputDevice name", 2), + XORG_UARG ("-pointer", + " name specify the core pointer InputDevice name", 2), + XORG_UARG ("-nosilk", " disable Silken Mouse", 1), + XORG_UARG ("-disableModInDev", + " disable dynamic modification of input device settings", + 1), + XORG_UARG ("-allowMouseOpenFail", + " start server even if the mouse can't be initialized", 1), + XORG_UARG ("-bestRefresh", + " choose modes with the best refresh rate", 1), + XORG_UARG ("-ignoreABI", + " make module ABI mismatches non-fatal", 1), + XORG_UARG ("-isolateDevice", + " bus_id restrict device resets to bus_id (PCI only)", 2), + ARG (xglxProcessXorgVTArgument, "vtXX", + " use the specified VT number"), + XORG_UARG ("-keeptty", + " don't detach controlling tty " + "(for debugging only)", 1), + XORG_UARG ("-novtswitch", " don't immediately switch to new VT", + 1), + XORG_UARG ("-sharevts", " share VTs with another X server", + 1), + ARG (xglxProcessXorgAcArgument, "-xorgAc", + " disable access control restrictions"), + ARG (xglxProcessXorgProgArgument, "-xorgProgram", + " server program"), + ARG (xglxProcessXorgDisplayArgument, "-xorgDisplay", + " server display"), + ARG (xglxProcessXorgVersionArgument, "-xorgVersion", + " show the server version") +}; + +xglxArgRec sharedArgs[] = { + XORG_ARG ("-br", 1) +}; + +void +xglxUseXorgMsg (void) +{ + int i; + + ErrorF ("\nXorg usage:\n"); + + if (getuid () == 0) + { + for (i = 0; i < sizeof (xorgUid0Args) / sizeof (xglxArgRec); i++) + ErrorF ("%s%s\n", xorgUid0Args[i].name, xorgUid0Args[i].usage); + } + else + { + for (i = 0; i < sizeof (xorgUidArgs) / sizeof (xglxArgRec); i++) + ErrorF ("%s%s\n", xorgUidArgs[i].name, xorgUidArgs[i].usage); + } + + for (i = 0; i < sizeof (xorgArgs) / sizeof (xglxArgRec); i++) + ErrorF ("%s%s\n", xorgArgs[i].name, xorgArgs[i].usage); +} + +int +xglxProcessXorgArgument (int argc, + char **argv, + int i) +{ + int skip, j; + + if (nXorgArgv == 0) + { + if (!xglxAddXorgArguments (&xorgProg, 1)) + return 0; + } + + if (getuid () == 0) + { + for (j = 0; j < sizeof (xorgUid0Args) / sizeof (xglxArgRec); j++) + { + skip = (*xorgUid0Args[j].processArgument) (&xorgUid0Args[j], + argc, argv, i); + if (skip) + return skip; + } + } + else + { + for (j = 0; j < sizeof (xorgUidArgs) / sizeof (xglxArgRec); j++) + { + skip = (*xorgUidArgs[j].processArgument) (&xorgUidArgs[j], + argc, argv, i); + if (skip) + return skip; + } + } + + for (j = 0; j < sizeof (xorgArgs) / sizeof (xorgArgs[0]); j++) + { + skip = (*xorgArgs[j].processArgument) (&xorgArgs[j], argc, argv, i); + if (skip) + return skip; + } + + for (j = 0; j < sizeof (sharedArgs) / sizeof (sharedArgs[0]); j++) + { + skip = (*sharedArgs[j].processArgument) (&sharedArgs[j], argc, argv, i); + if (skip) + return 0; + } + + return 0; +} + +static void +sigAlarm (int sig) +{ + ErrorF ("%s won't die, killing it\n", basename (xorgProg)); + + kill (xorgPid, SIGKILL); + if (xorgPid) + while (waitpid (xorgPid, NULL, 0) == -1 && errno == EINTR); +} + +void +xglxAbortXorg (void) +{ + sighandler_t oldSigAlarm; + unsigned int oldAlarm; + int status = 0; + char *name; + + if (!xorgPid) + return; + + name = basename (xorgProg); + + oldAlarm = alarm (0); + oldSigAlarm = signal (SIGALRM, sigAlarm); + + kill (xorgPid, SIGTERM); + + alarm (XORG_DIE_TIMEOUT); + while (waitpid (xorgPid, &status, 0) == -1 && errno == EINTR); + alarm (0); + + signal (SIGALRM, oldSigAlarm); + alarm (oldAlarm); + + if (WIFEXITED (status)) + { + if (WEXITSTATUS (status)) + ErrorF ("%s died, exit status %d\n", name, WEXITSTATUS (status)); + } + else if (WIFSIGNALED (status)) + ErrorF ("%s died, signal %d\n", name, WTERMSIG (status)); + else + ErrorF ("%s died, dubious exit\n", name); + + if (xorgAuth) + unlink (xorgAuth); +} + +static void +sigUsr1Waiting (int sig) +{ + signal (sig, sigUsr1Waiting); + receivedUsr1++; +} + +static void +sigUsr1Jump (int sig) +{ + +#ifdef HAVE_SIGPROCMASK + sigset_t set; +#endif + + signal (sig, sigUsr1Waiting); + +#ifdef HAVE_SIGPROCMASK + sigemptyset (&set); + sigaddset (&set, SIGUSR1); + sigprocmask (SIG_UNBLOCK, &set, NULL); +#endif + + longjmp (jumpbuf, 1); +} + +#define AUTH_DATA_LEN 16 /* bytes of authorization data */ + +static Bool +xglxSetupAuth (char *name, int authFd) +{ + Xauth auth; + int randomFd; + ssize_t bytes, size; + char authHost[256]; + char authData[AUTH_DATA_LEN]; + FILE *file; + + auth.family = FamilyLocal; + + gethostname (authHost, sizeof (authHost)); + + auth.address = authHost; + auth.address_length = strlen (authHost); + + auth.number = strrchr (xorgDisplay, ':'); + if (!auth.number) + { + ErrorF ("Bad Xorg display name: %s\n", xorgDisplay); + return FALSE; + } + + auth.number++; + + auth.number_length = strlen (auth.number); + if (!auth.number_length) + { + ErrorF ("Bad Xorg display name: %s\n", xorgDisplay); + return FALSE; + } + + auth.name = "MIT-MAGIC-COOKIE-1"; + auth.name_length = strlen (auth.name); + + randomFd = open (XORG_DEV_RANDOM, O_RDONLY); + if (randomFd == -1) + { + ErrorF ("Failed to open " XORG_DEV_RANDOM "\n"); + return FALSE; + } + + bytes = 0; + do { + size = read (randomFd, authData + bytes, AUTH_DATA_LEN - bytes); + if (size <= 0) + break; + + bytes += size; + } while (bytes != AUTH_DATA_LEN); + + close (randomFd); + + if (bytes != AUTH_DATA_LEN) + { + ErrorF ("Failed to read %d random bytes from " XORG_DEV_RANDOM "\n", + AUTH_DATA_LEN); + return FALSE; + } + + auth.data = authData; + auth.data_length = AUTH_DATA_LEN; + + file = fdopen (authFd, "w"); + if (!file) + { + ErrorF ("Failed to open authorization file: %s\n", name); + close (authFd); + return FALSE; + } + + XauWriteAuth (file, &auth); + fclose (file); + + return TRUE; +} + +char * +xglxInitXorg (void) +{ + sighandler_t oldSigUsr1; + pid_t pid; + char *name; + char *auth[] = { "-auth", xorgAuthBuf, "-nolisten", "tcp" }; + char *saver[] = { "-dpms", "-v", "-s", "0" }; + char *endArg = NULL; + int authFd; + int mask; + + if (xorgPid) + return xorgDisplay; + + if (!xorgProg) + { + struct stat buf; + int i; + + for (i = 0; i < sizeof (xorgProgs) / sizeof (char *); i++) + { + if (stat (xorgProgs[i], &buf) == 0) + { + xorgProg = xorgProgs[i]; + break; + } + } + + if (!xorgProg) + FatalError ("Can't find Xorg executable\n"); + } + + strcpy (xorgAuthBuf, xorgAuthTempl); + mask = umask (0077); + authFd = mkstemp (xorgAuthBuf); + umask (mask); + if (authFd == -1) + FatalError ("Failed to generate unique authorization file\n"); + + xorgAuth = xorgAuthBuf; + + if (nXorgArgv == 0) + { + if (!xglxAddXorgArguments (&xorgProg, 1)) + return 0; + } + else + { + xorgArgv[0] = xorgProg; + } + + if (!xglxAddXorgArguments (auth, sizeof (auth) / sizeof (char *))) + return 0; + + if (!xglxAddXorgArguments (saver, sizeof (saver) / sizeof (char *))) + return 0; + + if (!xglxAddXorgArguments (&xorgDisplay, 1)) + return 0; + + if (!xglxAddXorgArguments (&xorgTerminate, 1)) + return 0; + + if (!xglxAddXorgArguments (&endArg, 1)) + return 0; + + name = basename (xorgProg); + + if (!xglxSetupAuth (xorgAuth, authFd)) + FatalError ("Failed to set up authorization: %s\n", xorgAuth); + + oldSigUsr1 = signal (SIGUSR1, sigUsr1Waiting); + + pid = fork (); + + switch (pid) { + case -1: + perror ("fork"); + FatalError ("fork"); + break; + case 0: + signal (SIGUSR1, SIG_IGN); + execv (xorgArgv[0], xorgArgv); + perror (xorgArgv[0]); + exit (2); + break; + default: + xorgPid = pid; + break; + } + + for (;;) + { + int status; + + signal (SIGUSR1, sigUsr1Waiting); + if (setjmp (jumpbuf) && !waitAndExit) + break; + + signal (SIGUSR1, sigUsr1Jump); + if (receivedUsr1 && !waitAndExit) + break; + + if (waitpid (xorgPid, &status, 0) != -1) + { + if (WIFEXITED (status)) + { + if (waitAndExit) + { + if (WEXITSTATUS (status)) + FatalError ("%s died, exit status %d\n", name, + WEXITSTATUS (status)); + + exit (WEXITSTATUS (status)); + } + else + { + FatalError ("%s died, exit status %d\n", name, + WEXITSTATUS (status)); + } + } + else if (WIFSIGNALED (status)) + FatalError ("%s died, signal %d\n", name, WTERMSIG (status)); + else + FatalError ("%s died, dubious exit\n", name); + } + } + + signal (SIGUSR1, oldSigUsr1); + + setenv ("XAUTHORITY", xorgAuth, 1); + + return xorgDisplay; +} + +#endif |