Retire miniglx and move the actual glx code up to src/glx

This commit is contained in:
Kristian Høgsberg
2010-02-09 09:58:36 -05:00
parent 538539d879
commit 6e8897ff9f
70 changed files with 114 additions and 4367 deletions

View File

@@ -361,8 +361,8 @@ DRI_FILES = \
$(DIRECTORY)/include/GL/internal/glcore.h \
$(DIRECTORY)/include/GL/internal/sarea.h \
$(DIRECTORY)/src/glx/Makefile \
$(DIRECTORY)/src/glx/x11/Makefile \
$(DIRECTORY)/src/glx/x11/*.[ch] \
$(DIRECTORY)/src/glx/Makefile \
$(DIRECTORY)/src/glx/*.[ch] \
$(DIRECTORY)/src/mesa/drivers/dri/Makefile \
$(DIRECTORY)/src/mesa/drivers/dri/Makefile.template \
$(DIRECTORY)/src/mesa/drivers/dri/dri.pc.in \
@@ -488,7 +488,7 @@ GLUT_FILES = \
DEPEND_FILES = \
$(TOP)/src/mesa/depend \
$(TOP)/src/glx/x11/depend \
$(TOP)/src/glx/depend \
$(TOP)/src/glw/depend \
$(TOP)/src/glut/glx/depend \
$(TOP)/src/glu/sgi/depend

View File

@@ -16,7 +16,7 @@ DEFINES = -D_DARWIN_C_SOURCE -DPTHREADS -D_GNU_SOURCE \
-DGLX_ALIAS_UNSUPPORTED -DGLX_INDIRECT_RENDERING
# -D_GNU_SOURCE - for src/mesa/main ...
# -DGLX_DIRECT_RENDERING - pulls in libdrm stuff in glx/x11
# -DGLX_DIRECT_RENDERING - pulls in libdrm stuff in glx
# -DGLX_USE_APPLEGL - supposed to be used with GLX_DIRECT_RENDERING to use AGL rather than DRM, but doesn't compile
# -DIN_DRI_DRIVER
@@ -49,7 +49,7 @@ GLW_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) -L$(INSTALL_DIR)/$(LIB_DIR) -L$(X
APP_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -L$(INSTALL_DIR)/$(LIB_DIR) -L$(X11_DIR)/$(LIB_DIR) -lX11 -lXmu -lXt -lXi -lm
# omit glw lib for now:
SRC_DIRS = glsl glx/x11 mesa gallium glu glut/glx glew
SRC_DIRS = glsl glx mesa gallium glu glut/glx glew
GLU_DIRS = sgi
DRIVER_DIRS = osmesa
#DRIVER_DIRS = dri

View File

@@ -41,7 +41,7 @@ GLW_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -L/usr/local/lib -lGL -lXt -lX11
# Directories
SRC_DIRS = glx/x11 gallium mesa glu glut/glx glew glw
SRC_DIRS = glx gallium mesa glu glut/glx glew glw
DRIVER_DIRS = dri
PROGRAM_DIRS =
WINDOW_SYSTEM=dri

View File

@@ -51,7 +51,7 @@ GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
# Directories
SRC_DIRS := glx/x11 egl $(SRC_DIRS)
SRC_DIRS := glx egl $(SRC_DIRS)
PROGRAM_DIRS := egl $(PROGRAM_DIRS)
# EGL directories

View File

@@ -47,7 +47,7 @@ DRI_LIB_DEPS = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lm -lpthread -ldl \
$(LIBDRM_LIB) $(shell pkg-config --libs xcb) $(shell pkg-config --libs x11-xcb) $(shell pkg-config --libs xcb-glx)
SRC_DIRS = glx/x11 gallium mesa glu glut/glx glew glw
SRC_DIRS = glx gallium mesa glu glut/glx glew glw
PROGRAM_DIRS = xdemos
DRIVER_DIRS = dri

View File

@@ -47,7 +47,7 @@ GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lm -lpthread -ldl
# Directories
SRC_DIRS = glx/x11 glu glut/glx glew glw
SRC_DIRS = glx glu glut/glx glew glw
DRIVER_DIRS =
PROGRAM_DIRS =
WINDOW_SYSTEM=dri

View File

@@ -445,7 +445,7 @@ xlib)
GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS xlib"
;;
dri)
SRC_DIRS="$SRC_DIRS glx/x11"
SRC_DIRS="$SRC_DIRS glx"
DRIVER_DIRS="dri"
WINDOW_SYSTEM="dri"
GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS drm"

View File

@@ -309,7 +309,6 @@ surfaces.</p>
<li>Pass the conformance tests</li>
<li>Better automatic driver selection: <code>EGL_DISPLAY</code> loads all
drivers and might eat too much memory.</li>
<li>Stop using <code>glxinit.c</code> and sources from <code>src/glx/x11/</code></li>
</ul>

View File

@@ -14,12 +14,12 @@ common_OBJECTS = $(common_SOURCES:.c=.o)
x11_INCLUDES = \
-I$(TOP)/src/gallium/drivers \
-I$(TOP)/src/glx/x11 \
-I$(TOP)/src/glx \
-I$(TOP)/src/mesa \
$(shell pkg-config --cflags-only-I libdrm)
x11_SOURCES = $(wildcard x11/*.c) \
$(TOP)/src/glx/x11/dri2.c
$(TOP)/src/glx/dri2.c
x11_OBJECTS = $(x11_SOURCES:.c=.o)

View File

@@ -1,6 +1,6 @@
/**
* GLX initialization. Code based on glxext.c, glx_query.c, and
* glcontextmodes.c under src/glx/x11/. The major difference is that DRI
* glcontextmodes.c under src/glx/. The major difference is that DRI
* related code is stripped out.
*
* If the maintenance of this file takes too much time, we should consider

View File

@@ -1,12 +1,97 @@
TOP = ../..
TOP = ../../..
include $(TOP)/configs/current
EXTRA_DEFINES = -DXF86VIDMODE -D_REENTRANT \
-DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\"
default:
cd mini && $(MAKE)
SOURCES = \
glcontextmodes.c \
clientattrib.c \
compsize.c \
eval.c \
glxcmds.c \
glxcurrent.c \
glxext.c \
glxextensions.c \
indirect.c \
indirect_init.c \
indirect_size.c \
indirect_window_pos.c \
indirect_texture_compression.c \
indirect_transpose_matrix.c \
indirect_vertex_array.c \
indirect_vertex_program.c \
pixel.c \
pixelstore.c \
render2.c \
renderpix.c \
single2.c \
singlepix.c \
vertarr.c \
xfont.c \
glx_pbuffer.c \
glx_query.c \
drisw_glx.c \
dri_common.c \
dri_glx.c \
XF86dri.c \
glxhash.c \
dri2_glx.c \
dri2.c
GLAPI_LIB = $(TOP)/src/mesa/libglapi.a
OBJECTS = $(SOURCES:.c=.o)
INCLUDES = -I. \
-I$(TOP)/include \
-I$(TOP)/include/GL/internal \
-I$(TOP)/src/mesa \
-I$(TOP)/src/mesa/glapi \
$(LIBDRM_CFLAGS) \
$(DRI2PROTO_CFLAGS) \
$(X11_INCLUDES)
##### RULES #####
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(EXTRA_DEFINES) $< -o $@
.S.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(EXTRA_DEFINES) $< -o $@
##### TARGETS #####
default: depend $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
# Make libGL
$(TOP)/$(LIB_DIR)/$(GL_LIB_NAME): $(OBJECTS) $(GLAPI_LIB) Makefile
$(MKLIB) -o $(GL_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-major 1 -minor 2 $(MKLIB_OPTIONS) \
-install $(TOP)/$(LIB_DIR) -id $(INSTALL_LIB_DIR)/lib$(GL_LIB).1.dylib \
$(GL_LIB_DEPS) $(OBJECTS) $(GLAPI_LIB)
$(GLAPI_LIB):
@$(MAKE) -C $(TOP)/src/mesa libglapi.a
depend: $(SOURCES) Makefile
rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(SOURCES)
# Emacs tags
tags:
etags `find . -name \*.[ch]` `find $(TOP)/include`
install: $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
$(MAKE) -C $(TOP)/src/mesa install-libgl
# Remove .o and backup files
clean:
-@cd mini && $(MAKE) clean
-rm -f $(TOP)/$(LIB_DIR)/libGL.so*
-rm -f *.o *~
-rm -f depend depend.bak
-include depend

View File

@@ -1,89 +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
@ $(MKLIB) -o $(GL_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-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)
rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \
> /dev/null
# Emacs tags
tags:
etags `find . -name \*.[ch]` `find ../include`
# Dummy install target
install:
# Remove .o and backup files
clean:
-rm -f drmtest $(TOP)/$(LIB_DIR)/libGL.so*
-rm -f *.o *~
-rm -f depend depend.bak
include depend

View File

@@ -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.

View File

@@ -1,64 +0,0 @@
/**
* \file miniglx/dispatch.c
*
* \brief C-based dispatch of the OpenGL entry points (glAccum(), glBegin(),
* etc).
*
* \author Brian Paul <brian@precisioninsight.com>
*
* \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 */

