mirror of
https://github.com/love2d/love.git
synced 2026-08-17 11:00:31 +02:00
Make internal vertex attribute code less OpenGL-specific.
--HG-- branch : minor
This commit is contained in:
@@ -353,7 +353,9 @@ void Graphics::flushStreamDraws()
|
||||
|
||||
OpenGL::TempDebugGroup debuggroup("Stream vertices flush and draw");
|
||||
|
||||
uint32 attribs = 0;
|
||||
Attributes attributes;
|
||||
Buffers buffers;
|
||||
|
||||
size_t usedsizes[3] = {0, 0, 0};
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
@@ -361,26 +363,20 @@ void Graphics::flushStreamDraws()
|
||||
if (sbstate.formats[i] == CommonFormat::NONE)
|
||||
continue;
|
||||
|
||||
attributes.setCommonFormat(sbstate.formats[i], (uint8) i);
|
||||
|
||||
usedsizes[i] = getFormatStride(sbstate.formats[i]) * sbstate.vertexCount;
|
||||
|
||||
love::graphics::StreamBuffer *buffer = sbstate.vb[i];
|
||||
|
||||
gl.bindBuffer(BUFFER_VERTEX, (GLuint) buffer->getHandle());
|
||||
size_t offset = buffer->unmap(usedsizes[i]);
|
||||
|
||||
size_t offset = sbstate.vb[i]->unmap(usedsizes[i]);
|
||||
buffers.set(i, sbstate.vb[i], offset);
|
||||
sbstate.vbMap[i] = StreamBuffer::MapInfo();
|
||||
|
||||
gl.setVertexPointers(sbstate.formats[i], offset);
|
||||
attribs |= getFormatFlags(sbstate.formats[i]);
|
||||
}
|
||||
|
||||
if (attribs == 0)
|
||||
if (attributes.enablebits == 0)
|
||||
return;
|
||||
|
||||
GLenum glprimitivetype = OpenGL::getGLPrimitiveType(sbstate.primitiveMode);
|
||||
|
||||
Colorf nc = gl.getConstantColor();
|
||||
if (attribs & ATTRIBFLAG_COLOR)
|
||||
if (attributes.isEnabled(ATTRIB_COLOR))
|
||||
gl.setConstantColor(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
|
||||
pushIdentityTransform();
|
||||
@@ -388,7 +384,9 @@ void Graphics::flushStreamDraws()
|
||||
gl.prepareDraw();
|
||||
gl.bindTextureToUnit(sbstate.texture, 0, false);
|
||||
|
||||
gl.useVertexAttribArrays(attribs);
|
||||
gl.setVertexAttributes(attributes, buffers);
|
||||
|
||||
GLenum glprimitivetype = OpenGL::getGLPrimitiveType(sbstate.primitiveMode);
|
||||
|
||||
if (sbstate.indexCount > 0)
|
||||
{
|
||||
@@ -415,7 +413,7 @@ void Graphics::flushStreamDraws()
|
||||
|
||||
popTransform();
|
||||
|
||||
if (attribs & ATTRIB_CONSTANTCOLOR)
|
||||
if (attributes.isEnabled(ATTRIB_COLOR))
|
||||
gl.setConstantColor(nc);
|
||||
|
||||
streamBufferState.vertexCount = 0;
|
||||
|
||||
@@ -49,44 +49,11 @@ Mesh::~Mesh()
|
||||
{
|
||||
}
|
||||
|
||||
int Mesh::bindAttributeToShaderInput(int attributeindex, const std::string &inputname)
|
||||
{
|
||||
const AttribFormat &format = vertexFormat[attributeindex];
|
||||
|
||||
GLint attriblocation = -1;
|
||||
|
||||
// If the attribute is one of the LOVE-defined ones, use the constant
|
||||
// attribute index for it, otherwise query the index from the shader.
|
||||
VertexAttribID builtinattrib;
|
||||
if (vertex::getConstant(inputname.c_str(), builtinattrib))
|
||||
attriblocation = (GLint) builtinattrib;
|
||||
else if (Shader::current)
|
||||
attriblocation = Shader::current->getVertexAttributeIndex(inputname);
|
||||
|
||||
// The active shader might not use this vertex attribute name.
|
||||
if (attriblocation < 0)
|
||||
return attriblocation;
|
||||
|
||||
// Make sure the buffer isn't mapped (sends data to GPU if needed.)
|
||||
vbo->unmap();
|
||||
|
||||
gl.bindBuffer(BUFFER_VERTEX, (GLuint) vbo->getHandle());
|
||||
|
||||
GLboolean normalized = GL_FALSE;
|
||||
GLenum datatype = OpenGL::getGLVertexDataType(format.type, normalized);
|
||||
|
||||
const void *gloffset = BUFFER_OFFSET(getAttributeOffset(attributeindex));
|
||||
|
||||
glVertexAttribPointer(attriblocation, format.components, datatype, normalized, (GLsizei) vertexStride, gloffset);
|
||||
|
||||
return attriblocation;
|
||||
}
|
||||
|
||||
void Mesh::drawInternal(int start, int count, int instancecount, bool useindexbuffer, uint32 attribflags, uint32 instancedattribflags) const
|
||||
void Mesh::drawInternal(int start, int count, int instancecount, bool useindexbuffer, const vertex::Attributes &attributes, const vertex::Buffers &buffers) const
|
||||
{
|
||||
OpenGL::TempDebugGroup debuggroup("Mesh draw");
|
||||
|
||||
gl.useVertexAttribArrays(attribflags, instancedattribflags);
|
||||
gl.setVertexAttributes(attributes, buffers);
|
||||
gl.bindTextureToUnit(texture, 0, false);
|
||||
gl.prepareDraw();
|
||||
|
||||
|
||||
@@ -37,14 +37,11 @@ public:
|
||||
|
||||
Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, vertex::Usage usage);
|
||||
Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, int vertexcount, PrimitiveType drawmode, vertex::Usage usage);
|
||||
|
||||
virtual ~Mesh();
|
||||
|
||||
int bindAttributeToShaderInput(int attributeindex, const std::string &inputname) override;
|
||||
|
||||
protected:
|
||||
|
||||
void drawInternal(int start, int count, int instancecount, bool useindexbuffer, uint32 attribflags, uint32 instancedattribflags) const override;
|
||||
void drawInternal(int start, int count, int instancecount, bool useindexbuffer, const vertex::Attributes &attributes, const vertex::Buffers &buffers) const override;
|
||||
|
||||
}; // Mesh
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ void OpenGL::setupContext()
|
||||
else
|
||||
state.instancedAttribArrays = 0;
|
||||
|
||||
useVertexAttribArrays(0, 0);
|
||||
setVertexAttributes(vertex::Attributes(), vertex::Buffers());
|
||||
|
||||
// Get the current viewport.
|
||||
glGetIntegerv(GL_VIEWPORT, (GLint *) &state.viewport.x);
|
||||
@@ -647,111 +647,52 @@ void OpenGL::drawElements(GLenum mode, GLsizei count, GLenum type, const void *i
|
||||
++stats.drawCalls;
|
||||
}
|
||||
|
||||
void OpenGL::useVertexAttribArrays(uint32 arraybits, uint32 instancedbits)
|
||||
void OpenGL::setVertexAttributes(const vertex::Attributes &attributes, const vertex::Buffers &buffers)
|
||||
{
|
||||
uint32 diff = arraybits ^ state.enabledAttribArrays;
|
||||
uint32 instancediff = instancedbits ^ state.instancedAttribArrays;
|
||||
uint32 enablediff = attributes.enablebits ^ state.enabledAttribArrays;
|
||||
uint32 instancediff = attributes.instancebits ^ state.instancedAttribArrays;
|
||||
|
||||
if (diff == 0 && instancediff == 0)
|
||||
return;
|
||||
|
||||
// Max 32 attributes. As of when this was written, no GL driver exposes more
|
||||
// than 32. Lets hope that doesn't change...
|
||||
for (uint32 i = 0; i < 32; i++)
|
||||
for (uint32 i = 0; i < vertex::Attributes::MAX; i++)
|
||||
{
|
||||
uint32 bit = 1u << i;
|
||||
|
||||
if (diff & bit)
|
||||
if (enablediff & bit)
|
||||
{
|
||||
if (arraybits & bit)
|
||||
if (attributes.enablebits & bit)
|
||||
glEnableVertexAttribArray(i);
|
||||
else
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
|
||||
if (instancediff & bit)
|
||||
glVertexAttribDivisor(i, (instancedbits & bit) != 0 ? 1 : 0);
|
||||
glVertexAttribDivisor(i, (attributes.instancebits & bit) != 0 ? 1 : 0);
|
||||
|
||||
if (attributes.enablebits & bit)
|
||||
{
|
||||
const auto &attrib = attributes.attribs[i];
|
||||
const auto &bufferinfo = buffers.info[attrib.bufferindex];
|
||||
|
||||
GLboolean normalized = GL_FALSE;
|
||||
GLenum gltype = getGLVertexDataType(attrib.type, normalized);
|
||||
|
||||
const void *offsetpointer = BUFFER_OFFSET(bufferinfo.offset + attrib.offsetfromvertex);
|
||||
|
||||
bindBuffer(BUFFER_VERTEX, (GLuint) bufferinfo.buffer->getHandle());
|
||||
glVertexAttribPointer(i, attrib.components, gltype, normalized, attrib.stride, offsetpointer);
|
||||
}
|
||||
}
|
||||
|
||||
state.enabledAttribArrays = arraybits;
|
||||
state.instancedAttribArrays = instancedbits;
|
||||
state.enabledAttribArrays = attributes.enablebits;
|
||||
state.instancedAttribArrays = attributes.instancebits;
|
||||
|
||||
// glDisableVertexAttribArray will make the constant value for a vertex
|
||||
// attribute undefined. We rely on the per-vertex color attribute being
|
||||
// white when no per-vertex color is used, so we set it here.
|
||||
// FIXME: Is there a better place to do this?
|
||||
if ((diff & ATTRIBFLAG_COLOR) && !(arraybits & ATTRIBFLAG_COLOR))
|
||||
if ((enablediff & ATTRIBFLAG_COLOR) && !(attributes.enablebits & ATTRIBFLAG_COLOR))
|
||||
glVertexAttrib4f(ATTRIB_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void OpenGL::setVertexPointers(vertex::CommonFormat format, size_t stride, size_t offset)
|
||||
{
|
||||
using namespace vertex;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case CommonFormat::NONE:
|
||||
break;
|
||||
case CommonFormat::XYf:
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset));
|
||||
break;
|
||||
case CommonFormat::XYZf:
|
||||
glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset));
|
||||
break;
|
||||
case CommonFormat::RGBAub:
|
||||
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset));
|
||||
break;
|
||||
case CommonFormat::STf_RGBAub:
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(STf_RGBAub, s)));
|
||||
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(STf_RGBAub, color.r)));
|
||||
break;
|
||||
case CommonFormat::STPf_RGBAub:
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(STPf_RGBAub, s)));
|
||||
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(STPf_RGBAub, color.r)));
|
||||
break;
|
||||
case CommonFormat::XYf_STf:
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf, x)));
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf, s)));
|
||||
break;
|
||||
case CommonFormat::XYf_STPf:
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf, x)));
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf, s)));
|
||||
break;
|
||||
case CommonFormat::XYf_STf_RGBAub:
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf_RGBAub, x)));
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf_RGBAub, s)));
|
||||
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf_RGBAub, color.r)));
|
||||
break;
|
||||
case CommonFormat::XYf_STus_RGBAub:
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STus_RGBAub, x)));
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STus_RGBAub, s)));
|
||||
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STus_RGBAub, color.r)));
|
||||
break;
|
||||
case CommonFormat::XYf_STPf_RGBAub:
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, x)));
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, s)));
|
||||
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, color.r)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGL::setVertexPointers(vertex::CommonFormat format, size_t offset)
|
||||
{
|
||||
setVertexPointers(format, getFormatStride(format), offset);
|
||||
}
|
||||
|
||||
void OpenGL::setVertexPointers(vertex::CommonFormat format, love::graphics::Buffer *buffer, size_t offset)
|
||||
{
|
||||
bindBuffer(BUFFER_VERTEX, (GLuint) buffer->getHandle());
|
||||
setVertexPointers(format, offset);
|
||||
}
|
||||
|
||||
void OpenGL::setVertexPointers(vertex::CommonFormat format, love::graphics::Buffer *buffer, size_t stride, size_t offset)
|
||||
{
|
||||
bindBuffer(BUFFER_VERTEX, (GLuint) buffer->getHandle());
|
||||
setVertexPointers(format, stride, offset);
|
||||
}
|
||||
|
||||
void OpenGL::clearDepth(double value)
|
||||
{
|
||||
if (GLAD_ES_VERSION_2_0)
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace love
|
||||
namespace graphics
|
||||
{
|
||||
|
||||
class Resource;
|
||||
class Buffer;
|
||||
|
||||
namespace opengl
|
||||
@@ -206,23 +207,7 @@ public:
|
||||
void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instancecount = 1);
|
||||
void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount = 1);
|
||||
|
||||
/**
|
||||
* Sets the enabled vertex attribute arrays based on the specified attribute
|
||||
* bits. Each bit in the uint32 represents an enabled attribute array index.
|
||||
* For example, useVertexAttribArrays(1 << 0) will enable attribute index 0.
|
||||
* See the VertexAttribFlags enum for the standard vertex attributes.
|
||||
* This function *must* be used instead of glEnable/DisableVertexAttribArray.
|
||||
**/
|
||||
void useVertexAttribArrays(uint32 arraybits, uint32 instancedbits = 0);
|
||||
|
||||
/**
|
||||
* Calls glVertexAttribPointer appropriately for each attribute used in the
|
||||
* specified format.
|
||||
**/
|
||||
void setVertexPointers(vertex::CommonFormat format, size_t offset);
|
||||
void setVertexPointers(vertex::CommonFormat format, size_t stride, size_t offset);
|
||||
void setVertexPointers(vertex::CommonFormat format, love::graphics::Buffer *buffer, size_t offset);
|
||||
void setVertexPointers(vertex::CommonFormat format, love::graphics::Buffer *buffer, size_t stride, size_t offset);
|
||||
void setVertexAttributes(const vertex::Attributes &attributes, const vertex::Buffers &buffers);
|
||||
|
||||
/**
|
||||
* Wrapper for glClearDepth and glClearDepthf.
|
||||
|
||||
@@ -50,17 +50,14 @@ ParticleSystem *ParticleSystem::clone()
|
||||
return new ParticleSystem(*this);
|
||||
}
|
||||
|
||||
void ParticleSystem::drawInternal() const
|
||||
void ParticleSystem::drawInternal(const vertex::Attributes &attributes, const vertex::Buffers &buffers) const
|
||||
{
|
||||
using namespace vertex;
|
||||
|
||||
OpenGL::TempDebugGroup debuggroup("ParticleSystem draw");
|
||||
|
||||
gl.bindTextureToUnit(texture, 0, false);
|
||||
gl.prepareDraw();
|
||||
|
||||
gl.useVertexAttribArrays(getFormatFlags(CommonFormat::XYf_STf_RGBAub));
|
||||
gl.setVertexPointers(CommonFormat::XYf_STf_RGBAub, buffer, 0);
|
||||
gl.setVertexAttributes(attributes, buffers);
|
||||
|
||||
GLsizei count = (GLsizei) quadIndices.getIndexCount(getCount());
|
||||
GLenum gltype = OpenGL::getGLIndexDataType(quadIndices.getType());
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
void drawInternal() const override;
|
||||
void drawInternal(const vertex::Attributes &attributes, const vertex::Buffers &buffers) const override;
|
||||
|
||||
}; // ParticleSystem
|
||||
|
||||
|
||||
@@ -51,32 +51,11 @@ SpriteBatch::~SpriteBatch()
|
||||
{
|
||||
}
|
||||
|
||||
void SpriteBatch::drawInternal(vertex::CommonFormat format, size_t indexbytestart, size_t indexcount)
|
||||
void SpriteBatch::drawInternal(size_t indexbytestart, size_t indexcount, const vertex::Attributes &attributes, const vertex::Buffers &buffers)
|
||||
{
|
||||
OpenGL::TempDebugGroup debuggroup("SpriteBatch draw");
|
||||
|
||||
uint32 enabledattribs = getFormatFlags(format);
|
||||
|
||||
// We want attached attributes to override local attributes, so we should
|
||||
// call this before binding attached attributes.
|
||||
gl.setVertexPointers(format, array_buf, vertex_stride, 0);
|
||||
|
||||
for (const auto &it : attached_attributes)
|
||||
{
|
||||
Mesh *mesh = it.second.mesh.get();
|
||||
|
||||
// We have to do this check here as wll because setBufferSize can be
|
||||
// called after attachAttribute.
|
||||
if (mesh->getVertexCount() < (size_t) next * 4)
|
||||
throw love::Exception("Mesh with attribute '%s' attached to this SpriteBatch has too few vertices", it.first.c_str());
|
||||
|
||||
int location = mesh->bindAttributeToShaderInput(it.second.index, it.first);
|
||||
|
||||
if (location >= 0)
|
||||
enabledattribs |= 1u << (uint32) location;
|
||||
}
|
||||
|
||||
gl.useVertexAttribArrays(enabledattribs);
|
||||
gl.setVertexAttributes(attributes, buffers);
|
||||
gl.bindTextureToUnit(texture, 0, false);
|
||||
|
||||
gl.prepareDraw();
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
void drawInternal(vertex::CommonFormat format, size_t indexbytestart, size_t indexcount) override;
|
||||
void drawInternal(size_t indexbytestart, size_t indexcount, const vertex::Attributes &attributes, const vertex::Buffers &buffers) override;
|
||||
|
||||
}; // SpriteBatch
|
||||
|
||||
|
||||
@@ -45,9 +45,7 @@ void Text::drawInternal(const std::vector<Font::DrawCommand> &commands) const
|
||||
OpenGL::TempDebugGroup debuggroup("Text object draw");
|
||||
|
||||
gl.prepareDraw();
|
||||
|
||||
gl.setVertexPointers(Font::vertexFormat, vbo, 0);
|
||||
gl.useVertexAttribArrays(vertex::getFormatFlags(Font::vertexFormat));
|
||||
gl.setVertexAttributes(vertexAttributes, vertexBuffers);
|
||||
|
||||
const GLenum gltype = OpenGL::getGLIndexDataType(quadIndices.getType());
|
||||
const size_t elemsize = quadIndices.getElementSize();
|
||||
|
||||
Reference in New Issue
Block a user