diff options
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.cpp | 136 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.h | 131 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 34 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.cpp | 42 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.h | 6 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 33 |
7 files changed, 286 insertions, 100 deletions
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 65763db..ce63ee7 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -43,6 +43,19 @@ namespace android { // --------------------------------------------------------------------------- +struct HWComposer::cb_context { + struct callbacks : public hwc_procs_t { + // these are here to facilitate the transition when adding + // new callbacks (an implementation can check for NULL before + // calling a new callback). + void (*zero[4])(void); + }; + callbacks procs; + HWComposer* hwc; +}; + +// --------------------------------------------------------------------------- + HWComposer::HWComposer( const sp<SurfaceFlinger>& flinger, EventHandler& handler, @@ -51,6 +64,7 @@ HWComposer::HWComposer( mModule(0), mHwc(0), mList(0), mCapacity(0), mNumOVLayers(0), mNumFBLayers(0), mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE), + mCBContext(new cb_context), mEventHandler(handler), mRefreshPeriod(refreshPeriod), mVSyncCount(0), mDebugForceFakeVSync(false) @@ -68,11 +82,11 @@ HWComposer::HWComposer( HWC_HARDWARE_COMPOSER, strerror(-err)); if (err == 0) { if (mHwc->registerProcs) { - mCBContext.hwc = this; - mCBContext.procs.invalidate = &hook_invalidate; - mCBContext.procs.vsync = &hook_vsync; - mHwc->registerProcs(mHwc, &mCBContext.procs); - memset(mCBContext.procs.zero, 0, sizeof(mCBContext.procs.zero)); + mCBContext->hwc = this; + mCBContext->procs.invalidate = &hook_invalidate; + mCBContext->procs.vsync = &hook_vsync; + mHwc->registerProcs(mHwc, &mCBContext->procs); + memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero)); } if (mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) { if (mDebugForceFakeVSync) { @@ -102,6 +116,7 @@ HWComposer::~HWComposer() { if (mHwc) { hwc_close(mHwc); } + delete mCBContext; } status_t HWComposer::initCheck() const { @@ -230,10 +245,117 @@ size_t HWComposer::getNumLayers() const { return mList ? mList->numHwLayers : 0; } -hwc_layer_t* HWComposer::getLayers() const { - return mList ? mList->hwLayers : 0; +/* + * Helper template to implement a concrete HWCLayer + * This holds the pointer to the concrete hwc layer type + * and implements the "iterable" side of HWCLayer. + */ +template<typename CONCRETE, typename HWCTYPE> +class Iterable : public HWComposer::HWCLayer { +protected: + HWCTYPE* const mLayerList; + HWCTYPE* mCurrentLayer; + Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer) { } + inline HWCTYPE const * getLayer() const { return mCurrentLayer; } + inline HWCTYPE* getLayer() { return mCurrentLayer; } + virtual ~Iterable() { } +private: + // returns a copy of ourselves + virtual HWComposer::HWCLayer* dup() { + return new CONCRETE( static_cast<const CONCRETE&>(*this) ); + } + virtual status_t setLayer(size_t index) { + mCurrentLayer = &mLayerList[index]; + return NO_ERROR; + } +}; + +/* + * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_0_3 + * This implements the HWCLayer side of HWCIterableLayer. + */ +class HWCLayerVersion03 : public Iterable<HWCLayerVersion03, hwc_layer_t> { +public: + HWCLayerVersion03(hwc_layer_t* layer) + : Iterable<HWCLayerVersion03, hwc_layer_t>(layer) { } + + virtual int32_t getCompositionType() const { + return getLayer()->compositionType; + } + virtual uint32_t getHints() const { + return getLayer()->hints; + } + + virtual void setDefaultState() { + getLayer()->compositionType = HWC_FRAMEBUFFER; + getLayer()->hints = 0; + getLayer()->flags = HWC_SKIP_LAYER; + getLayer()->transform = 0; + getLayer()->blending = HWC_BLENDING_NONE; + getLayer()->visibleRegionScreen.numRects = 0; + getLayer()->visibleRegionScreen.rects = NULL; + } + virtual void setSkip(bool skip) { + if (skip) { + getLayer()->flags |= HWC_SKIP_LAYER; + } else { + getLayer()->flags &= ~HWC_SKIP_LAYER; + } + } + virtual void setBlending(uint32_t blending) { + getLayer()->blending = blending; + } + virtual void setTransform(uint32_t transform) { + getLayer()->transform = transform; + } + virtual void setFrame(const Rect& frame) { + reinterpret_cast<Rect&>(getLayer()->displayFrame) = frame; + } + virtual void setCrop(const Rect& crop) { + reinterpret_cast<Rect&>(getLayer()->sourceCrop) = crop; + } + virtual void setVisibleRegionScreen(const Region& reg) { + getLayer()->visibleRegionScreen.rects = + reinterpret_cast<hwc_rect_t const *>( + reg.getArray(&getLayer()->visibleRegionScreen.numRects)); + } + virtual void setBuffer(const sp<GraphicBuffer>& buffer) { + if (buffer == 0 || buffer->handle == 0) { + getLayer()->compositionType = HWC_FRAMEBUFFER; + getLayer()->flags |= HWC_SKIP_LAYER; + getLayer()->handle = 0; + } else { + getLayer()->handle = buffer->handle; + } + } +}; + +/* + * returns an iterator initialized at a given index in the layer list + */ +HWComposer::LayerListIterator HWComposer::getLayerIterator(size_t index) { + if (!mList || index > mList->numHwLayers) { + return LayerListIterator(); + } + return LayerListIterator(new HWCLayerVersion03(mList->hwLayers), index); +} + +/* + * returns an iterator on the beginning of the layer list + */ +HWComposer::LayerListIterator HWComposer::begin() { + return getLayerIterator(0); } +/* + * returns an iterator on the end of the layer list + */ +HWComposer::LayerListIterator HWComposer::end() { + return getLayerIterator(getNumLayers()); +} + + + void HWComposer::dump(String8& result, char* buffer, size_t SIZE, const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const { if (mHwc && mList) { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index aada3cd..cafa247 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -22,7 +22,7 @@ #include <EGL/egl.h> -#include <hardware/hwcomposer.h> +#include <hardware/hwcomposer_defs.h> #include <utils/StrongPointer.h> #include <utils/Vector.h> @@ -31,12 +31,17 @@ extern "C" int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, struct timespec *remain); +struct hwc_composer_device; +struct hwc_layer_list; +struct hwc_procs; + namespace android { // --------------------------------------------------------------------------- class String8; class SurfaceFlinger; class LayerBase; +class GraphicBuffer; class HWComposer { @@ -57,9 +62,6 @@ public: // tells the HAL what the framebuffer is void setFrameBuffer(EGLDisplay dpy, EGLSurface sur); - // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED. - status_t createWorkList(size_t numLayers); - // Asks the HAL what it can do status_t prepare() const; @@ -72,14 +74,109 @@ public: // release hardware resources status_t release() const; + // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED. + status_t createWorkList(size_t numLayers); + // get the layer array created by createWorkList() size_t getNumLayers() const; - hwc_layer_t* getLayers() const; // get number of layers of the given type as updated in prepare(). // type is HWC_OVERLAY or HWC_FRAMEBUFFER size_t getLayerCount(int type) const; + // needed forward declarations + class LayerListIterator; + + /* + * Interface to hardware composer's layers functionality. + * This abstracts the HAL interface to layers which can evolve in + * incompatible ways from one release to another. + * The idea is that we could extend this interface as we add + * features to h/w composer. + */ + class HWCLayerInterface { + protected: + virtual ~HWCLayerInterface() { } + public: + virtual int32_t getCompositionType() const = 0; + virtual uint32_t getHints() const = 0; + virtual void setDefaultState() = 0; + virtual void setSkip(bool skip) = 0; + virtual void setBlending(uint32_t blending) = 0; + virtual void setTransform(uint32_t transform) = 0; + virtual void setFrame(const Rect& frame) = 0; + virtual void setCrop(const Rect& crop) = 0; + virtual void setVisibleRegionScreen(const Region& reg) = 0; + virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0; + }; + + /* + * Interface used to implement an iterator to a list + * of HWCLayer. + */ + class HWCLayer : public HWCLayerInterface { + friend class LayerListIterator; + // select the layer at the given index + virtual status_t setLayer(size_t index) = 0; + virtual HWCLayer* dup() = 0; + static HWCLayer* copy(HWCLayer *rhs) { + return rhs ? rhs->dup() : NULL; + } + protected: + virtual ~HWCLayer() { } + }; + + /* + * Iterator through a HWCLayer list. + * This behaves more or less like a forward iterator. + */ + class LayerListIterator { + friend struct HWComposer; + HWCLayer* const mLayerList; + size_t mIndex; + + LayerListIterator() : mLayerList(NULL), mIndex(0) { } + + LayerListIterator(HWCLayer* layer, size_t index) + : mLayerList(layer), mIndex(index) { } + + // we don't allow assignment, because we don't need it for now + LayerListIterator& operator = (const LayerListIterator& rhs); + + public: + // copy operators + LayerListIterator(const LayerListIterator& rhs) + : mLayerList(HWCLayer::copy(rhs.mLayerList)), mIndex(rhs.mIndex) { + } + + ~LayerListIterator() { delete mLayerList; } + + // pre-increment + LayerListIterator& operator++() { + mLayerList->setLayer(++mIndex); + return *this; + } + + // dereference + HWCLayerInterface& operator * () { return *mLayerList; } + HWCLayerInterface* operator -> () { return mLayerList; } + + // comparison + bool operator == (const LayerListIterator& rhs) const { + return mIndex == rhs.mIndex; + } + bool operator != (const LayerListIterator& rhs) const { + return !operator==(rhs); + } + }; + + // Returns an iterator to the beginning of the layer list + LayerListIterator begin(); + + // Returns an iterator to the end of the layer list + LayerListIterator end(); + + // Events handling --------------------------------------------------------- enum { @@ -111,18 +208,9 @@ public: const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const; private: + LayerListIterator getLayerIterator(size_t index); - struct callbacks : public hwc_procs_t { - // these are here to facilitate the transition when adding - // new callbacks (an implementation can check for NULL before - // calling a new callback). - void (*zero[4])(void); - }; - - struct cb_context { - callbacks procs; - HWComposer* hwc; - }; + struct cb_context; static void hook_invalidate(struct hwc_procs* procs); static void hook_vsync(struct hwc_procs* procs, int dpy, int64_t timestamp); @@ -132,14 +220,14 @@ private: sp<SurfaceFlinger> mFlinger; hw_module_t const* mModule; - hwc_composer_device_t* mHwc; - hwc_layer_list_t* mList; + struct hwc_composer_device* mHwc; + struct hwc_layer_list* mList; size_t mCapacity; mutable size_t mNumOVLayers; mutable size_t mNumFBLayers; - hwc_display_t mDpy; - hwc_surface_t mSur; - cb_context mCBContext; + EGLDisplay mDpy; + EGLSurface mSur; + cb_context* mCBContext; EventHandler& mEventHandler; nsecs_t mRefreshPeriod; size_t mVSyncCount; @@ -147,7 +235,6 @@ private: bool mDebugForceFakeVSync; }; - // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 4062340..890bcb4 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -259,16 +259,17 @@ Rect Layer::computeBufferCrop() const { return crop; } -void Layer::setGeometry(hwc_layer_t* hwcl) +void Layer::setGeometry(HWComposer::HWCLayerInterface& layer) { - LayerBaseClient::setGeometry(hwcl); + LayerBaseClient::setGeometry(layer); - hwcl->flags &= ~HWC_SKIP_LAYER; + // enable this layer + layer.setSkip(false); // we can't do alpha-fade with the hwc HAL const State& s(drawingState()); if (s.alpha < 0xFF) { - hwcl->flags = HWC_SKIP_LAYER; + layer.setSkip(true); } /* @@ -288,29 +289,18 @@ void Layer::setGeometry(hwc_layer_t* hwcl) // we can only handle simple transformation if (finalTransform & Transform::ROT_INVALID) { - hwcl->flags = HWC_SKIP_LAYER; + layer.setSkip(true); } else { - hwcl->transform = finalTransform; + layer.setTransform(finalTransform); } - - Rect crop = computeBufferCrop(); - hwcl->sourceCrop.left = crop.left; - hwcl->sourceCrop.top = crop.top; - hwcl->sourceCrop.right = crop.right; - hwcl->sourceCrop.bottom = crop.bottom; + layer.setCrop(computeBufferCrop()); } -void Layer::setPerFrameData(hwc_layer_t* hwcl) { +void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) { const sp<GraphicBuffer>& buffer(mActiveBuffer); - if (buffer == NULL) { - // this can happen if the client never drew into this layer yet, - // or if we ran out of memory. In that case, don't let - // HWC handle it. - hwcl->flags |= HWC_SKIP_LAYER; - hwcl->handle = NULL; - } else { - hwcl->handle = buffer->handle; - } + // NOTE: buffer can be NULL if the client never drew into this + // layer yet, or if we ran out of memory + layer.setBuffer(buffer); } void Layer::onDraw(const Region& clip) const diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 393599f..7a164aa 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -64,8 +64,8 @@ public: bool isFixedSize() const; // LayerBase interface - virtual void setGeometry(hwc_layer_t* hwcl); - virtual void setPerFrameData(hwc_layer_t* hwcl); + virtual void setGeometry(HWComposer::HWCLayerInterface& layer); + virtual void setPerFrameData(HWComposer::HWCLayerInterface& layer); virtual void onDraw(const Region& clip) const; virtual uint32_t doTransaction(uint32_t transactionFlags); virtual void lockPageFlip(bool& recomputeVisibleRegions); diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index 16bac8f..fe15dc9 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -281,48 +281,34 @@ void LayerBase::unlockPageFlip( const Transform& planeTransform, Region& outDirtyRegion) { } -void LayerBase::setGeometry(hwc_layer_t* hwcl) +void LayerBase::setGeometry(HWComposer::HWCLayerInterface& layer) { - hwcl->compositionType = HWC_FRAMEBUFFER; - hwcl->hints = 0; - hwcl->flags = HWC_SKIP_LAYER; - hwcl->transform = 0; - hwcl->blending = HWC_BLENDING_NONE; + layer.setDefaultState(); // this gives us only the "orientation" component of the transform const State& s(drawingState()); const uint32_t finalTransform = s.transform.getOrientation(); // we can only handle simple transformation if (finalTransform & Transform::ROT_INVALID) { - hwcl->flags = HWC_SKIP_LAYER; + layer.setTransform(0); } else { - hwcl->transform = finalTransform; + layer.setTransform(finalTransform); } if (!isOpaque()) { - hwcl->blending = mPremultipliedAlpha ? - HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE; + layer.setBlending(mPremultipliedAlpha ? + HWC_BLENDING_PREMULT : + HWC_BLENDING_COVERAGE); } // scaling is already applied in mTransformedBounds - hwcl->displayFrame.left = mTransformedBounds.left; - hwcl->displayFrame.top = mTransformedBounds.top; - hwcl->displayFrame.right = mTransformedBounds.right; - hwcl->displayFrame.bottom = mTransformedBounds.bottom; - hwcl->visibleRegionScreen.rects = - reinterpret_cast<hwc_rect_t const *>( - visibleRegionScreen.getArray( - &hwcl->visibleRegionScreen.numRects)); - - hwcl->sourceCrop.left = 0; - hwcl->sourceCrop.top = 0; - hwcl->sourceCrop.right = mTransformedBounds.width(); - hwcl->sourceCrop.bottom = mTransformedBounds.height(); -} - -void LayerBase::setPerFrameData(hwc_layer_t* hwcl) { - hwcl->compositionType = HWC_FRAMEBUFFER; - hwcl->handle = NULL; + layer.setFrame(mTransformedBounds); + layer.setVisibleRegionScreen(visibleRegionScreen); + layer.setCrop(mTransformedBounds.getBounds()); +} + +void LayerBase::setPerFrameData(HWComposer::HWCLayerInterface& layer) { + layer.setBuffer(0); } void LayerBase::setFiltering(bool filtering) diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index c547a40..4d5d1e4 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -32,8 +32,6 @@ #include <private/gui/LayerState.h> -#include <hardware/hwcomposer.h> - #include "DisplayHardware/DisplayHardware.h" #include "Transform.h" @@ -116,8 +114,8 @@ public: virtual const char* getTypeId() const { return "LayerBase"; } - virtual void setGeometry(hwc_layer_t* hwcl); - virtual void setPerFrameData(hwc_layer_t* hwcl); + virtual void setGeometry(HWComposer::HWCLayerInterface& layer); + virtual void setPerFrameData(HWComposer::HWCLayerInterface& layer); /** diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 61b5f71..e2c7aed 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -800,12 +800,13 @@ void SurfaceFlinger::handleWorkList() const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ); const size_t count = currentLayers.size(); hwc.createWorkList(count); - hwc_layer_t* const cur(hwc.getLayers()); - for (size_t i=0 ; cur && i<count ; i++) { - currentLayers[i]->setGeometry(&cur[i]); + + HWComposer::LayerListIterator cur = hwc.begin(); + const HWComposer::LayerListIterator end = hwc.end(); + for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) { + currentLayers[i]->setGeometry(*cur); if (mDebugDisableHWC || mDebugRegion) { - cur[i].compositionType = HWC_FRAMEBUFFER; - cur[i].flags |= HWC_SKIP_LAYER; + cur->setSkip(true); } } } @@ -859,8 +860,10 @@ void SurfaceFlinger::setupHardwareComposer() { const DisplayHardware& hw(graphicPlane(0).displayHardware()); HWComposer& hwc(hw.getHwComposer()); - hwc_layer_t* const cur(hwc.getLayers()); - if (!cur) { + + HWComposer::LayerListIterator cur = hwc.begin(); + const HWComposer::LayerListIterator end = hwc.end(); + if (cur == end) { return; } @@ -880,9 +883,9 @@ void SurfaceFlinger::setupHardwareComposer() * update the per-frame h/w composer data for each layer * and build the transparent region of the FB */ - for (size_t i=0 ; i<count ; i++) { + for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) { const sp<LayerBase>& layer(layers[i]); - layer->setPerFrameData(&cur[i]); + layer->setPerFrameData(*cur); } status_t err = hwc.prepare(); ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err)); @@ -892,10 +895,11 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) { const DisplayHardware& hw(graphicPlane(0).displayHardware()); HWComposer& hwc(hw.getHwComposer()); - hwc_layer_t* const cur(hwc.getLayers()); + HWComposer::LayerListIterator cur = hwc.begin(); + const HWComposer::LayerListIterator end = hwc.end(); const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER); - if (!cur || fbLayerCount) { + if (cur==end || fbLayerCount) { // Never touch the framebuffer if we don't have any framebuffer layers if (hwc.getLayerCount(HWC_OVERLAY)) { @@ -920,13 +924,12 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); const size_t count = layers.size(); - - for (size_t i=0 ; i<count ; i++) { + for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) { const sp<LayerBase>& layer(layers[i]); const Region clip(dirty.intersect(layer->visibleRegionScreen)); if (!clip.isEmpty()) { - if (cur && (cur[i].compositionType == HWC_OVERLAY)) { - if (i && (cur[i].hints & HWC_HINT_CLEAR_FB) + if (cur->getCompositionType() == HWC_OVERLAY) { + if (i && (cur->getHints() & HWC_HINT_CLEAR_FB) && layer->isOpaque()) { // never clear the very first layer since we're // guaranteed the FB is already cleared |