diff --git a/tools/flags/CommonFlagsConfig.cpp b/tools/flags/CommonFlagsConfig.cpp index 7b8d071d1f..7856302615 100644 --- a/tools/flags/CommonFlagsConfig.cpp +++ b/tools/flags/CommonFlagsConfig.cpp @@ -37,6 +37,7 @@ static const struct { } gPredefinedConfigs[] = { { "gl", "gpu", "api=gl" }, { "gles", "gpu", "api=gles" }, + { "glesfakev2", "gpu", "api=glesfakev2" }, { "glmsaa4", "gpu", "api=gl,samples=4" }, { "glmsaa8" , "gpu", "api=gl,samples=8" }, { "glesmsaa4", "gpu", "api=gles,samples=4" }, @@ -145,6 +146,7 @@ static const char configExtendedHelp[] = "\t Options:\n" "\t\tgl \t\t\tUse OpenGL.\n" "\t\tgles \t\t\tUse OpenGL ES.\n" + "\t\tglesfakev2 \t\t\tUse OpenGL ES with version faked as 2.0.\n" "\t\tnullgl \t\t\tUse null OpenGL.\n" "\t\tangle_d3d9_es2\t\tUse OpenGL ES2 on the ANGLE Direct3D9 backend.\n" "\t\tangle_d3d11_es2\t\tUse OpenGL ES2 on the ANGLE Direct3D11 backend.\n" @@ -235,7 +237,9 @@ static bool parse_option_bool(const SkString& value, bool* outBool) { return false; } static bool parse_option_gpu_api(const SkString& value, - SkCommandLineConfigGpu::ContextType* outContextType) { + SkCommandLineConfigGpu::ContextType* outContextType, + bool* outFakeGLESVersion2) { + *outFakeGLESVersion2 = false; if (value.equals("gl")) { *outContextType = GrContextFactory::kGL_ContextType; return true; @@ -244,6 +248,11 @@ static bool parse_option_gpu_api(const SkString& value, *outContextType = GrContextFactory::kGLES_ContextType; return true; } + if (value.equals("glesfakev2")) { + *outContextType = GrContextFactory::kGLES_ContextType; + *outFakeGLESVersion2 = true; + return true; + } if (value.equals("angle_d3d9_es2")) { *outContextType = GrContextFactory::kANGLE_D3D9_ES2_ContextType; return true; @@ -413,12 +422,13 @@ public: bool get_option_gpu_api(const char* optionKey, SkCommandLineConfigGpu::ContextType* outContextType, + bool* outFakeGLESVersion2, bool optional = true) const { SkString* optionValue = fOptionsMap.find(SkString(optionKey)); if (optionValue == nullptr) { return optional; } - return parse_option_gpu_api(*optionValue, outContextType); + return parse_option_gpu_api(*optionValue, outContextType, outFakeGLESVersion2); } bool get_option_gpu_surf_type(const char* optionKey, @@ -454,6 +464,7 @@ private: SkCommandLineConfigGpu::SkCommandLineConfigGpu(const SkString& tag, const SkTArray& viaParts, ContextType contextType, + bool fakeGLESVersion2, bool useDIText, int samples, SkColorType colorType, @@ -483,6 +494,9 @@ SkCommandLineConfigGpu::SkCommandLineConfigGpu(const SkString& tag, if (!useStencilBuffers) { fContextOverrides |= ContextOverrides::kAvoidStencilBuffers; } + if (fakeGLESVersion2) { + fContextOverrides |= ContextOverrides::kFakeGLESVersionAs2; + } } SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString& tag, @@ -501,6 +515,7 @@ SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString& bool testPrecompile = false; bool useDDLs = false; bool ooprish = false; + bool fakeGLESVersion2 = false; SkCommandLineConfigGpu::SurfType surfType = SkCommandLineConfigGpu::SurfType::kDefault; bool parseSucceeded = false; @@ -510,7 +525,7 @@ SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString& } bool validOptions = - extendedOptions.get_option_gpu_api("api", &contextType, false) && + extendedOptions.get_option_gpu_api("api", &contextType, &fakeGLESVersion2, false) && extendedOptions.get_option_bool("dit", &useDIText) && extendedOptions.get_option_int("samples", &samples) && extendedOptions.get_option_gpu_color("color", &colorType, &alphaType, &colorSpace) && @@ -530,6 +545,7 @@ SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString& return new SkCommandLineConfigGpu(tag, vias, contextType, + fakeGLESVersion2, useDIText, samples, colorType, diff --git a/tools/flags/CommonFlagsConfig.h b/tools/flags/CommonFlagsConfig.h index 02bd8569a4..74bd20a617 100644 --- a/tools/flags/CommonFlagsConfig.h +++ b/tools/flags/CommonFlagsConfig.h @@ -54,6 +54,7 @@ public: SkCommandLineConfigGpu(const SkString& tag, const SkTArray& viaParts, ContextType contextType, + bool fakeGLESVer2, bool useDIText, int samples, SkColorType colorType, diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp index dc4aa8fa62..c6e18e4841 100644 --- a/tools/gpu/GrContextFactory.cpp +++ b/tools/gpu/GrContextFactory.cpp @@ -223,6 +223,10 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv if (!glCtx) { return ContextInfo(); } + if (glCtx->gl()->fStandard == kGLES_GrGLStandard && + (overrides & ContextOverrides::kFakeGLESVersionAs2)) { + glCtx->overrideVersion("OpenGL ES 2.0", "OpenGL ES GLSL ES 1.00"); + } testCtx.reset(glCtx); break; } diff --git a/tools/gpu/GrContextFactory.h b/tools/gpu/GrContextFactory.h index 4f669fa554..38471ce096 100644 --- a/tools/gpu/GrContextFactory.h +++ b/tools/gpu/GrContextFactory.h @@ -56,6 +56,7 @@ public: enum class ContextOverrides { kNone = 0x0, kAvoidStencilBuffers = 0x1, + kFakeGLESVersionAs2 = 0x2, }; static bool IsRenderingContext(ContextType type) { diff --git a/tools/gpu/gl/GLTestContext.cpp b/tools/gpu/gl/GLTestContext.cpp index 5b5ce3f05e..9291f86a88 100644 --- a/tools/gpu/gl/GLTestContext.cpp +++ b/tools/gpu/gl/GLTestContext.cpp @@ -156,7 +156,8 @@ namespace sk_gpu_test { GLTestContext::GLTestContext() : TestContext() {} GLTestContext::~GLTestContext() { - SkASSERT(nullptr == fGL.get()); + SkASSERT(!fGLInterface); + SkASSERT(!fOriginalGLInterface); } bool GLTestContext::isValid() const { @@ -192,7 +193,8 @@ static bool fence_is_supported(const GLTestContext* ctx) { } void GLTestContext::init(sk_sp gl) { - fGL = std::move(gl); + fGLInterface = std::move(gl); + fOriginalGLInterface = fGLInterface; fFenceSupport = fence_is_supported(this); fGpuTimer = GLGpuTimer::MakeIfSupported(this); #ifndef SK_GL @@ -201,30 +203,52 @@ void GLTestContext::init(sk_sp gl) { } void GLTestContext::teardown() { - fGL.reset(nullptr); + fGLInterface.reset(); + fOriginalGLInterface.reset(); INHERITED::teardown(); } void GLTestContext::testAbandon() { INHERITED::testAbandon(); #ifdef SK_GL - if (fGL) { - fGL->abandon(); + if (fGLInterface) { + fGLInterface->abandon(); + fOriginalGLInterface->abandon(); } #endif } void GLTestContext::finish() { #ifdef SK_GL - if (fGL) { - GR_GL_CALL(fGL.get(), Finish()); + if (fGLInterface) { + GR_GL_CALL(fGLInterface.get(), Finish()); } #endif } +void GLTestContext::overrideVersion(const char* version, const char* shadingLanguageVersion) { +#ifdef SK_GL + // GrGLFunction has both a limited capture size and doesn't call a destructor when it is + // initialized with a lambda. So here we're trusting fOriginalGLInterface will be kept alive. + auto getString = [wrapped = &fOriginalGLInterface->fFunctions.fGetString, + version, + shadingLanguageVersion](GrGLenum name) { + if (name == GR_GL_VERSION) { + return reinterpret_cast(version); + } else if (name == GR_GL_SHADING_LANGUAGE_VERSION) { + return reinterpret_cast(shadingLanguageVersion); + } + return (*wrapped)(name); + }; + auto newInterface = sk_make_sp(*fOriginalGLInterface); + newInterface->fFunctions.fGetString = getString; + fGLInterface = std::move(newInterface); +#endif +}; + sk_sp GLTestContext::makeContext(const GrContextOptions& options) { #ifdef SK_GL - return GrDirectContext::MakeGL(fGL, options); + return GrDirectContext::MakeGL(fGLInterface, options); #else return nullptr; #endif diff --git a/tools/gpu/gl/GLTestContext.h b/tools/gpu/gl/GLTestContext.h index 01bd0814cc..4346bfea97 100644 --- a/tools/gpu/gl/GLTestContext.h +++ b/tools/gpu/gl/GLTestContext.h @@ -9,6 +9,7 @@ #define GLTestContext_DEFINED #include "include/gpu/gl/GrGLInterface.h" +#include "src/gpu/gl/GrGLUtil.h" #include "tools/gpu/TestContext.h" namespace sk_gpu_test { @@ -26,7 +27,7 @@ public: /** Does this represent a successfully created GL context? */ bool isValid() const; - const GrGLInterface* gl() const { return fGL.get(); } + const GrGLInterface* gl() const { return fGLInterface.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 nullptr; } @@ -44,6 +45,8 @@ public: /** Wait until all GPU work is finished. */ void finish() override; + void overrideVersion(const char* version, const char* shadingLanguageVersion); + /** * Creates a new GL context of the same type and makes the returned context current * (if not null). @@ -81,9 +84,12 @@ protected: virtual GrGLFuncPtr onPlatformGetProcAddress(const char *) const = 0; private: - /** Subclass provides the gl interface object if construction was - * successful. */ - sk_sp fGL; + /** Subclass provides the gl interface object if construction was successful. */ + sk_sp fOriginalGLInterface; + + /** The same as fOriginalGLInterface unless the version has been overridden. */ + sk_sp fGLInterface; + #ifndef SK_GL bool fWasInitialized = false; #endif