OpenGL Distilled

8.3. Linux

Linux uses GLX, the OpenGL extension to the X Window System, to provide platform-specific support for OpenGL. For documentation on GLX, see OpenGL Graphics with the X Window System (Version 1.3), edited by Paula Womack and Jon Leech, available from the official OpenGL Web site, http://www.opengl.org. Note, however, that most Linux systems use Mesa, which provides GLX version 1.4 support.[1]

[1] As of this printing, the GLX version 1.4 specification hasn't been formally approved by the OpenGL ARB. Because Linux distributions almost universally provide Mesa, however, GLX version 1.4 is widely available.

To run an OpenGL program on a Linux system, the X Windows server must support the GLX extension. If you purchase a Linux system with an OpenGL graphics card, the system manufacturer preconfigures X to load GLX. Run the glxinfo client to confirm that your X server supports GLX.

GLX allows OpenGL clients to render onscreen using GLXWindows. It also allows two forms of offscreen rendering: GLXPixmaps and GLXPbuffers. Collectively, GLXWindows, GLXPixmaps, and GLXPbuffers are known as GLXDrawables.

Typically, GLXPixmaps don't use hardware acceleration. For hardware-accelerated offscreen rendering, use GLXPbuffers. This section focuses primarily on rendering to a window, though most of the concepts also apply to offscreen rendering. For more information on offscreen rendering, refer to OpenGL Graphics with the X Window System.

8.3.1. Creating Contexts

To create a rendering context that renders to a window, perform the following steps:

1.

Choose a suitable GLXFBConfig, which describes the OpenGL render buffer characteristics.

2.

Create a rendering context from the GLXFBConfig.

3.

Create a GLXWindow, the GLX equivalent of the X Window object.

To obtain a GLXFBConfig, call glXChooseFBConfig().

GLXFBConfig* glXChooseFBConfig( Display* dpy, int screen, const int*  attrib_list, int* nelements );

Obtains a list of GLXFBConfigs that meet the specified criteria. dpy and screen specify the X Windows server display.

Each pair of elements in the attrib_list array specifies a framebuffer attribute and its desired value. The element pair GLX_DOUBLEBUFFER, True, for example, causes glXChooseFBConfig() to return only double-buffered GLXFBConfigs. glXChooseFBConfig() doesn't always use exact matching, however. For a list of attributes and their matching criteria, see Table 3.4 in OpenGL Graphics with the X Window System.

glXChooseFBConfig() returns an array of GLXFBConfigs that match the attributes specified in attrib_list. The number of GLXFBConfigs in the array is returned in nelements.

glXChooseFBConfig() returns NULL if no GLXFBConfigs match the list of requirements in attrib_list.

Use glXChooseFBConfig() to obtain available GLXFBConfigs that meet or exceed your application requirements for rendering buffer characteristics. The following code, for example, obtains a list of GLXFBConfigs for use with double-buffered RGBA rendering to a window. The GLXFBConfigs will have at least 24 color buffer bits and at least 24 depth buffer bits.

const int attributes[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DOUBLEBUFFER, True, GLX_BUFFER_SIZE, 24, GLX_DEPTH_SIZE, 24, None }; int nElements; GLXFBConfig* fbConfigs = glXChooseFBConfig( dpy, screen, attributes, &nElements );

GLXFBConfig is an opaque data type. To examine all attributes of a GLXFBConfig, use glXGetFBConfigAttrib(). For more information, see OpenGL Graphics with the X Window System.

Use XFree() to free the GLXFBConfig array returned by glXChooseFBConfig().

After identifying a GLXFBConfig that meets your application's requirements, create a rendering context with a call to glXCreateNewContext().

GLXContext glXCreateNewContext( Display* dpy, GLXFBConfig config,  int render_type, GLXContext share_list, Bool direct );

Creates an OpenGL rendering context. dpy identifies the X Windows display server. config is a GLXFBConfig, as obtained with glXChoose-FBConfig(). Pass GLX_RGBA_TYPE for render_type.

If share_list isn't NULL, it specifies a rendering context to share OpenGL objects with. The share_list context will store display lists, buffer objects, and texture objects that the newly created context creates and uses. If share_list is NULL, the newly created context stores its own OpenGL objects.

Use direct to specify whether glXCreateNewContext() should return a direct or indirect rendering context. Passing true for direct requests a rendering context that bypasses the X server, allowing the client application to control the graphics hardware directly. If the server can't create a direct rendering context, glXCreateNewContext() will return an indirect rendering context, which renders through the X server.

