mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
love.graphics internal Buffer objects are no longer OpenGL-specific.
--HG-- branch : minor
This commit is contained in:
+4
-2
@@ -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 */,
|
||||
|
||||
@@ -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
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
// LOVE
|
||||
#include "Graphics.h"
|
||||
#include "Buffer.h"
|
||||
#include "math/MathModule.h"
|
||||
#include "Polyline.h"
|
||||
#include "font/Font.h"
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
// LOVE
|
||||
#include "Shader.h"
|
||||
#include "Graphics.h"
|
||||
#include "math/MathModule.h"
|
||||
|
||||
// glslang
|
||||
#include "libraries/glslang/glslang/Public/ShaderLang.h"
|
||||
|
||||
@@ -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[];
|
||||
|
||||
+26
-175
@@ -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
|
||||
@@ -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
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user