Add support for glDrawRangeElements
authorbsalomon <bsalomon@google.com>
Mon, 29 Aug 2016 16:18:39 +0000 (09:18 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 29 Aug 2016 16:18:39 +0000 (09:18 -0700)
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2287003002

Review-Url: https://codereview.chromium.org/2287003002

include/gpu/gl/GrGLFunctions.h
include/gpu/gl/GrGLInterface.h
src/gpu/gl/GrGLAssembleInterface.cpp
src/gpu/gl/GrGLCaps.cpp
src/gpu/gl/GrGLCaps.h
src/gpu/gl/GrGLGpu.cpp
src/gpu/gl/GrGLInterface.cpp
src/gpu/gl/GrGLTestInterface.cpp
src/gpu/gl/GrGLTestInterface.h

index 4dff208a9b9a48c7bbf75d23b547813a900120ef..7e720cd867c887f68abea37860d893f4eacded46 100644 (file)
@@ -66,6 +66,7 @@ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawBuffersProc)(GrGLsizei n, const G
 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, const GrGLvoid* indirect);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawRangeElementsProc)(GrGLenum mode, GrGLuint start, GrGLuint end, GrGLsizei count, GrGLenum type, const GrGLvoid* indices);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEnableProc)(GrGLenum cap);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEnableVertexAttribArrayProc)(GrGLuint index);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEndQueryProc)(GrGLenum target);
index 0603e9e1d6d520ded6cd941c5710a5ca67ce02d9..27184adcb5581ddc5c737e4594bfbbb57574801e 100644 (file)
@@ -155,6 +155,7 @@ public:
         GrGLFunction<GrGLDrawElementsProc> fDrawElements;
         GrGLFunction<GrGLDrawElementsIndirectProc> fDrawElementsIndirect;
         GrGLFunction<GrGLDrawElementsInstancedProc> fDrawElementsInstanced;
+        GrGLFunction<GrGLDrawRangeElementsProc> fDrawRangeElements;
         GrGLFunction<GrGLEnableProc> fEnable;
         GrGLFunction<GrGLEnableVertexAttribArrayProc> fEnableVertexAttribArray;
         GrGLFunction<GrGLEndQueryProc> fEndQuery;
index 2233005b6a01e63d7d83801ee1fc6f35b54441e2..e804dd605a4029b003e40e33afb59c49b67ff5ed 100644 (file)
@@ -148,7 +148,9 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
         GET_PROC(DrawArraysIndirect);
         GET_PROC(DrawElementsIndirect);
     }
-
+    if (glVer >= GR_GL_VER(2,0)) {
+        GET_PROC(DrawRangeElements);
+    }
     GET_PROC(Enable);
     GET_PROC(EnableVertexAttribArray);
     GET_PROC(EndQuery);
@@ -615,6 +617,9 @@ const GrGLInterface* GrGLAssembleGLESInterface(void* ctx, GrGLGetProc get) {
     }
 
     GET_PROC(DrawElements);
+    if (version >= GR_GL_VER(3,0)) {
+        GET_PROC(DrawRangeElements);
+    }
     GET_PROC(Enable);
     GET_PROC(EnableVertexAttribArray);
     GET_PROC(Finish);
index 255d5163025329b225db6496a6e0ac66ceac5ea3..b6e9f22fa54d1c62f1349df2f3babe42fc4ae9dc 100644 (file)
@@ -525,12 +525,14 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
                                     (fDrawIndirectSupport &&
                                      !fBaseInstanceSupport && // The ARB extension has no base inst.
                                      ctxInfo.hasExtension("GL_ARB_multi_draw_indirect"));
+        fDrawRangeElementsSupport = version >= GR_GL_VER(2,0);
     } else {
         fDrawIndirectSupport = version >= GR_GL_VER(3,1);
         fMultiDrawIndirectSupport = fDrawIndirectSupport &&
                                     ctxInfo.hasExtension("GL_EXT_multi_draw_indirect");
         fBaseInstanceSupport = fDrawIndirectSupport &&
                                ctxInfo.hasExtension("GL_EXT_base_instance");
+        fDrawRangeElementsSupport = version >= GR_GL_VER(3,0);
     }
 
     this->initShaderPrecisionTable(ctxInfo, gli, glslCaps);
index 3408ae0e8fddef5589034283d543bf07f82d7a3b..f0b09407aaf63d0134c3f3fa5a37c1b1ed268fca 100644 (file)
@@ -307,6 +307,9 @@ public:
     /// draw commands cannot be used unless we have base instance support.
     bool multiDrawIndirectSupport() const { return fMultiDrawIndirectSupport; }
 
+    /// Is there support for glDrawRangeElements?
+    bool drawRangeElementsSupport() const { return fDrawRangeElementsSupport; }
+
     /// Are the baseInstance fields supported in indirect draw commands?
     bool baseInstanceSupport() const { return fBaseInstanceSupport; }
 
@@ -400,6 +403,7 @@ private:
     bool fES2CompatibilitySupport : 1;
     bool fDrawInstancedSupport : 1;
     bool fDrawIndirectSupport : 1;
+    bool fDrawRangeElementsSupport : 1;
     bool fMultiDrawIndirectSupport : 1;
     bool fBaseInstanceSupport : 1;
     bool fUseNonVBOVertexAndIndexDynamicData : 1;
