Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/mapi/u_current.c
4558 views
1
/*
2
* Mesa 3-D graphics library
3
*
4
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5
*
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the "Software"),
8
* to deal in the Software without restriction, including without limitation
9
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
* and/or sell copies of the Software, and to permit persons to whom the
11
* Software is furnished to do so, subject to the following conditions:
12
*
13
* The above copyright notice and this permission notice shall be included
14
* in all copies or substantial portions of the Software.
15
*
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
* OTHER DEALINGS IN THE SOFTWARE.
23
*/
24
25
26
/*
27
* This file manages the OpenGL API dispatch layer.
28
* The dispatch table (struct _glapi_table) is basically just a list
29
* of function pointers.
30
* There are functions to set/get the current dispatch table for the
31
* current thread and to manage registration/dispatch of dynamically
32
* added extension functions.
33
*
34
* It's intended that this file and the other glapi*.[ch] files are
35
* flexible enough to be reused in several places: XFree86, DRI-
36
* based libGL.so, and perhaps the SGI SI.
37
*
38
* NOTE: There are no dependencies on Mesa in this code.
39
*
40
* Versions (API changes):
41
* 2000/02/23 - original version for Mesa 3.3 and XFree86 4.0
42
* 2001/01/16 - added dispatch override feature for Mesa 3.5
43
* 2002/06/28 - added _glapi_set_warning_func(), Mesa 4.1.
44
* 2002/10/01 - _glapi_get_proc_address() will now generate new entrypoints
45
* itself (using offset ~0). _glapi_add_entrypoint() can be
46
* called afterward and it'll fill in the correct dispatch
47
* offset. This allows DRI libGL to avoid probing for DRI
48
* drivers! No changes to the public glapi interface.
49
*/
50
51
#include "c11/threads.h"
52
#include "util/u_thread.h"
53
#include "u_current.h"
54
55
#ifndef MAPI_MODE_UTIL
56
57
#include "table.h"
58
#include "stub.h"
59
60
#else
61
62
extern void init_glapi_relocs_once(void);
63
extern void (*__glapi_noop_table[])(void);
64
65
#define table_noop_array __glapi_noop_table
66
#define stub_init_once() init_glapi_relocs_once()
67
68
#endif
69
70
/**
71
* \name Current dispatch and current context control variables
72
*
73
* Depending on whether or not multithreading is support, and the type of
74
* support available, several variables are used to store the current context
75
* pointer and the current dispatch table pointer. In the non-threaded case,
76
* the variables \c _glapi_Dispatch and \c _glapi_Context are used for this
77
* purpose.
78
*
79
* In the "normal" threaded case, the variables \c _glapi_Dispatch and
80
* \c _glapi_Context will be \c NULL if an application is detected as being
81
* multithreaded. Single-threaded applications will use \c _glapi_Dispatch
82
* and \c _glapi_Context just like the case without any threading support.
83
* When \c _glapi_Dispatch and \c _glapi_Context are \c NULL, the thread state
84
* data \c _gl_DispatchTSD and \c ContextTSD are used. Drivers and the
85
* static dispatch functions access these variables via \c _glapi_get_dispatch
86
* and \c _glapi_get_context.
87
*
88
* There is a race condition in setting \c _glapi_Dispatch to \c NULL. It is
89
* possible for the original thread to be setting it at the same instant a new
90
* thread, perhaps running on a different processor, is clearing it. Because
91
* of that, \c ThreadSafe, which can only ever be changed to \c GL_TRUE, is
92
* used to determine whether or not the application is multithreaded.
93
*
94
* In the TLS case, the variables \c _glapi_Dispatch and \c _glapi_Context are
95
* hardcoded to \c NULL. Instead the TLS variables \c _glapi_tls_Dispatch and
96
* \c _glapi_tls_Context are used. Having \c _glapi_Dispatch and
97
* \c _glapi_Context be hardcoded to \c NULL maintains binary compatability
98
* between TLS enabled loaders and non-TLS DRI drivers.
99
*/
100
/*@{*/
101
#if defined(USE_ELF_TLS)
102
103
__THREAD_INITIAL_EXEC struct _glapi_table *u_current_table
104
= (struct _glapi_table *) table_noop_array;
105
106
__THREAD_INITIAL_EXEC void *u_current_context;
107
108
#else
109
110
struct _glapi_table *u_current_table =
111
(struct _glapi_table *) table_noop_array;
112
void *u_current_context;
113
114
tss_t u_current_table_tsd;
115
static tss_t u_current_context_tsd;
116
static int ThreadSafe;
117
118
#endif /* defined(USE_ELF_TLS) */
119
/*@}*/
120
121
122
void
123
u_current_destroy(void)
124
{
125
#if !defined(USE_ELF_TLS)
126
tss_delete(u_current_table_tsd);
127
tss_delete(u_current_context_tsd);
128
#endif
129
}
130
131
132
#if !defined(USE_ELF_TLS)
133
134
static void
135
u_current_init_tsd(void)
136
{
137
tss_create(&u_current_table_tsd, NULL);
138
tss_create(&u_current_context_tsd, NULL);
139
}
140
141
/**
142
* Mutex for multithread check.
143
*/
144
static mtx_t ThreadCheckMutex = _MTX_INITIALIZER_NP;
145
146
static thread_id knownID;
147
148
/**
149
* We should call this periodically from a function such as glXMakeCurrent
150
* in order to test if multiple threads are being used.
151
*/
152
void
153
u_current_init(void)
154
{
155
static int firstCall = 1;
156
157
if (ThreadSafe)
158
return;
159
160
mtx_lock(&ThreadCheckMutex);
161
if (firstCall) {
162
u_current_init_tsd();
163
164
knownID = util_get_thread_id();
165
firstCall = 0;
166
}
167
else if (!util_thread_id_equal(knownID, util_get_thread_id())) {
168
ThreadSafe = 1;
169
u_current_set_table(NULL);
170
u_current_set_context(NULL);
171
}
172
mtx_unlock(&ThreadCheckMutex);
173
}
174
175
#else
176
177
void
178
u_current_init(void)
179
{
180
}
181
182
#endif
183
184
185
186
/**
187
* Set the current context pointer for this thread.
188
* The context pointer is an opaque type which should be cast to
189
* void from the real context pointer type.
190
*/
191
void
192
u_current_set_context(const void *ptr)
193
{
194
u_current_init();
195
196
#if defined(USE_ELF_TLS)
197
u_current_context = (void *) ptr;
198
#else
199
tss_set(u_current_context_tsd, (void *) ptr);
200
u_current_context = (ThreadSafe) ? NULL : (void *) ptr;
201
#endif
202
}
203
204
/**
205
* Get the current context pointer for this thread.
206
* The context pointer is an opaque type which should be cast from
207
* void to the real context pointer type.
208
*/
209
void *
210
u_current_get_context_internal(void)
211
{
212
#if defined(USE_ELF_TLS)
213
return u_current_context;
214
#else
215
if (ThreadSafe)
216
return tss_get(u_current_context_tsd);
217
else if (!util_thread_id_equal(knownID, util_get_thread_id()))
218
return NULL;
219
else
220
return u_current_context;
221
#endif
222
}
223
224
/**
225
* Set the global or per-thread dispatch table pointer.
226
* If the dispatch parameter is NULL we'll plug in the no-op dispatch
227
* table (__glapi_noop_table).
228
*/
229
void
230
u_current_set_table(const struct _glapi_table *tbl)
231
{
232
u_current_init();
233
234
stub_init_once();
235
236
if (!tbl)
237
tbl = (const struct _glapi_table *) table_noop_array;
238
239
#if defined(USE_ELF_TLS)
240
u_current_table = (struct _glapi_table *) tbl;
241
#else
242
tss_set(u_current_table_tsd, (void *) tbl);
243
u_current_table = (ThreadSafe) ? NULL : (void *) tbl;
244
#endif
245
}
246
247
/**
248
* Return pointer to current dispatch table for calling thread.
249
*/
250
struct _glapi_table *
251
u_current_get_table_internal(void)
252
{
253
#if defined(USE_ELF_TLS)
254
return u_current_table;
255
#else
256
if (ThreadSafe)
257
return (struct _glapi_table *) tss_get(u_current_table_tsd);
258
else if (!util_thread_id_equal(knownID, util_get_thread_id()))
259
return (struct _glapi_table *) table_noop_array;
260
else
261
return (struct _glapi_table *) u_current_table;
262
#endif
263
}
264
265