update hello-opencl

  - break dependency on code from src/compute
  - port away from C APIs to friendlier C++ wrapper APIs
  - add DEPS for OpenCL C++ wrapper headers so we can build on Mac
  - factor out a //third_party/opencl GN target

Change-Id: I9e37c6677cfb779021e66f2bd10f97570c450746
Reviewed-on: https://skia-review.googlesource.com/c/191281
Auto-Submit: Mike Klein <mtklein@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 96fdf86..bfad8d5 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -2404,16 +2404,11 @@
   if (skia_use_opencl) {
     test_app("hello-opencl") {
       sources = [
-        "src/compute/common/cl/assert_cl.c",
-        "src/compute/common/cl/find_cl.c",
         "tools/hello-opencl.cpp",
       ]
-      include_dirs = [ "src/compute/common" ]
-      if (is_linux) {
-        libs = [ "OpenCL" ]
-      } else if (is_win) {
-        libs = [ "OpenCL.lib" ]
-      }
+      deps = [
+        "//third_party/opencl",
+      ]
     }
   }
 }
diff --git a/DEPS b/DEPS
index e341ad1..e7d08d3 100644
--- a/DEPS
+++ b/DEPS
@@ -21,6 +21,7 @@
   "third_party/externals/lua"             : "https://skia.googlesource.com/external/github.com/lua/lua.git@v5-3-4",
   "third_party/externals/microhttpd"      : "https://android.googlesource.com/platform/external/libmicrohttpd@748945ec6f1c67b7efc934ab0808e1d32f2fb98d",
   "third_party/externals/opencl-lib"      : "https://skia.googlesource.com/external/github.com/GPUOpen-Tools/common-lib-amd-APPSDK-3.0@4e6d30e406d2e5a65e1d65e404fe6df5f772a32b",
+  "third_party/externals/opencl-registry" : "https://github.com/KhronosGroup/OpenCL-Registry@932ed55c85f887041291cef8019e54280c033c35",
   "third_party/externals/opengl-registry" : "https://skia.googlesource.com/external/github.com/KhronosGroup/OpenGL-Registry@14b80ebeab022b2c78f84a573f01028c96075553",
   "third_party/externals/piex"            : "https://android.googlesource.com/platform/external/piex.git@bb217acdca1cc0c16b704669dd6f91a1b509c406",
   "third_party/externals/sdl"             : "https://skia.googlesource.com/third_party/sdl@5d7cfcca344034aff9327f77fc181ae3754e7a90",
diff --git a/third_party/opencl/BUILD.gn b/third_party/opencl/BUILD.gn
new file mode 100644
index 0000000..03b2a90
--- /dev/null
+++ b/third_party/opencl/BUILD.gn
@@ -0,0 +1,15 @@
+import("../third_party.gni")
+
+third_party("opencl") {
+  # OpenCL C++ wrapper API, cl.hpp.
+  # (Some platforms only ship the C APIs, which cl.hpp builds on.)
+  public_include_dirs = [ "../externals/opencl-registry/api/2.1" ]
+
+  if (is_linux) {
+    libs = [ "OpenCL" ]
+  } else if (is_mac) {
+    libs = [ "OpenCL.framework" ]
+  } else if (is_win) {
+    libs = [ "OpenCL.lib" ]
+  }
+}
diff --git a/tools/hello-opencl.cpp b/tools/hello-opencl.cpp
index 7e57f0b..9b1be82 100644
--- a/tools/hello-opencl.cpp
+++ b/tools/hello-opencl.cpp
@@ -7,45 +7,76 @@
 
 // This is a simple OpenCL Hello World that tests you have a functioning OpenCL setup.
 
-#include <CL/cl.hpp>
+#include "cl.hpp"
 #include <initializer_list>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <vector>
 
