Re-implement line loops by constructing a 'looping' index buffer, so it is…

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
parent f654945b
...@@ -32,11 +32,6 @@ ...@@ -32,11 +32,6 @@
#undef near #undef near
#undef far #undef far
namespace
{
enum { CLOSING_INDEX_BUFFER_SIZE = 4096 };
}
namespace gl namespace gl
{ {
Context::Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) : mConfig(config) Context::Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) : mConfig(config)
...@@ -153,7 +148,7 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo ...@@ -153,7 +148,7 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo
mVertexDataManager = NULL; mVertexDataManager = NULL;
mIndexDataManager = NULL; mIndexDataManager = NULL;
mBlit = NULL; mBlit = NULL;
mClosingIB = NULL; mLineLoopIB = NULL;
mInvalidEnum = false; mInvalidEnum = false;
mInvalidValue = false; mInvalidValue = false;
...@@ -244,7 +239,7 @@ Context::~Context() ...@@ -244,7 +239,7 @@ Context::~Context()
delete mVertexDataManager; delete mVertexDataManager;
delete mIndexDataManager; delete mIndexDataManager;
delete mBlit; delete mBlit;
delete mClosingIB; delete mLineLoopIB;
if (mMaskedClearSavedState) if (mMaskedClearSavedState)
{ {
...@@ -2964,11 +2959,11 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan ...@@ -2964,11 +2959,11 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan
{ {
mDisplay->startScene(); 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); StaticIndexBuffer *countingIB = mIndexDataManager->getCountingIndices(count);
if (countingIB) if (countingIB)
...@@ -2987,10 +2982,9 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan ...@@ -2987,10 +2982,9 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan
return error(GL_OUT_OF_MEMORY); return error(GL_OUT_OF_MEMORY);
} }
} }
else // Regular case
if (mode == GL_LINE_LOOP) // Draw the last segment separately
{ {
drawClosingLine(0, count - 1, 0); mDevice->DrawPrimitive(primitiveType, 0, primitiveCount);
} }
} }
} }
...@@ -3051,11 +3045,13 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid ...@@ -3051,11 +3045,13 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid
{ {
mDisplay->startScene(); mDisplay->startScene();
mDevice->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount); if (mode == GL_LINE_LOOP)
if (mode == GL_LINE_LOOP) // Draw the last segment separately
{ {
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 @@ void Context::sync(bool block) ...@@ -3066,98 +3062,149 @@ void Context::sync(bool block)
mDisplay->sync(block); 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)
{ {
// 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;
}
UINT startIndex = 0;
bool succeeded = false; bool succeeded = false;
UINT offset;
if (supports32bitIndices()) if (supports32bitIndices())
{ {
const int spaceNeeded = 2 * sizeof(unsigned int); const int spaceNeeded = (count + 1) * sizeof(unsigned int);
if (!mClosingIB) if (!mLineLoopIB)
{ {
mClosingIB = new StreamingIndexBuffer(mDevice, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX32); mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
} }
mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT); 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;
unsigned int *data = static_cast<unsigned int*>(mClosingIB->map(spaceNeeded, &offset));
if (data) if (data)
{ {
data[0] = last; switch (type)
data[1] = first; {
mClosingIB->unmap(); case GL_NONE: // Non-indexed draw
offset /= 4; for (int i = 0; i < count; i++)
succeeded = true; {
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];
} }
else data[count] = static_cast<const GLubyte*>(indices)[0];
break;
case GL_UNSIGNED_SHORT:
for (int i = 0; i < count; i++)
{ {
const int spaceNeeded = 2 * sizeof(unsigned short); data[i] = static_cast<const GLushort*>(indices)[i];
}
if (!mClosingIB) data[count] = static_cast<const GLushort*>(indices)[0];
break;
case GL_UNSIGNED_INT:
for (int i = 0; i < count; i++)
{ {
mClosingIB = new StreamingIndexBuffer(mDevice, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX16); data[i] = static_cast<const GLuint*>(indices)[i];
}
data[count] = static_cast<const GLuint*>(indices)[0];
break;
default: UNREACHABLE();
} }
mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT); mLineLoopIB->unmap();
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; succeeded = true;
} }
} }
if (succeeded)
{
mDevice->SetIndices(mClosingIB->getBuffer());
mAppliedIBSerial = mClosingIB->getSerial();
mDevice->DrawIndexedPrimitive(D3DPT_LINELIST, -minIndex, minIndex, last, offset, 1);
} }
else else
{ {
ERR("Could not create an index buffer for closing a line loop."); const int spaceNeeded = (count + 1) * sizeof(unsigned short);
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()) if (!mLineLoopIB)
{ {
Buffer *indexBuffer = mState.elementArrayBuffer.get(); mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
intptr_t offset = reinterpret_cast<intptr_t>(indices);
indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset;
} }
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) 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: case GL_UNSIGNED_BYTE:
first = static_cast<const GLubyte*>(indices)[0]; for (int i = 0; i < count; i++)
last = static_cast<const GLubyte*>(indices)[count - 1]; {
data[i] = static_cast<const GLubyte*>(indices)[i];
}
data[count] = static_cast<const GLubyte*>(indices)[0];
break; break;
case GL_UNSIGNED_SHORT: case GL_UNSIGNED_SHORT:
first = static_cast<const GLushort*>(indices)[0]; for (int i = 0; i < count; i++)
last = static_cast<const GLushort*>(indices)[count - 1]; {
data[i] = static_cast<const GLushort*>(indices)[i];
}
data[count] = static_cast<const GLushort*>(indices)[0];
break; break;
case GL_UNSIGNED_INT: case GL_UNSIGNED_INT:
first = static_cast<const GLuint*>(indices)[0]; for (int i = 0; i < count; i++)
last = static_cast<const GLuint*>(indices)[count - 1]; {
data[i] = static_cast<const GLuint*>(indices)[i];
}
data[count] = static_cast<const GLuint*>(indices)[0];
break; break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
drawClosingLine(first, last, minIndex); 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() void Context::recordInvalidEnum()
......
...@@ -457,9 +457,7 @@ class Context ...@@ -457,9 +457,7 @@ class Context
void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances); void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances);
void sync(bool block); // flush/finish void sync(bool block); // flush/finish
// Draw the last segment of a line loop void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex);
void drawClosingLine(unsigned int first, unsigned int last, int minIndex);
void drawClosingLine(GLsizei count, GLenum type, const GLvoid *indices, int minIndex);
void recordInvalidEnum(); void recordInvalidEnum();
void recordInvalidValue(); void recordInvalidValue();
...@@ -561,7 +559,7 @@ class Context ...@@ -561,7 +559,7 @@ class Context
Blit *mBlit; Blit *mBlit;
StreamingIndexBuffer *mClosingIB; StreamingIndexBuffer *mLineLoopIB;
BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT]; BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT];
......
...@@ -15,11 +15,6 @@ ...@@ -15,11 +15,6 @@
#include "libGLESv2/mathutil.h" #include "libGLESv2/mathutil.h"
#include "libGLESv2/main.h" #include "libGLESv2/main.h"
namespace
{
enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
}
namespace gl namespace gl
{ {
unsigned int IndexBuffer::mCurrentSerial = 1; unsigned int IndexBuffer::mCurrentSerial = 1;
......
...@@ -18,6 +18,11 @@ ...@@ -18,6 +18,11 @@
#include "libGLESv2/Context.h" #include "libGLESv2/Context.h"
namespace
{
enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
}
namespace gl namespace gl
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment