WGL implemetation for OpenGL tutorial

Fixes to make WGL implementation work with OpenGL tutorial
- Give directive parser the correct shader spec when on Desktop GL
- Minor changes to parse Desktop GL shaders
- Moved clientType parameter from Context to Context->mState
- Minor fixes to WGL functions

Bug: angleproject:3666
Change-Id: I01ddb828f6d581ad445f49942589436849eae5d9
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1693244
Commit-Queue: Clemen Deng <clemendeng@google.com>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
Clemen Deng 2019-07-08 15:42:05 -04:00 коммит произвёл Commit Bot
Родитель 29fba5e088
Коммит 1d672749e7
20 изменённых файлов: 227 добавлений и 42 удалений

Просмотреть файл

@ -38,6 +38,8 @@ enum ShShaderSpec
SH_GLES3_1_SPEC,
SH_WEBGL3_SPEC,
SH_GL3_3_SPEC,
};
enum ShShaderOutput
@ -670,6 +672,14 @@ inline bool IsWebGLBasedSpec(ShShaderSpec spec)
{
return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC);
}
//
// Helper function to identify DesktopGL specs
//
inline bool IsDesktopGLSpec(ShShaderSpec spec)
{
return spec == SH_GL3_3_SPEC;
}
} // namespace sh
#endif // GLSLANG_SHADERLANG_H_

Просмотреть файл

@ -8,6 +8,7 @@
#define COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
#include <string>
#include "GLSLANG/ShaderLang.h"
namespace angle
{
@ -38,7 +39,7 @@ class DirectiveHandler
const std::string &name,
const std::string &behavior) = 0;
virtual void handleVersion(const SourceLocation &loc, int version) = 0;
virtual void handleVersion(const SourceLocation &loc, int version, ShShaderSpec spec) = 0;
};
} // namespace pp

Просмотреть файл

@ -10,6 +10,7 @@
#include <cstdlib>
#include <sstream>
#include "GLSLANG/ShaderLang.h"
#include "common/debug.h"
#include "compiler/preprocessor/DiagnosticsBase.h"
#include "compiler/preprocessor/DirectiveHandlerBase.h"
@ -699,7 +700,8 @@ void DirectiveParser::parseVersion(Token *token)
enum State
{
VERSION_NUMBER,
VERSION_PROFILE,
VERSION_PROFILE_ES,
VERSION_PROFILE_GL,
VERSION_ENDLINE
};
@ -727,10 +729,22 @@ void DirectiveParser::parseVersion(Token *token)
}
if (valid)
{
state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE;
if (sh::IsDesktopGLSpec(mSettings.shaderSpec))
{
state = VERSION_PROFILE_GL;
}
else if (version < 300)
{
state = VERSION_ENDLINE;
}
else
{
state = VERSION_PROFILE_ES;
}
}
break;
case VERSION_PROFILE:
case VERSION_PROFILE_ES:
ASSERT(!sh::IsDesktopGLSpec(mSettings.shaderSpec));
if (token->type != Token::IDENTIFIER || token->text != "es")
{
mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location,
@ -739,6 +753,16 @@ void DirectiveParser::parseVersion(Token *token)
}
state = VERSION_ENDLINE;
break;
case VERSION_PROFILE_GL:
ASSERT(sh::IsDesktopGLSpec(mSettings.shaderSpec));
if (token->type != Token::IDENTIFIER || token->text != "core")
{
mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location,
token->text);
valid = false;
}
state = VERSION_ENDLINE;
break;
default:
mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
token->text);
@ -747,6 +771,11 @@ void DirectiveParser::parseVersion(Token *token)
}
mTokenizer->lex(token);
if (token->type == '\n' && state == VERSION_PROFILE_GL)
{
state = VERSION_ENDLINE;
}
}
if (valid && (state != VERSION_ENDLINE))
@ -765,7 +794,7 @@ void DirectiveParser::parseVersion(Token *token)
if (valid)
{
mDirectiveHandler->handleVersion(token->location, version);
mDirectiveHandler->handleVersion(token->location, version, mSettings.shaderSpec);
mShaderVersion = version;
PredefineMacro(mMacroSet, "__VERSION__", version);
}

