diff options
author | Mathias Agopian <mathias@google.com> | 2012-06-18 18:06:45 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2012-06-28 15:51:08 -0700 |
commit | 3094df359d1e6e2ae8ca4e935cc093f563804c96 (patch) | |
tree | e103ad608725652ec640963481151b59432c7475 /services/surfaceflinger | |
parent | 852db07d69352ec5f75e16a6e5059f05faabdaf5 (diff) | |
download | frameworks_native-3094df359d1e6e2ae8ca4e935cc093f563804c96.zip frameworks_native-3094df359d1e6e2ae8ca4e935cc093f563804c96.tar.gz frameworks_native-3094df359d1e6e2ae8ca4e935cc093f563804c96.tar.bz2 |
First prototype atttempting to support an external display
both API and implementation will change, this is just a prototype
intended to show feasability.
SurfaceFlinger is passed an ISurfaceTexture through a new
callback, it is in turn used to create an EGLSurface which
surfaceflinger will draw into in addition to the main screen.
Change-Id: Id0bbb0b854bb7bae44d57246a90b65d4567f9a21
Diffstat (limited to 'services/surfaceflinger')
4 files changed, 92 insertions, 13 deletions
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp index e1c4f62..bb537c9 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -224,21 +224,11 @@ void DisplayHardware::init(uint32_t dpy) // initialize EGL EGLint attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_NONE, 0, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RECORDABLE_ANDROID, EGL_TRUE, EGL_NONE }; - // debug: disable h/w rendering - char property[PROPERTY_VALUE_MAX]; - if (property_get("debug.sf.hw", property, NULL) > 0) { - if (atoi(property) == 0) { - ALOGW("H/W composition disabled"); - attribs[2] = EGL_CONFIG_CAVEAT; - attribs[3] = EGL_SLOW_CONFIG; - } - } - // TODO: all the extensions below should be queried through // eglGetProcAddress(). @@ -248,6 +238,13 @@ void DisplayHardware::init(uint32_t dpy) EGLConfig config = NULL; err = selectConfigForPixelFormat(display, attribs, format, &config); + if (err) { + // maybe we failed because of EGL_RECORDABLE_ANDROID + ALOGW("couldn't find an EGLConfig with EGL_RECORDABLE_ANDROID"); + attribs[2] = EGL_NONE; + err = selectConfigForPixelFormat(display, attribs, format, &config); + } + ALOGE_IF(err, "couldn't find an EGLConfig matching the screen format"); EGLint r,g,b,a; diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h index f029a0a..31662dd 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -96,6 +96,7 @@ public: uint32_t getPageFlipCount() const; EGLDisplay getEGLDisplay() const { return mDisplay; } + EGLConfig getEGLConfig() const { return mConfig; } void dump(String8& res) const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 981d694..07ea3a0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -64,6 +64,7 @@ #include <private/android_filesystem_config.h> #include <private/gui/SharedBufferStack.h> #include <gui/BitTube.h> +#include <gui/SurfaceTextureClient.h> #define EGL_VERSION_HW_ANDROID 0x3143 @@ -97,7 +98,8 @@ SurfaceFlinger::SurfaceFlinger() mDebugInTransaction(0), mLastTransactionTime(0), mBootFinished(false), - mSecureFrameBuffer(0) + mSecureFrameBuffer(0), + mExternalDisplaySurface(EGL_NO_SURFACE) { init(); } @@ -370,6 +372,41 @@ sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() { return mEventThread->createEventConnection(); } +void SurfaceFlinger::connectDisplay(const sp<ISurfaceTexture> display) { + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + EGLSurface result = EGL_NO_SURFACE; + EGLSurface old_surface = EGL_NO_SURFACE; + sp<SurfaceTextureClient> stc; + + if (display != NULL) { + stc = new SurfaceTextureClient(display); + result = eglCreateWindowSurface(hw.getEGLDisplay(), + hw.getEGLConfig(), (EGLNativeWindowType)stc.get(), NULL); + ALOGE_IF(result == EGL_NO_SURFACE, + "eglCreateWindowSurface failed (ISurfaceTexture=%p)", + display.get()); + } + + { // scope for the lock + Mutex::Autolock _l(mStateLock); + old_surface = mExternalDisplaySurface; + mExternalDisplayNativeWindow = stc; + mExternalDisplaySurface = result; + ALOGD("mExternalDisplaySurface = %p", result); + } + + if (old_surface != EGL_NO_SURFACE) { + // Note: EGL allows to destroy an object while its current + // it will fail to become current next time though. + eglDestroySurface(hw.getEGLDisplay(), old_surface); + } +} + +EGLSurface SurfaceFlinger::getExternalDisplaySurface() const { + Mutex::Autolock _l(mStateLock); + return mExternalDisplaySurface; +} + // ---------------------------------------------------------------------------- void SurfaceFlinger::waitForEvent() { @@ -454,6 +491,43 @@ void SurfaceFlinger::onMessageReceived(int32_t what) hw.compositionComplete(); } + // render to the external display if we have one + EGLSurface externalDisplaySurface = getExternalDisplaySurface(); + if (externalDisplaySurface != EGL_NO_SURFACE) { + EGLSurface cur = eglGetCurrentSurface(EGL_DRAW); + EGLBoolean success = eglMakeCurrent(eglGetCurrentDisplay(), + externalDisplaySurface, externalDisplaySurface, + eglGetCurrentContext()); + + ALOGE_IF(!success, "eglMakeCurrent -> external failed"); + + if (success) { + // redraw the screen entirely... + glDisable(GL_TEXTURE_EXTERNAL_OES); + glDisable(GL_TEXTURE_2D); + glClearColor(0,0,0,1); + glClear(GL_COLOR_BUFFER_BIT); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); + const size_t count = layers.size(); + for (size_t i=0 ; i<count ; ++i) { + const sp<LayerBase>& layer(layers[i]); + layer->drawForSreenShot(); + } + + success = eglSwapBuffers(eglGetCurrentDisplay(), externalDisplaySurface); + ALOGE_IF(!success, "external display eglSwapBuffers failed"); + + hw.compositionComplete(); + } + + success = eglMakeCurrent(eglGetCurrentDisplay(), + cur, cur, eglGetCurrentContext()); + + ALOGE_IF(!success, "eglMakeCurrent -> internal failed"); + } + } break; } } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c3efdbc..8256fef 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -153,6 +153,8 @@ public: // called when screen is turning back on virtual void unblank(); + virtual void connectDisplay(const sp<ISurfaceTexture> display); + // called on the main thread in response to screenReleased() void onScreenReleased(); // called on the main thread in response to screenAcquired() @@ -388,6 +390,11 @@ private: // only written in the main thread, only read in other threads volatile int32_t mSecureFrameBuffer; + + + EGLSurface getExternalDisplaySurface() const; + sp<SurfaceTextureClient> mExternalDisplayNativeWindow; + EGLSurface mExternalDisplaySurface; }; // --------------------------------------------------------------------------- |