xref: /aosp_15_r20/external/mesa3d/src/glx/glxcurrent.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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