data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::UNBLANK, data, &reply);
}
+
+ virtual void connectDisplay(const sp<ISurfaceTexture> display) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ data.writeStrongBinder(display->asBinder());
+ remote()->transact(BnSurfaceComposer::CONNECT_DISPLAY, data, &reply);
+ }
};
IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
CHECK_INTERFACE(ISurfaceComposer, data, reply);
unblank();
} break;
+ case CONNECT_DISPLAY: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<ISurfaceTexture> surfaceTexture =
+ interface_cast<ISurfaceTexture>(data.readStrongBinder());
+ connectDisplay(surfaceTexture);
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
// 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().
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;
#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
mDebugInTransaction(0),
mLastTransactionTime(0),
mBootFinished(false),
- mSecureFrameBuffer(0)
+ mSecureFrameBuffer(0),
+ mExternalDisplaySurface(EGL_NO_SURFACE)
{
init();
}
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() {
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;
}
}