Merge branch 'mesa_7_5_branch' into mesa_7_6_branch
[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
49 return EGL_TRUE;
50 }
51
52
53 /**
54 * Just a placeholder/demo function. Real driver will never use this!
55 */
56 _EGLContext *
57 _eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
58 _EGLContext *share_list, const EGLint *attrib_list)
59 {
60 #if 0 /* example code */
61 _EGLContext *context;
62
63 context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
64 if (!context)
65 return NULL;
66
67 if (!_eglInitContext(drv, context, conf, attrib_list)) {
68 free(context);
69 return NULL;
70 }
71
72 return context;
73 #endif
74 return NULL;
75 }
76
77
78 /**
79 * Default fallback routine - drivers should usually override this.
80 */
81 EGLBoolean
82 _eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
83 {
84 if (!_eglIsContextBound(ctx))
85 free(ctx);
86 return EGL_TRUE;
87 }
88
89
90 EGLBoolean
91 _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
92 EGLint attribute, EGLint *value)
93 {
94 (void) drv;
95 (void) dpy;
96
97 switch (attribute) {
98 case EGL_CONFIG_ID:
99 *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
100 return EGL_TRUE;
101 #ifdef EGL_VERSION_1_2
102 case EGL_CONTEXT_CLIENT_TYPE:
103 *value = c->ClientAPI;
104 return EGL_TRUE;
105 #endif /* EGL_VERSION_1_2 */
106 case EGL_CONTEXT_CLIENT_VERSION:
107 *value = c->ClientVersion;
108 return EGL_TRUE;
109 default:
110 _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
111 return EGL_FALSE;
112 }
113 }
114
115
116 /**
117 * Drivers will typically call this to do the error checking and
118 * update the various flags.
119 * Then, the driver will do its device-dependent Make-Current stuff.
120 */
121 EGLBoolean
122 _eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw,
123 _EGLSurface *read, _EGLContext *ctx)
124 {
125 _EGLThreadInfo *t = _eglGetCurrentThread();
126 _EGLContext *oldContext = NULL;
127 _EGLSurface *oldDrawSurface = NULL;
128 _EGLSurface *oldReadSurface = NULL;
129 EGLint apiIndex;
130
131 if (_eglIsCurrentThreadDummy())
132 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
133
134 if (ctx) {
135 /* error checking */
136 if (ctx->Binding && ctx->Binding != t)
137 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
138 if (draw == NULL || read == NULL)
139 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
140 if (draw->Config != ctx->Config || read->Config != ctx->Config)
141 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
142 if ((draw->Binding && draw->Binding->Binding != t) ||
143 (read->Binding && read->Binding->Binding != t))
144 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
145
146 #ifdef EGL_VERSION_1_4
147 /* OpenGL and OpenGL ES are conflicting */
148 switch (ctx->ClientAPI) {
149 case EGL_OPENGL_ES_API:
150 if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)])
151 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
152 break;
153 case EGL_OPENGL_API:
154 if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_ES_API)])
155 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
156 break;
157 default:
158 break;
159 }
160 #endif
161 apiIndex = _eglConvertApiToIndex(ctx->ClientAPI);
162 }
163 else {
164 if (draw != NULL || read != NULL)
165 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
166 apiIndex = t->CurrentAPIIndex;
167 }
168
169 oldContext = t->CurrentContexts[apiIndex];
170 if (oldContext) {
171 oldDrawSurface = oldContext->DrawSurface;
172 oldReadSurface = oldContext->ReadSurface;
173 assert(oldDrawSurface);
174 assert(oldReadSurface);
175
176 /* break old bindings */
177 t->CurrentContexts[apiIndex] = NULL;
178 oldContext->Binding = NULL;
179 oldContext->DrawSurface = NULL;
180 oldContext->ReadSurface = NULL;
181 oldDrawSurface->Binding = NULL;
182 oldReadSurface->Binding = NULL;
183
184 /*
185 * check if the old context or surfaces need to be deleted
186 */
187 if (!_eglIsSurfaceLinked(oldDrawSurface)) {
188 assert(draw != oldDrawSurface && read != oldDrawSurface);
189 drv->API.DestroySurface(drv, dpy, oldDrawSurface);
190 }
191 if (oldReadSurface != oldDrawSurface &&
192 !_eglIsSurfaceLinked(oldReadSurface)) {
193 assert(draw != oldReadSurface && read != oldReadSurface);
194 drv->API.DestroySurface(drv, dpy, oldReadSurface);
195 }
196 if (!_eglIsContextLinked(oldContext)) {
197 assert(ctx != oldContext);
198 drv->API.DestroyContext(drv, dpy, oldContext);
199 }
200 }
201
202 /* build new bindings */
203 if (ctx) {
204 t->CurrentContexts[apiIndex] = ctx;
205 ctx->Binding = t;
206 ctx->DrawSurface = draw;
207 ctx->ReadSurface = read;
208 draw->Binding = ctx;
209 read->Binding = ctx;
210 }
211
212 return EGL_TRUE;
213 }
214
215
216 /**
217 * This is defined by the EGL_MESA_copy_context extension.
218 */
219 EGLBoolean
220 _eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source,
221 EGLContext dest, EGLint mask)
222 {
223 /* This function will always have to be overridden/implemented in the
224 * device driver. If the driver is based on Mesa, use _mesa_copy_context().
225 */
226 return EGL_FALSE;
227 }