1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3*61046927SAndroid Build Coastguard Worker * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4*61046927SAndroid Build Coastguard Worker *
5*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: SGI-B-2.0
6*61046927SAndroid Build Coastguard Worker */
7*61046927SAndroid Build Coastguard Worker
8*61046927SAndroid Build Coastguard Worker /**
9*61046927SAndroid Build Coastguard Worker * \file glxcurrent.c
10*61046927SAndroid Build Coastguard Worker * Client-side GLX interface for current context management.
11*61046927SAndroid Build Coastguard Worker */
12*61046927SAndroid Build Coastguard Worker
13*61046927SAndroid Build Coastguard Worker #include <pthread.h>
14*61046927SAndroid Build Coastguard Worker
15*61046927SAndroid Build Coastguard Worker #include "glxclient.h"
16*61046927SAndroid Build Coastguard Worker #include "glapi.h"
17*61046927SAndroid Build Coastguard Worker #include "glx_error.h"
18*61046927SAndroid Build Coastguard Worker
19*61046927SAndroid Build Coastguard Worker /*
20*61046927SAndroid Build Coastguard Worker ** We setup some dummy structures here so that the API can be used
21*61046927SAndroid Build Coastguard Worker ** even if no context is current.
22*61046927SAndroid Build Coastguard Worker */
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker static GLubyte dummyBuffer[__GLX_BUFFER_LIMIT_SIZE];
25*61046927SAndroid Build Coastguard Worker static struct glx_context_vtable dummyVtable;
26*61046927SAndroid Build Coastguard Worker /*
27*61046927SAndroid Build Coastguard Worker ** Dummy context used by small commands when there is no current context.
28*61046927SAndroid Build Coastguard Worker ** All the
29*61046927SAndroid Build Coastguard Worker ** gl and glx entry points are designed to operate as nop's when using
30*61046927SAndroid Build Coastguard Worker ** the dummy context structure.
31*61046927SAndroid Build Coastguard Worker */
32*61046927SAndroid Build Coastguard Worker struct glx_context dummyContext = {
33*61046927SAndroid Build Coastguard Worker &dummyBuffer[0],
34*61046927SAndroid Build Coastguard Worker &dummyBuffer[0],
35*61046927SAndroid Build Coastguard Worker &dummyBuffer[0],
36*61046927SAndroid Build Coastguard Worker &dummyBuffer[__GLX_BUFFER_LIMIT_SIZE],
37*61046927SAndroid Build Coastguard Worker sizeof(dummyBuffer),
38*61046927SAndroid Build Coastguard Worker &dummyVtable
39*61046927SAndroid Build Coastguard Worker };
40*61046927SAndroid Build Coastguard Worker
41*61046927SAndroid Build Coastguard Worker /*
42*61046927SAndroid Build Coastguard Worker * Current context management and locking
43*61046927SAndroid Build Coastguard Worker */
44*61046927SAndroid Build Coastguard Worker
45*61046927SAndroid Build Coastguard Worker _X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER;
46*61046927SAndroid Build Coastguard Worker
47*61046927SAndroid Build Coastguard Worker /**
48*61046927SAndroid Build Coastguard Worker * Per-thread GLX context pointer.
49*61046927SAndroid Build Coastguard Worker *
50*61046927SAndroid Build Coastguard Worker * \c __glXSetCurrentContext is written is such a way that this pointer can
51*61046927SAndroid Build Coastguard Worker * \b never be \c NULL. This is important! Because of this
52*61046927SAndroid Build Coastguard Worker * \c __glXGetCurrentContext can be implemented as trivial macro.
53*61046927SAndroid Build Coastguard Worker */
54*61046927SAndroid Build Coastguard Worker __THREAD_INITIAL_EXEC void *__glX_tls_Context = &dummyContext;
55*61046927SAndroid Build Coastguard Worker
56*61046927SAndroid Build Coastguard Worker _X_HIDDEN void
__glXSetCurrentContext(struct glx_context * c)57*61046927SAndroid Build Coastguard Worker __glXSetCurrentContext(struct glx_context * c)
58*61046927SAndroid Build Coastguard Worker {
59*61046927SAndroid Build Coastguard Worker __glX_tls_Context = (c != NULL) ? c : &dummyContext;
60*61046927SAndroid Build Coastguard Worker }
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard Worker _X_HIDDEN void
__glXSetCurrentContextNull(void)63*61046927SAndroid Build Coastguard Worker __glXSetCurrentContextNull(void)
64*61046927SAndroid Build Coastguard Worker {
65*61046927SAndroid Build Coastguard Worker __glXSetCurrentContext(&dummyContext);
66*61046927SAndroid Build Coastguard Worker #if defined(GLX_DIRECT_RENDERING)
67*61046927SAndroid Build Coastguard Worker _glapi_set_dispatch(NULL); /* no-op functions */
68*61046927SAndroid Build Coastguard Worker _glapi_set_context(NULL);
69*61046927SAndroid Build Coastguard Worker #endif
70*61046927SAndroid Build Coastguard Worker }
71*61046927SAndroid Build Coastguard Worker
72*61046927SAndroid Build Coastguard Worker _GLX_PUBLIC GLXContext
glXGetCurrentContext(void)73*61046927SAndroid Build Coastguard Worker glXGetCurrentContext(void)
74*61046927SAndroid Build Coastguard Worker {
75*61046927SAndroid Build Coastguard Worker struct glx_context *cx = __glXGetCurrentContext();
76*61046927SAndroid Build Coastguard Worker
77*61046927SAndroid Build Coastguard Worker if (cx == &dummyContext) {
78*61046927SAndroid Build Coastguard Worker return NULL;
79*61046927SAndroid Build Coastguard Worker }
80*61046927SAndroid Build Coastguard Worker else {
81*61046927SAndroid Build Coastguard Worker return (GLXContext) cx;
82*61046927SAndroid Build Coastguard Worker }
83*61046927SAndroid Build Coastguard Worker }
84*61046927SAndroid Build Coastguard Worker
85*61046927SAndroid Build Coastguard Worker _GLX_PUBLIC GLXDrawable
glXGetCurrentDrawable(void)86*61046927SAndroid Build Coastguard Worker glXGetCurrentDrawable(void)
87*61046927SAndroid Build Coastguard Worker {
88*61046927SAndroid Build Coastguard Worker struct glx_context *gc = __glXGetCurrentContext();
89*61046927SAndroid Build Coastguard Worker return gc->currentDrawable;
90*61046927SAndroid Build Coastguard Worker }
91*61046927SAndroid Build Coastguard Worker
92*61046927SAndroid Build Coastguard Worker /**
93*61046927SAndroid Build Coastguard Worker * Make a particular context current.
94*61046927SAndroid Build Coastguard Worker *
95*61046927SAndroid Build Coastguard Worker * \note This is in this file so that it can access dummyContext.
96*61046927SAndroid Build Coastguard Worker */
97*61046927SAndroid Build Coastguard Worker static Bool
MakeContextCurrent(Display * dpy,GLXDrawable draw,GLXDrawable read,GLXContext gc_user,int opcode)98*61046927SAndroid Build Coastguard Worker MakeContextCurrent(Display * dpy, GLXDrawable draw,
99*61046927SAndroid Build Coastguard Worker GLXDrawable read, GLXContext gc_user,
100*61046927SAndroid Build Coastguard Worker int opcode)
101*61046927SAndroid Build Coastguard Worker {
102*61046927SAndroid Build Coastguard Worker struct glx_context *gc = (struct glx_context *) gc_user;
103*61046927SAndroid Build Coastguard Worker struct glx_context *oldGC = __glXGetCurrentContext();
104*61046927SAndroid Build Coastguard Worker int ret = GL_TRUE;
105*61046927SAndroid Build Coastguard Worker
106*61046927SAndroid Build Coastguard Worker /* Make sure that the new context has a nonzero ID. In the request,
107*61046927SAndroid Build Coastguard Worker * a zero context ID is used only to mean that we bind to no current
108*61046927SAndroid Build Coastguard Worker * context.
109*61046927SAndroid Build Coastguard Worker */
110*61046927SAndroid Build Coastguard Worker if ((gc != NULL) && (gc->xid == None)) {
111*61046927SAndroid Build Coastguard Worker return GL_FALSE;
112*61046927SAndroid Build Coastguard Worker }
113*61046927SAndroid Build Coastguard Worker
114*61046927SAndroid Build Coastguard Worker /* can't have only one be 0 */
115*61046927SAndroid Build Coastguard Worker if (!!draw != !!read) {
116*61046927SAndroid Build Coastguard Worker __glXSendError(dpy, BadMatch, None, opcode, True);
117*61046927SAndroid Build Coastguard Worker return False;
118*61046927SAndroid Build Coastguard Worker }
119*61046927SAndroid Build Coastguard Worker
120*61046927SAndroid Build Coastguard Worker if (oldGC == gc &&
121*61046927SAndroid Build Coastguard Worker gc->currentDrawable == draw && gc->currentReadable == read)
122*61046927SAndroid Build Coastguard Worker return True;
123*61046927SAndroid Build Coastguard Worker
124*61046927SAndroid Build Coastguard Worker __glXLock();
125*61046927SAndroid Build Coastguard Worker
126*61046927SAndroid Build Coastguard Worker if (oldGC != &dummyContext) {
127*61046927SAndroid Build Coastguard Worker oldGC->vtable->unbind(oldGC);
128*61046927SAndroid Build Coastguard Worker oldGC->currentDpy = NULL;
129*61046927SAndroid Build Coastguard Worker
130*61046927SAndroid Build Coastguard Worker if (oldGC->xid == None) {
131*61046927SAndroid Build Coastguard Worker /* We are switching away from a context that was
132*61046927SAndroid Build Coastguard Worker * previously destroyed, so we need to free the memory
133*61046927SAndroid Build Coastguard Worker * for the old handle. */
134*61046927SAndroid Build Coastguard Worker oldGC->vtable->destroy(oldGC);
135*61046927SAndroid Build Coastguard Worker }
136*61046927SAndroid Build Coastguard Worker }
137*61046927SAndroid Build Coastguard Worker
138*61046927SAndroid Build Coastguard Worker __glXSetCurrentContextNull();
139*61046927SAndroid Build Coastguard Worker
140*61046927SAndroid Build Coastguard Worker if (gc) {
141*61046927SAndroid Build Coastguard Worker /* GLX spec 3.3: If ctx is current to some other thread, then
142*61046927SAndroid Build Coastguard Worker * glXMakeContextCurrent will generate a BadAccess error
143*61046927SAndroid Build Coastguard Worker */
144*61046927SAndroid Build Coastguard Worker if (gc->currentDpy)
145*61046927SAndroid Build Coastguard Worker {
146*61046927SAndroid Build Coastguard Worker __glXUnlock();
147*61046927SAndroid Build Coastguard Worker __glXSendError(dpy, BadAccess, None, opcode, True);
148*61046927SAndroid Build Coastguard Worker return False;
149*61046927SAndroid Build Coastguard Worker }
150*61046927SAndroid Build Coastguard Worker /* Attempt to bind the context. We do this before mucking with
151*61046927SAndroid Build Coastguard Worker * gc and __glXSetCurrentContext to properly handle our state in
152*61046927SAndroid Build Coastguard Worker * case of an error.
153*61046927SAndroid Build Coastguard Worker *
154*61046927SAndroid Build Coastguard Worker * If an error occurs, set the Null context since we've already
155*61046927SAndroid Build Coastguard Worker * blown away our old context. The caller is responsible for
156*61046927SAndroid Build Coastguard Worker * figuring out how to handle setting a valid context.
157*61046927SAndroid Build Coastguard Worker */
158*61046927SAndroid Build Coastguard Worker if (gc->vtable->bind(gc, draw, read) != Success) {
159*61046927SAndroid Build Coastguard Worker ret = GL_FALSE;
160*61046927SAndroid Build Coastguard Worker } else {
161*61046927SAndroid Build Coastguard Worker gc->currentDpy = dpy;
162*61046927SAndroid Build Coastguard Worker gc->currentDrawable = draw;
163*61046927SAndroid Build Coastguard Worker gc->currentReadable = read;
164*61046927SAndroid Build Coastguard Worker __glXSetCurrentContext(gc);
165*61046927SAndroid Build Coastguard Worker }
166*61046927SAndroid Build Coastguard Worker }
167*61046927SAndroid Build Coastguard Worker
168*61046927SAndroid Build Coastguard Worker __glXUnlock();
169*61046927SAndroid Build Coastguard Worker
170*61046927SAndroid Build Coastguard Worker if (!ret)
171*61046927SAndroid Build Coastguard Worker __glXSendError(dpy, GLXBadContext, None, opcode, False);
172*61046927SAndroid Build Coastguard Worker
173*61046927SAndroid Build Coastguard Worker return ret;
174*61046927SAndroid Build Coastguard Worker }
175*61046927SAndroid Build Coastguard Worker
176*61046927SAndroid Build Coastguard Worker _GLX_PUBLIC Bool
glXMakeCurrent(Display * dpy,GLXDrawable draw,GLXContext gc)177*61046927SAndroid Build Coastguard Worker glXMakeCurrent(Display * dpy, GLXDrawable draw, GLXContext gc)
178*61046927SAndroid Build Coastguard Worker {
179*61046927SAndroid Build Coastguard Worker return MakeContextCurrent(dpy, draw, draw, gc, X_GLXMakeCurrent);
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker
182*61046927SAndroid Build Coastguard Worker _GLX_PUBLIC Bool
glXMakeContextCurrent(Display * dpy,GLXDrawable d,GLXDrawable r,GLXContext ctx)183*61046927SAndroid Build Coastguard Worker glXMakeContextCurrent(Display *dpy, GLXDrawable d, GLXDrawable r,
184*61046927SAndroid Build Coastguard Worker GLXContext ctx)
185*61046927SAndroid Build Coastguard Worker {
186*61046927SAndroid Build Coastguard Worker return MakeContextCurrent(dpy, d, r, ctx, X_GLXMakeContextCurrent);
187*61046927SAndroid Build Coastguard Worker }
188*61046927SAndroid Build Coastguard Worker
189*61046927SAndroid Build Coastguard Worker _GLX_PUBLIC Bool
glXMakeCurrentReadSGI(Display * dpy,GLXDrawable d,GLXDrawable r,GLXContext ctx)190*61046927SAndroid Build Coastguard Worker glXMakeCurrentReadSGI(Display *dpy, GLXDrawable d, GLXDrawable r,
191*61046927SAndroid Build Coastguard Worker GLXContext ctx)
192*61046927SAndroid Build Coastguard Worker {
193*61046927SAndroid Build Coastguard Worker return MakeContextCurrent(dpy, d, r, ctx, X_GLXvop_MakeCurrentReadSGI);
194*61046927SAndroid Build Coastguard Worker }
195