Re-implement line loops by constructing a 'looping' index buffer, so it is compatible with instanced draws.
TRAC #19489
Signed-off-by: Daniel Koch
Author: Nicolas Capens
git-svn-id: https://angleproject.googlecode.com/svn/trunk@973 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 096874e..9d63e6b 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -32,11 +32,6 @@
#undef near
#undef far
-namespace
-{
- enum { CLOSING_INDEX_BUFFER_SIZE = 4096 };
-}
-
namespace gl
{
Context::Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) : mConfig(config)
@@ -153,7 +148,7 @@
mVertexDataManager = NULL;
mIndexDataManager = NULL;
mBlit = NULL;
- mClosingIB = NULL;
+ mLineLoopIB = NULL;
mInvalidEnum = false;
mInvalidValue = false;
@@ -244,7 +239,7 @@
delete mVertexDataManager;
delete mIndexDataManager;
delete mBlit;
- delete mClosingIB;
+ delete mLineLoopIB;
if (mMaskedClearSavedState)
{
@@ -2964,11 +2959,11 @@
{
mDisplay->startScene();
- if (instances == 0)
+ if (mode == GL_LINE_LOOP)
{
- mDevice->DrawPrimitive(primitiveType, 0, primitiveCount);
+ drawLineLoop(count, GL_NONE, NULL, 0);
}
- else
+ else if (instances > 0)
{
StaticIndexBuffer *countingIB = mIndexDataManager->getCountingIndices(count);
if (countingIB)
@@ -2987,10 +2982,9 @@
return error(GL_OUT_OF_MEMORY);
}
}
-
- if (mode == GL_LINE_LOOP) // Draw the last segment separately
+ else // Regular case
{
- drawClosingLine(0, count - 1, 0);
+ mDevice->DrawPrimitive(primitiveType, 0, primitiveCount);
}
}
}
@@ -3051,11 +3045,13 @@
{
mDisplay->startScene();
- mDevice->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount);
-
- if (mode == GL_LINE_LOOP) // Draw the last segment separately
+ if (mode == GL_LINE_LOOP)
{
- drawClosingLine(count, type, indices, indexInfo.minIndex);
+ drawLineLoop(count, type, indices, indexInfo.minIndex);
+ }
+ else
+ {
+ mDevice->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount);
}
}
}
@@ -3066,98 +3062,149 @@
mDisplay->sync(block);
}
-void Context::drawClosingLine(unsigned int first, unsigned int last, int minIndex)
+void Context::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex)
{
- bool succeeded = false;
- UINT offset;
-
- if (supports32bitIndices())
- {
- const int spaceNeeded = 2 * sizeof(unsigned int);
-
- if (!mClosingIB)
- {
- mClosingIB = new StreamingIndexBuffer(mDevice, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
- }
-
- mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
-
- unsigned int *data = static_cast<unsigned int*>(mClosingIB->map(spaceNeeded, &offset));
- if (data)
- {
- data[0] = last;
- data[1] = first;
- mClosingIB->unmap();
- offset /= 4;
- succeeded = true;
- }
- }
- else
- {
- const int spaceNeeded = 2 * sizeof(unsigned short);
-
- if (!mClosingIB)
- {
- mClosingIB = new StreamingIndexBuffer(mDevice, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
- }
-
- mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
-
- unsigned short *data = static_cast<unsigned short*>(mClosingIB->map(spaceNeeded, &offset));
- if (data)
- {
- data[0] = last;
- data[1] = first;
- mClosingIB->unmap();
- offset /= 2;
- succeeded = true;
- }
- }
-
- if (succeeded)
- {
- mDevice->SetIndices(mClosingIB->getBuffer());
- mAppliedIBSerial = mClosingIB->getSerial();
-
- mDevice->DrawIndexedPrimitive(D3DPT_LINELIST, -minIndex, minIndex, last, offset, 1);
- }
- else
- {
- ERR("Could not create an index buffer for closing a line loop.");
- error(GL_OUT_OF_MEMORY);
- }
-}
-
-void Context::drawClosingLine(GLsizei count, GLenum type, const GLvoid *indices, int minIndex)
-{
- unsigned int first = 0;
- unsigned int last = 0;
-
- if (mState.elementArrayBuffer.get())
+ // Get the raw indices for an indexed draw
+ if (type != GL_NONE && mState.elementArrayBuffer.get())
{
Buffer *indexBuffer = mState.elementArrayBuffer.get();
intptr_t offset = reinterpret_cast<intptr_t>(indices);
indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset;
}
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- first = static_cast<const GLubyte*>(indices)[0];
- last = static_cast<const GLubyte*>(indices)[count - 1];
- break;
- case GL_UNSIGNED_SHORT:
- first = static_cast<const GLushort*>(indices)[0];
- last = static_cast<const GLushort*>(indices)[count - 1];
- break;
- case GL_UNSIGNED_INT:
- first = static_cast<const GLuint*>(indices)[0];
- last = static_cast<const GLuint*>(indices)[count - 1];
- break;
- default: UNREACHABLE();
- }
+ UINT startIndex = 0;
+ bool succeeded = false;
- drawClosingLine(first, last, minIndex);
+ if (supports32bitIndices())
+ {
+ const int spaceNeeded = (count + 1) * sizeof(unsigned int);
+
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
+ }
+
+ if (mLineLoopIB)
+ {
+ mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
+
+ UINT offset = 0;
+ unsigned int *data = static_cast<unsigned int*>(mLineLoopIB->map(spaceNeeded, &offset));
+ startIndex = offset / 4;
+
+ if (data)
+ {
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte*>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte*>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort*>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort*>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint*>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint*>(indices)[0];
+ break;
+ default: UNREACHABLE();
+ }
+
+ mLineLoopIB->unmap();
+ succeeded = true;
+ }
+ }
+ }
+ else
+ {
+ const int spaceNeeded = (count + 1) * sizeof(unsigned short);
+
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
+ }
+
+ if (mLineLoopIB)
+ {
+ mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+
+ UINT offset = 0;
+ unsigned short *data = static_cast<unsigned short*>(mLineLoopIB->map(spaceNeeded, &offset));
+ startIndex = offset / 2;
+
+ if (data)
+ {
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte*>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte*>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort*>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort*>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint*>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint*>(indices)[0];
+ break;
+ default: UNREACHABLE();
+ }
+
+ mLineLoopIB->unmap();
+ succeeded = true;
+ }
+ }
+ }
+
+ if (succeeded)
+ {
+ if (mAppliedIBSerial != mLineLoopIB->getSerial())
+ {
+ mDevice->SetIndices(mLineLoopIB->getBuffer());
+ mAppliedIBSerial = mLineLoopIB->getSerial();
+ }
+
+ mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
+ }
+ else
+ {
+ ERR("Could not create a looping index buffer for GL_LINE_LOOP.");
+ return error(GL_OUT_OF_MEMORY);
+ }
}
void Context::recordInvalidEnum()
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 58b7abc..e094f61 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -457,9 +457,7 @@
void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances);
void sync(bool block); // flush/finish
- // Draw the last segment of a line loop
- void drawClosingLine(unsigned int first, unsigned int last, int minIndex);
- void drawClosingLine(GLsizei count, GLenum type, const GLvoid *indices, int minIndex);
+ void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex);
void recordInvalidEnum();
void recordInvalidValue();
@@ -561,7 +559,7 @@
Blit *mBlit;
- StreamingIndexBuffer *mClosingIB;
+ StreamingIndexBuffer *mLineLoopIB;
BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT];
diff --git a/src/libGLESv2/IndexDataManager.cpp b/src/libGLESv2/IndexDataManager.cpp
index e2e307d..3dc0aef 100644
--- a/src/libGLESv2/IndexDataManager.cpp
+++ b/src/libGLESv2/IndexDataManager.cpp
@@ -15,11 +15,6 @@
#include "libGLESv2/mathutil.h"
#include "libGLESv2/main.h"
-namespace
-{
- enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
-}
-
namespace gl
{
unsigned int IndexBuffer::mCurrentSerial = 1;
diff --git a/src/libGLESv2/IndexDataManager.h b/src/libGLESv2/IndexDataManager.h
index 3496d12..c1d4168 100644
--- a/src/libGLESv2/IndexDataManager.h
+++ b/src/libGLESv2/IndexDataManager.h
@@ -18,6 +18,11 @@
#include "libGLESv2/Context.h"
+namespace
+{
+ enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
+}
+
namespace gl
{