am e7d20eb0: Merge "SurfaceFlinger: Pass surface damage to HWC"

* commit 'e7d20eb000c1d342c8f5f58011023c0eb7cea6d5':
  SurfaceFlinger: Pass surface damage to HWC
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 77a9a19..c8b36ec 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -1020,6 +1020,21 @@
         SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects);
         visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
     }
+    virtual void setSurfaceDamage(const Region& reg) {
+        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
+            return;
+        }
+        hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
+        // We encode default full-screen damage as INVALID_RECT upstream, but as
+        // 0 rects for HWComposer
+        if (reg.isRect() && reg.getBounds() == Rect::INVALID_RECT) {
+            surfaceDamage.numRects = 0;
+            surfaceDamage.rects = NULL;
+            return;
+        }
+        SharedBuffer const* sb = reg.getSharedBuffer(&surfaceDamage.numRects);
+        surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
+    }
     virtual void setSidebandStream(const sp<NativeHandle>& stream) {
         ALOG_ASSERT(stream->handle() != NULL);
         getLayer()->compositionType = HWC_SIDEBAND;
@@ -1050,6 +1065,18 @@
         }
 
         getLayer()->acquireFenceFd = -1;
+
+        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
+            return;
+        }
+
+        hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
+        sb = SharedBuffer::bufferFromData(surfaceDamage.rects);
+        if (sb) {
+            sb->release();
+            surfaceDamage.numRects = 0;
+            surfaceDamage.rects = NULL;
+        }
     }
 };
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index a62ac5c..28d8c65 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -168,6 +168,7 @@
         virtual void setFrame(const Rect& frame) = 0;
         virtual void setCrop(const FloatRect& crop) = 0;
         virtual void setVisibleRegionScreen(const Region& reg) = 0;
+        virtual void setSurfaceDamage(const Region& reg) = 0;
         virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
         virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
         virtual void setAcquireFenceFd(int fenceFd) = 0;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2ac4765..7bb7529 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -513,6 +513,16 @@
     Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
     layer.setVisibleRegionScreen(visible);
 
+    // Pass full-surface damage down untouched
+    if (surfaceDamageRegion.isRect() &&
+            surfaceDamageRegion.getBounds() == Rect::INVALID_RECT) {
+        layer.setSurfaceDamage(surfaceDamageRegion);
+    } else {
+        Region surfaceDamage =
+            tr.transform(surfaceDamageRegion.intersect(hw->getViewport()));
+        layer.setSurfaceDamage(surfaceDamage);
+    }
+
     if (mSidebandStream.get()) {
         layer.setSidebandStream(mSidebandStream);
     } else {
@@ -1034,6 +1044,18 @@
     return true;
 }
 
+void Layer::useSurfaceDamage() {
+    if (mFlinger->mForceFullDamage) {
+        surfaceDamageRegion = Region::INVALID_REGION;
+    } else {
+        surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage();
+    }
+}
+
+void Layer::useEmptyDamage() {
+    surfaceDamageRegion.clear();
+}
+
 // ----------------------------------------------------------------------------
 // pageflip handling...
 // ----------------------------------------------------------------------------
@@ -1349,6 +1371,7 @@
 
     s.activeTransparentRegion.dump(result, "transparentRegion");
     visibleRegion.dump(result, "visibleRegion");
+    surfaceDamageRegion.dump(result, "surfaceDamageRegion");
     sp<Client> client(mClientRef.promote());
 
     result.appendFormat(            "      "
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 424c03e..46c17e5 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -76,6 +76,7 @@
     Region visibleRegion;
     Region coveredRegion;
     Region visibleNonTransparentRegion;
+    Region surfaceDamageRegion;
 
     // Layer serial number.  This gives layers an explicit ordering, so we
     // have a stable sort order when their layer stack and Z-order are
@@ -137,6 +138,12 @@
     bool setCrop(const Rect& crop);
     bool setLayerStack(uint32_t layerStack);
 
+    // If we have received a new buffer this frame, we will pass its surface
+    // damage down to hardware composer. Otherwise, we must send a region with
+    // one empty rect.
+    void useSurfaceDamage();
+    void useEmptyDamage();
+
     uint32_t getTransactionFlags(uint32_t flags);
     uint32_t setTransactionFlags(uint32_t flags);
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9dc140e..f967c9d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -145,6 +145,7 @@
         mDebugInTransaction(0),
         mLastTransactionTime(0),
         mBootFinished(false),
+        mForceFullDamage(false),
         mPrimaryHWVsyncEnabled(false),
         mHWVsyncAvailable(false),
         mDaltonize(false),
@@ -1725,12 +1726,17 @@
             frameQueued = true;
             if (layer->shouldPresentNow(mPrimaryDispSync)) {
                 layersWithQueuedFrames.push_back(layer.get());
+            } else {
+                layer->useEmptyDamage();
             }
+        } else {
+            layer->useEmptyDamage();
         }
     }
     for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
         Layer* layer = layersWithQueuedFrames[i];
         const Region dirty(layer->latchBuffer(visibleRegions));
+        layer->useSurfaceDamage();
         const Layer::State& s(layer->getDrawingState());
         invalidateLayerStack(s.layerStack, dirty);
     }
@@ -2876,6 +2882,11 @@
                 mPrimaryDispSync.setRefreshSkipCount(n);
                 return NO_ERROR;
             }
+            case 1017: {
+                n = data.readInt32();
+                mForceFullDamage = static_cast<bool>(n);
+                return NO_ERROR;
+            }
         }
     }
     return err;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4deb815..a06d1be 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -469,6 +469,7 @@
     volatile nsecs_t mDebugInTransaction;
     nsecs_t mLastTransactionTime;
     bool mBootFinished;
+    bool mForceFullDamage;
 
     // these are thread safe
     mutable MessageQueue mEventQueue;
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index abf3993..19c497a 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -108,6 +108,7 @@
     status_t result = GLConsumer::acquireBufferLocked(item, presentWhen);
     if (result == NO_ERROR) {
         mTransformToDisplayInverse = item->mTransformToDisplayInverse;
+        mSurfaceDamage = item->mSurfaceDamage;
     }
     return result;
 }
@@ -116,6 +117,10 @@
     return mTransformToDisplayInverse;
 }
 
+const Region& SurfaceFlingerConsumer::getSurfaceDamage() const {
+    return mSurfaceDamage;
+}
+
 sp<NativeHandle> SurfaceFlingerConsumer::getSidebandStream() const {
     return mConsumer->getSidebandStream();
 }
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index d1cf9b9..1aaba18 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -35,7 +35,7 @@
     SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
             uint32_t tex)
         : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false),
-          mTransformToDisplayInverse(false)
+          mTransformToDisplayInverse(false), mSurfaceDamage()
     {}
 
     class BufferRejecter {
@@ -60,6 +60,7 @@
 
     // must be called from SF main thread
     bool getTransformToDisplayInverse() const;
+    const Region& getSurfaceDamage() const;
 
     // Sets the contents changed listener. This should be used instead of
     // ConsumerBase::setFrameAvailableListener().
@@ -78,6 +79,9 @@
     // it is displayed onto. This is applied after GLConsumer::mCurrentTransform.
     // This must be set/read from SurfaceFlinger's main thread.
     bool mTransformToDisplayInverse;
+
+    // The portion of this surface that has changed since the previous frame
+    Region mSurfaceDamage;
 };
 
 // ----------------------------------------------------------------------------