love.graphics internal Buffer objects are no longer OpenGL-specific.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2017-01-28 19:26:57 -04:00
parent 470098b7e6
commit d990044288
27 changed files with 594 additions and 532 deletions
+4 -2
View File
@@ -465,6 +465,8 @@ source_group("modules\\font\\freetype" FILES ${LOVE_SRC_MODULE_FONT_FREETYPE})
#
set(LOVE_SRC_MODULE_GRAPHICS_ROOT
src/modules/graphics/Buffer.cpp
src/modules/graphics/Buffer.h
src/modules/graphics/Canvas.cpp
src/modules/graphics/Canvas.h
src/modules/graphics/Color.h
@@ -503,14 +505,14 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT
)
set(LOVE_SRC_MODULE_GRAPHICS_OPENGL
src/modules/graphics/opengl/Buffer.cpp
src/modules/graphics/opengl/Buffer.h
src/modules/graphics/opengl/BufferSync.cpp
src/modules/graphics/opengl/BufferSync.h
src/modules/graphics/opengl/Canvas.cpp
src/modules/graphics/opengl/Canvas.h
src/modules/graphics/opengl/Font.cpp
src/modules/graphics/opengl/Font.h
src/modules/graphics/opengl/GLBuffer.cpp
src/modules/graphics/opengl/GLBuffer.h
src/modules/graphics/opengl/Graphics.cpp
src/modules/graphics/opengl/Graphics.h
src/modules/graphics/opengl/Image.cpp
@@ -453,9 +453,9 @@
FA0B7D511A95902C000E1D17 /* Text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BA11A95902C000E1D17 /* Text.cpp */; };
FA0B7D521A95902C000E1D17 /* Text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BA11A95902C000E1D17 /* Text.cpp */; };
FA0B7D531A95902C000E1D17 /* Text.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BA21A95902C000E1D17 /* Text.h */; };
FA0B7D551A95902C000E1D17 /* GLBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BA41A95902C000E1D17 /* GLBuffer.cpp */; };
FA0B7D561A95902C000E1D17 /* GLBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BA41A95902C000E1D17 /* GLBuffer.cpp */; };
FA0B7D571A95902C000E1D17 /* GLBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BA51A95902C000E1D17 /* GLBuffer.h */; };
FA0B7D551A95902C000E1D17 /* Buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BA41A95902C000E1D17 /* Buffer.cpp */; };
FA0B7D561A95902C000E1D17 /* Buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BA41A95902C000E1D17 /* Buffer.cpp */; };
FA0B7D571A95902C000E1D17 /* Buffer.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BA51A95902C000E1D17 /* Buffer.h */; };
FA0B7D5E1A95902C000E1D17 /* wrap_Graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BAA1A95902C000E1D17 /* wrap_Graphics.cpp */; };
FA0B7D5F1A95902C000E1D17 /* wrap_Graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BAA1A95902C000E1D17 /* wrap_Graphics.cpp */; };
FA0B7D601A95902C000E1D17 /* wrap_Graphics.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BAB1A95902C000E1D17 /* wrap_Graphics.h */; };
@@ -1011,6 +1011,9 @@
FAB2D5AA1AABDD8A008224A4 /* TrueTypeRasterizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAB2D5A81AABDD8A008224A4 /* TrueTypeRasterizer.cpp */; };
FAB2D5AB1AABDD8A008224A4 /* TrueTypeRasterizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAB2D5A81AABDD8A008224A4 /* TrueTypeRasterizer.cpp */; };
FAB2D5AC1AABDD8A008224A4 /* TrueTypeRasterizer.h in Headers */ = {isa = PBXBuildFile; fileRef = FAB2D5A91AABDD8A008224A4 /* TrueTypeRasterizer.h */; };
FADF53F81E3C7ACD00012CC0 /* Buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF53F61E3C7ACD00012CC0 /* Buffer.cpp */; };
FADF53F91E3C7ACD00012CC0 /* Buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF53F61E3C7ACD00012CC0 /* Buffer.cpp */; };
FADF53FA1E3C7ACD00012CC0 /* Buffer.h in Headers */ = {isa = PBXBuildFile; fileRef = FADF53F71E3C7ACD00012CC0 /* Buffer.h */; };
FAE272521C05A15B00A67640 /* ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE272501C05A15B00A67640 /* ParticleSystem.cpp */; };
FAE272531C05A15B00A67640 /* ParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE272511C05A15B00A67640 /* ParticleSystem.h */; };
FAF140531E20934C00F898D2 /* CodeGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FC21E20934C00F898D2 /* CodeGen.cpp */; };
@@ -1450,8 +1453,8 @@
FA0B7BA01A95902C000E1D17 /* SpriteBatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatch.h; sourceTree = "<group>"; };
FA0B7BA11A95902C000E1D17 /* Text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Text.cpp; sourceTree = "<group>"; };
FA0B7BA21A95902C000E1D17 /* Text.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Text.h; sourceTree = "<group>"; };
FA0B7BA41A95902C000E1D17 /* GLBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLBuffer.cpp; sourceTree = "<group>"; };
FA0B7BA51A95902C000E1D17 /* GLBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLBuffer.h; sourceTree = "<group>"; };
FA0B7BA41A95902C000E1D17 /* Buffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Buffer.cpp; sourceTree = "<group>"; };
FA0B7BA51A95902C000E1D17 /* Buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Buffer.h; sourceTree = "<group>"; };
FA0B7BAA1A95902C000E1D17 /* wrap_Graphics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Graphics.cpp; sourceTree = "<group>"; };
FA0B7BAB1A95902C000E1D17 /* wrap_Graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Graphics.h; sourceTree = "<group>"; };
FA0B7BAC1A95902C000E1D17 /* wrap_Image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Image.cpp; sourceTree = "<group>"; };
@@ -1833,6 +1836,8 @@
FAB2D5A91AABDD8A008224A4 /* TrueTypeRasterizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrueTypeRasterizer.h; sourceTree = "<group>"; };
FAC734C11B2E021A00AB460A /* wrap_SoundData.lua */ = {isa = PBXFileReference; lastKnownFileType = text; path = wrap_SoundData.lua; sourceTree = "<group>"; };
FAC734C21B2E628700AB460A /* wrap_ImageData.lua */ = {isa = PBXFileReference; lastKnownFileType = text; path = wrap_ImageData.lua; sourceTree = "<group>"; };
FADF53F61E3C7ACD00012CC0 /* Buffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Buffer.cpp; sourceTree = "<group>"; };
FADF53F71E3C7ACD00012CC0 /* Buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Buffer.h; sourceTree = "<group>"; };
FAE272501C05A15B00A67640 /* ParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleSystem.cpp; sourceTree = "<group>"; };
FAE272511C05A15B00A67640 /* ParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleSystem.h; sourceTree = "<group>"; };
FAF13FC21E20934C00F898D2 /* CodeGen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGen.cpp; sourceTree = "<group>"; };
@@ -2615,6 +2620,8 @@
FA0B7B871A95902C000E1D17 /* graphics */ = {
isa = PBXGroup;
children = (
FADF53F61E3C7ACD00012CC0 /* Buffer.cpp */,
FADF53F71E3C7ACD00012CC0 /* Buffer.h */,
FA1BA0A51E16F20600AA2803 /* Canvas.cpp */,
FA1BA0A61E16F20600AA2803 /* Canvas.h */,
FA0B7B881A95902C000E1D17 /* Color.h */,
@@ -2658,14 +2665,14 @@
FA0B7B8C1A95902C000E1D17 /* opengl */ = {
isa = PBXGroup;
children = (
FA0B7BA41A95902C000E1D17 /* Buffer.cpp */,
FA0B7BA51A95902C000E1D17 /* Buffer.h */,
FA28EBD31E352DB5003446F4 /* BufferSync.cpp */,
FA28EBD41E352DB5003446F4 /* BufferSync.h */,
FA0B7B8D1A95902C000E1D17 /* Canvas.cpp */,
FA0B7B8E1A95902C000E1D17 /* Canvas.h */,
FA0B7B8F1A95902C000E1D17 /* Font.cpp */,
FA0B7B901A95902C000E1D17 /* Font.h */,
FA0B7BA41A95902C000E1D17 /* GLBuffer.cpp */,
FA0B7BA51A95902C000E1D17 /* GLBuffer.h */,
FA0B7B911A95902C000E1D17 /* Graphics.cpp */,
FA0B7B921A95902C000E1D17 /* Graphics.h */,
FA0B7B931A95902C000E1D17 /* Image.cpp */,
@@ -3533,7 +3540,7 @@
FAF140571E20934C00F898D2 /* arrays.h in Headers */,
FA0B7A371A958EA3000E1D17 /* b2Distance.h in Headers */,
FA0B7E681A95902C000E1D17 /* wrap_PrismaticJoint.h in Headers */,
FA0B7D571A95902C000E1D17 /* GLBuffer.h in Headers */,
FA0B7D571A95902C000E1D17 /* Buffer.h in Headers */,
FAF140AB1E20934C00F898D2 /* SymbolTable.h in Headers */,
FA27B3C71B4985D8008A9DCE /* Video.h in Headers */,
FA0B7ED71A95902D000E1D17 /* Timer.h in Headers */,
@@ -3628,6 +3635,7 @@
FA0B7E0E1A95902C000E1D17 /* Fixture.h in Headers */,
FA0B7A401A958EA3000E1D17 /* b2ChainShape.h in Headers */,
217DFBE81D9F6D490055D849 /* inet.h in Headers */,
FADF53FA1E3C7ACD00012CC0 /* Buffer.h in Headers */,
FA0B7AA61A958EA3000E1D17 /* b2RevoluteJoint.h in Headers */,
FA0B7EEA1A95902D000E1D17 /* wrap_Window.h in Headers */,
FA1557C01CE90A2C00AFF582 /* tinyexr.h in Headers */,
@@ -4084,6 +4092,7 @@
FA0B7D161A95902C000E1D17 /* Font.cpp in Sources */,
FA0B7EB61A95902C000E1D17 /* wrap_System.cpp in Sources */,
FA0B7DAC1A95902C000E1D17 /* STBHandler.cpp in Sources */,
FADF53F91E3C7ACD00012CC0 /* Buffer.cpp in Sources */,
FA0B79301A958E3B000E1D17 /* Module.cpp in Sources */,
FAF1409B1E20934C00F898D2 /* propagateNoContraction.cpp in Sources */,
FA0B7DDA1A95902C000E1D17 /* RandomGenerator.cpp in Sources */,
@@ -4187,7 +4196,7 @@
FA0B7DF51A95902C000E1D17 /* wrap_Mouse.cpp in Sources */,
FA0B7E861A95902C000E1D17 /* CoreAudioDecoder.cpp in Sources */,
FA0B7E761A95902C000E1D17 /* wrap_WeldJoint.cpp in Sources */,
FA0B7D561A95902C000E1D17 /* GLBuffer.cpp in Sources */,
FA0B7D561A95902C000E1D17 /* Buffer.cpp in Sources */,
FA0B7A6C1A958EA3000E1D17 /* b2World.cpp in Sources */,
FA1557C51CE90BD900AFF582 /* EXRHandler.cpp in Sources */,
FA57FB991AE1993600F2AD6D /* noise1234.cpp in Sources */,
@@ -4437,6 +4446,7 @@
FA0B7EB51A95902C000E1D17 /* wrap_System.cpp in Sources */,
FA0B7DAB1A95902C000E1D17 /* STBHandler.cpp in Sources */,
FA0B7AB81A958EA3000E1D17 /* enet.cpp in Sources */,
FADF53F81E3C7ACD00012CC0 /* Buffer.cpp in Sources */,
FA0B7DD91A95902C000E1D17 /* RandomGenerator.cpp in Sources */,
FAF1409A1E20934C00F898D2 /* propagateNoContraction.cpp in Sources */,
FA0B7A9B1A958EA3000E1D17 /* b2MouseJoint.cpp in Sources */,
@@ -4536,7 +4546,7 @@
FA0B7E851A95902C000E1D17 /* CoreAudioDecoder.cpp in Sources */,
FA0B7E751A95902C000E1D17 /* wrap_WeldJoint.cpp in Sources */,
FAF140951E20934C00F898D2 /* PpSymbols.cpp in Sources */,
FA0B7D551A95902C000E1D17 /* GLBuffer.cpp in Sources */,
FA0B7D551A95902C000E1D17 /* Buffer.cpp in Sources */,
FA57FB981AE1993600F2AD6D /* noise1234.cpp in Sources */,
FA0B7E211A95902C000E1D17 /* PolygonShape.cpp in Sources */,
FA0B7D511A95902C000E1D17 /* Text.cpp in Sources */,
+177
View File
@@ -0,0 +1,177 @@
/**
* Copyright (c) 2006-2017 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "Buffer.h"
#include "Graphics.h"
#include "common/Exception.h"
namespace love
{
namespace graphics
{
Buffer::Buffer(size_t size, BufferType type, vertex::Usage usage, uint32 mapflags)
: size(size)
, type(type)
, usage(usage)
, map_flags(mapflags)
, is_mapped(false)
{
}
Buffer::~Buffer()
{
}
// QuadIndices
size_t QuadIndices::maxSize = 0;
size_t QuadIndices::elementSize = 0;
size_t QuadIndices::objectCount = 0;
Buffer *QuadIndices::indexBuffer = nullptr;
char *QuadIndices::indices = nullptr;
QuadIndices::QuadIndices(Graphics *gfx, size_t size)
: size(size)
{
// The upper limit is the maximum of uint32 divided by six (the number
// of indices per size) and divided by the size of uint32. This guarantees
// no overflows when calculating the array size in bytes.
if (size == 0 || size > ((uint32) -1) / 6 / sizeof(uint32))
throw love::Exception("Invalid number of quads.");
// Create a new / larger buffer if needed.
if (indexBuffer == nullptr || size > maxSize)
{
Buffer *newbuffer = nullptr;
char *newindices = nullptr;
// Depending on the size, a switch to int and more memory is needed.
IndexDataType targettype = getType(size);
size_t elemsize = vertex::getIndexDataSize(targettype);
size_t buffersize = elemsize * 6 * size;
try
{
newbuffer = gfx->newBuffer(buffersize, nullptr, BUFFER_INDEX, vertex::USAGE_STATIC, 0);
newindices = new char[buffersize];
}
catch (std::bad_alloc &)
{
delete newbuffer;
delete[] newindices;
throw love::Exception("Out of memory.");
}
// Allocation of the new Buffer succeeded.
// The old Buffer can now be deleted.
delete indexBuffer;
indexBuffer = newbuffer;
delete[] indices;
indices = newindices;
maxSize = size;
elementSize = elemsize;
switch (targettype)
{
case INDEX_UINT16:
fill<uint16>();
break;
case INDEX_UINT32:
fill<uint32>();
break;
case INDEX_MAX_ENUM:
break;
}
}
objectCount++;
}
QuadIndices::QuadIndices(const QuadIndices &other)
: size(other.size)
{
objectCount++;
}
QuadIndices &QuadIndices::operator = (const QuadIndices &other)
{
size = other.size;
return *this;
}
QuadIndices::~QuadIndices()
{
--objectCount;
// Delete the buffer if we were the last living QuadIndices object.
if (objectCount <= 0)
{
delete indexBuffer;
indexBuffer = nullptr;
delete[] indices;
indices = nullptr;
}
}
size_t QuadIndices::getSize() const
{
return size;
}
size_t QuadIndices::getIndexCount(size_t elements) const
{
return elements * 6;
}
IndexDataType QuadIndices::getType(size_t s) const
{
return vertex::getIndexDataTypeFromMax(s);
}
size_t QuadIndices::getElementSize()
{
return elementSize;
}
Buffer *QuadIndices::getBuffer() const
{
return indexBuffer;
}
const void *QuadIndices::getIndices(size_t offset) const
{
return indices + offset;
}
template <typename T>
void QuadIndices::fill()
{
vertex::fillIndices(vertex::TriangleIndexMode::QUADS, 0, maxSize * 4, (T *) indices);
indexBuffer->fill(0, indexBuffer->getSize(), indices);
}
} // graphics
} // love
@@ -18,17 +18,12 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_GRAPHICS_OPENGL_GL_BUFFER_H
#define LOVE_GRAPHICS_OPENGL_GL_BUFFER_H
#pragma once
// LOVE
#include "common/config.h"
#include "graphics/Volatile.h"
#include "graphics/vertex.h"
// OpenGL
#include "OpenGL.h"
#include "common/int.h"
#include "vertex.h"
// C
#include <stddef.h>
@@ -37,57 +32,35 @@ namespace love
{
namespace graphics
{
namespace opengl
{
class Graphics;
/**
* GLBuffer is a thin abstraction over OpenGL's Buffer Objects.
* The class is meant for internal use.
*/
class GLBuffer : public Volatile
* A block of GPU-owned memory. Currently meant for internal use.
**/
class Buffer
{
public:
enum MapFlags
{
MAP_EXPLICIT_RANGE_MODIFY = 0x01, // see setMappedRangeModified.
MAP_EXPLICIT_RANGE_MODIFY = (1 << 0), // see setMappedRangeModified.
MAP_READ = (1 << 1),
};
/**
* Constructor.
*
* @param size The size of the GLBuffer in bytes.
* @param type The type of the buffer object.
* @param usage Usage hint.
*/
GLBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags = 0);
Buffer(size_t size, BufferType type, vertex::Usage usage, uint32 mapflags);
virtual ~Buffer();
/**
* Destructor.
*/
virtual ~GLBuffer();
/**
* Get the size of the GLBuffer, in bytes.
*
* @return The size of the GLBuffer.
*/
size_t getSize() const
{
return size;
}
/**
* Get the type of the buffer object.
*/
BufferType getType() const
{
return type;
}
/**
* Get the usage hint for this GLBuffer.
*/
vertex::Usage getUsage() const
{
return usage;
@@ -99,32 +72,29 @@ public:
}
/**
* Map the GLBuffer to client memory.
* Map the Buffer to client memory.
*
* This can be faster for large changes to the buffer. For smaller
* changes, see fill().
*
* @return A pointer to memory which represents the buffer.
*/
void *map();
virtual void *map() = 0;
/**
* Unmap a previously mapped GLBuffer. The buffer must be unmapped
* when used to draw elements.
* Unmap a previously mapped Buffer. The buffer must be unmapped when used
* to draw.
*/
void unmap();
virtual void unmap() = 0;
/**
* Marks a range of mapped data as modified.
* NOTE: GLBuffer::fill calls this internally for you.
* NOTE: Buffer::fill calls this internally for you.
**/
void setMappedRangeModified(size_t offset, size_t size);
virtual void setMappedRangeModified(size_t offset, size_t size) = 0;
/**
* Bind the GLBuffer to its specified target.
* (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, etc).
*/
void bind();
* Gets the backend-specific handle for this Buffer.
**/
virtual ptrdiff_t getHandle() const = 0;
/**
* Fill a portion of the buffer with data and marks the range as modified.
@@ -133,34 +103,27 @@ public:
* @param size The size of the incoming data.
* @param data Pointer to memory to copy data from.
*/
void fill(size_t offset, size_t size, const void *data);
virtual void fill(size_t offset, size_t size, const void *data) = 0;
/**
* Get a pointer which represents the specified byte offset.
*
* @param offset The byte offset. (0 is first byte).
* @return A pointer which represents the offset.
*/
const void *getPointer(size_t offset) const;
* Copy the contents of this Buffer to another Buffer object.
**/
virtual void copyTo(size_t offset, size_t size, Buffer *other, size_t otheroffset) = 0;
uint32 getMapFlags() const
{
return map_flags;
}
// Implements Volatile.
bool loadVolatile() override;
void unloadVolatile() override;
class Mapper
{
public:
/**
* Memory-maps a GLBuffer.
* Memory-maps a Buffer.
*/
Mapper(GLBuffer &buffer)
: buf(buffer)
Mapper(Buffer &buffer)
: buf(buffer)
{
elems = buf.map();
}
@@ -183,57 +146,33 @@ public:
private:
GLBuffer &buf;
Buffer &buf;
void *elems;
}; // Mapper
private:
/**
* Creates the VBO, and optionally restores data we saved earlier.
*
* @param restore True to restore data previously saved with 'unload'.
* @return True on success, false otherwise.
*/
bool load(bool restore);
void unload();
void unmapStatic(size_t offset, size_t size);
void unmapStream();
// Whether the buffer is currently mapped to main memory.
bool is_mapped;
protected:
// The size of the buffer, in bytes.
size_t size;
// The type of the buffer object.
BufferType type;
GLenum target;
// Usage hint. GL_[DYNAMIC, STATIC, STREAM]_DRAW.
vertex::Usage usage;
// The VBO identifier. Assigned by OpenGL.
GLuint vbo;
// A pointer to mapped memory.
char *memory_map;
size_t modified_offset;
size_t modified_size;
uint32 map_flags;
}; // GLBuffer
bool is_mapped;
}; // Buffer
/**
* QuadIndices manages one shared GLBuffer that stores the indices for an
* element array. Vertex arrays using the vertex structure (or anything else
* that can use the pattern below) can request a size and use it for the
* drawElements call.
* QuadIndices manages one shared Buffer that stores the indices for an element
* array. Vertex arrays using the vertex structure (or anything else that can
* use the pattern below) can request a size and use it for the indexed draw
* call.
*
* indices[i*6 + 0] = i*4 + 0;
* indices[i*6 + 1] = i*4 + 1;
@@ -243,25 +182,23 @@ private:
* indices[i*6 + 4] = i*4 + 1;
* indices[i*6 + 5] = i*4 + 3;
*
* There will always be a large enough GLBuffer around until all
* QuadIndices instances have been deleted.
* There will always be a large enough Buffer around until all QuadIndices
* instances have been deleted.
*
* Q: Why have something like QuadIndices?
* A: The indices for the SpriteBatch do not change, only the array size
* varies. Using one GLBuffer for all element arrays removes this
* duplicated data and saves some memory.
* A: The indices for the SpriteBatch do not change, only the array size varies.
* Using one Buffer for all element arrays removes this duplicated data and
* saves some memory.
*/
class QuadIndices
{
public:
/**
* Adds an entry to the list of sizes and resizes the GLBuffer
* Adds an entry to the list of sizes and resizes the Buffer
* if needed. A size of 1 allocates a group of 6 indices for 4 vertices
* creating 1 face.
*
* @param size The requested size in groups of 6 indices.
*/
QuadIndices(size_t size);
QuadIndices(Graphics *gfx, size_t size);
QuadIndices(const QuadIndices &other);
QuadIndices &operator = (const QuadIndices &other);
@@ -275,8 +212,6 @@ public:
/**
* Returns the number of index groups.
* This can be used for getIndexCount to get the full count of indices.
*
* @return The number of index groups.
*/
size_t getSize() const;
@@ -284,9 +219,6 @@ public:
* Returns the number of indices that the passed element count will have.
* Use QuadIndices::getSize to get the full index count for that
* QuadIndices instance.
*
* @param elements The number of elements to calculate the index count for.
* @return The index count.
*/
size_t getIndexCount(size_t elements) const;
@@ -294,12 +226,9 @@ public:
* Returns the integer type of the element array.
* If an optional nonzero size argument is passed, the function returns
* the integer type of the element array of that size.
*
* @param s The size of the array to calculated the integer type of.
* @return The element array integer type.
*/
GLenum getType(size_t s) const;
inline GLenum getType() const
IndexDataType getType(size_t s) const;
inline IndexDataType getType() const
{
return getType(maxSize);
}
@@ -308,28 +237,16 @@ public:
* Returns the size in bytes of an element in the element array.
* Can be used with getPointer to calculate an offset into the array based
* on a number of elements.
*
* @return The size of an element in bytes.
**/
size_t getElementSize();
/**
* Returns the pointer to the GLBuffer.
* The pointer will change if a new size request or removal causes
* a GLBuffer resize. It is recommended to retrieve the pointer
* value directly before the drawing call.
*
* @return The pointer to the GLBuffer.
* Returns the pointer to the Buffer.
* The pointer will change if a new size request or removal causes a Buffer
* resize. It is recommended to retrieve the pointer value directly before
* the drawing call.
*/
GLBuffer *getBuffer() const;
/**
* Returns a pointer which represents the specified byte offset.
*
* @param offset The offset in bytes.
* @return A pointer which represents the offset.
*/
const void *getPointer(size_t offset) const;
Buffer *getBuffer() const;
/**
* Returns a direct pointer to the index data.
@@ -339,9 +256,6 @@ public:
* the index data came from an Index Buffer.
* So the direct pointer to the index buffer should be used instead of the
* index buffer when rendering using client-side vertex arrays.
*
* @param offset An offset in bytes into the index data.
* @return A direct pointer to the index data at the specified offset.
**/
const void *getIndices(size_t offset) const;
@@ -360,20 +274,18 @@ private:
// The size in bytes of an element in the element array.
static size_t elementSize;
// The current GLBuffer size. 0 means no GLBuffer.
// The current GLBuffer size. 0 means no Buffer.
static size_t maxSize;
static size_t objectCount;
// The GLBuffer for the element array. Can be null.
static GLBuffer *indexBuffer;
// The Buffer for the element array. Can be null.
static Buffer *indexBuffer;
// The array of indices that will also be stored in the index buffer.
static char *indices;
};
} // opengl
}; // QuadIndices
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_GL_BUFFER_H
+1
View File
@@ -20,6 +20,7 @@
// LOVE
#include "Graphics.h"
#include "Buffer.h"
#include "math/MathModule.h"
#include "Polyline.h"
#include "font/Font.h"
+4
View File
@@ -49,6 +49,8 @@ class Reference;
namespace graphics
{
class Buffer;
const int MAX_COLOR_RENDER_TARGETS = 8;
/**
@@ -315,6 +317,8 @@ public:
virtual Shader *newShader(const Shader::ShaderSource &source) = 0;
virtual Buffer *newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) = 0;
bool validateShader(bool gles, const Shader::ShaderSource &source, std::string &err);
/**
+66 -2
View File
@@ -21,6 +21,7 @@
//LOVE
#include "common/config.h"
#include "ParticleSystem.h"
#include "Graphics.h"
#include "common/math.h"
#include "modules/math/RandomGenerator.h"
@@ -52,7 +53,7 @@ float calculate_variation(float inner, float outer, float var)
love::Type ParticleSystem::type("ParticleSystem", &Drawable::type);
ParticleSystem::ParticleSystem(Texture *texture, uint32 size)
ParticleSystem::ParticleSystem(Graphics *gfx, Texture *texture, uint32 size)
: pMem(nullptr)
, pFree(nullptr)
, pHead(nullptr)
@@ -90,12 +91,15 @@ ParticleSystem::ParticleSystem(Texture *texture, uint32 size)
, offset(float(texture->getWidth())*0.5f, float(texture->getHeight())*0.5f)
, defaultOffset(true)
, relativeRotation(false)
, buffer(nullptr)
, quadIndices(gfx, size)
{
if (size == 0 || size > MAX_PARTICLES)
throw love::Exception("Invalid ParticleSystem size.");
sizes.push_back(1.0f);
colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
setBufferSize(size);
}
@@ -143,6 +147,8 @@ ParticleSystem::ParticleSystem(const ParticleSystem &p)
, colors(p.colors)
, quads(p.quads)
, relativeRotation(p.relativeRotation)
, buffer(nullptr)
, quadIndices(p.quadIndices)
{
setBufferSize(maxParticles);
}
@@ -169,6 +175,13 @@ void ParticleSystem::createBuffers(size_t size)
{
pFree = pMem = new Particle[size];
maxParticles = (uint32) size;
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
size_t bytes = sizeof(Vertex) * size * 4;
buffer = gfx->newBuffer(bytes, nullptr, BUFFER_VERTEX, vertex::USAGE_STREAM, 0);
quadIndices = QuadIndices(gfx, size);
}
catch (std::bad_alloc &)
{
@@ -179,10 +192,11 @@ void ParticleSystem::createBuffers(size_t size)
void ParticleSystem::deleteBuffers()
{
// Clean up for great gracefulness!
delete[] pMem;
delete buffer;
pMem = nullptr;
buffer = nullptr;
maxParticles = 0;
activeParticles = 0;
}
@@ -933,6 +947,56 @@ void ParticleSystem::update(float dt)
prevPosition = position;
}
bool ParticleSystem::prepareDraw(Graphics *gfx, const Matrix4 &m)
{
uint32 pCount = getCount();
if (pCount == 0 || texture.get() == nullptr || pMem == nullptr || buffer == nullptr)
return false;
gfx->flushStreamDraws();
Graphics::TempTransform transform(gfx, m);
const Vertex *textureVerts = texture->getVertices();
Vertex *pVerts = (Vertex *) buffer->map();
Particle *p = pHead;
bool useQuads = !quads.empty();
Matrix3 t;
// set the vertex data for each particle (transformation, texcoords, color)
while (p)
{
if (useQuads)
textureVerts = quads[p->quadIndex]->getVertices();
// particle vertices are image vertices transformed by particle info
t.setTransformation(p->position.x, p->position.y, p->angle, p->size, p->size, offset.x, offset.y, 0.0f, 0.0f);
t.transform(pVerts, textureVerts, 4);
// Particle colors are stored as floats (0-1) but vertex colors are
// unsigned bytes (0-255).
Color c = toColor(p->color);
// set the texture coordinate and color data for particle vertices
for (int v = 0; v < 4; v++)
{
pVerts[v].s = textureVerts[v].s;
pVerts[v].t = textureVerts[v].t;
pVerts[v].color = c;
}
pVerts += 4;
p = p->next;
}
buffer->unmap();
return true;
}
bool ParticleSystem::getConstant(const char *in, AreaSpreadDistribution &out)
{
return distributions.find(in, out);
+11 -1
View File
@@ -29,6 +29,7 @@
#include "Color.h"
#include "Quad.h"
#include "Texture.h"
#include "Buffer.h"
// STL
#include <vector>
@@ -38,6 +39,8 @@ namespace love
namespace graphics
{
class Graphics;
/**
* A class for creating, moving and drawing particles.
* A big thanks to bobthebloke.org
@@ -81,7 +84,7 @@ public:
/**
* Creates a particle system with the specified buffer size and texture.
**/
ParticleSystem(Texture *texture, uint32 buffer);
ParticleSystem(Graphics *gfx, Texture *texture, uint32 buffer);
ParticleSystem(const ParticleSystem &p);
/**
@@ -548,6 +551,8 @@ protected:
int quadIndex;
};
bool prepareDraw(Graphics *gfx, const Matrix4 &m);
// Pointer to the beginning of the allocated memory.
Particle *pMem;
@@ -647,6 +652,11 @@ protected:
bool relativeRotation;
Buffer *buffer;
// Vertex index buffer.
QuadIndices quadIndices;
private:
void resetOffset();
+1
View File
@@ -21,6 +21,7 @@
// LOVE
#include "Shader.h"
#include "Graphics.h"
#include "math/MathModule.h"
// glslang
#include "libraries/glslang/glslang/Public/ShaderLang.h"
+17
View File
@@ -31,6 +31,11 @@
#include <vector>
#include <stddef.h>
namespace glslang
{
class TShader;
}
namespace love
{
namespace graphics
@@ -171,6 +176,8 @@ public:
**/
virtual void setVideoTextures(ptrdiff_t ytexture, ptrdiff_t cbtexture, ptrdiff_t crtexture) = 0;
virtual ptrdiff_t getHandle() const = 0;
static bool validate(Graphics *gfx, bool gles, const ShaderSource &source, bool checkWithDefaults, std::string &err);
static bool initialize();
@@ -187,9 +194,19 @@ public:
protected:
struct CachedShaderStage
{
int referenceCount;
ShaderStage stage;
glslang::TShader *glslangShader;
ptrdiff_t handle;
};
// Source code used for this Shader.
ShaderSource shaderSource;
static std::map<std::string, CachedShaderStage> cachedShaders;
private:
static StringMap<Language, LANGUAGE_MAX_ENUM>::Entry languageEntries[];
@@ -18,7 +18,7 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "GLBuffer.h"
#include "Buffer.h"
#include "common/Exception.h"
#include "graphics/vertex.h"
@@ -35,16 +35,12 @@ namespace graphics
namespace opengl
{
GLBuffer::GLBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags)
: is_mapped(false)
, size(size)
, type(type)
, usage(usage)
Buffer::Buffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags)
: love::graphics::Buffer(size, type, usage, mapflags)
, vbo(0)
, memory_map(nullptr)
, modified_offset(0)
, modified_size(0)
, map_flags(mapflags)
{
target = OpenGL::getGLBufferType(type);
@@ -67,7 +63,7 @@ GLBuffer::GLBuffer(size_t size, const void *data, BufferType type, vertex::Usage
}
}
GLBuffer::~GLBuffer()
Buffer::~Buffer()
{
if (vbo != 0)
unload();
@@ -75,7 +71,7 @@ GLBuffer::~GLBuffer()
delete[] memory_map;
}
void *GLBuffer::map()
void *Buffer::map()
{
if (is_mapped)
return memory_map;
@@ -88,7 +84,7 @@ void *GLBuffer::map()
return memory_map;
}
void GLBuffer::unmapStatic(size_t offset, size_t size)
void Buffer::unmapStatic(size_t offset, size_t size)
{
if (size == 0)
return;
@@ -98,7 +94,7 @@ void GLBuffer::unmapStatic(size_t offset, size_t size)
glBufferSubData(target, (GLintptr) offset, (GLsizeiptr) size, memory_map + offset);
}
void GLBuffer::unmapStream()
void Buffer::unmapStream()
{
GLenum glusage = OpenGL::getGLBufferUsage(getUsage());
@@ -109,7 +105,7 @@ void GLBuffer::unmapStream()
glBufferData(target, (GLsizeiptr) getSize(), memory_map, glusage);
}
void GLBuffer::unmap()
void Buffer::unmap()
{
if (!is_mapped)
return;
@@ -127,15 +123,15 @@ void GLBuffer::unmap()
if (modified_size > 0)
{
switch (OpenGL::getGLBufferUsage(getUsage()))
switch (getUsage())
{
case GL_STATIC_DRAW:
case vertex::USAGE_STATIC:
unmapStatic(modified_offset, modified_size);
break;
case GL_STREAM_DRAW:
case vertex::USAGE_STREAM:
unmapStream();
break;
case GL_DYNAMIC_DRAW:
case vertex::USAGE_DYNAMIC:
default:
// It's probably more efficient to treat it like a streaming buffer if
// at least a third of its contents have been modified during the map().
@@ -153,7 +149,7 @@ void GLBuffer::unmap()
is_mapped = false;
}
void GLBuffer::setMappedRangeModified(size_t offset, size_t modifiedsize)
void Buffer::setMappedRangeModified(size_t offset, size_t modifiedsize)
{
if (!is_mapped || !(map_flags & MAP_EXPLICIT_RANGE_MODIFY))
return;
@@ -169,12 +165,7 @@ void GLBuffer::setMappedRangeModified(size_t offset, size_t modifiedsize)
modified_size = new_range_end - modified_offset;
}
void GLBuffer::bind()
{
gl.bindBuffer(getType(), vbo);
}
void GLBuffer::fill(size_t offset, size_t size, const void *data)
void Buffer::fill(size_t offset, size_t size, const void *data)
{
memcpy(memory_map + offset, data, size);
@@ -187,26 +178,30 @@ void GLBuffer::fill(size_t offset, size_t size, const void *data)
}
}
const void *GLBuffer::getPointer(size_t offset) const
ptrdiff_t Buffer::getHandle() const
{
return BUFFER_OFFSET(offset);
return vbo;
}
bool GLBuffer::loadVolatile()
void Buffer::copyTo(size_t offset, size_t size, love::graphics::Buffer *other, size_t otheroffset)
{
other->fill(otheroffset, size, memory_map + offset);
}
bool Buffer::loadVolatile()
{
return load(true);
}
void GLBuffer::unloadVolatile()
void Buffer::unloadVolatile()
{
unload();
}
bool GLBuffer::load(bool restore)
bool Buffer::load(bool restore)
{
glGenBuffers(1, &vbo);
bind();
gl.bindBuffer(type, vbo);
while (glGetError() != GL_NO_ERROR)
/* Clear the error buffer. */;
@@ -220,157 +215,13 @@ bool GLBuffer::load(bool restore)
return (glGetError() == GL_NO_ERROR);
}
void GLBuffer::unload()
void Buffer::unload()
{
is_mapped = false;
gl.deleteBuffer(vbo);
vbo = 0;
}
// QuadIndices
size_t QuadIndices::maxSize = 0;
size_t QuadIndices::elementSize = 0;
size_t QuadIndices::objectCount = 0;
GLBuffer *QuadIndices::indexBuffer = nullptr;
char *QuadIndices::indices = nullptr;
QuadIndices::QuadIndices(size_t size)
: size(size)
{
// The upper limit is the maximum of GLuint divided by six (the number
// of indices per size) and divided by the size of GLuint. This guarantees
// no overflows when calculating the array size in bytes.
if (size == 0 || size > ((GLuint) -1) / 6 / sizeof(GLuint))
throw love::Exception("Invalid number of quads.");
// Create a new / larger buffer if needed.
if (indexBuffer == nullptr || size > maxSize)
{
GLBuffer *newbuffer = nullptr;
char *newindices = nullptr;
// Depending on the size, a switch to int and more memory is needed.
GLenum targettype = getType(size);
size_t elemsize = (targettype == GL_UNSIGNED_SHORT) ? sizeof(GLushort) : sizeof(GLuint);
size_t buffersize = elemsize * 6 * size;
// Create may throw out-of-memory exceptions.
// QuadIndices will propagate the exception and keep the old GLBuffer.
try
{
newbuffer = new GLBuffer(buffersize, nullptr, BUFFER_INDEX, vertex::USAGE_STATIC);
newindices = new char[buffersize];
}
catch (std::bad_alloc &)
{
delete newbuffer;
delete[] newindices;
throw love::Exception("Out of memory.");
}
// Allocation of the new GLBuffer succeeded.
// The old GLBuffer can now be deleted.
delete indexBuffer;
indexBuffer = newbuffer;
delete[] indices;
indices = newindices;
maxSize = size;
elementSize = elemsize;
switch (targettype)
{
case GL_UNSIGNED_SHORT:
fill<GLushort>();
break;
case GL_UNSIGNED_INT:
fill<GLuint>();
break;
}
}
objectCount++;
}
QuadIndices::QuadIndices(const QuadIndices &other)
: size(other.size)
{
objectCount++;
}
QuadIndices &QuadIndices::operator = (const QuadIndices &other)
{
size = other.size;
return *this;
}
QuadIndices::~QuadIndices()
{
--objectCount;
// Delete the buffer if we were the last living QuadIndices object.
if (objectCount <= 0)
{
delete indexBuffer;
indexBuffer = nullptr;
delete[] indices;
indices = nullptr;
}
}
size_t QuadIndices::getSize() const
{
return size;
}
size_t QuadIndices::getIndexCount(size_t elements) const
{
return elements * 6;
}
GLenum QuadIndices::getType(size_t s) const
{
// Calculates if unsigned short is big enough to hold all the vertex indices.
static const GLenum types[] = {GL_UNSIGNED_SHORT, GL_UNSIGNED_INT};
return types[s * 4 > std::numeric_limits<GLushort>::max()];
// if buffer-size > max(GLushort) then GL_UNSIGNED_INT else GL_UNSIGNED_SHORT
}
size_t QuadIndices::getElementSize()
{
return elementSize;
}
GLBuffer *QuadIndices::getBuffer() const
{
return indexBuffer;
}
const void *QuadIndices::getPointer(size_t offset) const
{
return indexBuffer->getPointer(offset);
}
const void *QuadIndices::getIndices(size_t offset) const
{
return indices + offset;
}
template <typename T>
void QuadIndices::fill()
{
using namespace love::graphics::vertex;
fillIndices(TriangleIndexMode::QUADS, 0, maxSize * 4, (T *) indices);
indexBuffer->fill(0, indexBuffer->getSize(), indices);
}
} // opengl
} // graphics
} // love
+80
View File
@@ -0,0 +1,80 @@
/**
* Copyright (c) 2006-2017 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#pragma once
// LOVE
#include "common/config.h"
#include "graphics/Buffer.h"
#include "graphics/Volatile.h"
// OpenGL
#include "OpenGL.h"
namespace love
{
namespace graphics
{
namespace opengl
{
class Buffer final : public love::graphics::Buffer, public Volatile
{
public:
Buffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags);
virtual ~Buffer();
void *map() override;
void unmap() override;
void setMappedRangeModified(size_t offset, size_t size) override;
void fill(size_t offset, size_t size, const void *data) override;
ptrdiff_t getHandle() const override;
void copyTo(size_t offset, size_t size, love::graphics::Buffer *other, size_t otheroffset) override;
// Implements Volatile.
bool loadVolatile() override;
void unloadVolatile() override;
private:
bool load(bool restore);
void unload();
void unmapStatic(size_t offset, size_t size);
void unmapStream();
GLenum target;
// The VBO identifier. Assigned by OpenGL.
GLuint vbo;
// A pointer to mapped memory.
char *memory_map;
size_t modified_offset;
size_t modified_size;
}; // Buffer
} // opengl
} // graphics
} // love
+16 -10
View File
@@ -29,6 +29,7 @@
#include "StreamBuffer.h"
#include "math/MathModule.h"
#include "window/Window.h"
#include "Buffer.h"
#include "libraries/xxHash/xxhash.h"
@@ -117,12 +118,12 @@ graphics::Font *Graphics::newFont(love::font::Rasterizer *r, const Texture::Filt
SpriteBatch *Graphics::newSpriteBatch(Texture *texture, int size, vertex::Usage usage)
{
return new SpriteBatch(texture, size, usage);
return new SpriteBatch(this, texture, size, usage);
}
ParticleSystem *Graphics::newParticleSystem(Texture *texture, int size)
{
return new ParticleSystem(texture, size);
return new ParticleSystem(this, texture, size);
}
love::graphics::Canvas *Graphics::newCanvas(int width, int height, const Canvas::Settings &settings)
@@ -159,29 +160,34 @@ love::graphics::Shader *Graphics::newShader(const Shader::ShaderSource &source)
return new Shader(source);
}
love::graphics::Buffer *Graphics::newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags)
{
return new Buffer(size, data, type, usage, mapflags);
}
Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode drawmode, vertex::Usage usage)
{
return new Mesh(vertices, drawmode, usage);
return new Mesh(this, vertices, drawmode, usage);
}
Mesh *Graphics::newMesh(int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage)
{
return new Mesh(vertexcount, drawmode, usage);
return new Mesh(this, vertexcount, drawmode, usage);
}
Mesh *Graphics::newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage)
{
return new Mesh(vertexformat, vertexcount, drawmode, usage);
return new Mesh(this, vertexformat, vertexcount, drawmode, usage);
}
Mesh *Graphics::newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, const void *data, size_t datasize, Mesh::DrawMode drawmode, vertex::Usage usage)
{
return new Mesh(vertexformat, data, datasize, drawmode, usage);
return new Mesh(this, vertexformat, data, datasize, drawmode, usage);
}
Text *Graphics::newText(graphics::Font *font, const std::vector<Font::ColoredString> &text)
{
return new Text(font, text);
return new Text(this, font, text);
}
Video *Graphics::newVideo(love::video::VideoStream *stream, float pixeldensity)
@@ -295,7 +301,7 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b
// index buffer objects, since the shared index buffer used by QuadIndices
// objects is destroyed when the last object is destroyed.
if (quadIndices == nullptr)
quadIndices = new QuadIndices(20);
quadIndices = new QuadIndices(this, 20);
// Restore the graphics state.
restoreState(states.back());
@@ -726,7 +732,7 @@ void Graphics::clear(Colorf c)
// This seems to be enough to fix the bug for me. Other methods I've
// tried (e.g. dummy draws) don't work in all cases.
gl.useProgram(0);
gl.useProgram(((Shader *)Shader::current)->getProgram());
gl.useProgram((GLuint) Shader::current->getHandle());
}
}
@@ -792,7 +798,7 @@ void Graphics::clear(const std::vector<OptionalColorf> &colors)
// This seems to be enough to fix the bug for me. Other methods I've
// tried (e.g. dummy draws) don't work in all cases.
gl.useProgram(0);
gl.useProgram(((Shader *)Shader::current)->getProgram());
gl.useProgram((GLuint) Shader::current->getHandle());
}
}
+2
View File
@@ -78,6 +78,8 @@ public:
love::graphics::Shader *newShader(const Shader::ShaderSource &source) override;
love::graphics::Buffer *newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) override;
Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode drawmode, vertex::Usage usage);
Mesh *newMesh(int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage);
+27 -30
View File
@@ -61,7 +61,7 @@ static std::vector<Mesh::AttribFormat> getDefaultVertexFormat()
love::Type Mesh::type("Mesh", &Drawable::type);
Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, DrawMode drawmode, vertex::Usage usage)
Mesh::Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, DrawMode drawmode, vertex::Usage usage)
: vertexFormat(vertexformat)
, vbo(nullptr)
, vertexCount(0)
@@ -78,17 +78,17 @@ Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, const void *data, size
calculateAttributeSizes();
vertexCount = datasize / vertexStride;
elementDataType = getIndexTypeFromMax(vertexCount);
elementDataType = vertex::getIndexDataTypeFromMax(vertexCount);
if (vertexCount == 0)
throw love::Exception("Data size is too small for specified vertex attribute formats.");
vbo = new GLBuffer(datasize, data, BUFFER_VERTEX, usage, GLBuffer::MAP_EXPLICIT_RANGE_MODIFY);
vbo = gfx->newBuffer(datasize, data, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ);
vertexScratchBuffer = new char[vertexStride];
}
Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawMode drawmode, vertex::Usage usage)
Mesh::Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawMode drawmode, vertex::Usage usage)
: vertexFormat(vertexformat)
, vbo(nullptr)
, vertexCount((size_t) vertexcount)
@@ -96,7 +96,7 @@ Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawM
, ibo(nullptr)
, useIndexBuffer(false)
, elementCount(0)
, elementDataType(getIndexTypeFromMax(vertexcount))
, elementDataType(vertex::getIndexDataTypeFromMax(vertexcount))
, drawMode(drawmode)
, rangeStart(-1)
, rangeCount(-1)
@@ -109,7 +109,7 @@ Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawM
size_t buffersize = vertexCount * vertexStride;
vbo = new GLBuffer(buffersize, nullptr, BUFFER_VERTEX, usage, GLBuffer::MAP_EXPLICIT_RANGE_MODIFY);
vbo = gfx->newBuffer(buffersize, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ);
// Initialize the buffer's contents to 0.
memset(vbo->map(), 0, buffersize);
@@ -119,13 +119,13 @@ Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawM
vertexScratchBuffer = new char[vertexStride];
}
Mesh::Mesh(const std::vector<Vertex> &vertices, DrawMode drawmode, vertex::Usage usage)
: Mesh(getDefaultVertexFormat(), &vertices[0], vertices.size() * sizeof(Vertex), drawmode, usage)
Mesh::Mesh(graphics::Graphics *gfx, const std::vector<Vertex> &vertices, DrawMode drawmode, vertex::Usage usage)
: Mesh(gfx, getDefaultVertexFormat(), &vertices[0], vertices.size() * sizeof(Vertex), drawmode, usage)
{
}
Mesh::Mesh(int vertexcount, DrawMode drawmode, vertex::Usage usage)
: Mesh(getDefaultVertexFormat(), vertexcount, drawmode, usage)
Mesh::Mesh(graphics::Graphics *gfx, int vertexcount, DrawMode drawmode, vertex::Usage usage)
: Mesh(gfx, getDefaultVertexFormat(), vertexcount, drawmode, usage)
{
}
@@ -393,7 +393,7 @@ void Mesh::flush()
* Copies index data from a vector to a mapped index buffer.
**/
template <typename T>
static void copyToIndexBuffer(const std::vector<uint32> &indices, GLBuffer::Mapper &buffermap, size_t maxval)
static void copyToIndexBuffer(const std::vector<uint32> &indices, Buffer::Mapper &buffermap, size_t maxval)
{
T *elems = (T *) buffermap.get();
@@ -410,7 +410,7 @@ void Mesh::setVertexMap(const std::vector<uint32> &map)
{
size_t maxval = getVertexCount();
IndexDataType datatype = getIndexTypeFromMax(maxval);
IndexDataType datatype = vertex::getIndexDataTypeFromMax(maxval);
// Calculate the size in bytes of the index buffer data.
size_t size = map.size() * vertex::getIndexDataSize(datatype);
@@ -422,7 +422,10 @@ void Mesh::setVertexMap(const std::vector<uint32> &map)
}
if (!ibo && size > 0)
ibo = new GLBuffer(size, nullptr, BUFFER_INDEX, vbo->getUsage());
{
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
ibo = gfx->newBuffer(size, nullptr, BUFFER_INDEX, vbo->getUsage(), Buffer::MAP_READ);
}
useIndexBuffer = true;
elementCount = map.size();
@@ -430,7 +433,7 @@ void Mesh::setVertexMap(const std::vector<uint32> &map)
if (!ibo || elementCount == 0)
return;
GLBuffer::Mapper ibomap(*ibo);
Buffer::Mapper ibomap(*ibo);
// Fill the buffer with the index values from the vector.
switch (datatype)
@@ -456,14 +459,17 @@ void Mesh::setVertexMap(IndexDataType datatype, const void *data, size_t datasiz
}
if (!ibo && datasize > 0)
ibo = new GLBuffer(datasize, nullptr, BUFFER_INDEX, vbo->getUsage());
{
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
ibo = gfx->newBuffer(datasize, nullptr, BUFFER_INDEX, vbo->getUsage(), Buffer::MAP_READ);
}
elementCount = datasize / vertex::getIndexDataSize(datatype);
if (!ibo || elementCount == 0)
return;
GLBuffer::Mapper ibomap(*ibo);
Buffer::Mapper ibomap(*ibo);
memcpy(ibomap.get(), data, datasize);
useIndexBuffer = true;
@@ -587,13 +593,12 @@ int Mesh::bindAttributeToShaderInput(int attributeindex, const std::string &inpu
if (attriblocation < 0)
return attriblocation;
// Needed for glVertexAttribPointer.
vbo->bind();
// Make sure the buffer isn't mapped (sends data to GPU if needed.)
vbo->unmap();
const void *gloffset = vbo->getPointer(getAttributeOffset(attributeindex));
gl.bindBuffer(BUFFER_VERTEX, (GLuint) vbo->getHandle());
const void *gloffset = BUFFER_OFFSET(getAttributeOffset(attributeindex));
GLenum datatype = getGLDataType(format.type);
GLboolean normalized = (datatype == GL_UNSIGNED_BYTE);
@@ -651,7 +656,7 @@ void Mesh::drawInstanced(love::graphics::Graphics *gfx, const love::Matrix4 &m,
if (useIndexBuffer && ibo && elementCount > 0)
{
// Use the custom vertex map (index buffer) to draw the vertices.
ibo->bind();
gl.bindBuffer(BUFFER_INDEX, (GLuint) ibo->getHandle());
// Make sure the index buffer isn't mapped (sends data to GPU if needed.)
ibo->unmap();
@@ -665,7 +670,7 @@ void Mesh::drawInstanced(love::graphics::Graphics *gfx, const love::Matrix4 &m,
count = std::min(count, (int) elementCount - start);
size_t elementsize = vertex::getIndexDataSize(elementDataType);
const void *indices = ibo->getPointer(start * elementsize);
const void *indices = BUFFER_OFFSET(start * elementsize);
GLenum type = OpenGL::getGLIndexDataType(elementDataType);
if (count > 0)
@@ -734,14 +739,6 @@ GLenum Mesh::getGLDataType(DataType type)
}
}
IndexDataType Mesh::getIndexTypeFromMax(size_t maxvalue)
{
if (maxvalue > LOVE_UINT16_MAX)
return INDEX_UINT32;
else
return INDEX_UINT16;
}
bool Mesh::getConstant(const char *in, Mesh::DrawMode &out)
{
return drawModes.find(in, out);
+11 -9
View File
@@ -29,7 +29,8 @@
#include "graphics/Drawable.h"
#include "graphics/Texture.h"
#include "graphics/vertex.h"
#include "GLBuffer.h"
#include "graphics/Buffer.h"
#include "OpenGL.h"
// C++
#include <vector>
@@ -39,6 +40,9 @@ namespace love
{
namespace graphics
{
class Graphics;
namespace opengl
{
@@ -86,11 +90,11 @@ public:
int components; // max 4
};
Mesh(const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, DrawMode drawmode, vertex::Usage usage);
Mesh(const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawMode drawmode, vertex::Usage usage);
Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, DrawMode drawmode, vertex::Usage usage);
Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawMode drawmode, vertex::Usage usage);
Mesh(const std::vector<Vertex> &vertices, DrawMode drawmode, vertex::Usage usage);
Mesh(int vertexcount, DrawMode drawmode, vertex::Usage usage);
Mesh(graphics::Graphics *gfx, const std::vector<Vertex> &vertices, DrawMode drawmode, vertex::Usage usage);
Mesh(graphics::Graphics *gfx, int vertexcount, DrawMode drawmode, vertex::Usage usage);
virtual ~Mesh();
@@ -229,8 +233,6 @@ private:
static size_t getAttribFormatSize(const AttribFormat &format);
static IndexDataType getIndexTypeFromMax(size_t maxvalue);
static GLenum getGLDrawMode(DrawMode mode);
static GLenum getGLDataType(DataType type);
@@ -240,7 +242,7 @@ private:
std::unordered_map<std::string, AttachedAttribute> attachedAttributes;
// Vertex buffer, for the vertex data.
GLBuffer *vbo;
Buffer *vbo;
size_t vertexCount;
size_t vertexStride;
@@ -249,7 +251,7 @@ private:
char *vertexScratchBuffer;
// Element (vertex index) buffer, for the vertex map.
GLBuffer *ibo;
Buffer *ibo;
bool useIndexBuffer;
size_t elementCount;
IndexDataType elementDataType;
+8 -78
View File
@@ -19,17 +19,11 @@
**/
//LOVE
#include "common/config.h"
#include "ParticleSystem.h"
#include "graphics/Graphics.h"
#include "OpenGL.h"
// STD
#include <algorithm>
#include <cmath>
#include <cstdlib>
namespace love
{
namespace graphics
@@ -37,32 +31,18 @@ namespace graphics
namespace opengl
{
ParticleSystem::ParticleSystem(Texture *texture, uint32 size)
: love::graphics::ParticleSystem(texture, size)
, buffer(nullptr)
, quadIndices(size)
ParticleSystem::ParticleSystem(Graphics *gfx, Texture *texture, uint32 size)
: love::graphics::ParticleSystem(gfx, texture, size)
{
createVertices(size);
}
ParticleSystem::ParticleSystem(const ParticleSystem &p)
: love::graphics::ParticleSystem(p)
, quadIndices(p.quadIndices)
{
createVertices(maxParticles);
}
ParticleSystem::~ParticleSystem()
{
delete buffer;
}
void ParticleSystem::createVertices(size_t numparticles)
{
size_t size = sizeof(Vertex) * numparticles * 4;
GLBuffer *newbuffer = new GLBuffer(size, nullptr, BUFFER_VERTEX, vertex::USAGE_STREAM, 0);
delete buffer;
buffer = newbuffer;
}
ParticleSystem *ParticleSystem::clone()
@@ -70,78 +50,28 @@ ParticleSystem *ParticleSystem::clone()
return new ParticleSystem(*this);
}
void ParticleSystem::setBufferSize(uint32 size)
{
love::graphics::ParticleSystem::setBufferSize(size);
quadIndices = QuadIndices(size);
createVertices(size);
}
void ParticleSystem::draw(Graphics *gfx, const Matrix4 &m)
{
uint32 pCount = getCount();
if (pCount == 0 || texture.get() == nullptr || pMem == nullptr || buffer == nullptr)
if (!prepareDraw(gfx, m))
return;
gfx->flushStreamDraws();
OpenGL::TempDebugGroup debuggroup("ParticleSystem draw");
Graphics::TempTransform transform(gfx, m);
const Vertex *textureVerts = texture->getVertices();
Vertex *pVerts = (Vertex *) buffer->map();
Particle *p = pHead;
bool useQuads = !quads.empty();
Matrix3 t;
// set the vertex data for each particle (transformation, texcoords, color)
while (p)
{
if (useQuads)
textureVerts = quads[p->quadIndex]->getVertices();
// particle vertices are image vertices transformed by particle info
t.setTransformation(p->position.x, p->position.y, p->angle, p->size, p->size, offset.x, offset.y, 0.0f, 0.0f);
t.transform(pVerts, textureVerts, 4);
// Particle colors are stored as floats (0-1) but vertex colors are
// unsigned bytes (0-255).
Color c = toColor(p->color);
// set the texture coordinate and color data for particle vertices
for (int v = 0; v < 4; v++)
{
pVerts[v].s = textureVerts[v].s;
pVerts[v].t = textureVerts[v].t;
pVerts[v].color = c;
}
pVerts += 4;
p = p->next;
}
buffer->unmap();
gl.bindTextureToUnit(texture, 0, false);
gl.prepareDraw();
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR);
buffer->bind();
gl.bindBuffer(BUFFER_VERTEX, (GLuint) buffer->getHandle());
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), BUFFER_OFFSET(offsetof(Vertex, color.r)));
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(offsetof(Vertex, x)));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(offsetof(Vertex, s)));
GLsizei count = (GLsizei) quadIndices.getIndexCount(pCount);
GLenum gltype = quadIndices.getType();
GLsizei count = (GLsizei) quadIndices.getIndexCount(getCount());
GLenum gltype = OpenGL::getGLIndexDataType(quadIndices.getType());
quadIndices.getBuffer()->bind();
gl.drawElements(GL_TRIANGLES, count, gltype, quadIndices.getPointer(0));
gl.bindBuffer(BUFFER_INDEX, (GLuint) quadIndices.getBuffer()->getHandle());
gl.drawElements(GL_TRIANGLES, count, gltype, BUFFER_OFFSET(0));
}
} // opengl
+6 -13
View File
@@ -23,37 +23,30 @@
// LOVE
#include "graphics/ParticleSystem.h"
#include "GLBuffer.h"
namespace love
{
namespace graphics
{
class Graphics;
namespace opengl
{
class ParticleSystem : public love::graphics::ParticleSystem
class ParticleSystem final : public love::graphics::ParticleSystem
{
public:
ParticleSystem(Texture *texture, uint32 buffer);
ParticleSystem(Graphics *gfx, Texture *texture, uint32 buffer);
ParticleSystem(const ParticleSystem &p);
virtual ~ParticleSystem();
ParticleSystem *clone() override;
void setBufferSize(uint32 size) override;
void draw(Graphics *gfx, const Matrix4 &m) override;
private:
void createVertices(size_t numparticles);
GLBuffer *buffer;
// Vertex index buffer.
QuadIndices quadIndices;
};
}; // ParticleSystem
} // opengl
} // graphics
+5
View File
@@ -726,6 +726,11 @@ bool Shader::hasUniform(const std::string &name) const
return uniforms.find(name) != uniforms.end();
}
ptrdiff_t Shader::getHandle() const
{
return program;
}
GLint Shader::getAttribLocation(const std::string &name)
{
auto it = attributes.find(name);
+1 -5
View File
@@ -62,6 +62,7 @@ public:
void updateUniform(const UniformInfo *info, int count, bool internalUpdate = false) override;
void sendTextures(const UniformInfo *info, Texture **textures, int count, bool internalUpdate = false) override;
bool hasUniform(const std::string &name) const override;
ptrdiff_t getHandle() const override;
void setVideoTextures(ptrdiff_t ytexture, ptrdiff_t cbtexture, ptrdiff_t crtexture) override;
GLint getAttribLocation(const std::string &name);
@@ -70,11 +71,6 @@ public:
void updatePointSize(float size);
void updateBuiltinUniforms();
GLuint getProgram() const
{
return program;
}
static std::string getGLSLVersion();
static bool isSupported();
+20 -20
View File
@@ -25,7 +25,6 @@
#include "OpenGL.h"
// LOVE
#include "GLBuffer.h"
#include "graphics/Texture.h"
#include "graphics/Graphics.h"
@@ -44,13 +43,13 @@ namespace opengl
love::Type SpriteBatch::type("SpriteBatch", &Drawable::type);
SpriteBatch::SpriteBatch(Texture *texture, int size, vertex::Usage usage)
SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usage usage)
: texture(texture)
, size(size)
, next(0)
, color(0)
, array_buf(nullptr)
, quad_indices(size)
, quad_indices(gfx, size)
, range_start(-1)
, range_count(-1)
{
@@ -59,7 +58,7 @@ SpriteBatch::SpriteBatch(Texture *texture, int size, vertex::Usage usage)
size_t vertex_size = sizeof(Vertex) * 4 * size;
array_buf = new GLBuffer(vertex_size, nullptr, BUFFER_VERTEX, usage, GLBuffer::MAP_EXPLICIT_RANGE_MODIFY);
array_buf = gfx->newBuffer(vertex_size, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY);
}
SpriteBatch::~SpriteBatch()
@@ -155,24 +154,21 @@ void SpriteBatch::setBufferSize(int newsize)
if (newsize == size)
return;
// Map the old GLBuffer to get a pointer to its data.
void *old_data = array_buf->map();
size_t vertex_size = sizeof(Vertex) * 4 * newsize;
GLBuffer *new_array_buf = nullptr;
love::graphics::Buffer *new_array_buf = nullptr;
int new_next = std::min(next, newsize);
try
{
new_array_buf = new GLBuffer(vertex_size, nullptr, array_buf->getType(), array_buf->getUsage(), array_buf->getMapFlags());
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
new_array_buf = gfx->newBuffer(vertex_size, nullptr, array_buf->getType(), array_buf->getUsage(), array_buf->getMapFlags());
// Copy as much of the old data into the new GLBuffer as can fit.
size_t copy_size = sizeof(Vertex) * 4 * new_next;
memcpy(new_array_buf->map(), old_data, copy_size);
new_array_buf->setMappedRangeModified(0, copy_size);
array_buf->copyTo(0, copy_size, new_array_buf, 0);
quad_indices = QuadIndices(newsize);
quad_indices = QuadIndices(gfx, newsize);
}
catch (love::Exception &)
{
@@ -262,17 +258,17 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
// Make sure the VBO isn't mapped when we draw (sends data to GPU if needed.)
array_buf->unmap();
array_buf->bind();
gl.bindBuffer(BUFFER_VERTEX, (GLuint) array_buf->getHandle());
// Apply per-sprite color, if a color is set.
if (color)
{
enabledattribs |= ATTRIBFLAG_COLOR;
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), array_buf->getPointer(color_offset));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), BUFFER_OFFSET(color_offset));
}
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), array_buf->getPointer(pos_offset));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), array_buf->getPointer(texel_offset));
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(pos_offset));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(texel_offset));
for (const auto &it : attached_attributes)
{
@@ -301,11 +297,15 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
count = std::min(count, next - start);
quad_indices.getBuffer()->bind();
const void *indices = quad_indices.getPointer(start * quad_indices.getElementSize());
if (count > 0)
gl.drawElements(GL_TRIANGLES, (GLsizei) quad_indices.getIndexCount(count), quad_indices.getType(), indices);
{
gl.bindBuffer(BUFFER_INDEX, (GLuint) quad_indices.getBuffer()->getHandle());
const void *indices = BUFFER_OFFSET(start * quad_indices.getElementSize());
GLenum gltype = OpenGL::getGLIndexDataType(quad_indices.getType());
gl.drawElements(GL_TRIANGLES, (GLsizei) quad_indices.getIndexCount(count), gltype, indices);
}
}
void SpriteBatch::addv(const Vertex *v, const Matrix4 &m, int index)
+4 -3
View File
@@ -34,7 +34,7 @@
#include "graphics/Volatile.h"
#include "graphics/Color.h"
#include "graphics/Quad.h"
#include "GLBuffer.h"
#include "graphics/Buffer.h"
#include "Mesh.h"
namespace love
@@ -44,6 +44,7 @@ namespace graphics
// Forward declarations.
class Texture;
class Graphics;
namespace opengl
{
@@ -54,7 +55,7 @@ public:
static love::Type type;
SpriteBatch(Texture *texture, int size, vertex::Usage usage);
SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usage usage);
virtual ~SpriteBatch();
int add(const Matrix4 &m, int index = -1);
@@ -138,7 +139,7 @@ private:
// added sprite.
Color *color;
GLBuffer *array_buf;
love::graphics::Buffer *array_buf;
QuadIndices quad_indices;
std::unordered_map<std::string, AttachedAttribute> attached_attributes;
+15 -23
View File
@@ -21,6 +21,7 @@
#include "Text.h"
#include "common/Matrix.h"
#include "graphics/Graphics.h"
#include "OpenGL.h"
#include <algorithm>
@@ -33,10 +34,10 @@ namespace opengl
love::Type Text::type("Text", &Drawable::type);
Text::Text(love::graphics::Font *font, const std::vector<Font::ColoredString> &text)
Text::Text(love::graphics::Graphics *gfx, love::graphics::Font *font, const std::vector<Font::ColoredString> &text)
: font(font)
, vbo(nullptr)
, quadIndices(20)
, quadIndices(gfx, 20)
, vert_offset(0)
, texture_cache_id((uint32) -1)
{
@@ -59,25 +60,15 @@ void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t
{
// Make it bigger than necessary to reduce potential future allocations.
size_t newsize = size_t((offset + datasize) * 1.5);
if (vbo != nullptr)
newsize = std::max(size_t(vbo->getSize() * 1.5), newsize);
GLBuffer *new_vbo = new GLBuffer(newsize, nullptr, BUFFER_VERTEX, vertex::USAGE_DYNAMIC);
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
Buffer *new_vbo = gfx->newBuffer(newsize, nullptr, BUFFER_VERTEX, vertex::USAGE_DYNAMIC, 0);
if (vbo != nullptr)
{
try
{
vbodata = (uint8 *) vbo->map();
}
catch (love::Exception &)
{
delete new_vbo;
throw;
}
new_vbo->fill(0, vbo->getSize(), vbodata);
}
vbo->copyTo(0, vbo->getSize(), new_vbo, 0);
delete vbo;
vbo = new_vbo;
@@ -229,7 +220,7 @@ void Text::draw(Graphics *gfx, const Matrix4 &m)
totalverts = std::max(cmd.startvertex + cmd.vertexcount, totalverts);
if ((size_t) totalverts / 4 > quadIndices.getSize())
quadIndices = QuadIndices((size_t) totalverts / 4);
quadIndices = QuadIndices(gfx, (size_t) totalverts / 4);
const size_t pos_offset = offsetof(Font::GlyphVertex, x);
const size_t tex_offset = offsetof(Font::GlyphVertex, s);
@@ -243,16 +234,17 @@ void Text::draw(Graphics *gfx, const Matrix4 &m)
gl.prepareDraw();
vbo->bind();
vbo->unmap(); // Make sure all pending data is flushed to the GPU.
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, vbo->getPointer(pos_offset));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, vbo->getPointer(tex_offset));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, vbo->getPointer(color_offset));
gl.bindBuffer(BUFFER_VERTEX, (GLuint) vbo->getHandle());
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(pos_offset));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, BUFFER_OFFSET(tex_offset));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(color_offset));
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR);
quadIndices.getBuffer()->bind();
gl.bindBuffer(BUFFER_INDEX, (GLuint) quadIndices.getBuffer()->getHandle());
// We need a separate draw call for every section of the text which uses a
// different texture than the previous section.
@@ -264,7 +256,7 @@ void Text::draw(Graphics *gfx, const Matrix4 &m)
// TODO: Use glDrawElementsBaseVertex when supported?
gl.bindTextureToUnit((GLuint) cmd.texture, 0, false);
gl.drawElements(GL_TRIANGLES, count, gltype, quadIndices.getPointer(offset));
gl.drawElements(GL_TRIANGLES, count, gltype, BUFFER_OFFSET(offset));
}
}
+6 -3
View File
@@ -25,12 +25,15 @@
#include "common/config.h"
#include "graphics/Drawable.h"
#include "graphics/Font.h"
#include "GLBuffer.h"
#include "graphics/Buffer.h"
namespace love
{
namespace graphics
{
class Graphics;
namespace opengl
{
@@ -40,7 +43,7 @@ public:
static love::Type type;
Text(love::graphics::Font *font, const std::vector<Font::ColoredString> &text = {});
Text(love::graphics::Graphics *gfx, love::graphics::Font *font, const std::vector<Font::ColoredString> &text = {});
virtual ~Text();
void set(const std::vector<Font::ColoredString> &text);
@@ -85,7 +88,7 @@ private:
void addTextData(const TextData &s);
StrongRef<love::graphics::Font> font;
GLBuffer *vbo;
Buffer *vbo;
QuadIndices quadIndices;
std::vector<Font::DrawCommand> draw_commands;
@@ -19,7 +19,6 @@
**/
#include "wrap_Graphics.h"
#include "OpenGL.h"
#include "graphics/Texture.h"
#include "image/ImageData.h"
#include "image/Image.h"
+6
View File
@@ -66,6 +66,12 @@ size_t getIndexDataSize(IndexDataType type)
}
}
IndexDataType getIndexDataTypeFromMax(size_t maxvalue)
{
IndexDataType types[] = {INDEX_UINT16, INDEX_UINT32};
return types[maxvalue > LOVE_UINT16_MAX ? 1 : 0];
}
int getIndexCount(TriangleIndexMode mode, int vertexCount)
{
switch (mode)
+1
View File
@@ -123,6 +123,7 @@ struct XYf_STus_RGBAub
size_t getFormatStride(CommonFormat format);
size_t getIndexDataSize(IndexDataType type);
IndexDataType getIndexDataTypeFromMax(size_t maxvalue);
int getIndexCount(TriangleIndexMode mode, int vertexCount);