mirror of
https://github.com/love2d/love.git
synced 2026-08-17 11:00:31 +02:00
Use automatic batching for love.graphics.print/printf.
This doesn’t actually improve performance at all in most cases, but it does remove some OpenGL-specific code from the Font files, and reduces the amount of duplicated rendering code. This makes it slightly easier to add support for Core Profile OpenGL 3. --HG-- branch : minor
This commit is contained in:
@@ -53,6 +53,13 @@ void gammaCorrectColor(Colorf &c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Colorf gammaCorrectColor(const Colorf &c)
|
||||||
|
{
|
||||||
|
Colorf r = c;
|
||||||
|
gammaCorrectColor(r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
void unGammaCorrectColor(Colorf &c)
|
void unGammaCorrectColor(Colorf &c)
|
||||||
{
|
{
|
||||||
if (isGammaCorrect())
|
if (isGammaCorrect())
|
||||||
@@ -63,6 +70,13 @@ void unGammaCorrectColor(Colorf &c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Colorf unGammaCorrectColor(const Colorf &c)
|
||||||
|
{
|
||||||
|
Colorf r = c;
|
||||||
|
unGammaCorrectColor(r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
love::Type Graphics::type("graphics", &Module::type);
|
love::Type Graphics::type("graphics", &Module::type);
|
||||||
|
|
||||||
Graphics::Graphics()
|
Graphics::Graphics()
|
||||||
@@ -92,7 +106,7 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest &
|
|||||||
if (req.primitiveMode != state.primitiveMode
|
if (req.primitiveMode != state.primitiveMode
|
||||||
|| req.formats[0] != state.formats[0] || req.formats[1] != state.formats[1]
|
|| req.formats[0] != state.formats[0] || req.formats[1] != state.formats[1]
|
||||||
|| ((req.indexMode != TriangleIndexMode::NONE) != (state.indexCount > 0))
|
|| ((req.indexMode != TriangleIndexMode::NONE) != (state.indexCount > 0))
|
||||||
|| req.texture != state.texture)
|
|| req.texture != state.texture || req.textureHandle != state.textureHandle)
|
||||||
{
|
{
|
||||||
shouldflush = true;
|
shouldflush = true;
|
||||||
}
|
}
|
||||||
@@ -156,6 +170,7 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest &
|
|||||||
state.formats[0] = req.formats[0];
|
state.formats[0] = req.formats[0];
|
||||||
state.formats[1] = req.formats[1];
|
state.formats[1] = req.formats[1];
|
||||||
state.texture = req.texture;
|
state.texture = req.texture;
|
||||||
|
state.textureHandle = req.textureHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldresize)
|
if (shouldresize)
|
||||||
|
|||||||
@@ -66,6 +66,9 @@ void gammaCorrectColor(Colorf &c);
|
|||||||
**/
|
**/
|
||||||
void unGammaCorrectColor(Colorf &c);
|
void unGammaCorrectColor(Colorf &c);
|
||||||
|
|
||||||
|
Colorf gammaCorrectColor(const Colorf &c);
|
||||||
|
Colorf unGammaCorrectColor(const Colorf &c);
|
||||||
|
|
||||||
class Graphics : public Module
|
class Graphics : public Module
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -236,6 +239,10 @@ public:
|
|||||||
int vertexCount = 0;
|
int vertexCount = 0;
|
||||||
Texture *texture = nullptr;
|
Texture *texture = nullptr;
|
||||||
|
|
||||||
|
// FIXME: This is only needed for fonts. We should just change fonts to
|
||||||
|
// use love.graphics Images instead of raw OpenGL textures.
|
||||||
|
ptrdiff_t textureHandle = 0;
|
||||||
|
|
||||||
StreamDrawRequest()
|
StreamDrawRequest()
|
||||||
{
|
{
|
||||||
// VS2013 can't initialize arrays in the above manner...
|
// VS2013 can't initialize arrays in the above manner...
|
||||||
@@ -455,6 +462,7 @@ protected:
|
|||||||
vertex::PrimitiveMode primitiveMode;
|
vertex::PrimitiveMode primitiveMode;
|
||||||
vertex::CommonFormat formats[2];
|
vertex::CommonFormat formats[2];
|
||||||
StrongRef<Texture> texture;
|
StrongRef<Texture> texture;
|
||||||
|
ptrdiff_t textureHandle = 0;
|
||||||
int vertexCount;
|
int vertexCount;
|
||||||
int indexCount;
|
int indexCount;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -141,6 +141,9 @@ GLenum Font::getTextureFormat(FontType fontType, GLenum *internalformat) const
|
|||||||
|
|
||||||
void Font::createTexture()
|
void Font::createTexture()
|
||||||
{
|
{
|
||||||
|
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
|
||||||
|
gfx->flushStreamDraws();
|
||||||
|
|
||||||
OpenGL::TempDebugGroup debuggroup("Font create texture");
|
OpenGL::TempDebugGroup debuggroup("Font create texture");
|
||||||
|
|
||||||
size_t bpp = fontType == FONT_TRUETYPE ? 2 : 4;
|
size_t bpp = fontType == FONT_TRUETYPE ? 2 : 4;
|
||||||
@@ -413,7 +416,7 @@ float Font::getHeight() const
|
|||||||
return (float) height;
|
return (float) height;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Font::DrawCommand> Font::generateVertices(const ColoredCodepoints &codepoints, std::vector<GlyphVertex> &vertices, float extra_spacing, Vector offset, TextInfo *info)
|
std::vector<Font::DrawCommand> Font::generateVertices(const ColoredCodepoints &codepoints, const Colorf &constantcolor, std::vector<GlyphVertex> &vertices, float extra_spacing, Vector offset, TextInfo *info)
|
||||||
{
|
{
|
||||||
// Spacing counter and newline handling.
|
// Spacing counter and newline handling.
|
||||||
float dx = offset.x;
|
float dx = offset.x;
|
||||||
@@ -431,9 +434,9 @@ std::vector<Font::DrawCommand> Font::generateVertices(const ColoredCodepoints &c
|
|||||||
|
|
||||||
uint32 prevglyph = 0;
|
uint32 prevglyph = 0;
|
||||||
|
|
||||||
Color initialcolor(255, 255, 255, 255);
|
Colorf linearconstantcolor = gammaCorrectColor(constantcolor);
|
||||||
|
|
||||||
Color curcolor = initialcolor;
|
Color curcolor = toColor(constantcolor);
|
||||||
int curcolori = -1;
|
int curcolori = -1;
|
||||||
int ncolors = (int) codepoints.colors.size();
|
int ncolors = (int) codepoints.colors.size();
|
||||||
|
|
||||||
@@ -443,7 +446,11 @@ std::vector<Font::DrawCommand> Font::generateVertices(const ColoredCodepoints &c
|
|||||||
|
|
||||||
if (curcolori + 1 < ncolors && codepoints.colors[curcolori + 1].index == i)
|
if (curcolori + 1 < ncolors && codepoints.colors[curcolori + 1].index == i)
|
||||||
{
|
{
|
||||||
curcolor = toColor(codepoints.colors[++curcolori].color);
|
Colorf color = gammaCorrectColor(codepoints.colors[++curcolori].color);
|
||||||
|
color *= linearconstantcolor;
|
||||||
|
unGammaCorrectColor(color);
|
||||||
|
|
||||||
|
curcolor = toColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g == '\n')
|
if (g == '\n')
|
||||||
@@ -476,7 +483,7 @@ std::vector<Font::DrawCommand> Font::generateVertices(const ColoredCodepoints &c
|
|||||||
vertices.resize(vertstartsize);
|
vertices.resize(vertstartsize);
|
||||||
prevglyph = 0;
|
prevglyph = 0;
|
||||||
curcolori = -1;
|
curcolori = -1;
|
||||||
curcolor = initialcolor;
|
curcolor = toColor(constantcolor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +523,6 @@ std::vector<Font::DrawCommand> Font::generateVertices(const ColoredCodepoints &c
|
|||||||
dx = floorf(dx + extra_spacing);
|
dx = floorf(dx + extra_spacing);
|
||||||
|
|
||||||
prevglyph = g;
|
prevglyph = g;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto drawsort = [](const DrawCommand &a, const DrawCommand &b) -> bool
|
const auto drawsort = [](const DrawCommand &a, const DrawCommand &b) -> bool
|
||||||
@@ -535,21 +541,14 @@ std::vector<Font::DrawCommand> Font::generateVertices(const ColoredCodepoints &c
|
|||||||
|
|
||||||
if (info != nullptr)
|
if (info != nullptr)
|
||||||
{
|
{
|
||||||
info->width = maxwidth - offset.x;;
|
info->width = maxwidth - offset.x;
|
||||||
info->height = (int) dy + (dx > 0.0f ? floorf(getHeight() * getLineHeight() + 0.5f) : 0) - offset.y;
|
info->height = (int) dy + (dx > 0.0f ? floorf(getHeight() * getLineHeight() + 0.5f) : 0) - offset.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Font::DrawCommand> Font::generateVertices(const std::string &text, std::vector<GlyphVertex> &vertices, float extra_spacing, Vector offset, TextInfo *info)
|
std::vector<Font::DrawCommand> Font::generateVerticesFormatted(const ColoredCodepoints &text, const Colorf &constantcolor, float wrap, AlignMode align, std::vector<GlyphVertex> &vertices, TextInfo *info)
|
||||||
{
|
|
||||||
ColoredCodepoints codepoints;
|
|
||||||
getCodepointsFromString(text, codepoints.cps);
|
|
||||||
return generateVertices(codepoints, vertices, extra_spacing, offset, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Font::DrawCommand> Font::generateVerticesFormatted(const ColoredCodepoints &text, float wrap, AlignMode align, std::vector<GlyphVertex> &vertices, TextInfo *info)
|
|
||||||
{
|
{
|
||||||
wrap = std::max(wrap, 0.0f);
|
wrap = std::max(wrap, 0.0f);
|
||||||
|
|
||||||
@@ -598,7 +597,7 @@ std::vector<Font::DrawCommand> Font::generateVerticesFormatted(const ColoredCode
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<DrawCommand> newcommands = generateVertices(line, vertices, extraspacing, offset);
|
std::vector<DrawCommand> newcommands = generateVertices(line, constantcolor, vertices, extraspacing, offset);
|
||||||
|
|
||||||
if (!newcommands.empty())
|
if (!newcommands.empty())
|
||||||
{
|
{
|
||||||
@@ -633,98 +632,55 @@ std::vector<Font::DrawCommand> Font::generateVerticesFormatted(const ColoredCode
|
|||||||
if (cacheid != textureCacheID)
|
if (cacheid != textureCacheID)
|
||||||
{
|
{
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
drawcommands = generateVerticesFormatted(text, wrap, align, vertices);
|
drawcommands = generateVerticesFormatted(text, constantcolor, wrap, align, vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
return drawcommands;
|
return drawcommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::drawVertices(const std::vector<DrawCommand> &drawcommands, bool bufferedvertices)
|
void Font::printv(graphics::Graphics *gfx, const Matrix4 &t, const std::vector<DrawCommand> &drawcommands, const std::vector<GlyphVertex> &vertices)
|
||||||
{
|
|
||||||
// Vertex attribute pointers need to be set before calling this function.
|
|
||||||
// This assumes that the attribute pointers are constant for all vertices.
|
|
||||||
|
|
||||||
int totalverts = 0;
|
|
||||||
for (const DrawCommand &cmd : drawcommands)
|
|
||||||
totalverts = std::max(cmd.startvertex + cmd.vertexcount, totalverts);
|
|
||||||
|
|
||||||
if ((size_t) totalverts / 4 > quadIndices.getSize())
|
|
||||||
quadIndices = QuadIndices((size_t) totalverts / 4);
|
|
||||||
|
|
||||||
gl.prepareDraw();
|
|
||||||
|
|
||||||
const GLenum gltype = quadIndices.getType();
|
|
||||||
const size_t elemsize = quadIndices.getElementSize();
|
|
||||||
|
|
||||||
// We only get indices from the index buffer if we're also using vertex
|
|
||||||
// buffers, because at least one graphics driver (the one for Kepler nvidia
|
|
||||||
// GPUs in OS X 10.11) fails to render geometry if an index buffer is used
|
|
||||||
// with client-side vertex arrays.
|
|
||||||
if (bufferedvertices)
|
|
||||||
quadIndices.getBuffer()->bind();
|
|
||||||
else
|
|
||||||
gl.bindBuffer(BUFFER_INDEX, 0);
|
|
||||||
|
|
||||||
// We need a separate draw call for every section of the text which uses a
|
|
||||||
// different texture than the previous section.
|
|
||||||
for (const DrawCommand &cmd : drawcommands)
|
|
||||||
{
|
|
||||||
GLsizei count = (cmd.vertexcount / 4) * 6;
|
|
||||||
size_t offset = (cmd.startvertex / 4) * 6 * elemsize;
|
|
||||||
|
|
||||||
// TODO: Use glDrawElementsBaseVertex when supported?
|
|
||||||
gl.bindTextureToUnit(cmd.texture, 0, false);
|
|
||||||
|
|
||||||
if (bufferedvertices)
|
|
||||||
gl.drawElements(GL_TRIANGLES, count, gltype, quadIndices.getPointer(offset));
|
|
||||||
else
|
|
||||||
gl.drawElements(GL_TRIANGLES, count, gltype, quadIndices.getIndices(offset));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Font::printv(const Matrix4 &t, const std::vector<DrawCommand> &drawcommands, const std::vector<GlyphVertex> &vertices)
|
|
||||||
{
|
{
|
||||||
if (vertices.empty() || drawcommands.empty())
|
if (vertices.empty() || drawcommands.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
|
Matrix4 m(gfx->getTransform(), t);
|
||||||
|
|
||||||
gfx->flushStreamDraws();
|
for (const DrawCommand &cmd : drawcommands)
|
||||||
|
{
|
||||||
|
Graphics::StreamDrawRequest req;
|
||||||
|
req.formats[0] = vertex::CommonFormat::XYf_STus_RGBAub;
|
||||||
|
req.indexMode = vertex::TriangleIndexMode::QUADS;
|
||||||
|
req.vertexCount = cmd.vertexcount;
|
||||||
|
req.textureHandle = cmd.texture;
|
||||||
|
|
||||||
OpenGL::TempDebugGroup debuggroup("Font print");
|
Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
|
||||||
|
GlyphVertex *vertexdata = (GlyphVertex *) data.stream[0];
|
||||||
|
|
||||||
Graphics::TempTransform transform(gfx, t);
|
memcpy(vertexdata, &vertices[cmd.startvertex], sizeof(GlyphVertex) * cmd.vertexcount);
|
||||||
|
m.transform(vertexdata, &vertices[cmd.startvertex], cmd.vertexcount);
|
||||||
gl.bindBuffer(BUFFER_VERTEX, 0);
|
}
|
||||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(GlyphVertex), &vertices[0].x);
|
|
||||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(GlyphVertex), &vertices[0].s);
|
|
||||||
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GlyphVertex), &vertices[0].color.r);
|
|
||||||
|
|
||||||
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR);
|
|
||||||
|
|
||||||
drawVertices(drawcommands, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::print(const std::vector<ColoredString> &text, const Matrix4 &m)
|
void Font::print(graphics::Graphics *gfx, const std::vector<ColoredString> &text, const Matrix4 &m, const Colorf &constantcolor)
|
||||||
{
|
{
|
||||||
ColoredCodepoints codepoints;
|
ColoredCodepoints codepoints;
|
||||||
getCodepointsFromString(text, codepoints);
|
getCodepointsFromString(text, codepoints);
|
||||||
|
|
||||||
std::vector<GlyphVertex> vertices;
|
std::vector<GlyphVertex> vertices;
|
||||||
std::vector<DrawCommand> drawcommands = generateVertices(codepoints, vertices);
|
std::vector<DrawCommand> drawcommands = generateVertices(codepoints, constantcolor, vertices);
|
||||||
|
|
||||||
printv(m, drawcommands, vertices);
|
printv(gfx, m, drawcommands, vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::printf(const std::vector<ColoredString> &text, float wrap, AlignMode align, const Matrix4 &m)
|
void Font::printf(graphics::Graphics *gfx, const std::vector<ColoredString> &text, float wrap, AlignMode align, const Matrix4 &m, const Colorf &constantcolor)
|
||||||
{
|
{
|
||||||
ColoredCodepoints codepoints;
|
ColoredCodepoints codepoints;
|
||||||
getCodepointsFromString(text, codepoints);
|
getCodepointsFromString(text, codepoints);
|
||||||
|
|
||||||
std::vector<GlyphVertex> vertices;
|
std::vector<GlyphVertex> vertices;
|
||||||
std::vector<DrawCommand> drawcommands = generateVerticesFormatted(codepoints, wrap, align, vertices);
|
std::vector<DrawCommand> drawcommands = generateVerticesFormatted(codepoints, constantcolor, wrap, align, vertices);
|
||||||
|
|
||||||
printv(m, drawcommands, vertices);
|
printv(gfx, m, drawcommands, vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Font::getWidth(const std::string &str)
|
int Font::getWidth(const std::string &str)
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include "font/Rasterizer.h"
|
#include "font/Rasterizer.h"
|
||||||
#include "graphics/Texture.h"
|
#include "graphics/Texture.h"
|
||||||
#include "graphics/Volatile.h"
|
#include "graphics/Volatile.h"
|
||||||
|
#include "graphics/vertex.h"
|
||||||
#include "GLBuffer.h"
|
#include "GLBuffer.h"
|
||||||
|
|
||||||
#include "OpenGL.h"
|
#include "OpenGL.h"
|
||||||
@@ -43,6 +44,9 @@ namespace love
|
|||||||
{
|
{
|
||||||
namespace graphics
|
namespace graphics
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class Graphics;
|
||||||
|
|
||||||
namespace opengl
|
namespace opengl
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -53,6 +57,7 @@ public:
|
|||||||
static love::Type type;
|
static love::Type type;
|
||||||
|
|
||||||
typedef std::vector<uint32> Codepoints;
|
typedef std::vector<uint32> Codepoints;
|
||||||
|
typedef vertex::XYf_STus_RGBAub GlyphVertex;
|
||||||
|
|
||||||
enum AlignMode
|
enum AlignMode
|
||||||
{
|
{
|
||||||
@@ -81,13 +86,6 @@ public:
|
|||||||
std::vector<IndexedColor> colors;
|
std::vector<IndexedColor> colors;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GlyphVertex
|
|
||||||
{
|
|
||||||
float x, y;
|
|
||||||
uint16 s, t;
|
|
||||||
Color color;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TextInfo
|
struct TextInfo
|
||||||
{
|
{
|
||||||
int width;
|
int width;
|
||||||
@@ -106,21 +104,20 @@ public:
|
|||||||
|
|
||||||
virtual ~Font();
|
virtual ~Font();
|
||||||
|
|
||||||
std::vector<DrawCommand> generateVertices(const ColoredCodepoints &codepoints, std::vector<GlyphVertex> &vertices, float extra_spacing = 0.0f, Vector offset = {}, TextInfo *info = nullptr);
|
std::vector<DrawCommand> generateVertices(const ColoredCodepoints &codepoints, const Colorf &constantColor, std::vector<GlyphVertex> &vertices,
|
||||||
std::vector<DrawCommand> generateVertices(const std::string &text, std::vector<GlyphVertex> &vertices, float extra_spacing = 0.0f, Vector offset = Vector(), TextInfo *info = nullptr);
|
float extra_spacing = 0.0f, Vector offset = {}, TextInfo *info = nullptr);
|
||||||
|
|
||||||
std::vector<DrawCommand> generateVerticesFormatted(const ColoredCodepoints &text, float wrap, AlignMode align, std::vector<GlyphVertex> &vertices, TextInfo *info = nullptr);
|
std::vector<DrawCommand> generateVerticesFormatted(const ColoredCodepoints &text, const Colorf &constantColor, float wrap, AlignMode align,
|
||||||
|
std::vector<GlyphVertex> &vertices, TextInfo *info = nullptr);
|
||||||
void drawVertices(const std::vector<DrawCommand> &drawcommands, bool bufferedvertices);
|
|
||||||
|
|
||||||
static void getCodepointsFromString(const std::string &str, Codepoints &codepoints);
|
static void getCodepointsFromString(const std::string &str, Codepoints &codepoints);
|
||||||
static void getCodepointsFromString(const std::vector<ColoredString> &strs, ColoredCodepoints &codepoints);
|
static void getCodepointsFromString(const std::vector<ColoredString> &strs, ColoredCodepoints &codepoints);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the text at the designated position with a transformation applied.
|
* Draws the specified text.
|
||||||
**/
|
**/
|
||||||
void print(const std::vector<ColoredString> &text, const Matrix4 &m);
|
void print(graphics::Graphics *gfx, const std::vector<ColoredString> &text, const Matrix4 &m, const Colorf &constantColor);
|
||||||
void printf(const std::vector<ColoredString> &text, float wrap, AlignMode align, const Matrix4 &m);
|
void printf(graphics::Graphics *gfx, const std::vector<ColoredString> &text, float wrap, AlignMode align, const Matrix4 &m, const Colorf &constantColor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the height of the font.
|
* Returns the height of the font.
|
||||||
@@ -218,7 +215,7 @@ private:
|
|||||||
const Glyph &addGlyph(uint32 glyph);
|
const Glyph &addGlyph(uint32 glyph);
|
||||||
const Glyph &findGlyph(uint32 glyph);
|
const Glyph &findGlyph(uint32 glyph);
|
||||||
float getKerning(uint32 leftglyph, uint32 rightglyph);
|
float getKerning(uint32 leftglyph, uint32 rightglyph);
|
||||||
void printv(const Matrix4 &t, const std::vector<DrawCommand> &drawcommands, const std::vector<GlyphVertex> &vertices);
|
void printv(graphics::Graphics *gfx, const Matrix4 &t, const std::vector<DrawCommand> &drawcommands, const std::vector<GlyphVertex> &vertices);
|
||||||
|
|
||||||
std::vector<StrongRef<love::font::Rasterizer>> rasterizers;
|
std::vector<StrongRef<love::font::Rasterizer>> rasterizers;
|
||||||
|
|
||||||
|
|||||||
@@ -468,7 +468,10 @@ void Graphics::flushStreamDraws()
|
|||||||
|
|
||||||
gl.prepareDraw();
|
gl.prepareDraw();
|
||||||
|
|
||||||
gl.bindTextureToUnit(sbstate.texture, 0, false);
|
if (sbstate.textureHandle != 0)
|
||||||
|
gl.bindTextureToUnit((GLuint) sbstate.textureHandle, 0, false);
|
||||||
|
else
|
||||||
|
gl.bindTextureToUnit(sbstate.texture, 0, false);
|
||||||
|
|
||||||
gl.useVertexAttribArrays(attribs);
|
gl.useVertexAttribArrays(attribs);
|
||||||
|
|
||||||
@@ -1730,7 +1733,7 @@ void Graphics::print(const std::vector<Font::ColoredString> &str, const Matrix4
|
|||||||
DisplayState &state = states.back();
|
DisplayState &state = states.back();
|
||||||
|
|
||||||
if (state.font.get() != nullptr)
|
if (state.font.get() != nullptr)
|
||||||
state.font->print(str, m);
|
state.font->print(this, str, m, state.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::printf(const std::vector<Font::ColoredString> &str, float wrap, Font::AlignMode align, const Matrix4 &m)
|
void Graphics::printf(const std::vector<Font::ColoredString> &str, float wrap, Font::AlignMode align, const Matrix4 &m)
|
||||||
@@ -1740,7 +1743,7 @@ void Graphics::printf(const std::vector<Font::ColoredString> &str, float wrap, F
|
|||||||
DisplayState &state = states.back();
|
DisplayState &state = states.back();
|
||||||
|
|
||||||
if (state.font.get() != nullptr)
|
if (state.font.get() != nullptr)
|
||||||
state.font->printf(str, wrap, align, m);
|
state.font->printf(this, str, wrap, align, m, state.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ love::Type Text::type("Text", &Drawable::type);
|
|||||||
Text::Text(Font *font, const std::vector<Font::ColoredString> &text)
|
Text::Text(Font *font, const std::vector<Font::ColoredString> &text)
|
||||||
: font(font)
|
: font(font)
|
||||||
, vbo(nullptr)
|
, vbo(nullptr)
|
||||||
|
, quadIndices(20)
|
||||||
, vert_offset(0)
|
, vert_offset(0)
|
||||||
, texture_cache_id((uint32) -1)
|
, texture_cache_id((uint32) -1)
|
||||||
{
|
{
|
||||||
@@ -114,11 +115,13 @@ void Text::addTextData(const TextData &t)
|
|||||||
|
|
||||||
Font::TextInfo text_info;
|
Font::TextInfo text_info;
|
||||||
|
|
||||||
|
Colorf constantcolor = Colorf(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
// We only have formatted text if the align mode is valid.
|
// We only have formatted text if the align mode is valid.
|
||||||
if (t.align == Font::ALIGN_MAX_ENUM)
|
if (t.align == Font::ALIGN_MAX_ENUM)
|
||||||
new_commands = font->generateVertices(t.codepoints, vertices, 0.0f, Vector(0.0f, 0.0f), &text_info);
|
new_commands = font->generateVertices(t.codepoints, constantcolor, vertices, 0.0f, Vector(0.0f, 0.0f), &text_info);
|
||||||
else
|
else
|
||||||
new_commands = font->generateVerticesFormatted(t.codepoints, t.wrap, t.align, vertices, &text_info);
|
new_commands = font->generateVerticesFormatted(t.codepoints, constantcolor, t.wrap, t.align, vertices, &text_info);
|
||||||
|
|
||||||
if (t.use_matrix)
|
if (t.use_matrix)
|
||||||
t.matrix.transform(&vertices[0], &vertices[0], (int) vertices.size());
|
t.matrix.transform(&vertices[0], &vertices[0], (int) vertices.size());
|
||||||
@@ -221,24 +224,48 @@ void Text::draw(Graphics *gfx, const Matrix4 &m)
|
|||||||
if (font->getTextureCacheID() != texture_cache_id)
|
if (font->getTextureCacheID() != texture_cache_id)
|
||||||
regenerateVertices();
|
regenerateVertices();
|
||||||
|
|
||||||
|
int totalverts = 0;
|
||||||
|
for (const Font::DrawCommand &cmd : draw_commands)
|
||||||
|
totalverts = std::max(cmd.startvertex + cmd.vertexcount, totalverts);
|
||||||
|
|
||||||
|
if ((size_t) totalverts / 4 > quadIndices.getSize())
|
||||||
|
quadIndices = QuadIndices((size_t) totalverts / 4);
|
||||||
|
|
||||||
const size_t pos_offset = offsetof(Font::GlyphVertex, x);
|
const size_t pos_offset = offsetof(Font::GlyphVertex, x);
|
||||||
const size_t tex_offset = offsetof(Font::GlyphVertex, s);
|
const size_t tex_offset = offsetof(Font::GlyphVertex, s);
|
||||||
const size_t color_offset = offsetof(Font::GlyphVertex, color.r);
|
const size_t color_offset = offsetof(Font::GlyphVertex, color.r);
|
||||||
const size_t stride = sizeof(Font::GlyphVertex);
|
const size_t stride = sizeof(Font::GlyphVertex);
|
||||||
|
|
||||||
|
const GLenum gltype = quadIndices.getType();
|
||||||
|
const size_t elemsize = quadIndices.getElementSize();
|
||||||
|
|
||||||
Graphics::TempTransform transform(gfx, m);
|
Graphics::TempTransform transform(gfx, m);
|
||||||
|
|
||||||
|
gl.prepareDraw();
|
||||||
|
|
||||||
vbo->bind();
|
vbo->bind();
|
||||||
vbo->unmap(); // Make sure all pending data is flushed to the GPU.
|
vbo->unmap(); // Make sure all pending data is flushed to the GPU.
|
||||||
|
|
||||||
// Font::drawVertices expects AttribPointer calls to be done already.
|
|
||||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, vbo->getPointer(pos_offset));
|
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_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));
|
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, vbo->getPointer(color_offset));
|
||||||
|
|
||||||
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR);
|
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR);
|
||||||
|
|
||||||
font->drawVertices(draw_commands, true);
|
quadIndices.getBuffer()->bind();
|
||||||
|
|
||||||
|
// We need a separate draw call for every section of the text which uses a
|
||||||
|
// different texture than the previous section.
|
||||||
|
for (const Font::DrawCommand &cmd : draw_commands)
|
||||||
|
{
|
||||||
|
GLsizei count = (cmd.vertexcount / 4) * 6;
|
||||||
|
size_t offset = (cmd.startvertex / 4) * 6 * elemsize;
|
||||||
|
|
||||||
|
// TODO: Use glDrawElementsBaseVertex when supported?
|
||||||
|
gl.bindTextureToUnit(cmd.texture, 0, false);
|
||||||
|
|
||||||
|
gl.drawElements(GL_TRIANGLES, count, gltype, quadIndices.getPointer(offset));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::setFont(Font *f)
|
void Text::setFont(Font *f)
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ private:
|
|||||||
|
|
||||||
StrongRef<Font> font;
|
StrongRef<Font> font;
|
||||||
GLBuffer *vbo;
|
GLBuffer *vbo;
|
||||||
|
QuadIndices quadIndices;
|
||||||
|
|
||||||
std::vector<Font::DrawCommand> draw_commands;
|
std::vector<Font::DrawCommand> draw_commands;
|
||||||
|
|
||||||
|
|||||||
@@ -39,13 +39,6 @@ enum BufferType
|
|||||||
BUFFER_MAX_ENUM
|
BUFFER_MAX_ENUM
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Vertex
|
|
||||||
{
|
|
||||||
float x, y;
|
|
||||||
float s, t;
|
|
||||||
Color color;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace vertex
|
namespace vertex
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -88,9 +81,9 @@ struct XYf_STf_RGBAub
|
|||||||
|
|
||||||
struct XYf_STus_RGBAub
|
struct XYf_STus_RGBAub
|
||||||
{
|
{
|
||||||
float x, y;
|
float x, y;
|
||||||
uint16 s, t;
|
uint16 s, t;
|
||||||
Color color;
|
Color color;
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t getFormatStride(CommonFormat format);
|
size_t getFormatStride(CommonFormat format);
|
||||||
@@ -101,5 +94,8 @@ void fillIndices(TriangleIndexMode mode, uint16 vertexStart, uint16 vertexCount,
|
|||||||
void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount, uint32 *indices);
|
void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount, uint32 *indices);
|
||||||
|
|
||||||
} // vertex
|
} // vertex
|
||||||
|
|
||||||
|
typedef vertex::XYf_STf_RGBAub Vertex;
|
||||||
|
|
||||||
} // graphics
|
} // graphics
|
||||||
} // love
|
} // love
|
||||||
|
|||||||
Reference in New Issue
Block a user