Add more shadow control knobs

Change-Id: I1ff500bf429029a97b681ced9df652f4ee9f1332
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index df2123b..43223ec 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -691,9 +691,10 @@
     propertyAmbientShadowStrength = 25;
     propertySpotShadowStrength = 25;
 
-    propertyLightPosXScale = 0.5f;
-    propertyLightPosYScale = 0.0f;
-    propertyLightPosZScale = 1.0f;
+    propertyLightDiameter = -1.0f;
+    propertyLightPosY = -1.0f;
+    propertyLightPosZ = -1.0f;
+    propertyAmbientRatio = -1.0f;
 }
 
 void Caches::setTempProperty(const char* name, const char* value) {
@@ -706,17 +707,21 @@
         propertySpotShadowStrength = atoi(value);
         ALOGD("spot shadow strength = 0x%x out of 0xff", propertySpotShadowStrength);
         return;
-    } else if (!strcmp(name, "lightPosXScale")) {
-        propertyLightPosXScale = fmin(fmax(atof(value), 0.0), 1.0);
-        ALOGD("lightPos X Scale = %.2f", propertyLightPosXScale);
+    } else if (!strcmp(name, "ambientRatio")) {
+        propertyAmbientRatio = fmin(fmax(atof(value), 0.0), 10.0);
+        ALOGD("ambientRatio = %.2f", propertyAmbientRatio);
         return;
-    }  else if (!strcmp(name, "lightPosYScale")) {
-        propertyLightPosYScale = fmin(fmax(atof(value), 0.0), 1.0);
-        ALOGD("lightPos Y Scale = %.2f", propertyLightPosXScale);
+    } else if (!strcmp(name, "lightDiameter")) {
+        propertyLightDiameter = fmin(fmax(atof(value), 0.0), 3000.0);
+        ALOGD("lightDiameter = %.2f", propertyLightDiameter);
         return;
-    }  else if (!strcmp(name, "lightPosZScale")) {
-        propertyLightPosZScale = fmin(fmax(atof(value), 0.0), 1.0);
-        ALOGD("lightPos Z Scale = %.2f", propertyLightPosXScale);
+    }  else if (!strcmp(name, "lightPosY")) {
+        propertyLightPosY = fmin(fmax(atof(value), 0.0), 3000.0);
+        ALOGD("lightPos Y = %.2f", propertyLightPosY);
+        return;
+    }  else if (!strcmp(name, "lightPosZ")) {
+        propertyLightPosZ = fmin(fmax(atof(value), 0.0), 3000.0);
+        ALOGD("lightPos Z = %.2f", propertyLightPosZ);
         return;
     }
     ALOGD("    failed");
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index ba3ccaf..2e2ee15 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -352,13 +352,10 @@
     void initTempProperties();
     void setTempProperty(const char* name, const char* value);
 
