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 @@
#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 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo
mVertexDataManager = NULL;
mIndexDataManager = NULL;
mBlit = NULL;
mClosingIB = NULL;
mLineLoopIB = NULL;
mInvalidEnum = false;
mInvalidValue = false;
......@@ -244,7 +239,7 @@ Context::~Context()
delete mVertexDataManager;
delete mIndexDataManager;
delete mBlit;
delete mClosingIB;
delete mLineLoopIB;
if (mMaskedClearSavedState)
{
......@@ -2964,11 +2959,11 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan
{
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 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan
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 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid
{
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)
{
drawLineLoop(count, type, indices, indexInfo.minIndex);
}
else
{
drawClosingLine(count, type, indices, indexInfo.minIndex);
mDevice->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount);
}
}
}
......@@ -3066,98 +3062,149 @@ void Context::sync(bool 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;
UINT offset;
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);
unsigned int *data = static_cast<unsigned int*>(mClosingIB->map(spaceNeeded, &offset));
if (data)
if (mLineLoopIB)
{
data[0] = last;
data[1] = first;
mClosingIB->unmap();
offset /= 4;
succeeded = true;
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 = 2 * sizeof(unsigned short);
const int spaceNeeded = (count + 1) * sizeof(unsigned short);
if (!mClosingIB)
if (!mLineLoopIB)
{
mClosingIB = new StreamingIndexBuffer(mDevice, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
}
mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
unsigned short *data = static_cast<unsigned short*>(mClosingIB->map(spaceNeeded, &offset));
if (data)
if (mLineLoopIB)
{
data[0] = last;
data[1] = first;
mClosingIB->unmap();
offset /= 2;
succeeded = true;
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)
{
mDevice->SetIndices(mClosingIB->getBuffer());
mAppliedIBSerial = mClosingIB->getSerial();
if (mAppliedIBSerial != mLineLoopIB->getSerial())
{
mDevice->SetIndices(mLineLoopIB->getBuffer());
mAppliedIBSerial = mLineLoopIB->getSerial();
}
mDevice->DrawIndexedPrimitive(D3DPT_LINELIST, -minIndex, minIndex, last, offset, 1);
mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
}
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())
{
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();
ERR("Could not create a looping index buffer for GL_LINE_LOOP.");
return error(GL_OUT_OF_MEMORY);
}
drawClosingLine(first, last, minIndex);
}
void Context::recordInvalidEnum()
......
......@@ -457,9 +457,7 @@ class Context
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 @@ class Context
Blit *mBlit;
StreamingIndexBuffer *mClosingIB;
StreamingIndexBuffer *mLineLoopIB;
BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT];
......
......@@ -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;
......
......@@ -18,6 +18,11 @@
#include "libGLESv2/Context.h"
namespace
{
enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
}
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