Lay groundwork for SkOpts.

This doesn't really do anything yet.  It's just the CPU detection code, skeleton new .cpp files, and a few little .gyp tweaks.

BUG=skia:4117

Committed: https://skia.googlesource.com/skia/+/ce2c5055cee5d5d3c9fc84c1b3eeed4b4d84a827

Review URL: https://codereview.chromium.org/1255193002
diff --git a/gyp/core.gypi b/gyp/core.gypi
index 28ef6d1..e88061a 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -134,6 +134,7 @@
         '<(skia_src_path)/core/SkMiniRecorder.cpp',
         '<(skia_src_path)/core/SkMultiPictureDraw.cpp',
         '<(skia_src_path)/core/SkNinePatchIter.cpp',
+        '<(skia_src_path)/core/SkOpts.cpp',
         '<(skia_src_path)/core/SkPackBits.cpp',
         '<(skia_src_path)/core/SkPaint.cpp',
         '<(skia_src_path)/core/SkPaintPriv.cpp',
diff --git a/gyp/opts.gypi b/gyp/opts.gypi
index 6d7a796..44e57d52 100644
--- a/gyp/opts.gypi
+++ b/gyp/opts.gypi
@@ -34,6 +34,7 @@
             '<(skia_src_path)/opts/SkTextureCompression_opts_neon.cpp',
             '<(skia_src_path)/opts/SkUtils_opts_arm_neon.cpp',
             '<(skia_src_path)/opts/SkXfermode_opts_arm_neon.cpp',
+            '<(skia_src_path)/opts/SkOpts_neon.cpp',
         ],
         'arm64_sources': [
             '<(skia_src_path)/opts/SkBitmapProcState_arm_neon.cpp',
@@ -51,6 +52,7 @@
             '<(skia_src_path)/opts/SkUtils_opts_none.cpp',
             '<(skia_src_path)/opts/SkXfermode_opts_arm.cpp',
             '<(skia_src_path)/opts/SkXfermode_opts_arm_neon.cpp',
+            '<(skia_src_path)/opts/SkOpts_neon.cpp',
         ],
 
         'mips_dsp_sources': [
@@ -74,12 +76,15 @@
             '<(skia_src_path)/opts/SkUtils_opts_SSE2.cpp',
             '<(skia_src_path)/opts/SkXfermode_opts_none.cpp',
             '<(skia_src_path)/opts/opts_check_x86.cpp',
+            '<(skia_src_path)/opts/SkOpts_sse2.cpp',
         ],
         'ssse3_sources': [
             '<(skia_src_path)/opts/SkBitmapProcState_opts_SSSE3.cpp',
+            '<(skia_src_path)/opts/SkOpts_ssse3.cpp',
         ],
         'sse41_sources': [
             '<(skia_src_path)/opts/SkBlurImage_opts_SSE4.cpp',
             '<(skia_src_path)/opts/SkBlitRow_opts_SSE4.cpp',
+            '<(skia_src_path)/opts/SkOpts_sse41.cpp',
         ],
 }
diff --git a/include/core/SkGraphics.h b/include/core/SkGraphics.h
index f2e3d8d..8d804b3 100644
--- a/include/core/SkGraphics.h
+++ b/include/core/SkGraphics.h
@@ -17,8 +17,8 @@
 public:
     /**
      *  Call this at process initialization time if your environment does not
-     *  permit static global initializers that execute code. Note that
-     *  Init() is not thread-safe.
+     *  permit static global initializers that execute code.
+     *  Init() is thread-safe and idempotent.
      */
     static void Init();
 
diff --git a/src/core/SkGraphics.cpp b/src/core/SkGraphics.cpp
index 7acee85..093e7a6 100644
--- a/src/core/SkGraphics.cpp
+++ b/src/core/SkGraphics.cpp
@@ -14,6 +14,7 @@
 #include "SkGeometry.h"
 #include "SkMath.h"
 #include "SkMatrix.h"
+#include "SkOpts.h"
 #include "SkPath.h"
 #include "SkPathEffect.h"
 #include "SkPixelRef.h"
@@ -39,17 +40,10 @@
     }
 }
 
-#define typesizeline(type)  { #type , sizeof(type) }
-
-#ifdef BUILD_EMBOSS_TABLE
-    extern void SkEmbossMask_BuildTable();
-#endif
-
-#ifdef BUILD_RADIALGRADIENT_TABLE
-    extern void SkRadialGradient_BuildTable();
-#endif
-
 void SkGraphics::Init() {
+    // SkGraphics::Init() must be thread-safe and idempotent.
+    SkOpts::Init();
+
 #ifdef SK_DEVELOPER
     skRTConfRegistry().possiblyDumpFile();
     skRTConfRegistry().validate();
@@ -58,71 +52,6 @@
         skRTConfRegistry().printNonDefault();
     }
 #endif
