egl: added eglDestroySurface function
[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, EGLDisplay dpy, _EGLContext *ctx,
18 EGLConfig config, const EGLint *attrib_list)
19 {
20 _EGLConfig *conf;
21 _EGLDisplay *display = _eglLookupDisplay(dpy);
22 EGLint i;
23
24 conf = _eglLookupConfig(drv, dpy, config);
25 if (!conf) {
26 _eglError(EGL_BAD_CONFIG, "_eglInitContext");
27 return EGL_FALSE;
28 }
29
30 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
31 switch (attrib_list[i]) {
32 case EGL_CONTEXT_CLIENT_VERSION:
33 /* xxx todo */
34 break;
35 default:
36 _eglError(EGL_BAD_ATTRIBUTE, "_eglInitContext");
37 return EGL_FALSE;
38 }
39 }
40
41 memset(ctx, 0, sizeof(_EGLContext));
42 ctx->Display = display;
43 ctx->Config = conf;
44 ctx->DrawSurface = EGL_NO_SURFACE;
45 ctx->ReadSurface = EGL_NO_SURFACE;
46
47 return EGL_TRUE;
48 }
49
50
51 /**
52 * Save a new _EGLContext into the hash table.
53 */
54 void
55 _eglSaveContext(_EGLContext *ctx)
56 {
57 /* no-op.
58 * Public EGLContext handle and private _EGLContext are the same.
59 */
60 }
61
62
63 /**
64 * Remove the given _EGLContext object from the hash table.
65 */
66 void
67 _eglRemoveContext(_EGLContext *ctx)
68 {
69 /* no-op.
70 * Public EGLContext handle and private _EGLContext are the same.
71 */
72 }
73
74
75 /**
76 * Return the public handle for the given private context ptr.
77 * This is the inverse of _eglLookupContext().
78 */
79 EGLContext
80 _eglGetContextHandle(_EGLContext *ctx)
81 {
82 /* just a cast! */
83 return (EGLContext) ctx;
84 }
85
86
87 /**
88 * Return the _EGLContext object that corresponds to the given
89 * EGLContext handle.
90 * This is the inverse of _eglGetContextHandle().
91 */
92 _EGLContext *
93 _eglLookupContext(EGLContext ctx)
94 {
95 /* just a cast since EGLContext is just a void ptr */
96 return (_EGLContext *) ctx;
97 }
98
99
100 /**
101 * Return the currently bound _EGLContext object, or NULL.
102 */
103 _EGLContext *
104 _eglGetCurrentContext(void)
105 {
106 _EGLThreadInfo *t = _eglGetCurrentThread();
107 return t->CurrentContext;
108 }
109
110
111 /**
112 * Just a placeholder/demo function. Real driver will never use this!
113 */
114 EGLContext
115 _eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
116 EGLContext share_list, const EGLint *attrib_list)
117 {
118 #if 0 /* example code */
119 _EGLContext *context;
120
121 context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
122 if (!context)
123 return EGL_NO_CONTEXT;
124
125 if (!_eglInitContext(drv, dpy, context, config, attrib_list)) {
126 free(context);
127 return EGL_NO_CONTEXT;
128 }
129
130 _eglSaveContext(context);
131 return (EGLContext) context;
132 #endif
133 return EGL_NO_CONTEXT;
134 }
135
136
137 /**
138 * Default fallback routine - drivers should usually override this.
139 */
140 EGLBoolean
141 _eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
142 {
143 _EGLContext *context = _eglLookupContext(ctx);
144 if (context) {
145 if (context->IsBound) {
146 context->DeletePending = EGL_TRUE;
147 }
148 else {
149 free(context);
150 }
151 return EGL_TRUE;
152 }
153 else {
154 _eglError(EGL_BAD_CONTEXT, "eglDestroyContext");
155 return EGL_TRUE;
156 }
157 }
158
159
160 EGLBoolean
161 _eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
162 EGLint attribute, EGLint *value)
163 {
164 _EGLContext *c = _eglLookupContext(ctx);
165
166 (void) drv;
167 (void) dpy;
168
169 if (!c) {
170 _eglError(EGL_BAD_CONTEXT, "eglQueryContext");
171 return EGL_FALSE;
172 }
173
174 switch (attribute) {
175 case EGL_CONFIG_ID:
176 *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
177 return EGL_TRUE;
178 #ifdef EGL_VERSION_1_2
179 case EGL_CONTEXT_CLIENT_TYPE:
180 *value = c->ClientAPI;
181 return EGL_FALSE;
182 #endif /* EGL_VERSION_1_2 */
183 default:
184 _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
185 return EGL_FALSE;
186 }
187 }
188
189
190 /**
191 * Drivers will typically call this to do the error checking and
192 * update the various IsBound and DeletePending flags.
193 * Then, the driver will do its device-dependent Make-Current stuff.
194 */
195 EGLBoolean
196 _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
197 EGLSurface r, EGLContext context)
198 {
199 _EGLThreadInfo *t = _eglGetCurrentThread();
200 _EGLContext *ctx = _eglLookupContext(context);
201 _EGLSurface *draw = _eglLookupSurface(d);
202 _EGLSurface *read = _eglLookupSurface(r);
203
204 _EGLContext *oldContext = _eglGetCurrentContext();
205 _EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW);
206 _EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ);
207
208 /* error checking */
209 if (ctx) {
210 if (draw == NULL || read == NULL) {
211 _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
212 return EGL_FALSE;
213 }
214 if (draw->Config != ctx->Config) {
215 _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
216 return EGL_FALSE;
217 }
218 if (read->Config != ctx->Config) {
219 _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
220 return EGL_FALSE;
221 }
222 }
223
224 /*
225 * check if the old context or surfaces need to be deleted
226 */
227 if (oldDrawSurface != NULL) {
228 oldDrawSurface->IsBound = EGL_FALSE;
229 if (oldDrawSurface->DeletePending) {
230 /* make sure we don't try to rebind a deleted surface */
231 if (draw == oldDrawSurface || draw == oldReadSurface) {
232 draw = NULL;
233 }
234 /* really delete surface now */
235 drv->API.DestroySurface(drv, dpy, oldDrawSurface->Handle);
236 }
237 }
238 if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) {
239 oldReadSurface->IsBound = EGL_FALSE;
240 if (oldReadSurface->DeletePending) {
241 /* make sure we don't try to rebind a deleted surface */
242 if (read == oldDrawSurface || read == oldReadSurface) {
243 read = NULL;
244 }
245 /* really delete surface now */
246 drv->API.DestroySurface(drv, dpy, oldReadSurface->Handle);
247 }
248 }
249 if (oldContext != NULL) {
250 oldContext->IsBound = EGL_FALSE;
251 if (oldContext->DeletePending) {
252 /* make sure we don't try to rebind a deleted context */
253 if (ctx == oldContext) {
254 ctx = NULL;
255 }
256 /* really delete context now */
257 drv->API.DestroyContext(drv, dpy, _eglGetContextHandle(oldContext));
258 }
259 }
260
261 if (ctx) {
262 /* check read/draw again, in case we deleted them above */
263 if (draw == NULL || read == NULL) {
264 _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
265 return EGL_FALSE;
266 }
267 ctx->DrawSurface = draw;
268 ctx->ReadSurface = read;
269 ctx->IsBound = EGL_TRUE;
270 draw->IsBound = EGL_TRUE;
271 read->IsBound = EGL_TRUE;
272 }
273
274 t->CurrentContext = ctx;
275
276 return EGL_TRUE;
277 }
278
279
280 /**
281 * This is defined by the EGL_MESA_copy_context extension.
282 */
283 EGLBoolean
284 _eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source,
285 EGLContext dest, EGLint mask)
286 {
287 /* This function will always have to be overridden/implemented in the
288 * device driver. If the driver is based on Mesa, use _mesa_copy_context().
289 */
290 return EGL_FALSE;
291 }