Add ES 3.0 fallback for instanced rendering

Adds the ability for GLInstancedRendering to use
glDrawElementsInstanced when glDrawElementsIndirect is not supported.

The only remaining 3.1 dependency now is EXT_texture_buffer.

Also moves the cap for glDraw*Instanced out of GrCaps and into
GrGLCaps.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2193303002

Review-Url: https://codereview.chromium.org/2193303002
diff --git a/src/gpu/instanced/GLInstancedRendering.cpp b/src/gpu/instanced/GLInstancedRendering.cpp
index 440796e..3af1aa7 100644
--- a/src/gpu/instanced/GLInstancedRendering.cpp
+++ b/src/gpu/instanced/GLInstancedRendering.cpp
@@ -34,7 +34,8 @@
 GrCaps::InstancedSupport GLInstancedRendering::CheckSupport(const GrGLCaps& glCaps) {
     // This method is only intended to be used for initializing fInstancedSupport in the caps.
     SkASSERT(GrCaps::InstancedSupport::kNone == glCaps.instancedSupport());
-    if (!glCaps.vertexArrayObjectSupport() || !glCaps.drawIndirectSupport()) {
+    if (!glCaps.vertexArrayObjectSupport() ||
+        (!glCaps.drawIndirectSupport() && !glCaps.drawInstancedSupport())) {
         return GrCaps::InstancedSupport::kNone;
     }
     return InstanceProcessor::CheckSupport(*glCaps.glslCaps(), glCaps);
@@ -118,23 +119,32 @@
     }
 
     SkASSERT(!fDrawIndirectBuffer);
-    fDrawIndirectBuffer.reset(
-        rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDrawCmds,
-                         kDrawIndirect_GrBufferType, kDynamic_GrAccessPattern,
-                         GrResourceProvider::kNoPendingIO_Flag |
-                         GrResourceProvider::kRequireGpuMemory_Flag));
-    if (!fDrawIndirectBuffer) {
-        return;
+    if (this->glGpu()->glCaps().drawIndirectSupport()) {
+        fDrawIndirectBuffer.reset(
+            rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDrawCmds,
+                             kDrawIndirect_GrBufferType, kDynamic_GrAccessPattern,
+                             GrResourceProvider::kNoPendingIO_Flag |
+                             GrResourceProvider::kRequireGpuMemory_Flag));
+        if (!fDrawIndirectBuffer) {
+            return;
+        }
     }
 
     Instance* glMappedInstances = static_cast<Instance*>(fInstanceBuffer->map());
+    SkASSERT(glMappedInstances);
     int glInstancesIdx = 0;
 
-    auto* glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndirectBuffer->map());
+    GrGLDrawElementsIndirectCommand* glMappedCmds = nullptr;
     int glDrawCmdsIdx = 0;
+    if (fDrawIndirectBuffer) {
+        glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndirectBuffer->map());
+        SkASSERT(glMappedCmds);
+    }
 
     bool baseInstanceSupport = this->glGpu()->glCaps().baseInstanceSupport();
+    SkASSERT(!baseInstanceSupport || fDrawIndirectBuffer);
 
+    SkASSERT(!fGLDrawCmdsInfo);
     if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) {
         fGLDrawCmdsInfo.reset(numGLDrawCmds);
     }
@@ -160,18 +170,19 @@
                 draw = draw->fNext;
             } while (draw && draw->fGeometry == geometry);
 
-            GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmdsIdx];
-            glCmd.fCount = geometry.fCount;
-            glCmd.fInstanceCount = instanceCount;
-            glCmd.fFirstIndex = geometry.fStart;
-            glCmd.fBaseVertex = 0;
-            glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0;
+            if (fDrawIndirectBuffer) {
+                GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmdsIdx];
+                glCmd.fCount = geometry.fCount;
+                glCmd.fInstanceCount = instanceCount;
+                glCmd.fFirstIndex = geometry.fStart;
+                glCmd.fBaseVertex = 0;
+                glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0;
+            }
 
             if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) {
-                fGLDrawCmdsInfo[glDrawCmdsIdx].fInstanceCount = instanceCount;
-#if GR_GL_LOG_INSTANCED_BATCHES
-                fGLDrawCmdsInfo[glDrawCmdsIdx].fGeometry = geometry;
-#endif
+                GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glDrawCmdsIdx];
+                cmdInfo.fGeometry = geometry;
+                cmdInfo.fInstanceCount = instanceCount;
             }
 
             glInstancesIdx += instanceCount;
