Move most of Text and Video love.graphics classes out of the opengl subfolder.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2017-01-28 21:37:09 -04:00
parent d990044288
commit 13af754d3d
19 changed files with 687 additions and 500 deletions
+7
View File
@@ -36,6 +36,7 @@
#include "Quad.h"
#include "math/Transform.h"
#include "font/Rasterizer.h"
#include "video/VideoStream.h"
// C++
#include <string>
@@ -49,6 +50,8 @@ class Reference;
namespace graphics
{
class Text;
class Video;
class Buffer;
const int MAX_COLOR_RENDER_TARGETS = 8;
@@ -317,8 +320,12 @@ public:
virtual Shader *newShader(const Shader::ShaderSource &source) = 0;
virtual Video *newVideo(love::video::VideoStream *stream, float pixeldensity) = 0;
virtual Buffer *newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) = 0;
virtual Text *newText(Font *font, const std::vector<Font::ColoredString> &text = {}) = 0;
bool validateShader(bool gles, const Shader::ShaderSource &source, std::string &err);
/**
+239
View File
@@ -0,0 +1,239 @@
/**
* 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 "Text.h"
#include "Graphics.h"
#include <algorithm>
namespace love
{
namespace graphics
{
love::Type Text::type("Text", &Drawable::type);
Text::Text(Graphics *gfx, Font *font, const std::vector<Font::ColoredString> &text)
: font(font)
, vbo(nullptr)
, quadIndices(gfx, 20)
, vert_offset(0)
, texture_cache_id((uint32) -1)
{
set(text);
}
Text::~Text()
{
delete vbo;
}
void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t vertoffset)
{
size_t offset = vertoffset * sizeof(Font::GlyphVertex);
size_t datasize = vertices.size() * sizeof(Font::GlyphVertex);
uint8 *vbodata = nullptr;
// If we haven't created a VBO or the vertices are too big, make a new one.
if (datasize > 0 && (!vbo || (offset + datasize) > vbo->getSize()))
{
// 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);
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
Buffer *new_vbo = gfx->newBuffer(newsize, nullptr, BUFFER_VERTEX, vertex::USAGE_DYNAMIC, 0);
if (vbo != nullptr)
vbo->copyTo(0, vbo->getSize(), new_vbo, 0);
delete vbo;
vbo = new_vbo;
}
if (vbo != nullptr && datasize > 0)
{
vbodata = (uint8 *) vbo->map();
memcpy(vbodata + offset, &vertices[0], datasize);
// We unmap when we draw, to avoid unnecessary full map()/unmap() calls.
}
}
void Text::regenerateVertices()
{
// If the font's texture cache was invalidated then we need to recreate the
// text's vertices, since glyph texcoords might have changed.
if (font->getTextureCacheID() != texture_cache_id)
{
std::vector<TextData> textdata = text_data;
clear();
for (const TextData &t : textdata)
addTextData(t);
texture_cache_id = font->getTextureCacheID();
}
}
void Text::addTextData(const TextData &t)
{
std::vector<Font::GlyphVertex> vertices;
std::vector<Font::DrawCommand> new_commands;
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.
if (t.align == Font::ALIGN_MAX_ENUM)
new_commands = font->generateVertices(t.codepoints, constantcolor, vertices, 0.0f, Vector(0.0f, 0.0f), &text_info);
else
new_commands = font->generateVerticesFormatted(t.codepoints, constantcolor, t.wrap, t.align, vertices, &text_info);
if (t.use_matrix)
t.matrix.transform(&vertices[0], &vertices[0], (int) vertices.size());
size_t voffset = vert_offset;
if (!t.append_vertices)
{
voffset = 0;
draw_commands.clear();
text_data.clear();
}
uploadVertices(vertices, voffset);
if (!new_commands.empty())
{
// The start vertex should be adjusted to account for the vertex offset.
for (Font::DrawCommand &cmd : new_commands)
cmd.startvertex += (int) voffset;
auto firstcmd = new_commands.begin();
// If the first draw command in the new list has the same texture as the
// last one in the existing list we're building and its vertices are
// in-order, we can combine them (saving a draw call.)
if (!draw_commands.empty())
{
auto prevcmd = draw_commands.back();
if (prevcmd.texture == firstcmd->texture && (prevcmd.startvertex + prevcmd.vertexcount) == firstcmd->startvertex)
{
draw_commands.back().vertexcount += firstcmd->vertexcount;
++firstcmd;
}
}
// Append the new draw commands to the list we're building.
draw_commands.insert(draw_commands.end(), firstcmd, new_commands.end());
}
vert_offset = voffset + vertices.size();
text_data.push_back(t);
text_data.back().text_info = text_info;
// Font::generateVertices can invalidate the font's texture cache.
if (font->getTextureCacheID() != texture_cache_id)
regenerateVertices();
}
void Text::set(const std::vector<Font::ColoredString> &text)
{
return set(text, -1.0f, Font::ALIGN_MAX_ENUM);
}
void Text::set(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align)
{
if (text.empty() || (text.size() == 1 && text[0].str.empty()))
return clear();
Font::ColoredCodepoints codepoints;
Font::getCodepointsFromString(text, codepoints);
addTextData({codepoints, wrap, align, {}, false, false, Matrix4()});
}
int Text::add(const std::vector<Font::ColoredString> &text, const Matrix4 &m)
{
return addf(text, -1.0f, Font::ALIGN_MAX_ENUM, m);
}
int Text::addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, const Matrix4 &m)
{
Font::ColoredCodepoints codepoints;
Font::getCodepointsFromString(text, codepoints);
addTextData({codepoints, wrap, align, {}, true, true, m});
return (int) text_data.size() - 1;
}
void Text::clear()
{
text_data.clear();
draw_commands.clear();
texture_cache_id = font->getTextureCacheID();
vert_offset = 0;
}
void Text::setFont(Font *f)
{
font.set(f);
// Invalidate the texture cache ID since the font is different. We also have
// to re-upload all the vertices based on the new font's textures.
texture_cache_id = (uint32) -1;
regenerateVertices();
}
Font *Text::getFont() const
{
return font.get();
}
int Text::getWidth(int index) const
{
if (index < 0)
index = std::max((int) text_data.size() - 1, 0);
if (index >= (int) text_data.size())
return 0;
return text_data[index].text_info.width;
}
int Text::getHeight(int index) const
{
if (index < 0)
index = std::max((int) text_data.size() - 1, 0);
if (index >= (int) text_data.size())
return 0;
return text_data[index].text_info.height;
}
} // graphics
} // love
+99
View File
@@ -0,0 +1,99 @@
/**
* 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 "Drawable.h"
#include "Font.h"
#include "Buffer.h"
namespace love
{
namespace graphics
{
class Graphics;
class Text : public Drawable
{
public:
static love::Type type;
Text(Graphics *gfx, Font *font, const std::vector<Font::ColoredString> &text = {});
virtual ~Text();
void set(const std::vector<Font::ColoredString> &text);
void set(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align);
int add(const std::vector<Font::ColoredString> &text, const Matrix4 &m);
int addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, const Matrix4 &m);
void clear();
void setFont(Font *f);
Font *getFont() const;
/**
* Gets the width of the currently set text.
**/
int getWidth(int index = 0) const;
/**
* Gets the height of the currently set text.
**/
int getHeight(int index = 0) const;
protected:
struct TextData
{
Font::ColoredCodepoints codepoints;
float wrap;
Font::AlignMode align;
Font::TextInfo text_info;
bool use_matrix;
bool append_vertices;
Matrix4 matrix;
};
void uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t vertoffset);
void regenerateVertices();
void addTextData(const TextData &s);
StrongRef<Font> font;
Buffer *vbo;
QuadIndices quadIndices;
std::vector<Font::DrawCommand> draw_commands;
std::vector<TextData> text_data;
size_t vert_offset;
// Used so we know when the font's texture cache is invalidated.
uint32 texture_cache_id;
}; // Text
} // graphics
} // love
+172
View File
@@ -0,0 +1,172 @@
/**
* 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 "Video.h"
// LOVE
#include "Shader.h"
#include "Graphics.h"
namespace love
{
namespace graphics
{
love::Type Video::type("Video", &Drawable::type);
Video::Video(love::video::VideoStream *stream, float pixeldensity)
: stream(stream)
, width(stream->getWidth() / pixeldensity)
, height(stream->getHeight() / pixeldensity)
, filter(Texture::defaultFilter)
{
textureHandles[2] = textureHandles[1] = textureHandles[0] = 0;
filter.mipmap = Texture::FILTER_NONE;
stream->fillBackBuffer();
for (int i = 0; i < 4; i++)
vertices[i].color = Color(255, 255, 255, 255);
// Vertices are ordered for use with triangle strips:
// 0---2
// | / |
// 1---3
vertices[0].x = 0.0f;
vertices[0].y = 0.0f;
vertices[1].x = 0.0f;
vertices[1].y = (float) height;
vertices[2].x = (float) width;
vertices[2].y = 0.0f;
vertices[3].x = (float) width;
vertices[3].y = (float) height;
vertices[0].s = 0.0f;
vertices[0].t = 0.0f;
vertices[1].s = 0.0f;
vertices[1].t = 1.0f;
vertices[2].s = 1.0f;
vertices[2].t = 0.0f;
vertices[3].s = 1.0f;
vertices[3].t = 1.0f;
}
Video::~Video()
{
}
love::video::VideoStream *Video::getStream()
{
return stream;
}
void Video::draw(Graphics *gfx, const Matrix4 &m)
{
update();
gfx->flushStreamDraws();
love::graphics::Shader *shader = Shader::current;
bool usingdefaultshader = (shader == Shader::defaultShader);
if (usingdefaultshader)
{
// If we're using the default shader, substitute the video version.
Shader::defaultVideoShader->attach();
shader = Shader::defaultVideoShader;
}
shader->setVideoTextures(textureHandles[0], textureHandles[1], textureHandles[2]);
Graphics::StreamDrawRequest req;
req.formats[0] = vertex::CommonFormat::XYf_STf_RGBAub;
req.indexMode = vertex::TriangleIndexMode::QUADS;
req.vertexCount = 4;
Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
Vertex *verts = (Vertex *) data.stream[0];
Matrix4 t(gfx->getTransform(), m);
t.transform(verts, vertices, 4);
Color c = toColor(gfx->getColor());
for (int i = 0; i < 4; i++)
{
verts[i].s = vertices[i].s;
verts[i].t = vertices[i].t;
verts[i].color = c;
}
gfx->flushStreamDraws();
if (usingdefaultshader)
Shader::defaultShader->attach();
}
void Video::update()
{
bool bufferschanged = stream->swapBuffers();
stream->fillBackBuffer();
if (bufferschanged)
{
auto frame = (const love::video::VideoStream::Frame*) stream->getFrontBuffer();
uploadFrame(frame);
}
}
love::audio::Source *Video::getSource()
{
return source;
}
void Video::setSource(love::audio::Source *source)
{
this->source = source;
}
int Video::getWidth() const
{
return width;
}
int Video::getHeight() const
{
return height;
}
int Video::getPixelWidth() const
{
return stream->getWidth();
}
int Video::getPixelHeight() const
{
return stream->getHeight();
}
const Texture::Filter &Video::getFilter() const
{
return filter;
}
} // graphics
} // love
+85
View File
@@ -0,0 +1,85 @@
/**
* 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/math.h"
#include "Drawable.h"
#include "Texture.h"
#include "vertex.h"
#include "video/VideoStream.h"
#include "audio/Source.h"
namespace love
{
namespace graphics
{
class Video : public Drawable
{
public:
static love::Type type;
Video(love::video::VideoStream *stream, float pixeldensity = 1.0f);
virtual ~Video();
// Drawable
void draw(Graphics *gfx, const Matrix4 &m) override;
love::video::VideoStream *getStream();
love::audio::Source *getSource();
void setSource(love::audio::Source *source);
int getWidth() const;
int getHeight() const;
int getPixelWidth() const;
int getPixelHeight() const;
virtual void setFilter(const Texture::Filter &f) = 0;
const Texture::Filter &getFilter() const;
protected:
virtual void uploadFrame(const love::video::VideoStream::Frame *frame) = 0;
StrongRef<love::video::VideoStream> stream;
int width;
int height;
Texture::Filter filter;
Vertex vertices[4];
ptrdiff_t textureHandles[3];
private:
void update();
StrongRef<love::audio::Source> source;
}; // Video
} // graphics
} // love
+4 -2
View File
@@ -30,6 +30,8 @@
#include "math/MathModule.h"
#include "window/Window.h"
#include "Buffer.h"
#include "Video.h"
#include "Text.h"
#include "libraries/xxHash/xxhash.h"
@@ -185,12 +187,12 @@ Mesh *Graphics::newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, con
return new Mesh(this, vertexformat, data, datasize, drawmode, usage);
}
Text *Graphics::newText(graphics::Font *font, const std::vector<Font::ColoredString> &text)
love::graphics::Text *Graphics::newText(graphics::Font *font, const std::vector<Font::ColoredString> &text)
{
return new Text(this, font, text);
}
Video *Graphics::newVideo(love::video::VideoStream *stream, float pixeldensity)
love::graphics::Video *Graphics::newVideo(love::video::VideoStream *stream, float pixeldensity)
{
return new Video(stream, pixeldensity);
}
+2 -6
View File
@@ -36,16 +36,12 @@
#include "image/Image.h"
#include "image/ImageData.h"
#include "video/VideoStream.h"
#include "Image.h"
#include "SpriteBatch.h"
#include "ParticleSystem.h"
#include "Canvas.h"
#include "Shader.h"
#include "Mesh.h"
#include "Text.h"
#include "Video.h"
namespace love
{
@@ -86,9 +82,9 @@ public:
Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage);
Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, const void *data, size_t datasize, Mesh::DrawMode drawmode, vertex::Usage usage);
Text *newText(love::graphics::Font *font, const std::vector<Font::ColoredString> &text = {});
love::graphics::Text *newText(love::graphics::Font *font, const std::vector<Font::ColoredString> &text = {}) override;
Video *newVideo(love::video::VideoStream *stream, float pixeldensity);
love::graphics::Video *newVideo(love::video::VideoStream *stream, float pixeldensity) override;
void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
bool setMode(int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil) override;
+3 -3
View File
@@ -335,14 +335,14 @@ public:
}
private:
GLuint vbo;
size_t gpuReadOffset;
GLenum glMode;
uint8 *data;
BufferSync sync;
}; // StreamBufferPersistentMapSync
love::graphics::StreamBuffer *CreateStreamBuffer(BufferType mode, size_t size)
+1 -202
View File
@@ -19,12 +19,9 @@
**/
#include "Text.h"
#include "common/Matrix.h"
#include "graphics/Graphics.h"
#include "OpenGL.h"
#include <algorithm>
namespace love
{
namespace graphics
@@ -32,174 +29,13 @@ namespace graphics
namespace opengl
{
love::Type Text::type("Text", &Drawable::type);
Text::Text(love::graphics::Graphics *gfx, love::graphics::Font *font, const std::vector<Font::ColoredString> &text)
: font(font)
, vbo(nullptr)
, quadIndices(gfx, 20)
, vert_offset(0)
, texture_cache_id((uint32) -1)
: love::graphics::Text(gfx, font, text)
{
set(text);
}
Text::~Text()
{
delete vbo;
}
void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t vertoffset)
{
size_t offset = vertoffset * sizeof(Font::GlyphVertex);
size_t datasize = vertices.size() * sizeof(Font::GlyphVertex);
uint8 *vbodata = nullptr;
// If we haven't created a VBO or the vertices are too big, make a new one.
if (datasize > 0 && (!vbo || (offset + datasize) > vbo->getSize()))
{
// 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);
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
Buffer *new_vbo = gfx->newBuffer(newsize, nullptr, BUFFER_VERTEX, vertex::USAGE_DYNAMIC, 0);
if (vbo != nullptr)
vbo->copyTo(0, vbo->getSize(), new_vbo, 0);
delete vbo;
vbo = new_vbo;
}
if (vbo != nullptr && datasize > 0)
{
vbodata = (uint8 *) vbo->map();
memcpy(vbodata + offset, &vertices[0], datasize);
// We unmap when we draw, to avoid unnecessary full map()/unmap() calls.
}
}
void Text::regenerateVertices()
{
// If the font's texture cache was invalidated then we need to recreate the
// text's vertices, since glyph texcoords might have changed.
if (font->getTextureCacheID() != texture_cache_id)
{
std::vector<TextData> textdata = text_data;
clear();
for (const TextData &t : textdata)
addTextData(t);
texture_cache_id = font->getTextureCacheID();
}
}
void Text::addTextData(const TextData &t)
{
std::vector<Font::GlyphVertex> vertices;
std::vector<Font::DrawCommand> new_commands;
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.
if (t.align == Font::ALIGN_MAX_ENUM)
new_commands = font->generateVertices(t.codepoints, constantcolor, vertices, 0.0f, Vector(0.0f, 0.0f), &text_info);
else
new_commands = font->generateVerticesFormatted(t.codepoints, constantcolor, t.wrap, t.align, vertices, &text_info);
if (t.use_matrix)
t.matrix.transform(&vertices[0], &vertices[0], (int) vertices.size());
size_t voffset = vert_offset;
if (!t.append_vertices)
{
voffset = 0;
draw_commands.clear();
text_data.clear();
}
uploadVertices(vertices, voffset);
if (!new_commands.empty())
{
// The start vertex should be adjusted to account for the vertex offset.
for (Font::DrawCommand &cmd : new_commands)
cmd.startvertex += (int) voffset;
auto firstcmd = new_commands.begin();
// If the first draw command in the new list has the same texture as the
// last one in the existing list we're building and its vertices are
// in-order, we can combine them (saving a draw call.)
if (!draw_commands.empty())
{
auto prevcmd = draw_commands.back();
if (prevcmd.texture == firstcmd->texture && (prevcmd.startvertex + prevcmd.vertexcount) == firstcmd->startvertex)
{
draw_commands.back().vertexcount += firstcmd->vertexcount;
++firstcmd;
}
}
// Append the new draw commands to the list we're building.
draw_commands.insert(draw_commands.end(), firstcmd, new_commands.end());
}
vert_offset = voffset + vertices.size();
text_data.push_back(t);
text_data.back().text_info = text_info;
// Font::generateVertices can invalidate the font's texture cache.
if (font->getTextureCacheID() != texture_cache_id)
regenerateVertices();
}
void Text::set(const std::vector<Font::ColoredString> &text)
{
return set(text, -1.0f, Font::ALIGN_MAX_ENUM);
}
void Text::set(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align)
{
if (text.empty() || (text.size() == 1 && text[0].str.empty()))
return clear();
Font::ColoredCodepoints codepoints;
Font::getCodepointsFromString(text, codepoints);
addTextData({codepoints, wrap, align, {}, false, false, Matrix4()});
}
int Text::add(const std::vector<Font::ColoredString> &text, const Matrix4 &m)
{
return addf(text, -1.0f, Font::ALIGN_MAX_ENUM, m);
}
int Text::addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, const Matrix4 &m)
{
Font::ColoredCodepoints codepoints;
Font::getCodepointsFromString(text, codepoints);
addTextData({codepoints, wrap, align, {}, true, true, m});
return (int) text_data.size() - 1;
}
void Text::clear()
{
text_data.clear();
draw_commands.clear();
texture_cache_id = font->getTextureCacheID();
vert_offset = 0;
}
void Text::draw(Graphics *gfx, const Matrix4 &m)
@@ -260,43 +96,6 @@ void Text::draw(Graphics *gfx, const Matrix4 &m)
}
}
void Text::setFont(love::graphics::Font *f)
{
font.set(f);
// Invalidate the texture cache ID since the font is different. We also have
// to re-upload all the vertices based on the new font's textures.
texture_cache_id = (uint32) -1;
regenerateVertices();
}
love::graphics::Font *Text::getFont() const
{
return font.get();
}
int Text::getWidth(int index) const
{
if (index < 0)
index = std::max((int) text_data.size() - 1, 0);
if (index >= (int) text_data.size())
return 0;
return text_data[index].text_info.width;
}
int Text::getHeight(int index) const
{
if (index < 0)
index = std::max((int) text_data.size() - 1, 0);
if (index >= (int) text_data.size())
return 0;
return text_data[index].text_info.height;
}
} // opengl
} // graphics
} // love
+4 -66
View File
@@ -18,92 +18,30 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_GRAPHICS_OPENGL_TEXT_H
#define LOVE_GRAPHICS_OPENGL_TEXT_H
#pragma once
// LOVE
#include "common/config.h"
#include "graphics/Drawable.h"
#include "graphics/Font.h"
#include "graphics/Buffer.h"
#include "graphics/Text.h"
namespace love
{
namespace graphics
{
class Graphics;
namespace opengl
{
class Text : public Drawable
class Text final : public love::graphics::Text
{
public:
static love::Type type;
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);
void set(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align);
int add(const std::vector<Font::ColoredString> &text, const Matrix4 &m);
int addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, const Matrix4 &m);
void clear();
// Implements Drawable.
void draw(Graphics *gfx, const Matrix4 &m) override;
void setFont(love::graphics::Font *f);
love::graphics::Font *getFont() const;
/**
* Gets the width of the currently set text.
**/
int getWidth(int index = 0) const;
/**
* Gets the height of the currently set text.
**/
int getHeight(int index = 0) const;
private:
struct TextData
{
Font::ColoredCodepoints codepoints;
float wrap;
Font::AlignMode align;
Font::TextInfo text_info;
bool use_matrix;
bool append_vertices;
Matrix4 matrix;
};
void uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t vertoffset);
void regenerateVertices();
void addTextData(const TextData &s);
StrongRef<love::graphics::Font> font;
Buffer *vbo;
QuadIndices quadIndices;
std::vector<Font::DrawCommand> draw_commands;
std::vector<TextData> text_data;
size_t vert_offset;
// Used so we know when the font's texture cache is invalidated.
uint32 texture_cache_id;
void draw(love::graphics::Graphics *gfx, const Matrix4 &m) override;
}; // Text
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_TEXT_H
+18 -143
View File
@@ -20,10 +20,6 @@
#include "Video.h"
// LOVE
#include "Shader.h"
#include "graphics/Graphics.h"
namespace love
{
namespace graphics
@@ -31,43 +27,9 @@ namespace graphics
namespace opengl
{
love::Type Video::type("Video", &Drawable::type);
Video::Video(love::video::VideoStream *stream, float pixeldensity)
: stream(stream)
, width(stream->getWidth() / pixeldensity)
, height(stream->getHeight() / pixeldensity)
, filter(Texture::defaultFilter)
: love::graphics::Video(stream, pixeldensity)
{
filter.mipmap = Texture::FILTER_NONE;
stream->fillBackBuffer();
for (int i = 0; i < 4; i++)
vertices[i].color = Color(255, 255, 255, 255);
// Vertices are ordered for use with triangle strips:
// 0---2
// | / |
// 1---3
vertices[0].x = 0.0f;
vertices[0].y = 0.0f;
vertices[1].x = 0.0f;
vertices[1].y = (float) height;
vertices[2].x = (float) width;
vertices[2].y = 0.0f;
vertices[3].x = (float) width;
vertices[3].y = (float) height;
vertices[0].s = 0.0f;
vertices[0].t = 0.0f;
vertices[1].s = 0.0f;
vertices[1].t = 1.0f;
vertices[2].s = 1.0f;
vertices[2].t = 0.0f;
vertices[3].s = 1.0f;
vertices[3].t = 1.0f;
loadVolatile();
}
@@ -78,8 +40,12 @@ Video::~Video()
bool Video::loadVolatile()
{
GLuint textures[3];
glGenTextures(3, textures);
for (int i = 0; i < 3; i++)
textureHandles[i] = textures[i];
// Create the textures using the initial frame data.
auto frame = (const love::video::VideoStream::Frame*) stream->getFrontBuffer();
@@ -111,113 +77,27 @@ void Video::unloadVolatile()
{
for (int i = 0; i < 3; i++)
{
gl.deleteTexture(textures[i]);
textures[i] = 0;
gl.deleteTexture((GLuint) textureHandles[i]);
textureHandles[i] = 0;
}
}
love::video::VideoStream *Video::getStream()
void Video::uploadFrame(const love::video::VideoStream::Frame *frame)
{
return stream;
}
int widths[3] = {frame->yw, frame->cw, frame->cw};
int heights[3] = {frame->yh, frame->ch, frame->ch};
void Video::draw(Graphics *gfx, const Matrix4 &m)
{
update();
const unsigned char *data[3] = {frame->yplane, frame->cbplane, frame->crplane};
gfx->flushStreamDraws();
bool srgb = false;
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(PIXELFORMAT_R8, false, srgb);
love::graphics::Shader *shader = Shader::current;
bool usingdefaultshader = (shader == Shader::defaultShader);
if (usingdefaultshader)
for (int i = 0; i < 3; i++)
{
// If we're using the default shader, substitute the video version.
Shader::defaultVideoShader->attach();
shader = Shader::defaultVideoShader;
gl.bindTextureToUnit((GLuint) textureHandles[i], 0, false);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, widths[i], heights[i],
fmt.externalformat, fmt.type, data[i]);
}
shader->setVideoTextures(textures[0], textures[1], textures[2]);
Graphics::StreamDrawRequest req;
req.formats[0] = vertex::CommonFormat::XYf_STf_RGBAub;
req.indexMode = vertex::TriangleIndexMode::QUADS;
req.vertexCount = 4;
Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
Vertex *verts = (Vertex *) data.stream[0];
Matrix4 t(gfx->getTransform(), m);
t.transform(verts, vertices, 4);
Color c = toColor(gfx->getColor());
for (int i = 0; i < 4; i++)
{
verts[i].s = vertices[i].s;
verts[i].t = vertices[i].t;
verts[i].color = c;
}
gfx->flushStreamDraws();
if (usingdefaultshader)
Shader::defaultShader->attach();
}
void Video::update()
{
bool bufferschanged = stream->swapBuffers();
stream->fillBackBuffer();
if (bufferschanged)
{
auto frame = (const love::video::VideoStream::Frame*) stream->getFrontBuffer();
int widths[3] = {frame->yw, frame->cw, frame->cw};
int heights[3] = {frame->yh, frame->ch, frame->ch};
const unsigned char *data[3] = {frame->yplane, frame->cbplane, frame->crplane};
bool srgb = false;
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(PIXELFORMAT_R8, false, srgb);
for (int i = 0; i < 3; i++)
{
gl.bindTextureToUnit(textures[i], 0, false);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, widths[i], heights[i],
fmt.externalformat, fmt.type, data[i]);
}
}
}
love::audio::Source *Video::getSource()
{
return source;
}
void Video::setSource(love::audio::Source *source)
{
this->source = source;
}
int Video::getWidth() const
{
return width;
}
int Video::getHeight() const
{
return height;
}
int Video::getPixelWidth() const
{
return stream->getWidth();
}
int Video::getPixelHeight() const
{
return stream->getHeight();
}
void Video::setFilter(const Texture::Filter &f)
@@ -229,16 +109,11 @@ void Video::setFilter(const Texture::Filter &f)
for (int i = 0; i < 3; i++)
{
gl.bindTextureToUnit(textures[i], 0, false);
gl.bindTextureToUnit((GLuint) textureHandles[i], 0, false);
gl.setTextureFilter(filter);
}
}
const Texture::Filter &Video::getFilter() const
{
return filter;
}
} // opengl
} // graphics
} // love
+5 -36
View File
@@ -21,12 +21,8 @@
#pragma once
// LOVE
#include "common/math.h"
#include "graphics/Drawable.h"
#include "graphics/Video.h"
#include "graphics/Volatile.h"
#include "video/VideoStream.h"
#include "audio/Source.h"
#include "OpenGL.h"
namespace love
@@ -36,49 +32,22 @@ namespace graphics
namespace opengl
{
class Video : public Drawable, public Volatile
class Video : public love::graphics::Video, public Volatile
{
public:
static love::Type type;
Video(love::video::VideoStream *stream, float pixeldensity = 1.0f);
~Video();
virtual ~Video();
// Volatile
bool loadVolatile() override;
void unloadVolatile() override;
// Drawable
void draw(Graphics *gfx, const Matrix4 &m) override;
love::video::VideoStream *getStream();
love::audio::Source *getSource();
void setSource(love::audio::Source *source);
int getWidth() const;
int getHeight() const;
int getPixelWidth() const;
int getPixelHeight() const;
void setFilter(const Texture::Filter &f);
const Texture::Filter &getFilter() const;
void setFilter(const Texture::Filter &f) override;
private:
void update();
StrongRef<love::video::VideoStream> stream;
StrongRef<love::audio::Source> source;
int width;
int height;
GLuint textures[3];
Vertex vertices[4];
void uploadFrame(const love::video::VideoStream::Frame *frame) override;
Texture::Filter filter;
+2 -2
View File
@@ -31,8 +31,8 @@
#include "graphics/wrap_Canvas.h"
#include "graphics/wrap_Shader.h"
#include "wrap_Mesh.h"
#include "wrap_Text.h"
#include "wrap_Video.h"
#include "graphics/wrap_Text.h"
#include "graphics/wrap_Video.h"
#include "Graphics.h"
namespace love
@@ -19,15 +19,13 @@
**/
#include "wrap_Text.h"
#include "graphics/wrap_Font.h"
#include "wrap_Font.h"
#include "math/wrap_Transform.h"
namespace love
{
namespace graphics
{
namespace opengl
{
Text *luax_checktext(lua_State *L, int idx)
{
@@ -227,6 +225,5 @@ extern "C" int luaopen_text(lua_State *L)
return luax_register_type(L, &Text::type, w_Text_functions, nullptr);
}
} // opengl
} // graphics
} // love
@@ -18,8 +18,7 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_GRAPHICS_OPENGL_WRAP_TEXT_H
#define LOVE_GRAPHICS_OPENGL_WRAP_TEXT_H
#pragma once
#include "Text.h"
#include "common/runtime.h"
@@ -28,15 +27,9 @@ namespace love
{
namespace graphics
{
namespace opengl
{
Text *luax_checktext(lua_State *L, int idx);
extern "C" int luaopen_text(lua_State *L);
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_WRAP_TEXT_H
@@ -29,8 +29,6 @@ namespace love
{
namespace graphics
{
namespace opengl
{
Video *luax_checkvideo(lua_State *L, int idx)
{
@@ -177,6 +175,5 @@ int luaopen_video(lua_State *L)
return ret;
}
} // opengl
} // graphics
} // love
@@ -28,11 +28,8 @@ namespace love
{
namespace graphics
{
namespace opengl
{
int luaopen_video(lua_State *L);
} // opengl
} // graphics
} // love