-
-#ifdef BUILD_EMBOSS_TABLE
-    SkEmbossMask_BuildTable();
-#endif
-#ifdef BUILD_RADIALGRADIENT_TABLE
-    SkRadialGradient_BuildTable();
-#endif
-
-#ifdef SK_DEBUGx
-    int i;
-
-    static const struct {
-        const char* fTypeName;
-        size_t      fSizeOf;
-    } gTypeSize[] = {
-        typesizeline(char),
-        typesizeline(short),
-        typesizeline(int),
-        typesizeline(long),
-        typesizeline(size_t),
-        typesizeline(void*),
-
-        typesizeline(S8CPU),
-        typesizeline(U8CPU),
-        typesizeline(S16CPU),
-        typesizeline(U16CPU),
-
-        typesizeline(SkPoint),
-        typesizeline(SkRect),
-        typesizeline(SkMatrix),
-        typesizeline(SkPath),
-        typesizeline(SkGlyph),
-        typesizeline(SkRefCnt),
-
-        typesizeline(SkPaint),
-        typesizeline(SkCanvas),
-        typesizeline(SkBlitter),
-        typesizeline(SkShader),
-        typesizeline(SkXfermode),
-        typesizeline(SkPathEffect)
-    };
-
-#ifdef SK_CPU_BENDIAN
-    SkDebugf("SkGraphics: big-endian\n");
-#else
-    SkDebugf("SkGraphics: little-endian\n");
-#endif
-
-    {
-        char    test = 0xFF;
-        int     itest = test;   // promote to int, see if it sign-extended
-        if (itest < 0)
-            SkDebugf("SkGraphics: char is signed\n");
-        else
-            SkDebugf("SkGraphics: char is unsigned\n");
-    }
-    for (i = 0; i < (int)SK_ARRAY_COUNT(gTypeSize); i++) {
-        SkDebugf("SkGraphics: sizeof(%s) = %d\n",
-                 gTypeSize[i].fTypeName, gTypeSize[i].fSizeOf);
-    }
-    SkDebugf("SkGraphics: font cache limit %dK\n",
-             GetFontCacheLimit() >> 10);
-
-#endif
-
 }
 
 void SkGraphics::Term() {
diff --git a/src/core/SkOpts.cpp b/src/core/SkOpts.cpp
new file mode 100644
index 0000000..4f7c5e9
--- /dev/null
+++ b/src/core/SkOpts.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkOnce.h"
+#include "SkOpts.h"
+
+#if defined(SK_CPU_X86)
+    #if defined(SK_BUILD_FOR_WIN32)
+        #include <intrin.h>
+        static void cpuid(uint32_t abcd[4]) { __cpuid((int*)abcd, 1); }
+    #else
+        #include <cpuid.h>
+        static void cpuid(uint32_t abcd[4]) { __get_cpuid(1, abcd+0, abcd+1, abcd+2, abcd+3); }
+    #endif
+#elif !defined(SK_ARM_HAS_NEON) && defined(SK_CPU_ARM32) && defined(SK_BUILD_FOR_ANDROID)
+    #include <cpu-features.h>
+#endif
+
+namespace SkOpts {
+    // (Define default function pointer values here...)
+
+    // Each Init_foo() is defined in src/opts/SkOpts_foo.cpp.
+    void Init_sse2();
+    void Init_ssse3();
+    void Init_sse41();
+    void Init_neon();
+    //TODO: _dsp2, _armv7, _armv8, _x86, _x86_64, _sse42, _avx, avx2, ... ?
+
+    static void init() {
+    #if defined(SK_CPU_X86)
+        uint32_t abcd[] = {0,0,0,0};
+        cpuid(abcd);
+        if (abcd[3] & (1<<26)) { Init_sse2(); }
+        if (abcd[2] & (1<< 9)) { Init_ssse3(); }
+        if (abcd[2] & (1<<19)) { Init_sse41(); }
+    #elif defined(SK_ARM_HAS_NEON)
+        Init_neon();
+    #elif defined(SK_CPU_ARM32) && defined(SK_BUILD_FOR_ANDROID)
+        if (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) { Init_neon(); }
+    #endif
+    }
+
+    SK_DECLARE_STATIC_ONCE(gInitOnce);
+    void Init() { SkOnce(&gInitOnce, init); }
+
+#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
+    static struct AutoInit {
+        AutoInit() { Init(); }
+    } gAutoInit;
+#endif
+}
diff --git a/src/core/SkOpts.h b/src/core/SkOpts.h
new file mode 100644
index 0000000..71abae5
--- /dev/null
+++ b/src/core/SkOpts.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkOpts_DEFINED
+#define SkOpts_DEFINED
+
+#include "SkTypes.h"
+
+namespace SkOpts {
+    // Call to replace pointers to portable functions with pointers to CPU-specific functions.
+    // Thread-safe and idempotent.
+    // Called by SkGraphics::Init(), and automatically #if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS.
+    void Init();
+
+    // (Function pointers go here).
+}
+
+#endif//SkOpts_DEFINED
diff --git a/src/opts/SkOpts_neon.cpp b/src/opts/SkOpts_neon.cpp
new file mode 100644
index 0000000..3508b35
--- /dev/null
+++ b/src/opts/SkOpts_neon.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkOpts.h"
+
+namespace SkOpts {
+    void Init_neon() {
+
+    }
+}
diff --git a/src/opts/SkOpts_sse2.cpp b/src/opts/SkOpts_sse2.cpp
new file mode 100644
index 0000000..31afa8c
--- /dev/null
+++ b/src/opts/SkOpts_sse2.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkOpts.h"
+
+namespace SkOpts {
+    void Init_sse2() {
+
+    }
+}
diff --git a/src/opts/SkOpts_sse41.cpp b/src/opts/SkOpts_sse41.cpp
new file mode 100644
index 0000000..72e5682
--- /dev/null
+++ b/src/opts/SkOpts_sse41.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkOpts.h"
+
+namespace SkOpts {
+    void Init_sse41() {
+
+    }
+}
diff --git a/src/opts/SkOpts_ssse3.cpp b/src/opts/SkOpts_ssse3.cpp
new file mode 100644
index 0000000..de32966
--- /dev/null
+++ b/src/opts/SkOpts_ssse3.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkOpts.h"
+
+namespace SkOpts {
+    void Init_ssse3() {
+
+    }
+}