Support multisampled framebuffers with the GL backend.

Move validation of sample counts into the Renderbuffer implementations
because the exact supported sample counts are not always known.

BUG=angleoproject:886

Change-Id: I9c90d9d435e940b852343a29a6aa11d6cb1ad23b
Reviewed-on: https://chromium-review.googlesource.com/255513
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/gl/FunctionsGL.cpp b/src/libANGLE/renderer/gl/FunctionsGL.cpp
index a56dec1..cc20bda 100644
--- a/src/libANGLE/renderer/gl/FunctionsGL.cpp
+++ b/src/libANGLE/renderer/gl/FunctionsGL.cpp
@@ -7,18 +7,89 @@
 // FunctionsGL.cpp: Implements the FuntionsGL class to contain loaded GL functions
 
 #include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
 
 namespace rx
 {
 
+static void GetGLVersion(PFNGLGETSTRINGPROC getStringFunction, GLuint *outMajorVersion, GLuint *outMinorVersion,
+                         bool *outIsES)
+{
+    const std::string version = reinterpret_cast<const char*>(getStringFunction(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"
+        *outIsES = false;
+        *outMajorVersion = version[0] - '0';
+        *outMinorVersion = version[2] - '0';
+    }
+    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
+        *outIsES = true;
+        *outMajorVersion = version[10] - '0';
+        *outMinorVersion = version[12] - '0';
+    }
+}
+
+static std::vector<std::string> GetNonIndexedExtensions(PFNGLGETSTRINGPROC getStringFunction)
+{
+    std::vector<std::string> result;
+
+    std::istringstream stream(reinterpret_cast<const char*>(getStringFunction(GL_EXTENSIONS)));
+    std::string extension;
+    while (std::getline(stream, extension, ' '))
+    {
+        result.push_back(extension);
+    }
+
+    return result;
+}
+
+static std::vector<std::string> GetIndexedExtensions(PFNGLGETINTEGERVPROC getIntegerFunction, PFNGLGETSTRINGIPROC getStringIFunction)
+{
+    std::vector<std::string> result;
+
+    GLint numExtensions;
+    getIntegerFunction(GL_NUM_EXTENSIONS, &numExtensions);
+
+    result.reserve(numExtensions);
+
+    for (GLint i = 0; i < numExtensions; i++)
+    {
+        result.push_back(reinterpret_cast<const char*>(getStringIFunction(GL_EXTENSIONS, i)));
+    }
+
+    return result;
+}
+
 template <typename T>
 static void AssignGLEntryPoint(void *function, T *outFunction)
 {
     *outFunction = reinterpret_cast<T>(function);
 }
 
+template <typename T>
+static void AssignGLExtensionEntryPoint(const std::vector<std::string> &extensions, const std::string &extension, void *function, T *outFunction)
+{
+    if (std::find(extensions.begin(), extensions.end(), extension) != extensions.end())
+    {
+        *outFunction = reinterpret_cast<T>(function);
+    }
+}
+
 FunctionsGL::FunctionsGL()
-    : blendFunc(nullptr),
+    : majorVersion(0),
+      minorVersion(0),
+      openGLES(false),
+      extensions(),
+
+      blendFunc(nullptr),
       clear(nullptr),
       clearColor(nullptr),
       clearDepth(nullptr),
@@ -694,8 +765,24 @@
 {
 }
 
-void FunctionsGL::initialize(GLuint majorVersion, GLuint minorVersion)
+void FunctionsGL::initialize()
 {
+    // Grab the version number
+    AssignGLEntryPoint(loadProcAddress("glGetString"), &getString);
+    GetGLVersion(getString, &majorVersion, &minorVersion, &openGLES);
+
+    // Grab the GL extensions
+    if (majorVersion > 3 || majorVersion == 3 && minorVersion >= 0)
+    {
+        AssignGLEntryPoint(loadProcAddress("glGetIntegerv"), &getIntegerv);
+        AssignGLEntryPoint(loadProcAddress("glGetStringi"), &getStringi);
+        extensions = GetIndexedExtensions(getIntegerv, getStringi);
+    }
+    else
+    {
+        extensions = GetNonIndexedExtensions(getString);
+    }
+
     // 1.0
     if (majorVersion > 1 || majorVersion == 1 && minorVersion >= 0)
     {
@@ -1024,6 +1111,9 @@
         AssignGLEntryPoint(loadProcAddress("glVertexAttribI4uiv"), &vertexAttribI4uiv);
         AssignGLEntryPoint(loadProcAddress("glVertexAttribI4usv"), &vertexAttribI4usv);
         AssignGLEntryPoint(loadProcAddress("glVertexAttribIPointer"), &vertexAttribIPointer);
+
+        // Extensions
+        AssignGLExtensionEntryPoint(extensions, "GL_ARB_internalformat_query", loadProcAddress("glGetInternalformativ"), &getInternalformativ);
     }
 
     // 3.1