summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp21
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h8
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp82
3 files changed, 62 insertions, 49 deletions
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 8ca880b..0291d78 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -34,7 +34,7 @@ namespace android {
// ---------------------------------------------------------------------------
HWComposer::HWComposer()
- : mModule(0), mHwc(0), mList(0),
+ : mModule(0), mHwc(0), mList(0), mCapacity(0),
mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE)
{
int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
@@ -63,10 +63,13 @@ void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) {
}
status_t HWComposer::createWorkList(size_t numLayers) {
- if (mHwc && (!mList || mList->numHwLayers < numLayers)) {
- free(mList);
- size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t);
- mList = (hwc_layer_list_t*)malloc(size);
+ if (mHwc) {
+ if (!mList || mCapacity < numLayers) {
+ free(mList);
+ size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t);
+ mList = (hwc_layer_list_t*)malloc(size);
+ mCapacity = numLayers;
+ }
mList->flags = HWC_GEOMETRY_CHANGED;
mList->numHwLayers = numLayers;
}
@@ -84,12 +87,12 @@ status_t HWComposer::commit() const {
return (status_t)err;
}
-HWComposer::iterator HWComposer::begin() {
- return mList ? &(mList->hwLayers[0]) : NULL;
+size_t HWComposer::getNumLayers() const {
+ return mList ? mList->numHwLayers : 0;
}
-HWComposer::iterator HWComposer::end() {
- return mList ? &(mList->hwLayers[mList->numHwLayers]) : NULL;
+hwc_layer_t* HWComposer::getLayers() const {
+ return mList ? mList->hwLayers : 0;
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 729f23b..c5d5c2b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -49,16 +49,14 @@ public:
status_t commit() const;
- typedef hwc_layer_t const * const_iterator;
- typedef hwc_layer_t* iterator;
-
- iterator begin();
- iterator end();
+ size_t getNumLayers() const;
+ hwc_layer_t* getLayers() const;
private:
hw_module_t const* mModule;
hwc_composer_device_t* mHwc;
hwc_layer_list_t* mList;
+ size_t mCapacity;
hwc_display_t mDpy;
hwc_surface_t mSur;
};
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 47bb4c1..006bb10 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -755,10 +755,9 @@ void SurfaceFlinger::handleWorkList()
const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
const size_t count = currentLayers.size();
hwc.createWorkList(count);
- HWComposer::iterator cur(hwc.begin());
- HWComposer::iterator last(hwc.end());
- for (size_t i=0 ; (i<count) && (cur!=last) ; ++i, ++cur) {
- currentLayers[i]->setGeometry(cur);
+ hwc_layer_t* const cur(hwc.getLayers());
+ for (size_t i=0 ; cur && i<count ; i++) {
+ currentLayers[i]->setGeometry(&cur[i]);
}
}
}
@@ -829,47 +828,41 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
status_t err = NO_ERROR;
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
- const size_t count = layers.size();
+ size_t count = layers.size();
const DisplayHardware& hw(graphicPlane(0).displayHardware());
HWComposer& hwc(hw.getHwComposer());
- HWComposer::iterator cur(hwc.begin());
- HWComposer::iterator last(hwc.end());
+ hwc_layer_t* const cur(hwc.getLayers());
- // update the per-frame h/w composer data for each layer
- if (cur != last) {
- for (size_t i=0 ; i<count && cur!=last ; ++i, ++cur) {
- layers[i]->setPerFrameData(cur);
- }
- err = hwc.prepare();
- LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
- }
+ LOGE_IF(cur && hwc.getNumLayers() != count,
+ "HAL number of layers (%d) doesn't match surfaceflinger (%d)",
+ hwc.getNumLayers(), count);
- // and then, render the layers targeted at the framebuffer
- Region transparent(hw.bounds());
- for (size_t i=0 ; i<count ; ++i) {
+ // just to be extra-safe, use the smallest count
+ count = count < hwc.getNumLayers() ? count : hwc.getNumLayers();
- // see if we need to skip this layer
- if (!err && cur != last) {
- if (!((cur->compositionType == HWC_FRAMEBUFFER) ||
- (cur->flags & HWC_SKIP_LAYER))) {
- ++cur;
- continue;
+ /*
+ * update the per-frame h/w composer data for each layer
+ * and build the transparent region of the FB
+ */
+ Region transparent;
+ if (cur) {
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<LayerBase>& layer(layers[i]);
+ layer->setPerFrameData(&cur[i]);
+ if (cur[i].hints & HWC_HINT_CLEAR_FB) {
+ if (!(layer->needsBlending())) {
+ transparent.orSelf(layer->visibleRegionScreen);
+ }
}
- ++cur;
- }
-
- // draw the layer into the framebuffer
- const sp<LayerBase>& layer(layers[i]);
- transparent.subtractSelf(layer->visibleRegionScreen);
- const Region clip(dirty.intersect(layer->visibleRegionScreen));
- if (!clip.isEmpty()) {
- layer->draw(clip);
}
+ err = hwc.prepare();
+ LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
}
- // finally clear everything we didn't draw as a result of calling
- // prepare (this leaves the FB transparent).
+ /*
+ * clear the area of the FB that need to be transparent
+ */
transparent.andSelf(dirty);
if (!transparent.isEmpty()) {
glClearColor(0,0,0,0);
@@ -883,6 +876,25 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
glClear(GL_COLOR_BUFFER_BIT);
}
}
+
+
+ /*
+ * and then, render the layers targeted at the framebuffer
+ */
+ for (size_t i=0 ; i<count ; i++) {
+ if (cur) {
+ if (!(cur[i].compositionType == HWC_FRAMEBUFFER) ||
+ cur[i].flags & HWC_SKIP_LAYER) {
+ // skip layers handled by the HAL
+ continue;
+ }
+ }
+ const sp<LayerBase>& layer(layers[i]);
+ const Region clip(dirty.intersect(layer->visibleRegionScreen));
+ if (!clip.isEmpty()) {
+ layer->draw(clip);
+ }
+ }
}
void SurfaceFlinger::unlockClients()