Просмотреть файл

@ -216,6 +216,8 @@ int MapSpecToShaderVersion(ShShaderSpec spec)
case SH_GLES3_1_SPEC:
case SH_WEBGL3_SPEC:
return 310;
case SH_GL3_3_SPEC:
return 330;
default:
UNREACHABLE();
return 0;
@ -376,7 +378,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
}
TParseContext parseContext(mSymbolTable, mExtensionBehavior, mShaderType, mShaderSpec,
compileOptions, true, &mDiagnostics, getResources());
compileOptions, !IsDesktopGLSpec(mShaderSpec), &mDiagnostics,
getResources());
parseContext.setFragmentPrecisionHighOnESSL1(mResources.FragmentPrecisionHigh == 1);

Просмотреть файл

@ -183,9 +183,12 @@ void TDirectiveHandler::handleExtension(const angle::pp::SourceLocation &loc,
}
}
void TDirectiveHandler::handleVersion(const angle::pp::SourceLocation &loc, int version)
void TDirectiveHandler::handleVersion(const angle::pp::SourceLocation &loc,
int version,
ShShaderSpec spec)
{
if (version == 100 || version == 300 || version == 310)
if (((version == 100 || version == 300 || version == 310) && !IsDesktopGLSpec(spec)) ||
(version == 330 && IsDesktopGLSpec(spec)))
{
mShaderVersion = version;
}
@ -194,7 +197,7 @@ void TDirectiveHandler::handleVersion(const angle::pp::SourceLocation &loc, int
std::stringstream stream = sh::InitializeStream<std::stringstream>();
stream << version;
std::string str = stream.str();
mDiagnostics.error(loc, "version number not supported", str.c_str());
mDiagnostics.error(loc, "client/version number not supported", str.c_str());
}
}

Просмотреть файл

@ -41,7 +41,9 @@ class TDirectiveHandler : public angle::pp::DirectiveHandler, angle::NonCopyable
const std::string &name,
const std::string &behavior) override;
void handleVersion(const angle::pp::SourceLocation &loc, int version) override;
void handleVersion(const angle::pp::SourceLocation &loc,
int version,
ShShaderSpec spec) override;
private:
TPragma mPragma;

Просмотреть файл

@ -453,7 +453,8 @@ GLenum GLVariablePrecision(const TType &type)
case EbpLow:
return GL_LOW_FLOAT;
case EbpUndefined:
// Should be defined as the default precision by the parser
// Desktop specs do not use precision
return GL_NONE;
default:
UNREACHABLE();
}
@ -469,7 +470,8 @@ GLenum GLVariablePrecision(const TType &type)
case EbpLow:
return GL_LOW_INT;
case EbpUndefined:
// Should be defined as the default precision by the parser
// Desktop specs do not use precision
return GL_NONE;
default:
UNREACHABLE();
}

Просмотреть файл

