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
);
86 if (err
== EGL_SUCCESS
) {
87 EGLint renderable_type
, api_bit
;
89 renderable_type
= GET_CONFIG_ATTRIB(ctx
->Config
, EGL_RENDERABLE_TYPE
);
90 api_bit
= _eglGetContextAPIBit(ctx
);
91 if (!(renderable_type
& api_bit
))
100 * Initialize the given _EGLContext object to defaults and/or the values
101 * in the attrib_list.
104 _eglInitContext(_EGLContext
*ctx
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
105 const EGLint
*attrib_list
)
107 const EGLenum api
= eglQueryAPI();
110 if (api
== EGL_NONE
) {
111 _eglError(EGL_BAD_MATCH
, "eglCreateContext(no client API)");
115 memset(ctx
, 0, sizeof(_EGLContext
));
116 ctx
->Resource
.Display
= dpy
;
117 ctx
->ClientAPI
= api
;
119 ctx
->WindowRenderBuffer
= EGL_NONE
;
121 ctx
->ClientVersion
= 1; /* the default, per EGL spec */
123 err
= _eglParseContextAttribList(ctx
, attrib_list
);
124 if (err
!= EGL_SUCCESS
)
125 return _eglError(err
, "eglCreateContext");
132 * Just a placeholder/demo function. Real driver will never use this!
135 _eglCreateContext(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
136 _EGLContext
*share_list
, const EGLint
*attrib_list
)
143 * Default fallback routine - drivers should usually override this.
146 _eglDestroyContext(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
148 if (!_eglIsContextBound(ctx
))
154 #ifdef EGL_VERSION_1_2
156 _eglQueryContextRenderBuffer(_EGLContext
*ctx
)
158 _EGLSurface
*surf
= ctx
->DrawSurface
;
163 if (surf
->Type
== EGL_WINDOW_BIT
&& ctx
->WindowRenderBuffer
!= EGL_NONE
)
164 rb
= ctx
->WindowRenderBuffer
;
166 rb
= surf
->RenderBuffer
;
169 #endif /* EGL_VERSION_1_2 */
173 _eglQueryContext(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*c
,
174 EGLint attribute
, EGLint
*value
)
180 return _eglError(EGL_BAD_PARAMETER
, "eglQueryContext");
184 *value
= GET_CONFIG_ATTRIB(c
->Config
, EGL_CONFIG_ID
);
186 case EGL_CONTEXT_CLIENT_VERSION
:
187 *value
= c
->ClientVersion
;
189 #ifdef EGL_VERSION_1_2
190 case EGL_CONTEXT_CLIENT_TYPE
:
191 *value
= c
->ClientAPI
;
193 case EGL_RENDER_BUFFER
:
194 *value
= _eglQueryContextRenderBuffer(c
);
196 #endif /* EGL_VERSION_1_2 */
198 return _eglError(EGL_BAD_ATTRIBUTE
, "eglQueryContext");
206 * Bind the context to the surfaces. Return the surfaces that are "orphaned".
207 * That is, when the context is not NULL, return the surfaces it previously
208 * bound to; when the context is NULL, the same surfaces are returned.
211 _eglBindContextToSurfaces(_EGLContext
*newCtx
,
212 _EGLSurface
**draw
, _EGLSurface
**read
)
214 _EGLSurface
*newDraw
= *draw
, *newRead
= *read
;
218 * The goal is to bind a newCtx to newDraw. Since newDraw may already have
219 * a binding context (oldCtx), and newCtx may already be bound to another
220 * surface (oldDraw), the old bindings are broken first and the new one is
223 oldCtx
= newDraw
->CurrentContext
;
224 if (newCtx
!= oldCtx
) {
226 assert(oldCtx
->DrawSurface
== newDraw
);
227 oldCtx
->DrawSurface
= NULL
;
231 _EGLSurface
*oldDraw
= newCtx
->DrawSurface
;
233 oldDraw
->CurrentContext
= NULL
;
235 newCtx
->DrawSurface
= newDraw
;
239 newDraw
->CurrentContext
= newCtx
;
243 if (newRead
!= newDraw
)
244 oldCtx
= newRead
->CurrentContext
;
245 if (newCtx
!= oldCtx
) {
247 assert(oldCtx
->ReadSurface
== newRead
);
248 oldCtx
->ReadSurface
= NULL
;
252 _EGLSurface
*oldRead
= newCtx
->ReadSurface
;
254 oldRead
->CurrentContext
= NULL
;
256 newCtx
->ReadSurface
= newRead
;
260 newRead
->CurrentContext
= newCtx
;
266 * Bind the context to the thread and return the previous context.
268 * Note that the context may be NULL.
271 _eglBindContextToThread(_EGLContext
*ctx
, _EGLThreadInfo
*t
)
277 _eglConvertApiToIndex(ctx
->ClientAPI
) : t
->CurrentAPIIndex
;
279 oldCtx
= t
->CurrentContexts
[apiIndex
];
282 oldCtx
->Binding
= NULL
;
286 t
->CurrentContexts
[apiIndex
] = ctx
;
294 * Return true if the given context and surfaces can be made current.
297 _eglCheckMakeCurrent(_EGLContext
*ctx
, _EGLSurface
*draw
, _EGLSurface
*read
)
299 _EGLThreadInfo
*t
= _eglGetCurrentThread();
302 if (_eglIsCurrentThreadDummy())
303 return _eglError(EGL_BAD_ALLOC
, "eglMakeCurrent");
308 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
312 /* ctx/draw/read must be all given */
313 if (draw
== NULL
|| read
== NULL
)
314 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
316 /* context stealing from another thread is not allowed */
317 if (ctx
->Binding
&& ctx
->Binding
!= t
)
318 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
323 * "If ctx is current to some other thread, or if either draw or read are
324 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
329 * "at most one context may be bound to a particular surface at a given
332 * The latter is more restrictive so we can check only the latter case.
334 if ((draw
->CurrentContext
&& draw
->CurrentContext
!= ctx
) ||
335 (read
->CurrentContext
&& read
->CurrentContext
!= ctx
))
336 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
338 /* simply require the configs to be equal */
339 if (draw
->Config
!= ctx
->Config
|| read
->Config
!= ctx
->Config
)
340 return _eglError(EGL_BAD_MATCH
, "eglMakeCurrent");
342 switch (ctx
->ClientAPI
) {
343 #ifdef EGL_VERSION_1_4
344 /* OpenGL and OpenGL ES are conflicting */
345 case EGL_OPENGL_ES_API
:
346 conflict_api
= EGL_OPENGL_API
;
349 conflict_api
= EGL_OPENGL_ES_API
;
357 if (conflict_api
>= 0 && _eglGetAPIContext(conflict_api
))
358 return _eglError(EGL_BAD_ACCESS
, "eglMakeCurrent");
365 * Bind the context to the current thread and given surfaces. Return the
366 * previously bound context and the surfaces it bound to. Each argument is
367 * both input and output.
370 _eglBindContext(_EGLContext
**ctx
, _EGLSurface
**draw
, _EGLSurface
**read
)
372 _EGLThreadInfo
*t
= _eglGetCurrentThread();
373 _EGLContext
*newCtx
= *ctx
, *oldCtx
;
375 if (!_eglCheckMakeCurrent(newCtx
, *draw
, *read
))
378 /* bind the new context */
379 oldCtx
= _eglBindContextToThread(newCtx
, t
);
382 _eglBindContextToSurfaces(newCtx
, draw
, read
);
384 /* unbind the old context from its binding surfaces */
385 if (oldCtx
&& oldCtx
!= newCtx
) {
386 assert(!*draw
&& !*read
);
388 *draw
= oldCtx
->DrawSurface
;
389 *read
= oldCtx
->ReadSurface
;
390 assert(*draw
&& *read
);
392 _eglBindContextToSurfaces(NULL
, draw
, read
);
396 /* draw and read have been updated in _eglBindContextToSurfaces */
403 * Just a placeholder/demo function. Drivers should override this.
406 _eglMakeCurrent(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*draw
,
407 _EGLSurface
*read
, _EGLContext
*ctx
)
414 * This is defined by the EGL_MESA_copy_context extension.
417 _eglCopyContextMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext source
,
418 EGLContext dest
, EGLint mask
)
420 /* This function will always have to be overridden/implemented in the
421 * device driver. If the driver is based on Mesa, use _mesa_copy_context().