5 #include "eglcontext.h"
6 #include "egldisplay.h"
7 #include "eglcurrent.h"
8 #include "eglsurface.h"
13 * Return the API bit (one of EGL_xxx_BIT) of the context.
16 _eglGetContextAPIBit(_EGLContext
*ctx
)
20 switch (ctx
->ClientAPI
) {
21 case EGL_OPENGL_ES_API
:
22 switch (ctx
->ClientVersion
) {
24 bit
= EGL_OPENGL_ES_BIT
;
27 bit
= EGL_OPENGL_ES2_BIT
;
48 * Parse the list of context attributes and return the proper error code.
51 _eglParseContextAttribList(_EGLContext
*ctx
, const EGLint
*attrib_list
)
53 EGLenum api
= ctx
->ClientAPI
;
54 EGLint i
, err
= EGL_SUCCESS
;
59 for (i
= 0; attrib_list
[i
] != EGL_NONE
; i
++) {
60 EGLint attr
= attrib_list
[i
++];
61 EGLint val
= attrib_list
[i
];
64 case EGL_CONTEXT_CLIENT_VERSION
:
65 if (api
!= EGL_OPENGL_ES_API
) {
66 err
= EGL_BAD_ATTRIBUTE
;
69 if (val
!= 1 && val
!= 2) {
70 err
= EGL_BAD_ATTRIBUTE
;
73 ctx
->ClientVersion
= val
;
76 err
= EGL_BAD_ATTRIBUTE
;
80 if (err
!= EGL_SUCCESS
) {
81 _eglLog(_EGL_DEBUG
, "bad context attribute 0x%04x", attr
);
91 * Initialize the given _EGLContext object to defaults and/or the values
95 _eglInitContext(_EGLContext
*ctx
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
96 const EGLint
*attrib_list
)
98 const EGLenum api
= eglQueryAPI();
101 if (api
== EGL_NONE
) {
102 _eglError(EGL_BAD_MATCH
, "eglCreateContext(no client API)");
106 _eglInitResource(&ctx
->Resource
, sizeof(*ctx
), dpy
);
107 ctx
->ClientAPI
= api
;
109 ctx
->WindowRenderBuffer
= EGL_NONE
;
111 ctx
->ClientVersion
= 1; /* the default, per EGL spec */
113 err
= _eglParseContextAttribList(ctx
, attrib_list
);
114 if (err
== EGL_SUCCESS
&& ctx
->Config
) {
117 api_bit
= _eglGetContextAPIBit(ctx
);
118 if (!(ctx
->Config
->RenderableType
& api_bit
)) {
119 _eglLog(_EGL_DEBUG
, "context api is 0x%x while config supports 0x%x",
120 api_bit
, ctx
->Config
->RenderableType
);
121 err
= EGL_BAD_CONFIG
;
124 if (err
!= EGL_SUCCESS
)
125 return _eglError(err
, "eglCreateContext");
131 #ifdef EGL_VERSION_1_2
133 _eglQueryContextRenderBuffer(_EGLContext
*ctx
)
135 _EGLSurface
*surf
= ctx
->DrawSurface
;
140 if (surf
->Type
== EGL_WINDOW_BIT
&& ctx
->WindowRenderBuffer
!= EGL_NONE
)
141 rb
= ctx
->WindowRenderBuffer
;
143 rb
= surf
->RenderBuffer
;
146 #endif /* EGL_VERSION_1_2 */
150 _eglQueryContext(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*c
,
151 EGLint attribute
, EGLint
*value
)
157 return _eglError(EGL_BAD_PARAMETER
, "eglQueryContext");
162 return _eglError(EGL_BAD_ATTRIBUTE
, "eglQueryContext");
163 *value
= c
->Config
->ConfigID
;
165 case EGL_CONTEXT_CLIENT_VERSION
:
166 *value
= c
->ClientVersion
;
168 #ifdef EGL_VERSION_1_2
169 case EGL_CONTEXT_CLIENT_TYPE
:
170 *value
= c
->ClientAPI
;
172 case EGL_RENDER_BUFFER
:
173 *value
= _eglQueryContextRenderBuffer(c
);
175 #endif /* EGL_VERSION_1_2 */
177 return _eglError(EGL_BAD_ATTRIBUTE
, "eglQueryContext");
185 * Bind the context to the thread and return the previous context.
187 * Note that the context may be NULL.
190 _eglBindContextToThread(_EGLContext
*ctx
, _EGLThreadInfo
*t
)
196 _eglConvertApiToIndex(ctx
->ClientAPI
) : t
->CurrentAPIIndex
;
198 oldCtx
= t
->CurrentContexts
[apiIndex
];
201 oldCtx
->Binding
= NULL
;
205 t
->CurrentContexts
[apiIndex
] = ctx
;
213 * Return true if the given context and surfaces can be made current.
216 _eglCheckMakeCurrent(_EGLContext
*ctx
, _EGLSurface
*draw
, _EGLSurface
*read
)
218 _EGLThreadInfo
*t
= _eglGetCurrentThread();
221 EGLBoolean surfaceless
;
223 if (_eglIsCurrentThreadDummy())
224 return _eglError(EGL_BAD_ALLOC
, "eglMakeCurrent");
229 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
233 dpy
= ctx
->Resource
.Display
;
234 switch (_eglGetContextAPIBit(ctx
)) {
235 case EGL_OPENGL_ES_BIT
:
236 surfaceless
= dpy
->Extensions
.KHR_surfaceless_gles1
;
238 case EGL_OPENGL_ES2_BIT
:
239 surfaceless
= dpy
->Extensions
.KHR_surfaceless_gles2
;
242 surfaceless
= dpy
->Extensions
.KHR_surfaceless_opengl
;
245 surfaceless
= EGL_FALSE
;
249 if (!surfaceless
&& (draw
== NULL
|| read
== NULL
))
250 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
255 * "If ctx is current to some other thread, or if either draw or read are
256 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
261 * "at most one context may be bound to a particular surface at a given
264 if (ctx
->Binding
&& ctx
->Binding
!= t
)
265 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
266 if (draw
&& draw
->CurrentContext
&& draw
->CurrentContext
!= ctx
) {
267 if (draw
->CurrentContext
->Binding
!= t
||
268 draw
->CurrentContext
->ClientAPI
!= ctx
->ClientAPI
)
269 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
271 if (read
&& read
->CurrentContext
&& read
->CurrentContext
!= ctx
) {
272 if (read
->CurrentContext
->Binding
!= t
||
273 read
->CurrentContext
->ClientAPI
!= ctx
->ClientAPI
)
274 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
277 /* simply require the configs to be equal */
278 if ((draw
&& draw
->Config
!= ctx
->Config
) ||
279 (read
&& read
->Config
!= ctx
->Config
))
280 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
282 switch (ctx
->ClientAPI
) {
283 #ifdef EGL_VERSION_1_4
284 /* OpenGL and OpenGL ES are conflicting */
285 case EGL_OPENGL_ES_API
:
286 conflict_api
= EGL_OPENGL_API
;
289 conflict_api
= EGL_OPENGL_ES_API
;
297 if (conflict_api
>= 0 && _eglGetAPIContext(conflict_api
))
298 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
305 * Bind the context to the current thread and given surfaces. Return the
306 * previous bound context and surfaces. The caller should unreference the
307 * returned context and surfaces.
309 * Making a second call with the resources returned by the first call
310 * unsurprisingly undoes the first call, except for the resouce reference
314 _eglBindContext(_EGLContext
*ctx
, _EGLSurface
*draw
, _EGLSurface
*read
,
315 _EGLContext
**old_ctx
,
316 _EGLSurface
**old_draw
, _EGLSurface
**old_read
)
318 _EGLThreadInfo
*t
= _eglGetCurrentThread();
319 _EGLContext
*prev_ctx
;
320 _EGLSurface
*prev_draw
, *prev_read
;
322 if (!_eglCheckMakeCurrent(ctx
, draw
, read
))
325 /* increment refcounts before binding */
327 _eglGetSurface(draw
);
328 _eglGetSurface(read
);
330 /* bind the new context */
331 prev_ctx
= _eglBindContextToThread(ctx
, t
);
333 /* break previous bindings */
335 prev_draw
= prev_ctx
->DrawSurface
;
336 prev_read
= prev_ctx
->ReadSurface
;
339 prev_draw
->CurrentContext
= NULL
;
341 prev_read
->CurrentContext
= NULL
;
343 prev_ctx
->DrawSurface
= NULL
;
344 prev_ctx
->ReadSurface
= NULL
;
347 prev_draw
= prev_read
= NULL
;
350 /* establish new bindings */
353 draw
->CurrentContext
= ctx
;
355 read
->CurrentContext
= ctx
;
357 ctx
->DrawSurface
= draw
;
358 ctx
->ReadSurface
= read
;
361 assert(old_ctx
&& old_draw
&& old_read
);
363 *old_draw
= prev_draw
;
364 *old_read
= prev_read
;