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
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::advanceFrame() {
+ if (mInterposer == NULL)
+ return NO_ERROR;
+
Mutex::Autolock lock(mMutex);
status_t result = NO_ERROR;
@@ -57,12 +66,12 @@
}
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 @@
}
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 @@
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 @@
* 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 @@
// 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;