blob: 187d165e58c9465fe28247afc0c98b8ad8379d90 [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
#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
void SkQP::printBackendInfo(const char* dstPath) {
#ifdef SK_ENABLE_DUMP_GPU
SkFILEWStream out(dstPath);
out.writeText("[\n");
GrContextFactory::ContextType contextsToDump[] = {skiatest::kNativeGLType,
GrContextFactory::kVulkan_ContextType};
for (auto contextType : contextsToDump) {
std::unique_ptr<TestContext> testCtx;
switch (contextType) {
#ifdef SK_GL
case GrContextFactory::kGL_ContextType:
testCtx.reset(sk_gpu_test::CreatePlatformGLTestContext(kGL_GrGLStandard, nullptr));
break;
case GrContextFactory::kGLES_ContextType:
testCtx.reset(
sk_gpu_test::CreatePlatformGLTestContext(kGLES_GrGLStandard, nullptr));
break;
#endif
#ifdef SK_VULKAN
case GrContextFactory::kVulkan_ContextType:
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
}