5 #include "eglcontext.h"
6 #include "egldisplay.h"
8 #include "eglglobals.h"
9 #include "eglsurface.h"
13 * Initialize the given _EGLContext object to defaults and/or the values
17 _eglInitContext(_EGLDriver
*drv
, _EGLContext
*ctx
,
18 _EGLConfig
*conf
, const EGLint
*attrib_list
)
21 const EGLenum api
= eglQueryAPI();
23 if (api
== EGL_NONE
) {
24 _eglError(EGL_BAD_MATCH
, "eglCreateContext(no client API)");
28 memset(ctx
, 0, sizeof(_EGLContext
));
30 ctx
->ClientVersion
= 1; /* the default, per EGL spec */
32 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
33 switch (attrib_list
[i
]) {
34 case EGL_CONTEXT_CLIENT_VERSION
:
36 ctx
->ClientVersion
= attrib_list
[i
];
39 _eglError(EGL_BAD_ATTRIBUTE
, "_eglInitContext");
45 ctx
->DrawSurface
= EGL_NO_SURFACE
;
46 ctx
->ReadSurface
= EGL_NO_SURFACE
;
48 ctx
->WindowRenderBuffer
= EGL_NONE
;
55 * Just a placeholder/demo function. Real driver will never use this!
58 _eglCreateContext(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
59 _EGLContext
*share_list
, const EGLint
*attrib_list
)
61 #if 0 /* example code */
64 context
= (_EGLContext
*) calloc(1, sizeof(_EGLContext
));
68 if (!_eglInitContext(drv
, context
, conf
, attrib_list
)) {
80 * Default fallback routine - drivers should usually override this.
83 _eglDestroyContext(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
85 if (!_eglIsContextBound(ctx
))
91 #ifdef EGL_VERSION_1_2
93 _eglQueryContextRenderBuffer(_EGLContext
*ctx
)
95 _EGLSurface
*surf
= ctx
->DrawSurface
;
100 if (surf
->Type
== EGL_WINDOW_BIT
&& ctx
->WindowRenderBuffer
!= EGL_NONE
)
101 rb
= ctx
->WindowRenderBuffer
;
103 rb
= surf
->RenderBuffer
;
106 #endif /* EGL_VERSION_1_2 */
110 _eglQueryContext(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*c
,
111 EGLint attribute
, EGLint
*value
)
117 return _eglError(EGL_BAD_PARAMETER
, "eglQueryContext");
121 *value
= GET_CONFIG_ATTRIB(c
->Config
, EGL_CONFIG_ID
);
123 case EGL_CONTEXT_CLIENT_VERSION
:
124 *value
= c
->ClientVersion
;
126 #ifdef EGL_VERSION_1_2
127 case EGL_CONTEXT_CLIENT_TYPE
:
128 *value
= c
->ClientAPI
;
130 case EGL_RENDER_BUFFER
:
131 *value
= _eglQueryContextRenderBuffer(c
);
133 #endif /* EGL_VERSION_1_2 */
135 return _eglError(EGL_BAD_ATTRIBUTE
, "eglQueryContext");
143 * Bind the context to the surfaces. Return the surfaces that are "orphaned".
144 * That is, when the context is not NULL, return the surfaces it previously
145 * bound to; when the context is NULL, the same surfaces are returned.
148 _eglBindContextToSurfaces(_EGLContext
*ctx
,
149 _EGLSurface
**draw
, _EGLSurface
**read
)
151 _EGLSurface
*newDraw
= *draw
, *newRead
= *read
;
153 if (newDraw
->Binding
)
154 newDraw
->Binding
->DrawSurface
= NULL
;
155 newDraw
->Binding
= ctx
;
157 if (newRead
->Binding
)
158 newRead
->Binding
->ReadSurface
= NULL
;
159 newRead
->Binding
= ctx
;
162 *draw
= ctx
->DrawSurface
;
163 ctx
->DrawSurface
= newDraw
;
165 *read
= ctx
->ReadSurface
;
166 ctx
->ReadSurface
= newRead
;
172 * Bind the context to the thread and return the previous context.
174 * Note that the context may be NULL.
177 _eglBindContextToThread(_EGLContext
*ctx
, _EGLThreadInfo
*t
)
183 _eglConvertApiToIndex(ctx
->ClientAPI
) : t
->CurrentAPIIndex
;
185 oldCtx
= t
->CurrentContexts
[apiIndex
];
190 oldCtx
->Binding
= NULL
;
194 t
->CurrentContexts
[apiIndex
] = ctx
;
201 * Return true if the given context and surfaces can be made current.
204 _eglCheckMakeCurrent(_EGLContext
*ctx
, _EGLSurface
*draw
, _EGLSurface
*read
)
206 _EGLThreadInfo
*t
= _eglGetCurrentThread();
209 if (_eglIsCurrentThreadDummy())
210 return _eglError(EGL_BAD_ALLOC
, "eglMakeCurrent");
215 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
219 /* ctx/draw/read must be all given */
220 if (draw
== NULL
|| read
== NULL
)
221 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
223 /* context stealing from another thread is not allowed */
224 if (ctx
->Binding
&& ctx
->Binding
!= t
)
225 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
230 * "If ctx is current to some other thread, or if either draw or read are
231 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
236 * "at most one context may be bound to a particular surface at a given
239 * The latter is more restrictive so we can check only the latter case.
241 if ((draw
->Binding
&& draw
->Binding
!= ctx
) ||
242 (read
->Binding
&& read
->Binding
!= ctx
))
243 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
245 /* simply require the configs to be equal */
246 if (draw
->Config
!= ctx
->Config
|| read
->Config
!= ctx
->Config
)
247 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
249 switch (ctx
->ClientAPI
) {
250 #ifdef EGL_VERSION_1_4
251 /* OpenGL and OpenGL ES are conflicting */
252 case EGL_OPENGL_ES_API
:
253 conflict_api
= EGL_OPENGL_API
;
256 conflict_api
= EGL_OPENGL_ES_API
;
264 if (conflict_api
>= 0 && _eglGetAPIContext(conflict_api
))
265 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
272 * Bind the context to the current thread and given surfaces. Return the
273 * previously bound context and the surfaces it bound to. Each argument is
274 * both input and output.
277 _eglBindContext(_EGLContext
**ctx
, _EGLSurface
**draw
, _EGLSurface
**read
)
279 _EGLThreadInfo
*t
= _eglGetCurrentThread();
280 _EGLContext
*newCtx
= *ctx
, *oldCtx
;
282 if (!_eglCheckMakeCurrent(newCtx
, *draw
, *read
))
285 /* bind the new context */
286 oldCtx
= _eglBindContextToThread(newCtx
, t
);
289 _eglBindContextToSurfaces(newCtx
, draw
, read
);
291 /* unbind the old context from its binding surfaces */
294 * If the new context replaces some old context, the new one should not
295 * be current before the replacement and it should not be bound to any
299 assert(!*draw
&& !*read
);
301 *draw
= oldCtx
->DrawSurface
;
302 *read
= oldCtx
->ReadSurface
;
303 assert(*draw
&& *read
);
305 _eglBindContextToSurfaces(NULL
, draw
, read
);
313 * Drivers will typically call this to do the error checking and
314 * update the various flags.
315 * Then, the driver will do its device-dependent Make-Current stuff.
318 _eglMakeCurrent(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*draw
,
319 _EGLSurface
*read
, _EGLContext
*ctx
)
321 if (!_eglBindContext(&ctx
, &draw
, &read
))
324 /* nothing we can do if the display is uninitialized */
325 if (dpy
->Initialized
) {
326 /* avoid double destroy */
327 if (read
&& read
== draw
)
330 if (ctx
&& !_eglIsContextLinked(ctx
))
331 drv
->API
.DestroyContext(drv
, dpy
, ctx
);
332 if (draw
&& !_eglIsSurfaceLinked(draw
))
333 drv
->API
.DestroySurface(drv
, dpy
, draw
);
334 if (read
&& !_eglIsSurfaceLinked(read
))
335 drv
->API
.DestroySurface(drv
, dpy
, read
);
343 * This is defined by the EGL_MESA_copy_context extension.
346 _eglCopyContextMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext source
,
347 EGLContext dest
, EGLint mask
)
349 /* This function will always have to be overridden/implemented in the
350 * device driver. If the driver is based on Mesa, use _mesa_copy_context().