| |
| |
| |
| Introduction |
| ------------ |
| |
| This document describes the implementation of the XFree86 4.0 libGL.so |
| library defined by the Linux/OpenGL Base specification found at |
| http://reality.sgi.com/opengl/linux/linuxbase.html. |
| |
| The documentation is divided into two sections: |
| User's Guide |
| Driver Developer's Guide |
| |
| Author: Brian Paul (brian@precisioninsight.com) |
| Date: February 2000 |
| |
| |
| |
| User's Guide |
| ------------ |
| |
| Using libGL.so |
| |
| The libGL.so library defines the gl- and glX-prefixed functions needed to |
| run OpenGL programs. OpenGL client applications should link with the |
| -lGL option to use it. |
| |
| libGL.so serves two primary functions: GLX protocol generation for indirect |
| rendering and loading/management of hardware drivers for direct rendering. |
| |
| When libGL.so initializes itself it uses the DRI to determine the |
| appropriate hardware driver for each screen on the local X display. |
| The hardware drivers are expected to be in the /usr/X11R6/lib/modules/dri/ |
| directory. Drivers are named with the convention <name>_dri.so where |
| <name> is a driver such as "radeon", "i965", "nouveau", etc. |
| |
| The LIBGL_DRIVERS_DIR environment variable may be used to specify a |
| different DRI modules directory, overriding /usr/X11R6/lib/modules/dri/. |
| This environment variable is ignored in setuid programs for security |
| reasons. |
| |
| When libGL.so is unable to locate appropriate hardware drivers it will |
| fall back to using indirect GLX rendering. |
| |
| To aid in solving problems, libGL.so will print diagnostic messages to |
| stderr if the LIBGL_DEBUG environment variable is defined. |
| |
| libGL.so is thread safe. The overhead of thread safety for common, |
| single-thread clients is negligible. However, the overhead of thread |
| safety for multi-threaded clients is significant. Each GL API call |
| requires two calls to pthread_get_specific() which can noticeably |
| impact performance. Warning: libGL.so is thread safe but individual |
| DRI drivers may not be. Please consult the documentation for a driver |
| to learn if it is thread safe. |
| |
| |
| |
| Indirect Rendering |
| |
| You can force indirect rendering mode by setting the LIBGL_ALWAYS_INDIRECT |
| environment variable. Hardware acceleration will not be used. |
| |
| |
| |
| libGL.so Extensibility |
| |
| libGL.so is designed to be extended without upgrading. That is, |
| drivers may install new OpenGL extension functions into libGL.so |
| without requiring libGL.so to be replaced. Clients of libGL.so should |
| use the glXGetProcAddressEXT() function to obtain the address of |
| functions by name. For more details of GLX_ARB_get_proc_address see |
| http://oss.sgi.com/projects/ogl-sample/registry/ARB/get_proc_address.spec |
| |
| libGL.so is also designed with flexibility such that it may be used |
| with many generations of hardware drivers to come. |
| |
| |
| |
| |
| Driver Developer's Guide |
| ------------------------ |
| |
| This section describes the requirements to make an XFree86 4.0 |
| libGL.so-compatible hardware driver. It is not intended for end |
| users of libGL.so. |
| |
| |
| XFree86 source files |
| |
| libGL.so is built inside XFree86 with sources found in xc/lib/GL/. |
| Specifically, libGL.so is built from: |
| |
| xc/lib/GL/glx/*.c |
| xc/lib/dri/XF86dri.c |
| xc/lib/dri/dri_glx.c |
| xc/lib/GL/mesa/src/glapi.c |
| xc/lib/GL/mesa/src/glapitemp.h |
| xc/lib/GL/mesa/src/glapitable.h |
| xc/lib/GL/mesa/src/glapioffsets.h |
| xc/lib/GL/mesa/src/glapinoop.c |
| xc/lib/GL/mesa/src/glheader.h |
| xc/lib/GL/mesa/src/glthread.c |
| xc/lib/GL/mesa/src/glthread.h |
| xc/lib/GL/mesa/src/X86/glapi_x86.S |
| xc/lib/GL/mesa/src/X86/assyntax.h |
| |
| Understand that the mesa/src/gl*.[ch] files are not tied to Mesa. They |
| have no dependencies on the rest of Mesa and are designed to be reusable |
| in a number of projects. |
| |
| The glapi_x86.X and assyntax.h files implement x86-optimized dispatch |
| of GL functions. They are not required; C-based dispatch can be used |
| instead, with a slight performance penalty. |
| |
| |
| |
| Driver loading and binding |
| |
| When libGL.so initializes itself (via the __glXInitialize function) a |
| call is made to driCreateDisplay(). This function uses DRI facilities |
| to determine the driver file appropriate for each screen on the local |
| display. Each screen's driver is then opened with dlopen() and asked |
| for its __driCreateScreen() function. The pointers to the __driCreateScreen() |
| functions are kept in an array, indexed by screen number, in the |
| __DRIdisplayRec struct. |
| |
| When a driver's __driCreateScreen() function is called, it must initialize |
| a __DRIscreenRec struct. This struct acts as the root of a tree of |
| function pointers which are called to create and destroy contexts and |
| drawables and perform all the operations needed by the GLX interface. |
| See the xc/lib/GL/glx/glxclient.h file for details. |
| |
| |
| |
| Dynamic Extension Function Registration |
| |
| In order to provide forward compatibility with future drivers, libGL.so |
| allows drivers to register new OpenGL extension functions which weren't |
| known when libGL.so was built. |
| |
| The register_extensions() function in xc/lib/GL/dri/dri_glx.c is called |
| as soon as libGL.so is loaded. This is done with gcc's constructor |
| attribute. This mechanism will likely have to be changed for other compilers. |
| |
| register_extensions() loops over all local displays and screens, determines |
| the DRI driver for each, and calls the driver's __driRegisterExtensions() |
| function, if present. |
| |
| The __driRegisterExtensions() function can add new entrypoints to libGL |
| by calling: |
| |
| GLboolean _glapi_add_entrypoint(const char *funcName, GLuint offset) |
| |
| The parameters are the name of the function (such as "glFoobarEXT") and the |
| offset of the dispatch slot in the API dispatch table. The return value |
| indicates success (GL_TRUE) or failure (GL_FALSE). |
| |
| _glapi_add_entrypoint() will synthesize entrypoint code in assembly |
| language. Assembly languages is required since parameter passing |
| can't be handled correctly using a C-based solution. |
| |
| The address of the new entrypoint is obtained by calling the |
| glXGetProcAddressARB() function. |
| |
| The dispatch offset number MUST be a number allocated by SGI in the same |
| manner in which new GL_* constants are allocated. Using an arbitrary |
| offset number will result in many problems. |
| |
| |
| |
| Dispatch Management |
| |
| When a GL context is made current, the driver must install its dispatch |
| table as the current dispatch table. This is done by calling |
| |
| void _glapi_set_dispatch(struct _glapi_table *dispatch); |
| |
| This will install the named dispatch table for the calling thread. |
| The current dispatch table for a thread can be obtained by calling |
| |
| struct _glapi_table *_glapi_get_dispatch(void); |
| |
| For higher performance in the common single-thread case, the global |
| variable _glapi_Dispatch will point to the current dispatch table. |
| This variable will be NULL when in multi-thread mode. |
| |
| |
| |
| Context Management |
| |
| libGL.so uses the XFree86 xthreads package to manage a thread-specific |
| current context pointer. See __glXGet/SetCurrentContext() in glext.c |
| |
| Drivers may use the _glapi_set/get_context() functions to maintain |
| a private thread-specific context pointer. |
| |