@@ -180,7 +191,9 @@
     }
 
     SkASSERT(glDrawCmdsIdx == numGLDrawCmds);
-    fDrawIndirectBuffer->unmap();
+    if (fDrawIndirectBuffer) {
+        fDrawIndirectBuffer->unmap();
+    }
 
     SkASSERT(glInstancesIdx == numGLInstances);
     fInstanceBuffer->unmap();
@@ -188,14 +201,16 @@
 
 void GLInstancedRendering::onDraw(const GrPipeline& pipeline, const InstanceProcessor& instProc,
                                   const Batch* baseBatch) {
-    if (!fDrawIndirectBuffer) {
+    if (!fDrawIndirectBuffer && !fGLDrawCmdsInfo) {
         return; // beginFlush was not successful.
     }
     if (!this->glGpu()->flushGLState(pipeline, instProc)) {
         return;
     }
 
-    this->glGpu()->bindBuffer(kDrawIndirect_GrBufferType, fDrawIndirectBuffer.get());
+    if (fDrawIndirectBuffer) {
+        this->glGpu()->bindBuffer(kDrawIndirect_GrBufferType, fDrawIndirectBuffer.get());
+    }
 
     const GrGLCaps& glCaps = this->glGpu()->glCaps();
     const GLBatch* batch = static_cast<const GLBatch*>(baseBatch);
@@ -214,23 +229,33 @@
     SkASSERT(SkToBool(fGLDrawCmdsInfo) == !glCaps.baseInstanceSupport());
 #endif
 
-    if (1 == numCommands || !glCaps.baseInstanceSupport() || !glCaps.multiDrawIndirectSupport()) {
-        int emulatedBaseInstance = batch->fEmulatedBaseInstance;
-        for (int i = 0; i < numCommands; ++i) {
-            int glCmdIdx = batch->fGLDrawCmdsIdx + i;
-            this->flushInstanceAttribs(emulatedBaseInstance);
-            GL_CALL(DrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
-                                         (GrGLDrawElementsIndirectCommand*) nullptr + glCmdIdx));
-            if (!glCaps.baseInstanceSupport()) {
-                emulatedBaseInstance += fGLDrawCmdsInfo[glCmdIdx].fInstanceCount;
-            }
-        }
-    } else {
+    if (numCommands > 1 && glCaps.multiDrawIndirectSupport() && glCaps.baseInstanceSupport()) {
+        SkASSERT(fDrawIndirectBuffer);
         int glCmdsIdx = batch->fGLDrawCmdsIdx;
         this->flushInstanceAttribs(batch->fEmulatedBaseInstance);
         GL_CALL(MultiDrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
                                           (GrGLDrawElementsIndirectCommand*) nullptr + glCmdsIdx,
                                           numCommands, 0));
+        return;
+    }
+
+    int emulatedBaseInstance = batch->fEmulatedBaseInstance;
+    for (int i = 0; i < numCommands; ++i) {
+        int glCmdIdx = batch->fGLDrawCmdsIdx + i;
+        const GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glCmdIdx];
+        this->flushInstanceAttribs(emulatedBaseInstance);
+        if (fDrawIndirectBuffer) {
+            GL_CALL(DrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
+                                         (GrGLDrawElementsIndirectCommand*) nullptr + glCmdIdx));
+        } else {
+            GL_CALL(DrawElementsInstanced(GR_GL_TRIANGLES, cmdInfo.fGeometry.fCount,
+                                          GR_GL_UNSIGNED_BYTE,
+                                          (GrGLubyte*) nullptr + cmdInfo.fGeometry.fStart,
+                                          cmdInfo.fInstanceCount));
+        }
+        if (!glCaps.baseInstanceSupport()) {
+            emulatedBaseInstance += cmdInfo.fInstanceCount;
+        }
     }
 }