summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.h3
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp32
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h5
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp96
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h2
5 files changed, 90 insertions, 48 deletions
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index 40a6f1e..f02c954 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -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;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index daefd5e..e707bdc 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -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) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 8758a80..aa8ebe1 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -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;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1703448..0ef03bb 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -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) {
- 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.
+ // 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.
- 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) &&
- !(cur[i].flags & HWC_SKIP_LAYER);
+ Region transparent;
- 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);
+ 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);
}
- 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]);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a8036a6..d7f005f 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -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();