View File

@@ -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 <kevin@precisioninsight.com>
* \author Brian Paul <brian@precisioninsight.com>
*/
/*
* 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_ */

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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_ */

View File

@@ -1,983 +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.
*/
#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 );
}

View File

@@ -1,97 +0,0 @@
TOP = ../../..
include $(TOP)/configs/current
EXTRA_DEFINES = -DXF86VIDMODE -D_REENTRANT \
-DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\"
SOURCES = \
glcontextmodes.c \
clientattrib.c \
compsize.c \
eval.c \
glxcmds.c \
glxcurrent.c \
glxext.c \
glxextensions.c \
indirect.c \
indirect_init.c \
indirect_size.c \
indirect_window_pos.c \
indirect_texture_compression.c \
indirect_transpose_matrix.c \
indirect_vertex_array.c \
indirect_vertex_program.c \
pixel.c \
pixelstore.c \
render2.c \
renderpix.c \
single2.c \
singlepix.c \
vertarr.c \
xfont.c \
glx_pbuffer.c \
glx_query.c \
drisw_glx.c \
dri_common.c \
dri_glx.c \
XF86dri.c \
glxhash.c \
dri2_glx.c \
dri2.c
GLAPI_LIB = $(TOP)/src/mesa/libglapi.a
OBJECTS = $(SOURCES:.c=.o)
INCLUDES = -I. \
-I$(TOP)/include \
-I$(TOP)/include/GL/internal \
-I$(TOP)/src/mesa \
-I$(TOP)/src/mesa/glapi \
$(LIBDRM_CFLAGS) \
$(DRI2PROTO_CFLAGS) \
$(X11_INCLUDES)
##### RULES #####
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(EXTRA_DEFINES) $< -o $@
.S.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(EXTRA_DEFINES) $< -o $@
##### TARGETS #####
default: depend $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
# Make libGL
$(TOP)/$(LIB_DIR)/$(GL_LIB_NAME): $(OBJECTS) $(GLAPI_LIB) Makefile
$(MKLIB) -o $(GL_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-major 1 -minor 2 $(MKLIB_OPTIONS) \
-install $(TOP)/$(LIB_DIR) -id $(INSTALL_LIB_DIR)/lib$(GL_LIB).1.dylib \
$(GL_LIB_DEPS) $(OBJECTS) $(GLAPI_LIB)
$(GLAPI_LIB):
@$(MAKE) -C $(TOP)/src/mesa libglapi.a
depend: $(SOURCES) Makefile
rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(SOURCES)
# Emacs tags
tags:
etags `find . -name \*.[ch]` `find $(TOP)/include`
install: $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
$(MAKE) -C $(TOP)/src/mesa install-libgl
# Remove .o and backup files
clean:
-rm -f $(TOP)/$(LIB_DIR)/libGL.so*
-rm -f *.o *~
-rm -f depend depend.bak
-include depend

View File

@@ -13,11 +13,11 @@ OUTPUTS = glprocs.h glapitemp.h glapioffsets.h glapitable.h glapidispatch.h \
../x86/glapi_x86.S \
../x86-64/glapi_x86-64.S \
../sparc/glapi_sparc.S \
../../glx/x11/indirect.c \
../../glx/x11/indirect.h \
../../glx/x11/indirect_init.c \
../../glx/x11/indirect_size.h \
../../glx/x11/indirect_size.c
../../glx/indirect.c \
../../glx/indirect.h \
../../glx/indirect_init.c \
../../glx/indirect_size.h \
../../glx/indirect_size.c
GLX_DIR = $(XORG_BASE)/glx
@@ -110,20 +110,20 @@ glapidispatch.h $(GLX_DIR)/glapidispatch.h: gl_table.py $(COMMON)
../sparc/glapi_sparc.S: gl_SPARC_asm.py $(COMMON)
$(PYTHON2) $(PYTHON_FLAGS) $< > $@
../../glx/x11/indirect.c: glX_proto_send.py $(COMMON_GLX)
../../glx/indirect.c: glX_proto_send.py $(COMMON_GLX)
$(PYTHON2) $(PYTHON_FLAGS) $< -m proto | $(INDENT) $(INDENT_FLAGS) > $@
../../glx/x11/indirect.h: glX_proto_send.py $(COMMON_GLX)
../../glx/indirect.h: glX_proto_send.py $(COMMON_GLX)
$(PYTHON2) $(PYTHON_FLAGS) $< -m init_h > $@
../../glx/x11/indirect_init.c: glX_proto_send.py $(COMMON_GLX)
../../glx/indirect_init.c: glX_proto_send.py $(COMMON_GLX)
$(PYTHON2) $(PYTHON_FLAGS) $< -m init_c > $@
../../glx/x11/indirect_size.h $(GLX_DIR)/indirect_size.h: glX_proto_size.py $(COMMON_GLX)
../../glx/indirect_size.h $(GLX_DIR)/indirect_size.h: glX_proto_size.py $(COMMON_GLX)
$(PYTHON2) $(PYTHON_FLAGS) $< -m size_h --only-set -h _INDIRECT_SIZE_H_ \
| $(INDENT) $(INDENT_FLAGS) > $@
../../glx/x11/indirect_size.c: glX_proto_size.py $(COMMON_GLX)
../../glx/indirect_size.c: glX_proto_size.py $(COMMON_GLX)
$(PYTHON2) $(PYTHON_FLAGS) $< -m size_c --only-set \
| $(INDENT) $(INDENT_FLAGS) > $@

View File

@@ -32,7 +32,7 @@
*
* \note
* This file is also used to build the client-side libGL that loads DRI-based
* device drivers. At build-time it is symlinked to src/glx/x11.
* device drivers. At build-time it is symlinked to src/glx.
*
* \author Brian Paul <brian@precisioninsight.com>
*/