-extern "C" {
-    #include "cl/assert_cl.h"   // for cl(), cl_ok() macros
-    #include "cl/find_cl.h"     // for clFindIdsByName
+static inline void assert_cl(cl_int rc, const char* file, int line) {
+    if (rc != CL_SUCCESS) {
+        fprintf(stderr, "%s:%d, got OpenCL error code %d\n", file,line,rc);
+        exit(1);
+    }
 }
+#define cl_ok(err) assert_cl(err, __FILE__, __LINE__)
 
 int main(int argc, char** argv) {
     // Find any OpenCL platform+device with these substrings.
     const char* platform_match = argc > 1 ? argv[1] : "";
     const char* device_match   = argc > 2 ? argv[2] : "";
 
-    cl_platform_id platform_id;
-    cl_device_id   device_id;
+    cl::Platform platform;
+    {
+        std::vector<cl::Platform> platforms;
+        cl_ok(cl::Platform::get(&platforms));
 
-    char device_name[256];
-    size_t device_name_len;
+        bool found = false;
+        for (cl::Platform p : platforms) {
+            std::string name;
+            cl_ok(p.getInfo(CL_PLATFORM_NAME, &name));
 
-    // clFindIdsByName will narrate what it's doing when this is set.
-    bool verbose = true;
+            fprintf(stdout, "Available platform %s\n", name.c_str());
 
-    // The cl() macro prepends cl to its argument, calls it, and asserts that it succeeded,
-    // printing out the file, line, and somewhat readable version of the error code on failure.
-    //
-    // It's generally used to call OpenCL APIs, but here we've written clFindIdsByName to match
-    // the convention, as its error conditions are just going to be passed along from OpenCL.
-    cl(FindIdsByName(platform_match,  device_match,
-                     &platform_id,    &device_id,
-                     sizeof(device_name), device_name, &device_name_len,
-                     verbose));
+            if (name.find(platform_match) != std::string::npos) {
+                platform = p;
+                found = true;
+            }
+        }
+        if (!found) {
+            fprintf(stderr, "No platform containing '%s' found.\n", platform_match);
+            exit(1);
+        }
+    }
 
-    printf("picked %.*s\n", (int)device_name_len, device_name);
+    cl::Device device;
+    {
+        std::vector<cl::Device> devices;
+        cl_ok(platform.getDevices(CL_DEVICE_TYPE_ALL, &devices));
 
-    // Allan's code is all C using OpenCL's C API,
-    // but we can mix that freely with the C++ API found in cl.hpp.
-    // cl_ok() comes in handy here, which is cl() without the extra cl- prefix.
+        bool found = false;
+        for (cl::Device d : devices) {
+            std::string name,
+                        version,
+                        driver;
+            cl_ok(d.getInfo(CL_DEVICE_NAME,    &name));
+            cl_ok(d.getInfo(CL_DEVICE_VERSION, &version));
+            cl_ok(d.getInfo(CL_DRIVER_VERSION, &driver));
 
-    cl::Device device(device_id);
+            fprintf(stdout, "Available device %s%s, driver version %s\n"
+                          , version.c_str(), name.c_str(), driver.c_str());
+
+            if (name.find(device_match) != std::string::npos) {
+                device = d;
+                found = true;
+            }
+        }
+        if (!found) {
+            fprintf(stderr, "No device containing '%s' found.\n", device_match);
+            exit(2);
+        }
+    }
 
     std::string name,
                 vendor,
@@ -54,8 +85,8 @@
     cl_ok(device.getInfo(CL_DEVICE_VENDOR,     &vendor));
     cl_ok(device.getInfo(CL_DEVICE_EXTENSIONS, &extensions));
 
-    printf("name %s, vendor %s, extensions:\n%s\n",
-           name.c_str(), vendor.c_str(), extensions.c_str());
+    fprintf(stdout, "Using %s, vendor %s, extensions:\n%s\n",
+            name.c_str(), vendor.c_str(), extensions.c_str());
 
     std::vector<cl::Device> devices = { device };
 
@@ -113,6 +144,6 @@
         }
     }
 
-    printf("OpenCL sez: %g x %g = %g\n", a[42], b[42], p[42]);
+    fprintf(stdout, "OpenCL sez: %g x %g = %g\n", a[42], b[42], p[42]);
     return 0;
 }