summaryrefslogtreecommitdiff
path: root/src/egl/main/eglcontext.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl/main/eglcontext.c')
-rw-r--r--src/egl/main/eglcontext.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
new file mode 100644
index 0000000000..374c006dae
--- /dev/null
+++ b/src/egl/main/eglcontext.c
@@ -0,0 +1,276 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "eglconfig.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "eglhash.h"
+#include "eglsurface.h"
+
+
+/**
+ * Initialize the given _EGLContext object to defaults.
+ */
+EGLBoolean
+_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
+ EGLConfig config, const EGLint *attrib_list)
+{
+ _EGLConfig *conf;
+ _EGLDisplay *display = _eglLookupDisplay(dpy);
+ EGLint i;
+
+ conf = _eglLookupConfig(drv, dpy, config);
+ if (!conf) {
+ _eglError(EGL_BAD_CONFIG, "eglCreateContext");
+ return EGL_FALSE;
+ }
+
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ switch (attrib_list[i]) {
+ /* no attribs defined for now */
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
+ return EGL_NO_CONTEXT;
+ }
+ }
+
+ memset(ctx, 0, sizeof(_EGLContext));
+ ctx->Display = display;
+ ctx->Config = conf;
+ ctx->DrawSurface = EGL_NO_SURFACE;
+ ctx->ReadSurface = EGL_NO_SURFACE;
+
+ return EGL_TRUE;
+}
+
+
+/*
+ * Assign an EGLContext handle to the _EGLContext object then put it into
+ * the hash table.
+ */
+void
+_eglSaveContext(_EGLContext *ctx)
+{
+ assert(ctx);
+ ctx->Handle = _eglHashGenKey(_eglGlobal.Contexts);
+ _eglHashInsert(_eglGlobal.Contexts, ctx->Handle, ctx);
+}
+
+
+/**
+ * Remove the given _EGLContext object from the hash table.
+ */
+void
+_eglRemoveContext(_EGLContext *ctx)
+{
+ _eglHashRemove(_eglGlobal.Contexts, ctx->Handle);
+}
+
+
+/**
+ * Return the _EGLContext object that corresponds to the given
+ * EGLContext handle.
+ */
+_EGLContext *
+_eglLookupContext(EGLContext ctx)
+{
+ _EGLContext *c = (_EGLContext *) _eglHashLookup(_eglGlobal.Contexts, ctx);
+ return c;
+}
+
+
+/**
+ * Return the currently bound _EGLContext object, or NULL.
+ */
+_EGLContext *
+_eglGetCurrentContext(void)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ return t->CurrentContext;
+}
+
+
+/**
+ * Just a placeholder/demo function. Real driver will never use this!
+ */
+EGLContext
+_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+ EGLContext share_list, const EGLint *attrib_list)
+{
+#if 0 /* example code */
+ _EGLContext *context;
+
+ context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
+ if (!context)
+ return EGL_NO_CONTEXT;
+
+ if (!_eglInitContext(drv, dpy, context, config, attrib_list)) {
+ free(context);
+ return EGL_NO_CONTEXT;
+ }
+
+ _eglSaveContext(context);
+ return context->Handle;
+#endif
+ return EGL_NO_CONTEXT;
+}
+
+
+/**
+ * Default fallback routine - drivers should usually override this.
+ */
+EGLBoolean
+_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
+{
+ _EGLContext *context = _eglLookupContext(ctx);
+ if (context) {
+ _eglHashRemove(_eglGlobal.Contexts, ctx);
+ if (context->IsBound) {
+ context->DeletePending = EGL_TRUE;
+ }
+ else {
+ free(context);
+ }
+ return EGL_TRUE;
+ }
+ else {
+ _eglError(EGL_BAD_CONTEXT, "eglDestroyContext");
+ return EGL_TRUE;
+ }
+}
+
+
+EGLBoolean
+_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
+ EGLint attribute, EGLint *value)
+{
+ _EGLContext *c = _eglLookupContext(ctx);
+
+ (void) drv;
+ (void) dpy;
+
+ if (!c) {
+ _eglError(EGL_BAD_CONTEXT, "eglQueryContext");
+ return EGL_FALSE;
+ }
+
+ switch (attribute) {
+ case EGL_CONFIG_ID:
+ *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
+ return EGL_TRUE;
+#ifdef EGL_VERSION_1_2
+ case EGL_CONTEXT_CLIENT_TYPE:
+ *value = c->ClientAPI;
+ return EGL_FALSE;
+#endif /* EGL_VERSION_1_2 */
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
+ return EGL_FALSE;
+ }
+}
+
+
+/**
+ * Drivers will typically call this to do the error checking and
+ * update the various IsBound and DeletePending flags.
+ * Then, the driver will do its device-dependent Make-Current stuff.
+ */
+EGLBoolean
+_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
+ EGLSurface r, EGLContext context)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ _EGLContext *ctx = _eglLookupContext(context);
+ _EGLSurface *draw = _eglLookupSurface(d);
+ _EGLSurface *read = _eglLookupSurface(r);
+
+ _EGLContext *oldContext = _eglGetCurrentContext();
+ _EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW);
+ _EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ);
+
+ /* error checking */
+ if (ctx) {
+ if (draw == NULL || read == NULL) {
+ _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+ return EGL_FALSE;
+ }
+ if (draw->Config != ctx->Config) {
+ _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+ return EGL_FALSE;
+ }
+ if (read->Config != ctx->Config) {
+ _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+ return EGL_FALSE;
+ }
+ }
+
+ /*
+ * check if the old context or surfaces need to be deleted
+ */
+ if (oldDrawSurface != NULL) {
+ oldDrawSurface->IsBound = EGL_FALSE;
+ if (oldDrawSurface->DeletePending) {
+ /* make sure we don't try to rebind a deleted surface */
+ if (draw == oldDrawSurface || draw == oldReadSurface) {
+ draw = NULL;
+ }
+ /* really delete surface now */
+ drv->API.DestroySurface(drv, dpy, oldDrawSurface->Handle);
+ }
+ }
+ if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) {
+ oldReadSurface->IsBound = EGL_FALSE;
+ if (oldReadSurface->DeletePending) {
+ /* make sure we don't try to rebind a deleted surface */
+ if (read == oldDrawSurface || read == oldReadSurface) {
+ read = NULL;
+ }
+ /* really delete surface now */
+ drv->API.DestroySurface(drv, dpy, oldReadSurface->Handle);
+ }
+ }
+ if (oldContext != NULL) {
+ oldContext->IsBound = EGL_FALSE;
+ if (oldContext->DeletePending) {
+ /* make sure we don't try to rebind a deleted context */
+ if (ctx == oldContext) {
+ ctx = NULL;
+ }
+ /* really delete context now */
+ drv->API.DestroyContext(drv, dpy, oldContext->Handle);
+ }
+ }
+
+ if (ctx) {
+ /* check read/draw again, in case we deleted them above */
+ if (draw == NULL || read == NULL) {
+ _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+ return EGL_FALSE;
+ }
+ ctx->DrawSurface = draw;
+ ctx->ReadSurface = read;
+ ctx->IsBound = EGL_TRUE;
+ draw->IsBound = EGL_TRUE;
+ read->IsBound = EGL_TRUE;
+ }
+
+ t->CurrentContext = ctx;
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * This is defined by the EGL_MESA_copy_context extension.
+ */
+EGLBoolean
+_eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source,
+ EGLContext dest, EGLint mask)
+{
+ /* This function will always have to be overridden/implemented in the
+ * device driver. If the driver is based on Mesa, use _mesa_copy_context().
+ */
+ return EGL_FALSE;
+}