Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/glx/indirect_glx.c
4558 views
1
/*
2
* Copyright © 2010 Intel Corporation
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Soft-
6
* ware"), to deal in the Software without restriction, including without
7
* limitation the rights to use, copy, modify, merge, publish, distribute,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, provided that the above copyright
10
* notice(s) and this permission notice appear in all copies of the Soft-
11
* ware and that both the above copyright notice(s) and this permission
12
* notice appear in supporting documentation.
13
*
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
17
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
18
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
19
* QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
22
* MANCE OF THIS SOFTWARE.
23
*
24
* Except as contained in this notice, the name of a copyright holder shall
25
* not be used in advertising or otherwise to promote the sale, use or
26
* other dealings in this Software without prior written authorization of
27
* the copyright holder.
28
*
29
* Authors:
30
* Kristian Høgsberg ([email protected])
31
*/
32
33
#include <stdbool.h>
34
35
#include "glapi.h"
36
#include "glxclient.h"
37
#include "indirect.h"
38
#include "util/debug.h"
39
40
#ifndef GLX_USE_APPLEGL
41
42
extern struct _glapi_table *__glXNewIndirectAPI(void);
43
44
/*
45
** All indirect rendering contexts will share the same indirect dispatch table.
46
*/
47
static struct _glapi_table *IndirectAPI = NULL;
48
49
static void
50
indirect_destroy_context(struct glx_context *gc)
51
{
52
__glXFreeVertexArrayState(gc);
53
54
free((char *) gc->vendor);
55
free((char *) gc->renderer);
56
free((char *) gc->version);
57
free((char *) gc->extensions);
58
__glFreeAttributeState(gc);
59
free((char *) gc->buf);
60
free((char *) gc->client_state_private);
61
free((char *) gc);
62
}
63
64
static Bool
65
SendMakeCurrentRequest(Display * dpy, GLXContextID gc_id,
66
GLXContextTag gc_tag, GLXDrawable draw,
67
GLXDrawable read, GLXContextTag *out_tag)
68
{
69
xGLXMakeCurrentReply reply;
70
Bool ret;
71
int opcode = __glXSetupForCommand(dpy);
72
73
LockDisplay(dpy);
74
75
if (draw == read) {
76
xGLXMakeCurrentReq *req;
77
78
GetReq(GLXMakeCurrent, req);
79
req->reqType = opcode;
80
req->glxCode = X_GLXMakeCurrent;
81
req->drawable = draw;
82
req->context = gc_id;
83
req->oldContextTag = gc_tag;
84
}
85
else {
86
struct glx_display *priv = __glXInitialize(dpy);
87
88
/* If the server can support the GLX 1.3 version, we should
89
* perfer that. Not only that, some servers support GLX 1.3 but
90
* not the SGI extension.
91
*/
92
93
if (priv->minorVersion >= 3) {
94
xGLXMakeContextCurrentReq *req;
95
96
GetReq(GLXMakeContextCurrent, req);
97
req->reqType = opcode;
98
req->glxCode = X_GLXMakeContextCurrent;
99
req->drawable = draw;
100
req->readdrawable = read;
101
req->context = gc_id;
102
req->oldContextTag = gc_tag;
103
}
104
else {
105
xGLXVendorPrivateWithReplyReq *vpreq;
106
xGLXMakeCurrentReadSGIReq *req;
107
108
GetReqExtra(GLXVendorPrivateWithReply,
109
sz_xGLXMakeCurrentReadSGIReq -
110
sz_xGLXVendorPrivateWithReplyReq, vpreq);
111
req = (xGLXMakeCurrentReadSGIReq *) vpreq;
112
req->reqType = opcode;
113
req->glxCode = X_GLXVendorPrivateWithReply;
114
req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
115
req->drawable = draw;
116
req->readable = read;
117
req->context = gc_id;
118
req->oldContextTag = gc_tag;
119
}
120
}
121
122
ret = _XReply(dpy, (xReply *) &reply, 0, False);
123
124
if (out_tag)
125
*out_tag = reply.contextTag;
126
127
UnlockDisplay(dpy);
128
SyncHandle();
129
130
return ret;
131
}
132
133
static int
134
indirect_bind_context(struct glx_context *gc, struct glx_context *old,
135
GLXDrawable draw, GLXDrawable read)
136
{
137
GLXContextTag tag;
138
Display *dpy = gc->psc->dpy;
139
Bool sent;
140
141
if (old != &dummyContext && !old->isDirect && old->psc->dpy == dpy) {
142
tag = old->currentContextTag;
143
old->currentContextTag = 0;
144
} else {
145
tag = 0;
146
}
147
148
sent = SendMakeCurrentRequest(dpy, gc->xid, tag, draw, read,
149
&gc->currentContextTag);
150
151
if (sent) {
152
if (!IndirectAPI)
153
IndirectAPI = __glXNewIndirectAPI();
154
_glapi_set_dispatch(IndirectAPI);
155
156
/* The indirect vertex array state must to be initialised after we
157
* have setup the context, as it needs to query server attributes.
158
*
159
* At the point this is called gc->currentDpy is not initialized
160
* nor is the thread's current context actually set. Hence the
161
* cleverness before the GetString calls.
162
*/
163
__GLXattribute *state = gc->client_state_private;
164
if (state && state->array_state == NULL) {
165
gc->currentDpy = gc->psc->dpy;
166
__glXSetCurrentContext(gc);
167
__indirect_glGetString(GL_EXTENSIONS);
168
__indirect_glGetString(GL_VERSION);
169
__glXInitVertexArrayState(gc);
170
}
171
}
172
173
return !sent;
174
}
175
176
static void
177
indirect_unbind_context(struct glx_context *gc, struct glx_context *new)
178
{
179
Display *dpy = gc->psc->dpy;
180
181
if (gc == new)
182
return;
183
184
/* We are either switching to no context, away from an indirect
185
* context to a direct context or from one dpy to another and have
186
* to send a request to the dpy to unbind the previous context.
187
*/
188
if (!new || new->isDirect || new->psc->dpy != dpy) {
189
SendMakeCurrentRequest(dpy, None, gc->currentContextTag, None, None,
190
NULL);
191
gc->currentContextTag = 0;
192
}
193
}
194
195
static void
196
indirect_wait_gl(struct glx_context *gc)
197
{
198
xGLXWaitGLReq *req;
199
Display *dpy = gc->currentDpy;
200
201
/* Flush any pending commands out */
202
__glXFlushRenderBuffer(gc, gc->pc);
203
204
/* Send the glXWaitGL request */
205
LockDisplay(dpy);
206
GetReq(GLXWaitGL, req);
207
req->reqType = gc->majorOpcode;
208
req->glxCode = X_GLXWaitGL;
209
req->contextTag = gc->currentContextTag;
210
UnlockDisplay(dpy);
211
SyncHandle();
212
}
213
214
static void
215
indirect_wait_x(struct glx_context *gc)
216
{
217
xGLXWaitXReq *req;
218
Display *dpy = gc->currentDpy;
219
220
/* Flush any pending commands out */
221
__glXFlushRenderBuffer(gc, gc->pc);
222
223
LockDisplay(dpy);
224
GetReq(GLXWaitX, req);
225
req->reqType = gc->majorOpcode;
226
req->glxCode = X_GLXWaitX;
227
req->contextTag = gc->currentContextTag;
228
UnlockDisplay(dpy);
229
SyncHandle();
230
}
231
232
static const struct glx_context_vtable indirect_context_vtable = {
233
.destroy = indirect_destroy_context,
234
.bind = indirect_bind_context,
235
.unbind = indirect_unbind_context,
236
.wait_gl = indirect_wait_gl,
237
.wait_x = indirect_wait_x,
238
};
239
240
_X_HIDDEN struct glx_context *
241
indirect_create_context(struct glx_screen *psc,
242
struct glx_config *mode,
243
struct glx_context *shareList, int renderType)
244
{
245
unsigned error = 0;
246
const uint32_t attribs[] = { GLX_RENDER_TYPE, renderType };
247
248
return indirect_create_context_attribs(psc, mode, shareList,
249
1, attribs, &error);
250
}
251
252
/**
253
* \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new
254
* function called \c __glXAllocateClientState that allocates the memory and
255
* does all the initialization (including the pixel pack / unpack).
256
*
257
* \note
258
* This function is \b not the place to validate the context creation
259
* parameters. It is just the allocator for the \c glx_context.
260
*/
261
_X_HIDDEN struct glx_context *
262
indirect_create_context_attribs(struct glx_screen *psc,
263
struct glx_config *mode,
264
struct glx_context *shareList,
265
unsigned num_attribs,
266
const uint32_t *attribs,
267
unsigned *error)
268
{
269
struct glx_context *gc;
270
int bufSize;
271
CARD8 opcode;
272
__GLXattribute *state;
273
int i, renderType = GLX_RGBA_TYPE;
274
uint32_t mask = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
275
uint32_t major = 1;
276
uint32_t minor = 0;
277
278
opcode = __glXSetupForCommand(psc->dpy);
279
if (!opcode) {
280
return NULL;
281
}
282
283
for (i = 0; i < num_attribs; i++) {
284
uint32_t attr = attribs[i*2], val = attribs[i*2 + 1];
285
286
if (attr == GLX_RENDER_TYPE)
287
renderType = val;
288
if (attr == GLX_CONTEXT_PROFILE_MASK_ARB)
289
mask = val;
290
if (attr == GLX_CONTEXT_MAJOR_VERSION_ARB)
291
major = val;
292
if (attr == GLX_CONTEXT_MINOR_VERSION_ARB)
293
minor = val;
294
}
295
296
/* We have no indirect support for core or ES contexts, and our compat
297
* context support is limited to GL 1.4.
298
*/
299
if (mask != GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB ||
300
major != 1 ||
301
minor > 4) {
302
return NULL;
303
}
304
305
/* Allocate our context record */
306
gc = calloc(1, sizeof *gc);
307
if (!gc) {
308
/* Out of memory */
309
return NULL;
310
}
311
312
glx_context_init(gc, psc, mode);
313
gc->isDirect = GL_FALSE;
314
gc->vtable = &indirect_context_vtable;
315
state = calloc(1, sizeof(struct __GLXattributeRec));
316
gc->renderType = renderType;
317
318
if (state == NULL) {
319
/* Out of memory */
320
free(gc);
321
return NULL;
322
}
323
gc->client_state_private = state;
324
state->NoDrawArraysProtocol = env_var_as_boolean("LIBGL_NO_DRAWARRAYS", false);
325
326
/*
327
** Create a temporary buffer to hold GLX rendering commands. The size
328
** of the buffer is selected so that the maximum number of GLX rendering
329
** commands can fit in a single X packet and still have room in the X
330
** packet for the GLXRenderReq header.
331
*/
332
333
bufSize = (XMaxRequestSize(psc->dpy) * 4) - sz_xGLXRenderReq;
334
gc->buf = malloc(bufSize);
335
if (!gc->buf) {
336
free(gc->client_state_private);
337
free(gc);
338
return NULL;
339
}
340
gc->bufSize = bufSize;
341
342
/* Fill in the new context */
343
gc->renderMode = GL_RENDER;
344
345
state->storePack.alignment = 4;
346
state->storeUnpack.alignment = 4;
347
348
gc->attributes.stackPointer = &gc->attributes.stack[0];
349
350
gc->pc = gc->buf;
351
gc->bufEnd = gc->buf + bufSize;
352
gc->isDirect = GL_FALSE;
353
if (__glXDebug) {
354
/*
355
** Set limit register so that there will be one command per packet
356
*/
357
gc->limit = gc->buf;
358
}
359
else {
360
gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
361
}
362
gc->majorOpcode = opcode;
363
364
/*
365
** Constrain the maximum drawing command size allowed to be
366
** transferred using the X_GLXRender protocol request. First
367
** constrain by a software limit, then constrain by the protocol
368
** limit.
369
*/
370
gc->maxSmallRenderCommandSize = MIN3(bufSize, __GLX_RENDER_CMD_SIZE_LIMIT,
371
__GLX_MAX_RENDER_CMD_SIZE);
372
373
374
return gc;
375
}
376
377
static const struct glx_screen_vtable indirect_screen_vtable = {
378
.create_context = indirect_create_context,
379
.create_context_attribs = indirect_create_context_attribs,
380
.query_renderer_integer = NULL,
381
.query_renderer_string = NULL,
382
};
383
384
_X_HIDDEN struct glx_screen *
385
indirect_create_screen(int screen, struct glx_display * priv)
386
{
387
struct glx_screen *psc;
388
389
psc = calloc(1, sizeof *psc);
390
if (psc == NULL)
391
return NULL;
392
393
glx_screen_init(psc, screen, priv);
394
psc->vtable = &indirect_screen_vtable;
395
396
return psc;
397
}
398
399
#endif
400
401