Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3e8b853d authored by Mathias Agopian's avatar Mathias Agopian Committed by Jesse Hall
Browse files

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
parent fe6102f0
Loading
Loading
Loading
Loading
+129 −7
Original line number Diff line number Diff line
@@ -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,9 +245,116 @@ 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 {
+109 −22
Original line number Diff line number Diff line
@@ -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

+12 −22
Original line number Diff line number Diff line
@@ -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
+2 −2
Original line number Diff line number Diff line
@@ -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);
+14 −28
Original line number Diff line number Diff line
@@ -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)
Loading