index 83d2df29bfdb81a4c21540604a4c4d9dc1e55c58..9981b66075427de65e4af3a28258095bad4b81e2 100644 (file)
@@ -2762,28 +2762,40 @@ void GrGLGpu::draw(const GrPipeline& pipeline,
 
         const GrMesh& mesh = meshes[i];
         GrMesh::Iterator iter;
-        const GrNonInstancedMesh* nonIdxMesh = iter.init(mesh);
+        const GrNonInstancedMesh* nonInstMesh = iter.init(mesh);
         do {
             size_t indexOffsetInBytes = 0;
-            this->setupGeometry(primProc, *nonIdxMesh, &indexOffsetInBytes);
-            if (nonIdxMesh->isIndexed()) {
+            this->setupGeometry(primProc, *nonInstMesh, &indexOffsetInBytes);
+            if (nonInstMesh->isIndexed()) {
                 GrGLvoid* indices =
-                    reinterpret_cast<GrGLvoid*>(indexOffsetInBytes + sizeof(uint16_t) *
-                    nonIdxMesh->startIndex());
+                    reinterpret_cast<GrGLvoid*>(indexOffsetInBytes +
+                                                sizeof(uint16_t) * nonInstMesh->startIndex());
                 // info.startVertex() was accounted for by setupGeometry.
-                GL_CALL(DrawElements(gPrimitiveType2GLMode[nonIdxMesh->primitiveType()],
-                                     nonIdxMesh->indexCount(),
-                                     GR_GL_UNSIGNED_SHORT,
-                                     indices));
+                if (this->glCaps().drawRangeElementsSupport()) {
+                    // We assume here that the batch that generated the mesh used the full
+                    // 0..vertexCount()-1 range.
+                    int start = 0;
+                    int end = nonInstMesh->vertexCount() - 1;
+                    GL_CALL(DrawRangeElements(gPrimitiveType2GLMode[nonInstMesh->primitiveType()],
+                                              start, end,
+                                              nonInstMesh->indexCount(),
+                                              GR_GL_UNSIGNED_SHORT,
+                                              indices));
+                } else {
+                    GL_CALL(DrawElements(gPrimitiveType2GLMode[nonInstMesh->primitiveType()],
+                                         nonInstMesh->indexCount(),
+                                         GR_GL_UNSIGNED_SHORT,
+                                         indices));
+                }
             } else {
                 // Pass 0 for parameter first. We have to adjust glVertexAttribPointer() to account
                 // for startVertex in the DrawElements case. So we always rely on setupGeometry to
                 // have accounted for startVertex.
-                GL_CALL(DrawArrays(gPrimitiveType2GLMode[nonIdxMesh->primitiveType()], 0,
-                                   nonIdxMesh->vertexCount()));
+                GL_CALL(DrawArrays(gPrimitiveType2GLMode[nonInstMesh->primitiveType()], 0,
+                                   nonInstMesh->vertexCount()));
             }
             fStats.incNumDraws();
-        } while ((nonIdxMesh = iter.next()));
+        } while ((nonInstMesh = iter.next()));
     }
 
     if (fHWPLSEnabled && plsState == GrPixelLocalStorageState::kFinish_GrPixelLocalStorageState) {
index ada6d8bc298ce5c0411ac27222fa0b1c46705090..c3fc8a8e8138db14d900f237edf22072d1233ef5 100644 (file)
@@ -793,5 +793,15 @@ bool GrGLInterface::validate() const {
         }
     }
 
+    if (kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(2,0)) {
+        if (nullptr == fFunctions.fDrawRangeElements) {
+            RETURN_FALSE_INTERFACE;
+        }
+    } else if (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0)) {
+        if (nullptr == fFunctions.fDrawRangeElements) {
+            RETURN_FALSE_INTERFACE;
+        }
+    }
+
     return true;
 }
index c9925874f789afb7287585d969d701596416d302..10968a784e832f0afa3aa2fbb81775f0ec287bde 100644 (file)
@@ -65,6 +65,7 @@ GrGLTestInterface::GrGLTestInterface() {
     fFunctions.fDrawElements = bind_to_member(this, &GrGLTestInterface::drawElements);
     fFunctions.fDrawElementsInstanced = bind_to_member(this, &GrGLTestInterface::drawElementsInstanced);
     fFunctions.fDrawElementsIndirect = bind_to_member(this, &GrGLTestInterface::drawElementsIndirect);
+    fFunctions.fDrawRangeElements = bind_to_member(this, &GrGLTestInterface::drawRangeElements);
     fFunctions.fEnable = bind_to_member(this, &GrGLTestInterface::enable);
     fFunctions.fEnableVertexAttribArray = bind_to_member(this, &GrGLTestInterface::enableVertexAttribArray);
     fFunctions.fEndQuery = bind_to_member(this, &GrGLTestInterface::endQuery);
index 8f8a8bc4e564f367a2141e07bdbd4f99c0840182..fc837bfec4902b5f5fbc7ba26fe60c2073d5bf18 100644 (file)
@@ -66,6 +66,7 @@ public:
     virtual GrGLvoid drawElements(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid* indices) {}
     virtual GrGLvoid drawElementsInstanced(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid *indices, GrGLsizei primcount) {}
     virtual GrGLvoid drawElementsIndirect(GrGLenum mode, GrGLenum type, const GrGLvoid* indirect) {}
+    virtual GrGLvoid drawRangeElements(GrGLenum mode, GrGLuint start, GrGLuint end, GrGLsizei count, GrGLenum type, const GrGLvoid* indices) {}
     virtual GrGLvoid enable(GrGLenum cap) {}
     virtual GrGLvoid enableVertexAttribArray(GrGLuint index) {}
     virtual GrGLvoid endQuery(GrGLenum target) {}