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 surface as the draw or read surface. Return the
144 * previous surface that the context is bound to.
146 * Note that the context may be NULL.
149 _eglBindContextToSurface(_EGLContext
*ctx
, _EGLSurface
*surf
, EGLint readdraw
)
151 _EGLSurface
**attachment
, *oldSurf
;
154 surf
->Binding
= NULL
;
158 attachment
= (readdraw
== EGL_DRAW
) ?
159 &ctx
->DrawSurface
: &ctx
->ReadSurface
;
160 oldSurf
= *attachment
;
166 oldSurf
->Binding
= NULL
;
175 * Bind the context to the thread and return the previous context.
177 * Note that the context may be NULL.
180 _eglBindContextToThread(_EGLContext
*ctx
, _EGLThreadInfo
*t
)
186 _eglConvertApiToIndex(ctx
->ClientAPI
) : t
->CurrentAPIIndex
;
188 oldCtx
= t
->CurrentContexts
[apiIndex
];
193 oldCtx
->Binding
= NULL
;
197 t
->CurrentContexts
[apiIndex
] = ctx
;
204 * Return true if the given context and surfaces can be made current.
207 _eglCheckMakeCurrent(_EGLContext
*ctx
, _EGLSurface
*draw
, _EGLSurface
*read
)
209 _EGLThreadInfo
*t
= _eglGetCurrentThread();
212 if (_eglIsCurrentThreadDummy())
213 return _eglError(EGL_BAD_ALLOC
, "eglMakeCurrent");
218 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
222 /* ctx/draw/read must be all given */
223 if (draw
== NULL
|| read
== NULL
)
224 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
226 /* context stealing from another thread is not allowed */
227 if (ctx
->Binding
&& ctx
->Binding
!= t
)
228 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
233 * "If ctx is current to some other thread, or if either draw or read are
234 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
239 * "at most one context may be bound to a particular surface at a given
242 * The latter is more restrictive so we can check only the latter case.
244 if ((draw
->Binding
&& draw
->Binding
!= ctx
) ||
245 (read
->Binding
&& read
->Binding
!= ctx
))
246 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
248 /* simply require the configs to be equal */
249 if (draw
->Config
!= ctx
->Config
|| read
->Config
!= ctx
->Config
)
250 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
252 switch (ctx
->ClientAPI
) {
253 #ifdef EGL_VERSION_1_4
254 /* OpenGL and OpenGL ES are conflicting */
255 case EGL_OPENGL_ES_API
:
256 conflict_api
= EGL_OPENGL_API
;
259 conflict_api
= EGL_OPENGL_ES_API
;
267 if (conflict_api
>= 0 && _eglGetAPIContext(conflict_api
))
268 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
275 * Drivers will typically call this to do the error checking and
276 * update the various flags.
277 * Then, the driver will do its device-dependent Make-Current stuff.
280 _eglMakeCurrent(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*draw
,
281 _EGLSurface
*read
, _EGLContext
*ctx
)
283 _EGLThreadInfo
*t
= _eglGetCurrentThread();
284 _EGLSurface
*oldDraw
= NULL
, *oldRead
= NULL
;
287 if (!_eglCheckMakeCurrent(ctx
, draw
, read
))
290 oldCtx
= _eglBindContextToThread(ctx
, t
);
293 oldDraw
= _eglBindContextToSurface(ctx
, draw
, EGL_DRAW
);
294 oldRead
= _eglBindContextToSurface(ctx
, read
, EGL_READ
);
297 /* unbind the old context from its binding surfaces */
298 oldDraw
= oldCtx
->DrawSurface
;
299 oldRead
= oldCtx
->ReadSurface
;
302 _eglBindContextToSurface(NULL
, oldDraw
, EGL_DRAW
);
303 if (oldRead
&& oldRead
!= oldDraw
)
304 _eglBindContextToSurface(NULL
, oldRead
, EGL_READ
);
307 /* avoid double destroy */
308 if (oldRead
&& oldRead
== oldDraw
)
311 if (oldCtx
&& !_eglIsContextLinked(oldCtx
))
312 drv
->API
.DestroyContext(drv
, dpy
, oldCtx
);
313 if (oldDraw
&& !_eglIsSurfaceLinked(oldDraw
))
314 drv
->API
.DestroySurface(drv
, dpy
, oldDraw
);
315 if (oldRead
&& !_eglIsSurfaceLinked(oldRead
))
316 drv
->API
.DestroySurface(drv
, dpy
, oldRead
);
323 * This is defined by the EGL_MESA_copy_context extension.
326 _eglCopyContextMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext source
,
327 EGLContext dest
, EGLint mask
)
329 /* This function will always have to be overridden/implemented in the
330 * device driver. If the driver is based on Mesa, use _mesa_copy_context().