summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorJesse Hall <jessehall@google.com>2013-03-22 15:13:48 -0700
committerJesse Hall <jessehall@google.com>2013-03-22 15:27:58 -0700
commitffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0a (patch)
treee96e4d9d19a81ec6ee46052e54f3b2fda16465f3 /services
parent48bc05b56df9919fc39c5f2e3ea6535560eec98f (diff)
downloadframeworks_native-ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0a.zip
frameworks_native-ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0a.tar.gz
frameworks_native-ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0a.tar.bz2
Fix virtual displays for HWC<=1.1
If we're using a HWC that doesn't support virtual displays, or we have more virtual displays than HWC supports concurrently, the VirtualDisplaySurface should simply be a passthrough from source (GLES) to sink. This change also tries to distinguish between display types and HWC display IDs a little better, though there's more to do here. Probably needs a higher-level rethink; it's too error-prone now. Bug: 8446838 Change-Id: I708d2cf262ec30177042304f174ca5b8da701df1
Diffstat (limited to 'services')
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp69
-rw-r--r--services/surfaceflinger/DisplayDevice.h3
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp32
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h16
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp10
5 files changed, 73 insertions, 57 deletions
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index cdc16ed..6936a7f 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -70,12 +70,13 @@ void checkGLErrors()
DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
+ int32_t hwcId,
bool isSecure,
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
EGLConfig config)
: mFlinger(flinger),
- mType(type), mHwcDisplayId(-1),
+ mType(type), mHwcDisplayId(hwcId),
mDisplayToken(displayToken),
mDisplaySurface(displaySurface),
mDisplay(EGL_NO_DISPLAY),
@@ -91,38 +92,6 @@ DisplayDevice::DisplayDevice(
mOrientation()
{
mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
- init(config);
-}
-
-DisplayDevice::~DisplayDevice() {
- if (mSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mDisplay, mSurface);
- mSurface = EGL_NO_SURFACE;
- }
-}
-
-bool DisplayDevice::isValid() const {
- return mFlinger != NULL;
-}
-
-int DisplayDevice::getWidth() const {
- return mDisplayWidth;
-}
-
-int DisplayDevice::getHeight() const {
- return mDisplayHeight;
-}
-
-PixelFormat DisplayDevice::getFormat() const {
- return mFormat;
-}
-
-EGLSurface DisplayDevice::getEGLSurface() const {
- return mSurface;
-}
-
-void DisplayDevice::init(EGLConfig config)
-{
ANativeWindow* const window = mNativeWindow.get();
int format;
@@ -146,11 +115,8 @@ void DisplayDevice::init(EGLConfig config)
mViewport.makeInvalid();
mFrame.makeInvalid();
- // external displays are always considered enabled
- mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES);
-
- // get an h/w composer ID
- mHwcDisplayId = mFlinger->allocateHwcDisplayId(mType);
+ // virtual displays are always considered enabled
+ mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);
// Name the display. The name will be replaced shortly if the display
// was created with createDisplay().
@@ -170,6 +136,33 @@ void DisplayDevice::init(EGLConfig config)
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
}
+DisplayDevice::~DisplayDevice() {
+ if (mSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mDisplay, mSurface);
+ mSurface = EGL_NO_SURFACE;
+ }
+}
+
+bool DisplayDevice::isValid() const {
+ return mFlinger != NULL;
+}
+
+int DisplayDevice::getWidth() const {
+ return mDisplayWidth;
+}
+
+int DisplayDevice::getHeight() const {
+ return mDisplayHeight;
+}
+
+PixelFormat DisplayDevice::getFormat() const {
+ return mFormat;
+}
+
+EGLSurface DisplayDevice::getEGLSurface() const {
+ return mSurface;
+}
+
void DisplayDevice::setDisplayName(const String8& displayName) {
if (!displayName.isEmpty()) {
// never override the name with an empty name
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d8f55b4..d4a6daa 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -72,6 +72,7 @@ public:
DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
+ int32_t hwcId, // negative for non-HWC-composited displays
bool isSecure,
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
@@ -152,8 +153,6 @@ public:
void dump(String8& result, char* buffer, size_t SIZE) const;
private:
- void init(EGLConfig config);
-
/*
* Constants, set during initialization
*/
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index b28500e..d2b3edb 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -21,24 +21,30 @@
namespace android {
// ---------------------------------------------------------------------------
-VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int disp,
+VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
const sp<IGraphicBufferProducer>& sink, const String8& name)
: mHwc(hwc),
- mDisplayId(disp),
- mSource(new BufferQueueInterposer(sink, name)),
+ mDisplayId(dispId),
mName(name)
-{}
+{
+ if (mDisplayId >= 0) {
+ mInterposer = new BufferQueueInterposer(sink, name);
+ mSourceProducer = mInterposer;
+ } else {
+ mSourceProducer = sink;
+ }
+}
VirtualDisplaySurface::~VirtualDisplaySurface() {
if (mAcquiredBuffer != NULL) {
- status_t result = mSource->releaseBuffer(Fence::NO_FENCE);
+ status_t result = mInterposer->releaseBuffer(Fence::NO_FENCE);
ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": "
"failed to release buffer: %d", mName.string(), result);
}
}
sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const {
- return mSource;
+ return mSourceProducer;
}
status_t VirtualDisplaySurface::compositionComplete() {
@@ -46,6 +52,9 @@ status_t VirtualDisplaySurface::compositionComplete() {
}
status_t VirtualDisplaySurface::advanceFrame() {
+ if (mInterposer == NULL)
+ return NO_ERROR;
+
Mutex::Autolock lock(mMutex);
status_t result = NO_ERROR;
@@ -57,12 +66,12 @@ status_t VirtualDisplaySurface::advanceFrame() {
}
sp<Fence> fence;
- result = mSource->acquireBuffer(&mAcquiredBuffer, &fence);
+ result = mInterposer->acquireBuffer(&mAcquiredBuffer, &fence);
if (result == BufferQueueInterposer::NO_BUFFER_AVAILABLE) {
- result = mSource->pullEmptyBuffer();
+ result = mInterposer->pullEmptyBuffer();
if (result != NO_ERROR)
return result;
- result = mSource->acquireBuffer(&mAcquiredBuffer, &fence);
+ result = mInterposer->acquireBuffer(&mAcquiredBuffer, &fence);
}
if (result != NO_ERROR)
return result;
@@ -71,6 +80,9 @@ status_t VirtualDisplaySurface::advanceFrame() {
}
void VirtualDisplaySurface::onFrameCommitted() {
+ if (mInterposer == NULL)
+ return;
+
Mutex::Autolock lock(mMutex);
if (mAcquiredBuffer != NULL) {
// fbFence signals when reads from the framebuffer are finished
@@ -85,7 +97,7 @@ void VirtualDisplaySurface::onFrameCommitted() {
String8::format("HWC done: %.21s", mName.string()),
fbFence, outFence);
- status_t result = mSource->releaseBuffer(fence);
+ status_t result = mInterposer->releaseBuffer(fence);
ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": "
"failed to release buffer: %d", mName.string(), result);
mAcquiredBuffer.clear();
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 61bafed..0706e75 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -45,12 +45,18 @@ class HWComposer;
* eglSwapBuffers doesn't immediately dequeue a buffer for the next frame,
* since we can't rely on being able to dequeue more than one buffer at a time.
*
+ * This class also has a passthrough mode, where it doesn't use a
+ * BufferQueueInterposer and never sends buffers to HWC. Instead, OpenGL ES
+ * output buffers are queued directly to the virtual display sink; this class
+ * is inactive after construction. This mode is used when the HWC doesn't
+ * support compositing for virtual displays.
+ *
* TODO(jessehall): Add a libgui test that ensures that EGL/GLES do lazy
* dequeBuffers; we've wanted to require that for other reasons anyway.
*/
class VirtualDisplaySurface : public DisplaySurface {
public:
- VirtualDisplaySurface(HWComposer& hwc, int disp,
+ VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
const sp<IGraphicBufferProducer>& sink,
const String8& name);
@@ -66,10 +72,14 @@ private:
// immutable after construction
HWComposer& mHwc;
- int mDisplayId;
- sp<BufferQueueInterposer> mSource;
+ int32_t mDisplayId;
String8 mName;
+ // with HWC support, both of these point to the same object.
+ // otherwise, mInterposer is NULL and mSourceProducer is the sink.
+ sp<BufferQueueInterposer> mInterposer;
+ sp<IGraphicBufferProducer> mSourceProducer;
+
// mutable, must be synchronized with mMutex
Mutex mMutex;
sp<GraphicBuffer> mAcquiredBuffer;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2df279a..0a210f7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -510,7 +510,8 @@ status_t SurfaceFlinger::readyToRun()
wp<IBinder> token = mBuiltinDisplays[i];
sp<DisplayDevice> hw = new DisplayDevice(this,
- type, isSecure, token, new FramebufferSurface(*mHwc, i),
+ type, allocateHwcDisplayId(type), isSecure, token,
+ new FramebufferSurface(*mHwc, i),
mEGLConfig);
if (i > DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: currently we don't get blank/unblank requests
@@ -1149,10 +1150,11 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
const DisplayDeviceState& state(curr[i]);
sp<DisplaySurface> dispSurface;
+ int32_t hwcDisplayId = allocateHwcDisplayId(state.type);
if (state.isVirtualDisplay()) {
if (state.surface != NULL) {
dispSurface = new VirtualDisplaySurface(
- *mHwc, state.type, state.surface,
+ *mHwc, hwcDisplayId, state.surface,
state.displayName);
}
} else {
@@ -1169,8 +1171,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
const wp<IBinder>& display(curr.keyAt(i));
if (dispSurface != NULL) {
sp<DisplayDevice> hw = new DisplayDevice(this,
- state.type, state.isSecure, display,
- dispSurface, mEGLConfig);
+ state.type, hwcDisplayId, state.isSecure,
+ display, dispSurface, mEGLConfig);
hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation,
state.viewport, state.frame);