diff options
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.cpp | 21 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.h | 8 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 82 |
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() |