diff options
-rw-r--r-- | opengl/libs/EGL/egl.cpp | 24 | ||||
-rw-r--r-- | opengl/libs/EGL/eglApi.cpp | 132 | ||||
-rw-r--r-- | opengl/libs/EGL/egl_display.cpp | 19 | ||||
-rw-r--r-- | opengl/libs/EGL/egl_display.h | 68 | ||||
-rw-r--r-- | opengl/libs/EGL/egl_object.cpp | 6 | ||||
-rw-r--r-- | opengl/libs/EGL/egl_object.h | 11 |
6 files changed, 169 insertions, 91 deletions
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index e8a14d8..b658240 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -203,27 +203,27 @@ static int sEarlyInitState = pthread_once(&once_control, &early_egl_init); // ---------------------------------------------------------------------------- -egl_display_t* validate_display(EGLDisplay dpy) { - egl_display_t * const dp = get_display(dpy); +egl_display_ptr validate_display(EGLDisplay dpy) { + egl_display_ptr dp = get_display(dpy); if (!dp) - return setError(EGL_BAD_DISPLAY, (egl_display_t*)NULL); + return setError(EGL_BAD_DISPLAY, egl_display_ptr(NULL)); if (!dp->isReady()) - return setError(EGL_NOT_INITIALIZED, (egl_display_t*)NULL); + return setError(EGL_NOT_INITIALIZED, egl_display_ptr(NULL)); return dp; } -egl_connection_t* validate_display_config(EGLDisplay dpy, EGLConfig, - egl_display_t const*& dp) { - dp = validate_display(dpy); +egl_display_ptr validate_display_connection(EGLDisplay dpy, + egl_connection_t*& cnx) { + cnx = NULL; + egl_display_ptr dp = validate_display(dpy); if (!dp) - return (egl_connection_t*) NULL; - - egl_connection_t* const cnx = &gEGLImpl; + return dp; + cnx = &gEGLImpl; if (cnx->dso == 0) { - return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); + return setError(EGL_BAD_CONFIG, egl_display_ptr(NULL)); } - return cnx; + return dp; } // ---------------------------------------------------------------------------- diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 8df7d39..969b50f 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -133,7 +133,7 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { clearError(); - egl_display_t * const dp = get_display(dpy); + egl_display_ptr dp = get_display(dpy); if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); EGLBoolean res = dp->initialize(major, minor); @@ -149,7 +149,7 @@ EGLBoolean eglTerminate(EGLDisplay dpy) clearError(); - egl_display_t* const dp = get_display(dpy); + egl_display_ptr dp = get_display(dpy); if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); EGLBoolean res = dp->terminate(); @@ -167,7 +167,7 @@ EGLBoolean eglGetConfigs( EGLDisplay dpy, { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; if (num_config==0) { @@ -192,7 +192,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; if (num_config==0) { @@ -215,9 +215,9 @@ EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, { clearError(); - egl_display_t const* dp = 0; - egl_connection_t* cnx = validate_display_config(dpy, config, dp); - if (!cnx) return EGL_FALSE; + egl_connection_t* cnx = NULL; + const egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (!dp) return EGL_FALSE; return cnx->egl.eglGetConfigAttrib( dp->disp.dpy, config, attribute, value); @@ -233,9 +233,9 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, { clearError(); - egl_display_t const* dp = 0; - egl_connection_t* cnx = validate_display_config(dpy, config, dp); - if (cnx) { + egl_connection_t* cnx = NULL; + egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (dp) { EGLDisplay iDpy = dp->disp.dpy; EGLint format; @@ -267,7 +267,8 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, EGLSurface surface = cnx->egl.eglCreateWindowSurface( iDpy, config, window, attrib_list); if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, cnx); + egl_surface_t* s = new egl_surface_t(dp.get(), config, window, + surface, cnx); return s; } @@ -284,13 +285,14 @@ EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, { clearError(); - egl_display_t const* dp = 0; - egl_connection_t* cnx = validate_display_config(dpy, config, dp); - if (cnx) { + egl_connection_t* cnx = NULL; + egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (dp) { EGLSurface surface = cnx->egl.eglCreatePixmapSurface( dp->disp.dpy, config, pixmap, attrib_list); if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx); + egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, + surface, cnx); return s; } } @@ -302,13 +304,14 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, { clearError(); - egl_display_t const* dp = 0; - egl_connection_t* cnx = validate_display_config(dpy, config, dp); - if (cnx) { + egl_connection_t* cnx = NULL; + egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (dp) { EGLSurface surface = cnx->egl.eglCreatePbufferSurface( dp->disp.dpy, config, attrib_list); if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx); + egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, + surface, cnx); return s; } } @@ -319,10 +322,10 @@ EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - SurfaceRef _s(dp, surface); + SurfaceRef _s(dp.get(), surface); if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); @@ -339,10 +342,10 @@ EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - SurfaceRef _s(dp, surface); + SurfaceRef _s(dp.get(), surface); if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); @@ -355,12 +358,12 @@ void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) { ATRACE_CALL(); clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) { return; } - SurfaceRef _s(dp, surface); + SurfaceRef _s(dp.get(), surface); if (!_s.get()) { setError(EGL_BAD_SURFACE, EGL_FALSE); return; @@ -381,9 +384,9 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, { clearError(); - egl_display_t const* dp = 0; - egl_connection_t* cnx = validate_display_config(dpy, config, dp); - if (cnx) { + egl_connection_t* cnx = NULL; + const egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (dpy) { if (share_list != EGL_NO_CONTEXT) { egl_context_t* const c = get_context(share_list); share_list = c->context; @@ -406,7 +409,8 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, } }; } - egl_context_t* c = new egl_context_t(dpy, context, config, cnx, version); + egl_context_t* c = new egl_context_t(dpy, context, config, cnx, + version); #if EGL_TRACE if (gEGLDebugLevel > 0) GLTrace_eglCreateContext(version, c); @@ -421,11 +425,11 @@ EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - ContextRef _c(dp, ctx); + ContextRef _c(dp.get(), ctx); if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); @@ -442,7 +446,7 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, { clearError(); - egl_display_t const * const dp = get_display(dpy); + egl_display_ptr dp = validate_display(dpy); if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not @@ -454,9 +458,9 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, } // get a reference to the object passed in - ContextRef _c(dp, ctx); - SurfaceRef _d(dp, draw); - SurfaceRef _r(dp, read); + ContextRef _c(dp.get(), ctx); + SurfaceRef _d(dp.get(), draw); + SurfaceRef _r(dp.get(), read); // validate the context (if not EGL_NO_CONTEXT) if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { @@ -506,7 +510,7 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, } - EGLBoolean result = const_cast<egl_display_t*>(dp)->makeCurrent(c, cur_c, + EGLBoolean result = dp->makeCurrent(c, cur_c, draw, read, ctx, impl_draw, impl_read, impl_ctx); @@ -538,10 +542,10 @@ EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - ContextRef _c(dp, ctx); + ContextRef _c(dp.get(), ctx); if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); egl_context_t * const c = get_context(ctx); @@ -783,10 +787,10 @@ EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) ATRACE_CALL(); clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - SurfaceRef _s(dp, draw); + SurfaceRef _s(dp.get(), draw); if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); @@ -827,10 +831,10 @@ EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - SurfaceRef _s(dp, surface); + SurfaceRef _s(dp.get(), surface); if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); @@ -842,7 +846,7 @@ const char* eglQueryString(EGLDisplay dpy, EGLint name) { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return (const char *) NULL; switch (name) { @@ -870,10 +874,10 @@ EGLBoolean eglSurfaceAttrib( { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - SurfaceRef _s(dp, surface); + SurfaceRef _s(dp.get(), surface); if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); @@ -890,10 +894,10 @@ EGLBoolean eglBindTexImage( { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - SurfaceRef _s(dp, surface); + SurfaceRef _s(dp.get(), surface); if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); @@ -910,10 +914,10 @@ EGLBoolean eglReleaseTexImage( { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - SurfaceRef _s(dp, surface); + SurfaceRef _s(dp.get(), surface); if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); @@ -929,7 +933,7 @@ EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; EGLBoolean res = EGL_TRUE; @@ -1023,9 +1027,9 @@ EGLSurface eglCreatePbufferFromClientBuffer( { clearError(); - egl_display_t const* dp = 0; - egl_connection_t* cnx = validate_display_config(dpy, config, dp); - if (!cnx) return EGL_FALSE; + egl_connection_t* cnx = NULL; + const egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (!dp) return EGL_FALSE; if (cnx->egl.eglCreatePbufferFromClientBuffer) { return cnx->egl.eglCreatePbufferFromClientBuffer( dp->disp.dpy, buftype, buffer, config, attrib_list); @@ -1042,10 +1046,10 @@ EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - SurfaceRef _s(dp, surface); + SurfaceRef _s(dp.get(), surface); if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); @@ -1061,10 +1065,10 @@ EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - SurfaceRef _s(dp, surface); + SurfaceRef _s(dp.get(), surface); if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); @@ -1080,10 +1084,10 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_NO_IMAGE_KHR; - ContextRef _c(dp, ctx); + ContextRef _c(dp.get(), ctx); egl_context_t * const c = _c.get(); EGLImageKHR result = EGL_NO_IMAGE_KHR; @@ -1101,7 +1105,7 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; @@ -1120,7 +1124,7 @@ EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_l { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_NO_SYNC_KHR; EGLSyncKHR result = EGL_NO_SYNC_KHR; @@ -1135,7 +1139,7 @@ EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; EGLBoolean result = EGL_FALSE; @@ -1151,7 +1155,7 @@ EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; EGLBoolean result = EGL_FALSE; @@ -1168,7 +1172,7 @@ EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, { clearError(); - egl_display_t const * const dp = validate_display(dpy); + const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; EGLBoolean result = EGL_FALSE; diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp index 6b6f8cf..52e79f2 100644 --- a/opengl/libs/EGL/egl_display.cpp +++ b/opengl/libs/EGL/egl_display.cpp @@ -14,6 +14,8 @@ ** limitations under the License. */ +#define __STDC_LIMIT_MACROS 1 + #include <string.h> #include "egl_cache.h" @@ -67,7 +69,8 @@ extern void setGLHooksThreadSpecific(gl_hooks_t const *value); egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS]; egl_display_t::egl_display_t() : - magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0) { + magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0), + mWakeCount(0) { } egl_display_t::~egl_display_t() { @@ -368,6 +371,20 @@ EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c, return result; } +bool egl_display_t::enter() { + Mutex::Autolock _l(lock); + ALOGE_IF(mWakeCount < 0 || mWakeCount == INT32_MAX, + "Invalid WakeCount (%d) on enter\n", mWakeCount); + mWakeCount++; + return true; +} + +void egl_display_t::leave() { + Mutex::Autolock _l(lock); + ALOGE_IF(mWakeCount <= 0, "Invalid WakeCount (%d) on leave\n", mWakeCount); + mWakeCount--; +} + // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h index 3e22efa..8fd23eb 100644 --- a/opengl/libs/EGL/egl_display.h +++ b/opengl/libs/EGL/egl_display.h @@ -27,6 +27,7 @@ #include <GLES/gl.h> #include <GLES/glext.h> +#include <cutils/compiler.h> #include <utils/SortedVector.h> #include <utils/threads.h> #include <utils/String8.h> @@ -111,6 +112,10 @@ public: bool traceGpuCompletion; // property: debug.egl.traceGpuCompletion private: + friend class egl_display_ptr; + bool enter(); + void leave(); + uint32_t refs; mutable Mutex lock; SortedVector<egl_object_t*> objects; @@ -118,19 +123,74 @@ private: String8 mVersionString; String8 mClientApiString; String8 mExtensionString; + int32_t mWakeCount; }; // ---------------------------------------------------------------------------- -inline egl_display_t* get_display(EGLDisplay dpy) { +class egl_display_ptr { +public: + explicit egl_display_ptr(egl_display_t* dpy): mDpy(dpy) { + if (mDpy) { + if (CC_UNLIKELY(!mDpy->enter())) { + mDpy = NULL; + } + } + } + + // We only really need a C++11 move constructor, not a copy constructor. + // A move constructor would save an enter()/leave() pair on every EGL API + // call. But enabling -std=c++0x causes lots of errors elsewhere, so I + // can't use a move constructor yet. + // + // egl_display_ptr(egl_display_ptr&& other) { + // mDpy = other.mDpy; + // other.mDpy = NULL; + // } + egl_display_ptr(const egl_display_ptr& other): mDpy(other.mDpy) { + if (mDpy) { + mDpy->enter(); + } + } + + ~egl_display_ptr() { + if (mDpy) { + mDpy->leave(); + } + } + + const egl_display_t* operator->() const { return mDpy; } + egl_display_t* operator->() { return mDpy; } + + const egl_display_t* get() const { return mDpy; } + egl_display_t* get() { return mDpy; } + + operator bool() const { return mDpy != NULL; } + +private: + egl_display_t* mDpy; + + // non-assignable + egl_display_ptr& operator=(const egl_display_ptr&); +}; + +// ---------------------------------------------------------------------------- + +inline egl_display_ptr get_display(EGLDisplay dpy) { + return egl_display_ptr(egl_display_t::get(dpy)); +} + +// Does not ensure EGL is unhibernated. Use with caution: calls into the +// underlying EGL implementation are not safe. +inline egl_display_t* get_display_nowake(EGLDisplay dpy) { return egl_display_t::get(dpy); } // ---------------------------------------------------------------------------- -egl_display_t* validate_display(EGLDisplay dpy); -egl_connection_t* validate_display_config(EGLDisplay dpy, - EGLConfig config, egl_display_t const*& dp); +egl_display_ptr validate_display(EGLDisplay dpy); +egl_display_ptr validate_display_connection(EGLDisplay dpy, + egl_connection_t*& cnx); EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx); EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface); diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp index d0cbb31..b42b268 100644 --- a/opengl/libs/EGL/egl_object.cpp +++ b/opengl/libs/EGL/egl_object.cpp @@ -65,10 +65,8 @@ bool egl_object_t::get(egl_display_t const* display, egl_object_t* object) { egl_context_t::egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config, egl_connection_t const* cnx, int version) : - egl_object_t(get_display(dpy)), dpy(dpy), context(context), - config(config), read(0), draw(0), cnx(cnx), - version(version) -{ + egl_object_t(get_display_nowake(dpy)), dpy(dpy), context(context), + config(config), read(0), draw(0), cnx(cnx), version(version) { } void egl_context_t::onLooseCurrent() { diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h index 4d91f54..d1162db 100644 --- a/opengl/libs/EGL/egl_object.h +++ b/opengl/libs/EGL/egl_object.h @@ -139,12 +139,11 @@ protected: public: typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref; - egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, - EGLSurface surface, egl_connection_t const* cnx) : - egl_object_t(get_display(dpy)), dpy(dpy), surface(surface), - config(config), win(win), cnx(cnx) { - } - EGLDisplay dpy; + egl_surface_t(egl_display_t* dpy, EGLConfig config, + EGLNativeWindowType win, EGLSurface surface, + egl_connection_t const* cnx) : + egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx) + {} EGLSurface surface; EGLConfig config; sp<ANativeWindow> win; |