diff options
Diffstat (limited to 'src/glx/mini')
-rw-r--r-- | src/glx/mini/Makefile | 84 | ||||
-rw-r--r-- | src/glx/mini/NOTES | 115 | ||||
-rw-r--r-- | src/glx/mini/dispatch.c | 64 | ||||
-rw-r--r-- | src/glx/mini/driver.h | 168 | ||||
-rw-r--r-- | src/glx/mini/example.miniglx.conf | 36 | ||||
-rw-r--r-- | src/glx/mini/miniglx.c | 2579 | ||||
-rw-r--r-- | src/glx/mini/miniglxP.h | 205 | ||||
-rw-r--r-- | src/glx/mini/miniglx_events.c | 984 |
8 files changed, 0 insertions, 4235 deletions
diff --git a/src/glx/mini/Makefile b/src/glx/mini/Makefile deleted file mode 100644 index 71f085d5cd9..00000000000 --- a/src/glx/mini/Makefile +++ /dev/null @@ -1,84 +0,0 @@ -# Build the MiniGLX libGL.so library. - -TOP = ../../.. -include $(TOP)/configs/current - - -DEFINES += -DGLX_DIRECT_RENDERING -DIN_MINI_GLX -UIN_DRI_DRIVER - -C_SOURCES = \ - $(TOP)/src/mesa/main/dispatch.c \ - $(TOP)/src/mesa/glapi/glapi.c \ - $(TOP)/src/mesa/glapi/glthread.c \ - $(TOP)/src/glx/x11/glcontextmodes.c \ - miniglx.c \ - miniglx_events.c - -X86_SOURCES = $(TOP)/src/mesa/x86/glapi_x86.S - -OBJECTS = $(C_SOURCES:.c=.o) \ - $(ASM_SOURCES:.S=.o) - -INCLUDES = -I. $(INCLUDE_DIRS) - -INCLUDE_DIRS = \ - -I$(TOP)/include \ - -I$(TOP)/src/mesa \ - -I$(TOP)/src/mesa/main \ - -I$(TOP)/src/mesa/glapi \ - -I$(TOP)/src/glx/x11 \ - -I$(TOP)/src/mesa/drivers/dri/common \ - $(LIBDRM_CFLAGS) \ - $(PCIACCESS_CFLAGS) - - - -##### RULES ##### - -.c.o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ - -.S.o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ - - -##### TARGETS ##### - -default: depend $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/miniglx.conf - - -# Make libGL -$(TOP)/$(LIB_DIR)/$(GL_LIB_NAME): $(OBJECTS) Makefile - @ $(TOP)/bin/mklib -o $(GL_LIB) -linker '$(CC)' \ - -major 1 -minor 2 $(MKLIB_OPTIONS) \ - -install $(TOP)/$(LIB_DIR) $(GL_LIB_DEPS) $(OBJECTS) \ - $(LIBDRM_LIB) $(PCIACCESS_LIB) - - -# install sample miniglx.conf -$(TOP)/$(LIB_DIR)/miniglx.conf: - $(INSTALL) example.miniglx.conf $(TOP)/$(LIB_DIR)/miniglx.conf - - -drmtest: xf86drm.o drmtest.o - rm -f drmtest && $(CC) -o drmtest xf86drm.o drmtest.o - - -depend: $(C_SOURCES) $(ASM_SOURCES) - touch depend - $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \ - > /dev/null - - -# Emacs tags -tags: - etags `find . -name \*.[ch]` `find ../include` - - -# Remove .o and backup files -clean: - -rm -f drmtest $(TOP)/$(LIB_DIR)/libGL.so* - -rm -f *.o *~ - -rm -f depend - -include depend diff --git a/src/glx/mini/NOTES b/src/glx/mini/NOTES deleted file mode 100644 index 1774107d634..00000000000 --- a/src/glx/mini/NOTES +++ /dev/null @@ -1,115 +0,0 @@ - - -Getting MiniGLX up and running ------------------------------- - -It's necessary to do a bit of work to set up an environment to run miniglx. - -For the radeon driver, it's necessary to get the right set of kernel -modules installed before attempting to run any programs: - - rmmod radeon agpgart; - insmod agpgart; - insmod $(MESA)/src/kernel/radeonfb/radeonfb.o; - insmod $(MESA)/src/kernel/radeon/radeon.o; - -For all drivers, its necessary to reach the compiled libraries, and -tell MiniGLX where to find it's configuration file: - - export LD_LIBRARY_PATH=$(MESA)/lib; - export MINIGLX_CONF=$(MESA)/lib/miniglx.conf - ------------------------------------------------------------- - -MiniGLX Example Programs ------------------------- - -The following programs will work with miniglx: - - $(MESA)/tests/miniglx - $(MESA)/xdemos/glxgears - -Thanks to the miniglut stub library, most of the mesa glut demos will -work. In particular, the following have been tested. (Note there is -no keyboard or mouse interaction with these demos). - - $(MESA)/demos/gears - $(MESA)/demos/geartrain - $(MESA)/demos/morph3d - $(MESA)/demos/isosurf - $(MESA)/demos/texobj - $(MESA)/demos/texcyl - $(MESA)/demos/gloss - $(MESA)/demos/fire - $(MESA)/demos/tunnel - $(MESA)/demos/teapot - $(MESA)/samples/prim - $(MESA)/samples/olympic - $(MESA)/samples/star - $(MESA)/samples/wave - ...etc - -In fact most of the glut demos seem to work within the constraints of -having no keyboard/mouse interactivity. Furthermore, the use of the -glut wrapper means that these programs don't require recompilation to -run under MiniGLX -- the same binary works with both regular GLX and -MiniGLX. - - ------------------------------------------------------------- - -Porting GLX apps to MiniGLX ---------------------------- - -A quick list of issues encountered in porting existing GLX apps to -MiniGLX. Listed in no particular order. - -1) No input events - -MiniGLX doesn't provide an input layer, so any X11 input event -handling in the existing app will have to be redone for whatever -input devices exist on the target. - -2) No configuration, expose events - -Many GLX and Xlib programs wait on an event to ensure the window has -become visible after being mapped. MiniGLX provides no equivalent -facility. - -3) Different headers - -X11/Xlib.h, GL/GLX.h, etc must not be used if the program is being -compiled against MiniGLX. - -The equivalent header is GL/MiniGLX.h. - -4) Different library - -It may be necessary to link directly against the minGLX libGL.so. - -5) Reduced number of Xlib and GLX entrypoints. - -By definition (MiniGLX is a subset of GLX), many Xlib and GLX -entrypoints, structures and macros are not present in MiniGLX. It -will be necessary to find and eliminate all references to -non-supported entrypoints. - - ---------------------------------------------------------------- - -Bugs in radeonfb.o -- the radeon framebuffer driver. ----------------------------------------------------- - -Several bugs have been found in the radeonfb.o framebuffer driver. -Most of these are resolved in the version included in the MiniGLX -sources, but some remain: - -1) Occasionally, after entering graphics mode, colors appear 'shifted' -or 'translated', particularly in higher resolution modes. This is -definitely a bug in radeonfb.o as this can be provoked even when using -the software dri driver (fb_dri.so). Importance: High. Workaround: -Use 800x600 as it seems to be less frequent at this resolution, -otherwise, restart the application. - - - diff --git a/src/glx/mini/dispatch.c b/src/glx/mini/dispatch.c deleted file mode 100644 index ac24df9e7d4..00000000000 --- a/src/glx/mini/dispatch.c +++ /dev/null @@ -1,64 +0,0 @@ -/** - * \file miniglx/dispatch.c - * - * \brief C-based dispatch of the OpenGL entry points (glAccum(), glBegin(), - * etc). - * - * \author Brian Paul <[email protected]> - * - * \note This code IS NOT USED if we're compiling on an x86 system and using - * the glapi_x86.S assembly code. - */ - -/* - * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "glheader.h" -#include "glapi.h" -#include "glapitable.h" - - -#if !(defined(USE_X86_ASM) || defined(USE_SPARC_ASM)) - -#define KEYWORD1 - -#define KEYWORD2 - -#define NAME(func) gl##func - -#define DISPATCH(func, args, msg) \ - const struct _glapi_table *dispatch; \ - dispatch = _glapi_Dispatch ? _glapi_Dispatch : _glapi_get_dispatch();\ - (dispatch->func) args - -#define RETURN_DISPATCH(func, args, msg) \ - const struct _glapi_table *dispatch; \ - dispatch = _glapi_Dispatch ? _glapi_Dispatch : _glapi_get_dispatch();\ - return (dispatch->func) args - - -#include "glapitemp.h" - -#endif /* USE_X86_ASM */ diff --git a/src/glx/mini/driver.h b/src/glx/mini/driver.h deleted file mode 100644 index 39c0f9b5fa6..00000000000 --- a/src/glx/mini/driver.h +++ /dev/null @@ -1,168 +0,0 @@ -/** - * \file driver.h - * \brief DRI utility functions definitions. - * - * This module acts as glue between GLX and the actual hardware driver. A DRI - * driver doesn't really \e have to use any of this - it's optional. But, some - * useful stuff is done here that otherwise would have to be duplicated in most - * drivers. - * - * Basically, these utility functions take care of some of the dirty details of - * screen initialization, context creation, context binding, DRM setup, etc. - * - * These functions are compiled into each DRI driver so libGL.so knows nothing - * about them. - * - * Look for more comments in the dri_util.c file. - * - * \author Kevin E. Martin <[email protected]> - * \author Brian Paul <[email protected]> - */ - -/* - * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _driver_H_ -#define _driver_H_ - -#include "GL/gl.h" -#include "GL/internal/glcore.h" - -#include "drm.h" -#include "drm_sarea.h" - -/** - * \brief DRIDriverContext type. - */ -typedef struct DRIDriverContextRec { - const char *pciBusID; - int pciBus; - int pciDevice; - int pciFunc; - int chipset; - int bpp; - int cpp; - int agpmode; - int isPCI; - - int colorTiling; /**< \brief color tiling is enabled */ - - unsigned long FBStart; /**< \brief physical address of the framebuffer */ - unsigned long MMIOStart; /**< \brief physical address of the MMIO region */ - - int FBSize; /**< \brief size of the mmap'd framebuffer in bytes */ - int MMIOSize; /**< \brief size of the mmap'd MMIO region in bytes */ - - void *FBAddress; /**< \brief start of the mmap'd framebuffer */ - void *MMIOAddress; /**< \brief start of the mmap'd MMIO region */ - - /** - * \brief Client configuration details - * - * These are computed on the server and sent to clients as part of - * the initial handshaking. - */ - struct { - drm_handle_t hSAREA; - int SAREASize; - drm_handle_t hFrameBuffer; - int fbOrigin; - int fbSize; - int fbStride; - int virtualWidth; - int virtualHeight; - int Width; - } shared; - - /** - * \name From DRIInfoRec - */ - /*@{*/ - int drmFD; /**< \brief DRM device file descriptor */ - drm_sarea_t *pSAREA; - unsigned int serverContext; /**< \brief DRM context only active on server */ - /*@}*/ - - - /** - * \name Driver private - * - * Populated by __driInitFBDev() - */ - /*@{*/ - void *driverPrivate; - void *driverClientMsg; - int driverClientMsgSize; - /*@}*/ -} DRIDriverContext; - -/** - * \brief Interface to the DRI driver. - * - * This structure is retrieved from the loadable driver by the \e - * __driDriver symbol to access the Mini GLX specific hardware - * initialization and take down routines. - */ -typedef struct DRIDriverRec { - /** - * \brief Validate the framebuffer device mode - */ - int (*validateMode)( const DRIDriverContext *context ); - - /** - * \brief Examine mode returned by fbdev (may differ from the one - * requested), restore any hw regs clobbered by fbdev. - */ - int (*postValidateMode)( const DRIDriverContext *context ); - - /** - * \brief Initialize the framebuffer device. - */ - int (*initFBDev)( DRIDriverContext *context ); - - /** - * \brief Halt the framebuffer device. - */ - void (*haltFBDev)( DRIDriverContext *context ); - - - /** - * \brief Idle and shutdown hardware in preparation for a VT switch. - */ - int (*shutdownHardware)( const DRIDriverContext *context ); - - /** - * \brief Restore hardware state after regaining the VT. - */ - int (*restoreHardware)( const DRIDriverContext *context ); - - /** - * \brief Notify hardware driver of gain/loose focus. May be zero - * as this is of limited utility for most drivers. - */ - void (*notifyFocus)( int have_focus ); -} DRIDriver; - -#endif /* _driver_H_ */ diff --git a/src/glx/mini/example.miniglx.conf b/src/glx/mini/example.miniglx.conf deleted file mode 100644 index 62dd4f65ec4..00000000000 --- a/src/glx/mini/example.miniglx.conf +++ /dev/null @@ -1,36 +0,0 @@ -# Example miniglx configuration file (/etc/miniglx.conf) -# - -# Framebuffer device to open: Might need to change this on dual-head -# systems. -fbdevDevice=/dev/fb0 - -# Which driver? -# radeon_dri.so -- HW accelerated radeon driver -# fb_dri.so -- Software rasterizer -clientDriverName=radeon_dri.so - -# The pci bus id of the video card. Find this with scanpci, lspci or -# look in /proc/pci. -pciBusID=PCI:1:0:0 - -# Is the card PCI or AGP ? -isPCI=0 - -# Virtual screen dimensions. Can reduce this to save videocard memory -# at the expense of maximum window size available. -virtualWidth=1280 -virtualHeight=1024 - -# Screen depth. Only 16 & 32bpp supported. -bpp=32 - -# AGP Mode. Not all cards supported (1, 2 or 4) -agpmode=1 - -# Rotated monitor? -- NOTE: only works with subsetted radeon driver! -rotateMode=0 - -# Do we want to use color tiling ? -colorTiling=0 - diff --git a/src/glx/mini/miniglx.c b/src/glx/mini/miniglx.c deleted file mode 100644 index 71a0658eae3..00000000000 --- a/src/glx/mini/miniglx.c +++ /dev/null @@ -1,2579 +0,0 @@ -/** - * \file miniglx.c - * \brief Mini GLX interface functions. - * \author Brian Paul - * - * The Mini GLX interface is a subset of the GLX interface, plus a - * minimal set of Xlib functions. - */ - -/* - * Mesa 3-D graphics library - * Version: 6.0.1 - * - * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -/** - * \mainpage Mini GLX - * - * \section miniglxIntro Introduction - * - * The Mini GLX interface facilitates OpenGL rendering on embedded devices. The - * interface is a subset of the GLX interface, plus a minimal set of Xlib-like - * functions. - * - * Programs written to the Mini GLX specification should run unchanged - * on systems with the X Window System and the GLX extension (after - * recompilation). The intention is to allow flexibility for - * prototyping and testing. - * - * The files in the src/miniglx/ directory are compiled to build the - * libGL.so library. This is the library which applications link with. - * libGL.so in turn, loads the hardware-specific device driver. - * - * - * \section miniglxDoxygen About Doxygen - * - * For a list of all files, select <b>File List</b>. Choose a file from - * the list for a list of all functions in the file. - * - * For a list of all functions, types, constants, etc. - * select <b>File Members</b>. - * - * - * \section miniglxReferences References - * - * - <A HREF="file:../../docs/MiniGLX.html">Mini GLX Specification</A>, - * Tungsten Graphics, Inc. - * - OpenGL Graphics with the X Window System, Silicon Graphics, Inc., - * ftp://ftp.sgi.com/opengl/doc/opengl1.2/glx1.3.ps - * - Xlib - C Language X Interface, X Consortium Standard, X Version 11, - * Release 6.4, ftp://ftp.x.org/pub/R6.4/xc/doc/hardcopy/X11/xlib.PS.gz - * - XFree86 Man pages, The XFree86 Project, Inc., - * http://www.xfree86.org/current/manindex3.html - * - */ - -/** - * \page datatypes Notes on the XVisualInfo, Visual, and __GLXvisualConfig data types - * - * -# X (unfortunately) has two (or three) data types which - * describe visuals. Ideally, there would just be one. - * -# We need the #__GLXvisualConfig type to augment #XVisualInfo and #Visual - * because we need to describe the GLX-specific attributes of visuals. - * -# In this interface there is a one-to-one-to-one correspondence between - * the three types and they're all interconnected. - * -# The #XVisualInfo type has a pointer to a #Visual. The #Visual structure - * (aka MiniGLXVisualRec) has a pointer to the #__GLXvisualConfig. The - * #Visual structure also has a pointer pointing back to the #XVisualInfo. - * -# The #XVisualInfo structure is the only one who's contents are public. - * -# The glXChooseVisual() and XGetVisualInfo() are the only functions that - * return #XVisualInfo structures. They can be freed with XFree(), though - * there is a small memory leak. - */ - - -#include <assert.h> -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <dlfcn.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/time.h> /* for gettimeofday */ -#include <linux/kd.h> -#include <linux/vt.h> - -#include "miniglxP.h" -#include "dri_util.h" - -#include "imports.h" -#include "glcontextmodes.h" -#include "glapi.h" - -#include "pciaccess.h" - -static GLboolean __glXCreateContextWithConfig(__DRInativeDisplay *dpy, - int screen, int fbconfigID, void *contextID, - drm_context_t *hHWContext); - -static GLboolean __glXGetDrawableInfo(__DRInativeDisplay *dpy, int scrn, - __DRIid draw, unsigned int * index, unsigned int * stamp, - int * x, int * y, int * width, int * height, - int * numClipRects, drm_clip_rect_t ** pClipRects, - int * backX, int * backY, - int * numBackClipRects, drm_clip_rect_t ** pBackClipRects); - -static __DRIscreen * __glXFindDRIScreen(__DRInativeDisplay *dpy, int scrn); - -static GLboolean __glXWindowExists(__DRInativeDisplay *dpy, __DRIid draw); - -static int __glXGetUST( int64_t * ust ); - -static GLboolean __glXGetMscRate(__DRInativeDisplay * dpy, __DRIid drawable, - int32_t * numerator, int32_t * denominator); - -static GLboolean xf86DRI_DestroyContext(__DRInativeDisplay *dpy, int screen, - __DRIid context_id ); - -static GLboolean xf86DRI_CreateDrawable(__DRInativeDisplay *dpy, int screen, - __DRIid drawable, drm_drawable_t *hHWDrawable ); - -static GLboolean xf86DRI_DestroyDrawable(__DRInativeDisplay *dpy, int screen, - __DRIid drawable); - - -/** Wrapper around either malloc() */ -void * -_mesa_malloc(size_t bytes) -{ - return malloc(bytes); -} - -/** Wrapper around either calloc() */ -void * -_mesa_calloc(size_t bytes) -{ - return calloc(1, bytes); -} - -/** Wrapper around either free() */ -void -_mesa_free(void *ptr) -{ - free(ptr); -} - - -/** - * \brief Current GLX context. - * - * \sa glXGetCurrentContext(). - */ -static GLXContext CurrentContext = NULL; - - - -static Display *SignalDisplay = 0; - -static void SwitchVT(int sig) -{ - fprintf(stderr, "SwitchVT %d dpy %p\n", sig, SignalDisplay); - - if (SignalDisplay) { - SignalDisplay->vtSignalFlag = 1; - switch( sig ) - { - case SIGUSR1: /* vt has been released */ - SignalDisplay->haveVT = 0; - break; - case SIGUSR2: /* vt has been acquired */ - SignalDisplay->haveVT = 1; - break; - } - } -} - -/**********************************************************************/ -/** \name Framebuffer device functions */ -/**********************************************************************/ -/*@{*/ - -/** - * \brief Do the first part of setting up the framebuffer device. - * - * \param dpy the display handle. - * \param use_vt use a VT for display or not - * - * \return GL_TRUE on success, or GL_FALSE on failure. - * - * \sa This is called during XOpenDisplay(). - * - * \internal - * Gets the VT number, opens the respective console TTY device. Saves its state - * to restore when exiting and goes into graphics mode. - * - * Opens the framebuffer device and make a copy of the original variable screen - * information and gets the fixed screen information. Maps the framebuffer and - * MMIO region into the process address space. - */ -static GLboolean -OpenFBDev( Display *dpy, int use_vt ) -{ - char ttystr[1000]; - int fd, vtnumber, ttyfd; - - assert(dpy); - - if (geteuid()) { - fprintf(stderr, "error: you need to be root\n"); - return GL_FALSE; - } - - if (use_vt) { - - /* open /dev/tty0 and get the VT number */ - if ((fd = open("/dev/tty0", O_WRONLY, 0)) < 0) { - fprintf(stderr, "error opening /dev/tty0\n"); - return GL_FALSE; - } - if (ioctl(fd, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) { - fprintf(stderr, "error: couldn't get a free vt\n"); - return GL_FALSE; - } - - fprintf(stderr, "*** got vt nr: %d\n", vtnumber); - close(fd); - - /* open the console tty */ - sprintf(ttystr, "/dev/tty%d", vtnumber); /* /dev/tty1-64 */ - dpy->ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0); - if (dpy->ConsoleFD < 0) { - fprintf(stderr, "error couldn't open console fd\n"); - return GL_FALSE; - } - - /* save current vt number */ - { - struct vt_stat vts; - if (ioctl(dpy->ConsoleFD, VT_GETSTATE, &vts) == 0) - dpy->OriginalVT = vts.v_active; - } - - /* disconnect from controlling tty */ - ttyfd = open("/dev/tty", O_RDWR); - if (ttyfd >= 0) { - ioctl(ttyfd, TIOCNOTTY, 0); - close(ttyfd); - } - - /* some magic to restore the vt when we exit */ - { - struct vt_mode vt; - struct sigaction sig_tty; - - /* Set-up tty signal handler to catch the signal we request below */ - SignalDisplay = dpy; - memset( &sig_tty, 0, sizeof( sig_tty ) ); - sig_tty.sa_handler = SwitchVT; - sigemptyset( &sig_tty.sa_mask ); - if( sigaction( SIGUSR1, &sig_tty, &dpy->OrigSigUsr1 ) || - sigaction( SIGUSR2, &sig_tty, &dpy->OrigSigUsr2 ) ) - { - fprintf(stderr, "error: can't set up signal handler (%s)", - strerror(errno) ); - return GL_FALSE; - } - - - - vt.mode = VT_PROCESS; - vt.waitv = 0; - vt.relsig = SIGUSR1; - vt.acqsig = SIGUSR2; - if (ioctl(dpy->ConsoleFD, VT_SETMODE, &vt) < 0) { - fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n", - strerror(errno)); - return GL_FALSE; - } - - - if (ioctl(dpy->ConsoleFD, VT_ACTIVATE, vtnumber) != 0) - printf("ioctl VT_ACTIVATE: %s\n", strerror(errno)); - if (ioctl(dpy->ConsoleFD, VT_WAITACTIVE, vtnumber) != 0) - printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno)); - - if (ioctl(dpy->ConsoleFD, VT_GETMODE, &vt) < 0) { - fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno)); - return GL_FALSE; - } - - - - } - - /* go into graphics mode */ - if (ioctl(dpy->ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) { - fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n", - strerror(errno)); - return GL_FALSE; - } - } - - /* open the framebuffer device */ - dpy->FrameBufferFD = open(dpy->fbdevDevice, O_RDWR); - if (dpy->FrameBufferFD < 0) { - fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno)); - return GL_FALSE; - } - - /* get the original variable screen info */ - if (ioctl(dpy->FrameBufferFD, FBIOGET_VSCREENINFO, &dpy->OrigVarInfo)) { - fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n", - strerror(errno)); - return GL_FALSE; - } - - /* make copy */ - dpy->VarInfo = dpy->OrigVarInfo; /* structure copy */ - - /* Turn off hw accels (otherwise mmap of mmio region will be - * refused) - */ - dpy->VarInfo.accel_flags = 0; - if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->VarInfo)) { - fprintf(stderr, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n", - strerror(errno)); - return GL_FALSE; - } - - - - /* Get the fixed screen info */ - if (ioctl(dpy->FrameBufferFD, FBIOGET_FSCREENINFO, &dpy->FixedInfo)) { - fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n", - strerror(errno)); - return GL_FALSE; - } - - - - /* mmap the framebuffer into our address space */ - dpy->driverContext.FBStart = dpy->FixedInfo.smem_start; - dpy->driverContext.FBSize = dpy->FixedInfo.smem_len; - dpy->driverContext.shared.fbSize = dpy->FixedInfo.smem_len; - dpy->driverContext.FBAddress = (caddr_t) mmap(0, /* start */ - dpy->driverContext.shared.fbSize, /* bytes */ - PROT_READ | PROT_WRITE, /* prot */ - MAP_SHARED, /* flags */ - dpy->FrameBufferFD, /* fd */ - 0 /* offset */); - if (dpy->driverContext.FBAddress == (caddr_t) - 1) { - fprintf(stderr, "error: unable to mmap framebuffer: %s\n", - strerror(errno)); - return GL_FALSE; - } - - /* mmap the MMIO region into our address space */ - dpy->driverContext.MMIOStart = dpy->FixedInfo.mmio_start; - dpy->driverContext.MMIOSize = dpy->FixedInfo.mmio_len; - dpy->driverContext.MMIOAddress = (caddr_t) mmap(0, /* start */ - dpy->driverContext.MMIOSize, /* bytes */ - PROT_READ | PROT_WRITE, /* prot */ - MAP_SHARED, /* flags */ - dpy->FrameBufferFD, /* fd */ - dpy->FixedInfo.smem_len /* offset */); - if (dpy->driverContext.MMIOAddress == (caddr_t) - 1) { - fprintf(stderr, "error: unable to mmap mmio region: %s\n", - strerror(errno)); - return GL_FALSE; - } - - fprintf(stderr, "got MMIOAddress %p offset %d\n", - dpy->driverContext.MMIOAddress, - dpy->FixedInfo.smem_len); - - return GL_TRUE; -} - - - - -/** - * \brief Setup up the desired framebuffer device mode. - * - * \param dpy the display handle. - * - * \return GL_TRUE on success, or GL_FALSE on failure. - * - * \sa This is called during __miniglx_StartServer(). - * - * \internal - * - * Bumps the size of the window the the next supported mode. Sets the - * variable screen information according to the desired mode and asks - * the driver to validate the mode. Certifies that a DirectColor or - * TrueColor visual is used from the updated fixed screen information. - * In the case of DirectColor visuals, sets up an 'identity' colormap to - * mimic a TrueColor visual. - * - * Calls the driver hooks 'ValidateMode' and 'PostValidateMode' to - * allow the driver to make modifications to the chosen mode according - * to hardware constraints, or to save and restore videocard registers - * that may be clobbered by the fbdev driver. - * - * \todo Timings are hard-coded in the source for a set of supported modes. - */ -static GLboolean -SetupFBDev( Display *dpy ) -{ - int width, height; - - assert(dpy); - - width = dpy->driverContext.shared.virtualWidth; - height = dpy->driverContext.shared.virtualHeight; - - if (width==832) - width=800; -#if 0 - /* Bump size up to next supported mode. - */ - if (width <= 720 && height <= 480) { - width = 720; height = 480; - } - else if (width <= 960 && height <= 540) { - width = 960; height = 540; - } - else if (width <= 800 && height <= 600) { - width = 800; height = 600; - } - else if (width <= 1024 && height <= 768) { - width = 1024; height = 768; - } - else if (width <= 768 && height <= 1024) { - width = 768; height = 1024; - } - else if (width <= 1280 && height <= 1024) { - width = 1280; height = 1024; - } -#endif - - dpy->driverContext.shared.fbStride = width * (dpy->driverContext.bpp / 8); - - /* set the depth, resolution, etc */ - dpy->VarInfo = dpy->OrigVarInfo; - dpy->VarInfo.bits_per_pixel = dpy->driverContext.bpp; - dpy->VarInfo.xres_virtual = dpy->driverContext.shared.virtualWidth; - dpy->VarInfo.yres_virtual = dpy->driverContext.shared.virtualHeight; - dpy->VarInfo.xres = dpy->driverContext.shared.Width; - dpy->VarInfo.yres = height; - dpy->VarInfo.xoffset = 0; - dpy->VarInfo.yoffset = 0; - dpy->VarInfo.nonstd = 0; - dpy->VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */ - - if (dpy->VarInfo.bits_per_pixel == 32) { - dpy->VarInfo.red.offset = 16; - dpy->VarInfo.green.offset = 8; - dpy->VarInfo.blue.offset = 0; - dpy->VarInfo.transp.offset = 24; - dpy->VarInfo.red.length = 8; - dpy->VarInfo.green.length = 8; - dpy->VarInfo.blue.length = 8; - dpy->VarInfo.transp.length = 8; - } - else if (dpy->VarInfo.bits_per_pixel == 16) { - dpy->VarInfo.red.offset = 11; - dpy->VarInfo.green.offset = 5; - dpy->VarInfo.blue.offset = 0; - dpy->VarInfo.red.length = 5; - dpy->VarInfo.green.length = 6; - dpy->VarInfo.blue.length = 5; - dpy->VarInfo.transp.offset = 0; - dpy->VarInfo.transp.length = 0; - } - else { - fprintf(stderr, "Only 32bpp and 16bpp modes supported at the moment\n"); - return 0; - } - - if (!dpy->driver->validateMode( &dpy->driverContext )) { - fprintf(stderr, "Driver validateMode() failed\n"); - return 0; - } - - /* These should be calculated with the gtf.c program, and then we could - remove all this... AlanH. */ - if (dpy->VarInfo.xres == 1280 && - dpy->VarInfo.yres == 1024) { - /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */ - dpy->VarInfo.pixclock = 7408; - dpy->VarInfo.left_margin = 248; - dpy->VarInfo.right_margin = 16; - dpy->VarInfo.upper_margin = 38; - dpy->VarInfo.lower_margin = 1; - dpy->VarInfo.hsync_len = 144; - dpy->VarInfo.vsync_len = 3; - } - else if (dpy->VarInfo.xres == 1024 && - dpy->VarInfo.yres == 768) { - /* timing values taken from /etc/fb.modes (1024x768 @ 75Hz) */ - dpy->VarInfo.pixclock = 12699; - dpy->VarInfo.left_margin = 176; - dpy->VarInfo.right_margin = 16; - dpy->VarInfo.upper_margin = 28; - dpy->VarInfo.lower_margin = 1; - dpy->VarInfo.hsync_len = 96; - dpy->VarInfo.vsync_len = 3; - } - else if (dpy->VarInfo.xres == 800 && - dpy->VarInfo.yres == 600) { - /* timing values taken from /etc/fb.modes (800x600 @ 75Hz) */ - dpy->VarInfo.pixclock = 27778; - dpy->VarInfo.left_margin = 128; - dpy->VarInfo.right_margin = 24; - dpy->VarInfo.upper_margin = 22; - dpy->VarInfo.lower_margin = 1; - dpy->VarInfo.hsync_len = 72; - dpy->VarInfo.vsync_len = 2; - } - else if (dpy->VarInfo.xres == 720 && - dpy->VarInfo.yres == 480) { - dpy->VarInfo.pixclock = 37202; - dpy->VarInfo.left_margin = 88; - dpy->VarInfo.right_margin = 16; - dpy->VarInfo.upper_margin = 14; - dpy->VarInfo.lower_margin = 1; - dpy->VarInfo.hsync_len = 72; - dpy->VarInfo.vsync_len = 3; - } - else if (dpy->VarInfo.xres == 960 && - dpy->VarInfo.yres == 540) { - dpy->VarInfo.pixclock = 24273; - dpy->VarInfo.left_margin = 128; - dpy->VarInfo.right_margin = 32; - dpy->VarInfo.upper_margin = 16; - dpy->VarInfo.lower_margin = 1; - dpy->VarInfo.hsync_len = 96; - dpy->VarInfo.vsync_len = 3; - } - else if (dpy->VarInfo.xres == 768 && - dpy->VarInfo.yres == 1024) { - /* timing values for 768x1024 @ 75Hz */ - dpy->VarInfo.pixclock = 11993; - dpy->VarInfo.left_margin = 136; - dpy->VarInfo.right_margin = 32; - dpy->VarInfo.upper_margin = 41; - dpy->VarInfo.lower_margin = 1; - dpy->VarInfo.hsync_len = 80; - dpy->VarInfo.vsync_len = 3; - } - else { - /* XXX need timings for other screen sizes */ - fprintf(stderr, "XXXX screen size %d x %d not supported at this time!\n", - dpy->VarInfo.xres, dpy->VarInfo.yres); - return GL_FALSE; - } - - fprintf(stderr, "[miniglx] Setting mode: visible %dx%d virtual %dx%dx%d\n", - dpy->VarInfo.xres, dpy->VarInfo.yres, - dpy->VarInfo.xres_virtual, dpy->VarInfo.yres_virtual, - dpy->VarInfo.bits_per_pixel); - - /* set variable screen info */ - if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->VarInfo)) { - fprintf(stderr, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n", - strerror(errno)); - return GL_FALSE; - } - - /* get the variable screen info, in case it has been modified */ - if (ioctl(dpy->FrameBufferFD, FBIOGET_VSCREENINFO, &dpy->VarInfo)) { - fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n", - strerror(errno)); - return GL_FALSE; - } - - - fprintf(stderr, "[miniglx] Readback mode: visible %dx%d virtual %dx%dx%d\n", - dpy->VarInfo.xres, dpy->VarInfo.yres, - dpy->VarInfo.xres_virtual, dpy->VarInfo.yres_virtual, - dpy->VarInfo.bits_per_pixel); - - /* Get the fixed screen info */ - if (ioctl(dpy->FrameBufferFD, FBIOGET_FSCREENINFO, &dpy->FixedInfo)) { - fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n", - strerror(errno)); - return GL_FALSE; - } - - if (dpy->FixedInfo.visual != FB_VISUAL_TRUECOLOR && - dpy->FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) { - fprintf(stderr, "non-TRUECOLOR visuals not supported.\n"); - return GL_FALSE; - } - - if (dpy->FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) { - struct fb_cmap cmap; - unsigned short red[256], green[256], blue[256]; - int rcols = 1 << dpy->VarInfo.red.length; - int gcols = 1 << dpy->VarInfo.green.length; - int bcols = 1 << dpy->VarInfo.blue.length; - int i; - - cmap.start = 0; - cmap.len = gcols; - cmap.red = red; - cmap.green = green; - cmap.blue = blue; - cmap.transp = NULL; - - for (i = 0; i < rcols ; i++) - red[i] = (65536/(rcols-1)) * i; - - for (i = 0; i < gcols ; i++) - green[i] = (65536/(gcols-1)) * i; - - for (i = 0; i < bcols ; i++) - blue[i] = (65536/(bcols-1)) * i; - - if (ioctl(dpy->FrameBufferFD, FBIOPUTCMAP, (void *) &cmap) < 0) { - fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i); - exit(1); - } - } - - /* May need to restore regs fbdev has clobbered: - */ - if (!dpy->driver->postValidateMode( &dpy->driverContext )) { - fprintf(stderr, "Driver postValidateMode() failed\n"); - return 0; - } - - return GL_TRUE; -} - - -/** - * \brief Restore the framebuffer device to state it was in before we started - * - * Undoes the work done by SetupFBDev(). - * - * \param dpy the display handle. - * - * \return GL_TRUE on success, or GL_FALSE on failure. - * - * \sa Called from XDestroyWindow(). - * - * \internal - * Restores the original variable screen info. - */ -static GLboolean -RestoreFBDev( Display *dpy ) -{ - /* restore original variable screen info */ - if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->OrigVarInfo)) { - fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n", - strerror(errno)); - return GL_FALSE; - } - dpy->VarInfo = dpy->OrigVarInfo; - - return GL_TRUE; -} - - -/** - * \brief Close the framebuffer device. - * - * \param dpy the display handle. - * - * \sa Called from XCloseDisplay(). - * - * \internal - * Unmaps the framebuffer and MMIO region. Restores the text mode and the - * original virtual terminal. Closes the console and framebuffer devices. - */ -static void -CloseFBDev( Display *dpy ) -{ - struct vt_mode VT; - - munmap(dpy->driverContext.FBAddress, dpy->driverContext.FBSize); - munmap(dpy->driverContext.MMIOAddress, dpy->driverContext.MMIOSize); - - if (dpy->ConsoleFD) { - /* restore text mode */ - ioctl(dpy->ConsoleFD, KDSETMODE, KD_TEXT); - - /* set vt */ - if (ioctl(dpy->ConsoleFD, VT_GETMODE, &VT) != -1) { - VT.mode = VT_AUTO; - ioctl(dpy->ConsoleFD, VT_SETMODE, &VT); - } - - /* restore original vt */ - if (dpy->OriginalVT >= 0) { - ioctl(dpy->ConsoleFD, VT_ACTIVATE, dpy->OriginalVT); - dpy->OriginalVT = -1; - } - - close(dpy->ConsoleFD); - } - close(dpy->FrameBufferFD); -} - -/*@}*/ - - -/**********************************************************************/ -/** \name Misc functions needed for DRI drivers */ -/**********************************************************************/ -/*@{*/ - -/** - * \brief Find the DRI screen dependent methods associated with the display. - * - * \param dpy a display handle, as returned by XOpenDisplay(). - * \param scrn the screen number. Not referenced. - * - * \returns a pointer to a __DRIscreenRec structure. - * - * \internal - * Returns the MiniGLXDisplayRec::driScreen attribute. - */ -static __DRIscreen * -__glXFindDRIScreen(__DRInativeDisplay *dpy, int scrn) -{ - (void) scrn; - return &((Display*)dpy)->driScreen; -} - -/** - * \brief Validate a drawable. - * - * \param dpy a display handle, as returned by XOpenDisplay(). - * \param draw drawable to validate. - * - * \internal - * Since Mini GLX only supports one window, compares the specified drawable with - * the MiniGLXDisplayRec::TheWindow attribute. - */ -static GLboolean -__glXWindowExists(__DRInativeDisplay *dpy, __DRIid draw) -{ - const Display * const display = (Display*)dpy; - if (display->TheWindow == (Window) draw) - return True; - else - return False; -} - -/** - * \brief Get current thread ID. - * - * \return thread ID. - * - * \internal - * Always returns 0. - */ -/*unsigned long -_glthread_GetID(void) -{ - return 0; -}*/ - -/*@}*/ - - -/** - * \brief Scan Linux /prog/bus/pci/devices file to determine hardware - * chipset based on supplied bus ID. - * - * \return probed chipset (non-zero) on success, zero otherwise. - * - * \internal - */ -static int get_chipset_from_busid( Display *dpy ) -{ - char buf[0x200]; - FILE *file; - const char *fname = "/proc/bus/pci/devices"; - int retval = 0; - - if (!(file = fopen(fname,"r"))) { - fprintf(stderr, "couldn't open %s: %s\n", fname, strerror(errno)); - return 0; - } - - while (fgets(buf, sizeof(buf)-1, file)) { - unsigned int nr, bus, dev, fn, vendor, device, encode; - nr = sscanf(buf, "%04x\t%04x%04x", &encode, - &vendor, &device); - - bus = encode >> 8; - dev = (encode & 0xFF) >> 3; - fn = encode & 0x7; - - if (nr != 3) - break; - - if (bus == dpy->driverContext.pciBus && - dev == dpy->driverContext.pciDevice && - fn == dpy->driverContext.pciFunc) { - retval = device; - break; - } - } - - fclose(file); - - if (retval) - fprintf(stderr, "[miniglx] probed chipset 0x%x\n", retval); - else - fprintf(stderr, "[miniglx] failed to probe chipset\n"); - - return retval; -} - - -/** - * \brief Read settings from a configuration file. - * - * The configuration file is usually "/etc/miniglx.conf", but can be overridden - * with the MINIGLX_CONF environment variable. - * - * The format consists in \code option = value \endcode lines. The option names - * corresponds to the fields in MiniGLXDisplayRec. - * - * \param dpy the display handle as. - * - * \return non-zero on success, zero otherwise. - * - * \internal - * Sets some defaults. Opens and parses the the Mini GLX configuration file and - * fills in the MiniGLXDisplayRec field that corresponds for each option. - */ -static int __read_config_file( Display *dpy ) -{ - FILE *file; - const char *fname; - - /* Fallback/defaults - */ - dpy->fbdevDevice = "/dev/fb0"; - dpy->clientDriverName = "fb_dri.so"; - dpy->driverContext.pciBus = 0; - dpy->driverContext.pciDevice = 0; - dpy->driverContext.pciFunc = 0; - dpy->driverContext.chipset = 0; - dpy->driverContext.pciBusID = 0; - dpy->driverContext.shared.virtualWidth = 1280; - dpy->driverContext.shared.virtualHeight = 1024; - dpy->driverContext.bpp = 32; - dpy->driverContext.cpp = 4; - dpy->rotateMode = 0; - dpy->driverContext.agpmode = 1; - dpy->driverContext.isPCI = 0; - dpy->driverContext.colorTiling = 0; - - fname = getenv("MINIGLX_CONF"); - if (!fname) fname = "/etc/miniglx.conf"; - - file = fopen(fname, "r"); - if (!file) { - fprintf(stderr, "couldn't open config file %s: %s\n", fname, strerror(errno)); - return 0; - } - - - while (!feof(file)) { - char buf[81], *opt = buf, *val, *tmp1, *tmp2; - fgets(buf, sizeof(buf), file); - - /* Parse 'opt = val' -- must be easier ways to do this. - */ - while (isspace(*opt)) opt++; - val = opt; - if (*val == '#') continue; /* comment */ - while (!isspace(*val) && *val != '=' && *val) val++; - tmp1 = val; - while (isspace(*val)) val++; - if (*val != '=') continue; - *tmp1 = 0; - val++; - while (isspace(*val)) val++; - tmp2 = val; - while (!isspace(*tmp2) && *tmp2 != '\n' && *tmp2) tmp2++; - *tmp2 = 0; - - - if (strcmp(opt, "fbdevDevice") == 0) - dpy->fbdevDevice = strdup(val); - else if (strcmp(opt, "clientDriverName") == 0) - dpy->clientDriverName = strdup(val); - else if (strcmp(opt, "rotateMode") == 0) - dpy->rotateMode = atoi(val) ? 1 : 0; - else if (strcmp(opt, "pciBusID") == 0) { - if (sscanf(val, "PCI:%d:%d:%d", - &dpy->driverContext.pciBus, - &dpy->driverContext.pciDevice, - &dpy->driverContext.pciFunc) != 3) { - fprintf(stderr, "malformed bus id: %s\n", val); - continue; - } - dpy->driverContext.pciBusID = strdup(val); - } - else if (strcmp(opt, "chipset") == 0) { - if (sscanf(val, "0x%x", &dpy->driverContext.chipset) != 1) - fprintf(stderr, "malformed chipset: %s\n", opt); - } - else if (strcmp(opt, "virtualWidth") == 0) { - if (sscanf(val, "%d", &dpy->driverContext.shared.virtualWidth) != 1) - fprintf(stderr, "malformed virtualWidth: %s\n", opt); - } - else if (strcmp(opt, "virtualHeight") == 0) { - if (sscanf(val, "%d", &dpy->driverContext.shared.virtualHeight) != 1) - fprintf(stderr, "malformed virutalHeight: %s\n", opt); - } - else if (strcmp(opt, "bpp") == 0) { - if (sscanf(val, "%d", &dpy->driverContext.bpp) != 1) - fprintf(stderr, "malformed bpp: %s\n", opt); - dpy->driverContext.cpp = dpy->driverContext.bpp / 8; - } - else if (strcmp(opt, "agpmode") == 0) { - if (sscanf(val, "%d", &dpy->driverContext.agpmode) != 1) - fprintf(stderr, "malformed agpmode: %s\n", opt); - } - else if (strcmp(opt, "isPCI") == 0) { - dpy->driverContext.isPCI = atoi(val) ? 1 : 0; - } - else if (strcmp(opt, "colorTiling") == 0) { - dpy->driverContext.colorTiling = atoi(val) ? 1 : 0; - } - } - - fclose(file); - - if (dpy->driverContext.chipset == 0 && dpy->driverContext.pciBusID != 0) - dpy->driverContext.chipset = get_chipset_from_busid( dpy ); - - return 1; -} - -/** - * Versioned name of the expected \c __driCreateNewScreen function. - * - * The version of the last incompatible loader/driver inteface change is - * appended to the name of the \c __driCreateNewScreen function. This - * prevents loaders from trying to load drivers that are too old. - * - * \todo - * Create a macro or something so that this is automatically updated. - */ -static const char createNewScreenName[] = "__driCreateNewScreen_20050727"; - - -static int InitDriver( Display *dpy ) -{ - /* - * Begin DRI setup. - * We're kind of combining the per-display and per-screen information - * which was kept separate in XFree86/DRI's libGL. - */ - dpy->dlHandle = dlopen(dpy->clientDriverName, RTLD_NOW | RTLD_GLOBAL); - if (!dpy->dlHandle) { - fprintf(stderr, "Unable to open %s: %s\n", dpy->clientDriverName, - dlerror()); - goto failed; - } - - /* Pull in Mini GLX specific hooks: - */ - dpy->driver = (struct DRIDriverRec *) dlsym(dpy->dlHandle, - "__driDriver"); - if (!dpy->driver) { - fprintf(stderr, "Couldn't find __driDriver in %s\n", - dpy->clientDriverName); - goto failed; - } - - /* Pull in standard DRI client-side driver hooks: - */ - dpy->createNewScreen = (PFNCREATENEWSCREENFUNC) - dlsym(dpy->dlHandle, createNewScreenName); - if (!dpy->createNewScreen) { - fprintf(stderr, "Couldn't find %s in %s\n", createNewScreenName, - dpy->clientDriverName); - goto failed; - } - - return GL_TRUE; - -failed: - if (dpy->dlHandle) { - dlclose(dpy->dlHandle); - dpy->dlHandle = 0; - } - return GL_FALSE; -} - - -/**********************************************************************/ -/** \name Public API functions (Xlib and GLX) */ -/**********************************************************************/ -/*@{*/ - - -/** - * \brief Initialize the graphics system. - * - * \param display_name currently ignored. It is recommended to pass it as NULL. - * \return a pointer to a #Display if the function is able to initialize - * the graphics system, NULL otherwise. - * - * Allocates a MiniGLXDisplayRec structure and fills in with information from a - * configuration file. - * - * Calls OpenFBDev() to open the framebuffer device and calls - * DRIDriverRec::initFBDev to do the client-side initialization on it. - * - * Loads the DRI driver and pulls in Mini GLX specific hooks into a - * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook. - * Asks the driver for a list of supported visuals. Performs the per-screen - * client-side initialization. Also setups the callbacks in the screen private - * information. - * - * Does the framebuffer device setup. Calls __miniglx_open_connections() to - * serve clients. - */ -Display * -__miniglx_StartServer( const char *display_name ) -{ - Display *dpy; - int use_vt = 0; - - pci_system_init(); - - dpy = (Display *)calloc(1, sizeof(Display)); - if (!dpy) - return NULL; - - dpy->IsClient = False; - - if (!__read_config_file( dpy )) { - fprintf(stderr, "Couldn't get configuration details\n"); - free(dpy); - return NULL; - } - - /* Open the fbdev device - */ - if (!OpenFBDev(dpy, use_vt)) { - fprintf(stderr, "OpenFBDev failed\n"); - free(dpy); - return NULL; - } - - if (!InitDriver(dpy)) { - fprintf(stderr, "InitDriver failed\n"); - free(dpy); - return NULL; - } - - /* Perform the initialization normally done in the X server - */ - if (!dpy->driver->initFBDev( &dpy->driverContext )) { - fprintf(stderr, "%s: __driInitFBDev failed\n", __FUNCTION__); - dlclose(dpy->dlHandle); - return GL_FALSE; - } - - /* do fbdev setup - */ - if (!SetupFBDev(dpy)) { - fprintf(stderr, "SetupFBDev failed\n"); - free(dpy); - return NULL; - } - - /* unlock here if not using VT -- JDS */ - if (!use_vt) { - if (dpy->driver->restoreHardware) - dpy->driver->restoreHardware( &dpy->driverContext ); - DRM_UNLOCK( dpy->driverContext.drmFD, - dpy->driverContext.pSAREA, - dpy->driverContext.serverContext ); - dpy->hwActive = 1; - } - - /* Ready for clients: - */ - if (!__miniglx_open_connections(dpy)) { - free(dpy); - return NULL; - } - - return dpy; -} - - -/** - * Implement \c __DRIinterfaceMethods::getProcAddress. - */ -static __DRIfuncPtr get_proc_address( const char * proc_name ) -{ - (void) proc_name; - return NULL; -} - - -/** - * Table of functions exported by the loader to the driver. - */ -static const __DRIinterfaceMethods interface_methods = { - get_proc_address, - - _gl_context_modes_create, - _gl_context_modes_destroy, - - __glXFindDRIScreen, - __glXWindowExists, - - __glXCreateContextWithConfig, - xf86DRI_DestroyContext, - - xf86DRI_CreateDrawable, - xf86DRI_DestroyDrawable, - __glXGetDrawableInfo, - - __glXGetUST, - __glXGetMscRate, -}; - - -static void * -CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc) -{ - void *psp = NULL; - drm_handle_t hSAREA; - drmAddress pSAREA; - const char *BusID; - int i; - __DRIversion ddx_version; - __DRIversion dri_version; - __DRIversion drm_version; - __DRIframebuffer framebuffer; - int fd = -1; - int status; - const char * err_msg; - const char * err_extra; - drmVersionPtr version; - drm_handle_t hFB; - drm_magic_t magic; - - - hSAREA = dpy->driverContext.shared.hSAREA; - BusID = dpy->driverContext.pciBusID; - - fd = drmOpen(NULL, BusID); - - err_msg = "open DRM"; - err_extra = strerror( -fd ); - - if (fd < 0) goto done; - - err_msg = "drmGetMagic"; - err_extra = NULL; - - if (drmGetMagic(fd, &magic)) goto done; - - dpy->authorized = False; - send_char_msg( dpy, 0, _Authorize ); - send_msg( dpy, 0, &magic, sizeof(magic)); - - /* force net buffer flush */ - while (!dpy->authorized) - handle_fd_events( dpy, 0 ); - - version = drmGetVersion(fd); - if (version) { - drm_version.major = version->version_major; - drm_version.minor = version->version_minor; - drm_version.patch = version->version_patchlevel; - drmFreeVersion(version); - } - else { - drm_version.major = -1; - drm_version.minor = -1; - drm_version.patch = -1; - } - - /* - * Get device name (like "tdfx") and the ddx version numbers. - * We'll check the version in each DRI driver's "createScreen" - * function. - */ - ddx_version.major = -1; - ddx_version.minor = 0; - ddx_version.patch = 0; - - /* - * Get the DRI X extension version. - */ - dri_version.major = 4; - dri_version.minor = 0; - dri_version.patch = 0; - - /* - * Get device-specific info. pDevPriv will point to a struct - * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) - * that has information about the screen size, depth, pitch, - * ancilliary buffers, DRM mmap handles, etc. - */ - hFB = dpy->driverContext.shared.hFrameBuffer; - framebuffer.size = dpy->driverContext.shared.fbSize; - framebuffer.stride = dpy->driverContext.shared.fbStride; - framebuffer.dev_priv_size = dpy->driverContext.driverClientMsgSize; - framebuffer.dev_priv = dpy->driverContext.driverClientMsg; - framebuffer.width = dpy->driverContext.shared.virtualWidth; - framebuffer.height = dpy->driverContext.shared.virtualHeight; - - /* - * Map the framebuffer region. - */ - status = drmMap(fd, hFB, framebuffer.size, - (drmAddressPtr)&framebuffer.base); - - err_msg = "drmMap of framebuffer"; - err_extra = strerror( -status ); - - if ( status != 0 ) goto done; - - /* - * Map the SAREA region. Further mmap regions may be setup in - * each DRI driver's "createScreen" function. - */ - status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA); - - err_msg = "drmMap of sarea"; - err_extra = strerror( -status ); - - if ( status == 0 ) { - err_msg = "InitDriver"; - err_extra = NULL; - psp = dpy->createNewScreen(dpy, scrn, psc, NULL, - & ddx_version, - & dri_version, - & drm_version, - & framebuffer, - pSAREA, - fd, - 20050727, - & interface_methods, - (__GLcontextModes **) &dpy->driver_modes); - - /* fill in dummy visual ids */ - { - __GLcontextModes *temp; - temp = (__GLcontextModes *)dpy->driver_modes; - i = 1; - while (temp) - { - temp->visualID = i++; - temp=temp->next; - } - } - } - -done: - if ( psp == NULL ) { - if ( pSAREA != MAP_FAILED ) { - (void)drmUnmap(pSAREA, SAREA_MAX); - } - - if ( framebuffer.base != MAP_FAILED ) { - (void)drmUnmap((drmAddress)framebuffer.base, framebuffer.size); - } - - if ( framebuffer.dev_priv != NULL ) { - free(framebuffer.dev_priv); - } - - if ( fd >= 0 ) { - (void)drmClose(fd); - } - - if ( err_extra != NULL ) { - fprintf(stderr, "libGL error: %s failed (%s)\n", err_msg, - err_extra); - } - else { - fprintf(stderr, "libGL error: %s failed\n", err_msg ); - } - - fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n"); - } - - return psp; -} - -/** - * \brief Initialize the graphics system. - * - * \param display_name currently ignored. It is recommended to pass it as NULL. - * \return a pointer to a #Display if the function is able to initialize - * the graphics system, NULL otherwise. - * - * Allocates a MiniGLXDisplayRec structure and fills in with information from a - * configuration file. - * - * Calls __miniglx_open_connections() to connect to the server. - * - * Loads the DRI driver and pulls in Mini GLX specific hooks into a - * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook. - * Asks the driver for a list of supported visuals. Performs the per-screen - * client-side initialization. Also setups the callbacks in the screen private - * information. - * - * \todo - * - read config file - * - what about virtualWidth, etc? - * - determine dpy->driverClientMsgSize, - * - allocate dpy->driverClientMsg - */ -Display * -XOpenDisplay( const char *display_name ) -{ - Display *dpy; - - dpy = (Display *)calloc(1, sizeof(Display)); - if (!dpy) - return NULL; - - dpy->IsClient = True; - - /* read config file - */ - if (!__read_config_file( dpy )) { - fprintf(stderr, "Couldn't get configuration details\n"); - free(dpy); - return NULL; - } - - /* Connect to the server and receive driverClientMsg - */ - if (!__miniglx_open_connections(dpy)) { - free(dpy); - return NULL; - } - - /* dlopen the driver .so file - */ - if (!InitDriver(dpy)) { - fprintf(stderr, "InitDriver failed\n"); - free(dpy); - return NULL; - } - - /* Perform the client-side initialization. - * - * Clearly there is a limit of one on the number of windows in - * existence at any time. - * - * Need to shut down DRM and free DRI data in XDestroyWindow(), too. - */ - dpy->driScreen.private = CallCreateNewScreen(dpy, 0, &dpy->driScreen); - if (!dpy->driScreen.private) { - fprintf(stderr, "%s: __driCreateScreen failed\n", __FUNCTION__); - dlclose(dpy->dlHandle); - free(dpy); - return NULL; - } - - /* Anything more to do? - */ - return dpy; -} - - -/** - * \brief Release display resources. - * - * When the application is about to exit, the resources associated with the - * graphics system can be released by calling this function. - * - * \param dpy display handle. It becomes invalid at this point. - * - * Destroys the window if any, and destroys the per-screen - * driver private information. - * Calls __miniglx_close_connections(). - * - * If a server, puts the the framebuffer back into the initial state. - * - * Finally frees the display structure. - */ -void -XCloseDisplay( Display *dpy ) -{ - glXMakeCurrent( dpy, NULL, NULL); - - if (dpy->NumWindows) - XDestroyWindow( dpy, dpy->TheWindow ); - - /* As this is done in XOpenDisplay, need to undo it here: - */ - dpy->driScreen.destroyScreen(dpy, 0, dpy->driScreen.private); - - __miniglx_close_connections( dpy ); - - if (!dpy->IsClient) { - /* put framebuffer back to initial state - */ - (*dpy->driver->haltFBDev)( &dpy->driverContext ); - RestoreFBDev(dpy); - CloseFBDev(dpy); - } - - dlclose(dpy->dlHandle); - free(dpy); -} - - -/** - * \brief Window creation. - * - * \param display a display handle, as returned by XOpenDisplay(). - * \param parent the parent window for the new window. For Mini GLX this should - * be - * \code RootWindow(display, 0) \endcode - * \param x the window abscissa. For Mini GLX, it should be zero. - * \param y the window ordinate. For Mini GLX, it should be zero. - * \param width the window width. For Mini GLX, this specifies the desired - * screen width such as 1024 or 1280. - * \param height the window height. For Mini GLX, this specifies the desired - * screen height such as 768 or 1024. - * \param border_width the border width. For Mini GLX, it should be zero. - * \param depth the window pixel depth. For Mini GLX, this should be the depth - * found in the #XVisualInfo object returned by glXChooseVisual() - * \param winclass the window class. For Mini GLX this value should be - * #InputOutput. - * \param visual the visual type. It should be the visual field of the - * #XVisualInfo object returned by glXChooseVisual(). - * \param valuemask which fields of the XSetWindowAttributes() are to be used. - * For Mini GLX this is typically the bitmask - * \code CWBackPixel | CWBorderPixel | CWColormap \endcode - * \param attributes initial window attributes. The - * XSetWindowAttributes::background_pixel, XSetWindowAttributes::border_pixel - * and XSetWindowAttributes::colormap fields should be set. - * - * \return a window handle if it succeeds or zero if it fails. - * - * \note For Mini GLX, windows are full-screen; they cover the entire frame - * buffer. Also, Mini GLX imposes a limit of one window. A second window - * cannot be created until the first one is destroyed. - * - * This function creates and initializes a ::MiniGLXWindowRec structure after - * ensuring that there is no other window created. Performs the per-drawable - * client-side initialization calling the __DRIscreenRec::createDrawable - * method. - * - */ -Window -XCreateWindow( Display *dpy, Window parent, int x, int y, - unsigned int width, unsigned int height, - unsigned int border_width, int depth, unsigned int winclass, - Visual *visual, unsigned long valuemask, - XSetWindowAttributes *attributes ) -{ - const int empty_attribute_list[1] = { None }; - - Window win; - - /* ignored */ - (void) x; - (void) y; - (void) border_width; - (void) depth; - (void) winclass; - (void) valuemask; - (void) attributes; - - if (!dpy->IsClient) { - fprintf(stderr, "Server process may not create windows (currently)\n"); - return NULL; - } - - if (dpy->NumWindows > 0) - return NULL; /* only allow one window */ - - assert(dpy->TheWindow == NULL); - - win = malloc(sizeof(struct MiniGLXWindowRec)); - if (!win) - return NULL; - - /* In rotated mode, translate incoming x,y,width,height into - * 'normal' coordinates. - */ - if (dpy->rotateMode) { - int tmp; - tmp = width; width = height; height = tmp; - tmp = x; x = y; y = tmp; - } - - /* init other per-window fields */ - win->x = x; - win->y = y; - win->w = width; - win->h = height; - win->visual = visual; /* ptr assignment */ - - win->bytesPerPixel = dpy->driverContext.cpp; - win->rowStride = dpy->driverContext.shared.virtualWidth * win->bytesPerPixel; - win->size = win->rowStride * height; - win->frontStart = dpy->driverContext.FBAddress + (win->rowStride * win->x) + (win->y * win->bytesPerPixel); - win->frontBottom = (GLubyte *) win->frontStart + (height-1) * win->rowStride; - - /* This is incorrect: the hardware driver could put the backbuffer - * just about anywhere. These fields, including the above are - * hardware dependent & don't really belong here. - */ - if (visual->mode->doubleBufferMode) { - win->backStart = (GLubyte *) win->frontStart + - win->rowStride * dpy->driverContext.shared.virtualHeight; - win->backBottom = (GLubyte *) win->backStart - + (height - 1) * win->rowStride; - win->curBottom = win->backBottom; - } - else { - /* single buffered */ - win->backStart = NULL; - win->backBottom = NULL; - win->curBottom = win->frontBottom; - } - - dpy->driScreen.createNewDrawable(dpy, visual->mode, (int) win, - &win->driDrawable, GLX_WINDOW_BIT, empty_attribute_list); - - if (!win->driDrawable.private) { - fprintf(stderr, "%s: dri.createDrawable failed\n", __FUNCTION__); - free(win); - return NULL; - } - - dpy->NumWindows++; - dpy->TheWindow = win; - - return win; -} - - -/** - * \brief Destroy window. - * - * \param display display handle. - * \param w window handle. - * - * This function calls XUnmapWindow() and frees window \p w. - * - * In case of destroying the current buffer first unbinds the GLX context - * by calling glXMakeCurrent() with no drawable. - */ -void -XDestroyWindow( Display *display, Window win ) -{ - if (display && display->IsClient && win) { - /* check if destroying the current buffer */ - Window curDraw = glXGetCurrentDrawable(); - if (win == curDraw) { - glXMakeCurrent( display, NULL, NULL); - } - - XUnmapWindow( display, win ); - - /* Destroy the drawable. */ - win->driDrawable.destroyDrawable(display, win->driDrawable.private); - free(win); - - /* unlink window from display */ - display->NumWindows--; - assert(display->NumWindows == 0); - display->TheWindow = NULL; - } -} - - - - -/** - * \brief Create color map structure. - * - * \param dpy the display handle as returned by XOpenDisplay(). - * \param w the window on whose screen you want to create a color map. This - * parameter is ignored by Mini GLX but should be the value returned by the - * \code RootWindow(display, 0) \endcode macro. - * \param visual a visual type supported on the screen. This parameter is - * ignored by Mini GLX but should be the XVisualInfo::visual returned by - * glXChooseVisual(). - * \param alloc the color map entries to be allocated. This parameter is ignored - * by Mini GLX but should be set to #AllocNone. - * - * \return the color map. - * - * This function is only provided to ease porting. Practically a no-op - - * returns a pointer to a dynamically allocated chunk of memory (one byte). - */ -Colormap -XCreateColormap( Display *dpy, Window w, Visual *visual, int alloc ) -{ - (void) dpy; - (void) w; - (void) visual; - (void) alloc; - return (Colormap) malloc(1); -} - - -/** - * \brief Destroy color map structure. - * - * \param display The display handle as returned by XOpenDisplay(). - * \param colormap the color map to destroy. - * - * This function is only provided to ease porting. Practically a no-op. - * - * Frees the memory pointed by \p colormap. - */ -void -XFreeColormap( Display *display, Colormap colormap ) -{ - (void) display; - (void) colormap; - free(colormap); -} - - -/** - * \brief Free client data. - * - * \param data the data that is to be freed. - * - * Frees the memory pointed by \p data. - */ -void -XFree( void *data ) -{ - free(data); -} - - -/** - * \brief Query available visuals. - * - * \param dpy the display handle, as returned by XOpenDisplay(). - * \param vinfo_mask a bitmask indicating which fields of the \p vinfo_template - * are to be matched. The value must be \c VisualScreenMask. - * \param vinfo_template a template whose fields indicate which visual - * attributes must be matched by the results. The XVisualInfo::screen field of - * this structure must be zero. - * \param nitens_return will hold the number of visuals returned. - * - * \return the address of an array of all available visuals. - * - * An example of using XGetVisualInfo() to get all available visuals follows: - * - * \code - * XVisualInfo vinfo_template, *results; - * int nitens_return; - * Display *dpy = XOpenDisplay(NULL); - * vinfo_template.screen = 0; - * results = XGetVisualInfo(dpy, VisualScreenMask, &vinfo_template, &nitens_return); - * \endcode - * - * Returns the list of all ::XVisualInfo available, one per - * ::__GLcontextMode stored in MiniGLXDisplayRec::modes. - */ -XVisualInfo * -XGetVisualInfo( Display *dpy, long vinfo_mask, XVisualInfo *vinfo_template, int *nitens_return ) -{ - const __GLcontextModes *mode; - XVisualInfo *results; - Visual *visResults; - int i, n=0; - - // ASSERT(vinfo_mask == VisualScreenMask); - ASSERT(vinfo_template.screen == 0); - - if (vinfo_mask == VisualIDMask) - { - for ( mode = dpy->driver_modes ; mode != NULL ; mode= mode->next ) - if (mode->visualID == vinfo_template->visualid) - n=1; - - if (n==0) - return NULL; - - results = (XVisualInfo *)calloc(1, n * sizeof(XVisualInfo)); - if (!results) { - *nitens_return = 0; - return NULL; - } - - visResults = (Visual *)calloc(1, n * sizeof(Visual)); - if (!results) { - free(results); - *nitens_return = 0; - return NULL; - } - - for ( mode = dpy->driver_modes ; mode != NULL ; mode= mode->next ) - if (mode->visualID == vinfo_template->visualid) - { - visResults[0].mode=mode; - visResults[0].visInfo = results; - visResults[0].dpy = dpy; - if (dpy->driverContext.bpp == 32) - visResults[0].pixelFormat = PF_B8G8R8A8; /* XXX: FIX ME */ - else - visResults[0].pixelFormat = PF_B5G6R5; /* XXX: FIX ME */ - - results[0].visual = visResults; - results[0].visualid = mode->visualID; -#if defined(__cplusplus) || defined(c_plusplus) - results[0].c_class = TrueColor; -#else - results[0].class = TrueColor; -#endif - results[0].depth = mode->redBits + - mode->redBits + - mode->redBits + - mode->redBits; - results[0].bits_per_rgb = dpy->driverContext.bpp; - - } - - } - else // if (vinfo_mask == VisualScreenMask) - { - n = 0; - for ( mode = dpy->driver_modes ; mode != NULL ; mode = mode->next ) - n++; - - results = (XVisualInfo *)calloc(1, n * sizeof(XVisualInfo)); - if (!results) { - *nitens_return = 0; - return NULL; - } - - visResults = (Visual *)calloc(1, n * sizeof(Visual)); - if (!results) { - free(results); - *nitens_return = 0; - return NULL; - } - - for ( mode = dpy->driver_modes, i = 0 ; mode != NULL ; mode = mode->next, i++ ) { - visResults[i].mode = mode; - visResults[i].visInfo = results + i; - visResults[i].dpy = dpy; - - if (dpy->driverContext.bpp == 32) - visResults[i].pixelFormat = PF_B8G8R8A8; /* XXX: FIX ME */ - else - visResults[i].pixelFormat = PF_B5G6R5; /* XXX: FIX ME */ - - results[i].visual = visResults + i; - results[i].visualid = mode->visualID; -#if defined(__cplusplus) || defined(c_plusplus) - results[i].c_class = TrueColor; -#else - results[i].class = TrueColor; -#endif - results[i].depth = mode->redBits + - mode->redBits + - mode->redBits + - mode->redBits; - results[i].bits_per_rgb = dpy->driverContext.bpp; - } - } - *nitens_return = n; - return results; -} - - -/** - * \brief Return a visual that matches specified attributes. - * - * \param dpy the display handle, as returned by XOpenDisplay(). - * \param screen the screen number. It is currently ignored by Mini GLX and - * should be zero. - * \param attribList a list of GLX attributes which describe the desired pixel - * format. It is terminated by the token \c None. - * - * The attributes are as follows: - * \arg GLX_USE_GL: - * This attribute should always be present in order to maintain compatibility - * with GLX. - * \arg GLX_RGBA: - * If present, only RGBA pixel formats will be considered. Otherwise, only - * color index formats are considered. - * \arg GLX_DOUBLEBUFFER: - * if present, only double-buffered pixel formats will be chosen. - * \arg GLX_RED_SIZE \e n: - * Must be followed by a non-negative integer indicating the minimum number of - * bits per red pixel component that is acceptable. - * \arg GLX_GREEN_SIZE \e n: - * Must be followed by a non-negative integer indicating the minimum number of - * bits per green pixel component that is acceptable. - * \arg GLX_BLUE_SIZE \e n: - * Must be followed by a non-negative integer indicating the minimum number of - * bits per blue pixel component that is acceptable. - * \arg GLX_ALPHA_SIZE \e n: - * Must be followed by a non-negative integer indicating the minimum number of - * bits per alpha pixel component that is acceptable. - * \arg GLX_STENCIL_SIZE \e n: - * Must be followed by a non-negative integer indicating the minimum number of - * bits per stencil value that is acceptable. - * \arg GLX_DEPTH_SIZE \e n: - * Must be followed by a non-negative integer indicating the minimum number of - * bits per depth component that is acceptable. - * \arg None: - * This token is used to terminate the attribute list. - * - * \return a pointer to an #XVisualInfo object which most closely matches the - * requirements of the attribute list. If there is no visual which matches the - * request, \c NULL will be returned. - * - * \note Visuals with accumulation buffers are not available. - * - * This function searches the list of available visual configurations in - * MiniGLXDisplayRec::configs for a configuration which best matches the GLX - * attribute list parameter. A new ::XVisualInfo object is created which - * describes the visual configuration. The match criteria is described in the - * specification. - */ -XVisualInfo* -glXChooseVisual( Display *dpy, int screen, int *attribList ) -{ - const __GLcontextModes *mode; - Visual *vis; - XVisualInfo *visInfo; - const int *attrib; - GLboolean rgbFlag = GL_FALSE, dbFlag = GL_FALSE, stereoFlag = GL_FALSE; - GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0; - GLint indexBits = 0, depthBits = 0, stencilBits = 0; - GLint numSamples = 0; - int i=0; - - /* - * XXX in the future, <screen> might be interpreted as a VT - */ - ASSERT(dpy); - ASSERT(screen == 0); - - vis = (Visual *)calloc(1, sizeof(Visual)); - if (!vis) - return NULL; - - visInfo = (XVisualInfo *)malloc(sizeof(XVisualInfo)); - if (!visInfo) { - free(vis); - return NULL; - } - - visInfo->visual = vis; - vis->visInfo = visInfo; - vis->dpy = dpy; - - /* parse the attribute list */ - for (attrib = attribList; attrib && *attrib != None; attrib++) { - switch (attrib[0]) { - case GLX_DOUBLEBUFFER: - dbFlag = GL_TRUE; - break; - case GLX_RGBA: - rgbFlag = GL_TRUE; - break; - case GLX_RED_SIZE: - redBits = attrib[1]; - attrib++; - break; - case GLX_GREEN_SIZE: - greenBits = attrib[1]; - attrib++; - break; - case GLX_BLUE_SIZE: - blueBits = attrib[1]; - attrib++; - break; - case GLX_ALPHA_SIZE: - alphaBits = attrib[1]; - attrib++; - break; - case GLX_STENCIL_SIZE: - stencilBits = attrib[1]; - attrib++; - break; - case GLX_DEPTH_SIZE: - depthBits = attrib[1]; - attrib++; - break; -#if 0 - case GLX_ACCUM_RED_SIZE: - accumRedBits = attrib[1]; - attrib++; - break; - case GLX_ACCUM_GREEN_SIZE: - accumGreenBits = attrib[1]; - attrib++; - break; - case GLX_ACCUM_BLUE_SIZE: - accumBlueBits = attrib[1]; - attrib++; - break; - case GLX_ACCUM_ALPHA_SIZE: - accumAlphaBits = attrib[1]; - attrib++; - break; - case GLX_LEVEL: - /* ignored for now */ - break; -#endif - default: - /* unexpected token */ - fprintf(stderr, "unexpected token in glXChooseVisual attrib list\n"); - free(vis); - free(visInfo); - return NULL; - } - } - - /* search screen configs for suitable visual */ - (void) numSamples; - (void) indexBits; - (void) redBits; - (void) greenBits; - (void) blueBits; - (void) alphaBits; - (void) stereoFlag; - for ( mode = dpy->driver_modes ; mode != NULL ; mode = mode->next ) { - i++; - if (mode->rgbMode == rgbFlag && - mode->doubleBufferMode == dbFlag && - mode->redBits >= redBits && - mode->greenBits >= greenBits && - mode->blueBits >= blueBits && - mode->alphaBits >= alphaBits && - mode->depthBits >= depthBits && - mode->stencilBits >= stencilBits) { - /* found it */ - visInfo->visualid = i; - vis->mode = mode; - break; - } - } - if (!vis->mode) - return NULL; - - /* compute depth and bpp */ - if (rgbFlag) { - /* XXX maybe support depth 16 someday */ -#if defined(__cplusplus) || defined(c_plusplus) - visInfo->c_class = TrueColor; -#else - visInfo->class = TrueColor; -#endif - visInfo->depth = dpy->driverContext.bpp; - visInfo->bits_per_rgb = dpy->driverContext.bpp; - if (dpy->driverContext.bpp == 32) - vis->pixelFormat = PF_B8G8R8A8; - else - vis->pixelFormat = PF_B5G6R5; - } - else { - /* color index mode */ -#if defined(__cplusplus) || defined(c_plusplus) - visInfo->c_class = PseudoColor; -#else - visInfo->class = PseudoColor; -#endif - visInfo->depth = 8; - visInfo->bits_per_rgb = 8; /* bits/pixel */ - vis->pixelFormat = PF_CI8; - } - - return visInfo; -} - - -/** - * \brief Return information about GLX visuals. - * - * \param dpy the display handle, as returned by XOpenDisplay(). - * \param vis the visual to be queried, as returned by glXChooseVisual(). - * \param attrib the visual attribute to be returned. - * \param value pointer to an integer in which the result of the query will be - * stored. - * - * \return zero if no error occurs, \c GLX_INVALID_ATTRIBUTE if the attribute - * parameter is invalid, or \c GLX_BAD_VISUAL if the \p vis parameter is - * invalid. - * - * Returns the appropriate attribute of ::__GLXvisualConfig pointed by - * MiniGLXVisualRec::glxConfig of XVisualInfo::visual. - * - * \sa data types. - */ -int -glXGetConfig( Display *dpy, XVisualInfo *vis, int attrib, int *value ) -{ - const __GLcontextModes *mode = vis->visual->mode; - if (!mode) { - *value = 0; - return GLX_BAD_VISUAL; - } - - switch (attrib) { - case GLX_USE_GL: - *value = True; - return 0; - case GLX_RGBA: - *value = mode->rgbMode; - return 0; - case GLX_DOUBLEBUFFER: - *value = mode->doubleBufferMode; - return 0; - case GLX_RED_SIZE: - *value = mode->redBits; - return 0; - case GLX_GREEN_SIZE: - *value = mode->greenBits; - return 0; - case GLX_BLUE_SIZE: - *value = mode->blueBits; - return 0; - case GLX_ALPHA_SIZE: - *value = mode->alphaBits; - return 0; - case GLX_DEPTH_SIZE: - *value = mode->depthBits; - return 0; - case GLX_STENCIL_SIZE: - *value = mode->stencilBits; - return 0; - default: - *value = 0; - return GLX_BAD_ATTRIBUTE; - } - return 0; -} - - -/** - * \brief Create a new GLX rendering context. - * - * \param dpy the display handle, as returned by XOpenDisplay(). - * \param vis the visual that defines the frame buffer resources available to - * the rendering context, as returned by glXChooseVisual(). - * \param shareList If non-zero, texture objects and display lists are shared - * with the named rendering context. If zero, texture objects and display lists - * will (initially) be private to this context. They may be shared when a - * subsequent context is created. - * \param direct whether direct or indirect rendering is desired. For Mini GLX - * this value is ignored but it should be set to \c True. - * - * \return a ::GLXContext handle if it succeeds or zero if it fails due to - * invalid parameter or insufficient resources. - * - * This function creates and initializes a ::MiniGLXContextRec structure and - * calls the __DRIscreenRec::createContext method to initialize the client - * private data. - */ -GLXContext -glXCreateContext( Display *dpy, XVisualInfo *vis, - GLXContext shareList, Bool direct ) -{ - GLXContext ctx; - void *sharePriv; - - ASSERT(vis); - - ctx = (struct MiniGLXContextRec *)calloc(1, sizeof(struct MiniGLXContextRec)); - if (!ctx) - return NULL; - - ctx->vid = vis->visualid; - - if (shareList) - sharePriv = shareList->driContext.private; - else - sharePriv = NULL; - - ctx->driContext.mode = vis->visual->mode; - ctx->driContext.private = dpy->driScreen.createNewContext(dpy, vis->visual->mode, - GLX_WINDOW_BIT, sharePriv, &ctx->driContext); - - if (!ctx->driContext.private) { - free(ctx); - return NULL; - } - - return ctx; -} - - -/** - * \brief Destroy a GLX context. - * - * \param dpy the display handle, as returned by XOpenDisplay(). - * \param ctx the GLX context to be destroyed. - * - * This function frees the \p ctx parameter after unbinding the current context - * by calling the __DRIcontextRec::bindContext method with zeros and calling - * the __DRIcontextRec::destroyContext method. - */ -void -glXDestroyContext( Display *dpy, GLXContext ctx ) -{ - GLXContext glxctx = glXGetCurrentContext(); - - if (ctx) { - if (glxctx == ctx) { - /* destroying current context */ - ctx->driContext.bindContext(dpy, 0, 0, 0, 0); - CurrentContext = 0; - } - ctx->driContext.destroyContext(dpy, 0, ctx->driContext.private); - free(ctx); - } -} - - -/** - * \brief Bind a GLX context to a window or a pixmap. - * - * \param dpy the display handle, as returned by XOpenDisplay(). - * \param drawable the window or drawable to bind to the rendering context. - * This should be the value returned by XCreateWindow(). - * \param ctx the GLX context to be destroyed. - * - * \return \c True if it succeeds, \c False otherwise to indicate an invalid - * display, window or context parameter. - * - * The current rendering context may be unbound by calling glXMakeCurrent() - * with the window and context parameters set to zero. - * - * An application may create any number of rendering contexts and bind them as - * needed. Note that binding a rendering context is generally not a - * light-weight operation. Most simple OpenGL applications create only one - * rendering context. - * - * This function first unbinds any old context via - * __DRIcontextRec::unbindContext and binds the new one via - * __DRIcontextRec::bindContext. - * - * If \p drawable is zero it unbinds the GLX context by calling - * __DRIcontextRec::bindContext with zeros. - */ -Bool -glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx) -{ - if (dpy && drawable && ctx) { - GLXContext oldContext = glXGetCurrentContext(); - GLXDrawable oldDrawable = glXGetCurrentDrawable(); - /* unbind old */ - if (oldContext) { - oldContext->driContext.unbindContext(dpy, 0, - (__DRIid) oldDrawable, (__DRIid) oldDrawable, - &oldContext->driContext); - } - /* bind new */ - CurrentContext = ctx; - ctx->driContext.bindContext(dpy, 0, (__DRIid) drawable, - (__DRIid) drawable, &ctx->driContext); - ctx->drawBuffer = drawable; - ctx->curBuffer = drawable; - } - else if (ctx && dpy) { - /* unbind */ - ctx->driContext.bindContext(dpy, 0, 0, 0, 0); - } - else if (dpy) { - CurrentContext = 0; /* kw: this seems to be intended??? */ - } - - return True; -} - - -/** - * \brief Exchange front and back buffers. - * - * \param dpy the display handle, as returned by XOpenDisplay(). - * \param drawable the drawable whose buffers are to be swapped. - * - * Any pending rendering commands will be completed before the buffer swap - * takes place. - * - * Calling glXSwapBuffers() on a window which is single-buffered has no effect. - * - * This function just calls the __DRIdrawableRec::swapBuffers method to do the - * work. - */ -void -glXSwapBuffers( Display *dpy, GLXDrawable drawable ) -{ - if (!dpy || !drawable) - return; - - drawable->driDrawable.swapBuffers(dpy, drawable->driDrawable.private); -} - - -/** - * \brief Return the current context - * - * \return the current context, as specified by glXMakeCurrent(), or zero if no - * context is currently bound. - * - * \sa glXCreateContext(), glXMakeCurrent() - * - * Returns the value of the ::CurrentContext global variable. - */ -GLXContext -glXGetCurrentContext( void ) -{ - return CurrentContext; -} - - -/** - * \brief Return the current drawable. - * - * \return the current drawable, as specified by glXMakeCurrent(), or zero if - * no drawable is currently bound. - * - * This function gets the current context via glXGetCurrentContext() and - * returns the MiniGLXContextRec::drawBuffer attribute. - */ -GLXDrawable -glXGetCurrentDrawable( void ) -{ - GLXContext glxctx = glXGetCurrentContext(); - if (glxctx) - return glxctx->drawBuffer; - else - return NULL; -} - - -static GLboolean -__glXCreateContextWithConfig(__DRInativeDisplay *dpy, int screen, - int fbconfigID, void *contextID, drm_context_t *hHWContext) -{ - __DRIscreen *pDRIScreen; - __DRIscreenPrivate *psp; - - pDRIScreen = __glXFindDRIScreen(dpy, screen); - if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) { - return GL_FALSE; - } - - psp = (__DRIscreenPrivate *) pDRIScreen->private; - - if (psp->fd) { - if (drmCreateContext(psp->fd, hHWContext)) { - fprintf(stderr, ">>> drmCreateContext failed\n"); - return GL_FALSE; - } - *(void**)contextID = (void*) *hHWContext; - } - - return GL_TRUE; -} - - -static GLboolean -__glXGetDrawableInfo(__DRInativeDisplay *dpy, int scrn, - __DRIid draw, unsigned int * index, unsigned int * stamp, - int * x, int * y, int * width, int * height, - int * numClipRects, drm_clip_rect_t ** pClipRects, - int * backX, int * backY, - int * numBackClipRects, drm_clip_rect_t ** pBackClipRects) -{ - GLXDrawable drawable = (GLXDrawable) draw; - drm_clip_rect_t * cliprect; - Display* display = (Display*)dpy; - __DRIscreenPrivate *psp = display->driScreen.private; - __DRIcontextPrivate *pcp = (__DRIcontextPrivate *)CurrentContext->driContext.private; - __DRIdrawablePrivate *pdp = pcp->driDrawablePriv; - if (drawable == 0) { - return GL_FALSE; - } - - cliprect = (drm_clip_rect_t*) _mesa_malloc(sizeof(drm_clip_rect_t)); - cliprect->x1 = drawable->x; - cliprect->y1 = drawable->y; - cliprect->x2 = drawable->x + drawable->w; - cliprect->y2 = drawable->y + drawable->h; - - /* the drawable index is by client id */ - *index = display->clientID; - - *stamp = pcp->driScreenPriv->pSAREA->drawableTable[display->clientID].stamp; - drmUpdateDrawableInfo(psp->fd, pdp->hHWDrawable, DRM_DRAWABLE_CLIPRECTS, 1, cliprect); - *x = drawable->x; - *y = drawable->y; - *width = drawable->w; - *height = drawable->h; - *numClipRects = 1; - *pClipRects = cliprect; - - *backX = drawable->x; - *backY = drawable->y; - *numBackClipRects = 0; - *pBackClipRects = 0; - - return GL_TRUE; -} - - -static GLboolean -xf86DRI_DestroyContext(__DRInativeDisplay *dpy, int screen, __DRIid context_id ) -{ - return GL_TRUE; -} - - -static GLboolean -xf86DRI_CreateDrawable(__DRInativeDisplay *dpy, int screen, __DRIid drawable, - drm_drawable_t *hHWDrawable ) -{ - - Display *display = (Display *)dpy; - __DRIscreenPrivate *psp = display->driScreen.private; - int ret; - ret = drmCreateDrawable(psp->fd, hHWDrawable); - - fprintf(stderr, "drawable is %d %08X ret is %d\n", *hHWDrawable, drawable, -ret); - if (ret != 0) - return GL_FALSE; - return GL_TRUE; -} - - -static GLboolean -xf86DRI_DestroyDrawable(__DRInativeDisplay *dpy, int screen, __DRIid drawable) -{ - return GL_TRUE; -} - - -/** - * \brief Query function address. - * - * The glXGetProcAddress() function will return the address of any available - * OpenGL or Mini GLX function. - * - * \param procName name of the function to be returned. - * - * \return If \p procName is a valid function name, a pointer to that function - * will be returned. Otherwise, \c NULL will be returned. - * - * The purpose of glXGetProcAddress() is to facilitate using future extensions - * to OpenGL or Mini GLX. If a future version of the library adds new extension - * functions they'll be accessible via glXGetProcAddress(). The alternative is - * to hard-code calls to the new functions in the application but doing so will - * prevent linking the application with older versions of the library. - * - * Returns the function address by looking up its name in a static (name, - * address) pair list. - */ -void (*glXGetProcAddress(const GLubyte *procname))( void ) -{ - struct name_address { - const char *name; - const void *func; - }; - static const struct name_address functions[] = { - { "glXChooseVisual", (void *) glXChooseVisual }, - { "glXCreateContext", (void *) glXCreateContext }, - { "glXDestroyContext", (void *) glXDestroyContext }, - { "glXMakeCurrent", (void *) glXMakeCurrent }, - { "glXSwapBuffers", (void *) glXSwapBuffers }, - { "glXGetCurrentContext", (void *) glXGetCurrentContext }, - { "glXGetCurrentDrawable", (void *) glXGetCurrentDrawable }, - { "glXGetProcAddress", (void *) glXGetProcAddress }, - { "XOpenDisplay", (void *) XOpenDisplay }, - { "XCloseDisplay", (void *) XCloseDisplay }, - { "XCreateWindow", (void *) XCreateWindow }, - { "XDestroyWindow", (void *) XDestroyWindow }, - { "XMapWindow", (void *) XMapWindow }, - { "XCreateColormap", (void *) XCreateColormap }, - { "XFreeColormap", (void *) XFreeColormap }, - { "XFree", (void *) XFree }, - { "XGetVisualinfo", (void *) XGetVisualInfo }, - { "glXCreatePbuffer", (void *) glXCreatePbuffer }, - { "glXDestroyPbuffer", (void *) glXDestroyPbuffer }, - { "glXChooseFBConfig", (void *) glXChooseFBConfig }, - { "glXGetVisualFromFBConfig", (void *) glXGetVisualFromFBConfig }, - { NULL, NULL } - }; - const struct name_address *entry; - for (entry = functions; entry->name; entry++) { - if (strcmp(entry->name, (const char *) procname) == 0) { - return entry->func; - } - } - return _glapi_get_proc_address((const char *) procname); -} - - -/** - * \brief Query the Mini GLX version. - * - * \param dpy the display handle. It is currently ignored, but should be the - * value returned by XOpenDisplay(). - * \param major receives the major version number of Mini GLX. - * \param minor receives the minor version number of Mini GLX. - * - * \return \c True if the function succeeds, \c False if the function fails due - * to invalid parameters. - * - * \sa #MINI_GLX_VERSION_1_0. - * - * Returns the hard-coded Mini GLX version. - */ -Bool -glXQueryVersion( Display *dpy, int *major, int *minor ) -{ - (void) dpy; - *major = 1; - *minor = 0; - return True; -} - - -/** - * \brief Create a new pbuffer. - */ -GLXPbuffer -glXCreatePbuffer( Display *dpy, GLXFBConfig config, const int *attribList ) -{ - return NULL; -} - - -void -glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) -{ - free(pbuf); -} - - -GLXFBConfig * -glXChooseFBConfig( Display *dpy, int screen, const int *attribList, - int *nitems ) -{ - GLXFBConfig *f = (GLXFBConfig *) malloc(sizeof(GLXFBConfig)); - f->visInfo = glXChooseVisual( dpy, screen, (int *) attribList ); - if (f->visInfo) { - *nitems = 1; - return f; - } - else { - *nitems = 0; - free(f); - return NULL; - } -} - - -XVisualInfo * -glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) -{ - /* XVisualInfo and GLXFBConfig are the same structure */ - (void) dpy; - return config.visInfo; -} - -void *glXAllocateMemoryMESA(Display *dpy, int scrn, - size_t size, float readFreq, - float writeFreq, float priority) -{ - if (dpy->driScreen.private && dpy->driScreen.allocateMemory) { - return (*dpy->driScreen.allocateMemory)( dpy, scrn, size, - readFreq, writeFreq, - priority ); - } - - return NULL; -} - -void glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer) -{ - if (dpy->driScreen.private && dpy->driScreen.freeMemory) { - (*dpy->driScreen.freeMemory)( dpy, scrn, pointer ); - } -} - -GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn, - const void *pointer ) -{ - if (dpy->driScreen.private && dpy->driScreen.memoryOffset) { - return (*dpy->driScreen.memoryOffset)( dpy, scrn, pointer ); - } - - return 0; -} - - -/** - * Get the unadjusted system time (UST). Currently, the UST is measured in - * microseconds since Epoc. The actual resolution of the UST may vary from - * system to system, and the units may vary from release to release. - * Drivers should not call this function directly. They should instead use - * \c glXGetProcAddress to obtain a pointer to the function. - * - * \param ust Location to store the 64-bit UST - * \returns Zero on success or a negative errno value on failure. - * - * \note - * This function was copied directly from src/glx/x11/glxcmds.c. - */ -static int __glXGetUST( int64_t * ust ) -{ - struct timeval tv; - - if ( ust == NULL ) { - return -EFAULT; - } - - if ( gettimeofday( & tv, NULL ) == 0 ) { - ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; - return 0; - } else { - return -errno; - } -} - - -/** - * - * \bug - * This needs to be implemented for miniGlx. - */ -static GLboolean __glXGetMscRate(__DRInativeDisplay * dpy, __DRIid drawable, - int32_t * numerator, int32_t * denominator) -{ - *numerator = 0; - *denominator = 0; - return False; -} -/*@}*/ diff --git a/src/glx/mini/miniglxP.h b/src/glx/mini/miniglxP.h deleted file mode 100644 index 96ed0e81cd7..00000000000 --- a/src/glx/mini/miniglxP.h +++ /dev/null @@ -1,205 +0,0 @@ -/** - * \file miniglxP.h - * \brief Define replacements for some X data types and define the DRI-related - * data structures. - * - * \note Cut down version of glxclient.h. - * - */ - -#ifndef _mini_GLX_client_h_ -#define _mini_GLX_client_h_ - -#include <signal.h> -#include <linux/fb.h> - -#include <GL/miniglx.h> -#include "glheader.h" -#include "mtypes.h" - -#include "driver.h" -#include "GL/internal/dri_interface.h" - -/** - * \brief Supported pixel formats. - */ -enum PixelFormat { - PF_B8G8R8, /**< \brief 24-bit BGR */ - PF_B8G8R8A8, /**< \brief 32-bit BGRA */ - PF_B5G6R5, /**< \brief 16-bit BGR */ - PF_B5G5R5, /**< \brief 15-bit BGR */ - PF_CI8 /**< \brief 8-bit color index */ -}; - -/** - * \brief X Visual type. - * - * \sa ::Visual, \ref datatypes. - */ -struct MiniGLXVisualRec { - /** \brief GLX visual information */ - const __GLcontextModes *mode; - - /** \brief pointer back to corresponding ::XVisualInfo */ - XVisualInfo *visInfo; - - /** \brief display handle */ - Display *dpy; - - /** \brief pixel format */ - enum PixelFormat pixelFormat; -}; - - - -/** - * \brief X Window type. - * - * \sa ::Window, \ref datatypes. - */ -struct MiniGLXWindowRec { - Visual *visual; - /** \brief position (always 0,0) */ - int x, y; - /** \brief size */ - unsigned int w, h; - void *frontStart; /**< \brief start of front color buffer */ - void *backStart; /**< \brief start of back color buffer */ - size_t size; /**< \brief color buffer size, in bytes */ - GLuint bytesPerPixel; - GLuint rowStride; /**< \brief in bytes */ - GLubyte *frontBottom; /**< \brief pointer to last row */ - GLubyte *backBottom; /**< \brief pointer to last row */ - GLubyte *curBottom; /**< = frontBottom or backBottom */ - __DRIdrawable driDrawable; - GLuint ismapped; -}; - - -/** - * \brief GLXContext type. - * - * \sa ::GLXContext, \ref datatypes. - */ -struct MiniGLXContextRec { - Window drawBuffer; /**< \brief drawing buffer */ - Window curBuffer; /**< \brief current buffer */ - VisualID vid; /**< \brief visual ID */ - __DRIcontext driContext; /**< \brief context dependent methods */ -}; - -#define MINIGLX_BUF_SIZE 512 -#define MINIGLX_MAX_SERVER_FDS 10 -#define MINIGLX_MAX_CLIENT_FDS 1 -#define MINIGLX_EVENT_QUEUE_SZ 16 -#define MINIGLX_EVENT_QUEUE_MASK (MINIGLX_EVENT_QUEUE_SZ-1) - -/** - * A connection to/from the server - * - * All information is to/from the server is buffered and then dispatched by - * __miniglx_Select() to avoid blocking the server. - */ -struct MiniGLXConnection { - int fd; /**< \brief file descriptor */ - char readbuf[MINIGLX_BUF_SIZE]; /**< \brief read buffer */ - char writebuf[MINIGLX_BUF_SIZE]; /**< \brief write buffer */ - int readbuf_count; /**< \brief count of bytes waiting to be read */ - int writebuf_count; /**< \brief count of bytes waiting to be written */ -}; - - -/** - * \brief X Display type - * - * \sa ::Display, \ref datatypes. - */ -struct MiniGLXDisplayRec { - /** \brief fixed framebuffer screen info */ - struct fb_fix_screeninfo FixedInfo; - /** \brief original and current variable framebuffer screen info */ - struct fb_var_screeninfo OrigVarInfo, VarInfo; - struct sigaction OrigSigUsr1; - struct sigaction OrigSigUsr2; - int OriginalVT; - int ConsoleFD; /**< \brief console TTY device file descriptor */ - int FrameBufferFD; /**< \brief framebuffer device file descriptor */ - int NumWindows; /**< \brief number of open windows */ - Window TheWindow; /**< \brief open window - only allow one window for now */ - int rotateMode; - - - volatile int vtSignalFlag; - volatile int haveVT; /**< \brief whether the VT is hold */ - int hwActive; /**< \brief whether the hardware is active -- mimics - the variations of MiniGLXDisplayRec::haveVT */ - - - int IsClient; /**< \brief whether it's a client or the server */ - int clientID; - int nrFds; /**< \brief number of connections (usually just one for the clients) */ - struct MiniGLXConnection *fd; /**< \brief connections */ - int drmFd; /**< \brief handle to drm device */ - int authorized; /**< \brief has server authorized this process? */ - - struct { - int nr, head, tail; - XEvent queue[MINIGLX_EVENT_QUEUE_SZ]; - } eventqueue; - - /** - * \name Visuals - * - * Visuals (configs) in this screen. - */ - /*@{*/ - const __GLcontextModes *driver_modes; /**< \brief Modes filtered by driver. */ - /*@}*/ - - /** - * \name From __GLXdisplayPrivate - */ - /*@{*/ - PFNCREATENEWSCREENFUNC createNewScreen; /**< \brief \e __driCreateScreen hook */ - __DRIscreen driScreen; /**< \brief Screen dependent methods */ - void *dlHandle; /**< - * \brief handle to the client dynamic - * library - */ - /*@}*/ - - /** - * \brief Mini GLX specific driver hooks - */ - struct DRIDriverRec *driver; - struct DRIDriverContextRec driverContext; - - /** - * \name Configuration details - * - * They are read from a configuration file by __read_config_file(). - */ - /*@{*/ - const char *fbdevDevice; - const char *clientDriverName; - /*@}*/ -}; - -/** Character messages. */ -enum msgs { - _CanIHaveFocus, - _IDontWantFocus, - _YouveGotFocus, - _YouveLostFocus, - _RepaintPlease, - _Authorize, -}; -extern int send_msg( Display *dpy, int i, const void *msg, size_t sz ); -extern int send_char_msg( Display *dpy, int i, char msg ); -extern int blocking_read( Display *dpy, int connection, char *msg, size_t msg_size ); -extern int handle_fd_events( Display *dpy, int nonblock ); - -extern int __miniglx_open_connections( Display *dpy ); -extern void __miniglx_close_connections( Display *dpy ); - -#endif /* !_mini_GLX_client_h_ */ diff --git a/src/glx/mini/miniglx_events.c b/src/glx/mini/miniglx_events.c deleted file mode 100644 index 969398bc16f..00000000000 --- a/src/glx/mini/miniglx_events.c +++ /dev/null @@ -1,984 +0,0 @@ -/** - * \file miniglx_events.c - * \brief Mini GLX client/server communication functions. - * \author Keith Whitwell - * - * The Mini GLX interface is a subset of the GLX interface, plus a - * minimal set of Xlib functions. This file adds interfaces to - * arbitrate a single cliprect between multiple direct rendering - * clients. - * - * A fairly complete client/server non-blocking communication - * mechanism. Probably overkill given that none of our messages - * currently exceed 1 byte in length and take place over the - * relatively benign channel provided by a Unix domain socket. - */ - -/* - * Mesa 3-D graphics library - * Version: 5.0 - * - * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* $Id: miniglx_events.c,v 1.6 2006/04/03 07:31:27 airlied Exp $ */ - - -#include <assert.h> -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <dlfcn.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/stat.h> - -#include <linux/kd.h> -#include <linux/vt.h> - -#include "xf86drm.h" -#include "miniglxP.h" - - -#define MINIGLX_FIFO_NAME "/tmp/miniglx.fifo" - -/** - * \brief Allocate an XEvent structure on the event queue. - * - * \param dpy the display handle. - * - * \return Pointer to the queued event structure or NULL on failure. - * - * \internal - * If there is space on the XEvent queue, return a pointer - * to the next free event and increment the eventqueue tail value. - * Otherwise return null. - */ -static XEvent *queue_event( Display *dpy ) -{ - int incr = (dpy->eventqueue.tail + 1) & MINIGLX_EVENT_QUEUE_MASK; - if (incr == dpy->eventqueue.head) { - return 0; - } - else { - XEvent *ev = &dpy->eventqueue.queue[dpy->eventqueue.tail]; - dpy->eventqueue.tail = incr; - return ev; - } -} - -/** - * \brief Dequeue an XEvent and copy it into provided storage. - * - * \param dpy the display handle. - * \param event_return pointer to copy the queued event to. - * - * \return True or False depending on success. - * - * \internal - * If there is a queued XEvent on the queue, copy it to the provided - * pointer and increment the eventqueue head value. Otherwise return - * null. - */ -static int dequeue_event( Display *dpy, XEvent *event_return ) -{ - if (dpy->eventqueue.tail == dpy->eventqueue.head) { - return False; - } - else { - *event_return = dpy->eventqueue.queue[dpy->eventqueue.head]; - dpy->eventqueue.head += 1; - dpy->eventqueue.head &= MINIGLX_EVENT_QUEUE_MASK; - return True; - } -} - -/** - * \brief Shutdown a socket connection. - * - * \param dpy the display handle. - * \param i the index in dpy->fd of the socket connection. - * - * \internal - * Shutdown and close the file descriptor. If this is the special - * connection in fd[0], issue an error message and exit - there's been - * some sort of failure somewhere. Otherwise, let the application - * know about whats happened by issuing a DestroyNotify event. - */ -static void shut_fd( Display *dpy, int i ) -{ - if (dpy->fd[i].fd < 0) - return; - - shutdown (dpy->fd[i].fd, SHUT_RDWR); - close (dpy->fd[i].fd); - dpy->fd[i].fd = -1; - dpy->fd[i].readbuf_count = 0; - dpy->fd[i].writebuf_count = 0; - - if (i == 0) { - fprintf(stderr, "server connection lost\n"); - exit(1); - } - else { - /* Pass this to the application as a DestroyNotify event. - */ - XEvent *er = queue_event(dpy); - if (!er) return; - er->xdestroywindow.type = DestroyNotify; - er->xdestroywindow.serial = 0; - er->xdestroywindow.send_event = 0; - er->xdestroywindow.display = dpy; - er->xdestroywindow.window = (Window)i; - - drmGetLock(dpy->driverContext.drmFD, 1, 0); - drmUnlock(dpy->driverContext.drmFD, 1); - } -} - -/** - * \brief Send a message to a socket connection. - * - * \param dpy the display handle. - * \param i the index in dpy->fd of the socket connection. - * \param msg the message to send. - * \param sz the size of the message - * - * \internal - * Copy the message to the write buffer for the nominated connection. - * This will be actually sent to that file descriptor from - * __miniglx_Select(). - */ -int send_msg( Display *dpy, int i, - const void *msg, size_t sz ) -{ - int cnt = dpy->fd[i].writebuf_count; - if (MINIGLX_BUF_SIZE - cnt < sz) { - fprintf(stderr, "client %d: writebuf overflow\n", i); - return False; - } - - memcpy( dpy->fd[i].writebuf + cnt, msg, sz ); cnt += sz; - dpy->fd[i].writebuf_count = cnt; - return True; -} - -/** - * \brief Send a message to a socket connection. - * - * \param dpy the display handle. - * \param i the index in dpy->fd of the socket connection. - * \param msg the message to send. - * - * \internal - * Use send_msg() to send a one-byte message to a socket. - */ -int send_char_msg( Display *dpy, int i, char msg ) -{ - return send_msg( dpy, i, &msg, sizeof(char)); -} - - -/** - * \brief Block and receive a message from a socket connection. - * - * \param dpy the display handle. - * \param connection the index in dpy->fd of the socket connection. - * \param msg storage for the received message. - * \param msg_size the number of bytes to read. - * - * \internal - * Block and read from the connection's file descriptor - * until msg_size bytes have been received. - * - * Only called from welcome_message_part(). - */ -int blocking_read( Display *dpy, int connection, - char *msg, size_t msg_size ) -{ - int i, r; - - for (i = 0 ; i < msg_size ; i += r) { - r = read(dpy->fd[connection].fd, msg + i, msg_size - i); - if (r < 1) { - fprintf(stderr, "blocking_read: %d %s\n", r, strerror(errno)); - shut_fd(dpy,connection); - return False; - } - } - - return True; -} - -/** - * \brief Send/receive a part of the welcome message. - * - * \param dpy the display handle. - * \param i the index in dpy->fd of the socket connection. - * \param msg storage for the sent/received message. - * \param sz the number of bytes to write/read. - * - * \return True on success, or False on failure. - * - * This function is called by welcome_message_part(), to either send or receive - * (via blocking_read()) part of the welcome message, according to whether - * Display::IsClient is set. - * - * Each part of the welcome message on the wire consists of a count and then the - * actual message data with that number of bytes. - */ -static int welcome_message_part( Display *dpy, int i, void **msg, int sz ) -{ - if (dpy->IsClient) { - int sz; - if (!blocking_read( dpy, i, (char *)&sz, sizeof(sz))) return False; - if (!*msg) *msg = malloc(sz); - if (!*msg) return False; - if (!blocking_read( dpy, i, *msg, sz )) return False; - return sz; - } - else { - if (!send_msg( dpy, i, &sz, sizeof(sz))) return False; - if (!send_msg( dpy, i, *msg, sz )) return False; - } - - return True; -} - -/** - * \brief Send/receive the welcome message. - * - * \param dpy the display handle. - * \param i the index in dpy->fd of the socket connection. - * - * \return True on success, or False on failure. - * - * Using welcome_message_part(), sends/receives the client ID, the client - * configuration details in DRIDriverContext::shared, and the driver private - * message in DRIDriverContext::driverClientMsg. - */ -static int welcome_message( Display *dpy, int i ) -{ - void *tmp = &dpy->driverContext.shared; - int *clientid = dpy->IsClient ? &dpy->clientID : &i; - int size; - - if (!welcome_message_part( dpy, i, (void **)&clientid, sizeof(*clientid))) - return False; - - if (!welcome_message_part( dpy, i, &tmp, sizeof(dpy->driverContext.shared))) - return False; - - size=welcome_message_part( dpy, i, - (void **)&dpy->driverContext.driverClientMsg, - dpy->driverContext.driverClientMsgSize ); - - if (!size) - return False; - - if (dpy->IsClient) { - dpy->driverContext.driverClientMsgSize = size; - } - return True; -} - - -/** - * \brief Handle a new client connection. - * - * \param dpy the display handle. - * - * \return True on success or False on failure. - * - * Accepts the connection, sets it in non-blocking operation, and finds a free - * slot in Display::fd for it. - */ -static int handle_new_client( Display *dpy ) -{ - struct sockaddr_un client_address; - unsigned int l = sizeof(client_address); - int r, i; - - r = accept(dpy->fd[0].fd, (struct sockaddr *) &client_address, &l); - if (r < 0) { - perror ("accept()"); - shut_fd(dpy,0); - return False; - } - - if (fcntl(r, F_SETFL, O_NONBLOCK) != 0) { - perror("fcntl"); - close(r); - return False; - } - - - /* Some rough & ready adaption of the XEvent semantics. - */ - for (i = 1 ; i < dpy->nrFds ; i++) { - if (dpy->fd[i].fd < 0) { - XEvent *er = queue_event(dpy); - if (!er) { - close(r); - return False; - } - - dpy->fd[i].fd = r; - er->xcreatewindow.type = CreateNotify; - er->xcreatewindow.serial = 0; - er->xcreatewindow.send_event = 0; - er->xcreatewindow.display = dpy; - er->xcreatewindow.window = (Window)i; /* fd slot == window, now? */ - - /* Send the driver client message - this is expected as the - * first message on a new connection. The recpient already - * knows the size of the message. - */ - welcome_message( dpy, i ); - return True; - } - } - - - fprintf(stderr, "[miniglx] %s: Max nr clients exceeded\n", __FUNCTION__); - close(r); - return False; -} - -/** - * This routine "puffs out" the very basic communications between - * client and server to full-sized X Events that can be handled by the - * application. - * - * \param dpy the display handle. - * \param i the index in dpy->fd of the socket connection. - * - * \return True on success or False on failure. - * - * \internal - * Interprets the message (see msg) into a XEvent and advances the file FIFO - * buffer. - */ -static int -handle_fifo_read( Display *dpy, int i ) -{ - drm_magic_t magic; - int err; - - while (dpy->fd[i].readbuf_count) { - char id = dpy->fd[i].readbuf[0]; - XEvent *er; - int count = 1; - - if (dpy->IsClient) { - switch (id) { - /* The server has called XMapWindow on a client window */ - case _YouveGotFocus: - er = queue_event(dpy); - if (!er) return False; - er->xmap.type = MapNotify; - er->xmap.serial = 0; - er->xmap.send_event = False; - er->xmap.display = dpy; - er->xmap.event = dpy->TheWindow; - er->xmap.window = dpy->TheWindow; - er->xmap.override_redirect = False; - if (dpy->driver->notifyFocus) - dpy->driver->notifyFocus( 1 ); - break; - - /* The server has called XMapWindow on a client window */ - case _RepaintPlease: - er = queue_event(dpy); - if (!er) return False; - er->xexpose.type = Expose; - er->xexpose.serial = 0; - er->xexpose.send_event = False; - er->xexpose.display = dpy; - er->xexpose.window = dpy->TheWindow; - if (dpy->rotateMode) { - er->xexpose.x = dpy->TheWindow->y; - er->xexpose.y = dpy->TheWindow->x; - er->xexpose.width = dpy->TheWindow->h; - er->xexpose.height = dpy->TheWindow->w; - } - else { - er->xexpose.x = dpy->TheWindow->x; - er->xexpose.y = dpy->TheWindow->y; - er->xexpose.width = dpy->TheWindow->w; - er->xexpose.height = dpy->TheWindow->h; - } - er->xexpose.count = 0; - break; - - /* The server has called 'XUnmapWindow' on a client - * window. - */ - case _YouveLostFocus: - er = queue_event(dpy); - if (!er) return False; - er->xunmap.type = UnmapNotify; - er->xunmap.serial = 0; - er->xunmap.send_event = False; - er->xunmap.display = dpy; - er->xunmap.event = dpy->TheWindow; - er->xunmap.window = dpy->TheWindow; - er->xunmap.from_configure = False; - if (dpy->driver->notifyFocus) - dpy->driver->notifyFocus( 0 ); - break; - - case _Authorize: - dpy->authorized = True; - break; - - default: - fprintf(stderr, "Client received unhandled message type %d\n", id); - shut_fd(dpy, i); /* Actually shuts down the client */ - return False; - } - } - else { - switch (id) { - /* Lets the server know that the client is ready to render - * (having called 'XMapWindow' locally). - */ - case _CanIHaveFocus: - er = queue_event(dpy); - if (!er) return False; - er->xmaprequest.type = MapRequest; - er->xmaprequest.serial = 0; - er->xmaprequest.send_event = False; - er->xmaprequest.display = dpy; - er->xmaprequest.parent = 0; - er->xmaprequest.window = (Window)i; - break; - - /* Both _YouveLostFocus and _IDontWantFocus generate unmap - * events. The idea is that _YouveLostFocus lets the client - * know that it has had focus revoked by the server, whereas - * _IDontWantFocus lets the server know that the client has - * unmapped its own window. - */ - case _IDontWantFocus: - er = queue_event(dpy); - if (!er) return False; - er->xunmap.type = UnmapNotify; - er->xunmap.serial = 0; - er->xunmap.send_event = False; - er->xunmap.display = dpy; - er->xunmap.event = (Window)i; - er->xunmap.window = (Window)i; - er->xunmap.from_configure = False; - break; - - case _Authorize: - /* is full message here yet? */ - if (dpy->fd[i].readbuf_count < count + sizeof(magic)) { - count = 0; - break; - } - memcpy(&magic, dpy->fd[i].readbuf + count, sizeof(magic)); - fprintf(stderr, "Authorize - magic %d\n", magic); - - err = drmAuthMagic(dpy->driverContext.drmFD, magic); - count += sizeof(magic); - - send_char_msg( dpy, i, _Authorize ); - break; - - default: - fprintf(stderr, "Server received unhandled message type %d\n", id); - shut_fd(dpy, i); /* Generates DestroyNotify event */ - return False; - } - } - - dpy->fd[i].readbuf_count -= count; - - if (dpy->fd[i].readbuf_count) { - memmove(dpy->fd[i].readbuf, - dpy->fd[i].readbuf + count, - dpy->fd[i].readbuf_count); - } - } - - return True; -} - -/** - * Handle a VT signal - * - * \param dpy display handle. - * - * The VT switches is detected by comparing Display::haveVT and - * Display::hwActive. When loosing the VT the hardware lock is acquired, the - * hardware is shutdown via a call to DRIDriverRec::shutdownHardware(), and the - * VT released. When acquiring the VT back the hardware state is restored via a - * call to DRIDriverRec::restoreHardware() and the hardware lock released. - */ -static void __driHandleVtSignals( Display *dpy ) -{ - dpy->vtSignalFlag = 0; - - fprintf(stderr, "%s: haveVT %d hwActive %d\n", __FUNCTION__, - dpy->haveVT, dpy->hwActive); - - if (!dpy->haveVT && dpy->hwActive) { - /* Need to get lock and shutdown hardware */ - DRM_LIGHT_LOCK( dpy->driverContext.drmFD, - dpy->driverContext.pSAREA, - dpy->driverContext.serverContext ); - dpy->driver->shutdownHardware( &dpy->driverContext ); - - /* Can now give up control of the VT */ - ioctl( dpy->ConsoleFD, VT_RELDISP, 1 ); - dpy->hwActive = 0; - } - else if (dpy->haveVT && !dpy->hwActive) { - /* Get VT (wait??) */ - ioctl( dpy->ConsoleFD, VT_RELDISP, VT_ACTIVATE ); - - /* restore HW state, release lock */ - dpy->driver->restoreHardware( &dpy->driverContext ); - DRM_UNLOCK( dpy->driverContext.drmFD, - dpy->driverContext.pSAREA, - dpy->driverContext.serverContext ); - dpy->hwActive = 1; - } -} - - -#undef max -#define max(x,y) ((x) > (y) ? (x) : (y)) - -/** - * Logic for the select() call. - * - * \param dpy display handle. - * \param n highest fd in any set plus one. - * \param rfds fd set to be watched for reading, or NULL to create one. - * \param wfds fd set to be watched for writing, or NULL to create one. - * \param xfds fd set to be watched for exceptions or error, or NULL to create one. - * \param tv timeout value, or NULL for no timeout. - * - * \return number of file descriptors contained in the sets, or a negative number on failure. - * - * \note - * This all looks pretty complex, but is necessary especially on the - * server side to prevent a poorly-behaved client from causing the - * server to block in a read or write and hence not service the other - * clients. - * - * \sa - * See select_tut in the Linux manual pages for more discussion. - * - * \internal - * Creates and initializes the file descriptor sets by inspecting Display::fd - * if these aren't passed in the function call. Calls select() and fulfill the - * demands by trying to fill MiniGLXConnection::readbuf and draining - * MiniGLXConnection::writebuf. - * The server fd[0] is handled specially for new connections, by calling - * handle_new_client(). - * - */ -int -__miniglx_Select( Display *dpy, int n, fd_set *rfds, fd_set *wfds, fd_set *xfds, - struct timeval *tv ) -{ - int i; - int retval; - fd_set my_rfds, my_wfds; - struct timeval my_tv; - - if (!rfds) { - rfds = &my_rfds; - FD_ZERO(rfds); - } - - if (!wfds) { - wfds = &my_wfds; - FD_ZERO(wfds); - } - - /* Don't block if there are events queued. Review this if the - * flush in XMapWindow is changed to blocking. (Test case: - * miniglxtest). - */ - if (dpy->eventqueue.head != dpy->eventqueue.tail) { - my_tv.tv_sec = my_tv.tv_usec = 0; - tv = &my_tv; - } - - for (i = 0 ; i < dpy->nrFds; i++) { - if (dpy->fd[i].fd < 0) - continue; - - if (dpy->fd[i].writebuf_count) - FD_SET(dpy->fd[i].fd, wfds); - - if (dpy->fd[i].readbuf_count < MINIGLX_BUF_SIZE) - FD_SET(dpy->fd[i].fd, rfds); - - n = max(n, dpy->fd[i].fd + 1); - } - - if (dpy->vtSignalFlag) - __driHandleVtSignals( dpy ); - - retval = select( n, rfds, wfds, xfds, tv ); - - if (dpy->vtSignalFlag) { - int tmp = errno; - __driHandleVtSignals( dpy ); - errno = tmp; - } - - if (retval < 0) { - FD_ZERO(rfds); - FD_ZERO(wfds); - return retval; - } - - /* Handle server fd[0] specially on the server - accept new client - * connections. - */ - if (!dpy->IsClient) { - if (FD_ISSET(dpy->fd[0].fd, rfds)) { - FD_CLR(dpy->fd[0].fd, rfds); - handle_new_client( dpy ); - } - } - - /* Otherwise, try and fill readbuffer and drain writebuffer: - */ - for (i = 0 ; i < dpy->nrFds ; i++) { - if (dpy->fd[i].fd < 0) - continue; - - /* If there aren't any event slots left, don't examine - * any more file events. This will prevent lost events. - */ - if (dpy->eventqueue.head == - ((dpy->eventqueue.tail + 1) & MINIGLX_EVENT_QUEUE_MASK)) { - fprintf(stderr, "leaving event loop as event queue is full\n"); - return retval; - } - - if (FD_ISSET(dpy->fd[i].fd, wfds)) { - int r = write(dpy->fd[i].fd, - dpy->fd[i].writebuf, - dpy->fd[i].writebuf_count); - - if (r < 1) - shut_fd(dpy,i); - else { - dpy->fd[i].writebuf_count -= r; - if (dpy->fd[i].writebuf_count) { - memmove(dpy->fd[i].writebuf, - dpy->fd[i].writebuf + r, - dpy->fd[i].writebuf_count); - } - } - } - - if (FD_ISSET(dpy->fd[i].fd, rfds)) { - int r = read(dpy->fd[i].fd, - dpy->fd[i].readbuf + dpy->fd[i].readbuf_count, - MINIGLX_BUF_SIZE - dpy->fd[i].readbuf_count); - - if (r < 1) - shut_fd(dpy,i); - else { - dpy->fd[i].readbuf_count += r; - - handle_fifo_read( dpy, i ); - } - } - } - - return retval; -} - -/** - * \brief Handle socket events. - * - * \param dpy the display handle. - * \param nonblock whether to return immediately or wait for an event. - * - * \return True on success, False on failure. Aborts on critical error. - * - * \internal - * This function is the select() main loop. - */ -int handle_fd_events( Display *dpy, int nonblock ) -{ - while (1) { - struct timeval tv = {0, 0}; - int r = __miniglx_Select( dpy, 0, 0, 0, 0, nonblock ? &tv : 0 ); - if (r >= 0) - return True; - if (errno == EINTR || errno == EAGAIN) - continue; - perror ("select()"); - exit (1); - } -} - -/** - * Initializes the connections. - * - * \param dpy the display handle. - * - * \return True on success or False on failure. - * - * Allocates and initializes the Display::fd array and create a Unix socket on - * the first entry. For a server binds the socket to a filename and listen for - * connections. For a client connects to the server and waits for a welcome - * message. Sets the socket in nonblocking mode. - */ -int __miniglx_open_connections( Display *dpy ) -{ - struct sockaddr_un sa; - int i; - - dpy->nrFds = dpy->IsClient ? 1 : MINIGLX_MAX_SERVER_FDS; - dpy->fd = calloc(1, dpy->nrFds * sizeof(struct MiniGLXConnection)); - if (!dpy->fd) - return False; - - for (i = 0 ; i < dpy->nrFds ; i++) - dpy->fd[i].fd = -1; - - if (!dpy->IsClient) { - if (unlink(MINIGLX_FIFO_NAME) != 0 && errno != ENOENT) { - perror("unlink " MINIGLX_FIFO_NAME); - return False; - } - - } - - /* Create a Unix socket -- Note this is *not* a network connection! - */ - dpy->fd[0].fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (dpy->fd[0].fd < 0) { - perror("socket " MINIGLX_FIFO_NAME); - return False; - } - - memset(&sa, 0, sizeof(sa)); - sa.sun_family = AF_UNIX; - strcpy(sa.sun_path, MINIGLX_FIFO_NAME); - - if (dpy->IsClient) { - /* Connect to server - */ - if (connect(dpy->fd[0].fd, (struct sockaddr *)&sa, sizeof(sa)) != 0) { - perror("connect"); - shut_fd(dpy,0); - return False; - } - - /* Wait for configuration messages from the server. - */ - welcome_message( dpy, 0 ); - } - else { - mode_t tmp = umask( 0000 ); /* open to everybody ? */ - - /* Bind socket to our filename - */ - if (bind(dpy->fd[0].fd, (struct sockaddr *)&sa, sizeof(sa)) != 0) { - perror("bind"); - shut_fd(dpy,0); - return False; - } - - umask( tmp ); - - /* Listen for connections - */ - if (listen(dpy->fd[0].fd, 5) != 0) { - perror("listen"); - shut_fd(dpy,0); - return False; - } - } - - if (fcntl(dpy->fd[0].fd, F_SETFL, O_NONBLOCK) != 0) { - perror("fcntl"); - shut_fd(dpy,0); - return False; - } - - - return True; -} - - -/** - * Frees the connections initialized by __miniglx_open_connections(). - * - * \param dpy the display handle. - */ -void __miniglx_close_connections( Display *dpy ) -{ - int i; - - for (i = 0 ; i < dpy->nrFds ; i++) { - if (dpy->fd[i].fd >= 0) { - shutdown (dpy->fd[i].fd, SHUT_RDWR); - close (dpy->fd[i].fd); - } - } - - dpy->nrFds = 0; - free(dpy->fd); -} - - -/** - * Set a drawable flag. - * - * \param dpy the display handle. - * \param w drawable (window). - * \param flag flag. - * - * Sets the specified drawable flag in the SAREA and increment its stamp while - * holding the light hardware lock. - */ -static void set_drawable_flag( Display *dpy, int w, int flag ) -{ - if (dpy->driverContext.pSAREA) { - if (dpy->hwActive) - DRM_LIGHT_LOCK( dpy->driverContext.drmFD, - dpy->driverContext.pSAREA, - dpy->driverContext.serverContext ); - - dpy->driverContext.pSAREA->drawableTable[w].stamp++; - dpy->driverContext.pSAREA->drawableTable[w].flags = flag; - - if (dpy->hwActive) - DRM_UNLOCK( dpy->driverContext.drmFD, - dpy->driverContext.pSAREA, - dpy->driverContext.serverContext ); - } -} - - - -/** - * \brief Map Window. - * - * \param dpy the display handle as returned by XOpenDisplay(). - * \param w the window handle. - * - * If called by a client, sends a request for focus to the server. If - * called by the server, will generate a MapNotify and Expose event at - * the client. - * - */ -void -XMapWindow( Display *dpy, Window w ) -{ - if (dpy->IsClient) - send_char_msg( dpy, 0, _CanIHaveFocus ); - else { - set_drawable_flag( dpy, (int)w, 1 ); - send_char_msg( dpy, (int)w, _YouveGotFocus ); - send_char_msg( dpy, (int)w, _RepaintPlease ); - dpy->TheWindow = w; - } - handle_fd_events( dpy, 0 ); /* flush write queue */ -} - -/** - * \brief Unmap Window. - * - * \param dpy the display handle as returned by XOpenDisplay(). - * \param w the window handle. - * - * Called from the client: Lets the server know that the window won't - * be updated anymore. - * - * Called from the server: Tells the specified client that it no longer - * holds the focus. - */ -void -XUnmapWindow( Display *dpy, Window w ) -{ - if (dpy->IsClient) { - send_char_msg( dpy, 0, _IDontWantFocus ); - } - else { - dpy->TheWindow = 0; - set_drawable_flag( dpy, (int)w, 0 ); - send_char_msg( dpy, (int)w, _YouveLostFocus ); - } - handle_fd_events( dpy, 0 ); /* flush write queue */ -} - - -/** - * \brief Block and wait for next X event. - * - * \param dpy the display handle as returned by XOpenDisplay(). - * \param event_return a pointer to an XEvent structure for the returned data. - * - * Wait until there is a new XEvent pending. - */ -int XNextEvent(Display *dpy, XEvent *event_return) -{ - for (;;) { - if ( dpy->eventqueue.head != dpy->eventqueue.tail ) - return dequeue_event( dpy, event_return ); - - handle_fd_events( dpy, 0 ); - } -} - -/** - * \brief Non-blocking check for next X event. - * - * \param dpy the display handle as returned by XOpenDisplay(). - * \param event_mask ignored. - * \param event_return a pointer to an XEvent structure for the returned data. - * - * Check if there is a new XEvent pending. Note that event_mask is - * ignored and any pending event will be returned. - */ -Bool XCheckMaskEvent(Display *dpy, long event_mask, XEvent *event_return) -{ - if ( dpy->eventqueue.head != dpy->eventqueue.tail ) - return dequeue_event( dpy, event_return ); - - handle_fd_events( dpy, 1 ); - - return dequeue_event( dpy, event_return ); -} |