summaryrefslogtreecommitdiff
path: root/src/GLdispatch/GLdispatch.h
blob: 0573bba4cf4fe2d6f71cb7a1082daf8b7e4c4f9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*
 * Copyright (c) 2013, NVIDIA CORPORATION.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and/or associated documentation files (the
 * "Materials"), to deal in the Materials without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Materials, and to
 * permit persons to whom the Materials are furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * unaltered in all copies or substantial portions of the Materials.
 * Any additions, deletions, or changes to the original source files
 * must be clearly indicated in accompanying documentation.
 *
 * If only executable code is distributed, then the accompanying
 * documentation must state that "this software is based in part on the
 * work of the Khronos Group."
 *
 * THE MATERIALS ARE 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 THE AUTHORS OR COPYRIGHT HOLDERS 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
 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 */

#if !defined(__GL_DISPATCH_H__)
#define __GL_DISPATCH_H__

#include "glheader.h"
#include "compiler.h"
#include "glvnd/GLdispatchABI.h"

/*!
 * The current version of the ABI between libGLdispatch and the window system
 * libraries.
 *
 * \see __glDispatchGetABIVersion
 */
#define GLDISPATCH_ABI_VERSION 0

/*!
 * \defgroup gldispatch core GL/GLES dispatch and TLS module
 *
 * GLdispatch is a thin wrapper around Mesa's mapi/glapi dispatch table
 * implementation which does some bookkeeping to simplify dispatch table
 * management. API libraries use this library to retrieve dispatch stubs and fix
 * up the dispatch table at make current time to point to the appropriate vendor
 * library entrypoints.
 */

/* Namespaces for API state */
enum {
    GLDISPATCH_API_GLX,
    GLDISPATCH_API_EGL
};

/*!
 * This opaque structure describes the core GL dispatch table.
 */
typedef struct __GLdispatchTableRec __GLdispatchTable;

typedef void (*__GLdispatchProc)(void);

typedef void *(*__GLgetProcAddressCallback)(const char *procName, void *param);

/**
 * An opaque structure used for internal API state data.
 */
struct __GLdispatchAPIStatePrivateRec;

/*!
 * Generic API state structure. The window system binding API libraries subclass
 * from this structure to track API-library specific current state (e.g.
 * current drawables). There is one API state for each combination of (winsys
 * library, thread that has had a context current). The winsys library is
 * responsible for tracking, allocating, and freeing its API states. Though
 * each thread owns an API state within the winsys library, only one API state
 * may be "current" at a time (the API state of the winsys binding which has
 * a context current). This is done to conserve TLS space.
 */
typedef struct __GLdispatchAPIStateRec {
    /*************************************************************************
     * Winsys-managed variables: fixed for lifetime of state
     *************************************************************************/

    /*!
     * Namespace of the state: either API_GLX or API_EGL
     */
    int tag;

    /**
     * A callback that is called when a thread that has a current context
     * terminates.
     *
     * This is called after libGLdispatch handles its cleanup, so
     * __glDispatchGetCurrentAPIState will return NULL. The API state is passed
     * as a parameter instead.
     *
     * The callback should not call __glDispatchMakeCurrent or
     * __glDispatchLoseCurrent.
     *
     * \param apiState The API state passed to __glDispatchMakeCurrent.
     */
    void (*threadDestroyedCallback)(struct __GLdispatchAPIStateRec *apiState);

    /*************************************************************************
     * GLdispatch-managed variables: Modified by MakeCurrent()
     *************************************************************************/

    /*!
     * Private data for this API state.
     *
     * This structure is assigned in \c __glDispatchMakeCurrent, and freed in
     * \c __glDispatchLoseCurrent.
     *
     * The value of this pointer, if any, is an internal detail of
     * libGLdispatch. The window system library should just ignore it.
     */
    struct __GLdispatchAPIStatePrivateRec *priv;
} __GLdispatchAPIState;

