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:
parent
393c2ff0d2
commit
18a2f9dff8
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
67
tools/gpu/TestContext.cpp
Normal 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
95
tools/gpu/TestContext.h
Normal 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
|
@ -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) {
|
||||
|
@ -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
|
||||
|
40
tools/gpu/vk/VkTestContext.cpp
Normal file
40
tools/gpu/vk/VkTestContext.cpp
Normal 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
|
47
tools/gpu/vk/VkTestContext.h
Normal file
47
tools/gpu/vk/VkTestContext.h
Normal 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
|
Loading…
Reference in New Issue
Block a user