blob: 1d603bd0b59be0dfccf9a0ac45215595f4b35222 [file] [log] [blame]
/*
* 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
#if defined(SK_GRAPHITE)
#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(skgpu::ContextType type) {
return skgpu::ganesh::ContextTypeBackend(type) == GrBackendApi::kOpenGL;
}
bool IsVulkanContextType(skgpu::ContextType type) {
return skgpu::ganesh::ContextTypeBackend(type) == GrBackendApi::kVulkan;
}
bool IsMockContextType(skgpu::ContextType type) {
return type == skgpu::ContextType::kMock;
}
// These are not supported
bool IsMetalContextType(skgpu::ContextType type) { return false; }
bool IsDirect3DContextType(skgpu::ContextType type) { return false; }
bool IsDawnContextType(skgpu::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 = skgpu::ContextType::kGL;
#else
static constexpr auto kNativeGLType = skgpu::ContextType::kGLES;
#endif
#ifdef SK_BUILD_FOR_ANDROID
static_assert(kNativeGLType == skgpu::ContextType::kGLES, "CTS requires GLES");
#endif
static bool skip_context(skgpu::ContextType contextType) {
// Use "native" instead of explicitly trying both OpenGL and OpenGL ES.
if (contextType == skgpu::ContextType::kGL || contextType == skgpu::ContextType::kGLES) {
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 == skgpu::ContextType::kVulkan && !vk_has_physical_devices()) {
return true;
}
return false;
}
void RunWithGaneshTestContexts(GrContextTestFn* testFn,
ContextTypeFilterFn* filter,
Reporter* reporter,
const GrContextOptions& options) {
for (int typeInt = 0; typeInt < skgpu::kContextTypeCount; ++typeInt) {
skgpu::ContextType contextType = static_cast<skgpu::ContextType>(typeInt);
if (skip_context(contextType)) {
continue;
}
// The logic below is intended to mirror the behavior in DMGpuTestProcs.cpp
if (filter && !(*filter)(contextType)) {
continue;
}
sk_gpu_test::GrContextFactory factory(options);
sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(contextType);
ReporterContext ctx(reporter, SkString(skgpu::ContextTypeName(contextType)));
if (ctxInfo.directContext()) {
ctxInfo.testContext()->makeCurrent();
(*testFn)(reporter, ctxInfo);
// Sync so any release/finished procs get called.
ctxInfo.directContext()->flushAndSubmit(GrSyncCpu::kYes);
}
}
}
#if defined(SK_GRAPHITE)
namespace graphite {
void RunWithGraphiteTestContexts(GraphiteTestFn* test,
ContextTypeFilterFn* filter,
Reporter* reporter,
const TestOptions& options) {
ContextFactory factory(options);
for (int typeInt = 0; typeInt < skgpu::kContextTypeCount; ++typeInt) {
skgpu::ContextType contextType = static_cast<skgpu::ContextType>(typeInt);
if (skip_context(contextType)) {
continue;
}
// The logic below is intended to mirror the behavior in DMGpuTestProcs.cpp
if (filter && !(*filter)(contextType)) {
continue;
}
skiatest::graphite::ContextInfo ctxInfo = factory.getContextInfo(contextType);
if (!ctxInfo.fContext) {
continue;
}
ReporterContext ctx(reporter, SkString(skgpu::ContextTypeName(contextType)));
(*test)(reporter, ctxInfo.fContext, ctxInfo.fTestContext);
}
}
} // namespace graphite
#endif // SK_GRAPHITE
} // namespace skiatest
void SkQP::printBackendInfo(const char* dstPath) {
#ifdef SK_ENABLE_DUMP_GPU
SkFILEWStream out(dstPath);
out.writeText("[\n");
skgpu::ContextType contextsToDump[] = {skiatest::kNativeGLType, skgpu::ContextType::kVulkan};
for (auto contextType : contextsToDump) {
std::unique_ptr<TestContext> testCtx;
switch (contextType) {
#ifdef SK_GL
case skgpu::ContextType::kGL:
testCtx.reset(sk_gpu_test::CreatePlatformGLTestContext(kGL_GrGLStandard, nullptr));
break;
case skgpu::ContextType::kGLES:
testCtx.reset(
sk_gpu_test::CreatePlatformGLTestContext(kGLES_GrGLStandard, nullptr));
break;
#endif
#ifdef SK_VULKAN
case skgpu::ContextType::kVulkan:
testCtx.reset(sk_gpu_test::CreatePlatformVkTestContext(nullptr));
break;
#endif
default: {
}
}
if (testCtx) {
GrContextOptions options;
testCtx->makeCurrent();
if (sk_sp<GrDirectContext> ctx = testCtx->makeContext(options)) {
SkString info = ctx->dump();
// remove null
out.write(info.c_str(), info.size());
out.writeText(",\n");
}
}
}
out.writeText("]\n");
#endif
}