From 99c7dbb24994df2f3e175f7b25dd2c9dd92a72f0 Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Thu, 14 Mar 2013 14:29:29 -0700 Subject: [PATCH] Add DisplaySurface abstraction 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 | 32 ++++---- services/surfaceflinger/DisplayDevice.cpp | 75 ++++++++----------- services/surfaceflinger/DisplayDevice.h | 9 +-- .../DisplayHardware/DisplaySurface.h | 68 +++++++++++++++++ .../DisplayHardware/FramebufferSurface.cpp | 29 ++++++- .../DisplayHardware/FramebufferSurface.h | 23 +++--- .../DisplayHardware/HWComposer.cpp | 6 +- .../DisplayHardware/VirtualDisplaySurface.cpp | 60 +++++++++++++++ .../DisplayHardware/VirtualDisplaySurface.h | 57 ++++++++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 34 ++++----- 10 files changed, 292 insertions(+), 101 deletions(-) create mode 100644 services/surfaceflinger/DisplayHardware/DisplaySurface.h create mode 100644 services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp create mode 100644 services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 5ff8154e7..6f89ffadf 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -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 diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 37a14c8fd..ecd12d084 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -35,7 +35,7 @@ #include -#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& displayToken, - const sp& nativeWindow, - const sp& framebufferSurface, + const sp& 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); } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index f67101705..d8f55b457 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -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& displayToken, - const sp& nativeWindow, - const sp& framebufferSurface, + const sp& displaySurface, EGLConfig config); ~DisplayDevice(); @@ -165,9 +164,7 @@ private: // ANativeWindow this display is rendering into sp mNativeWindow; - - // set if mNativeWindow is a FramebufferSurface - sp mFramebufferSurface; + sp mDisplaySurface; EGLDisplay mDisplay; EGLSurface mSurface; diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h new file mode 100644 index 000000000..2de6b4cc9 --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h @@ -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 +#include +#include + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class IGraphicBufferProducer; +class String8; + +class DisplaySurface : public virtual RefBase { +public: + virtual sp 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 + diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 960f9a953..b5abaacfd 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -68,6 +68,17 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) : mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS); } +sp 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& outBuffer, sp& 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(fbs)->dump(s); +// +// // calls FramebufferSurface::dump() since it is virtual +// static_cast(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); } diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 639e72061..0aab7424c 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -22,6 +22,8 @@ #include +#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 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 diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 7df3671ab..4b6c4130b 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -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 index 000000000..d30e9bf15 --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -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 +#include "VirtualDisplaySurface.h" + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int disp, + const sp& sink, const String8& name) +: mHwc(hwc), + mDisplayId(disp), + mSink(sink), + mName(name) +{} + +VirtualDisplaySurface::~VirtualDisplaySurface() { +} + +sp 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 index 000000000..db886ed0e --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -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 +#include "DisplaySurface.h" + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class HWComposer; + +class VirtualDisplaySurface : public DisplaySurface { +public: + VirtualDisplaySurface(HWComposer& hwc, int disp, + const sp& sink, + const String8& name); + + virtual sp 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 mSink; + String8 mName; +}; + +// --------------------------------------------------------------------------- +} // namespace android +// --------------------------------------------------------------------------- + +#endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H + diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 551f9023e..88c7fa0db 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -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 token = mBuiltinDisplays[i]; - sp fbs = new FramebufferSurface(*mHwc, i); - sp stc = new Surface( - static_cast< sp >(fbs->getBufferQueue())); sp 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 fbs; - sp stc; - if (!state.isVirtualDisplay()) { - + sp 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 >( - fbs->getBufferQueue())); - } else { - if (state.surface != NULL) { - stc = new Surface(state.surface); - } + dispSurface = new FramebufferSurface(*mHwc, state.type); } const wp& display(curr.keyAt(i)); - if (stc != NULL) { + if (dispSurface != NULL) { sp 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);