Add GL indirect drawing APIs

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1666803002

Review URL: https://codereview.chromium.org/1666803002
diff --git a/include/gpu/gl/GrGLFunctions.h b/include/gpu/gl/GrGLFunctions.h
index 1086186..ad59ec0 100644
--- a/include/gpu/gl/GrGLFunctions.h
+++ b/include/gpu/gl/GrGLFunctions.h
@@ -13,14 +13,6 @@
 
 extern "C" {
 
-typedef void (GR_GL_FUNCTION_TYPE* GRGLDEBUGPROC)(GrGLenum source,
-                                                  GrGLenum type,
-                                                  GrGLuint id,
-                                                  GrGLenum severity,
-                                                  GrGLsizei length,
-                                                  const GrGLchar* message,
-                                                  const void* userParam);
-
 ///////////////////////////////////////////////////////////////////////////////
 
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLActiveTextureProc)(GrGLenum texture);
@@ -66,9 +58,13 @@
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDisableProc)(GrGLenum cap);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDisableVertexAttribArrayProc)(GrGLuint index);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawArraysProc)(GrGLenum mode, GrGLint first, GrGLsizei count);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawArraysInstancedProc)(GrGLenum mode, GrGLint first, GrGLsizei count, GrGLsizei primcount);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawArraysIndirectProc)(GrGLenum mode, GrGLvoid* indirect);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawBufferProc)(GrGLenum mode);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawBuffersProc)(GrGLsizei n, const GrGLenum* bufs);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawElementsProc)(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid* indices);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawElementsInstancedProc)(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid *indices, GrGLsizei primcount);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawElementsIndirectProc)(GrGLenum mode, GrGLenum type, GrGLvoid* indirect);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEGLImageTargetTexture2DProc)(GrGLenum target, GrGLeglImage image);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEnableProc)(GrGLenum cap);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEnableVertexAttribArrayProc)(GrGLuint index);
@@ -179,6 +175,7 @@
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttrib2fvProc)(GrGLuint indx, const GrGLfloat* values);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttrib3fvProc)(GrGLuint indx, const GrGLfloat* values);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttrib4fvProc)(GrGLuint indx, const GrGLfloat* values);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttribDivisorProc)(GrGLuint index, GrGLuint divisor);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttribPointerProc)(GrGLuint indx, GrGLint size, GrGLenum type, GrGLboolean normalized, GrGLsizei stride, const GrGLvoid* ptr);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLViewportProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height);
 
@@ -216,12 +213,9 @@
 /* GL_NV_framebuffer_mixed_samples */
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverageModulationProc)(GrGLenum components);
 
-/* ARB_draw_instanced */
-typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawArraysInstancedProc)(GrGLenum mode, GrGLint first, GrGLsizei count, GrGLsizei primcount);
-typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawElementsInstancedProc)(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid *indices, GrGLsizei primcount);
-
-/* ARB_instanced_arrays */
-typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttribDivisorProc)(GrGLuint index, GrGLuint divisor);
+/* EXT_multi_draw_indirect */
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLMultiDrawArraysIndirectProc)(GrGLenum mode, const GrGLvoid *indirect, GrGLsizei drawcount, GrGLsizei stride);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLMultiDrawElementsIndirectProc)(GrGLenum mode, GrGLenum type, const GrGLvoid *indirect, GrGLsizei drawcount, GrGLsizei stride);
 
 /* NV_bindless_texture */
 typedef GrGLuint64 (GR_GL_FUNCTION_TYPE* GrGLGetTextureHandleProc)(GrGLuint texture);
diff --git a/include/gpu/gl/GrGLInterface.h b/include/gpu/gl/GrGLInterface.h
index 5fa31ed..dd9a9fb 100644
--- a/include/gpu/gl/GrGLInterface.h
+++ b/include/gpu/gl/GrGLInterface.h
@@ -196,9 +196,13 @@
         GLPtr<GrGLDisableProc> fDisable;
         GLPtr<GrGLDisableVertexAttribArrayProc> fDisableVertexAttribArray;
         GLPtr<GrGLDrawArraysProc> fDrawArrays;
+        GLPtr<GrGLDrawArraysIndirectProc> fDrawArraysIndirect;
+        GLPtr<GrGLDrawArraysInstancedProc> fDrawArraysInstanced;
         GLPtr<GrGLDrawBufferProc> fDrawBuffer;
         GLPtr<GrGLDrawBuffersProc> fDrawBuffers;
         GLPtr<GrGLDrawElementsProc> fDrawElements;
