OSDN Git Service

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