Refactor OpenGLVersion out of OpenGLFunctions.

We need the ability to parse the GL version irrespective of
GL extension handling, so pull it out into its own class.

BUG=dawn:580
Change-Id: I620267146159ba8e4fa8cba5f6ebff57e981add0
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/33540
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Stephen White <senorblanco@chromium.org>
diff --git a/generator/templates/opengl/OpenGLFunctionsBase.h b/generator/templates/opengl/OpenGLFunctionsBase.h
index fcaa6d3..2e16563 100644
--- a/generator/templates/opengl/OpenGLFunctionsBase.h
+++ b/generator/templates/opengl/OpenGLFunctionsBase.h
@@ -12,6 +12,9 @@
 //* See the License for the specific language governing permissions and
 //* limitations under the License.
 
+#ifndef DAWNNATIVE_OPENGL_OPENGLFUNCTIONSBASE_H_
+#define DAWNNATIVE_OPENGL_OPENGLFUNCTIONSBASE_H_
+
 #include "dawn_native/Error.h"
 #include "dawn_native/opengl/opengl_platform.h"
 
@@ -38,3 +41,5 @@
     };
 
 }}  // namespace dawn_native::opengl
+
+#endif // DAWNNATIVE_OPENGL_OPENGLFUNCTIONSBASE_H_
diff --git a/src/dawn_native/BUILD.gn b/src/dawn_native/BUILD.gn
index 9c9c8ab..5e1999f 100644
--- a/src/dawn_native/BUILD.gn
+++ b/src/dawn_native/BUILD.gn
@@ -448,6 +448,8 @@
       "opengl/NativeSwapChainImplGL.h",
       "opengl/OpenGLFunctions.cpp",
       "opengl/OpenGLFunctions.h",
+      "opengl/OpenGLVersion.cpp",
+      "opengl/OpenGLVersion.h",
       "opengl/PersistentPipelineStateGL.cpp",
       "opengl/PersistentPipelineStateGL.h",
       "opengl/PipelineGL.cpp",
diff --git a/src/dawn_native/opengl/OpenGLFunctions.cpp b/src/dawn_native/opengl/OpenGLFunctions.cpp
index c54a0ad..472fa5b 100644
--- a/src/dawn_native/opengl/OpenGLFunctions.cpp
+++ b/src/dawn_native/opengl/OpenGLFunctions.cpp
@@ -15,43 +15,15 @@
 #include "dawn_native/opengl/OpenGLFunctions.h"
 
 #include <cctype>
