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
This commit is contained in:
parent
852db07d69
commit
3094df359d
|
@ -145,6 +145,9 @@ public:
|
||||||
|
|
||||||
/* triggers screen on and waits for it to complete */
|
/* triggers screen on and waits for it to complete */
|
||||||
virtual void unblank() = 0;
|
virtual void unblank() = 0;
|
||||||
|
|
||||||
|
/* connects to an external display */
|
||||||
|
virtual void connectDisplay(const sp<ISurfaceTexture> display) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -168,6 +171,7 @@ public:
|
||||||
CREATE_DISPLAY_EVENT_CONNECTION,
|
CREATE_DISPLAY_EVENT_CONNECTION,
|
||||||
BLANK,
|
BLANK,
|
||||||
UNBLANK,
|
UNBLANK,
|
||||||
|
CONNECT_DISPLAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual status_t onTransact( uint32_t code,
|
virtual status_t onTransact( uint32_t code,
|
||||||
|
|
|
@ -207,6 +207,13 @@ public:
|
||||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||||
remote()->transact(BnSurfaceComposer::UNBLANK, data, &reply);
|
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");
|
IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
|
||||||
|
@ -301,6 +308,12 @@ status_t BnSurfaceComposer::onTransact(
|
||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||||
unblank();
|
unblank();
|
||||||
} break;
|
} break;
|
||||||
|
case CONNECT_DISPLAY: {
|
||||||
|
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||||
|
sp<ISurfaceTexture> surfaceTexture =
|
||||||
|
interface_cast<ISurfaceTexture>(data.readStrongBinder());
|
||||||
|
connectDisplay(surfaceTexture);
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
return BBinder::onTransact(code, data, reply, flags);
|
return BBinder::onTransact(code, data, reply, flags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,21 +224,11 @@ void DisplayHardware::init(uint32_t dpy)
|
||||||
|
|
||||||
// initialize EGL
|
// initialize EGL
|
||||||
EGLint attribs[] = {
|
EGLint attribs[] = {
|
||||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||||
EGL_NONE, 0,
|
EGL_RECORDABLE_ANDROID, EGL_TRUE,
|
||||||
EGL_NONE
|
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
|
// TODO: all the extensions below should be queried through
|
||||||
// eglGetProcAddress().
|
// eglGetProcAddress().
|
||||||
|
|
||||||
|
@ -248,6 +238,13 @@ void DisplayHardware::init(uint32_t dpy)
|
||||||
|
|
||||||
EGLConfig config = NULL;
|
EGLConfig config = NULL;
|
||||||
err = selectConfigForPixelFormat(display, attribs, format, &config);
|
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");
|
ALOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
|
||||||
|
|
||||||
EGLint r,g,b,a;
|
EGLint r,g,b,a;
|
||||||
|
|
|
@ -96,6 +96,7 @@ public:
|
||||||
|
|
||||||
uint32_t getPageFlipCount() const;
|
uint32_t getPageFlipCount() const;
|
||||||
EGLDisplay getEGLDisplay() const { return mDisplay; }
|
EGLDisplay getEGLDisplay() const { return mDisplay; }
|
||||||
|
EGLConfig getEGLConfig() const { return mConfig; }
|
||||||
|
|
||||||
void dump(String8& res) const;
|
void dump(String8& res) const;
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include <private/android_filesystem_config.h>
|
#include <private/android_filesystem_config.h>
|
||||||
#include <private/gui/SharedBufferStack.h>
|
#include <private/gui/SharedBufferStack.h>
|
||||||
#include <gui/BitTube.h>
|
#include <gui/BitTube.h>
|
||||||
|
#include <gui/SurfaceTextureClient.h>
|
||||||
|
|
||||||
#define EGL_VERSION_HW_ANDROID 0x3143
|
#define EGL_VERSION_HW_ANDROID 0x3143
|
||||||
|
|
||||||
|
@ -97,7 +98,8 @@ SurfaceFlinger::SurfaceFlinger()
|
||||||
mDebugInTransaction(0),
|
mDebugInTransaction(0),
|
||||||
mLastTransactionTime(0),
|
mLastTransactionTime(0),
|
||||||
mBootFinished(false),
|
mBootFinished(false),
|
||||||
mSecureFrameBuffer(0)
|
mSecureFrameBuffer(0),
|
||||||
|
mExternalDisplaySurface(EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
@ -370,6 +372,41 @@ sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
|
||||||
return mEventThread->createEventConnection();
|
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() {
|
void SurfaceFlinger::waitForEvent() {
|
||||||
|
@ -454,6 +491,43 @@ void SurfaceFlinger::onMessageReceived(int32_t what)
|
||||||
hw.compositionComplete();
|
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;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,6 +153,8 @@ public:
|
||||||
// called when screen is turning back on
|
// called when screen is turning back on
|
||||||
virtual void unblank();
|
virtual void unblank();
|
||||||
|
|
||||||
|
virtual void connectDisplay(const sp<ISurfaceTexture> display);
|
||||||
|
|
||||||
// called on the main thread in response to screenReleased()
|
// called on the main thread in response to screenReleased()
|
||||||
void onScreenReleased();
|
void onScreenReleased();
|
||||||
// called on the main thread in response to screenAcquired()
|
// 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
|
// only written in the main thread, only read in other threads
|
||||||
volatile int32_t mSecureFrameBuffer;
|
volatile int32_t mSecureFrameBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
EGLSurface getExternalDisplaySurface() const;
|
||||||
|
sp<SurfaceTextureClient> mExternalDisplayNativeWindow;
|
||||||
|
EGLSurface mExternalDisplaySurface;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue