OSDN Git Service

Add DisplaySurface abstraction
authorJesse Hall <jessehall@google.com>
Thu, 14 Mar 2013 21:29:29 +0000 (14:29 -0700)
committerJesse Hall <jessehall@google.com>
Mon, 18 Mar 2013 21:21:16 +0000 (14:21 -0700)
DisplayDevice now has a DisplaySurface instead of using
FramebufferSurface directly. FramebufferSurface implements
DisplaySurface, and so does the new VirtualDisplaySurface class.
DisplayDevice now always has a surface, not just for virtual displays.

In this change VirtualDisplaySurface is just a stub; buffers still go
directly from GLES to the final consumer.

Bug: 8384764
Change-Id: I57cb668edbc6c37bfebda90b9222d435bf589f37

services/surfaceflinger/Android.mk
services/surfaceflinger/DisplayDevice.cpp
services/surfaceflinger/DisplayDevice.h
services/surfaceflinger/DisplayHardware/DisplaySurface.h [new file with mode: 0644]
services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
services/surfaceflinger/DisplayHardware/FramebufferSurface.h
services/surfaceflinger/DisplayHardware/HWComposer.cpp
services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp [new file with mode: 0644]
services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h [new file with mode: 0644]
services/surfaceflinger/SurfaceFlinger.cpp

index 5ff8154..6f89ffa 100644 (file)
@@ -2,22 +2,22 @@ LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    Client.cpp                              \
-    DisplayDevice.cpp                       \
-    EventThread.cpp                         \
-    FrameTracker.cpp                        \
-    Layer.cpp                               \
-    LayerDim.cpp                            \
-    DisplayHardware/FramebufferSurface.cpp  \
-    DisplayHardware/HWComposer.cpp          \
-    DisplayHardware/PowerHAL.cpp            \
-    GLExtensions.cpp                        \
-    MessageQueue.cpp                        \
-    SurfaceFlinger.cpp                      \
-    SurfaceFlingerConsumer.cpp              \
-    SurfaceTextureLayer.cpp                 \
-    Transform.cpp                           \
-    
+    Client.cpp \
+    DisplayDevice.cpp \
+    EventThread.cpp \
+    FrameTracker.cpp \
+    GLExtensions.cpp \
+    Layer.cpp \
+    LayerDim.cpp \
+    MessageQueue.cpp \
+    SurfaceFlinger.cpp \
+    SurfaceFlingerConsumer.cpp \
+    SurfaceTextureLayer.cpp \
+    Transform.cpp \
+    DisplayHardware/FramebufferSurface.cpp \
+    DisplayHardware/HWComposer.cpp \
+    DisplayHardware/PowerHAL.cpp \
+    DisplayHardware/VirtualDisplaySurface.cpp \
 
 LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
index 37a14c8..ecd12d0 100644 (file)
@@ -35,7 +35,7 @@
 
 #include <hardware/gralloc.h>
 
-#include "DisplayHardware/FramebufferSurface.h"
+#include "DisplayHardware/DisplaySurface.h"
 #include "DisplayHardware/HWComposer.h"
 
 #include "clz.h"
@@ -72,14 +72,12 @@ DisplayDevice::DisplayDevice(
         DisplayType type,
         bool isSecure,
         const wp<IBinder>& displayToken,
-        const sp<ANativeWindow>& nativeWindow,
-        const sp<FramebufferSurface>& framebufferSurface,
+        const sp<DisplaySurface>& displaySurface,
         EGLConfig config)
     : mFlinger(flinger),
       mType(type), mHwcDisplayId(-1),
       mDisplayToken(displayToken),
-      mNativeWindow(nativeWindow),
-      mFramebufferSurface(framebufferSurface),
+      mDisplaySurface(displaySurface),
       mDisplay(EGL_NO_DISPLAY),
       mSurface(EGL_NO_SURFACE),
       mContext(EGL_NO_CONTEXT),
@@ -92,6 +90,7 @@ DisplayDevice::DisplayDevice(
       mLayerStack(NO_LAYER_STACK),
       mOrientation()
 {
+    mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
     init(config);
 }
 
@@ -183,10 +182,7 @@ uint32_t DisplayDevice::getPageFlipCount() const {
 }
 
 status_t DisplayDevice::compositionComplete() const {
-    if (mFramebufferSurface == NULL) {
-        return NO_ERROR;
-    }
-    return mFramebufferSurface->compositionComplete();
+    return mDisplaySurface->compositionComplete();
 }
 
 void DisplayDevice::flip(const Region& dirty) const
@@ -209,45 +205,38 @@ void DisplayDevice::flip(const Region& dirty) const
 }
 
 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
-    EGLBoolean success = EGL_TRUE;
-    if (hwc.initCheck() != NO_ERROR) {
-        // no HWC, we call eglSwapBuffers()
-        success = eglSwapBuffers(mDisplay, mSurface);
-    } else {
-        // We have a valid HWC, but not all displays can use it, in particular
-        // the virtual displays are on their own.
-        // TODO: HWC 1.2 will allow virtual displays
-        if (mType >= DisplayDevice::DISPLAY_VIRTUAL) {
-            // always call eglSwapBuffers() for virtual displays
-            success = eglSwapBuffers(mDisplay, mSurface);
-        } else if (hwc.supportsFramebufferTarget()) {
-            // as of hwc 1.1 we always call eglSwapBuffers if we have some
-            // GLES layers
-            if (hwc.hasGlesComposition(mType)) {
-                success = eglSwapBuffers(mDisplay, mSurface);
+    // We need to call eglSwapBuffers() unless:
+    // (a) there was no GLES composition this frame, or
+    // (b) we're using a legacy HWC with no framebuffer target support (in
+    //     which case HWComposer::commit() handles things).
+    if (hwc.initCheck() != NO_ERROR ||
+            (hwc.hasGlesComposition(mHwcDisplayId) &&
+             hwc.supportsFramebufferTarget())) {
+        EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
+        if (!success) {
+            EGLint error = eglGetError();
+            if (error == EGL_CONTEXT_LOST ||
+                    mType == DisplayDevice::DISPLAY_PRIMARY) {
+                LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
+                        mDisplay, mSurface, error);
+            } else {
+                ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
+                        mDisplay, mSurface, error);
             }
-        } else {
-            // HWC doesn't have the framebuffer target, we don't call
-            // eglSwapBuffers(), since this is handled by HWComposer::commit().
         }
     }
 
-    if (!success) {
-        EGLint error = eglGetError();
-        if (error == EGL_CONTEXT_LOST ||
-                mType == DisplayDevice::DISPLAY_PRIMARY) {
-            LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
-                    mDisplay, mSurface, error);
-        }
+    status_t result = mDisplaySurface->advanceFrame();
+    if (result != NO_ERROR) {
+        ALOGE("[%s] failed pushing new frame to HWC: %d",
+                mDisplayName.string(), result);
     }
 }
 
 void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
     if (hwc.initCheck() == NO_ERROR) {
-        if (mFramebufferSurface != NULL) {
-            int fd = hwc.getAndResetReleaseFenceFd(mType);
-            mFramebufferSurface->setReleaseFenceFd(fd);
-        }
+        int fd = hwc.getAndResetReleaseFenceFd(mType);
+        mDisplaySurface->setReleaseFenceFd(fd);
     }
 }
 
@@ -455,9 +444,7 @@ void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
 
     result.append(buffer);
 
-    String8 fbtargetDump;
-    if (mFramebufferSurface != NULL) {
-        mFramebufferSurface->dump(fbtargetDump);
-        result.append(fbtargetDump);
-    }
+    String8 surfaceDump;
+    mDisplaySurface->dump(surfaceDump);
+    result.append(surfaceDump);
 }
index f671017..d8f55b4 100644 (file)
@@ -37,7 +37,7 @@ struct ANativeWindow;
 namespace android {
 
 class DisplayInfo;
-class FramebufferSurface;
+class DisplaySurface;
 class Layer;
 class SurfaceFlinger;
 class HWComposer;
@@ -74,8 +74,7 @@ public:
             DisplayType type,
             bool isSecure,
             const wp<IBinder>& displayToken,
-            const sp<ANativeWindow>& nativeWindow,
-            const sp<FramebufferSurface>& framebufferSurface,
+            const sp<DisplaySurface>& displaySurface,
             EGLConfig config);
 
     ~DisplayDevice();
@@ -165,9 +164,7 @@ private:
 
     // ANativeWindow this display is rendering into
     sp<ANativeWindow> mNativeWindow;
-
-    // set if mNativeWindow is a FramebufferSurface
-    sp<FramebufferSurface> mFramebufferSurface;
+    sp<DisplaySurface> mDisplaySurface;
 
     EGLDisplay      mDisplay;
     EGLSurface      mSurface;
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
new file mode 100644 (file)
index 0000000..2de6b4c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_DISPLAY_SURFACE_H
+#define ANDROID_SF_DISPLAY_SURFACE_H
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class IGraphicBufferProducer;
+class String8;
+
+class DisplaySurface : public virtual RefBase {
+public:
+    virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const = 0;
+
+    // Should be called when composition rendering is complete for a frame (but
+    // eglSwapBuffers hasn't necessarily been called). Required by certain
+    // older drivers for synchronization.
+    // TODO: Remove this when we drop support for HWC 1.0.
+    virtual status_t compositionComplete() = 0;
+
+    // Inform the surface that GLES composition is complete for this frame, and
+    // the surface should make sure that HWComposer has the correct buffer for
+    // this frame. Some implementations may only push a new buffer to
+    // HWComposer if GLES composition took place, others need to push a new
+    // buffer on every frame.
+    virtual status_t advanceFrame() = 0;
+
+    // setReleaseFenceFd stores a fence file descriptor that will signal when
+    // the current buffer is no longer being read. This fence will be returned
+    // to the producer when the current buffer is released by updateTexImage().
+    // Multiple fences can be set for a given buffer; they will be merged into
+    // a single union fence. The GLConsumer will close the file descriptor
+    // when finished with it.
+    virtual status_t setReleaseFenceFd(int fenceFd) = 0;
+
+    virtual void dump(String8& result) const = 0;
+
+protected:
+    DisplaySurface() {}
+    virtual ~DisplaySurface() {}
+};
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SF_DISPLAY_SURFACE_H
+
index 960f9a9..b5abaac 100644 (file)
@@ -68,6 +68,17 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) :
     mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
 }
 
+sp<IGraphicBufferProducer> FramebufferSurface::getIGraphicBufferProducer() const {
+    return getBufferQueue();
+}
+
+status_t FramebufferSurface::advanceFrame() {
+    // Once we remove FB HAL support, we can call nextBuffer() from here
+    // instead of using onFrameAvailable(). No real benefit, except it'll be
+    // more like VirtualDisplaySurface.
+    return NO_ERROR;
+}
+
 status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
     Mutex::Autolock lock(mMutex);
 
@@ -147,7 +158,23 @@ status_t FramebufferSurface::compositionComplete()
     return mHwc.fbCompositionComplete();
 }
 