+        GLPtr<GrGLDrawElementsIndirectProc> fDrawElementsIndirect;
+        GLPtr<GrGLDrawElementsInstancedProc> fDrawElementsInstanced;
         GLPtr<GrGLEnableProc> fEnable;
         GLPtr<GrGLEnableVertexAttribArrayProc> fEnableVertexAttribArray;
         GLPtr<GrGLEndQueryProc> fEndQuery;
@@ -327,6 +331,7 @@
         GLPtr<GrGLVertexAttrib2fvProc> fVertexAttrib2fv;
         GLPtr<GrGLVertexAttrib3fvProc> fVertexAttrib3fv;
         GLPtr<GrGLVertexAttrib4fvProc> fVertexAttrib4fv;
+        GLPtr<GrGLVertexAttribDivisorProc> fVertexAttribDivisor;
         GLPtr<GrGLVertexAttribPointerProc> fVertexAttribPointer;
         GLPtr<GrGLViewportProc> fViewport;
 
@@ -362,12 +367,9 @@
         /* NV_framebuffer_mixed_samples */
         GLPtr<GrGLCoverageModulationProc> fCoverageModulation;
 
-        /* ARB_draw_instanced */
-        GLPtr<GrGLDrawArraysInstancedProc> fDrawArraysInstanced;
-        GLPtr<GrGLDrawElementsInstancedProc> fDrawElementsInstanced;
-
-        /* ARB_instanced_arrays */
-        GLPtr<GrGLVertexAttribDivisorProc> fVertexAttribDivisor;
+        /* EXT_multi_draw_indirect */
+        GLPtr<GrGLMultiDrawArraysIndirectProc> fMultiDrawArraysIndirect;
+        GLPtr<GrGLMultiDrawElementsIndirectProc> fMultiDrawElementsIndirect;
 
         /* NV_bindless_texture */
         // We use the NVIDIA verson for now because it does not require dynamically uniform handles.
diff --git a/include/gpu/gl/GrGLTypes.h b/include/gpu/gl/GrGLTypes.h
index 248ce88..d0edcf1 100644
--- a/include/gpu/gl/GrGLTypes.h
+++ b/include/gpu/gl/GrGLTypes.h
@@ -58,10 +58,40 @@
 typedef signed long int GrGLsizeiptr;
 #endif
 typedef void* GrGLeglImage;
+
+struct GrGLDrawArraysIndirectCommand {
+    GrGLuint fCount;
+    GrGLuint fInstanceCount;
+    GrGLuint fFirst;
+    GrGLuint fBaseInstance;  // Requires EXT_base_instance on ES.
+};
+
+GR_STATIC_ASSERT(16 == sizeof(GrGLDrawArraysIndirectCommand));
+
+struct GrGLDrawElementsIndirectCommand {
+    GrGLuint fCount;
+    GrGLuint fInstanceCount;
+    GrGLuint fFirstIndex;
+    GrGLuint fBaseVertex;
+    GrGLuint fBaseInstance;  // Requires EXT_base_instance on ES.
+};
+
+GR_STATIC_ASSERT(20 == sizeof(GrGLDrawElementsIndirectCommand));
+
+/**
+ * KHR_debug
+ */
+typedef void (GR_GL_FUNCTION_TYPE* GRGLDEBUGPROC)(GrGLenum source,
+                                                  GrGLenum type,
+                                                  GrGLuint id,
+                                                  GrGLenum severity,
+                                                  GrGLsizei length,
+                                                  const GrGLchar* message,
+                                                  const void* userParam);
+
 /**
  * EGL types.
  */
-
 typedef void* GrEGLImage;
 typedef void* GrEGLDisplay;
 typedef void* GrEGLContext;
diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp
index 6b578f3..30eed62 100644
--- a/src/gpu/gl/GrGLAssembleInterface.cpp
+++ b/src/gpu/gl/GrGLAssembleInterface.cpp
@@ -138,6 +138,19 @@
     GET_PROC(DrawBuffer);
     GET_PROC(DrawBuffers);
     GET_PROC(DrawElements);
+
+    if (glVer >= GR_GL_VER(3,1) || extensions.has("GL_ARB_draw_instanced") ||
+        extensions.has("GL_EXT_draw_instanced")) {
+        GET_PROC(DrawArraysInstanced);
+        GET_PROC(DrawElementsInstanced);
+    }
+
+    if (glVer >= GR_GL_VER(4,0)) {
+        // We don't use ARB_draw_indirect because it does not support a base instance.
+        GET_PROC(DrawArraysIndirect);
+        GET_PROC(DrawElementsIndirect);
+    }
+
     GET_PROC(Enable);
     GET_PROC(EnableVertexAttribArray);
     GET_PROC(EndQuery);
@@ -228,6 +241,11 @@
     GET_PROC(VertexAttrib2fv);
     GET_PROC(VertexAttrib3fv);
     GET_PROC(VertexAttrib4fv);
