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
This commit is contained in:
Mathias Agopian 2012-05-13 20:42:01 -07:00 committed by Jesse Hall
parent fe6102f07c
commit 3e8b853d67
7 changed files with 284 additions and 98 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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();
layer.setFrame(mTransformedBounds);
layer.setVisibleRegionScreen(visibleRegionScreen);
layer.setCrop(mTransformedBounds.getBounds());
}
void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
hwcl->compositionType = HWC_FRAMEBUFFER;
hwcl->handle = NULL;
void LayerBase::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
layer.setBuffer(0);
}
void LayerBase::setFiltering(bool filtering)

View File

@ -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);
/**

View File

@ -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