glXCreateNewContext() returns NULL if it fails for any reason.

GLX has the concept of an address space, which determines whether OpenGL objects can be shared between rendering contexts. For more information, see OpenGL Graphics with the X Window System.

If the GLXFBConfig supports rendering to a window (that is, its GLX_DRAWABLE_TYPE attribute has the GLX_WINDOW_BIT set), the GLXFBConfig has an associated X visual. Obtain the XVisualInfo struct from the GLXFBConfig with a call to glXGetVisualFromFBConfig().

XVisualInfo* glXGetVisualFromFBConfig( Display* dpy, GLXFBConfig

  config );

Obtains the X visual from a GLXFBConfig. dpy specifies the X Window server, and config specifies the GLXFBConfig to obtain an XVisualInfo struct from. glXGetVisualFromFBConfig() returns NULL if it fails for any reason.

Applications that render to windows use fields from the returned XVisualInfo struct to create a color map and window.

To render to a window, your application needs to create a standard X Window (for example, XCreateWindow()) with the visual info from the GLXFBConfig and then create a GLXWindow. To create a GLXWindow, call glXCreateWindow().

GLXWindow glXCreateWindow( Display* dpy, GLXFBConfig config,  Window win, const int* attrib_list );

Creates a new GLXWindow and returns its XID. dpy specifies the X Windows server, config is a suitable GLXFBConfig, as returned by glXChooseFBConfig(), and win is a Window XID.

attrib_list is reserved for future use. Pass NULL for attrib_list.

glXCreateWindow() returns the XID of a new GLXWindow or NULL if it fails for any reason. Call glXDestroyWindow() to destroy a GLXWindow.

8.3.2. Using Contexts

Before you can render to a window, you need to bind the rendering context to the GLXWindow. To do this, call glXMakeContextCurrent().

Bool glXMakeContextCurrent( Display* dpy, GLXDrawable draw,

  GLXDrawable read, GLXContext ctx );

Makes the specified ctx current to the specified GLXDrawables in the current thread. dpy specifies the X Window server display. draw and read specify the GLXDrawable for OpenGL render and read operations, respectively. Typically, applications pass the same drawable for both parameters. If your application renders to a window, pass the same GLXWindow XID for both draw and read. ctx specifies the rendering context to bind to draw and read.

If glXMakeContextCurrent() succeeds, it returns true. If it fails for any reason, it returns False. There are several reasons why glXMakeContextCurrent() might fail; see Section 3.3.7, "Rendering Contexts," of OpenGL Graphics with the X Window System.

After a successful call to glXMakeContextCurrent(), subsequent OpenGL state commands affect state stored in ctx, rendering commands ultimately appear in draw, and read commands (such as glReadPixels()) obtain pixel data from read.

In GLX, a thread can have only one context current at a time. If the calling thread already has a current context, calling glXMakeContextCurrent() flushes the previous context and makes it noncurrent.

To make ctx noncurrent without binding a new context to draw and read, issue the following command:

glXMakeContextCurrent( dpy, None, None, NULL );

8.3.3. Swapping Buffers

If your context is double buffered (that is, if the GLX_DOUBLEBUFFER attribute of the GLXFBConfig is true), you must swap buffers after rendering a frame to display the contents of the back buffer. To swap buffers, call glXSwapBuffers().

void glXSwapBuffers( Display* dpy, GLXDrawable draw );

Makes the back buffer associated with draw visible. dpy specifies the X Window server display, and draw specifies the GLXDrawable to swap.

After swapping, the GLXDrawable displays the old contents of the back buffer. The contents of the new back buffer are undefined.

If draw is current to a rendering context, glXSwapBuffers() implicitly flushes any buffered commands in that rendering context.

Typically, GLX implementations synchronize buffer swaps to the monitor vertical retrace. GLX doesn't specify vertical retrace synchronization, however. As a result, this behavior may vary from one implementation to the next.

8.3.4. Deleting Contexts

When your application no longer has a use for a rendering context, destroy the rendering context with a call to glXDestroyContext().

void glXDestroyContext( Display* dpy, GLXContext ctx );

Destroys ctx and its associated resources. dpy specifies the X Window server display, and ctx specifies the rendering context to be destroyed.

glXDestroyContext() doesn't destroy the rendering context if it's still current. For this reason, applications typically make the context noncurrent and then destroy it, as in the following code:

glXMakeContextCurrent( dpy, None, None, NULL ); glXDestroyContext( dpy, ctx );

Категории