Add base class for GLTestContext and add new subclass VkTestContext.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1964243003

Review-Url: https://codereview.chromium.org/1964243003
This commit is contained in:
bsalomon 2016-05-11 10:09:18 -07:00 committed by Commit bot
parent 393c2ff0d2
commit 18a2f9dff8
9 changed files with 366 additions and 177 deletions

View File

@ -10,13 +10,32 @@
#define GrVkDefines_DEFINED
#if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_WIN32)
#define VK_USE_PLATFORM_WIN32_KHR
# define VK_USE_PLATFORM_WIN32_KHR
#elif defined(SK_BUILD_FOR_ANDROID)
#define VK_USE_PLATFORM_ANDROID_KHR
# define VK_USE_PLATFORM_ANDROID_KHR
#elif defined(SK_BUILD_FOR_UNIX)
#define VK_USE_PLATFORM_XLIB_KHR
# define VK_USE_PLATFORM_XLIB_KHR
#endif
#if defined(Bool) || defined(Status) || defined(True) || defined(False)
# pragma error "Macros unexpectedly defined."
#endif
#include <vulkan/vulkan.h>
// Xlib.h may define these macros with common names (Grrr)
#ifdef Bool
# undef Bool
#endif
#ifdef Status
# undef Status
#endif
#ifdef True
# undef True
#endif
#ifdef False
# undef False
#endif
#endif

View File

