Update SkQP to use its own GpuTestProcs

Enables us to filter out Vulkan tests for devices that do not
report any vulkan hardware.

Bug: b/240880901
Change-Id: I653e3edb5829d75f1a17a49b004fa5f053f8f4ff
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/565903
Commit-Queue: Derek Sollenberger <djsollen@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index bd521ab..39ae3cc 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -2538,9 +2538,9 @@
       testonly = true
       public_configs = [ ":skia_private" ]
       sources = [
-        "dm/DMGpuTestProcs.cpp",
         "tools/skqp/src/skqp.cpp",
         "tools/skqp/src/skqp.h",
+        "tools/skqp/src/skqp_GpuTestProcs.cpp",
       ]
       deps = [
         ":gm",
diff --git a/tools/skqp/src/skqp_GpuTestProcs.cpp b/tools/skqp/src/skqp_GpuTestProcs.cpp
new file mode 100644
index 0000000..678dc7d
--- /dev/null
+++ b/tools/skqp/src/skqp_GpuTestProcs.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2022 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tests/Test.h"
+#include "tools/skqp/src/skqp.h"
+
+#include "include/core/SkStream.h"
+#include "include/gpu/GrDirectContext.h"
+
+#ifdef SK_VULKAN
+#include "tools/gpu/vk/VkTestContext.h"
+#include <mutex>
+#endif
+#ifdef SK_GRAPHITE_ENABLED
+#include "include/gpu/graphite/Context.h"
+#include "tools/graphite/ContextFactory.h"
+#endif
+
+using sk_gpu_test::ContextInfo;
+using sk_gpu_test::GrContextFactory;
+using sk_gpu_test::TestContext;
+
+#ifdef SK_GL
+using sk_gpu_test::GLTestContext;
+#endif
+
+namespace skiatest {
+
+bool IsGLContextType(sk_gpu_test::GrContextFactory::ContextType type) {
+    return GrBackendApi::kOpenGL == GrContextFactory::ContextTypeBackend(type);
+}
+bool IsVulkanContextType(sk_gpu_test::GrContextFactory::ContextType type) {
+    return GrBackendApi::kVulkan == GrContextFactory::ContextTypeBackend(type);
+}
+bool IsRenderingGLContextType(sk_gpu_test::GrContextFactory::ContextType type) {
+    return IsGLContextType(type) && GrContextFactory::IsRenderingContext(type);
+}
+bool IsMockContextType(sk_gpu_test::GrContextFactory::ContextType type) {
+    return type == GrContextFactory::kMock_ContextType;
+}
+
+// These are not supported
+bool IsMetalContextType(sk_gpu_test::GrContextFactory::ContextType type) { return false; }
+bool IsDirect3DContextType(sk_gpu_test::GrContextFactory::ContextType type) { return false; }
+bool IsDawnContextType(sk_gpu_test::GrContextFactory::ContextType type) { return false; }
+
+static bool vk_has_physical_devices() {
+    static bool supported = false;
+#ifdef SK_VULKAN
+    static std::once_flag flag;
+    std::call_once(flag, []() {
+        // We could create a VkInstance and call vkEnumeratePhysicalDevices devices directly, but
+        // CreatePlatformVkTestContext is already configured to do that and will return nullptr if
+        // there are no available devices.
+        std::unique_ptr<TestContext> testCtx(sk_gpu_test::CreatePlatformVkTestContext(nullptr));
+        if (testCtx) {
+            supported = true;
+        }
+    });
+#endif
+    return supported;
+}
+
+#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
+// Used for testing on desktop machines.
+static constexpr auto kNativeGLType = GrContextFactory::kGL_ContextType;
+#else
+static constexpr auto kNativeGLType = GrContextFactory::kGLES_ContextType;
+#endif
+
+#ifdef SK_BUILD_FOR_ANDROID
+static_assert(kNativeGLType == GrContextFactory::kGLES_ContextType, "CTS requires GLES");
+#endif
+
+static bool skip_context(GrContextFactory::ContextType contextType) {
+    // Use "native" instead of explicitly trying both OpenGL and OpenGL ES.
+    if (contextType == GrContextFactory::kGL_ContextType ||
+        contextType == GrContextFactory::kGLES_ContextType) {
+        if (contextType != kNativeGLType) {
+            return true;
+        }
+    }
+
+    // The Android CDD (https://source.android.com/compatibility/12/android-12-cdd.pdf) does not
+    // require Vulkan, but if it enumerates at least one VkPhysicalDevice then it is expected that
+    // Vulkan is supported
+    if (contextType == GrContextFactory::kVulkan_ContextType && !vk_has_physical_devices()) {
+        return true;
+    }
+    return false;
+}
+
+void RunWithGPUTestContexts(GrContextTestFn* test,
+                            GrContextTypeFilterFn* contextTypeFilter,
+                            Reporter* reporter,
+                            const GrContextOptions& options) {
+    for (int typeInt = 0; typeInt < GrContextFactory::kContextTypeCnt; ++typeInt) {
+        GrContextFactory::ContextType contextType = (GrContextFactory::ContextType)typeInt;
+        if (skip_context(contextType)) {
+            continue;
+        }
+
+        // The logic below is intended to mirror the behavior in DMGpuTestProcs.cpp
+        if (contextTypeFilter && !(*contextTypeFilter)(contextType)) {
+            continue;
+        }
+
+        sk_gpu_test::GrContextFactory factory(options);
+        sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(contextType);
+
+        ReporterContext ctx(reporter, SkString(GrContextFactory::ContextTypeName(contextType)));
+        if (ctxInfo.directContext()) {
+            ctxInfo.testContext()->makeCurrent();
+            (*test)(reporter, ctxInfo);
+            // Sync so any release/finished procs get called.
+            ctxInfo.directContext()->flushAndSubmit(/*sync*/ true);
+        }
+    }
+}
+
+#ifdef SK_GRAPHITE_ENABLED
+
+namespace graphite {
+
+void RunWithGraphiteTestContexts(GraphiteTestFn* test, Reporter* reporter) { SK_ABORT(); }
+
+}  // namespace graphite
+
+#endif  // SK_GRAPHITE_ENABLED
+
+}  // namespace skiatest