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 memset(ctx
, 0, sizeof(_EGLContext
));
107 ctx
->Resource
.Display
= dpy
;
108 ctx
->ClientAPI
= api
;
110 ctx
->WindowRenderBuffer
= EGL_NONE
;
112 ctx
->ClientVersion
= 1; /* the default, per EGL spec */
114 err
= _eglParseContextAttribList(ctx
, attrib_list
);
115 if (err
== EGL_SUCCESS
&& ctx
->Config
) {
118 api_bit
= _eglGetContextAPIBit(ctx
);
119 if (!(ctx
->Config
->RenderableType
& api_bit
)) {
120 _eglLog(_EGL_DEBUG
, "context api is 0x%x while config supports 0x%x",
121 api_bit
, ctx
->Config
->RenderableType
);
122 err
= EGL_BAD_CONFIG
;
125 if (err
!= EGL_SUCCESS
)
126 return _eglError(err
, "eglCreateContext");
133 * Just a placeholder/demo function. Real driver will never use this!
136 _eglCreateContext(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
137 _EGLContext
*share_list
, const EGLint
*attrib_list
)
144 * Default fallback routine - drivers should usually override this.
147 _eglDestroyContext(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
149 if (!_eglIsContextBound(ctx
))
155 #ifdef EGL_VERSION_1_2
157 _eglQueryContextRenderBuffer(_EGLContext
*ctx
)
159 _EGLSurface
*surf
= ctx
->DrawSurface
;
164 if (surf
->Type
== EGL_WINDOW_BIT
&& ctx
->WindowRenderBuffer
!= EGL_NONE
)
165 rb
= ctx
->WindowRenderBuffer
;
167 rb
= surf
->RenderBuffer
;
170 #endif /* EGL_VERSION_1_2 */
174 _eglQueryContext(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*c
,
175 EGLint attribute
, EGLint
*value
)
181 return _eglError(EGL_BAD_PARAMETER
, "eglQueryContext");
186 return _eglError(EGL_BAD_ATTRIBUTE
, "eglQueryContext");
187 *value
= c
->Config
->ConfigID
;
189 case EGL_CONTEXT_CLIENT_VERSION
:
190 *value
= c
->ClientVersion
;
192 #ifdef EGL_VERSION_1_2
193 case EGL_CONTEXT_CLIENT_TYPE
:
194 *value
= c
->ClientAPI
;
196 case EGL_RENDER_BUFFER
:
197 *value
= _eglQueryContextRenderBuffer(c
);
199 #endif /* EGL_VERSION_1_2 */
201 return _eglError(EGL_BAD_ATTRIBUTE
, "eglQueryContext");
209 * Bind the context to the thread and return the previous context.
211 * Note that the context may be NULL.
214 _eglBindContextToThread(_EGLContext
*ctx
, _EGLThreadInfo
*t
)
220 _eglConvertApiToIndex(ctx
->ClientAPI
) : t
->CurrentAPIIndex
;
222 oldCtx
= t
->CurrentContexts
[apiIndex
];
225 oldCtx
->Binding
= NULL
;
229 t
->CurrentContexts
[apiIndex
] = ctx
;
237 * Return true if the given context and surfaces can be made current.
240 _eglCheckMakeCurrent(_EGLContext
*ctx
, _EGLSurface
*draw
, _EGLSurface
*read
)
242 _EGLThreadInfo
*t
= _eglGetCurrentThread();
245 EGLBoolean surfaceless
;
247 if (_eglIsCurrentThreadDummy())
248 return _eglError(EGL_BAD_ALLOC
, "eglMakeCurrent");
253 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
257 dpy
= ctx
->Resource
.Display
;
258 switch (_eglGetContextAPIBit(ctx
)) {
259 case EGL_OPENGL_ES_BIT
:
260 surfaceless
= dpy
->Extensions
.KHR_surfaceless_gles1
;
262 case EGL_OPENGL_ES2_BIT
:
263 surfaceless
= dpy
->Extensions
.KHR_surfaceless_gles2
;
266 surfaceless
= dpy
->Extensions
.KHR_surfaceless_opengl
;
269 surfaceless
= EGL_FALSE
;
273 if (!surfaceless
&& (draw
== NULL
|| read
== NULL
))
274 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
276 /* context stealing from another thread is not allowed */
277 if (ctx
->Binding
&& ctx
->Binding
!= t
)
278 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
283 * "If ctx is current to some other thread, or if either draw or read are
284 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
289 * "at most one context may be bound to a particular surface at a given
292 * The latter is more restrictive so we can check only the latter case.
294 if ((draw
&& draw
->CurrentContext
&& draw
->CurrentContext
!= ctx
) ||
295 (read
&& read
->CurrentContext
&& read
->CurrentContext
!= ctx
))
296 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
298 /* simply require the configs to be equal */
299 if ((draw
&& draw
->Config
!= ctx
->Config
) ||
300 (read
&& read
->Config
!= ctx
->Config
))
301 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
303 switch (ctx
->ClientAPI
) {
304 #ifdef EGL_VERSION_1_4
305 /* OpenGL and OpenGL ES are conflicting */
306 case EGL_OPENGL_ES_API
:
307 conflict_api
= EGL_OPENGL_API
;
310 conflict_api
= EGL_OPENGL_ES_API
;
318 if (conflict_api
>= 0 && _eglGetAPIContext(conflict_api
))
319 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
326 * Bind the context to the current thread and given surfaces. Return the
327 * "orphaned" context and surfaces. Each argument is both input and output.
330 _eglBindContext(_EGLContext
**ctx
, _EGLSurface
**draw
, _EGLSurface
**read
)
332 _EGLThreadInfo
*t
= _eglGetCurrentThread();
333 _EGLContext
*newCtx
= *ctx
, *oldCtx
;
334 _EGLSurface
*newDraw
= *draw
, *newRead
= *read
;
336 if (!_eglCheckMakeCurrent(newCtx
, newDraw
, newRead
))
339 /* bind the new context */
340 oldCtx
= _eglBindContextToThread(newCtx
, t
);
342 /* break old bindings */
345 *draw
= oldCtx
->DrawSurface
;
346 *read
= oldCtx
->ReadSurface
;
349 (*draw
)->CurrentContext
= NULL
;
351 (*read
)->CurrentContext
= NULL
;
353 oldCtx
->DrawSurface
= NULL
;
354 oldCtx
->ReadSurface
= NULL
;
357 /* establish new bindings */
360 newDraw
->CurrentContext
= newCtx
;
362 newRead
->CurrentContext
= newCtx
;
364 newCtx
->DrawSurface
= newDraw
;
365 newCtx
->ReadSurface
= newRead
;
368 /* an old context or surface is not orphaned if it is still bound */
371 if (*draw
== newDraw
|| *draw
== newRead
)
373 if (*read
== newDraw
|| *read
== newRead
)
381 * Just a placeholder/demo function. Drivers should override this.
384 _eglMakeCurrent(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*draw
,
385 _EGLSurface
*read
, _EGLContext
*ctx
)
392 * This is defined by the EGL_MESA_copy_context extension.
395 _eglCopyContextMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext source
,
396 EGLContext dest
, EGLint mask
)
398 /* This function will always have to be overridden/implemented in the
399 * device driver. If the driver is based on Mesa, use _mesa_copy_context().