Merge "fix transition from full overlays to fb"

This commit is contained in:
Mathias Agopian
2011-09-20 17:55:24 -07:00
committed by Android (Google) Code Review
5 changed files with 90 additions and 48 deletions

View File

@@ -84,9 +84,10 @@ public:
status_t compositionComplete() const;
Rect bounds() const {
Rect getBounds() const {
return Rect(mWidth, mHeight);
}
inline Rect bounds() const { return getBounds(); }
// only for debugging
int getCurrentBufferIndex() const;

View File

@@ -40,6 +40,7 @@ namespace android {
HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger)
: mFlinger(flinger),
mModule(0), mHwc(0), mList(0), mCapacity(0),
mNumOVLayers(0), mNumFBLayers(0),
mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE)
{
int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
@@ -98,9 +99,40 @@ status_t HWComposer::createWorkList(size_t numLayers) {
status_t HWComposer::prepare() const {
int err = mHwc->prepare(mHwc, mList);
if (err == NO_ERROR) {
size_t numOVLayers = 0;
size_t numFBLayers = 0;
size_t count = mList->numHwLayers;
for (size_t i=0 ; i<count ; i++) {
hwc_layer& l(mList->hwLayers[i]);
if (l.flags & HWC_SKIP_LAYER) {
l.compositionType = HWC_FRAMEBUFFER;
}
switch (l.compositionType) {
case HWC_OVERLAY:
numOVLayers++;
break;
case HWC_FRAMEBUFFER:
numFBLayers++;
break;
}
}
mNumOVLayers = numOVLayers;
mNumFBLayers = numFBLayers;
}
return (status_t)err;
}
size_t HWComposer::getLayerCount(int type) const {
switch (type) {
case HWC_OVERLAY:
return mNumOVLayers;
case HWC_FRAMEBUFFER:
return mNumFBLayers;
}
return 0;
}
status_t HWComposer::commit() const {
int err = mHwc->set(mHwc, mDpy, mSur, mList);
if (mList) {

View File

@@ -64,6 +64,9 @@ public:
size_t getNumLayers() const;
hwc_layer_t* getLayers() const;
// updated in preapre()
size_t getLayerCount(int type) const;
// for debugging
void dump(String8& out, char* scratch, size_t SIZE,
const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const;
@@ -81,6 +84,8 @@ private:
hwc_composer_device_t* mHwc;
hwc_layer_list_t* mList;
size_t mCapacity;
mutable size_t mNumOVLayers;
mutable size_t mNumFBLayers;
hwc_display_t mDpy;
hwc_surface_t mSur;
cb_context mCBContext;

View File

@@ -876,24 +876,21 @@ void SurfaceFlinger::handleRepaint()
}
}
Region expandDirty = setupHardwareComposer(mDirtyRegion);
mDirtyRegion.orSelf(expandDirty);
mSwapRegion.orSelf(mDirtyRegion);
setupHardwareComposer(mDirtyRegion);
composeSurfaces(mDirtyRegion);
// clear the dirty regions
// update the swap region and clear the dirty region
mSwapRegion.orSelf(mDirtyRegion);
mDirtyRegion.clear();
}
Region SurfaceFlinger::setupHardwareComposer(const Region& dirty)
void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut)
{
Region dirtyOut(dirty);
const DisplayHardware& hw(graphicPlane(0).displayHardware());
HWComposer& hwc(hw.getHwComposer());
hwc_layer_t* const cur(hwc.getLayers());
if (!cur) {
return dirtyOut;
return;
}
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
@@ -916,53 +913,62 @@ Region SurfaceFlinger::setupHardwareComposer(const Region& dirty)
const sp<LayerBase>& layer(layers[i]);
layer->setPerFrameData(&cur[i]);
}
const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);
status_t err = hwc.prepare();
LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
if (err == NO_ERROR) {
// what's happening here is tricky.
// we want to clear all the layers with the CLEAR_FB flags
// that are opaque.
// however, since some GPU are efficient at preserving
// the backbuffer, we want to take advantage of that so we do the
// clear only in the dirty region (other areas will be preserved
// on those GPUs).
// NOTE: on non backbuffer preserving GPU, the dirty region
// has already been expanded as needed, so the code is correct
// there too.
//
// However, the content of the framebuffer cannot be trusted when
// we switch to/from FB/OVERLAY, in which case we need to
// expand the dirty region to those areas too.
//
// Note also that there is a special case when switching from
// "no layers in FB" to "some layers in FB", where we need to redraw
// the entire FB, since some areas might contain uninitialized
// data.
//
// Also we want to make sure to not clear areas that belong to
// layers above that won't redraw (we would just erasing them),
// that is, we can't erase anything outside the dirty region.
Region transparent;
for (size_t i=0 ; i<count ; i++) {
// what's happening here is tricky.
// we want to clear all the layers with the CLEAR_FB flags
// that are opaque.
// however, since some GPU are efficient at preserving
// the backbuffer, we want to take advantage of that so we do the
// clear only in the dirty region (other areas will be preserved
// on those GPUs).
// NOTE: on non backbuffer preserving GPU, the dirty region
// has already been expanded as needed, so the code is correct
// there too.
// However, the content of the framebuffer cannot be trusted when
// we switch to/from FB/OVERLAY, in which case we need to
// expand the dirty region to those areas too.
//
// Also we want to make sure to not clear areas that belong to
// layers above that won't redraw (we would just erasing them),
// that is, we can't erase anything outside the dirty region.
const sp<LayerBase>& layer(layers[i]);
if ((cur[i].hints & HWC_HINT_CLEAR_FB) && layer->isOpaque()) {
transparent.orSelf(layer->visibleRegionScreen);
if (!fbLayerCount && hwc.getLayerCount(HWC_FRAMEBUFFER)) {
transparent.set(hw.getBounds());
dirtyInOut = transparent;
} else {
for (size_t i=0 ; i<count ; i++) {
const sp<LayerBase>& layer(layers[i]);
if ((cur[i].hints & HWC_HINT_CLEAR_FB) && layer->isOpaque()) {
transparent.orSelf(layer->visibleRegionScreen);
}
bool isOverlay = (cur[i].compositionType != HWC_FRAMEBUFFER);
if (isOverlay != layer->isOverlay()) {
// we transitioned to/from overlay, so add this layer
// to the dirty region so the framebuffer can be either
// cleared or redrawn.
dirtyInOut.orSelf(layer->visibleRegionScreen);
}
layer->setOverlay(isOverlay);
}
bool isOverlay = (cur[i].compositionType != HWC_FRAMEBUFFER) &&
!(cur[i].flags & HWC_SKIP_LAYER);
if (isOverlay != layer->isOverlay()) {
// we transitioned to/from overlay, so add this layer
// to the dirty region so the framebuffer can be either
// cleared or redrawn.
dirtyOut.orSelf(layer->visibleRegionScreen);
}
layer->setOverlay(isOverlay);
// don't erase stuff outside the dirty region
transparent.andSelf(dirtyInOut);
}
/*
* clear the area of the FB that need to be transparent
*/
// don't erase stuff outside the dirty region
transparent.andSelf(dirtyOut);
if (!transparent.isEmpty()) {
glClearColor(0,0,0,0);
Region::const_iterator it = transparent.begin();
@@ -976,7 +982,6 @@ Region SurfaceFlinger::setupHardwareComposer(const Region& dirty)
}
}
}
return dirtyOut;
}
void SurfaceFlinger::composeSurfaces(const Region& dirty)
@@ -997,8 +1002,7 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER) &&
!(cur[i].flags & HWC_SKIP_LAYER)) {
if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER)) {
continue;
}
const sp<LayerBase>& layer(layers[i]);

View File

@@ -277,7 +277,7 @@ private:
void handleWorkList();
void handleRepaint();
void postFramebuffer();
Region setupHardwareComposer(const Region& dirty);
void setupHardwareComposer(Region& dirtyInOut);
void composeSurfaces(const Region& dirty);
void repaintEverything();