Implemented glDrawRangeElements

This function is basically the same as
glDrawElements, except, in Debug, it
returns an error if the draw operation
reads outside of the expected range.

Change-Id: I2472c317eb5d8a1da89c5a76f076fe95adc6789e
Reviewed-on: https://swiftshader-review.googlesource.com/2829
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 70beb74..bc6064c 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -2700,9 +2700,9 @@
 }

 

 // Applies the indices and element array bindings

-GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)

+GLenum Context::applyIndexBuffer(const void *indices, GLuint start, GLuint end, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)

 {

-    GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer, indices, indexInfo);

+    GLenum err = mIndexDataManager->prepareIndexData(type, start, end, count, mState.elementArrayBuffer, indices, indexInfo);

 

     if(err == GL_NO_ERROR)

     {

@@ -3285,7 +3285,7 @@
     }

 }

 

-void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)

+void Context::drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices)

 {

     if(!mState.currentProgram)

     {

@@ -3316,7 +3316,7 @@
     applyState(mode);

 

     TranslatedIndexData indexInfo;

-    GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);

+    GLenum err = applyIndexBuffer(indices, start, end, count, mode, type, &indexInfo);

     if(err != GL_NO_ERROR)

     {

         return error(err);

diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index 995015a..b2bd8ee 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -553,7 +553,7 @@
     void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);

     void clear(GLbitfield mask);

     void drawArrays(GLenum mode, GLint first, GLsizei count);

-    void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);

+    void drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);

     void finish();

     void flush();

 

@@ -585,7 +585,7 @@
     bool applyRenderTarget();

     void applyState(GLenum drawMode);

     GLenum applyVertexBuffer(GLint base, GLint first, GLsizei count);

-    GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);

+    GLenum applyIndexBuffer(const void *indices, GLuint start, GLuint end, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);

     void applyShaders();

     void applyTextures();

     void applyTextures(sw::SamplerType type);

diff --git a/src/OpenGL/libGLESv2/IndexDataManager.cpp b/src/OpenGL/libGLESv2/IndexDataManager.cpp
index a2b468c..0bf93f0 100644
--- a/src/OpenGL/libGLESv2/IndexDataManager.cpp
+++ b/src/OpenGL/libGLESv2/IndexDataManager.cpp
@@ -90,7 +90,7 @@
     else UNREACHABLE();

 }

 

-GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated)

+GLenum IndexDataManager::prepareIndexData(GLenum type, GLuint start, GLuint end, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated)

 {

     if(!mStreamingBuffer)

     {

@@ -152,6 +152,11 @@
 		translated->indexOffset = streamOffset;

     }

 

+	if(translated->minIndex < start || translated->maxIndex > end)

+	{

+		ERR("glDrawRangeElements: out of range access. Range provided: [%d -> %d]. Range used: [%d -> %d].", start, end, translated->minIndex, translated->maxIndex);

+	}

+

     return GL_NO_ERROR;

 }

 

diff --git a/src/OpenGL/libGLESv2/IndexDataManager.h b/src/OpenGL/libGLESv2/IndexDataManager.h
index 0bab66e..5ff6d94 100644
--- a/src/OpenGL/libGLESv2/IndexDataManager.h
+++ b/src/OpenGL/libGLESv2/IndexDataManager.h
@@ -56,7 +56,7 @@
     IndexDataManager();

     virtual ~IndexDataManager();

 

-    GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated);

+    GLenum prepareIndexData(GLenum type, GLuint start, GLuint end, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated);

 

 	static std::size_t typeSize(GLenum type);

 

diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index 3277120..e528154 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -1819,7 +1819,7 @@
 			return error(GL_INVALID_ENUM);

 		}

 

-		context->drawElements(mode, count, type, indices);

+		context->drawElements(mode, 0, UINT_MAX, count, type, indices);

 	}

 }

 

diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 05f2468..4d4964a 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -517,7 +517,12 @@
 		return error(GL_INVALID_VALUE);

 	}

 

-	UNIMPLEMENTED();

+	es2::Context *context = es2::getContext();

+

+	if(context)

+	{

+		context->drawElements(mode, start, end, count, type, indices);

+	}

 }

 

 void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels)