Correctly detect the wrong Z value for the light

b/17221975

Change-Id: I2b46da95ad12ca5260d7fe9514a75558b6b6393b
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index cb20a0b..2178cc7 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -647,7 +647,7 @@
     if (lightToPolyZ != 0) {
         // If any caster's vertex is almost above the light, we just keep it as 95%
         // of the height of the light.
-        ratioZ = MathUtils::min(polyVertex.z / lightToPolyZ, CASTER_Z_CAP_RATIO);
+        ratioZ = MathUtils::clamp(polyVertex.z / lightToPolyZ, 0.0f, CASTER_Z_CAP_RATIO);
     }
 
     outline.x = polyVertex.x - ratioZ * (lightCenter.x - polyVertex.x);
@@ -669,6 +669,10 @@
 void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter,
         float lightSize, const Vector3* poly, int polyLength, const Vector3& polyCentroid,
         VertexBuffer& shadowTriangleStrip) {
+    if (CC_UNLIKELY(lightCenter.z <= 0)) {
+        ALOGW("Relative Light Z is not positive. No spot shadow!");
+        return;
+    }
     OutlineData outlineData[polyLength];
     Vector2 outlineCentroid;
     // Calculate the projected outline for each polygon's vertices from the light center.
@@ -787,7 +791,7 @@
         // The ratio can be simulated by using the inverse of maximum of ratioVI for
         // all (V).
         distOutline = (outlineData[i].position - outlineCentroid).length();
-        if (distOutline == 0) {
+        if (CC_UNLIKELY(distOutline == 0)) {
             // If the outline has 0 area, then there is no spot shadow anyway.
             ALOGW("Outline has 0 area, no spot shadow!");
             return;
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 00448b8..d89859b 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -76,6 +76,11 @@
         return a < b ? a : b;
     }
 
+    template<typename T>
+    static inline T clamp(T a, T minValue, T maxValue) {
+        return min(max(a, minValue), maxValue);
+    }
+
     inline static float lerp(float v1, float v2, float t) {
         return v1 + ((v2 - v1) * t);
     }