/*1* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)2* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sublicense,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice including the dates of first publication and12* either this permission notice or a reference to13* http://oss.sgi.com/projects/FreeB/14* shall be included in all copies or substantial portions of the Software.15*16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS17* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,18* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL19* SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,20* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF21* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE22* SOFTWARE.23*24* Except as contained in this notice, the name of Silicon Graphics, Inc.25* shall not be used in advertising or otherwise to promote the sale, use or26* other dealings in this Software without prior written authorization from27* Silicon Graphics, Inc.28*/2930/**31* \file glxclient.h32* Direct rendering support added by Precision Insight, Inc.33*34* \author Kevin E. Martin <[email protected]>35*/3637#ifndef _GLX_client_h_38#define _GLX_client_h_39#include <X11/Xproto.h>40#include <X11/Xlibint.h>41#include <X11/Xfuncproto.h>42#include <X11/extensions/extutil.h>43#define GLX_GLXEXT_PROTOTYPES44#include <GL/glx.h>45#include <GL/glxext.h>46#include <string.h>47#include <stdlib.h>48#include <stdio.h>49#include <stdint.h>50#include <pthread.h>51#include "GL/glxproto.h"52#include "glxconfig.h"53#include "glxhash.h"54#include "util/macros.h"55#include "util/u_thread.h"56#include "loader.h"57#include "glxextensions.h"5859#if defined(USE_LIBGLVND)60#define _GLX_PUBLIC _X_HIDDEN61#else62#define _GLX_PUBLIC _X_EXPORT63#endif6465#ifdef __cplusplus66extern "C" {67#endif6869extern void glx_message(int level, const char *f, ...) PRINTFLIKE(2, 3);7071#define DebugMessageF(...) glx_message(_LOADER_DEBUG, __VA_ARGS__)72#define InfoMessageF(...) glx_message(_LOADER_INFO, __VA_ARGS__)73#define ErrorMessageF(...) glx_message(_LOADER_WARNING, __VA_ARGS__)74#define CriticalErrorMessageF(...) glx_message(_LOADER_FATAL, __VA_ARGS__)757677#define GLX_MAJOR_VERSION 1 /* current version numbers */78#define GLX_MINOR_VERSION 47980struct glx_display;81struct glx_context;8283/************************************************************************/8485#ifdef GLX_DIRECT_RENDERING8687extern void DRI_glXUseXFont(struct glx_context *ctx,88Font font, int first, int count, int listbase);8990#endif9192#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)9394/**95* Display dependent methods. This structure is initialized during the96* \c driCreateDisplay call.97*/98typedef struct __GLXDRIdisplayRec __GLXDRIdisplay;99typedef struct __GLXDRIscreenRec __GLXDRIscreen;100typedef struct __GLXDRIdrawableRec __GLXDRIdrawable;101102struct __GLXDRIdisplayRec103{104/**105* Method to destroy the private DRI display data.106*/107void (*destroyDisplay) (__GLXDRIdisplay * display);108109struct glx_screen *(*createScreen)(int screen, struct glx_display * priv);110};111112struct __GLXDRIscreenRec {113114void (*destroyScreen)(struct glx_screen *psc);115116__GLXDRIdrawable *(*createDrawable)(struct glx_screen *psc,117XID drawable,118GLXDrawable glxDrawable,119struct glx_config *config);120121int64_t (*swapBuffers)(__GLXDRIdrawable *pdraw, int64_t target_msc,122int64_t divisor, int64_t remainder, Bool flush);123void (*copySubBuffer)(__GLXDRIdrawable *pdraw,124int x, int y, int width, int height, Bool flush);125int (*getDrawableMSC)(struct glx_screen *psc, __GLXDRIdrawable *pdraw,126int64_t *ust, int64_t *msc, int64_t *sbc);127int (*waitForMSC)(__GLXDRIdrawable *pdraw, int64_t target_msc,128int64_t divisor, int64_t remainder, int64_t *ust,129int64_t *msc, int64_t *sbc);130int (*waitForSBC)(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,131int64_t *msc, int64_t *sbc);132int (*setSwapInterval)(__GLXDRIdrawable *pdraw, int interval);133int (*getSwapInterval)(__GLXDRIdrawable *pdraw);134int (*getBufferAge)(__GLXDRIdrawable *pdraw);135void (*bindTexImage)(__GLXDRIdrawable *pdraw, int buffer, const int *attribs);136void (*releaseTexImage)(__GLXDRIdrawable *pdraw, int buffer);137};138139struct __GLXDRIdrawableRec140{141void (*destroyDrawable) (__GLXDRIdrawable * drawable);142143XID xDrawable;144XID drawable;145struct glx_screen *psc;146GLenum textureTarget;147GLenum textureFormat; /* EXT_texture_from_pixmap support */148unsigned long eventMask;149int refcount;150};151152/*153** Function to create and DRI display data and initialize the display154** dependent methods.155*/156extern __GLXDRIdisplay *driswCreateDisplay(Display * dpy);157extern __GLXDRIdisplay *dri2CreateDisplay(Display * dpy);158extern __GLXDRIdisplay *dri3_create_display(Display * dpy);159extern __GLXDRIdisplay *driwindowsCreateDisplay(Display * dpy);160161/*162**163*/164extern void dri2InvalidateBuffers(Display *dpy, XID drawable);165extern unsigned dri2GetSwapEventType(Display *dpy, XID drawable);166167/*168** Functions to obtain driver configuration information from a direct169** rendering client application170*/171extern const char *glXGetScreenDriver(Display * dpy, int scrNum);172173extern const char *glXGetDriverConfig(const char *driverName);174175#endif176177/************************************************************************/178179#define __GL_CLIENT_ATTRIB_STACK_DEPTH 16180181typedef struct __GLXpixelStoreModeRec182{183GLboolean swapEndian;184GLboolean lsbFirst;185GLuint rowLength;186GLuint imageHeight;187GLuint imageDepth;188GLuint skipRows;189GLuint skipPixels;190GLuint skipImages;191GLuint alignment;192} __GLXpixelStoreMode;193194195typedef struct __GLXattributeRec196{197GLuint mask;198199/**200* Pixel storage state. Most of the pixel store mode state is kept201* here and used by the client code to manage the packing and202* unpacking of data sent to/received from the server.203*/204__GLXpixelStoreMode storePack, storeUnpack;205206/**207* Is EXT_vertex_array / GL 1.1 DrawArrays protocol specifically208* disabled?209*/210GLboolean NoDrawArraysProtocol;211212/**213* Vertex Array storage state. The vertex array component214* state is stored here and is used to manage the packing of215* DrawArrays data sent to the server.216*/217struct array_state_vector *array_state;218} __GLXattribute;219220typedef struct __GLXattributeMachineRec221{222__GLXattribute *stack[__GL_CLIENT_ATTRIB_STACK_DEPTH];223__GLXattribute **stackPointer;224} __GLXattributeMachine;225226struct mesa_glinterop_device_info;227struct mesa_glinterop_export_in;228struct mesa_glinterop_export_out;229230struct glx_context_vtable {231void (*destroy)(struct glx_context *ctx);232int (*bind)(struct glx_context *context, struct glx_context *old,233GLXDrawable draw, GLXDrawable read);234void (*unbind)(struct glx_context *context, struct glx_context *new_ctx);235void (*wait_gl)(struct glx_context *ctx);236void (*wait_x)(struct glx_context *ctx);237int (*interop_query_device_info)(struct glx_context *ctx,238struct mesa_glinterop_device_info *out);239int (*interop_export_object)(struct glx_context *ctx,240struct mesa_glinterop_export_in *in,241struct mesa_glinterop_export_out *out);242};243244/**245* GLX state that needs to be kept on the client. One of these records246* exist for each context that has been made current by this client.247*/248struct glx_context249{250/**251* \name Drawing command buffer.252*253* Drawing commands are packed into this buffer before being sent as a254* single GLX protocol request. The buffer is sent when it overflows or255* is flushed by \c __glXFlushRenderBuffer. \c pc is the next location256* in the buffer to be filled. \c limit is described above in the buffer257* slop discussion.258*259* Commands that require large amounts of data to be transfered will260* also use this buffer to hold a header that describes the large261* command.262*263* These must be the first 6 fields since they are static initialized264* in the dummy context in glxext.c265*/266/*@{ */267GLubyte *buf;268GLubyte *pc;269GLubyte *limit;270GLubyte *bufEnd;271GLint bufSize;272/*@} */273274const struct glx_context_vtable *vtable;275276/**277* The XID of this rendering context. When the context is created a278* new XID is allocated. This is set to None when the context is279* destroyed but is still current to some thread. In this case the280* context will be freed on next MakeCurrent.281*/282XID xid;283284/**285* The XID of the \c shareList context.286*/287XID share_xid;288289/**290* Screen number.291*/292GLint screen;293struct glx_screen *psc;294295/**296* \c GL_TRUE if the context was created with ImportContext, which297* means the server-side context was created by another X client.298*/299GLboolean imported;300301/**302* The context tag returned by MakeCurrent when this context is made303* current. This tag is used to identify the context that a thread has304* current so that proper server context management can be done. It is305* used for all context specific commands (i.e., \c Render, \c RenderLarge,306* \c WaitX, \c WaitGL, \c UseXFont, and \c MakeCurrent (for the old307* context)).308*/309GLXContextTag currentContextTag;310311/**312* \name Rendering mode313*314* The rendering mode is kept on the client as well as the server.315* When \c glRenderMode is called, the buffer associated with the316* previous rendering mode (feedback or select) is filled.317*/318/*@{ */319GLenum renderMode;320GLfloat *feedbackBuf;321GLuint *selectBuf;322/*@} */323324/**325* Client side attribs.326*/327__GLXattributeMachine attributes;328329/**330* Client side error code. This is set when client side gl API331* routines need to set an error because of a bad enumerant or332* running out of memory, etc.333*/334GLenum error;335336/**337* Whether this context does direct rendering.338*/339Bool isDirect;340341#if defined(GLX_DIRECT_RENDERING) && defined(GLX_USE_APPLEGL)342void *driContext;343#endif344345/**346* \c dpy of current display for this context. Will be \c NULL if not347* current to any display, or if this is the "dummy context".348*/349Display *currentDpy;350351/**352* The current drawable for this context. Will be None if this353* context is not current to any drawable. currentReadable is below.354*/355GLXDrawable currentDrawable;356357/**358* \name GL Constant Strings359*360* Constant strings that describe the server implementation361* These pertain to GL attributes, not to be confused with362* GLX versioning attributes.363*/364/*@{ */365GLubyte *vendor;366GLubyte *renderer;367GLubyte *version;368GLubyte *extensions;369/*@} */370371/**372* Maximum small render command size. This is the smaller of 64k and373* the size of the above buffer.374*/375GLint maxSmallRenderCommandSize;376377/**378* Major opcode for the extension. Copied here so a lookup isn't379* needed.380*/381GLint majorOpcode;382383/**384* Pointer to the config used to create this context.385*/386struct glx_config *config;387388/**389* The current read-drawable for this context. Will be None if this390* context is not current to any drawable.391*392* \since Internal API version 20030606.393*/394GLXDrawable currentReadable;395396/**397* Pointer to client-state data that is private to libGL. This is only398* used for indirect rendering contexts.399*400* No internal API version change was made for this change. Client-side401* drivers should NEVER use this data or even care that it exists.402*/403void *client_state_private;404405/**406* Stored value for \c glXQueryContext attribute \c GLX_RENDER_TYPE.407*/408int renderType;409410/**411* \name Raw server GL version412*413* True core GL version supported by the server. This is the raw value414* returned by the server, and it may not reflect what is actually415* supported (or reported) by the client-side library.416*/417/*@{ */418int server_major; /**< Major version number. */419int server_minor; /**< Minor version number. */420/*@} */421422/**423* Number of threads we're currently current in.424*/425unsigned long thread_refcount;426427/**428* GLX_ARB_create_context_no_error setting for this context.429* This needs to be kept here to enforce shared context rules.430*/431Bool noError;432433char gl_extension_bits[__GL_EXT_BYTES];434};435436extern Bool437glx_context_init(struct glx_context *gc,438struct glx_screen *psc, struct glx_config *fbconfig);439440#define __glXSetError(gc,code) \441if (!(gc)->error) { \442(gc)->error = code; \443}444445extern void __glFreeAttributeState(struct glx_context *);446447/************************************************************************/448449/**450* The size of the largest drawing command known to the implementation451* that will use the GLXRender GLX command. In this case it is452* \c glPolygonStipple.453*/454#define __GLX_MAX_SMALL_RENDER_CMD_SIZE 156455456/**457* To keep the implementation fast, the code uses a "limit" pointer458* to determine when the drawing command buffer is too full to hold459* another fixed size command. This constant defines the amount of460* space that must always be available in the drawing command buffer461* at all times for the implementation to work. It is important that462* the number be just large enough, but not so large as to reduce the463* efficacy of the buffer. The "+32" is just to keep the code working464* in case somebody counts wrong.465*/466#define __GLX_BUFFER_LIMIT_SIZE (__GLX_MAX_SMALL_RENDER_CMD_SIZE + 32)467468/**469* This implementation uses a smaller threshold for switching470* to the RenderLarge protocol than the protcol requires so that471* large copies don't occur.472*/473#define __GLX_RENDER_CMD_SIZE_LIMIT 4096474475/**476* One of these records exists per screen of the display. It contains477* a pointer to the config data for that screen (if the screen supports GL).478*/479struct glx_screen_vtable {480struct glx_context *(*create_context)(struct glx_screen *psc,481struct glx_config *config,482struct glx_context *shareList,483int renderType);484485struct glx_context *(*create_context_attribs)(struct glx_screen *psc,486struct glx_config *config,487struct glx_context *shareList,488unsigned num_attrib,489const uint32_t *attribs,490unsigned *error);491int (*query_renderer_integer)(struct glx_screen *psc,492int attribute,493unsigned int *value);494int (*query_renderer_string)(struct glx_screen *psc,495int attribute,496const char **value);497498char *(*get_driver_name)(struct glx_screen *psc);499};500501struct glx_screen502{503const struct glx_screen_vtable *vtable;504505/**506* \name Storage for the GLX vendor, version, and extension strings507*/508/*@{ */509const char *serverGLXexts;510const char *serverGLXvendor;511const char *serverGLXversion;512/*@} */513514/**515* GLX extension string to be reported to applications. This is the516* set of extensions that the application can actually use.517*/518char *effectiveGLXexts;519520struct glx_display *display;521522Display *dpy;523int scr;524525#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)526/**527* Per screen direct rendering interface functions and data.528*/529__GLXDRIscreen *driScreen;530#endif531532/**533* Linked list of glx visuals and fbconfigs for this screen.534*/535struct glx_config *visuals, *configs;536537/**538* Per-screen dynamic GLX extension tracking. The \c direct_support539* field only contains enough bits for 64 extensions. Should libGL540* ever need to track more than 64 GLX extensions, we can safely grow541* this field. The \c struct glx_screen structure is not used outside542* libGL.543*/544/*@{ */545unsigned char direct_support[__GLX_EXT_BYTES];546GLboolean ext_list_first_time;547548unsigned char glx_force_enabled[__GLX_EXT_BYTES];549unsigned char glx_force_disabled[__GLX_EXT_BYTES];550551unsigned char gl_force_enabled[__GL_EXT_BYTES];552unsigned char gl_force_disabled[__GL_EXT_BYTES];553/*@} */554555};556557/**558* Per display private data. One of these records exists for each display559* that is using the OpenGL (GLX) extension.560*/561struct glx_display562{563struct glx_display *next;564565/* The extension protocol codes */566XExtCodes codes;567568/**569* Back pointer to the display570*/571Display *dpy;572573/**574* \name Minor Version575*576* Minor version returned by the server during initialization. The major577* version is asserted to be 1 during extension setup.578*/579/*@{ */580int minorVersion;581/*@} */582583/**584* Configurations of visuals for all screens on this display.585* Also, per screen data which now includes the server \c GLX_EXTENSION586* string.587*/588struct glx_screen **screens;589590__glxHashTable *glXDrawHash;591592#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)593__glxHashTable *drawHash;594595/**596* Per display direct rendering interface functions and data.597*/598__GLXDRIdisplay *driswDisplay;599__GLXDRIdisplay *dri2Display;600__GLXDRIdisplay *dri3Display;601#endif602#ifdef GLX_USE_WINDOWSGL603__GLXDRIdisplay *windowsdriDisplay;604#endif605};606607struct glx_drawable {608XID xDrawable;609XID drawable;610611uint32_t lastEventSbc;612int64_t eventSbcWrap;613};614615extern int616glx_screen_init(struct glx_screen *psc,617int screen, struct glx_display * priv);618extern void619glx_screen_cleanup(struct glx_screen *psc);620621#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)622extern __GLXDRIdrawable *623dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id);624#endif625626extern GLubyte *__glXFlushRenderBuffer(struct glx_context *, GLubyte *);627628extern void __glXSendLargeChunk(struct glx_context * gc, GLint requestNumber,629GLint totalRequests,630const GLvoid * data, GLint dataLen);631632extern void __glXSendLargeCommand(struct glx_context *, const GLvoid *, GLint,633const GLvoid *, GLint);634635/* Initialize the GLX extension for dpy */636extern struct glx_display *__glXInitialize(Display *);637638/************************************************************************/639640extern int __glXDebug;641642/* This is per-thread storage in an MT environment */643644extern void __glXSetCurrentContext(struct glx_context * c);645646# if defined( USE_ELF_TLS )647648extern __THREAD_INITIAL_EXEC void *__glX_tls_Context;649650# define __glXGetCurrentContext() __glX_tls_Context651652# else653654extern struct glx_context *__glXGetCurrentContext(void);655656# endif /* defined( USE_ELF_TLS ) */657658extern void __glXSetCurrentContextNull(void);659660661/*662** Global lock for all threads in this address space using the GLX663** extension664*/665extern pthread_mutex_t __glXmutex;666#define __glXLock() pthread_mutex_lock(&__glXmutex)667#define __glXUnlock() pthread_mutex_unlock(&__glXmutex)668669/*670** Setup for a command. Initialize the extension for dpy if necessary.671*/672extern CARD8 __glXSetupForCommand(Display * dpy);673674/************************************************************************/675676/*677** Data conversion and packing support.678*/679680extern const GLuint __glXDefaultPixelStore[9];681682/* Send an image to the server using RenderLarge. */683extern void __glXSendLargeImage(struct glx_context * gc, GLint compsize, GLint dim,684GLint width, GLint height, GLint depth,685GLenum format, GLenum type,686const GLvoid * src, GLubyte * pc,687GLubyte * modes);688689/* Return the size, in bytes, of some pixel data */690extern GLint __glImageSize(GLint, GLint, GLint, GLenum, GLenum, GLenum);691692/* Return the number of elements per group of a specified format*/693extern GLint __glElementsPerGroup(GLenum format, GLenum type);694695/* Return the number of bytes per element, based on the element type (other696** than GL_BITMAP).697*/698extern GLint __glBytesPerElement(GLenum type);699700/*701** Fill the transport buffer with the data from the users buffer,702** applying some of the pixel store modes (unpack modes) to the data703** first. As a side effect of this call, the "modes" field is704** updated to contain the modes needed by the server to decode the705** sent data.706*/707extern void __glFillImage(struct glx_context *, GLint, GLint, GLint, GLint, GLenum,708GLenum, const GLvoid *, GLubyte *, GLubyte *);709710/* Copy map data with a stride into a packed buffer */711extern void __glFillMap1f(GLint, GLint, GLint, const GLfloat *, GLubyte *);712extern void __glFillMap1d(GLint, GLint, GLint, const GLdouble *, GLubyte *);713extern void __glFillMap2f(GLint, GLint, GLint, GLint, GLint,714const GLfloat *, GLfloat *);715extern void __glFillMap2d(GLint, GLint, GLint, GLint, GLint,716const GLdouble *, GLdouble *);717718/*719** Empty an image out of the reply buffer into the clients memory applying720** the pack modes to pack back into the clients requested format.721*/722extern void __glEmptyImage(struct glx_context *, GLint, GLint, GLint, GLint, GLenum,723GLenum, const GLubyte *, GLvoid *);724725726/*727** Allocate and Initialize Vertex Array client state, and free.728*/729extern void __glXInitVertexArrayState(struct glx_context *);730extern void __glXFreeVertexArrayState(struct glx_context *);731732_X_HIDDEN void733__glX_send_client_info(struct glx_display *glx_dpy);734735/************************************************************************/736737/*738** Declarations that should be in Xlib739*/740#ifdef __GL_USE_OUR_PROTOTYPES741extern void _XFlush(Display *);742extern Status _XReply(Display *, xReply *, int, Bool);743extern void _XRead(Display *, void *, long);744extern void _XSend(Display *, const void *, long);745#endif746747748extern void __glXInitializeVisualConfigFromTags(struct glx_config * config,749int count, const INT32 * bp,750Bool tagged_only,751Bool fbconfig_style_tags);752753extern char *__glXQueryServerString(Display *dpy, CARD32 screen, CARD32 name);754extern char *__glXGetString(Display *dpy, CARD32 screen, CARD32 name);755756extern GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable,757int32_t * numerator,758int32_t * denominator);759760#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)761extern GLboolean762__glxGetMscRate(struct glx_screen *psc,763int32_t * numerator, int32_t * denominator);764765/* So that dri2.c:DRI2WireToEvent() can access766* glx_info->codes->first_event */767XExtDisplayInfo *__glXFindDisplay (Display *dpy);768769extern void770GarbageCollectDRIDrawables(struct glx_screen *psc);771772extern __GLXDRIdrawable *773GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable);774#endif775776extern struct glx_screen *GetGLXScreenConfigs(Display * dpy, int scrn);777778#ifdef GLX_USE_APPLEGL779extern struct glx_screen *780applegl_create_screen(int screen, struct glx_display * priv);781782extern struct glx_context *783applegl_create_context(struct glx_screen *psc,784struct glx_config *mode,785struct glx_context *shareList, int renderType);786787extern int788applegl_create_display(struct glx_display *display);789790extern void *791applegl_get_proc_address(const char *symbol);792#endif793794extern Bool validate_renderType_against_config(const struct glx_config *config,795int renderType);796797798extern struct glx_drawable *GetGLXDrawable(Display *dpy, GLXDrawable drawable);799extern int InitGLXDrawable(Display *dpy, struct glx_drawable *glxDraw,800XID xDrawable, GLXDrawable drawable);801extern void DestroyGLXDrawable(Display *dpy, GLXDrawable drawable);802803extern struct glx_context dummyContext;804805extern struct glx_screen *806indirect_create_screen(int screen, struct glx_display * priv);807extern struct glx_context *808indirect_create_context(struct glx_screen *psc,809struct glx_config *mode,810struct glx_context *shareList, int renderType);811extern struct glx_context *812indirect_create_context_attribs(struct glx_screen *base,813struct glx_config *config_base,814struct glx_context *shareList,815unsigned num_attribs,816const uint32_t *attribs,817unsigned *error);818819820extern int __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,821int attribute, unsigned int *value);822823#ifdef __cplusplus824}825#endif826827#endif /* !__GLX_client_h__ */828829830