-void FramebufferSurface::dump(String8& result) {
+// Since DisplaySurface and ConsumerBase both have a method with this
+// signature, results will vary based on the static pointer type the caller is
+// using:
+//   void dump(FrameBufferSurface* fbs, String8& s) {
+//       // calls FramebufferSurface::dump()
+//       fbs->dump(s);
+//
+//       // calls ConsumerBase::dump() since it is non-virtual
+//       static_cast<ConsumerBase*>(fbs)->dump(s);
+//
+//       // calls FramebufferSurface::dump() since it is virtual
+//       static_cast<DisplaySurface*>(fbs)->dump(s);
+//   }
+// To make sure that all of these end up doing the same thing, we just redirect
+// to ConsumerBase::dump() here. It will take the internal lock, and then call
+// virtual dumpLocked(), which is where the real work happens.
+void FramebufferSurface::dump(String8& result) const {
     ConsumerBase::dump(result);
 }
 
index 639e720..0aab742 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <gui/ConsumerBase.h>
 
+#include "DisplaySurface.h"
+
 // ---------------------------------------------------------------------------
 namespace android {
 // ---------------------------------------------------------------------------
@@ -32,23 +34,20 @@ class HWComposer;
 
 // ---------------------------------------------------------------------------
 
-class FramebufferSurface : public ConsumerBase {
+class FramebufferSurface : public ConsumerBase,
+                           public DisplaySurface {
 public:
     FramebufferSurface(HWComposer& hwc, int disp);
 
-    status_t compositionComplete();
+    virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
 
-    // TODO(jessehall): This overrides the non-virtual ConsumerBase version.
-    // Will rework slightly in a following change.
-    void dump(String8& result);
+    virtual status_t compositionComplete();
+    virtual status_t advanceFrame();
+    virtual status_t setReleaseFenceFd(int fenceFd);
 
-    // setReleaseFenceFd stores a fence file descriptor that will signal when the
-    // current buffer is no longer being read. This fence will be returned to
-    // the producer when the current buffer is released by updateTexImage().
-    // Multiple fences can be set for a given buffer; they will be merged into
-    // a single union fence. The GLConsumer will close the file descriptor
-    // when finished with it.
-    status_t setReleaseFenceFd(int fenceFd);
+    // Implementation of DisplaySurface::dump(). Note that ConsumerBase also
+    // has a non-virtual dump() with the same signature.
+    virtual void dump(String8& result) const;
 
 private:
     virtual ~FramebufferSurface() { }; // this class cannot be overloaded
index 7df3671..4b6c413 100644 (file)
@@ -617,14 +617,14 @@ status_t HWComposer::prepare() {
 }
 
 bool HWComposer::hasHwcComposition(int32_t id) const {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
         return false;
     return mDisplayData[id].hasOvComp;
 }
 
 bool HWComposer::hasGlesComposition(int32_t id) const {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
-        return false;
+    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return true;
     return mDisplayData[id].hasFbComp;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
new file mode 100644 (file)
index 0000000..d30e9bf
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/IGraphicBufferProducer.h>
+#include "VirtualDisplaySurface.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int disp,
+        const sp<IGraphicBufferProducer>& sink, const String8& name)
+:   mHwc(hwc),
+    mDisplayId(disp),
+    mSink(sink),
+    mName(name)
+{}
+
+VirtualDisplaySurface::~VirtualDisplaySurface() {
+}
+
+sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const {
+    return mSink;
+}
+
+status_t VirtualDisplaySurface::compositionComplete() {
+    return NO_ERROR;
+}
+
+status_t VirtualDisplaySurface::advanceFrame() {
+    return NO_ERROR;
+}
+
+status_t VirtualDisplaySurface::setReleaseFenceFd(int fenceFd) {
+    if (fenceFd >= 0) {
+        ALOGW("[%s] unexpected release fence", mName.string());
+        close(fenceFd);
+    }
+    return NO_ERROR;
+}
+
+void VirtualDisplaySurface::dump(String8& result) const {
+}
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
new file mode 100644 (file)
index 0000000..db886ed
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+
+#include <utils/String8.h>
+#include "DisplaySurface.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class HWComposer;
+
+class VirtualDisplaySurface : public DisplaySurface {
+public:
+    VirtualDisplaySurface(HWComposer& hwc, int disp,
+            const sp<IGraphicBufferProducer>& sink,
+            const String8& name);
+
+    virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
+
+    virtual status_t compositionComplete();
+    virtual status_t advanceFrame();
+    virtual status_t setReleaseFenceFd(int fenceFd);
+    virtual void dump(String8& result) const;
+
+private:
+    virtual ~VirtualDisplaySurface();
+
+    // immutable after construction
+    HWComposer& mHwc;
+    int mDisplayId;
+    sp<IGraphicBufferProducer> mSink;
+    String8 mName;
+};
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+
index 551f902..88c7fa0 100644 (file)
@@ -66,6 +66,7 @@
 
 #include "DisplayHardware/FramebufferSurface.h"
 #include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/VirtualDisplaySurface.h"
 
 
 #define EGL_VERSION_HW_ANDROID  0x3143
@@ -501,11 +502,9 @@ status_t SurfaceFlinger::readyToRun()
             createBuiltinDisplayLocked(type);
             wp<IBinder> token = mBuiltinDisplays[i];
 
-            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);
-            sp<Surface> stc = new Surface(
-                        static_cast< sp<IGraphicBufferProducer> >(fbs->getBufferQueue()));
             sp<DisplayDevice> hw = new DisplayDevice(this,
-                    type, isSecure, token, stc, fbs, mEGLConfig);
+                    type, isSecure, token, new FramebufferSurface(*mHwc, i),
+                    mEGLConfig);
             if (i > DisplayDevice::DISPLAY_PRIMARY) {
                 // FIXME: currently we don't get blank/unblank requests
                 // for displays other than the main display, so we always
@@ -1174,10 +1173,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
                 if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                     const DisplayDeviceState& state(curr[i]);
 
-                    sp<FramebufferSurface> fbs;
-                    sp<Surface> stc;
-                    if (!state.isVirtualDisplay()) {
-
+                    sp<DisplaySurface> dispSurface;
+                    if (state.isVirtualDisplay()) {
+                        if (state.surface != NULL) {
+                            dispSurface = new VirtualDisplaySurface(
+                                    *mHwc, state.type, state.surface,
+                                    state.displayName);
+                        }
+                    } else {
                         ALOGE_IF(state.surface!=NULL,
                                 "adding a supported display, but rendering "
                                 "surface is provided (%p), ignoring it",
@@ -1185,21 +1188,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
 
                         // for supported (by hwc) displays we provide our
                         // own rendering surface
-                        fbs = new FramebufferSurface(*mHwc, state.type);
-                        stc = new Surface(
-                                static_cast< sp<IGraphicBufferProducer> >(
-                                        fbs->getBufferQueue()));
-                    } else {
-                        if (state.surface != NULL) {
-                            stc = new Surface(state.surface);
-                        }
+                        dispSurface = new FramebufferSurface(*mHwc, state.type);
                     }
 
                     const wp<IBinder>& display(curr.keyAt(i));
-                    if (stc != NULL) {
+                    if (dispSurface != NULL) {
                         sp<DisplayDevice> hw = new DisplayDevice(this,
-                                state.type, state.isSecure, display, stc, fbs,
-                                mEGLConfig);
+                                state.type, state.isSecure, display,
+                                dispSurface, mEGLConfig);
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
                                 state.viewport, state.frame);