11abd8d6cb
Update the ANGLE test GL context, GrContextFactory, and config parsing to allow explicit control of ANGLE front/backend. This will allow us to explicitly test ES2 vs ES3 interfaces to ANGLE as well as D3D9, D3D11, and OpenGL backends. Also makes the angle api types valid in all builds (but will just fail when SK_ANGLE=1 or not on windows for the d3d backends). BUG=skia:5804 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2381033002 CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Win-MSVC-ShuttleC-GPU-GTX960-x86_64-Debug-ANGLE-Trybot Review-Url: https://codereview.chromium.org/2381033002
235 lines
8.4 KiB
C++
235 lines
8.4 KiB
C++
|
|
/*
|
|
* Copyright 2014 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "GrContextFactory.h"
|
|
#include "gl/GLTestContext.h"
|
|
|
|
#if SK_ANGLE
|
|
#include "gl/angle/GLTestContext_angle.h"
|
|
#endif
|
|
#include "gl/command_buffer/GLTestContext_command_buffer.h"
|
|
#include "gl/debug/DebugGLTestContext.h"
|
|
#if SK_MESA
|
|
#include "gl/mesa/GLTestContext_mesa.h"
|
|
#endif
|
|
#ifdef SK_VULKAN
|
|
#include "vk/VkTestContext.h"
|
|
#endif
|
|
#include "gl/null/NullGLTestContext.h"
|
|
#include "gl/GrGLGpu.h"
|
|
#include "GrCaps.h"
|
|
|
|
namespace sk_gpu_test {
|
|
GrContextFactory::GrContextFactory() { }
|
|
|
|
GrContextFactory::GrContextFactory(const GrContextOptions& opts)
|
|
: fGlobalOptions(opts) {
|
|
// In this factory, instanced rendering is specified with ContextOptions::kUseInstanced.
|
|
SkASSERT(!fGlobalOptions.fEnableInstancedRendering);
|
|
}
|
|
|
|
GrContextFactory::~GrContextFactory() {
|
|
this->destroyContexts();
|
|
}
|
|
|
|
void GrContextFactory::destroyContexts() {
|
|
for (Context& context : fContexts) {
|
|
if (context.fTestContext) {
|
|
context.fTestContext->makeCurrent();
|
|
}
|
|
if (!context.fGrContext->unique()) {
|
|
context.fGrContext->releaseResourcesAndAbandonContext();
|
|
context.fAbandoned = true;
|
|
}
|
|
context.fGrContext->unref();
|
|
delete context.fTestContext;
|
|
}
|
|
fContexts.reset();
|
|
}
|
|
|
|
void GrContextFactory::abandonContexts() {
|
|
for (Context& context : fContexts) {
|
|
if (!context.fAbandoned) {
|
|
if (context.fTestContext) {
|
|
context.fTestContext->makeCurrent();
|
|
context.fTestContext->testAbandon();
|
|
delete(context.fTestContext);
|
|
context.fTestContext = nullptr;
|
|
}
|
|
context.fGrContext->abandonContext();
|
|
context.fAbandoned = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GrContextFactory::releaseResourcesAndAbandonContexts() {
|
|
for (Context& context : fContexts) {
|
|
if (!context.fAbandoned) {
|
|
if (context.fTestContext) {
|
|
context.fTestContext->makeCurrent();
|
|
}
|
|
context.fGrContext->releaseResourcesAndAbandonContext();
|
|
context.fAbandoned = true;
|
|
if (context.fTestContext) {
|
|
delete context.fTestContext;
|
|
context.fTestContext = nullptr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
|
|
const GrContextFactory::ContextType GrContextFactory::kNativeGL_ContextType =
|
|
GrContextFactory::kGL_ContextType;
|
|
#else
|
|
const GrContextFactory::ContextType GrContextFactory::kNativeGL_ContextType =
|
|
GrContextFactory::kGLES_ContextType;
|
|
#endif
|
|
|
|
ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOptions options) {
|
|
for (int i = 0; i < fContexts.count(); ++i) {
|
|
Context& context = fContexts[i];
|
|
if (context.fType == type &&
|
|
context.fOptions == options &&
|
|
!context.fAbandoned) {
|
|
context.fTestContext->makeCurrent();
|
|
return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext);
|
|
}
|
|
}
|
|
SkAutoTDelete<TestContext> testCtx;
|
|
sk_sp<GrContext> grCtx;
|
|
GrBackendContext backendContext = 0;
|
|
sk_sp<const GrGLInterface> glInterface;
|
|
GrBackend backend = ContextTypeBackend(type);
|
|
switch (backend) {
|
|
case kOpenGL_GrBackend: {
|
|
GLTestContext* glCtx;
|
|
switch (type) {
|
|
case kGL_ContextType:
|
|
glCtx = CreatePlatformGLTestContext(kGL_GrGLStandard);
|
|
break;
|
|
case kGLES_ContextType:
|
|
glCtx = CreatePlatformGLTestContext(kGLES_GrGLStandard);
|
|
break;
|
|
#if SK_ANGLE
|
|
case kANGLE_D3D9_ES2_ContextType:
|
|
glCtx = CreateANGLETestContext(ANGLEBackend::kD3D9, ANGLEContextVersion::kES2);
|
|
break;
|
|
case kANGLE_D3D11_ES2_ContextType:
|
|
glCtx = CreateANGLETestContext(ANGLEBackend::kD3D11,
|
|
ANGLEContextVersion::kES2);
|
|
break;
|
|
case kANGLE_D3D11_ES3_ContextType:
|
|
glCtx = CreateANGLETestContext(ANGLEBackend::kD3D11,
|
|
ANGLEContextVersion::kES3);
|
|
break;
|
|
case kANGLE_GL_ES2_ContextType:
|
|
glCtx = CreateANGLETestContext(ANGLEBackend::kOpenGL,
|
|
ANGLEContextVersion::kES2);
|
|
break;
|
|
case kANGLE_GL_ES3_ContextType:
|
|
glCtx = CreateANGLETestContext(ANGLEBackend::kOpenGL,
|
|
ANGLEContextVersion::kES3);
|
|
break;
|
|
#endif
|
|
case kCommandBuffer_ContextType:
|
|
glCtx = CommandBufferGLTestContext::Create();
|
|
break;
|
|
#if SK_MESA
|
|
case kMESA_ContextType:
|
|
glCtx = CreateMesaGLTestContext();
|
|
break;
|
|
#endif
|
|
case kNullGL_ContextType:
|
|
glCtx = CreateNullGLTestContext(ContextOptions::kEnableNVPR & options);
|
|
break;
|
|
case kDebugGL_ContextType:
|
|
glCtx = CreateDebugGLTestContext();
|
|
break;
|
|
default:
|
|
return ContextInfo();
|
|
}
|
|
if (!glCtx) {
|
|
return ContextInfo();
|
|
}
|
|
testCtx.reset(glCtx);
|
|
glInterface.reset(SkRef(glCtx->gl()));
|
|
// Block NVPR from non-NVPR types. We don't block NVPR from contexts that will use
|
|
// instanced rendering because that would prevent us from testing mixed samples.
|
|
if (!((ContextOptions::kEnableNVPR | ContextOptions::kUseInstanced) & options)) {
|
|
glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface.get()));
|
|
if (!glInterface) {
|
|
return ContextInfo();
|
|
}
|
|
}
|
|
backendContext = reinterpret_cast<GrBackendContext>(glInterface.get());
|
|
break;
|
|
}
|
|
#ifdef SK_VULKAN
|
|
case kVulkan_GrBackend:
|
|
SkASSERT(kVulkan_ContextType == type);
|
|
if (ContextOptions::kEnableNVPR & options) {
|
|
return ContextInfo();
|
|
}
|
|
testCtx.reset(CreatePlatformVkTestContext());
|
|
if (!testCtx) {
|
|
return ContextInfo();
|
|
}
|
|
|
|
// 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.
|
|
if (!fSentinelGLContext) {
|
|
fSentinelGLContext.reset(CreatePlatformGLTestContext(kGL_GrGLStandard));
|
|
if (!fSentinelGLContext) {
|
|
fSentinelGLContext.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
|
|
}
|
|
}
|
|
backendContext = testCtx->backendContext();
|
|
break;
|
|
#endif
|
|
default:
|
|
return ContextInfo();
|
|
}
|
|
testCtx->makeCurrent();
|
|
SkASSERT(testCtx && testCtx->backend() == backend);
|
|
GrContextOptions grOptions = fGlobalOptions;
|
|
if (ContextOptions::kUseInstanced & options) {
|
|
grOptions.fEnableInstancedRendering = true;
|
|
}
|
|
grCtx.reset(GrContext::Create(backend, backendContext, grOptions));
|
|
if (!grCtx.get()) {
|
|
return ContextInfo();
|
|
}
|
|
if (ContextOptions::kEnableNVPR & options) {
|
|
if (!grCtx->caps()->shaderCaps()->pathRenderingSupport()) {
|
|
return ContextInfo();
|
|
}
|
|
}
|
|
if (ContextOptions::kUseInstanced & options) {
|
|
if (GrCaps::InstancedSupport::kNone == grCtx->caps()->instancedSupport()) {
|
|
return ContextInfo();
|
|
}
|
|
}
|
|
if (ContextOptions::kRequireSRGBSupport & options) {
|
|
if (!grCtx->caps()->srgbSupport()) {
|
|
return ContextInfo();
|
|
}
|
|
}
|
|
|
|
Context& context = fContexts.push_back();
|
|
context.fBackend = backend;
|
|
context.fTestContext = testCtx.release();
|
|
context.fGrContext = SkRef(grCtx.get());
|
|
context.fType = type;
|
|
context.fOptions = options;
|
|
context.fAbandoned = false;
|
|
return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext);
|
|
}
|
|
} // namespace sk_gpu_test
|