eglcontext.c revision adbff7e977c7c768e752a24fb643d68bdf961bfe
1#include <assert.h> 2#include <stdlib.h> 3#include <string.h> 4#include "eglconfig.h" 5#include "eglcontext.h" 6#include "egldriver.h" 7#include "eglglobals.h" 8#include "eglhash.h" 9#include "eglsurface.h" 10 11 12/** 13 * Initialize the given _EGLContext object to defaults. 14 */ 15void 16_eglInitContext(_EGLContext *ctx) 17{ 18 /* just init to zer for now */ 19 memset(ctx, 0, sizeof(_EGLContext)); 20} 21 22 23/* 24 * Assign an EGLContext handle to the _EGLContext object then put it into 25 * the hash table. 26 */ 27void 28_eglSaveContext(_EGLContext *ctx) 29{ 30 assert(ctx); 31 ctx->Handle = _eglHashGenKey(_eglGlobal.Contexts); 32 _eglHashInsert(_eglGlobal.Contexts, ctx->Handle, ctx); 33} 34 35 36/** 37 * Remove the given _EGLContext object from the hash table. 38 */ 39void 40_eglRemoveContext(_EGLContext *ctx) 41{ 42 _eglHashRemove(_eglGlobal.Contexts, ctx->Handle); 43} 44 45 46/** 47 * Return the _EGLContext object that corresponds to the given 48 * EGLContext handle. 49 */ 50_EGLContext * 51_eglLookupContext(EGLContext ctx) 52{ 53 _EGLContext *c = (_EGLContext *) _eglHashLookup(_eglGlobal.Contexts, ctx); 54 return c; 55} 56 57 58/** 59 * Return the currently bound _EGLContext object, or NULL. 60 */ 61_EGLContext * 62_eglGetCurrentContext(void) 63{ 64 /* XXX this should be per-thread someday */ 65 return _eglGlobal.CurrentContext; 66} 67 68 69/** 70 * Just a placeholder/demo function. Real driver will never use this! 71 */ 72EGLContext 73_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list) 74{ 75 _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); 76 if (!conf) { 77 _eglError(EGL_BAD_CONFIG, "eglCreateContext"); 78 return EGL_NO_CONTEXT; 79 } 80 81 if (share_list != EGL_NO_CONTEXT) { 82 _EGLContext *shareCtx = _eglLookupContext(share_list); 83 if (!shareCtx) { 84 _eglError(EGL_BAD_CONTEXT, "eglCreateContext(share_list)"); 85 return EGL_NO_CONTEXT; 86 } 87 } 88 89 return EGL_NO_CONTEXT; 90} 91 92 93/** 94 * Default fallback routine - drivers should usually override this. 95 */ 96EGLBoolean 97_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) 98{ 99 _EGLContext *context = _eglLookupContext(ctx); 100 if (context) { 101 _eglHashRemove(_eglGlobal.Contexts, ctx); 102 if (context->IsBound) { 103 context->DeletePending = EGL_TRUE; 104 } 105 else { 106 free(context); 107 } 108 return EGL_TRUE; 109 } 110 else { 111 _eglError(EGL_BAD_CONTEXT, "eglDestroyContext"); 112 return EGL_TRUE; 113 } 114} 115 116 117EGLBoolean 118_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) 119{ 120 _EGLContext *c = _eglLookupContext(ctx); 121 122 (void) drv; 123 (void) dpy; 124 125 if (!c) { 126 _eglError(EGL_BAD_CONTEXT, "eglQueryContext"); 127 return EGL_FALSE; 128 } 129 130 switch (attribute) { 131 case EGL_CONFIG_ID: 132 *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID); 133 return EGL_TRUE; 134 default: 135 _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); 136 return EGL_FALSE; 137 } 138} 139 140 141/** 142 * Drivers will typically call this to do the error checking and 143 * update the various IsBound and DeletePending flags. 144 * Then, the driver will do its device-dependent Make-Current stuff. 145 */ 146EGLBoolean 147_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, EGLSurface r, EGLContext context) 148{ 149 _EGLContext *ctx = _eglLookupContext(context); 150 _EGLSurface *draw = _eglLookupSurface(d); 151 _EGLSurface *read = _eglLookupSurface(r); 152 153 _EGLContext *oldContext = _eglGetCurrentContext(); 154 _EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW); 155 _EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ); 156 157 /* error checking */ 158 if (ctx) { 159 if (draw == NULL || read == NULL) { 160 _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 161 return EGL_FALSE; 162 } 163 if (draw->Config != ctx->Config) { 164 _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 165 return EGL_FALSE; 166 } 167 if (read->Config != ctx->Config) { 168 _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 169 return EGL_FALSE; 170 } 171 } 172 173 /* 174 * check if the old context or surfaces need to be deleted 175 */ 176 if (oldDrawSurface != NULL) { 177 oldDrawSurface->IsBound = EGL_FALSE; 178 if (oldDrawSurface->DeletePending) { 179 /* make sure we don't try to rebind a deleted surface */ 180 if (draw == oldDrawSurface || draw == oldReadSurface) { 181 draw = NULL; 182 } 183 /* really delete surface now */ 184 drv->DestroySurface(drv, dpy, oldDrawSurface->Handle); 185 } 186 } 187 if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) { 188 oldReadSurface->IsBound = EGL_FALSE; 189 if (oldReadSurface->DeletePending) { 190 /* make sure we don't try to rebind a deleted surface */ 191 if (read == oldDrawSurface || read == oldReadSurface) { 192 read = NULL; 193 } 194 /* really delete surface now */ 195 drv->DestroySurface(drv, dpy, oldReadSurface->Handle); 196 } 197 } 198 if (oldContext != NULL) { 199 oldContext->IsBound = EGL_FALSE; 200 if (oldContext->DeletePending) { 201 /* make sure we don't try to rebind a deleted context */ 202 if (ctx == oldContext) { 203 ctx = NULL; 204 } 205 /* really delete context now */ 206 drv->DestroyContext(drv, dpy, oldContext->Handle); 207 } 208 } 209 210 if (ctx) { 211 /* check read/draw again, in case we deleted them above */ 212 if (draw == NULL || read == NULL) { 213 _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 214 return EGL_FALSE; 215 } 216 ctx->DrawSurface = draw; 217 ctx->ReadSurface = read; 218 ctx->IsBound = EGL_TRUE; 219 draw->IsBound = EGL_TRUE; 220 read->IsBound = EGL_TRUE; 221 } 222 223 _eglGlobal.CurrentContext = ctx; 224 225 return EGL_TRUE; 226} 227