+
+    if (glVer >= GR_GL_VER(3,2) || extensions.has("GL_ARB_instanced_arrays")) {
+        GET_PROC(VertexAttribDivisor);
+    }
+
     GET_PROC(VertexAttribPointer);
     GET_PROC(Viewport);
     GET_PROC(BindFragDataLocationIndexed);
@@ -338,14 +356,10 @@
         GET_PROC(GetProgramResourceLocation);
     }
 
-    if (glVer >= GR_GL_VER(3,1) || extensions.has("GL_ARB_draw_instanced") ||
-        extensions.has("GL_EXT_draw_instanced")) {
-        GET_PROC(DrawArraysInstanced);
-        GET_PROC(DrawElementsInstanced);
-    }
-
-    if (glVer >= GR_GL_VER(3,2) || extensions.has("GL_ARB_instanced_arrays")) {
-        GET_PROC(VertexAttribDivisor);
+    if (glVer >= GR_GL_VER(4,3)) {
+        // We don't use ARB_multi_draw_indirect because it does not support GL_DRAW_INDIRECT_BUFFER.
+        GET_PROC(MultiDrawArraysIndirect);
+        GET_PROC(MultiDrawElementsIndirect);
     }
 
     if (extensions.has("GL_NV_bindless_texture")) {
@@ -564,6 +578,20 @@
     GET_PROC(Disable);
     GET_PROC(DisableVertexAttribArray);
     GET_PROC(DrawArrays);
+
+    if (version >= GR_GL_VER(3,0)) {
+        GET_PROC(DrawArraysInstanced);
+        GET_PROC(DrawElementsInstanced);
+    } else if (extensions.has("GL_EXT_draw_instanced")) {
+        GET_PROC_SUFFIX(DrawArraysInstanced, EXT);
+        GET_PROC_SUFFIX(DrawElementsInstanced, EXT);
+    }
+
+    if (version >= GR_GL_VER(3,1)) {
+        GET_PROC(DrawArraysIndirect);
+        GET_PROC(DrawElementsIndirect);
+    }
+
     GET_PROC(DrawElements);
     GET_PROC(Enable);
     GET_PROC(EnableVertexAttribArray);
@@ -643,6 +671,13 @@
     GET_PROC(VertexAttrib2fv);
     GET_PROC(VertexAttrib3fv);
     GET_PROC(VertexAttrib4fv);
+
+    if (version >= GR_GL_VER(3,0)) {
+        GET_PROC(VertexAttribDivisor);
+    } else if (extensions.has("GL_EXT_instanced_arrays")) {
+        GET_PROC_SUFFIX(VertexAttribDivisor, EXT);
+    }
+
     GET_PROC(VertexAttribPointer);
     GET_PROC(Viewport);
     GET_PROC(BindFramebuffer);
@@ -779,18 +814,9 @@
         GET_PROC_SUFFIX(CoverageModulation, CHROMIUM);
     }
 
-    if (version >= GR_GL_VER(3,0)) {
-        GET_PROC(DrawArraysInstanced);
-        GET_PROC(DrawElementsInstanced);
-    } else if (extensions.has("GL_EXT_draw_instanced")) {
-        GET_PROC_SUFFIX(DrawArraysInstanced, EXT);
-        GET_PROC_SUFFIX(DrawElementsInstanced, EXT);
-    }
-
-    if (version >= GR_GL_VER(3,0)) {
-        GET_PROC(VertexAttribDivisor);
-    } else if (extensions.has("GL_EXT_instanced_arrays")) {
-        GET_PROC_SUFFIX(VertexAttribDivisor, EXT);
+    if (extensions.has("GL_EXT_multi_draw_indirect")) {
+        GET_PROC_SUFFIX(MultiDrawArraysIndirect, EXT);
+        GET_PROC_SUFFIX(MultiDrawElementsIndirect, EXT);
     }
 
     if (extensions.has("GL_NV_bindless_texture")) {
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 1a87274..a913fbe 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -41,6 +41,9 @@
     fDebugSupport = false;
     fES2CompatibilitySupport = false;
     fMultisampleDisableSupport = false;
+    fDrawIndirectSupport = false;
+    fMultiDrawIndirectSupport = false;
+    fBaseInstanceSupport = false;
     fUseNonVBOVertexAndIndexDynamicData = false;
     fIsCoreProfile = false;
     fBindFragDataLocationSupport = false;
@@ -482,6 +485,17 @@
                  ctxInfo.hasExtension("GL_EXT_instanced_arrays"));
     }
 
+    if (kGL_GrGLStandard == standard) {
+        // We don't use ARB_draw_indirect because it does not support a base instance.
+        // We don't use ARB_multi_draw_indirect because it does not support GL_DRAW_INDIRECT_BUFFER.
+        fDrawIndirectSupport =
+            fMultiDrawIndirectSupport = fBaseInstanceSupport = version >= GR_GL_VER(4,3);
+    } else {
+        fDrawIndirectSupport = version >= GR_GL_VER(3,1);
+        fMultiDrawIndirectSupport = ctxInfo.hasExtension("GL_EXT_multi_draw_indirect");
+        fBaseInstanceSupport = ctxInfo.hasExtension("GL_EXT_base_instance");
+    }
+
     this->initShaderPrecisionTable(ctxInfo, gli, glslCaps);
 
     if (contextOptions.fUseShaderSwizzling) {
@@ -936,6 +950,9 @@
     r.appendf("Direct state access support: %s\n", (fDirectStateAccessSupport ? "YES": "NO"));
     r.appendf("Debug support: %s\n", (fDebugSupport ? "YES": "NO"));
     r.appendf("Multisample disable support: %s\n", (fMultisampleDisableSupport ? "YES" : "NO"));
+    r.appendf("Draw indirect support: %s\n", (fDrawIndirectSupport ? "YES" : "NO"));
+    r.appendf("Multi draw indirect support: %s\n", (fMultiDrawIndirectSupport ? "YES" : "NO"));
+    r.appendf("Base instance support: %s\n", (fBaseInstanceSupport ? "YES" : "NO"));
     r.appendf("Use non-VBO for dynamic data: %s\n",
              (fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO"));
     r.appendf("SRGB write contol: %s\n", (fSRGBWriteControl ? "YES" : "NO"));
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 044ecce..abfcc28 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -283,6 +283,17 @@
     /// Can we call glDisable(GL_MULTISAMPLE)?
     bool multisampleDisableSupport() const { return fMultisampleDisableSupport; }
 
+    /// Is there support for glDraw*Indirect? Note that the baseInstance fields of indirect draw
+    /// commands cannot be used unless we have base instance support.
+    bool drawIndirectSupport() const { return fDrawIndirectSupport; }
+
+    /// Is there support for glMultiDraw*Indirect? Note that the baseInstance fields of indirect
+    /// draw commands cannot be used unless we have base instance support.
+    bool multiDrawIndirectSupport() const { return fMultiDrawIndirectSupport; }
+
+    /// Are the baseInstance fields supported in indirect draw commands?
+    bool baseInstanceSupport() const { return fBaseInstanceSupport; }
+
     /// Use indices or vertices in CPU arrays rather than VBOs for dynamic content.
     bool useNonVBOVertexAndIndexDynamicData() const { return fUseNonVBOVertexAndIndexDynamicData; }
 
@@ -378,6 +389,9 @@
     bool fDebugSupport : 1;
     bool fES2CompatibilitySupport : 1;
     bool fMultisampleDisableSupport : 1;
+    bool fDrawIndirectSupport : 1;
+    bool fMultiDrawIndirectSupport : 1;
+    bool fBaseInstanceSupport : 1;
     bool fUseNonVBOVertexAndIndexDynamicData : 1;
     bool fIsCoreProfile : 1;
     bool fBindFragDataLocationSupport : 1;
diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h
index a759413..9be769f 100644
--- a/src/gpu/gl/GrGLDefines.h
+++ b/src/gpu/gl/GrGLDefines.h
@@ -108,8 +108,10 @@
 /* Buffer Objects */
 #define GR_GL_ARRAY_BUFFER                   0x8892
 #define GR_GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GR_GL_DRAW_INDIRECT_BUFFER           0x8F3F
 #define GR_GL_ARRAY_BUFFER_BINDING           0x8894
 #define GR_GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+#define GR_GL_DRAW_INDIRECT_BUFFER_BINDING   0x8F43
 #define GR_GL_PIXEL_PACK_BUFFER              0x88EB
 #define GR_GL_PIXEL_UNPACK_BUFFER            0x88EC
 
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index b8d7db6..925f081 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -579,6 +579,22 @@
         }    
     }
 
+    if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
+        (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) {
+        if (NULL == fFunctions.fDrawArraysIndirect ||
+            NULL == fFunctions.fDrawElementsIndirect) {
+            RETURN_FALSE_INTERFACE
+        }
+    }
+
+    if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
+        (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_multi_draw_indirect"))) {
+        if (NULL == fFunctions.fMultiDrawArraysIndirect ||
+            NULL == fFunctions.fMultiDrawElementsIndirect) {
+            RETURN_FALSE_INTERFACE
+        }
+    }
+
     if (fExtensions.has("GL_NV_bindless_texture")) {
         if (nullptr == fFunctions.fGetTextureHandle ||
             nullptr == fFunctions.fGetTextureSamplerHandle ||