diff options
author | Jesse Hall <jessehall@google.com> | 2013-03-14 14:29:29 -0700 |
---|---|---|
committer | Jesse Hall <jessehall@google.com> | 2013-03-18 14:21:16 -0700 |
commit | 99c7dbb24994df2f3e175f7b25dd2c9dd92a72f0 (patch) | |
tree | d49c7660b0e8de474c00f9b842830c3770af95ba /services/surfaceflinger | |
parent | 4c00cc11141da7d159eb2323b186ed344115c0f1 (diff) | |
download | frameworks_native-99c7dbb24994df2f3e175f7b25dd2c9dd92a72f0.zip frameworks_native-99c7dbb24994df2f3e175f7b25dd2c9dd92a72f0.tar.gz frameworks_native-99c7dbb24994df2f3e175f7b25dd2c9dd92a72f0.tar.bz2 |
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
Diffstat (limited to 'services/surfaceflinger')
10 files changed, 292 insertions, 101 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 5ff8154..6f89ffa 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 37a14c8..ecd12d0 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -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); } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index f671017..d8f55b4 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<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 index 0000000..2de6b4c --- /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 <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 + diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 960f9a9..b5abaac 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<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); } diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 639e720..0aab742 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -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 diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 7df3671..4b6c413 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 0000000..d30e9bf --- /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 <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 index 0000000..db886ed --- /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 <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 + diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 551f902..88c7fa0 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<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); |