-    // These scaling factors range from 0 to 1, to scale the light position
-    // within the bound of (screenwidth, screenheight, max(screenwidth, screenheight));
-    // The default scale is (0.5, 0, 1) which put the light at
-    // (screenwidth / 2, 0, max(screenwidth, screenheight)).
-    float propertyLightPosXScale;
-    float propertyLightPosYScale;
-    float propertyLightPosZScale;
+    float propertyLightDiameter;
+    float propertyLightPosY;
+    float propertyLightPosZ;
+    float propertyAmbientRatio;
     int propertyAmbientShadowStrength;
     int propertySpotShadowStrength;
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 1f5389c..f3180f7 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -3287,10 +3287,8 @@
     if (mCaches.propertySpotShadowStrength > 0) {
         paint.setARGB(casterAlpha * mCaches.propertySpotShadowStrength, 0, 0, 0);
         VertexBuffer spotShadowVertexBuffer;
-        Vector3 lightPosScale(mCaches.propertyLightPosXScale,
-                mCaches.propertyLightPosYScale, mCaches.propertyLightPosZScale);
         VertexBufferMode vertexBufferMode = ShadowTessellator::tessellateSpotShadow(
-                isCasterOpaque, casterPolygon, casterVertexCount, lightPosScale,
+                isCasterOpaque, casterPolygon, casterVertexCount,
                 *currentTransform(), getWidth(), getHeight(), casterBounds, localClip,
                 spotShadowVertexBuffer);
         drawVertexBuffer(vertexBufferMode, spotShadowVertexBuffer, &paint);
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index 4d0edfb..feeeef1 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -22,6 +22,7 @@
 #include <utils/Trace.h>
 
 #include "AmbientShadow.h"
+#include "Caches.h"
 #include "ShadowTessellator.h"
 #include "SpotShadow.h"
 
@@ -41,9 +42,14 @@
 
     // A bunch of parameters to tweak the shadow.
     // TODO: Allow some of these changable by debug settings or APIs.
-    const float heightFactor = 1.0f / 128;
+    float heightFactor = 1.0f / 128;
     const float geomFactor = 64;
 
+    Caches& caches = Caches::getInstance();
+    if (CC_UNLIKELY(caches.propertyAmbientRatio > 0.0f)) {
+        heightFactor *= caches.propertyAmbientRatio;
+    }
+
     Rect ambientShadowBounds(casterBounds);
     ambientShadowBounds.outset(maxZ * geomFactor * heightFactor);
 
@@ -62,16 +68,26 @@
 
 VertexBufferMode ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque,
         const Vector3* casterPolygon, int casterVertexCount,
-        const Vector3& lightPosScale, const mat4& receiverTransform,
+        const mat4& receiverTransform,
         int screenWidth, int screenHeight, const Rect& casterBounds,
         const Rect& localClip, VertexBuffer& shadowVertexBuffer) {
     ATRACE_CALL();
 
+    Caches& caches = Caches::getInstance();
+
     // A bunch of parameters to tweak the shadow.
     // TODO: Allow some of these changable by debug settings or APIs.
     int maximal = max(screenWidth, screenHeight);
-    Vector3 lightCenter(screenWidth * lightPosScale.x, screenHeight * lightPosScale.y,
-            maximal * lightPosScale.z);
+    Vector3 lightCenter(screenWidth * 0.5f, 0, maximal);
+
+    if (CC_UNLIKELY(caches.propertyLightPosY > 0)) {
+        lightCenter.y = - caches.propertyLightPosY; // negated since this shifts up
+    }
+    if (CC_UNLIKELY(caches.propertyLightPosZ > 0)) {
+        lightCenter.z = caches.propertyLightPosZ;
+    }
+
+
 #if DEBUG_SHADOW
     ALOGD("light center %f %f %f", lightCenter.x, lightCenter.y, lightCenter.z);
 #endif
@@ -82,9 +98,13 @@
     reverseReceiverTransform.loadInverse(receiverTransform);
     reverseReceiverTransform.mapPoint3d(lightCenter);
 
-    const float lightSize = maximal / 4;
+    float lightSize = maximal / 4;
     const int lightVertexCount = 8;
 
+    if (CC_UNLIKELY(caches.propertyLightDiameter > 0)) {
+        lightSize = caches.propertyLightDiameter;
+    }
+
     // Now light and caster are both in local space, we will check whether
     // the shadow is within the clip area.
     Rect lightRect = Rect(lightCenter.x - lightSize, lightCenter.y - lightSize,
diff --git a/libs/hwui/ShadowTessellator.h b/libs/hwui/ShadowTessellator.h
index 05370dd..d112ace 100644
--- a/libs/hwui/ShadowTessellator.h
+++ b/libs/hwui/ShadowTessellator.h
@@ -73,7 +73,7 @@
 
     static VertexBufferMode tessellateSpotShadow(bool isCasterOpaque,
             const Vector3* casterPolygon, int casterVertexCount,
-            const Vector3& lightPosScale, const mat4& receiverTransform,
+            const mat4& receiverTransform,
             int screenWidth, int screenHeight, const Rect& casterBounds,
             const Rect& localClip, VertexBuffer& shadowVertexBuffer);