@ -22,8 +22,18 @@ namespace
// To know when to call sh::Initialize and sh::Finalize.
size_t gActiveCompilers = 0;
ShShaderSpec SelectShaderSpec(GLint majorVersion, GLint minorVersion, bool isWebGL)
ShShaderSpec SelectShaderSpec(GLint majorVersion,
GLint minorVersion,
bool isWebGL,
EGLenum clientType)
{
// For Desktop GL
if (clientType == EGL_OPENGL_API)
{
ASSERT(majorVersion == 3 && minorVersion == 3);
return SH_GL3_3_SPEC;
}
if (majorVersion >= 3)
{
if (minorVersion == 1)
@ -51,7 +61,8 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state)
: mImplementation(implFactory->createCompiler()),
mSpec(SelectShaderSpec(state.getClientMajorVersion(),
state.getClientMinorVersion(),
state.getExtensions().webglCompatibility)),
state.getExtensions().webglCompatibility,
state.getClientType())),
mOutputType(mImplementation->getTranslatorOutputType()),
mResources()
{

Просмотреть файл

@ -284,6 +284,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
: mState(reinterpret_cast<ContextID>(this),
shareContext ? &shareContext->mState : nullptr,
shareTextures,
clientType,
GetClientVersion(attribs),
GetDebug(attribs),
GetBindGeneratesResource(attribs),
@ -297,7 +298,6 @@ Context::Context(rx::EGLImplFactory *implFactory,
mLabel(nullptr),
mCompiler(),
mConfig(config),
mClientType(clientType),
mHasBeenCurrent(false),
mContextLost(false),
mResetStatus(GraphicsResetStatus::NoError),
@ -2662,7 +2662,7 @@ const egl::Config *Context::getConfig() const
EGLenum Context::getClientType() const
{
return mClientType;
return mState.getClientType();
}
EGLenum Context::getRenderBuffer() const
@ -2976,23 +2976,22 @@ void Context::initVersionStrings()
const Version &clientVersion = getClientVersion();
std::ostringstream versionString;
versionString << "OpenGL ";
if (mClientType == EGL_OPENGL_ES_API)
if (getClientType() == EGL_OPENGL_ES_API)
{
versionString << "ES ";
versionString << "OpenGL ES ";
}
versionString << clientVersion.major << "." << clientVersion.minor << " (ANGLE "
versionString << clientVersion.major << "." << clientVersion.minor << ".0 (ANGLE "
<< ANGLE_VERSION_STRING << ")";
mVersionString = MakeStaticString(versionString.str());
std::ostringstream shadingLanguageVersionString;
if (mClientType == EGL_OPENGL_ES_API)
if (getClientType() == EGL_OPENGL_ES_API)
{
shadingLanguageVersionString << "OpenGL ES GLSL ES ";
}
else
{
ASSERT(mClientType == EGL_OPENGL_API);
ASSERT(getClientType() == EGL_OPENGL_API);
shadingLanguageVersionString << "OpenGL GLSL ";
}
shadingLanguageVersionString << (clientVersion.major == 2 ? 1 : clientVersion.major) << "."

Просмотреть файл

@ -606,7 +606,6 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
mutable BindingPointer<Compiler> mCompiler;
const egl::Config *mConfig;
EGLenum mClientType;
TextureMap mZeroTextures;

Просмотреть файл

@ -393,7 +393,10 @@ Display *Display::GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativ
const auto &iter = displays->find(nativeDisplay);
// Check that there is a matching display
ASSERT(iter != displays->end());
if (iter == displays->end())
{
return nullptr;
}
return iter->second;
}

Просмотреть файл

@ -234,13 +234,15 @@ const angle::PackedEnumMap<BufferBinding, State::BufferBindingSetter> State::kBu
State::State(ContextID contextIn,
const State *shareContextState,
TextureManager *shareTextures,
const EGLenum clientType,
const Version &clientVersion,
bool debug,
bool bindGeneratesResource,
bool clientArraysEnabled,
bool robustResourceInit,
bool programBinaryCacheEnabled)
: mClientVersion(clientVersion),
: mClientType(clientType),
mClientVersion(clientVersion),
mContext(contextIn),
mBufferManager(AllocateOrGetSharedResourceManager(shareContextState, &State::mBufferManager)),
mShaderProgramManager(

Просмотреть файл

@ -58,6 +58,7 @@ class State : angle::NonCopyable
State(ContextID contextIn,
const State *shareContextState,
TextureManager *shareTextures,
const EGLenum clientType,
const Version &clientVersion,
bool debug,
bool bindGeneratesResource,
@ -71,6 +72,7 @@ class State : angle::NonCopyable
// Getters
ContextID getContextID() const { return mContext; }
EGLenum getClientType() const { return mClientType; }
GLint getClientMajorVersion() const { return mClientVersion.major; }
GLint getClientMinorVersion() const { return mClientVersion.minor; }
const Version &getClientVersion() const { return mClientVersion; }
@ -722,6 +724,7 @@ class State : angle::NonCopyable
// Dispatch table for buffer update functions.
static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters;
EGLenum mClientType;
Version mClientVersion;
ContextID mContext;

Просмотреть файл

@ -238,17 +238,38 @@ PROC GL_APIENTRY wglGetProcAddress(LPCSTR lpszProc)
BOOL GL_APIENTRY wglMakeCurrent(HDC hDc, HGLRC newContext)
{
Thread *thread = egl::GetCurrentThread();
Thread *thread = egl::GetCurrentThread();
egl::Display *display = egl::Display::GetExistingDisplayFromNativeDisplay(hDc);
gl::Context *context = reinterpret_cast<gl::Context *>(newContext);
const gl::Context *context =
GetContextIfValid(display, reinterpret_cast<gl::Context *>(newContext));
ANGLE_EGL_TRY_RETURN(
thread,
display->makeCurrent(thread, display->getWGLSurface(), display->getWGLSurface(), context),
"wglMakeCurrent", display, FALSE);
// If display or context are invalid, make thread's current rendering context not current
if (!context)
{
gl::Context *oldContext = thread->getContext();
if (oldContext)
{
ANGLE_EGL_TRY_RETURN(thread, oldContext->unMakeCurrent(display), "wglMakeCurrent",
GetContextIfValid(display, oldContext), EGL_FALSE);
}
SetContextCurrent(thread, nullptr);
return TRUE;
}
SetContextCurrent(thread, context);
egl::Surface *surface = display->getWGLSurface();
Surface *previousDraw = thread->getCurrentDrawSurface();
Surface *previousRead = thread->getCurrentReadSurface();
gl::Context *previousContext = thread->getContext();
if (previousDraw != surface || previousRead != surface || previousContext != context)
{
ANGLE_EGL_TRY_RETURN(
thread,
display->makeCurrent(thread, surface, surface, const_cast<gl::Context *>(context)),
"wglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
SetContextCurrent(thread, const_cast<gl::Context *>(context));
}
return TRUE;
}

Просмотреть файл

@ -226,3 +226,79 @@ TEST_F(ShCompileTest, DecimalSepLocale)
}
}
}
// For testing Desktop GL Shaders
class ShCompileDesktopGLTest : public ShCompileTest
{
public:
ShCompileDesktopGLTest() {}
protected:
void SetUp() override
{
sh::InitBuiltInResources(&mResources);
mCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_GL3_3_SPEC,
SH_GLSL_330_CORE_OUTPUT, &mResources);
ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
}
};
// Test calling sh::Compile with fragment shader source string
TEST_F(ShCompileDesktopGLTest, FragmentShaderString)
{
constexpr char kComputeShaderString[] =
R"(#version 330
void main()
{
})";
const char *shaderStrings[] = {kComputeShaderString};
testCompile(shaderStrings, 1, true);
}
// Test calling sh::Compile with core version
TEST_F(ShCompileDesktopGLTest, FragmentShaderCoreVersion)
{
constexpr char kComputeShaderString[] =
R"(#version 330 core
void main()
{
})";
const char *shaderStrings[] = {kComputeShaderString};
testCompile(shaderStrings, 1, true);
}
// Test calling sh::Compile with core version
TEST_F(ShCompileDesktopGLTest, DISABLED_FragmentShaderAdditionConversion)
{
constexpr char kComputeShaderString[] =
R"(#version 330 core
void main()
{
float f = 1 + 1.5;
})";
const char *shaderStrings[] = {kComputeShaderString};
testCompile(shaderStrings, 1, true);
}
// GL shaders use implicit conversions between types
// Testing internal implicit conversions
TEST_F(ShCompileDesktopGLTest, DISABLED_FragmentShaderFunctionConversion)
{
constexpr char kFragmentShaderString[] =
R"(#version 330 core
void main()
{
float cosTheta = clamp(0.5,0,1);
float exp = pow(0.5,2);
})";
const char *shaderStrings[] = {kFragmentShaderString};
testCompile(shaderStrings, 1, true);
}

