Retire miniglx and move the actual glx code up to src/glx
This commit is contained in:
6
Makefile
6
Makefile
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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>
|
||||
|
||||
|
@@ -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)
|
||||
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
@@ -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.
|
||||
|
||||
|
||||
|
@@ -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 */
|
@@ -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_ */
|
@@ -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
@@ -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_ */
|
@@ -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 );
|
||||
}
|
@@ -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
|
@@ -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) > $@
|
||||
|
||||
|
@@ -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>
|
||||
*/
|
||||
|
Reference in New Issue
Block a user