Merge "fix transition from full overlays to fb"
This commit is contained in:
committed by
Android (Google) Code Review
commit
a1d2790747
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user