Просмотреть файл

@ -29,7 +29,8 @@ class MockDirectiveHandler : public pp::DirectiveHandler
const std::string &name,
const std::string &behavior));
MOCK_METHOD2(handleVersion, void(const pp::SourceLocation &loc, int version));
MOCK_METHOD3(handleVersion,
void(const pp::SourceLocation &loc, int version, ShShaderSpec spec));
};
} // namespace angle

Просмотреть файл

@ -44,9 +44,14 @@ void SimplePreprocessorTest::preprocess(const char *input)
}
void SimplePreprocessorTest::preprocess(const char *input, const char *expected)
{
preprocess(input, expected, SH_GLES2_SPEC);
}
void SimplePreprocessorTest::preprocess(const char *input, const char *expected, ShShaderSpec spec)
{
pp::Preprocessor preprocessor(&mDiagnostics, &mDirectiveHandler,
pp::PreprocessorSettings(SH_GLES2_SPEC));
pp::PreprocessorSettings(spec));
std::stringstream output;
preprocess(input, &output, &preprocessor);

Просмотреть файл

@ -38,6 +38,7 @@ class SimplePreprocessorTest : public testing::Test
// Preprocesses the input string and verifies that it matches expected output.
void preprocess(const char *input, const char *expected);
void preprocess(const char *input, const char *expected, ShShaderSpec spec);
// Lexes a single token from input and writes it to token.
void lexSingleToken(const char *input, pp::Token *token);

