* heterogeneous hardware devices in the future.
*
* The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are
- * opaque handles implemented with 32-bit unsigned integers.
- * It's up to the driver function or fallback function to look up the
- * handle and get an object.
- * By using opaque handles, we leave open the possibility of having
- * indirect rendering in the future, like GLX.
+ * opaque handles. Internal objects are linked to a display to
+ * create the handles.
*
+ * For each public API entry point, the opaque handles are looked up
+ * before being dispatched to the drivers. When it fails to look up
+ * a handle, one of
+ *
+ * EGL_BAD_DISPLAY
+ * EGL_BAD_CONFIG
+ * EGL_BAD_CONTEXT
+ * EGL_BAD_SURFACE
+ * EGL_BAD_SCREEN_MESA
+ * EGL_BAD_MODE_MESA
+ *
+ * is generated and the driver function is not called. An
+ * uninitialized EGLDisplay has no driver associated with it. When
+ * such display is detected,
+ *
+ * EGL_NOT_INITIALIZED
+ *
+ * is generated.
+ *
+ * Some of the entry points use current display, context, or surface
+ * implicitly. For such entry points, the implicit objects are also
+ * checked before calling the driver function. Other than the
+ * errors listed above,
+ *
+ * EGL_BAD_CURRENT_SURFACE
+ *
+ * may also be generated.
*
* Notes on naming conventions:
*
#include "eglconfig.h"
#include "eglscreen.h"
#include "eglmode.h"
+#include "eglimage.h"
/**
* We initialize our global vars and create a private _EGLDisplay object.
*/
EGLDisplay EGLAPIENTRY
-eglGetDisplay(NativeDisplayType nativeDisplay)
+eglGetDisplay(EGLNativeDisplayType nativeDisplay)
{
_EGLDisplay *dpy;
dpy = _eglFindDisplay(nativeDisplay);
eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
- _EGLDriver *drv;
EGLint major_int, minor_int;
if (!disp)
return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
- drv = disp->Driver;
- if (!drv) {
- drv = _eglOpenDriver(disp);
- if (!drv)
- return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
+ if (!disp->Initialized) {
+ _EGLDriver *drv = disp->Driver;
+
+ if (!drv) {
+ _eglPreloadDrivers();
+ drv = _eglMatchDriver(disp);
+ if (!drv)
+ return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
+ }
/* Initialize the particular display now */
- if (!drv->API.Initialize(drv, disp, &major_int, &minor_int)) {
- _eglCloseDriver(drv, disp);
+ if (!drv->API.Initialize(drv, disp, &major_int, &minor_int))
return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
- }
disp->APImajor = major_int;
disp->APIminor = minor_int;
snprintf(disp->Version, sizeof(disp->Version),
"%d.%d (%s)", major_int, minor_int, drv->Name);
- /* update the global notion of supported APIs */
- _eglGlobal.ClientAPIsMask |= disp->ClientAPIsMask;
+ /* limit to APIs supported by core */
+ disp->ClientAPIsMask &= _EGL_API_ALL_BITS;
disp->Driver = drv;
+ disp->Initialized = EGL_TRUE;
} else {
major_int = disp->APImajor;
minor_int = disp->APIminor;
eglTerminate(EGLDisplay dpy)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
- _EGLDriver *drv;
if (!disp)
return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
- drv = disp->Driver;
- if (drv) {
+ if (disp->Initialized) {
+ _EGLDriver *drv = disp->Driver;
+
drv->API.Terminate(drv, disp);
- _eglCloseDriver(drv, disp);
- disp->Driver = NULL;
+ /* do not reset disp->Driver */
+ disp->Initialized = EGL_FALSE;
}
return EGL_TRUE;
_eglError(EGL_BAD_DISPLAY, msg);
return NULL;
}
- if (!disp->Driver) {
+ if (!disp->Initialized) {
_eglError(EGL_NOT_INITIALIZED, msg);
return NULL;
}
EGLSurface EGLAPIENTRY
eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
- NativeWindowType window, const EGLint *attrib_list)
+ EGLNativeWindowType window, const EGLint *attrib_list)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
_EGLConfig *conf = _eglLookupConfig(config, disp);
EGLSurface EGLAPIENTRY
eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
- NativePixmapType pixmap, const EGLint *attrib_list)
+ EGLNativePixmapType pixmap, const EGLint *attrib_list)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
_EGLConfig *conf = _eglLookupConfig(config, disp);
EGLBoolean EGLAPIENTRY
eglSwapInterval(EGLDisplay dpy, EGLint interval)
{
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLSurface *surf;
_EGL_DECLARE_DD(dpy);
- return drv->API.SwapInterval(drv, disp, interval);
+
+ if (!ctx || !_eglIsContextLinked(ctx) || ctx->Resource.Display != disp)
+ return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
+
+ surf = ctx->DrawSurface;
+ if (!_eglIsSurfaceLinked(surf))
+ return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+
+ return drv->API.SwapInterval(drv, disp, surf, interval);
}
EGLBoolean EGLAPIENTRY
eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
{
+ _EGLContext *ctx = _eglGetCurrentContext();
_EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+
+ /* surface must be bound to current context in EGL 1.4 */
+ if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface)
+ return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+
return drv->API.SwapBuffers(drv, disp, surf);
}
EGLBoolean EGLAPIENTRY
-eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
+eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
{
_EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
return drv->API.CopyBuffers(drv, disp, surf, target);
EGLBoolean EGLAPIENTRY
-eglWaitGL(void)
+eglWaitClient(void)
{
- _EGLDisplay *disp = _eglGetCurrentDisplay();
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLDisplay *disp;
_EGLDriver *drv;
- if (!disp)
+ if (!ctx)
return EGL_TRUE;
+ /* let bad current context imply bad current surface */
+ if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
+ return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
- /* a current display is always initialized */
+ /* a valid current context implies an initialized current display */
+ disp = ctx->Resource.Display;
+ assert(disp->Initialized);
drv = disp->Driver;
- return drv->API.WaitGL(drv, disp);
+ return drv->API.WaitClient(drv, disp, ctx);
+}
+
+
+EGLBoolean EGLAPIENTRY
+eglWaitGL(void)
+{
+#ifdef EGL_VERSION_1_2
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ EGLint api_index = t->CurrentAPIIndex;
+ EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
+ EGLBoolean ret;
+
+ if (api_index != es_index && _eglIsCurrentThreadDummy())
+ return _eglError(EGL_BAD_ALLOC, "eglWaitGL");
+
+ t->CurrentAPIIndex = es_index;
+ ret = eglWaitClient();
+ t->CurrentAPIIndex = api_index;
+ return ret;
+#else
+ return eglWaitClient();
+#endif
}
EGLBoolean EGLAPIENTRY
eglWaitNative(EGLint engine)
{
- _EGLDisplay *disp = _eglGetCurrentDisplay();
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLDisplay *disp;
_EGLDriver *drv;
- if (!disp)
+ if (!ctx)
return EGL_TRUE;
+ /* let bad current context imply bad current surface */
+ if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
+ return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
- /* a current display is always initialized */
+ /* a valid current context implies an initialized current display */
+ disp = ctx->Resource.Display;
+ assert(disp->Initialized);
drv = disp->Driver;
return drv->API.WaitNative(drv, disp, engine);
EGLDisplay EGLAPIENTRY
eglGetCurrentDisplay(void)
{
- _EGLDisplay *dpy = _eglGetCurrentDisplay();
- return _eglGetDisplayHandle(dpy);
+ _EGLContext *ctx = _eglGetCurrentContext();
+ return (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
}
EGLSurface EGLAPIENTRY
eglGetCurrentSurface(EGLint readdraw)
{
- _EGLSurface *s = _eglGetCurrentSurface(readdraw);
- return _eglGetSurfaceHandle(s);
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLSurface *surf;
+
+ if (!ctx)
+ return EGL_NO_SURFACE;
+
+ switch (readdraw) {
+ case EGL_DRAW:
+ surf = ctx->DrawSurface;
+ break;
+ case EGL_READ:
+ surf = ctx->ReadSurface;
+ break;
+ default:
+ _eglError(EGL_BAD_PARAMETER, __FUNCTION__);
+ surf = NULL;
+ break;
+ }
+
+ return _eglGetSurfaceHandle(surf);
}
}
-void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
+__eglMustCastToProperFunctionPointerType EGLAPIENTRY
+eglGetProcAddress(const char *procname)
{
static const struct {
const char *name;
{ "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
{ "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
#endif /* EGL_MESA_screen_surface */
+#ifdef EGL_KHR_image_base
+ { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
+ { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
+#endif /* EGL_KHR_image_base */
{ NULL, NULL }
};
EGLint i;
}
}
- /* preload a driver if there isn't one */
- if (!_eglGlobal.NumDrivers)
- _eglPreloadDriver(NULL);
+ _eglPreloadDrivers();
/* now loop over drivers to query their procs */
for (i = 0; i < _eglGlobal.NumDrivers; i++) {
- _EGLProc p = _eglGlobal.Drivers[i]->API.GetProcAddress(procname);
+ _EGLDriver *drv = _eglGlobal.Drivers[i];
+ _EGLProc p = drv->API.GetProcAddress(drv, procname);
if (p)
return p;
}
if (!_eglIsApiValid(api))
return _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
- switch (api) {
-#ifdef EGL_VERSION_1_4
- case EGL_OPENGL_API:
- if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT) {
- t->CurrentAPIIndex = _eglConvertApiToIndex(api);
- return EGL_TRUE;
- }
- _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
- return EGL_FALSE;
-#endif
- case EGL_OPENGL_ES_API:
- if (_eglGlobal.ClientAPIsMask & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)) {
- t->CurrentAPIIndex = _eglConvertApiToIndex(api);
- return EGL_TRUE;
- }
- _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
- return EGL_FALSE;
- case EGL_OPENVG_API:
- if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT) {
- t->CurrentAPIIndex = _eglConvertApiToIndex(api);
- return EGL_TRUE;
- }
- _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
- return EGL_FALSE;
- default:
- return EGL_FALSE;
- }
+ t->CurrentAPIIndex = _eglConvertApiToIndex(api);
return EGL_TRUE;
}
EGLBoolean
eglReleaseThread(void)
{
- /* unbind current context */
+ /* unbind current contexts */
if (!_eglIsCurrentThreadDummy()) {
- _EGLDisplay *disp = _eglGetCurrentDisplay();
- _EGLDriver *drv;
- if (disp) {
- drv = disp->Driver;
- (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ EGLint i;
+
+ for (i = 0; i < _EGL_API_NUM_APIS; i++) {
+ _EGLContext *ctx = t->CurrentContexts[i];
+ if (ctx) {
+ _EGLDisplay *disp = ctx->Resource.Display;
+ _EGLDriver *drv = disp->Driver;
+ /* what if display is not initialized? */
+ if (disp->Initialized)
+ (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
+ }
}
}
}
-EGLBoolean
-eglWaitClient(void)
+#endif /* EGL_VERSION_1_2 */
+
+
+#ifdef EGL_KHR_image_base
+
+
+EGLImageKHR
+eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+ EGLClientBuffer buffer, const EGLint *attr_list)
{
- _EGLDisplay *disp = _eglGetCurrentDisplay();
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLContext *context = _eglLookupContext(ctx, disp);
_EGLDriver *drv;
+ _EGLImage *img;
- if (!disp)
- return EGL_TRUE;
+ drv = _eglCheckDisplay(disp, __FUNCTION__);
+ if (!drv)
+ return EGL_NO_IMAGE_KHR;
+ if (!context && ctx != EGL_NO_CONTEXT) {
+ _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
+ return EGL_NO_IMAGE_KHR;
+ }
- /* a current display is always initialized */
- drv = disp->Driver;
+ img = drv->API.CreateImageKHR(drv,
+ disp, context, target, buffer, attr_list);
+ if (img)
+ return _eglLinkImage(img, disp);
+ else
+ return EGL_NO_IMAGE_KHR;
+}
+
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLImage *img = _eglLookupImage(image, disp);
+ _EGLDriver *drv;
- return drv->API.WaitClient(drv, disp);
+ drv = _eglCheckDisplay(disp, __FUNCTION__);
+ if (!drv)
+ return EGL_FALSE;
+ if (!img)
+ return _eglError(EGL_BAD_PARAMETER, __FUNCTION__);
+
+ _eglUnlinkImage(img);
+ return drv->API.DestroyImageKHR(drv, disp, img);
}
-#endif /* EGL_VERSION_1_2 */
+#endif /* EGL_KHR_image_base */