eglcontext.c revision 4a49301e
1#include <assert.h> 2#include <stdlib.h> 3#include <string.h> 4#include "eglconfig.h" 5#include "eglcontext.h" 6#include "egldisplay.h" 7#include "egldriver.h" 8#include "eglglobals.h" 9#include "eglsurface.h" 10 11 12/** 13 * Initialize the given _EGLContext object to defaults and/or the values 14 * in the attrib_list. 15 */ 16EGLBoolean 17_eglInitContext(_EGLDriver *drv, _EGLContext *ctx, 18 _EGLConfig *conf, const EGLint *attrib_list) 19{ 20 EGLint i; 21 const EGLenum api = eglQueryAPI(); 22 23 if (api == EGL_NONE) { 24 _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); 25 return EGL_FALSE; 26 } 27 28 memset(ctx, 0, sizeof(_EGLContext)); 29 30 ctx->ClientVersion = 1; /* the default, per EGL spec */ 31 32 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { 33 switch (attrib_list[i]) { 34 case EGL_CONTEXT_CLIENT_VERSION: 35 i++; 36 ctx->ClientVersion = attrib_list[i]; 37 break; 38 default: 39 _eglError(EGL_BAD_ATTRIBUTE, "_eglInitContext"); 40 return EGL_FALSE; 41 } 42 } 43 44 ctx->Config = conf; 45 ctx->DrawSurface = EGL_NO_SURFACE; 46 ctx->ReadSurface = EGL_NO_SURFACE; 47 ctx->ClientAPI = api; 48 ctx->WindowRenderBuffer = EGL_NONE; 49 50 return EGL_TRUE; 51} 52 53 54/** 55 * Just a placeholder/demo function. Real driver will never use this! 56 */ 57_EGLContext * 58_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, 59 _EGLContext *share_list, const EGLint *attrib_list) 60{ 61#if 0 /* example code */ 62 _EGLContext *context; 63 64 context = (_EGLContext *) calloc(1, sizeof(_EGLContext)); 65 if (!context) 66 return NULL; 67 68 if (!_eglInitContext(drv, context, conf, attrib_list)) { 69 free(context); 70 return NULL; 71 } 72 73 return context; 74#endif 75 return NULL; 76} 77 78 79/** 80 * Default fallback routine - drivers should usually override this. 81 */ 82EGLBoolean 83_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) 84{ 85 if (!_eglIsContextBound(ctx)) 86 free(ctx); 87 return EGL_TRUE; 88} 89 90 91#ifdef EGL_VERSION_1_2 92static EGLint 93_eglQueryContextRenderBuffer(_EGLContext *ctx) 94{ 95 _EGLSurface *surf = ctx->DrawSurface; 96 EGLint rb; 97 98 if (!surf) 99 return EGL_NONE; 100 if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE) 101 rb = ctx->WindowRenderBuffer; 102 else 103 rb = surf->RenderBuffer; 104 return rb; 105} 106#endif /* EGL_VERSION_1_2 */ 107 108 109EGLBoolean 110_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c, 111 EGLint attribute, EGLint *value) 112{ 113 (void) drv; 114 (void) dpy; 115 116 if (!value) 117 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext"); 118 119 switch (attribute) { 120 case EGL_CONFIG_ID: 121 *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID); 122 break; 123 case EGL_CONTEXT_CLIENT_VERSION: 124 *value = c->ClientVersion; 125 break; 126#ifdef EGL_VERSION_1_2 127 case EGL_CONTEXT_CLIENT_TYPE: 128 *value = c->ClientAPI; 129 break; 130 case EGL_RENDER_BUFFER: 131 *value = _eglQueryContextRenderBuffer(c); 132 break; 133#endif /* EGL_VERSION_1_2 */ 134 default: 135 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); 136 } 137 138 return EGL_TRUE; 139} 140 141 142/** 143 * Drivers will typically call this to do the error checking and 144 * update the various flags. 145 * Then, the driver will do its device-dependent Make-Current stuff. 146 */ 147EGLBoolean 148_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, 149 _EGLSurface *read, _EGLContext *ctx) 150{ 151 _EGLThreadInfo *t = _eglGetCurrentThread(); 152 _EGLContext *oldContext = NULL; 153 _EGLSurface *oldDrawSurface = NULL; 154 _EGLSurface *oldReadSurface = NULL; 155 EGLint apiIndex; 156 157 if (_eglIsCurrentThreadDummy()) 158 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); 159 160 if (ctx) { 161 /* error checking */ 162 if (ctx->Binding && ctx->Binding != t) 163 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 164 if (draw == NULL || read == NULL) 165 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 166 if (draw->Config != ctx->Config || read->Config != ctx->Config) 167 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 168 if ((draw->Binding && draw->Binding->Binding != t) || 169 (read->Binding && read->Binding->Binding != t)) 170 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 171 172#ifdef EGL_VERSION_1_4 173 /* OpenGL and OpenGL ES are conflicting */ 174 switch (ctx->ClientAPI) { 175 case EGL_OPENGL_ES_API: 176 if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)]) 177 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 178 break; 179 case EGL_OPENGL_API: 180 if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_ES_API)]) 181 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 182 break; 183 default: 184 break; 185 } 186#endif 187 apiIndex = _eglConvertApiToIndex(ctx->ClientAPI); 188 } 189 else { 190 if (draw != NULL || read != NULL) 191 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 192 apiIndex = t->CurrentAPIIndex; 193 } 194 195 oldContext = t->CurrentContexts[apiIndex]; 196 if (oldContext) { 197 oldDrawSurface = oldContext->DrawSurface; 198 oldReadSurface = oldContext->ReadSurface; 199 assert(oldDrawSurface); 200 assert(oldReadSurface); 201 202 /* break old bindings */ 203 t->CurrentContexts[apiIndex] = NULL; 204 oldContext->Binding = NULL; 205 oldContext->DrawSurface = NULL; 206 oldContext->ReadSurface = NULL; 207 oldDrawSurface->Binding = NULL; 208 oldReadSurface->Binding = NULL; 209 210 /* 211 * check if the old context or surfaces need to be deleted 212 */ 213 if (!_eglIsSurfaceLinked(oldDrawSurface)) { 214 assert(draw != oldDrawSurface && read != oldDrawSurface); 215 drv->API.DestroySurface(drv, dpy, oldDrawSurface); 216 } 217 if (oldReadSurface != oldDrawSurface && 218 !_eglIsSurfaceLinked(oldReadSurface)) { 219 assert(draw != oldReadSurface && read != oldReadSurface); 220 drv->API.DestroySurface(drv, dpy, oldReadSurface); 221 } 222 if (!_eglIsContextLinked(oldContext)) { 223 assert(ctx != oldContext); 224 drv->API.DestroyContext(drv, dpy, oldContext); 225 } 226 } 227 228 /* build new bindings */ 229 if (ctx) { 230 t->CurrentContexts[apiIndex] = ctx; 231 ctx->Binding = t; 232 ctx->DrawSurface = draw; 233 ctx->ReadSurface = read; 234 draw->Binding = ctx; 235 read->Binding = ctx; 236 } 237 238 return EGL_TRUE; 239} 240 241 242/** 243 * This is defined by the EGL_MESA_copy_context extension. 244 */ 245EGLBoolean 246_eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, 247 EGLContext dest, EGLint mask) 248{ 249 /* This function will always have to be overridden/implemented in the 250 * device driver. If the driver is based on Mesa, use _mesa_copy_context(). 251 */ 252 return EGL_FALSE; 253} 254