refactor HWComposer to break dependency with the HAL headers
HWComposer must abstract the HWC HAL entirely, so that the
HAL can continue to evolve (and break binary compatibility)
without breaking SurfaceFlinger. The HWC data structure had
leaked outside of HWComposer, this is now fixed.
We now have an abstract interface that provide all the
needed functionality, HWCompose provides concrete
implementations of it based on the the HWC version.
Change-Id: I40c4676dc986b682ede5520a1c60efe64037b0bb
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 @@
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 @@
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 @@
if (mHwc) {
hwc_close(mHwc);
}
+ delete mCBContext;
}
status_t HWComposer::initCheck() const {
@@ -230,10 +245,117 @@
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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
bool mDebugForceFakeVSync;
};
-
// ---------------------------------------------------------------------------
}; // namespace android