From 45721773e1a68e96da4b6cc04cef276bae7ca3e9 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 12 Aug 2010 15:03:26 -0700 Subject: [PATCH] Fix a couple issues with the new hwcomposer HAL - we now clear the framebuffer upon request from the HAL - the HAL list size could get out of sync with reality - there was also an issue where sometime we could run past the list Change-Id: Ic3a34314aed24181f2d8cc787096af83c046ef27 --- .../DisplayHardware/HWComposer.cpp | 21 +++-- .../DisplayHardware/HWComposer.h | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 84 +++++++++++-------- 3 files changed, 63 insertions(+), 50 deletions(-) diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 8ca880b09..0291d7894 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 729f23bbe..c5d5c2b7f 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 47bb4c1b1..006bb1076 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -755,10 +755,9 @@ void SurfaceFlinger::handleWorkList() const Vector< sp >& 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 ; (isetGeometry(cur); + hwc_layer_t* const cur(hwc.getLayers()); + for (size_t i=0 ; cur && isetGeometry(&cur[i]); } } } @@ -829,47 +828,41 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) status_t err = NO_ERROR; const Vector< sp >& 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 ; isetPerFrameData(cur); + LOGE_IF(cur && hwc.getNumLayers() != count, + "HAL number of layers (%d) doesn't match surfaceflinger (%d)", + hwc.getNumLayers(), count); + + // just to be extra-safe, use the smallest count + count = count < hwc.getNumLayers() ? count : hwc.getNumLayers(); + + /* + * 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& layer(layers[i]); + layer->setPerFrameData(&cur[i]); + if (cur[i].hints & HWC_HINT_CLEAR_FB) { + if (!(layer->needsBlending())) { + transparent.orSelf(layer->visibleRegionScreen); + } + } } err = hwc.prepare(); LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err)); } - // and then, render the layers targeted at the framebuffer - Region transparent(hw.bounds()); - for (size_t i=0 ; icompositionType == HWC_FRAMEBUFFER) || - (cur->flags & HWC_SKIP_LAYER))) { - ++cur; - continue; - } - ++cur; - } - - // draw the layer into the framebuffer - const sp& layer(layers[i]); - transparent.subtractSelf(layer->visibleRegionScreen); - const Region clip(dirty.intersect(layer->visibleRegionScreen)); - if (!clip.isEmpty()) { - layer->draw(clip); - } - } - - // 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& layer(layers[i]); + const Region clip(dirty.intersect(layer->visibleRegionScreen)); + if (!clip.isEmpty()) { + layer->draw(clip); + } + } } void SurfaceFlinger::unlockClients()