OSDN Git Service

Fix virtual displays for HWC<=1.1
authorJesse Hall <jessehall@google.com>
Fri, 22 Mar 2013 22:13:48 +0000 (15:13 -0700)
committerJesse Hall <jessehall@google.com>
Fri, 22 Mar 2013 22:27:58 +0000 (15:27 -0700)
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

services/surfaceflinger/DisplayDevice.cpp
services/surfaceflinger/DisplayDevice.h
services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
services/surfaceflinger/SurfaceFlinger.cpp

index cdc16ed..6936a7f 100644 (file)
@@ -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
index d8f55b4..d4a6daa 100644 (file)
@@ -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
      */
index b28500e..d2b3edb 100644 (file)
 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();
index 61bafed..0706e75 100644 (file)
@@ -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;
index 2df279a..0a210f7 100644 (file)
@@ -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);