-#include <tuple>
 
 namespace dawn_native { namespace opengl {
 
     MaybeError OpenGLFunctions::Initialize(GetProcAddress getProc) {
-        PFNGLGETSTRINGPROC getString = reinterpret_cast<PFNGLGETSTRINGPROC>(getProc("glGetString"));
-        if (getString == nullptr) {
-            return DAWN_INTERNAL_ERROR("Couldn't load glGetString");
-        }
-
-        std::string version = reinterpret_cast<const char*>(getString(GL_VERSION));
-
-        if (version.find("OpenGL ES") != std::string::npos) {
-            // ES spec states that the GL_VERSION string will be in the following format:
-            // "OpenGL ES N.M vendor-specific information"
-            mStandard = Standard::ES;
-            mMajorVersion = version[10] - '0';
-            mMinorVersion = version[12] - '0';
-
-            // The minor version shouldn't get to two digits.
-            ASSERT(version.size() <= 13 || !isdigit(version[13]));
-
-            DAWN_TRY(LoadOpenGLESProcs(getProc, mMajorVersion, mMinorVersion));
+        DAWN_TRY(mVersion.Initialize(getProc));
+        if (mVersion.IsES()) {
+            DAWN_TRY(LoadOpenGLESProcs(getProc, mVersion.GetMajor(), mVersion.GetMinor()));
         } else {
-            // OpenGL spec states the GL_VERSION string will be in the following format:
-            // <version number><space><vendor-specific information>
-            // The version number is either of the form major number.minor number or major
-            // number.minor number.release number, where the numbers all have one or more
-            // digits
-            mStandard = Standard::Desktop;
-            mMajorVersion = version[0] - '0';
-            mMinorVersion = version[2] - '0';
-
-            // The minor version shouldn't get to two digits.
-            ASSERT(version.size() <= 3 || !isdigit(version[3]));
-
-            DAWN_TRY(LoadDesktopGLProcs(getProc, mMajorVersion, mMinorVersion));
+            DAWN_TRY(LoadDesktopGLProcs(getProc, mVersion.GetMajor(), mVersion.GetMinor()));
         }
 
         InitializeSupportedGLExtensions();
@@ -74,14 +46,16 @@
         return mSupportedGLExtensionsSet.count(extension) != 0;
     }
 
+    const OpenGLVersion& OpenGLFunctions::GetVersion() const {
+        return mVersion;
+    }
+
     bool OpenGLFunctions::IsAtLeastGL(uint32_t majorVersion, uint32_t minorVersion) const {
-        return mStandard == Standard::Desktop &&
-               std::tie(mMajorVersion, mMinorVersion) >= std::tie(majorVersion, minorVersion);
+        return mVersion.IsDesktop() && mVersion.IsAtLeast(majorVersion, minorVersion);
     }
 
     bool OpenGLFunctions::IsAtLeastGLES(uint32_t majorVersion, uint32_t minorVersion) const {
-        return mStandard == Standard::ES &&
-               std::tie(mMajorVersion, mMinorVersion) >= std::tie(majorVersion, minorVersion);
+        return mVersion.IsES() && mVersion.IsAtLeast(majorVersion, minorVersion);
     }
 
 }}  // namespace dawn_native::opengl
diff --git a/src/dawn_native/opengl/OpenGLFunctions.h b/src/dawn_native/opengl/OpenGLFunctions.h
index e514300..69180b4 100644
--- a/src/dawn_native/opengl/OpenGLFunctions.h
+++ b/src/dawn_native/opengl/OpenGLFunctions.h
@@ -18,6 +18,7 @@
 #include <unordered_set>
 
 #include "dawn_native/opengl/OpenGLFunctionsBase_autogen.h"
+#include "dawn_native/opengl/OpenGLVersion.h"
 
 namespace dawn_native { namespace opengl {
 
@@ -25,6 +26,7 @@
       public:
         MaybeError Initialize(GetProcAddress getProc);
 
+        const OpenGLVersion& GetVersion() const;
         bool IsAtLeastGL(uint32_t majorVersion, uint32_t minorVersion) const;
         bool IsAtLeastGLES(uint32_t majorVersion, uint32_t minorVersion) const;
 
@@ -33,14 +35,7 @@
       private:
         void InitializeSupportedGLExtensions();
 
-        uint32_t mMajorVersion;
-        uint32_t mMinorVersion;
-
-        enum class Standard {
-            Desktop,
-            ES,
-        };
-        Standard mStandard;
+        OpenGLVersion mVersion;
 
         std::unordered_set<std::string> mSupportedGLExtensionsSet;
     };
diff --git a/src/dawn_native/opengl/OpenGLVersion.cpp b/src/dawn_native/opengl/OpenGLVersion.cpp
new file mode 100644
index 0000000..edb6adf
--- /dev/null
+++ b/src/dawn_native/opengl/OpenGLVersion.cpp
@@ -0,0 +1,76 @@
+// Copyright 2020 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn_native/opengl/OpenGLVersion.h"
+
+#include <cctype>
+#include <tuple>
+
+namespace dawn_native { namespace opengl {
+
+    MaybeError OpenGLVersion::Initialize(GetProcAddress getProc) {
+        PFNGLGETSTRINGPROC getString = reinterpret_cast<PFNGLGETSTRINGPROC>(getProc("glGetString"));
+        if (getString == nullptr) {
+            return DAWN_INTERNAL_ERROR("Couldn't load glGetString");
+        }
+
+        std::string version = reinterpret_cast<const char*>(getString(GL_VERSION));
+
+        if (version.find("OpenGL ES") != std::string::npos) {
+            // ES spec states that the GL_VERSION string will be in the following format:
+            // "OpenGL ES N.M vendor-specific information"
+            mStandard = Standard::ES;
+            mMajorVersion = version[10] - '0';
+            mMinorVersion = version[12] - '0';
+
+            // The minor version shouldn't get to two digits.
+            ASSERT(version.size() <= 13 || !isdigit(version[13]));
+        } else {
+            // OpenGL spec states the GL_VERSION string will be in the following format:
+            // <version number><space><vendor-specific information>
+            // The version number is either of the form major number.minor number or major
+            // number.minor number.release number, where the numbers all have one or more
+            // digits
+            mStandard = Standard::Desktop;
+            mMajorVersion = version[0] - '0';
+            mMinorVersion = version[2] - '0';
+
+            // The minor version shouldn't get to two digits.
+            ASSERT(version.size() <= 3 || !isdigit(version[3]));
+        }
+
+        return {};
+    }
+
+    bool OpenGLVersion::IsDesktop() const {
+        return mStandard == Standard::Desktop;
+    }
+
+    bool OpenGLVersion::IsES() const {
+        return mStandard == Standard::ES;
+    }
+
+    uint32_t OpenGLVersion::GetMajor() const {
+        return mMajorVersion;
+    }
+
+    uint32_t OpenGLVersion::GetMinor() const {
+        return mMinorVersion;
+    }
+
+    bool OpenGLVersion::IsAtLeast(uint32_t majorVersion, uint32_t minorVersion) const {
+        return std::tie(mMajorVersion, mMinorVersion) >= std::tie(majorVersion, minorVersion);
+    }
+
+}}  // namespace dawn_native::opengl
diff --git a/src/dawn_native/opengl/OpenGLVersion.h b/src/dawn_native/opengl/OpenGLVersion.h
new file mode 100644
index 0000000..88ddd50
--- /dev/null
+++ b/src/dawn_native/opengl/OpenGLVersion.h
@@ -0,0 +1,44 @@
+// Copyright 2020 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef DAWNNATIVE_OPENGL_OPENGLVERSION_H_
+#define DAWNNATIVE_OPENGL_OPENGLVERSION_H_
+
+#include "dawn_native/opengl/OpenGLFunctionsBase_autogen.h"
+
+namespace dawn_native { namespace opengl {
+
+    struct OpenGLVersion {
+      public:
+        MaybeError Initialize(GetProcAddress getProc);
+
+        bool IsDesktop() const;
+        bool IsES() const;
+        uint32_t GetMajor() const;
+        uint32_t GetMinor() const;
+        bool IsAtLeast(uint32_t majorVersion, uint32_t minorVersion) const;
+
+      private:
+        enum class Standard {
+            Desktop,
+            ES,
+        };
+        uint32_t mMajorVersion;
+        uint32_t mMinorVersion;
+        Standard mStandard;
+    };
+
+}}  // namespace dawn_native::opengl
+
+#endif  // DAWNNATIVE_OPENGL_OPENGLVERSION_H_
diff --git a/src/dawn_native/opengl/ShaderModuleGL.cpp b/src/dawn_native/opengl/ShaderModuleGL.cpp
index 98c542a..2723c5c 100644
--- a/src/dawn_native/opengl/ShaderModuleGL.cpp
+++ b/src/dawn_native/opengl/ShaderModuleGL.cpp
@@ -77,12 +77,13 @@
         options.vertex.flip_vert_y = true;
         options.vertex.fixup_clipspace = true;
 
-        // TODO(cwallez@chromium.org): discover the backing context version and use that.
-#if defined(DAWN_PLATFORM_APPLE)
-        options.version = 410;
-#else
-        options.version = 440;
-#endif
+        const OpenGLVersion& version = ToBackend(GetDevice())->gl.GetVersion();
+        if (version.IsDesktop()) {
+            // The computation of GLSL version below only works for 3.3 and above.
+            ASSERT(version.IsAtLeast(3, 3));
+        }
+        options.es = version.IsES();
+        options.version = version.GetMajor() * 100 + version.GetMinor() * 10;
 
         spirv_cross::CompilerGLSL compiler(GetSpirv());
         compiler.set_common_options(options);