@ -20,7 +20,7 @@
#include "gl/mesa/GLTestContext_mesa.h"
#endif
#if SK_VULKAN
#include "vk/GrVkBackendContext.h"
#include "vk/VkTestContext.h"
#endif
#include "gl/null/NullGLTestContext.h"
#include "gl/GrGLGpu.h"
@ -39,15 +39,15 @@ GrContextFactory::~GrContextFactory() {
void GrContextFactory::destroyContexts() {
for (Context& context : fContexts) {
if (context.fGLContext) {
context.fGLContext->makeCurrent();
if (context.fTestContext) {
context.fTestContext->makeCurrent();
}
if (!context.fGrContext->unique()) {
context.fGrContext->releaseResourcesAndAbandonContext();
context.fAbandoned = true;
}
context.fGrContext->unref();
delete context.fGLContext;
delete context.fTestContext;
}
fContexts.reset();
}
@ -55,11 +55,11 @@ void GrContextFactory::destroyContexts() {
void GrContextFactory::abandonContexts() {
for (Context& context : fContexts) {
if (!context.fAbandoned) {
if (context.fGLContext) {
context.fGLContext->makeCurrent();
context.fGLContext->testAbandon();
delete(context.fGLContext);
context.fGLContext = nullptr;
if (context.fTestContext) {
context.fTestContext->makeCurrent();
context.fTestContext->testAbandon();
delete(context.fTestContext);
context.fTestContext = nullptr;
}
context.fGrContext->abandonContext();
context.fAbandoned = true;
@ -70,14 +70,14 @@ void GrContextFactory::abandonContexts() {
void GrContextFactory::releaseResourcesAndAbandonContexts() {
for (Context& context : fContexts) {
if (!context.fAbandoned) {
if (context.fGLContext) {
context.fGLContext->makeCurrent();
if (context.fTestContext) {
context.fTestContext->makeCurrent();
}
context.fGrContext->releaseResourcesAndAbandonContext();
context.fAbandoned = true;
if (context.fGLContext) {
delete context.fGLContext;
context.fGLContext = nullptr;
if (context.fTestContext) {
delete context.fTestContext;
context.fTestContext = nullptr;
}
}
}
@ -97,61 +97,58 @@ ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOptions op
if (context.fType == type &&
context.fOptions == options &&
!context.fAbandoned) {
if (context.fGLContext) {
context.fGLContext->makeCurrent();
}
return ContextInfo(context.fGrContext, context.fGLContext);
context.fTestContext->makeCurrent();
return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext);
}
}
SkAutoTDelete<GLTestContext> glCtx;
SkAutoTDelete<TestContext> testCtx;
sk_sp<GrContext> grCtx;
GrBackendContext backendContext = 0;
sk_sp<const GrGLInterface> glInterface;
#ifdef SK_VULKAN
sk_sp<const GrVkBackendContext> vkBackend;
#endif
GrBackend backend = ContextTypeBackend(type);
switch (backend) {
case kOpenGL_GrBackend:
case kOpenGL_GrBackend: {
GLTestContext* glCtx;
switch (type) {
case kGL_ContextType:
glCtx.reset(CreatePlatformGLTestContext(kGL_GrGLStandard));
glCtx = CreatePlatformGLTestContext(kGL_GrGLStandard);
break;
case kGLES_ContextType:
glCtx.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
glCtx = CreatePlatformGLTestContext(kGLES_GrGLStandard);
break;
#if SK_ANGLE
# ifdef SK_BUILD_FOR_WIN
case kANGLE_ContextType:
glCtx.reset(CreateANGLEDirect3DGLTestContext());
glCtx = CreateANGLEDirect3DGLTestContext();
break;
# endif
case kANGLE_GL_ContextType:
glCtx.reset(CreateANGLEOpenGLGLTestContext());
glCtx = CreateANGLEOpenGLGLTestContext();
break;
#endif
#if SK_COMMAND_BUFFER
case kCommandBuffer_ContextType:
glCtx.reset(CommandBufferGLTestContext::Create());
glCtx = CommandBufferGLTestContext::Create();
break;
#endif
#if SK_MESA
case kMESA_ContextType:
glCtx.reset(CreateMesaGLTestContext());
glCtx = CreateMesaGLTestContext();
break;
#endif
case kNullGL_ContextType:
glCtx.reset(CreateNullGLTestContext(kEnableNVPR_ContextOptions & options));
glCtx = CreateNullGLTestContext(kEnableNVPR_ContextOptions & options);
break;
case kDebugGL_ContextType:
glCtx.reset(CreateDebugGLTestContext());
glCtx = CreateDebugGLTestContext();
break;
default:
return ContextInfo();
}
if (nullptr == glCtx.get()) {
if (!glCtx) {
return ContextInfo();
}
testCtx.reset(glCtx);
glInterface.reset(SkRef(glCtx->gl()));
// Block NVPR from non-NVPR types.
if (!(kEnableNVPR_ContextOptions & options)) {
@ -161,8 +158,8 @@ ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOptions op
}
}
backendContext = reinterpret_cast<GrBackendContext>(glInterface.get());
glCtx->makeCurrent();
break;
}
#ifdef SK_VULKAN
case kVulkan_GrBackend:
SkASSERT(kVulkan_ContextType == type);
@ -170,11 +167,11 @@ ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOptions op
(kRequireSRGBSupport_ContextOptions & options)) {
return ContextInfo();
}
vkBackend.reset(GrVkBackendContext::Create());
if (!vkBackend) {
testCtx.reset(CreatePlatformVkTestContext());
if (!testCtx) {
return ContextInfo();
}
backendContext = reinterpret_cast<GrBackendContext>(vkBackend.get());
// There is some bug (either in Skia or the NV Vulkan driver) where VkDevice
// destruction will hang occaisonally. For some reason having an existing GL
// context fixes this.
@ -184,12 +181,14 @@ ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOptions op
fSentinelGLContext.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
}
}
backendContext = testCtx->backendContext();
break;
#endif
default:
return ContextInfo();
}
testCtx->makeCurrent();
SkASSERT(testCtx && testCtx->backend() == backend);
grCtx.reset(GrContext::Create(backend, backendContext, fGlobalOptions));
if (!grCtx.get()) {
return ContextInfo();
@ -206,11 +205,12 @@ ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOptions op
}
Context& context = fContexts.push_back();
context.fGLContext = glCtx.release();
context.fBackend = backend;
context.fTestContext = testCtx.release();
context.fGrContext = SkRef(grCtx.get());
context.fType = type;
context.fOptions = options;
context.fAbandoned = false;
return ContextInfo(context.fGrContext, context.fGLContext);
return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext);
}
} // namespace sk_gpu_test

View File

@ -12,6 +12,7 @@
#include "GrContextOptions.h"
#include "gl/GLTestContext.h"
#include "vk/VkTestContext.h"
#include "SkTArray.h"
struct GrVkBackendContext;
@ -20,17 +21,35 @@ namespace sk_gpu_test {
class ContextInfo {
public:
ContextInfo() = default;
ContextInfo& operator=(const ContextInfo&) = default;
GrBackend backend() const { return fBackend; };
GrContext* grContext() const { return fGrContext; }
GLTestContext* glContext() const { return fGLContext; }
GLTestContext* glContext() const {
SkASSERT(kOpenGL_GrBackend == fBackend);
return static_cast<GLTestContext*>(fTestContext);
}
#ifdef SK_VULKAN
VkTestContext* vkContext() const {
SkASSERT(kVulkan_GrBackend == fBackend);
return static_cast<VkTestContext*>(fTestContext);
}
#endif
private:
ContextInfo()
: fGrContext(nullptr), fGLContext(nullptr) { }
ContextInfo(GrContext* grContext, GLTestContext* glContext)
: fGrContext(grContext), fGLContext(glContext) { }
GrContext* fGrContext;
GLTestContext* fGLContext; //! Valid until the factory destroys it via abandonContexts() or
//! destroyContexts(). Null if context is not based on OpenGL.
ContextInfo(GrBackend backend, TestContext* testContext, GrContext* grContext)
: fBackend(backend)
, fTestContext(testContext)
, fGrContext(grContext) {}
GrBackend fBackend = kOpenGL_GrBackend;
// Valid until the factory destroys it via abandonContexts() or destroyContexts().
TestContext* fTestContext = nullptr;
GrContext* fGrContext = nullptr;
friend class GrContextFactory;
};
@ -134,7 +153,7 @@ public:
* Get a GrContext initialized with a type of GL context. It also makes the GL context current.
*/
GrContext* get(ContextType type, ContextOptions options = kNone_ContextOptions) {
return this->getContextInfo(type, options).fGrContext;
return this->getContextInfo(type, options).grContext();
}
const GrContextOptions& getGlobalOptions() const { return fGlobalOptions; }
@ -142,7 +161,8 @@ private:
struct Context {
ContextType fType;
ContextOptions fOptions;
GLTestContext* fGLContext; // null if non-GL
GrBackend fBackend;
TestContext* fTestContext;
GrContext* fGrContext;
bool fAbandoned;
};

67
tools/gpu/TestContext.cpp Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "TestContext.h"
namespace sk_gpu_test {
TestContext::TestContext() : fFenceSync(nullptr), fCurrentFenceIdx(0) {
memset(fFrameFences, 0, sizeof(fFrameFences));
}
TestContext::~TestContext() {
// Subclass should call teardown.
#ifdef SK_DEBUG
for (size_t i = 0; i < SK_ARRAY_COUNT(fFrameFences); i++) {
SkASSERT(0 == fFrameFences[i]);
}
#endif
SkASSERT(!fFenceSync);
}
void TestContext::makeCurrent() const { this->onPlatformMakeCurrent(); }
void TestContext::swapBuffers() { this->onPlatformSwapBuffers(); }
void TestContext::waitOnSyncOrSwap() {
if (!fFenceSync) {
// Fallback on the platform SwapBuffers method for synchronization. This may have no effect.
this->swapBuffers();
return;
}
if (fFrameFences[fCurrentFenceIdx]) {
if (!fFenceSync->waitFence(fFrameFences[fCurrentFenceIdx], true)) {
SkDebugf("WARNING: Wait failed for fence sync. Timings might not be accurate.\n");
}
fFenceSync->deleteFence(fFrameFences[fCurrentFenceIdx]);
}
fFrameFences[fCurrentFenceIdx] = fFenceSync->insertFence();
fCurrentFenceIdx = (fCurrentFenceIdx + 1) % SK_ARRAY_COUNT(fFrameFences);
}
void TestContext::testAbandon() {
if (fFenceSync) {
memset(fFrameFences, 0, sizeof(fFrameFences));
}
}
void TestContext::teardown() {
if (fFenceSync) {
for (size_t i = 0; i < SK_ARRAY_COUNT(fFrameFences); i++) {
if (fFrameFences[i]) {
fFenceSync->deleteFence(fFrameFences[i]);
fFrameFences[i] = 0;
}
}
delete fFenceSync;
fFenceSync = nullptr;
}
}
}

95
tools/gpu/TestContext.h Normal file
View File

@ -0,0 +1,95 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef TestContext_DEFINED
#define TestContext_DEFINED
#include "GrTypes.h"
#include "../private/SkGpuFenceSync.h"
#include "../private/SkTemplates.h"
namespace sk_gpu_test {
/**
* An offscreen 3D context. This class is intended for Skia's internal testing needs and not
* for general use.
*/
class TestContext : public SkNoncopyable {
public:
virtual ~TestContext();
virtual bool isValid() const = 0;
bool fenceSyncSupport() const { return fFenceSync != nullptr; }
bool getMaxGpuFrameLag(int *maxFrameLag) const {
if (!fFenceSync) {
return false;
}
*maxFrameLag = kMaxFrameLag;
return true;
}
void makeCurrent() const;
virtual GrBackend backend() = 0;
virtual GrBackendContext backendContext() = 0;
/** Swaps front and back buffer (if the context has such buffers) */
void swapBuffers();
/**
* The only purpose of this function it to provide a means of scheduling
* work on the GPU (since all of the subclasses create primary buffers for
* testing that are small and not meant to be rendered to the screen).
*
* If the platform supports fence syncs (OpenGL 3.2+ or EGL_KHR_fence_sync),
* this will not swap any buffers, but rather emulate triple buffer synchronization
* using fences.
*
* Otherwise it will call the platform SwapBuffers method. This may or may
* not perform some sort of synchronization, depending on whether the
* drawing surface provided by the platform is double buffered.
*/
void waitOnSyncOrSwap();
/**
* This notifies the context that we are deliberately testing abandoning
* the context. It is useful for debugging contexts that would otherwise
* test that GPU resources are properly deleted. It also allows a debugging
* context to test that further API calls are not made by Skia GPU code.
*/
virtual void testAbandon();
/**
* returns the fencesync object owned by this GLTestContext
*/
SkGpuFenceSync *fenceSync() { return fFenceSync; }
protected:
SkGpuFenceSync* fFenceSync;
TestContext();
/** This should destroy the 3D context. */
virtual void teardown();
virtual void onPlatformMakeCurrent() const = 0;
virtual void onPlatformSwapBuffers() const = 0;
private:
enum {
kMaxFrameLag = 3
};
SkPlatformGpuFence fFrameFences[kMaxFrameLag - 1];
int fCurrentFenceIdx;
typedef SkNoncopyable INHERITED;
};
} // namespace sk_gpu_test
#endif

View File

@ -1,13 +1,12 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GLTestContext.h"
#include "gl/GrGLUtil.h"
#include "SkGpuFenceSync.h"
namespace sk_gpu_test {
class GLTestContext::GLFenceSync : public SkGpuFenceSync {
@ -38,75 +37,28 @@ private:
typedef SkGpuFenceSync INHERITED;
};
GLTestContext::GLTestContext()
: fCurrentFenceIdx(0) {
memset(fFrameFences, 0, sizeof(fFrameFences));
}
GLTestContext::GLTestContext() : TestContext() {}
GLTestContext::~GLTestContext() {
// Subclass should call teardown.
#ifdef SK_DEBUG
for (size_t i = 0; i < SK_ARRAY_COUNT(fFrameFences); i++) {
SkASSERT(0 == fFrameFences[i]);
}
#endif
SkASSERT(nullptr == fGL.get());
SkASSERT(nullptr == fFenceSync.get());
}
void GLTestContext::init(const GrGLInterface* gl, SkGpuFenceSync* fenceSync) {
SkASSERT(!fGL.get());
fGL.reset(gl);
fFenceSync.reset(fenceSync ? fenceSync : GLFenceSync::CreateIfSupported(this));
fFenceSync = fenceSync ? fenceSync : GLFenceSync::CreateIfSupported(this);
}
void GLTestContext::teardown() {
if (fFenceSync) {
for (size_t i = 0; i < SK_ARRAY_COUNT(fFrameFences); i++) {
if (fFrameFences[i]) {
fFenceSync->deleteFence(fFrameFences[i]);
fFrameFences[i] = 0;
}
}
fFenceSync.reset(nullptr);
}
fGL.reset(nullptr);
}
void GLTestContext::makeCurrent() const {
this->onPlatformMakeCurrent();
}
void GLTestContext::swapBuffers() {
this->onPlatformSwapBuffers();
}
void GLTestContext::waitOnSyncOrSwap() {
if (!fFenceSync) {
// Fallback on the platform SwapBuffers method for synchronization. This may have no effect.
this->swapBuffers();
return;
}
if (fFrameFences[fCurrentFenceIdx]) {
if (!fFenceSync->waitFence(fFrameFences[fCurrentFenceIdx], true)) {
SkDebugf("WARNING: Wait failed for fence sync. Timings might not be accurate.\n");
}
fFenceSync->deleteFence(fFrameFences[fCurrentFenceIdx]);
}
fFrameFences[fCurrentFenceIdx] = fFenceSync->insertFence();
fCurrentFenceIdx = (fCurrentFenceIdx + 1) % SK_ARRAY_COUNT(fFrameFences);
INHERITED::teardown();
}
void GLTestContext::testAbandon() {
INHERITED::testAbandon();
if (fGL) {
fGL->abandon();
}
if (fFenceSync) {
memset(fFrameFences, 0, sizeof(fFrameFences));
}
}
GLTestContext::GLFenceSync* GLTestContext::GLFenceSync::CreateIfSupported(const GLTestContext* ctx) {

View File

@ -8,34 +8,26 @@
#ifndef GLTestContext_DEFINED
#define GLTestContext_DEFINED
#include "TestContext.h"
#include "gl/GrGLInterface.h"
#include "../private/SkGpuFenceSync.h"
namespace sk_gpu_test {
/**
* Create an offscreen Oppengl context. Provides a GrGLInterface struct of function pointers for
* the context. This class is intended for Skia's internal testing needs and not for general use.
* An offscreen OpenGL context. Provides a GrGLInterface struct of function pointers for the context
* This class is intended for Skia's internal testing needs and not for general use.
*/
class GLTestContext : public SkNoncopyable {
class GLTestContext : public TestContext {
public:
virtual ~GLTestContext();
bool isValid() const { return NULL != gl(); }
const GrGLInterface *gl() const { return fGL.get(); }
bool fenceSyncSupport() const { return fFenceSync != nullptr; }
bool getMaxGpuFrameLag(int *maxFrameLag) const {
if (!fFenceSync) {
return false;
}
*maxFrameLag = kMaxFrameLag;
return true;
virtual GrBackend backend() override { return kOpenGL_GrBackend; }
virtual GrBackendContext backendContext() override {
return reinterpret_cast<GrBackendContext>(fGL.get());
}
void makeCurrent() const;
bool isValid() const override { return SkToBool(this->gl()); }
const GrGLInterface *gl() const { return fGL.get(); }
/** Used for testing EGLImage integration. Take a GL_TEXTURE_2D and wraps it in an EGL Image */
virtual GrEGLImage texture2DToEGLImage(GrGLuint /*texID*/) const { return 0; }
@ -53,30 +45,7 @@ public:
*/
virtual GrGLuint eglImageToExternalTexture(GrEGLImage) const { return 0; }
void swapBuffers();
/**
* The only purpose of this function it to provide a means of scheduling
* work on the GPU (since all of the subclasses create primary buffers for
* testing that are small and not meant to be rendered to the screen).
*
* If the platform supports fence sync (OpenGL 3.2+ or EGL_KHR_fence_sync),
* this will not swap any buffers, but rather emulate triple buffer
* synchronization using fences.
*
* Otherwise it will call the platform SwapBuffers method. This may or may
* not perform some sort of synchronization, depending on whether the
* drawing surface provided by the platform is double buffered.
*/
void waitOnSyncOrSwap();
/**
* This notifies the context that we are deliberately testing abandoning
* the context. It is useful for debugging contexts that would otherwise
* test that GPU resources are properly deleted. It also allows a debugging
* context to test that further GL calls are not made by Skia GPU code.
*/
void testAbandon();
void testAbandon() override;
/**
* Creates a new GL context of the same type and makes the returned context current
@ -84,13 +53,6 @@ public:
*/
virtual GLTestContext *createNew() const { return nullptr; }
class GLFenceSync; // SkGpuFenceSync implementation that uses the OpenGL functionality.
/*
* returns the fencesync object owned by this GLTestContext
*/
SkGpuFenceSync *fenceSync() { return fFenceSync.get(); }
protected:
GLTestContext();
@ -99,43 +61,30 @@ protected:
*/
void init(const GrGLInterface *, SkGpuFenceSync * = NULL);
void teardown();
/*
* Operations that have a platform-dependent implementation.
*/
virtual void onPlatformMakeCurrent() const = 0;
virtual void onPlatformSwapBuffers() const = 0;
void teardown() override;
virtual GrGLFuncPtr onPlatformGetProcAddress(const char *) const = 0;
private:
enum {
kMaxFrameLag = 3
};
SkAutoTDelete <SkGpuFenceSync> fFenceSync;
SkPlatformGpuFence fFrameFences[kMaxFrameLag - 1];
int fCurrentFenceIdx;
class GLFenceSync; // SkGpuFenceSync implementation that uses the OpenGL functionality.
/** Subclass provides the gl interface object if construction was
* successful. */
SkAutoTUnref<const GrGLInterface> fGL;
friend class GLFenceSync; // For onPlatformGetProcAddress.
typedef TestContext INHERITED;
};
/** Creates platform-dependent GL context object. The shareContext parameter is in an optional
/**
* Creates platform-dependent GL context object. The shareContext parameter is in an optional
* context with which to share display lists. This should be a pointer to an GLTestContext created
* with SkCreatePlatformGLTestContext. NULL indicates that no sharing is to take place. Returns a valid
* gl context object or NULL if such can not be created.
* Note: If Skia embedder needs a custom GL context that sets up the GL interface, this function
* should be implemented by the embedder. Otherwise, the default implementation for the platform
* should be compiled in the library.
* with SkCreatePlatformGLTestContext. NULL indicates that no sharing is to take place. Returns a
* valid gl context object or NULL if such can not be created.
*/
GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI, GLTestContext *shareContext = nullptr);
GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
GLTestContext *shareContext = nullptr);
} // namespace sk_gpu_test
#endif

View File

@ -0,0 +1,40 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "VkTestContext.h"
#ifdef SK_VULKAN
namespace {
// TODO: Implement fence syncs and swap buffers
class VkTestContextImpl : public sk_gpu_test::VkTestContext {
public:
VkTestContextImpl()
: VkTestContext(sk_sp<const GrVkBackendContext>(GrVkBackendContext::Create())) {}
~VkTestContextImpl() override { this->teardown(); }
void testAbandon() override {}
protected:
void teardown() override { fVk.reset(nullptr); }
private:
void onPlatformMakeCurrent() const override {}
void onPlatformSwapBuffers() const override {}
typedef sk_gpu_test::VkTestContext INHERITED;
};
}
namespace sk_gpu_test {
VkTestContext* CreatePlatformVkTestContext() {
return new VkTestContextImpl;
}
} // namespace sk_gpu_test
#endif

View File

@ -0,0 +1,47 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef VkTestContext_DEFINED
#define VkTestContext_DEFINED
#include "TestContext.h"
#ifdef SK_VULKAN
#include "vk/GrVkBackendContext.h"
namespace sk_gpu_test {
class VkTestContext : public TestContext {
public:
virtual GrBackend backend() override { return kVulkan_GrBackend; }
virtual GrBackendContext backendContext() override {
return reinterpret_cast<GrBackendContext>(fVk.get());
}
bool isValid() const override { return NULL != this->vk(); }
const GrVkInterface* vk() const { return fVk->fInterface; };
protected:
VkTestContext(sk_sp<const GrVkBackendContext> vk) : fVk(std::move(vk)) {};
sk_sp<const GrVkBackendContext> fVk;
private:
typedef TestContext INHERITED;
};
/**
* Creates Vk context object bound to the native Vk library.
*/
VkTestContext* CreatePlatformVkTestContext();
} // namespace sk_gpu_test
#endif
#endif