Support instanced CHROMIUM_path_rendering

This implements instanced path rendering.

BUG=angleproject:1382

Change-Id: I4654251882975d707b22c7bb522af14ae34eb1a1
Reviewed-on: https://chromium-review.googlesource.com/355401
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Sami Väisänen <svaisanen@nvidia.com>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 2559657..9b3ecc7 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -12,6 +12,7 @@
 #include <iterator>
 #include <sstream>
 #include <string.h>
+#include <vector>
 
 #include "common/matrix_utils.h"
 #include "common/platform.h"
@@ -41,6 +42,58 @@
 {
 
 template <typename T>
+std::vector<gl::Path *> GatherPaths(gl::ResourceManager &resourceManager,
+                                    GLsizei numPaths,
+                                    const void *paths,
+                                    GLuint pathBase)
+{
+    std::vector<gl::Path *> ret;
+    ret.reserve(numPaths);
+
+    const auto *nameArray = static_cast<const T *>(paths);
+
+    for (GLsizei i = 0; i < numPaths; ++i)
+    {
+        const GLuint pathName = nameArray[i] + pathBase;
+
+        ret.push_back(resourceManager.getPath(pathName));
+    }
+
+    return ret;
+}
+
+std::vector<gl::Path *> GatherPaths(gl::ResourceManager &resourceManager,
+                                    GLsizei numPaths,
+                                    GLenum pathNameType,
+                                    const void *paths,
+                                    GLuint pathBase)
+{
+    switch (pathNameType)
+    {
+        case GL_UNSIGNED_BYTE:
+            return GatherPaths<GLubyte>(resourceManager, numPaths, paths, pathBase);
+
+        case GL_BYTE:
+            return GatherPaths<GLbyte>(resourceManager, numPaths, paths, pathBase);
+
+        case GL_UNSIGNED_SHORT:
+            return GatherPaths<GLushort>(resourceManager, numPaths, paths, pathBase);
+
+        case GL_SHORT:
+            return GatherPaths<GLshort>(resourceManager, numPaths, paths, pathBase);
+
+        case GL_UNSIGNED_INT:
+            return GatherPaths<GLuint>(resourceManager, numPaths, paths, pathBase);
+
+        case GL_INT:
+            return GatherPaths<GLint>(resourceManager, numPaths, paths, pathBase);
+    }
+
+    UNREACHABLE();
+    return std::vector<gl::Path *>();
+}
+
+template <typename T>
 gl::Error GetQueryObjectParameter(gl::Context *context, GLuint id, GLenum pname, T *params)
 {
     gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
@@ -1471,6 +1524,114 @@
     mImplementation->stencilThenCoverStrokePath(pathObj, reference, mask, coverMode);
 }
 
+void Context::coverFillPathInstanced(GLsizei numPaths,
+                                     GLenum pathNameType,
+                                     const void *paths,
+                                     GLuint pathBase,
+                                     GLenum coverMode,
+                                     GLenum transformType,
+                                     const GLfloat *transformValues)
+{
+    const auto &pathObjects =
+        GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->coverFillPathInstanced(pathObjects, coverMode, transformType, transformValues);
+}
+void Context::coverStrokePathInstanced(GLsizei numPaths,
+                                       GLenum pathNameType,
+                                       const void *paths,
+                                       GLuint pathBase,
+                                       GLenum coverMode,
+                                       GLenum transformType,
+                                       const GLfloat *transformValues)
+{
+    const auto &pathObjects =
+        GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->coverStrokePathInstanced(pathObjects, coverMode, transformType,
+                                              transformValues);
+}
+void Context::stencilFillPathInstanced(GLsizei numPaths,
+                                       GLenum pathNameType,
+                                       const void *paths,
+                                       GLuint pathBase,
+                                       GLenum fillMode,
+                                       GLuint mask,
+                                       GLenum transformType,
+                                       const GLfloat *transformValues)
+{
+    const auto &pathObjects =
+        GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilFillPathInstanced(pathObjects, fillMode, mask, transformType,
+                                              transformValues);
+}
+void Context::stencilStrokePathInstanced(GLsizei numPaths,
+                                         GLenum pathNameType,
+                                         const void *paths,
+                                         GLuint pathBase,
+                                         GLint reference,
+                                         GLuint mask,
+                                         GLenum transformType,
+                                         const GLfloat *transformValues)
+{
+    const auto &pathObjects =
+        GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilStrokePathInstanced(pathObjects, reference, mask, transformType,
+                                                transformValues);
+}
+void Context::stencilThenCoverFillPathInstanced(GLsizei numPaths,
+                                                GLenum pathNameType,
+                                                const void *paths,
+                                                GLuint pathBase,
+                                                GLenum fillMode,
+                                                GLuint mask,
+                                                GLenum coverMode,
+                                                GLenum transformType,
+                                                const GLfloat *transformValues)
+{
+    const auto &pathObjects =
+        GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilThenCoverFillPathInstanced(pathObjects, coverMode, fillMode, mask,
+                                                       transformType, transformValues);
+}
+void Context::stencilThenCoverStrokePathInstanced(GLsizei numPaths,
+                                                  GLenum pathNameType,
+                                                  const void *paths,
+                                                  GLuint pathBase,
+                                                  GLint reference,
+                                                  GLuint mask,
+                                                  GLenum coverMode,
+                                                  GLenum transformType,
+                                                  const GLfloat *transformValues)
+{
+    const auto &pathObjects =
+        GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilThenCoverStrokePathInstanced(pathObjects, coverMode, reference, mask,
+                                                         transformType, transformValues);
+}
+
 void Context::handleError(const Error &error)
 {
     if (error.isError())