Merge "Initialize new HWC 1.2 fields" into jb-mr1-dev
diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h
index 421bdda..8c190dd 100644
--- a/include/private/ui/RegionHelper.h
+++ b/include/private/ui/RegionHelper.h
@@ -26,10 +26,10 @@
 template<typename RECT>
 class region_operator
 {
+public:
     typedef typename RECT::value_type TYPE;    
     static const TYPE max_value = 0x7FFFFFF;
 
-public:
     /* 
      * Common boolean operations:
      * value is computed as 0b101 op 0b110
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 0049fde..43a4450 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -161,7 +161,8 @@
     static void translate(Region& reg, int dx, int dy);
     static void translate(Region& dst, const Region& reg, int dx, int dy);
 
-    static bool validate(const Region& reg, const char* name);
+    static bool validate(const Region& reg,
+            const char* name, bool silent = false);
     
     // mStorage is a (manually) sorted array of Rects describing the region
     // with an extra Rect as the last element which is set to the
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 94fb1d5..932ef68 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -20,6 +20,7 @@
 
 #include <utils/Log.h>
 #include <utils/String8.h>
+#include <utils/CallStack.h>
 
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -113,10 +114,6 @@
     Rect rect(l,t,r,b);
     size_t where = mStorage.size() - 1;
     mStorage.insertAt(rect, where, 1);
-
-#if VALIDATE_REGIONS
-    validate(*this, "addRectUnchecked");
-#endif
 }
 
 // ----------------------------------------------------------------------------
@@ -338,47 +335,72 @@
     }
 };
 
-bool Region::validate(const Region& reg, const char* name)
+bool Region::validate(const Region& reg, const char* name, bool silent)
 {
     bool result = true;
     const_iterator cur = reg.begin();
     const_iterator const tail = reg.end();
-    const_iterator prev = cur++;
+    const_iterator prev = cur;
     Rect b(*prev);
     while (cur != tail) {
-        b.left   = b.left   < cur->left   ? b.left   : cur->left;
-        b.top    = b.top    < cur->top    ? b.top    : cur->top;
-        b.right  = b.right  > cur->right  ? b.right  : cur->right;
-        b.bottom = b.bottom > cur->bottom ? b.bottom : cur->bottom;
-        if (cur->top == prev->top) {
-            if (cur->bottom != prev->bottom) {
-                ALOGE("%s: invalid span %p", name, cur);
+        if (cur->isValid() == false) {
+            ALOGE_IF(!silent, "%s: region contains an invalid Rect", name);
+            result = false;
+        }
+        if (cur->right > region_operator<Rect>::max_value) {
+            ALOGE_IF(!silent, "%s: rect->right > max_value", name);
+            result = false;
+        }
+        if (cur->bottom > region_operator<Rect>::max_value) {
+            ALOGE_IF(!silent, "%s: rect->right > max_value", name);
+            result = false;
+        }
+        if (prev != cur) {
+            b.left   = b.left   < cur->left   ? b.left   : cur->left;
+            b.top    = b.top    < cur->top    ? b.top    : cur->top;
+            b.right  = b.right  > cur->right  ? b.right  : cur->right;
+            b.bottom = b.bottom > cur->bottom ? b.bottom : cur->bottom;
+            if ((*prev < *cur) == false) {
+                ALOGE_IF(!silent, "%s: region's Rects not sorted", name);
                 result = false;
-            } else if (cur->left < prev->right) {
-                ALOGE("%s: spans overlap horizontally prev=%p, cur=%p",
+            }
+            if (cur->top == prev->top) {
+                if (cur->bottom != prev->bottom) {
+                    ALOGE_IF(!silent, "%s: invalid span %p", name, cur);
+                    result = false;
+                } else if (cur->left < prev->right) {
+                    ALOGE_IF(!silent,
+                            "%s: spans overlap horizontally prev=%p, cur=%p",
+                            name, prev, cur);
+                    result = false;
+                }
+            } else if (cur->top < prev->bottom) {
+                ALOGE_IF(!silent,
+                        "%s: spans overlap vertically prev=%p, cur=%p",
                         name, prev, cur);
                 result = false;
             }
-        } else if (cur->top < prev->bottom) {
-            ALOGE("%s: spans overlap vertically prev=%p, cur=%p",
-                    name, prev, cur);
-            result = false;
+            prev = cur;
         }
-        prev = cur;
         cur++;
     }
     if (b != reg.getBounds()) {
         result = false;
-        ALOGE("%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name,
+        ALOGE_IF(!silent,
+                "%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name,
                 b.left, b.top, b.right, b.bottom,
                 reg.getBounds().left, reg.getBounds().top, 
                 reg.getBounds().right, reg.getBounds().bottom);
     }
     if (reg.mStorage.size() == 2) {
-        ALOGE("mStorage size is 2, which is never valid");
+        result = false;
+        ALOGE_IF(!silent, "%s: mStorage size is 2, which is never valid", name);
     }
-    if (result == false) {
+    if (result == false && !silent) {
         reg.dump(name);
+        CallStack stack;
+        stack.update();
+        stack.dump("");
     }
     return result;
 }
@@ -564,27 +586,37 @@
 }
 
 status_t Region::flatten(void* buffer) const {
+#if VALIDATE_REGIONS
+    validate(*this, "Region::flatten");
+#endif
     Rect* rects = reinterpret_cast<Rect*>(buffer);
     memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect));
     return NO_ERROR;
 }
 
 status_t Region::unflatten(void const* buffer, size_t size) {
-    mStorage.clear();
+    Region result;
     if (size >= sizeof(Rect)) {
         Rect const* rects = reinterpret_cast<Rect const*>(buffer);
         size_t count = size / sizeof(Rect);
         if (count > 0) {
-            ssize_t err = mStorage.insertAt(0, count);
+            result.mStorage.clear();
+            ssize_t err = result.mStorage.insertAt(0, count);
             if (err < 0) {
                 return status_t(err);
             }
-            memcpy(mStorage.editArray(), rects, count*sizeof(Rect));
+            memcpy(result.mStorage.editArray(), rects, count*sizeof(Rect));
         }
     }
 #if VALIDATE_REGIONS
-    validate(*this, "Region::unflatten");
+    validate(result, "Region::unflatten");
 #endif
+
+    if (!result.validate(result, "Region::unflatten", true)) {
+        ALOGE("Region::unflatten() failed, invalid region");
+        return BAD_VALUE;
+    }
+    mStorage = result.mStorage;
     return NO_ERROR;
 }
 
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index eea79f8..31bfcd7 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -57,6 +57,10 @@
   LOCAL_CFLAGS += -DMAX_EGL_CACHE_ENTRY_SIZE=$(MAX_EGL_CACHE_ENTRY_SIZE)
 endif
 
+ifneq ($(MAX_EGL_CACHE_KEY_SIZE),)
+  LOCAL_CFLAGS += -DMAX_EGL_CACHE_KEY_SIZE=$(MAX_EGL_CACHE_KEY_SIZE)
+endif
+
 ifneq ($(MAX_EGL_CACHE_SIZE),)
   LOCAL_CFLAGS += -DMAX_EGL_CACHE_SIZE=$(MAX_EGL_CACHE_SIZE)
 endif
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index ed2bef3..72655df 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -29,12 +29,16 @@
 #define MAX_EGL_CACHE_ENTRY_SIZE (16 * 1024);
 #endif
 
+#ifndef MAX_EGL_CACHE_KEY_SIZE
+#define MAX_EGL_CACHE_KEY_SIZE (1024);
+#endif
+
 #ifndef MAX_EGL_CACHE_SIZE
 #define MAX_EGL_CACHE_SIZE (64 * 1024);
 #endif
 
 // Cache size limits.
-static const size_t maxKeySize = 1024;
+static const size_t maxKeySize = MAX_EGL_CACHE_KEY_SIZE;
 static const size_t maxValueSize = MAX_EGL_CACHE_ENTRY_SIZE;
 static const size_t maxTotalSize = MAX_EGL_CACHE_SIZE;
 
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 01ae1c2..6a9cb3e 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -309,7 +309,7 @@
 void DisplayDevice::updateGeometryTransform() {
     int w = mDisplayWidth;
     int h = mDisplayHeight;
-    Transform R, S;
+    Transform T, R, S;
     if (DisplayDevice::orientationToTransfrom(
             mOrientation, w, h, &R) == NO_ERROR) {
         dirtyRegion.set(bounds());
@@ -340,20 +340,23 @@
         float src_height = viewport.height();
         float dst_width  = frame.width();
         float dst_height = frame.height();
-        if (src_width != src_height || dst_width != dst_height) {
+        if (src_width != dst_width || src_height != dst_height) {
             float sx = dst_width  / src_width;
             float sy = dst_height / src_height;
             S.set(sx, 0, 0, sy);
         }
+
         float src_x = viewport.left;
         float src_y = viewport.top;
         float dst_x = frame.left;
         float dst_y = frame.top;
         float tx = dst_x - src_x;
         float ty = dst_y - src_y;
-        S.set(tx, ty);
+        T.set(tx, ty);
 
-        // rotate first, followed by scaling
-        mGlobalTransform = S * R;
+        // The viewport and frame are both in the logical orientation, so the
+        // translation is also in that space. So translation must be applied
+        // before rotating from logical to physical orientation.
+        mGlobalTransform = S * R * T;
     }
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 058ba45..6542acd 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -753,27 +753,29 @@
         ATRACE_CALL();
         mVisibleRegionsDirty = false;
         invalidateHwcGeometry();
+
         const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
         for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+            Region opaqueRegion;
+            Region dirtyRegion;
+            Vector< sp<LayerBase> > layersSortedByZ;
             const sp<DisplayDevice>& hw(mDisplays[dpy]);
             const Transform& tr(hw->getTransform());
             const Rect bounds(hw->getBounds());
+            if (hw->canDraw()) {
+                SurfaceFlinger::computeVisibleRegions(currentLayers,
+                        hw->getLayerStack(), dirtyRegion, opaqueRegion);
 
-            Region opaqueRegion;
-            Region dirtyRegion;
-            computeVisibleRegions(currentLayers,
-                    hw->getLayerStack(), dirtyRegion, opaqueRegion);
-
-            Vector< sp<LayerBase> > layersSortedByZ;
-            const size_t count = currentLayers.size();
-            for (size_t i=0 ; i<count ; i++) {
-                const sp<LayerBase>& layer(currentLayers[i]);
-                const Layer::State& s(layer->drawingState());
-                if (s.layerStack == hw->getLayerStack()) {
-                    Region visibleRegion(tr.transform(layer->visibleRegion));
-                    visibleRegion.andSelf(bounds);
-                    if (!visibleRegion.isEmpty()) {
-                        layersSortedByZ.add(layer);
+                const size_t count = currentLayers.size();
+                for (size_t i=0 ; i<count ; i++) {
+                    const sp<LayerBase>& layer(currentLayers[i]);
+                    const Layer::State& s(layer->drawingState());
+                    if (s.layerStack == hw->getLayerStack()) {
+                        Region visibleRegion(tr.transform(layer->visibleRegion));
+                        visibleRegion.andSelf(bounds);
+                        if (!visibleRegion.isEmpty()) {
+                            layersSortedByZ.add(layer);
+                        }
                     }
                 }
             }
@@ -1776,6 +1778,7 @@
         mEventThread->onScreenReleased();
         hw->releaseScreen();
         getHwComposer().release();
+        mVisibleRegionsDirty = true;
         // from this point on, SF will stop drawing
     }
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ea03e2d..ffe68c6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -351,8 +351,8 @@
      * Compositing
      */
     void invalidateHwcGeometry();
-    void computeVisibleRegions(const LayerVector& currentLayers,
-            uint32_t layerStack,
+    static void computeVisibleRegions(
+            const LayerVector& currentLayers, uint32_t layerStack,
             Region& dirtyRegion, Region& opaqueRegion);
 
     void preComposition();