diff options
Diffstat (limited to 'opengl/libs')
| -rw-r--r-- | opengl/libs/Android.mk | 4 | ||||
| -rw-r--r-- | opengl/libs/EGL/egl.cpp | 492 |
2 files changed, 356 insertions, 140 deletions
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk index e1fd48b..9578452 100644 --- a/opengl/libs/Android.mk +++ b/opengl/libs/Android.mk @@ -28,6 +28,10 @@ LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES LOCAL_CFLAGS += -fvisibility=hidden +ifeq ($(TARGET_BOARD_PLATFORM),msm7k) +LOCAL_CFLAGS += -DADRENO130=1 +endif + include $(BUILD_SHARED_LIBRARY) installed_libEGL := $(LOCAL_INSTALLED_MODULE) diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index 03e764c..d1ddcd3 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -36,6 +36,8 @@ #include <cutils/properties.h> #include <cutils/memory.h> +#include <utils/SortedVector.h> + #include "hooks.h" #include "egl_impl.h" #include "Loader.h" @@ -63,40 +65,122 @@ static char const * const gExtensionString = // ---------------------------------------------------------------------------- -template <int MAGIC> -struct egl_object_t -{ - egl_object_t() : magic(MAGIC) { } - ~egl_object_t() { magic = 0; } - bool isValid() const { return magic == MAGIC; } +class egl_object_t { + static SortedVector<egl_object_t*> sObjects; + static Mutex sLock; + + volatile int32_t terminated; + mutable volatile int32_t count; + +public: + egl_object_t() : terminated(0), count(1) { + Mutex::Autolock _l(sLock); + sObjects.add(this); + } + + inline bool isAlive() const { return !terminated; } + private: - uint32_t magic; + bool get() { + Mutex::Autolock _l(sLock); + if (egl_object_t::sObjects.indexOf(this) >= 0) { + android_atomic_inc(&count); + return true; + } + return false; + } + + bool put() { + Mutex::Autolock _l(sLock); + if (android_atomic_dec(&count) == 1) { + sObjects.remove(this); + return true; + } + return false; + } + +public: + template <typename N, typename T> + struct LocalRef { + N* ref; + LocalRef(T o) : ref(0) { + N* native = reinterpret_cast<N*>(o); + if (o && native->get()) { + ref = native; + } + } + ~LocalRef() { + if (ref && ref->put()) { + delete ref; + } + } + inline N* get() { + return ref; + } + void acquire() const { + if (ref) { + android_atomic_inc(&ref->count); + } + } + void release() const { + if (ref) { + int32_t c = android_atomic_dec(&ref->count); + // ref->count cannot be 1 prior atomic_dec because we have + // a reference, and if we have one, it means there was + // already one before us. + LOGE_IF(c==1, "refcount is now 0 in release()"); + } + } + void terminate() { + if (ref) { + ref->terminated = 1; + release(); + } + } + }; }; -struct egl_display_t : public egl_object_t<'_dpy'> -{ - EGLDisplay dpys[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; - EGLConfig* configs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; - EGLint numConfigs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; - EGLint numTotalConfigs; - char const* extensionsString; - volatile int32_t refs; +SortedVector<egl_object_t*> egl_object_t::sObjects; +Mutex egl_object_t::sLock; + +struct egl_display_t { + enum { NOT_INITIALIZED, INITIALIZED, TERMINATED }; + struct strings_t { char const * vendor; char const * version; char const * clientApi; char const * extensions; }; - strings_t queryString[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; + + struct DisplayImpl { + DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0), + state(NOT_INITIALIZED), numConfigs(0) { } + EGLDisplay dpy; + EGLConfig* config; + EGLint state; + EGLint numConfigs; + strings_t queryString; + }; + + uint32_t magic; + DisplayImpl disp[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; + EGLint numTotalConfigs; + volatile int32_t refs; + + egl_display_t() : magic('_dpy'), numTotalConfigs(0) { } + ~egl_display_t() { magic = 0; } + inline bool isValid() const { return magic == '_dpy'; } + inline bool isAlive() const { return isValid(); } }; -struct egl_surface_t : public egl_object_t<'_srf'> +struct egl_surface_t : public egl_object_t { + typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref; + egl_surface_t(EGLDisplay dpy, EGLSurface surface, int impl, egl_connection_t const* cnx) - : dpy(dpy), surface(surface), impl(impl), cnx(cnx) - { - // NOTE: window must be incRef'ed and connected already + : dpy(dpy), surface(surface), impl(impl), cnx(cnx) { } ~egl_surface_t() { } @@ -106,8 +190,10 @@ struct egl_surface_t : public egl_object_t<'_srf'> egl_connection_t const* cnx; }; -struct egl_context_t : public egl_object_t<'_ctx'> +struct egl_context_t : public egl_object_t { + typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref; + egl_context_t(EGLDisplay dpy, EGLContext context, int impl, egl_connection_t const* cnx) : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx) @@ -121,8 +207,10 @@ struct egl_context_t : public egl_object_t<'_ctx'> egl_connection_t const* cnx; }; -struct egl_image_t : public egl_object_t<'_img'> +struct egl_image_t : public egl_object_t { + typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref; + egl_image_t(EGLDisplay dpy, EGLContext context) : dpy(dpy), context(context) { @@ -133,6 +221,10 @@ struct egl_image_t : public egl_object_t<'_img'> EGLImageKHR images[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; }; +typedef egl_surface_t::Ref SurfaceRef; +typedef egl_context_t::Ref ContextRef; +typedef egl_image_t::Ref ImageRef; + struct tls_t { tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { } @@ -272,14 +364,14 @@ int binarySearch( static EGLint configToUniqueId(egl_display_t const* dp, int i, int index) { // NOTE: this mapping works only if we have no more than two EGLimpl - return (i>0 ? dp->numConfigs[0] : 0) + index; + return (i>0 ? dp->disp[0].numConfigs : 0) + index; } static void uniqueIdToConfig(egl_display_t const* dp, EGLint configId, int& i, int& index) { // NOTE: this mapping works only if we have no more than two EGLimpl - size_t numConfigs = dp->numConfigs[0]; + size_t numConfigs = dp->disp[0].numConfigs; i = configId / numConfigs; index = configId % numConfigs; } @@ -391,7 +483,7 @@ static egl_connection_t* validate_display_config( return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); } index = uintptr_t(config) & 0xFFFFFF; - if (index >= dp->numConfigs[impl]) { + if (index >= dp->disp[impl].numConfigs) { return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); } egl_connection_t* const cnx = &gEGLImpl[impl]; @@ -405,11 +497,9 @@ static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx) { if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) return setError(EGL_BAD_DISPLAY, EGL_FALSE); - if (!get_display(dpy)->isValid()) + if (!get_display(dpy)->isAlive()) return setError(EGL_BAD_DISPLAY, EGL_FALSE); - if (!ctx) // TODO: make sure context is a valid object - return setError(EGL_BAD_CONTEXT, EGL_FALSE); - if (!get_context(ctx)->isValid()) + if (!get_context(ctx)->isAlive()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); return EGL_TRUE; } @@ -418,37 +508,34 @@ static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface) { if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) return setError(EGL_BAD_DISPLAY, EGL_FALSE); - if (!get_display(dpy)->isValid()) + if (!get_display(dpy)->isAlive()) return setError(EGL_BAD_DISPLAY, EGL_FALSE); - if (!surface) // TODO: make sure surface is a valid object - return setError(EGL_BAD_SURFACE, EGL_FALSE); - if (!get_surface(surface)->isValid()) + if (!get_surface(surface)->isAlive()) return setError(EGL_BAD_SURFACE, EGL_FALSE); return EGL_TRUE; } - EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image) { + ImageRef _i(image); + if (!_i.get()) return EGL_NO_IMAGE_KHR; + EGLContext context = getContext(); if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR) return EGL_NO_IMAGE_KHR; egl_context_t const * const c = get_context(context); - if (!c->isValid()) + if (!c->isAlive()) return EGL_NO_IMAGE_KHR; egl_image_t const * const i = get_image(image); - if (!i->isValid()) - return EGL_NO_IMAGE_KHR; - return i->images[c->impl]; } // ---------------------------------------------------------------------------- // this mutex protects: -// d->dpys[] +// d->disp[] // egl_init_drivers_locked() // static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER; @@ -477,7 +564,7 @@ EGLBoolean egl_init_drivers_locked() if (cnx->dso) { EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY); LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!"); - d->dpys[IMPL_SOFTWARE] = dpy; + d->disp[IMPL_SOFTWARE].dpy = dpy; if (dpy == EGL_NO_DISPLAY) { loader.close(cnx->dso); cnx->dso = NULL; @@ -495,7 +582,7 @@ EGLBoolean egl_init_drivers_locked() if (cnx->dso) { EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY); LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!"); - d->dpys[IMPL_HARDWARE] = dpy; + d->disp[IMPL_HARDWARE].dpy = dpy; if (dpy == EGL_NO_DISPLAY) { loader.close(cnx->dso); cnx->dso = NULL; @@ -505,7 +592,7 @@ EGLBoolean egl_init_drivers_locked() LOGD("3D hardware acceleration is disabled"); } } - + if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) { return EGL_FALSE; } @@ -563,7 +650,6 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) // initialize each EGL and // build our own extension string first, based on the extension we know // and the extension supported by our client implementation - dp->extensionsString = strdup(gExtensionString); for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; cnx->major = -1; @@ -571,25 +657,43 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) if (!cnx->dso) continue; - if (cnx->hooks->egl.eglInitialize( - dp->dpys[i], &cnx->major, &cnx->minor)) { +#if defined(ADRENO130) +#warning "Adreno-130 eglInitialize() workaround" + /* + * The ADRENO 130 driver returns a different EGLDisplay each time + * eglGetDisplay() is called, but also makes the EGLDisplay invalid + * after eglTerminate() has been called, so that eglInitialize() + * cannot be called again. Therefore, we need to make sure to call + * eglGetDisplay() before calling eglInitialize(); + */ + if (i == IMPL_HARDWARE) { + dp->disp[i].dpy = + cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY); + } +#endif + + EGLDisplay idpy = dp->disp[i].dpy; + if (cnx->hooks->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) { //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p", - // i, dp->dpys[i], cnx->major, cnx->minor, cnx); + // i, idpy, cnx->major, cnx->minor, cnx); + + // display is now initialized + dp->disp[i].state = egl_display_t::INITIALIZED; // get the query-strings for this display for each implementation - dp->queryString[i].vendor = - cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VENDOR); - dp->queryString[i].version = - cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VERSION); - dp->queryString[i].extensions = strdup( - cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_EXTENSIONS)); - dp->queryString[i].clientApi = - cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_CLIENT_APIS); + dp->disp[i].queryString.vendor = + cnx->hooks->egl.eglQueryString(idpy, EGL_VENDOR); + dp->disp[i].queryString.version = + cnx->hooks->egl.eglQueryString(idpy, EGL_VERSION); + dp->disp[i].queryString.extensions = + cnx->hooks->egl.eglQueryString(idpy, EGL_EXTENSIONS); + dp->disp[i].queryString.clientApi = + cnx->hooks->egl.eglQueryString(idpy, EGL_CLIENT_APIS); } else { - LOGD("%d: eglInitialize() failed (%s)", - i, egl_strerror(cnx->hooks->egl.eglGetError())); + LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy, + egl_strerror(cnx->hooks->egl.eglGetError())); } } @@ -598,15 +702,16 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso && cnx->major>=0 && cnx->minor>=0) { EGLint n; - if (cnx->hooks->egl.eglGetConfigs(dp->dpys[i], 0, 0, &n)) { - dp->configs[i] = (EGLConfig*)malloc(sizeof(EGLConfig)*n); - if (dp->configs[i]) { + if (cnx->hooks->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) { + dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n); + if (dp->disp[i].config) { if (cnx->hooks->egl.eglGetConfigs( - dp->dpys[i], dp->configs[i], n, &dp->numConfigs[i])) + dp->disp[i].dpy, dp->disp[i].config, n, + &dp->disp[i].numConfigs)) { // sort the configurations so we can do binary searches - qsort( dp->configs[i], - dp->numConfigs[i], + qsort( dp->disp[i].config, + dp->disp[i].numConfigs, sizeof(EGLConfig), cmp_configs); dp->numTotalConfigs += n; @@ -639,18 +744,24 @@ EGLBoolean eglTerminate(EGLDisplay dpy) EGLBoolean res = EGL_FALSE; for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; - if (cnx->dso) { - cnx->hooks->egl.eglTerminate(dp->dpys[i]); + if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) { + if (cnx->hooks->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) { + LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy, + egl_strerror(cnx->hooks->egl.eglGetError())); + } // REVISIT: it's unclear what to do if eglTerminate() fails - free(dp->configs[i]); - free((void*)dp->queryString[i].extensions); - dp->numConfigs[i] = 0; - dp->dpys[i] = EGL_NO_DISPLAY; + free(dp->disp[i].config); + + dp->disp[i].numConfigs = 0; + dp->disp[i].config = 0; + dp->disp[i].state = egl_display_t::TERMINATED; + res = EGL_TRUE; } } - free((void*)dp->extensionsString); - dp->extensionsString = 0; + + // TODO: all egl_object_t should be marked for termination + dp->numTotalConfigs = 0; clearTLS(); return res; @@ -674,7 +785,7 @@ EGLBoolean eglGetConfigs( EGLDisplay dpy, } GLint n = 0; for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) { - for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) { + for (int i=0 ; i<dp->disp[j].numConfigs && config_size ; i++) { *configs++ = MAKE_CONFIG(j, i); config_size--; n++; @@ -731,7 +842,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { cnx->hooks->egl.eglGetConfigAttrib( - dp->dpys[i], dp->configs[i][index], + dp->disp[i].dpy, dp->disp[i].config[index], EGL_CONFIG_ID, &configId); // and switch to the new list @@ -746,7 +857,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, // which one. res = cnx->hooks->egl.eglChooseConfig( - dp->dpys[i], attrib_list, configs, config_size, &n); + dp->disp[i].dpy, attrib_list, configs, config_size, &n); if (res && n>0) { // n has to be 0 or 1, by construction, and we already know // which config it will return (since there can be only one). @@ -765,13 +876,14 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglChooseConfig( - dp->dpys[i], attrib_list, configs, config_size, &n)) { + dp->disp[i].dpy, attrib_list, configs, config_size, &n)) { if (configs) { // now we need to convert these client EGLConfig to our // internal EGLConfig format. This is done in O(n log n). for (int j=0 ; j<n ; j++) { int index = binarySearch<EGLConfig>( - dp->configs[i], 0, dp->numConfigs[i]-1, configs[j]); + dp->disp[i].config, 0, + dp->disp[i].numConfigs-1, configs[j]); if (index >= 0) { if (configs) { configs[j] = MAKE_CONFIG(i, index); @@ -806,7 +918,7 @@ EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, return EGL_TRUE; } return cnx->hooks->egl.eglGetConfigAttrib( - dp->dpys[i], dp->configs[i][index], attribute, value); + dp->disp[i].dpy, dp->disp[i].config[index], attribute, value); } // ---------------------------------------------------------------------------- @@ -822,7 +934,7 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); if (cnx) { EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface( - dp->dpys[i], dp->configs[i][index], window, attrib_list); + dp->disp[i].dpy, dp->disp[i].config[index], window, attrib_list); if (surface != EGL_NO_SURFACE) { egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); return s; @@ -840,7 +952,7 @@ EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); if (cnx) { EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface( - dp->dpys[i], dp->configs[i][index], pixmap, attrib_list); + dp->disp[i].dpy, dp->disp[i].config[index], pixmap, attrib_list); if (surface != EGL_NO_SURFACE) { egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); return s; @@ -857,7 +969,7 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); if (cnx) { EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface( - dp->dpys[i], dp->configs[i][index], attrib_list); + dp->disp[i].dpy, dp->disp[i].config[index], attrib_list); if (surface != EGL_NO_SURFACE) { egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); return s; @@ -868,28 +980,35 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) { + SurfaceRef _s(surface); + if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (!validate_display_surface(dpy, surface)) return EGL_FALSE; egl_display_t const * const dp = get_display(dpy); - egl_surface_t const * const s = get_surface(surface); + egl_surface_t * const s = get_surface(surface); EGLBoolean result = s->cnx->hooks->egl.eglDestroySurface( - dp->dpys[s->impl], s->surface); - - delete s; + dp->disp[s->impl].dpy, s->surface); + if (result == EGL_TRUE) { + _s.terminate(); + } return result; } EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) { + SurfaceRef _s(surface); + if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (!validate_display_surface(dpy, surface)) return EGL_FALSE; egl_display_t const * const dp = get_display(dpy); egl_surface_t const * const s = get_surface(surface); return s->cnx->hooks->egl.eglQuerySurface( - dp->dpys[s->impl], s->surface, attribute, value); + dp->disp[s->impl].dpy, s->surface, attribute, value); } // ---------------------------------------------------------------------------- @@ -904,7 +1023,8 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); if (cnx) { EGLContext context = cnx->hooks->egl.eglCreateContext( - dp->dpys[i], dp->configs[i][index], share_list, attrib_list); + dp->disp[i].dpy, dp->disp[i].config[index], + share_list, attrib_list); if (context != EGL_NO_CONTEXT) { egl_context_t* c = new egl_context_t(dpy, context, i, cnx); return c; @@ -915,66 +1035,125 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { + ContextRef _c(ctx); + if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); + if (!validate_display_context(dpy, ctx)) return EGL_FALSE; egl_display_t const * const dp = get_display(dpy); egl_context_t * const c = get_context(ctx); EGLBoolean result = c->cnx->hooks->egl.eglDestroyContext( - dp->dpys[c->impl], c->context); - delete c; + dp->disp[c->impl].dpy, c->context); + if (result == EGL_TRUE) { + _c.terminate(); + } return result; } EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { + // get a reference to the object passed in + ContextRef _c(ctx); + SurfaceRef _d(draw); + SurfaceRef _r(read); + + // validate the display and the context (if not EGL_NO_CONTEXT) egl_display_t const * const dp = get_display(dpy); if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) { + // EGL_NO_CONTEXT is valid + return EGL_FALSE; + } - if (read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE && - ctx == EGL_NO_CONTEXT) - { - EGLBoolean result = EGL_TRUE; - ctx = getContext(); - if (ctx) { - egl_context_t * const c = get_context(ctx); - result = c->cnx->hooks->egl.eglMakeCurrent(dp->dpys[c->impl], 0, 0, 0); - if (result == EGL_TRUE) { - setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]); - setContext(EGL_NO_CONTEXT); + // these are the underlying implementation's object + EGLContext impl_ctx = EGL_NO_CONTEXT; + EGLSurface impl_draw = EGL_NO_SURFACE; + EGLSurface impl_read = EGL_NO_SURFACE; + + // these are our objects structs passed in + egl_context_t * c = NULL; + egl_surface_t const * d = NULL; + egl_surface_t const * r = NULL; + + // these are the current objects structs + egl_context_t * cur_c = get_context(getContext()); + egl_surface_t * cur_r = NULL; + egl_surface_t * cur_d = NULL; + + if (ctx != EGL_NO_CONTEXT) { + c = get_context(ctx); + cur_r = get_surface(c->read); + cur_d = get_surface(c->draw); + impl_ctx = c->context; + } else { + // no context given, use the implementation of the current context + if (cur_c == NULL) { + // no current context + if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { + // calling eglMakeCurrent( ..., EGL_NO_CONTEXT, !=0, !=0); + return setError(EGL_BAD_PARAMETER, EGL_FALSE); } + // not an error, there is just not current context. + return EGL_TRUE; } - return result; } - if (!validate_display_context(dpy, ctx)) - return EGL_FALSE; - - EGLSurface impl_draw = EGL_NO_SURFACE; - EGLSurface impl_read = EGL_NO_SURFACE; - egl_context_t * const c = get_context(ctx); + // retrieve the underlying implementation's draw EGLSurface if (draw != EGL_NO_SURFACE) { - egl_surface_t const * d = get_surface(draw); - if (!d) return setError(EGL_BAD_SURFACE, EGL_FALSE); - if (d->impl != c->impl) + d = get_surface(draw); + // make sure the EGLContext and EGLSurface passed in are for + // the same driver + if (c && d->impl != c->impl) return setError(EGL_BAD_MATCH, EGL_FALSE); impl_draw = d->surface; } + + // retrieve the underlying implementation's read EGLSurface if (read != EGL_NO_SURFACE) { - egl_surface_t const * r = get_surface(read); - if (!r) return setError(EGL_BAD_SURFACE, EGL_FALSE); - if (r->impl != c->impl) + r = get_surface(read); + // make sure the EGLContext and EGLSurface passed in are for + // the same driver + if (c && r->impl != c->impl) return setError(EGL_BAD_MATCH, EGL_FALSE); impl_read = r->surface; } - EGLBoolean result = c->cnx->hooks->egl.eglMakeCurrent( - dp->dpys[c->impl], impl_draw, impl_read, c->context); + + EGLBoolean result; + + if (c) { + result = c->cnx->hooks->egl.eglMakeCurrent( + dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx); + } else { + result = cur_c->cnx->hooks->egl.eglMakeCurrent( + dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx); + } if (result == EGL_TRUE) { - setGlThreadSpecific(c->cnx->hooks); - setContext(ctx); - c->read = read; - c->draw = draw; + // by construction, these are either 0 or valid (possibly terminated) + // it should be impossible for these to be invalid + ContextRef _cur_c(cur_c); + SurfaceRef _cur_r(cur_r); + SurfaceRef _cur_d(cur_d); + + // cur_c has to be valid here (but could be terminated) + if (ctx != EGL_NO_CONTEXT) { + setGlThreadSpecific(c->cnx->hooks); + setContext(ctx); + _c.acquire(); + } else { + setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]); + setContext(EGL_NO_CONTEXT); + } + _cur_c.release(); + + _r.acquire(); + _cur_r.release(); + if (c) c->read = read; + + _d.acquire(); + _cur_d.release(); + if (c) c->draw = draw; } return result; } @@ -983,6 +1162,9 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) { + ContextRef _c(ctx); + if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); + if (!validate_display_context(dpy, ctx)) return EGL_FALSE; @@ -990,7 +1172,7 @@ EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, egl_context_t * const c = get_context(ctx); return c->cnx->hooks->egl.eglQueryContext( - dp->dpys[c->impl], c->context, attribute, value); + dp->disp[c->impl].dpy, c->context, attribute, value); } EGLContext eglGetCurrentContext(void) @@ -1158,22 +1340,28 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) { + SurfaceRef _s(draw); + if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (!validate_display_surface(dpy, draw)) return EGL_FALSE; egl_display_t const * const dp = get_display(dpy); egl_surface_t const * const s = get_surface(draw); - return s->cnx->hooks->egl.eglSwapBuffers(dp->dpys[s->impl], s->surface); + return s->cnx->hooks->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface); } EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, NativePixmapType target) { + SurfaceRef _s(surface); + if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (!validate_display_surface(dpy, surface)) return EGL_FALSE; egl_display_t const * const dp = get_display(dpy); egl_surface_t const * const s = get_surface(surface); return s->cnx->hooks->egl.eglCopyBuffers( - dp->dpys[s->impl], s->surface, target); + dp->disp[s->impl].dpy, s->surface, target); } const char* eglQueryString(EGLDisplay dpy, EGLint name) @@ -1200,13 +1388,16 @@ const char* eglQueryString(EGLDisplay dpy, EGLint name) EGLBoolean eglSurfaceAttrib( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) { + SurfaceRef _s(surface); + if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (!validate_display_surface(dpy, surface)) return EGL_FALSE; egl_display_t const * const dp = get_display(dpy); egl_surface_t const * const s = get_surface(surface); if (s->cnx->hooks->egl.eglSurfaceAttrib) { return s->cnx->hooks->egl.eglSurfaceAttrib( - dp->dpys[s->impl], s->surface, attribute, value); + dp->disp[s->impl].dpy, s->surface, attribute, value); } return setError(EGL_BAD_SURFACE, EGL_FALSE); } @@ -1214,13 +1405,16 @@ EGLBoolean eglSurfaceAttrib( EGLBoolean eglBindTexImage( EGLDisplay dpy, EGLSurface surface, EGLint buffer) { + SurfaceRef _s(surface); + if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (!validate_display_surface(dpy, surface)) return EGL_FALSE; egl_display_t const * const dp = get_display(dpy); egl_surface_t const * const s = get_surface(surface); if (s->cnx->hooks->egl.eglBindTexImage) { return s->cnx->hooks->egl.eglBindTexImage( - dp->dpys[s->impl], s->surface, buffer); + dp->disp[s->impl].dpy, s->surface, buffer); } return setError(EGL_BAD_SURFACE, EGL_FALSE); } @@ -1228,13 +1422,16 @@ EGLBoolean eglBindTexImage( EGLBoolean eglReleaseTexImage( EGLDisplay dpy, EGLSurface surface, EGLint buffer) { + SurfaceRef _s(surface); + if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (!validate_display_surface(dpy, surface)) return EGL_FALSE; egl_display_t const * const dp = get_display(dpy); egl_surface_t const * const s = get_surface(surface); if (s->cnx->hooks->egl.eglReleaseTexImage) { return s->cnx->hooks->egl.eglReleaseTexImage( - dp->dpys[s->impl], s->surface, buffer); + dp->disp[s->impl].dpy, s->surface, buffer); } return setError(EGL_BAD_SURFACE, EGL_FALSE); } @@ -1249,7 +1446,8 @@ EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglSwapInterval) { - if (cnx->hooks->egl.eglSwapInterval(dp->dpys[i], interval) == EGL_FALSE) { + if (cnx->hooks->egl.eglSwapInterval( + dp->disp[i].dpy, interval) == EGL_FALSE) { res = EGL_FALSE; } } @@ -1351,7 +1549,8 @@ EGLSurface eglCreatePbufferFromClientBuffer( if (!cnx) return EGL_FALSE; if (cnx->hooks->egl.eglCreatePbufferFromClientBuffer) { return cnx->hooks->egl.eglCreatePbufferFromClientBuffer( - dp->dpys[i], buftype, buffer, dp->configs[i][index], attrib_list); + dp->disp[i].dpy, buftype, buffer, + dp->disp[i].config[index], attrib_list); } return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); } @@ -1363,6 +1562,9 @@ EGLSurface eglCreatePbufferFromClientBuffer( EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list) { + SurfaceRef _s(surface); + if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (!validate_display_surface(dpy, surface)) return EGL_FALSE; @@ -1371,13 +1573,16 @@ EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, if (s->cnx->hooks->egl.eglLockSurfaceKHR) { return s->cnx->hooks->egl.eglLockSurfaceKHR( - dp->dpys[s->impl], s->surface, attrib_list); + dp->disp[s->impl].dpy, s->surface, attrib_list); } return setError(EGL_BAD_DISPLAY, EGL_FALSE); } EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) { + SurfaceRef _s(surface); + if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (!validate_display_surface(dpy, surface)) return EGL_FALSE; @@ -1386,7 +1591,7 @@ EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) if (s->cnx->hooks->egl.eglUnlockSurfaceKHR) { return s->cnx->hooks->egl.eglUnlockSurfaceKHR( - dp->dpys[s->impl], s->surface); + dp->disp[s->impl].dpy, s->surface); } return setError(EGL_BAD_DISPLAY, EGL_FALSE); } @@ -1395,13 +1600,15 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) { if (ctx != EGL_NO_CONTEXT) { + ContextRef _c(ctx); + if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); if (!validate_display_context(dpy, ctx)) return EGL_NO_IMAGE_KHR; egl_display_t const * const dp = get_display(dpy); egl_context_t * const c = get_context(ctx); // since we have an EGLContext, we know which implementation to use EGLImageKHR image = c->cnx->hooks->egl.eglCreateImageKHR( - dp->dpys[c->impl], c->context, target, buffer, attrib_list); + dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list); if (image == EGL_NO_IMAGE_KHR) return image; @@ -1425,7 +1632,7 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, if (cnx->dso) { if (cnx->hooks->egl.eglCreateImageKHR) { implImages[i] = cnx->hooks->egl.eglCreateImageKHR( - dp->dpys[i], ctx, target, buffer, attrib_list); + dp->disp[i].dpy, ctx, target, buffer, attrib_list); if (implImages[i] != EGL_NO_IMAGE_KHR) { success = true; } @@ -1443,16 +1650,15 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) { - egl_display_t const * const dp = get_display(dpy); + egl_display_t const * const dp = get_display(dpy); if (dp == 0) { return setError(EGL_BAD_DISPLAY, EGL_FALSE); } - egl_image_t* image = get_image(img); - if (!image->isValid()) { - return setError(EGL_BAD_PARAMETER, EGL_FALSE); - } + ImageRef _i(img); + if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); + egl_image_t* image = get_image(img); bool success = false; for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; @@ -1460,7 +1666,7 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) if (cnx->dso) { if (cnx->hooks->egl.eglCreateImageKHR) { if (cnx->hooks->egl.eglDestroyImageKHR( - dp->dpys[i], image->images[i])) { + dp->disp[i].dpy, image->images[i])) { success = true; } } @@ -1470,7 +1676,7 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) if (!success) return EGL_FALSE; - delete image; + _i.terminate(); return EGL_TRUE; } @@ -1483,26 +1689,32 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height) { + SurfaceRef _s(draw); + if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (!validate_display_surface(dpy, draw)) return EGL_FALSE; egl_display_t const * const dp = get_display(dpy); egl_surface_t const * const s = get_surface(draw); if (s->cnx->hooks->egl.eglSetSwapRectangleANDROID) { - return s->cnx->hooks->egl.eglSetSwapRectangleANDROID(dp->dpys[s->impl], - s->surface, left, top, width, height); + return s->cnx->hooks->egl.eglSetSwapRectangleANDROID( + dp->disp[s->impl].dpy, s->surface, left, top, width, height); } return setError(EGL_BAD_DISPLAY, NULL); } EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw) { + SurfaceRef _s(draw); + if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLClientBuffer*)0); + if (!validate_display_surface(dpy, draw)) return 0; egl_display_t const * const dp = get_display(dpy); egl_surface_t const * const s = get_surface(draw); if (s->cnx->hooks->egl.eglGetRenderBufferANDROID) { - return s->cnx->hooks->egl.eglGetRenderBufferANDROID(dp->dpys[s->impl], - s->surface); + return s->cnx->hooks->egl.eglGetRenderBufferANDROID( + dp->disp[s->impl].dpy, s->surface); } return setError(EGL_BAD_DISPLAY, (EGLClientBuffer*)0); } |
