diff options
| -rw-r--r-- | include/surfaceflinger/Surface.h | 8 | ||||
| -rw-r--r-- | include/ui/egl/android_natives.h | 38 | ||||
| -rw-r--r-- | libs/surfaceflinger_client/Surface.cpp | 89 | ||||
| -rw-r--r-- | libs/ui/FramebufferNativeWindow.cpp | 2 |
4 files changed, 129 insertions, 8 deletions
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index 980883211d..0279d84b64 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -210,9 +210,16 @@ private: status_t dequeueBuffer(sp<GraphicBuffer>* buffer); + void dispatch_setUsage(va_list args); + int dispatch_connect(va_list args); + int dispatch_disconnect(va_list args); void setUsage(uint32_t reqUsage); + int connect(int api); + int disconnect(int api); + uint32_t getUsage() const; + int getConnectedApi() const; // constants sp<SurfaceComposerClient> mClient; @@ -227,6 +234,7 @@ private: // protected by mSurfaceLock Rect mSwapRectangle; uint32_t mUsage; + int mConnected; // protected by mSurfaceLock. These are also used from lock/unlock // but in that case, they must be called form the same thread. diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h index 3740db5d95..773fd9301f 100644 --- a/include/ui/egl/android_natives.h +++ b/include/ui/egl/android_natives.h @@ -69,7 +69,14 @@ enum { /* valid operations for the (*perform)() hook */ enum { - NATIVE_WINDOW_SET_USAGE = 0 + NATIVE_WINDOW_SET_USAGE = 0, + NATIVE_WINDOW_CONNECT = 1, + NATIVE_WINDOW_DISCONNECT = 2 +}; + +/* parameter for NATIVE_WINDOW_[DIS]CONNECT */ +enum { + NATIVE_WINDOW_API_EGL = 1 }; typedef struct android_native_window_t @@ -157,8 +164,13 @@ typedef struct android_native_window_t * This hook should not be called directly, instead use the helper functions * defined below. * + * (*perform)() returns -ENOENT if the 'what' parameter is not supported + * by the surface's implementation. + * * The valid operations are: * NATIVE_WINDOW_SET_USAGE + * NATIVE_WINDOW_CONNECT + * NATIVE_WINDOW_DISCONNECT * */ @@ -185,6 +197,30 @@ static inline int native_window_set_usage( return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage); } +/* + * native_window_connect(..., NATIVE_WINDOW_API_EGL) must be called + * by EGL when the window is made current. + * Returns -EINVAL if for some reason the window cannot be connected, which + * can happen if it's connected to some other API. + */ +static inline int native_window_connect( + android_native_window_t* window, int api) +{ + return window->perform(window, NATIVE_WINDOW_CONNECT, api); +} + +/* + * native_window_disconnect(..., NATIVE_WINDOW_API_EGL) must be called + * by EGL when the window is made not current. + * An error is returned if for instance the window wasn't connected in the + * first place. + */ +static inline int native_window_disconnect( + android_native_window_t* window, int api) +{ + return window->perform(window, NATIVE_WINDOW_DISCONNECT, api); +} + // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp index eb3457bfda..5dd75c3213 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -353,6 +353,7 @@ void Surface::init() const_cast<uint32_t&>(android_native_window_t::flags) = 0; // be default we request a hardware surface mUsage = GRALLOC_USAGE_HW_RENDER; + mConnected = 0; mNeedFullUpdate = false; } @@ -579,28 +580,93 @@ int Surface::perform(int operation, va_list args) { int res = NO_ERROR; switch (operation) { - case NATIVE_WINDOW_SET_USAGE: - setUsage( va_arg(args, int) ); - break; - default: - res = NAME_NOT_FOUND; - break; + case NATIVE_WINDOW_SET_USAGE: + dispatch_setUsage( args ); + break; + case NATIVE_WINDOW_CONNECT: + res = dispatch_connect( args ); + break; + case NATIVE_WINDOW_DISCONNECT: + res = dispatch_disconnect( args ); + break; + default: + res = NAME_NOT_FOUND; + break; } return res; } +void Surface::dispatch_setUsage(va_list args) { + int usage = va_arg(args, int); + setUsage( usage ); +} +int Surface::dispatch_connect(va_list args) { + int api = va_arg(args, int); + return connect( api ); +} +int Surface::dispatch_disconnect(va_list args) { + int api = va_arg(args, int); + return disconnect( api ); +} + + void Surface::setUsage(uint32_t reqUsage) { Mutex::Autolock _l(mSurfaceLock); mUsage = reqUsage; } +int Surface::connect(int api) +{ + Mutex::Autolock _l(mSurfaceLock); + int err = NO_ERROR; + switch (api) { + case NATIVE_WINDOW_API_EGL: + if (mConnected) { + err = -EINVAL; + } else { + mConnected = api; + } + break; + default: + err = -EINVAL; + break; + } + return err; +} + +int Surface::disconnect(int api) +{ + Mutex::Autolock _l(mSurfaceLock); + int err = NO_ERROR; + switch (api) { + case NATIVE_WINDOW_API_EGL: + if (mConnected == api) { + mConnected = 0; + } else { + err = -EINVAL; + } + break; + default: + err = -EINVAL; + break; + } + return err; +} + uint32_t Surface::getUsage() const { Mutex::Autolock _l(mSurfaceLock); return mUsage; } +int Surface::getConnectedApi() const +{ + Mutex::Autolock _l(mSurfaceLock); + return mConnected; +} + + // ---------------------------------------------------------------------------- status_t Surface::lock(SurfaceInfo* info, bool blocking) { @@ -609,11 +675,20 @@ status_t Surface::lock(SurfaceInfo* info, bool blocking) { status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) { + if (getConnectedApi()) { + LOGE("Surface::lock(%p) failed. Already connected to another API", + (android_native_window_t*)this); + CallStack stack; + stack.update(); + stack.dump(""); + return INVALID_OPERATION; + } + if (mApiLock.tryLock() != NO_ERROR) { LOGE("calling Surface::lock from different threads!"); CallStack stack; stack.update(); - stack.dump("Surface::lock called from different threads"); + stack.dump(""); return WOULD_BLOCK; } diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index 1fa2c68f2a..52380a077c 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -250,6 +250,8 @@ int FramebufferNativeWindow::perform(android_native_window_t* window, { switch (operation) { case NATIVE_WINDOW_SET_USAGE: + case NATIVE_WINDOW_CONNECT: + case NATIVE_WINDOW_DISCONNECT: break; default: return NAME_NOT_FOUND; |