summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2012-06-18 18:06:45 -0700
committerMathias Agopian <mathias@google.com>2012-06-28 15:51:08 -0700
commit3094df359d1e6e2ae8ca4e935cc093f563804c96 (patch)
treee103ad608725652ec640963481151b59432c7475 /services/surfaceflinger
parent852db07d69352ec5f75e16a6e5059f05faabdaf5 (diff)
downloadframeworks_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')
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.cpp21
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.h1
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp76
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h7
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;
};
// ---------------------------------------------------------------------------