1 /*
2 * Copyright 2022 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "tests/Test.h"
9 #include "tools/skqp/src/skqp.h"
10
11 #include "include/core/SkStream.h"
12 #include "include/gpu/ganesh/GrDirectContext.h"
13
14 #ifdef SK_VULKAN
15 #include "tools/gpu/vk/VkTestContext.h"
16 #include <mutex>
17 #endif
18 #if defined(SK_GRAPHITE)
19 #include "include/gpu/graphite/Context.h"
20 #include "tools/graphite/ContextFactory.h"
21 #endif
22
23 using sk_gpu_test::ContextInfo;
24 using sk_gpu_test::GrContextFactory;
25 using sk_gpu_test::TestContext;
26
27 #ifdef SK_GL
28 using sk_gpu_test::GLTestContext;
29 #endif
30
31 namespace skiatest {
32
IsGLContextType(skgpu::ContextType type)33 bool IsGLContextType(skgpu::ContextType type) {
34 return skgpu::ganesh::ContextTypeBackend(type) == GrBackendApi::kOpenGL;
35 }
IsVulkanContextType(skgpu::ContextType type)36 bool IsVulkanContextType(skgpu::ContextType type) {
37 return skgpu::ganesh::ContextTypeBackend(type) == GrBackendApi::kVulkan;
38 }
IsMockContextType(skgpu::ContextType type)39 bool IsMockContextType(skgpu::ContextType type) {
40 return type == skgpu::ContextType::kMock;
41 }
42
43 // These are not supported
IsMetalContextType(skgpu::ContextType type)44 bool IsMetalContextType(skgpu::ContextType type) { return false; }
IsDirect3DContextType(skgpu::ContextType type)45 bool IsDirect3DContextType(skgpu::ContextType type) { return false; }
IsDawnContextType(skgpu::ContextType type)46 bool IsDawnContextType(skgpu::ContextType type) { return false; }
47
vk_has_physical_devices()48 static bool vk_has_physical_devices() {
49 static bool supported = false;
50 #ifdef SK_VULKAN
51 static std::once_flag flag;
52 std::call_once(flag, []() {
53 // We could create a VkInstance and call vkEnumeratePhysicalDevices devices directly, but
54 // CreatePlatformVkTestContext is already configured to do that and will return nullptr if
55 // there are no available devices.
56 std::unique_ptr<TestContext> testCtx(sk_gpu_test::CreatePlatformVkTestContext(nullptr));
57 if (testCtx) {
58 supported = true;
59 }
60 });
61 #endif
62 return supported;
63 }
64
65 #if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
66 // Used for testing on desktop machines.
67 static constexpr auto kNativeGLType = skgpu::ContextType::kGL;
68 #else
69 static constexpr auto kNativeGLType = skgpu::ContextType::kGLES;
70 #endif
71
72 #ifdef SK_BUILD_FOR_ANDROID
73 static_assert(kNativeGLType == skgpu::ContextType::kGLES, "CTS requires GLES");
74 #endif
75
skip_context(skgpu::ContextType contextType)76 static bool skip_context(skgpu::ContextType contextType) {
77 // Use "native" instead of explicitly trying both OpenGL and OpenGL ES.
78 if (contextType == skgpu::ContextType::kGL || contextType == skgpu::ContextType::kGLES) {
79 if (contextType != kNativeGLType) {
80 return true;
81 }
82 }
83
84 // The Android CDD (https://source.android.com/compatibility/12/android-12-cdd.pdf) does not
85 // require Vulkan, but if it enumerates at least one VkPhysicalDevice then it is expected that
86 // Vulkan is supported
87 if (contextType == skgpu::ContextType::kVulkan && !vk_has_physical_devices()) {
88 return true;
89 }
90 return false;
91 }
92
RunWithGaneshTestContexts(GrContextTestFn * testFn,ContextTypeFilterFn * filter,Reporter * reporter,const GrContextOptions & options)93 void RunWithGaneshTestContexts(GrContextTestFn* testFn,
94 ContextTypeFilterFn* filter,
95 Reporter* reporter,
96 const GrContextOptions& options) {
97 for (int typeInt = 0; typeInt < skgpu::kContextTypeCount; ++typeInt) {
98 skgpu::ContextType contextType = static_cast<skgpu::ContextType>(typeInt);
99 if (skip_context(contextType)) {
100 continue;
101 }
102
103 // The logic below is intended to mirror the behavior in DMGpuTestProcs.cpp
104 if (filter && !(*filter)(contextType)) {
105 continue;
106 }
107
108 sk_gpu_test::GrContextFactory factory(options);
109 sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(contextType);
110
111 ReporterContext ctx(reporter, SkString(skgpu::ContextTypeName(contextType)));
112 if (ctxInfo.directContext()) {
113 ctxInfo.testContext()->makeCurrent();
114 (*testFn)(reporter, ctxInfo);
115 // Sync so any release/finished procs get called.
116 ctxInfo.directContext()->flushAndSubmit(GrSyncCpu::kYes);
117 }
118 }
119 }
120
121 #if defined(SK_GRAPHITE)
122
123 namespace graphite {
124
RunWithGraphiteTestContexts(GraphiteTestFn * test,ContextTypeFilterFn * filter,Reporter * reporter,const TestOptions & options)125 void RunWithGraphiteTestContexts(GraphiteTestFn* test,
126 ContextTypeFilterFn* filter,
127 Reporter* reporter,
128 const TestOptions& options) {
129 ContextFactory factory(options);
130 for (int typeInt = 0; typeInt < skgpu::kContextTypeCount; ++typeInt) {
131 skgpu::ContextType contextType = static_cast<skgpu::ContextType>(typeInt);
132 if (skip_context(contextType)) {
133 continue;
134 }
135
136 // The logic below is intended to mirror the behavior in DMGpuTestProcs.cpp
137 if (filter && !(*filter)(contextType)) {
138 continue;
139 }
140
141 skiatest::graphite::ContextInfo ctxInfo = factory.getContextInfo(contextType);
142 if (!ctxInfo.fContext) {
143 continue;
144 }
145
146 ReporterContext ctx(reporter, SkString(skgpu::ContextTypeName(contextType)));
147 (*test)(reporter, ctxInfo.fContext, ctxInfo.fTestContext);
148 }
149 }
150
151 } // namespace graphite
152
153 #endif // SK_GRAPHITE
154
155 } // namespace skiatest
156
printBackendInfo(const char * dstPath)157 void SkQP::printBackendInfo(const char* dstPath) {
158 #ifdef SK_ENABLE_DUMP_GPU
159 SkFILEWStream out(dstPath);
160 out.writeText("[\n");
161
162 skgpu::ContextType contextsToDump[] = {skiatest::kNativeGLType, skgpu::ContextType::kVulkan};
163
164 for (auto contextType : contextsToDump) {
165 std::unique_ptr<TestContext> testCtx;
166 switch (contextType) {
167 #ifdef SK_GL
168 case skgpu::ContextType::kGL:
169 testCtx.reset(sk_gpu_test::CreatePlatformGLTestContext(kGL_GrGLStandard, nullptr));
170 break;
171 case skgpu::ContextType::kGLES:
172 testCtx.reset(
173 sk_gpu_test::CreatePlatformGLTestContext(kGLES_GrGLStandard, nullptr));
174 break;
175 #endif
176 #ifdef SK_VULKAN
177 case skgpu::ContextType::kVulkan:
178 testCtx.reset(sk_gpu_test::CreatePlatformVkTestContext(nullptr));
179 break;
180 #endif
181 default: {
182 }
183 }
184
185 if (testCtx) {
186 GrContextOptions options;
187 testCtx->makeCurrent();
188 if (sk_sp<GrDirectContext> ctx = testCtx->makeContext(options)) {
189 SkString info = ctx->dump();
190 // remove null
191 out.write(info.c_str(), info.size());
192 out.writeText(",\n");
193 }
194 }
195 }
196 out.writeText("]\n");
197 #endif
198 }
199