Interpreter: Add radians and normalize builtins

Change-Id: I2c76d8cbcfc3f36448127de5a3e1a22f76eda863
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/229489
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index f1fdbdd..fa4f248 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright 2019 Google LLC
  *
  * Use of this source code is governed by a BSD-style license that can be
@@ -17,14 +17,16 @@
     , fContext(*context)
     , fOutput(output)
     , fIntrinsics {
-         { "cos",     ByteCodeInstruction::kCos },
-         { "cross",   ByteCodeInstruction::kCross },
-         { "dot",     SpecialIntrinsic::kDot },
-         { "inverse", ByteCodeInstruction::kInverse2x2 },
-         { "sin",     ByteCodeInstruction::kSin },
-         { "sqrt",    ByteCodeInstruction::kSqrt },
-         { "tan",     ByteCodeInstruction::kTan },
-         { "mix",     ByteCodeInstruction::kMix },
+        { "cos",       ByteCodeInstruction::kCos },
+        { "cross",     ByteCodeInstruction::kCross },
+        { "dot",       SpecialIntrinsic::kDot },
+        { "inverse",   ByteCodeInstruction::kInverse2x2 },
+        { "normalize", ByteCodeInstruction::kNormalize },
+        { "radians",   SpecialIntrinsic::kRadians },
+        { "sin",       ByteCodeInstruction::kSin },
+        { "sqrt",      ByteCodeInstruction::kSqrt },
+        { "tan",       ByteCodeInstruction::kTan },
+        { "mix",       ByteCodeInstruction::kMix },
       } {}
 
 
@@ -197,6 +199,7 @@
         VECTOR_UNARY_OP(kConvertUtoF)
 
         VECTOR_UNARY_OP(kCos)
+        VECTOR_UNARY_OP(kNormalize)
         VECTOR_UNARY_OP(kSin)
         VECTOR_UNARY_OP(kSqrt)
         VECTOR_UNARY_OP(kTan)
@@ -879,17 +882,34 @@
     }
     int count = SlotCount(c.fArguments[0]->fType);
     if (found->second.fIsSpecial) {
-        SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
-        SkASSERT(c.fArguments.size() == 2);
-        SkASSERT(count == SlotCount(c.fArguments[1]->fType));
-        this->write((ByteCodeInstruction)((int)ByteCodeInstruction::kMultiplyF + count - 1));
-        for (int i = count; i > 1; --i) {
-            this->write(ByteCodeInstruction::kAddF);
+        SpecialIntrinsic special = found->second.fValue.fSpecial;
+        switch (special) {
+            case SpecialIntrinsic::kDot: {
+                SkASSERT(c.fArguments.size() == 2);
+                SkASSERT(count == SlotCount(c.fArguments[1]->fType));
+                this->write((ByteCodeInstruction)((int)ByteCodeInstruction::kMultiplyF + count-1));
+                for (int i = count; i > 1; --i) {
+                    this->write(ByteCodeInstruction::kAddF);
+                }
+                break;
+            }
+            case SpecialIntrinsic::kRadians: {
+                this->write(ByteCodeInstruction::kPushImmediate);
+                this->write32(float_to_bits(0.0174532925f)); // π/180
+                for (int i = count; i > 1; --i) {
+                    this->write(ByteCodeInstruction::kDup);
+                }
+                this->write((ByteCodeInstruction)((int)ByteCodeInstruction::kMultiplyF + count-1));
+                break;
+            }
+            default:
+                SkASSERT(false);
         }
     } else {
         switch (found->second.fValue.fInstruction) {
             case ByteCodeInstruction::kCos:
             case ByteCodeInstruction::kMix:
+            case ByteCodeInstruction::kNormalize:
             case ByteCodeInstruction::kSin:
             case ByteCodeInstruction::kSqrt:
             case ByteCodeInstruction::kTan:
@@ -910,7 +930,8 @@
                     default: SkASSERT(false);
                 }
                 this->write(op);
-            } break;
+                break;
+            }
             default:
                 SkASSERT(false);
         }