Просмотреть файл

@ -90,7 +90,7 @@ TEST_F(ExtensionTest, ExtensionAfterNonPreProcessorTokenESSL3)
using testing::_;
// Directive successfully parsed.
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 300));
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 300, SH_GLES2_SPEC));
// Expect an error about extension pragmas after non-preprocessor tokens.
EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL, _, _));

Просмотреть файл

@ -19,13 +19,27 @@ TEST_F(VersionTest, Valid)
const char *expected = "\n";
using testing::_;
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 200));
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 200, SH_GLES2_SPEC));
// No error or warning.
EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
preprocess(str, expected);
}
// Test for Desktop GL Shaders
TEST_F(VersionTest, GLSpec)
{
const char *str = "#version 330 core\n";
const char *expected = "\n";
using testing::_;
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 330, SH_GL3_3_SPEC));
// No error or warning.
EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
preprocess(str, expected, SH_GL3_3_SPEC);
}
TEST_F(VersionTest, CommentsIgnored)
{
const char *str =
@ -41,7 +55,7 @@ TEST_F(VersionTest, CommentsIgnored)
const char *expected = "\n";
using testing::_;
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 200));
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 200, SH_GLES2_SPEC));
// No error or warning.
EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
@ -55,7 +69,7 @@ TEST_F(VersionTest, MissingNewline)
using testing::_;
// Directive successfully parsed.
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 200));
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 200, SH_GLES2_SPEC));
// Error reported about EOF.
EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_EOF_IN_DIRECTIVE, _, _));
@ -72,7 +86,7 @@ TEST_F(VersionTest, AfterComments)
using testing::_;
// Directive successfully parsed.
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 3), 200));
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 3), 200, SH_GLES2_SPEC));
// No error or warning.
EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
@ -89,7 +103,7 @@ TEST_F(VersionTest, AfterWhitespace)
using testing::_;
// Directive successfully parsed.
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 3), 200));
EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 3), 200, SH_GLES2_SPEC));
// No error or warning.
EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
@ -183,7 +197,7 @@ TEST_P(InvalidVersionTest, Identified)
using testing::_;
// No handleVersion call.
EXPECT_CALL(mDirectiveHandler, handleVersion(_, _)).Times(0);
EXPECT_CALL(mDirectiveHandler, handleVersion(_, _, _)).Times(0);
// Invalid version directive call.
EXPECT_CALL(mDiagnostics, print(param.id, pp::SourceLocation(0, 1), _));