Merge branch 'texformat-rework'
[mesa.git] / src / egl / main / eglcontext.c
1 #include <assert.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "eglconfig.h"
5 #include "eglcontext.h"
6 #include "egldisplay.h"
7 #include "egldriver.h"
8 #include "eglglobals.h"
9 #include "eglsurface.h"
10
11
12 /**
13 * Initialize the given _EGLContext object to defaults and/or the values
14 * in the attrib_list.
15 */
16 EGLBoolean
17 _eglInitContext(_EGLDriver *drv, _EGLContext *ctx,
18 _EGLConfig *conf, const EGLint *attrib_list)
19 {
20 EGLint i;
21 const EGLenum api = eglQueryAPI();
22
23 if (api == EGL_NONE) {
24 _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
25 return EGL_FALSE;
26 }
27
28 memset(ctx, 0, sizeof(_EGLContext));
29
30 ctx->ClientVersion = 1; /* the default, per EGL spec */
31
32 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
33 switch (attrib_list[i]) {
34 case EGL_CONTEXT_CLIENT_VERSION:
35 i++;
36 ctx->ClientVersion = attrib_list[i];
37 break;
38 default:
39 _eglError(EGL_BAD_ATTRIBUTE, "_eglInitContext");
40 return EGL_FALSE;
41 }
42 }
43
44 ctx->Config = conf;
45 ctx->DrawSurface = EGL_NO_SURFACE;
46 ctx->ReadSurface = EGL_NO_SURFACE;
47 ctx->ClientAPI = api;
48 ctx->WindowRenderBuffer = EGL_NONE;
49
50 return EGL_TRUE;
51 }
52
53
54 /**
55 * Just a placeholder/demo function. Real driver will never use this!
56 */
57 _EGLContext *
58 _eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
59 _EGLContext *share_list, const EGLint *attrib_list)
60 {
61 #if 0 /* example code */
62 _EGLContext *context;
63
64 context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
65 if (!context)
66 return NULL;
67
68 if (!_eglInitContext(drv, context, conf, attrib_list)) {
69 free(context);
70 return NULL;
71 }
72
73 return context;
74 #endif
75 return NULL;
76 }
77
78
79 /**
80 * Default fallback routine - drivers should usually override this.
81 */
82 EGLBoolean
83 _eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
84 {
85 if (!_eglIsContextBound(ctx))
86 free(ctx);
87 return EGL_TRUE;
88 }
89
90
91 #ifdef EGL_VERSION_1_2
92 static EGLint
93 _eglQueryContextRenderBuffer(_EGLContext *ctx)
94 {
95 _EGLSurface *surf = ctx->DrawSurface;
96 EGLint rb;
97
98 if (!surf)
99 return EGL_NONE;
100 if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
101 rb = ctx->WindowRenderBuffer;
102 else
103 rb = surf->RenderBuffer;
104 return rb;
105 }
106 #endif /* EGL_VERSION_1_2 */
107
108
109 EGLBoolean
110 _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
111 EGLint attribute, EGLint *value)
112 {
113 (void) drv;
114 (void) dpy;
115
116 if (!value)
117 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
118
119 switch (attribute) {
120 case EGL_CONFIG_ID:
121 *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
122 break;
123 case EGL_CONTEXT_CLIENT_VERSION:
124 *value = c->ClientVersion;
125 break;
126 #ifdef EGL_VERSION_1_2
127 case EGL_CONTEXT_CLIENT_TYPE:
128 *value = c->ClientAPI;
129 break;
130 case EGL_RENDER_BUFFER:
131 *value = _eglQueryContextRenderBuffer(c);
132 break;
133 #endif /* EGL_VERSION_1_2 */
134 default:
135 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
136 }
137
138 return EGL_TRUE;
139 }
140
141
142 /**
143 * Drivers will typically call this to do the error checking and
144 * update the various flags.
145 * Then, the driver will do its device-dependent Make-Current stuff.
146 */
147 EGLBoolean
148 _eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw,
149 _EGLSurface *read, _EGLContext *ctx)
150 {
151 _EGLThreadInfo *t = _eglGetCurrentThread();
152 _EGLContext *oldContext = NULL;
153 _EGLSurface *oldDrawSurface = NULL;
154 _EGLSurface *oldReadSurface = NULL;
155 EGLint apiIndex;
156
157 if (_eglIsCurrentThreadDummy())
158 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
159
160 if (ctx) {
161 /* error checking */
162 if (ctx->Binding && ctx->Binding != t)
163 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
164 if (draw == NULL || read == NULL)
165 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
166 if (draw->Config != ctx->Config || read->Config != ctx->Config)
167 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
168 if ((draw->Binding && draw->Binding->Binding != t) ||
169 (read->Binding && read->Binding->Binding != t))
170 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
171
172 #ifdef EGL_VERSION_1_4
173 /* OpenGL and OpenGL ES are conflicting */
174 switch (ctx->ClientAPI) {
175 case EGL_OPENGL_ES_API:
176 if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)])
177 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
178 break;
179 case EGL_OPENGL_API:
180 if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_ES_API)])
181 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
182 break;
183 default:
184 break;
185 }
186 #endif
187 apiIndex = _eglConvertApiToIndex(ctx->ClientAPI);
188 }
189 else {
190 if (draw != NULL || read != NULL)
191 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
192 apiIndex = t->CurrentAPIIndex;
193 }
194
195 oldContext = t->CurrentContexts[apiIndex];
196 if (oldContext) {
197 oldDrawSurface = oldContext->DrawSurface;
198 oldReadSurface = oldContext->ReadSurface;
199 assert(oldDrawSurface);
200 assert(oldReadSurface);
201
202 /* break old bindings */
203 t->CurrentContexts[apiIndex] = NULL;
204 oldContext->Binding = NULL;
205 oldContext->DrawSurface = NULL;
206 oldContext->ReadSurface = NULL;
207 oldDrawSurface->Binding = NULL;
208 oldReadSurface->Binding = NULL;
209
210 /*
211 * check if the old context or surfaces need to be deleted
212 */
213 if (!_eglIsSurfaceLinked(oldDrawSurface)) {
214 assert(draw != oldDrawSurface && read != oldDrawSurface);
215 drv->API.DestroySurface(drv, dpy, oldDrawSurface);
216 }
217 if (oldReadSurface != oldDrawSurface &&
218 !_eglIsSurfaceLinked(oldReadSurface)) {
219 assert(draw != oldReadSurface && read != oldReadSurface);
220 drv->API.DestroySurface(drv, dpy, oldReadSurface);
221 }
222 if (!_eglIsContextLinked(oldContext)) {
223 assert(ctx != oldContext);
224 drv->API.DestroyContext(drv, dpy, oldContext);
225 }
226 }
227
228 /* build new bindings */
229 if (ctx) {
230 t->CurrentContexts[apiIndex] = ctx;
231 ctx->Binding = t;
232 ctx->DrawSurface = draw;
233 ctx->ReadSurface = read;
234 draw->Binding = ctx;
235 read->Binding = ctx;
236 }
237
238 return EGL_TRUE;
239 }
240
241
242 /**
243 * This is defined by the EGL_MESA_copy_context extension.
244 */
245 EGLBoolean
246 _eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source,
247 EGLContext dest, EGLint mask)
248 {
249 /* This function will always have to be overridden/implemented in the
250 * device driver. If the driver is based on Mesa, use _mesa_copy_context().
251 */
252 return EGL_FALSE;
253 }