Add a property for overriding FP precision.

This merges the Stephen's CL 32c56ec on Jun. 1. It also renames
RSInfo::{Full,Relaxed,Imprecise} to RSInfo::{FP_Full,FP_Relaxed,
FP_Imprecise} which is more descriptive.

Change-Id: I6f202524d58a7f5a9dd8ea122aa0fd81162291b0
diff --git a/lib/RenderScript/RSCompilerDriver.cpp b/lib/RenderScript/RSCompilerDriver.cpp
index 58c1263..a59a7f9 100644
--- a/lib/RenderScript/RSCompilerDriver.cpp
+++ b/lib/RenderScript/RSCompilerDriver.cpp
@@ -43,6 +43,13 @@
 bool is_force_recompile() {
   char buf[PROPERTY_VALUE_MAX];
 
+  // Re-compile if floating point precision has been overridden.
+  property_get("debug.rs.precision", buf, "");
+  if (buf[0] != '\0') {
+    return true;
+  }
+
+  // Re-compile if debug.rs.forcerecompile is set.
   property_get("debug.rs.forcerecompile", buf, "0");
   if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) {
     return true;
@@ -163,7 +170,7 @@
 #if defined(DEFAULT_ARM_CODEGEN)
   // NEON should be disable when full-precision floating point is required.
   assert((pScript.getInfo() != NULL) && "NULL RS info!");
-  if (pScript.getInfo()->getFloatPrecisionRequirement() == RSInfo::Full) {
+  if (pScript.getInfo()->getFloatPrecisionRequirement() == RSInfo::FP_Full) {
     // Must be ARMCompilerConfig.
     ARMCompilerConfig *arm_config = static_cast<ARMCompilerConfig *>(mConfig);
     changed |= arm_config->enableNEON(/* pEnable */false);
diff --git a/lib/RenderScript/RSInfo.cpp b/lib/RenderScript/RSInfo.cpp
index 3939ee2..e06ea62 100644
--- a/lib/RenderScript/RSInfo.cpp
+++ b/lib/RenderScript/RSInfo.cpp
@@ -25,6 +25,8 @@
 #include "bcc/Support/FileBase.h"
 #include "bcc/Support/Log.h"
 
+#include <cutils/properties.h>
+
 using namespace bcc;
 
 const char RSInfo::LibBCCPath[] = "/system/lib/libbcc.so";
@@ -311,11 +313,13 @@
   return (pStr - mStringPool);
 }
 
-enum RSInfo::FloatPrecision RSInfo::getFloatPrecisionRequirement() const {
+RSInfo::FloatPrecision RSInfo::getFloatPrecisionRequirement() const {
   // Check to see if we have any FP precision-related pragmas.
   static const char relaxed_pragma[] = "rs_fp_relaxed";
   static const char imprecise_pragma[] = "rs_fp_imprecise";
+  static const char full_pragma[] = "rs_fp_full";
   bool relaxed_pragma_seen = false;
+  RSInfo::FloatPrecision result;
 
   for (PragmaListTy::const_iterator pragma_iter = mPragmas.begin(),
            pragma_end = mPragmas.end(); pragma_iter != pragma_end;
@@ -328,16 +332,37 @@
         ALOGW("Multiple float precision pragmas specified!");
       }
       // Fast return when there's rs_fp_imprecise specified.
-      return Imprecise;
+      result = FP_Imprecise;
     }
   }
 
   // Imprecise is selected over Relaxed precision.
   // In the absence of both, we stick to the default Full precision.
   if (relaxed_pragma_seen) {
-    return Relaxed;
+    result = FP_Relaxed;
   } else {
-    return Full;
+    result = FP_Full;
   }
-  // unreachable
+
+  // Provide an override for precsion via adb shell setprop
+  // adb shell setprop debug.rs.precision rs_fp_full
+  // adb shell setprop debug.rs.precision rs_fp_relaxed
+  // adb shell setprop debug.rs.precision rs_fp_imprecise
+  char precision_prop_buf[PROPERTY_VALUE_MAX];
+  property_get("debug.rs.precision", precision_prop_buf, "");
+
+  if (precision_prop_buf[0]) {
+    if (::strcmp(precision_prop_buf, relaxed_pragma) == 0) {
+      ALOGI("Switching to RS FP relaxed mode via setprop");
+      result = FP_Relaxed;
+    } else if (::strcmp(precision_prop_buf, imprecise_pragma) == 0) {
+      ALOGI("Switching to RS FP imprecise mode via setprop");
+      result = FP_Imprecise;
+    } else if (::strcmp(precision_prop_buf, full_pragma) == 0) {
+      ALOGI("Switching to RS FP full mode via setprop");
+      result = FP_Full;
+    }
+  }
+
+  return result;
 }