typedef struct __GLdispatchPatchCallbacksRec {
    /*!
     * Checks to see if the vendor library supports patching the given stub
     * type and size.
     *
     * \param type The type of entrypoints. This will be a one of the
     * __GLDISPATCH_STUB_* values.
     * \param stubSize The maximum size of the stub that the vendor library can
     * write, in bytes.
     * \param lookupStubOffset A callback into libglvnd to look up the address
     * of each entrypoint.
     */
    GLboolean (* isPatchSupported)(int type, int stubSize);

    /*!
     * Called by libglvnd to request that a vendor library patch its top-level
     * entrypoints.
     *
     * The vendor library should use the \p lookupStubOffset callback to find
     * the addresses of each entrypoint.
     *
     * This function may be called more than once to patch multiple sets of
     * entrypoints. For example, depending on how they're built, libOpenGL.so
     * or libGL.so may have their own entrypoints that are separate functions
     * from the ones in libGLdispatch.
     *
     * Note that during this call is the only time that the entrypoints can be
     * modified. After the call to \c initiatePatch returns, the vendor library
     * should treat the entrypoints as read-only.
     *
     * \param type The type of entrypoints. This will be a one of the
     * __GLDISPATCH_STUB_* values.
     * \param stubSize The maximum size of the stub that the vendor library can
     * write, in bytes.
     * \param lookupStubOffset A callback into libglvnd to look up the address
     * of each entrypoint.
     *
     * \return GL_TRUE if the vendor library supports patching with this type
     * and size.
     */
    GLboolean (*initiatePatch)(int type,
                               int stubSize,
                               DispatchPatchLookupStubOffset lookupStubOffset);

    /*!
     * (OPTIONAL) Called by libglvnd to notify the current vendor that it no
     * longer owns the top-level entrypoints.
     *
     * Libglvnd will take care of the restoring the entrypoints back to their
     * original state. The vendor library must not try to modify them.
     */
    void (*releasePatch)(void);

    /*!
     * (OPTIONAL) Called at the start of window-system functions (GLX and EGL).
     * This callback allows vendor libraries to perform any per-thread
     * initialization.
     *
     * This is basically a workaround for broken applications. A lot of apps
     * will make one or more invalid GLX/EGL calls on a thread (often including
     * a MakeCurrent with invalid parameters), and then will try to call an
     * OpenGL function.
     *
     * A non-libglvnd-based driver would be able to initialize any thread state
     * even on a bogus GLX call, but with libglvnd, those calls wouldn't get
     * past libGLX.
     *
     * This function is optional. If it's \c NULL, then libGLdispatch will
     * simply ignore it.
     *
     * \note This function may be called concurrently from multiple threads.
     */
    void (*threadAttach)(void);
} __GLdispatchPatchCallbacks;

/*!
 * Gets the version number for the ABI between libGLdispatch and the
 * window-system libraries.
 *
 * The current version (which libGLX checks for) is \c GLDISPATCH_ABI_VERSION.
 *
 * Note that this only defines the interface between the libGLdispatch and a
 * window-system library such as libGLX. The interface between libGLX and a
 * vendor library still uses \c GLX_VENDOR_ABI_VERSION for its version number.
 *
 * This function can (and generally should) be called before
 * \c __glDispatchInit.
 */
PUBLIC int __glDispatchGetABIVersion(void);

/*!
 * Initialize GLdispatch with pthreads functions needed for locking.
 */
PUBLIC void __glDispatchInit(void);

/*!
 * Tears down GLdispatch state.
 */
PUBLIC void __glDispatchFini(void);

/*!
 * Called when the client library has detected a fork, and GLdispatch state
 * needs to be reset to handle the fork.
 */
PUBLIC void __glDispatchReset(void);

/*!
 * This returns a process-unique ID that is suitable for use with a new GL
 * vendor.
 */
PUBLIC int __glDispatchNewVendorID(void);

/*!
 * Get a dispatch stub suitable for returning to the application from
 * GetProcAddress().
 */
PUBLIC __GLdispatchProc __glDispatchGetProcAddress(const char *procName);

/*!
 * Create a new dispatch table in GLdispatch. This reference hangs off the
 * client GLX or EGL context, and is passed into GLdispatch during make current.
 * A dispatch table is owned by a particular vendor.
 *
 * \param[in] getProcAddress a vendor library callback GLdispatch can use to
 * query addresses of functions from the vendor. This callback also takes
 * a pointer to caller-private data.
 * \param[in] param A pointer to pass to \p getProcAddress.
 */
PUBLIC __GLdispatchTable *__glDispatchCreateTable(
    __GLgetProcAddressCallback getProcAddress,
    void *param
);

/*!
 * Destroy a dispatch table in GLdispatch.
 */
PUBLIC void __glDispatchDestroyTable(__GLdispatchTable *dispatch);

/*!
 * This makes the given API state current, and assigns this API state
 * the passed-in current dispatch table and vendor ID.
 *
 * When this function is called, the current thread must not already have an
 * API state. To switch between two API states, first release the old API state
 * by calling \c __glDispatchLoseCurrent.
 *
 * If patchCb is not NULL, GLdispatch will attempt to overwrite its
 * entrypoints (and the entrypoints of any loaded interface libraries)
 * using the provided callbacks.  If patchCb is NULL and the entrypoints
 * have been previously overwritten, GLdispatch will attempt to restore
 * the default libglvnd entrypoints.
 *
 * This returns GL_FALSE if the make current operation failed, and GL_TRUE
 * if it succeeded.
 */
PUBLIC GLboolean __glDispatchMakeCurrent(__GLdispatchAPIState *apiState,
                                         __GLdispatchTable *dispatch,
                                         int vendorID,
                                         const __GLdispatchPatchCallbacks *patchCb);

/*!
 * This makes the NOP dispatch table current and sets the current API state to
 * NULL.
 *
 * A window system library should only call this if it created the current API
 * state. That is, if libGLX should not attempt to release an EGL context or
 * vice-versa.
 */
PUBLIC void __glDispatchLoseCurrent(void);

/*!
 * This gets the current (opaque) API state pointer. If the pointer is
 * NULL, no context is current, otherwise the contents of the pointer depends on
 * which client API owns the context (EGL or GLX).
 */
PUBLIC __GLdispatchAPIState *__glDispatchGetCurrentAPIState(void);

/**
 * Checks to see if multiple threads are being used. This should be called
 * periodically from places like glXMakeCurrent.
 */
PUBLIC void __glDispatchCheckMultithreaded(void);

#endif