Property support for light positioning.

Tune up the light size to make it look better.

Change-Id: I139a05f3dd53dacbe55759b91188f0e1cc2c7f80
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 2e7990e..8bd9de0 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -686,6 +686,10 @@
     propertyEnable3d = false;
     propertyCameraDistance = 1.0f;
     propertyShadowStrength = 0x3f;
+
+    propertyLightPosXScale = 0.5f;
+    propertyLightPosYScale = 0.0f;
+    propertyLightPosZScale = 1.0f;
 }
 
 void Caches::setTempProperty(const char* name, const char* value) {
@@ -704,6 +708,21 @@
         propertyShadowStrength = atoi(value);
         ALOGD("shadow strength = 0x%x out of 0xff", propertyShadowStrength);
         return;
+    } else if (!strcmp(name, "lightPosXScale")) {
+        propertyLightPosXScale = fmin(fmax(atof(value), 0.0), 1.0);
+        propertyDirtyViewport = true;
+        ALOGD("lightPos X Scale = %.2f", propertyLightPosXScale);
+        return;
+    }  else if (!strcmp(name, "lightPosYScale")) {
+        propertyLightPosYScale = fmin(fmax(atof(value), 0.0), 1.0);
+        propertyDirtyViewport = true;
+        ALOGD("lightPos Y Scale = %.2f", propertyLightPosXScale);
+        return;
+    }  else if (!strcmp(name, "lightPosZScale")) {
+        propertyLightPosZScale = fmin(fmax(atof(value), 0.0), 1.0);
+        propertyDirtyViewport = true;
+        ALOGD("lightPos Z Scale = %.2f", propertyLightPosXScale);
+        return;
     }
     ALOGD("    failed");
 }
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 01e8d84..e7ba9ac 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -359,6 +359,14 @@
     bool propertyEnable3d;
     bool propertyDirtyViewport; // flag set when dirtying the viewport
     float propertyCameraDistance;
+
+    // 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;
     int propertyShadowStrength;
 
 private:
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 8fb6e38..7ee803f 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -3200,9 +3200,12 @@
     drawVertexBuffer(ambientShadowVertexBuffer, &paint);
 
     VertexBuffer spotShadowVertexBuffer;
-    ShadowTessellator::tessellateSpotShadow(width, height,
+    Vector3 lightPosScale(mCaches.propertyLightPosXScale,
+            mCaches.propertyLightPosYScale, mCaches.propertyLightPosZScale);
+    ShadowTessellator::tessellateSpotShadow(width, height, lightPosScale,
             *currentTransform(), getWidth(), getHeight(),
             casterTransform, spotShadowVertexBuffer);
+
     drawVertexBuffer(spotShadowVertexBuffer, &paint);
 
     return DrawGlInfo::kStatusDrew;
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index b9ce872..6dfd925 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -85,8 +85,9 @@
 }
 
 void ShadowTessellator::tessellateSpotShadow(float width, float height,
-        const mat4& receiverTransform, int screenWidth, int screenHeight,
-        const mat4& casterTransform, VertexBuffer& shadowVertexBuffer) {
+        const Vector3& lightPosScale, const mat4& receiverTransform,
+        int screenWidth, int screenHeight, const mat4& casterTransform,
+        VertexBuffer& shadowVertexBuffer) {
     const int vertexCount = 4;
     Vector3 polygon[vertexCount];
     generateCasterPolygon(width, height, casterTransform, vertexCount, polygon);
@@ -97,7 +98,8 @@
     const int layers = 2;
     const float strength = 0.5;
     int maximal = max(screenWidth, screenHeight);
-    Vector3 lightCenter(screenWidth / 2, 0, maximal);
+    Vector3 lightCenter(screenWidth * lightPosScale.x, screenHeight * lightPosScale.y,
+            maximal * lightPosScale.z);
 #if DEBUG_SHADOW
     ALOGD("light center %f %f %f", lightCenter.x, lightCenter.y, lightCenter.z);
 #endif
@@ -108,7 +110,7 @@
     reverseReceiverTransform.loadInverse(receiverTransform);
     reverseReceiverTransform.mapPoint3d(lightCenter);
 
-    const float lightSize = maximal / 8;
+    const float lightSize = maximal / 4;
     const int lightVertexCount = 16;
 
     SpotShadow::createSpotShadow(polygon, vertexCount, lightCenter, lightSize,
diff --git a/libs/hwui/ShadowTessellator.h b/libs/hwui/ShadowTessellator.h
index 44ac8c0..2399f8f 100644
--- a/libs/hwui/ShadowTessellator.h
+++ b/libs/hwui/ShadowTessellator.h
@@ -30,8 +30,9 @@
             const mat4& casterTransform, VertexBuffer& shadowVertexBuffer);
 
     static void tessellateSpotShadow(float width, float height,
-            const mat4& receiverTransform, int screenWidth, int screenHeight,
-            const mat4& casterTransform, VertexBuffer& shadowVertexBuffer);
+            const Vector3& lightPosScale, const mat4& receiverTransform,
+            int screenWidth, int screenHeight, const mat4& casterTransform,
+            VertexBuffer& shadowVertexBuffer);
 
 private:
     static void generateCasterPolygon(float width, float height,