many graphics performance tweaks

* use hardware vertex buffers (video memory)
* cache text drawing with vertex buffers instead of framebuffers
* avoid recalculating texture transformation matrix
This commit is contained in:
Eduardo Bart 2012-03-20 16:10:04 -03:00
parent b4261a8c7b
commit 5c35938a92
20 changed files with 180 additions and 155 deletions

View File

@ -22,26 +22,21 @@
#include "coordsbuffer.h" #include "coordsbuffer.h"
void CoordsBuffer::clear() CoordsBuffer::CoordsBuffer()
{ {
m_destRects.reset(); m_hardwareCacheMode = HardwareBuffer::DynamicDraw;
m_srcRects.reset(); m_hardwareVertexBuffer = nullptr;
m_textureCoords.clear(); m_hardwareTextureVertexBuffer = nullptr;
m_vertices.clear(); m_hardwareCached = false;
m_updateCache = true; m_hardwareCaching = false;
} }
void CoordsBuffer::addRect(const Rect& dest) CoordsBuffer::~CoordsBuffer()
{ {
m_destRects << dest; if(m_hardwareVertexBuffer)
m_updateCache = true; delete m_hardwareVertexBuffer;
} if(m_hardwareTextureVertexBuffer)
delete m_hardwareTextureVertexBuffer;
void CoordsBuffer::addRect(const Rect& dest, const Rect& src)
{
m_destRects << dest;
m_srcRects << src;
m_updateCache = true;
} }
void CoordsBuffer::addBoudingRect(const Rect& dest, int innerLineWidth) void CoordsBuffer::addBoudingRect(const Rect& dest, int innerLineWidth)
@ -58,7 +53,6 @@ void CoordsBuffer::addBoudingRect(const Rect& dest, int innerLineWidth)
addRect(Rect(right - w + 1, top, w, height - w)); // right addRect(Rect(right - w + 1, top, w, height - w)); // right
addRect(Rect(left + w, bottom - w + 1, width - w, w)); // bottom addRect(Rect(left + w, bottom - w + 1, width - w, w)); // bottom
addRect(Rect(left, top + w, w, height - w)); // left addRect(Rect(left, top + w, w, height - w)); // left
m_updateCache = true;
} }
void CoordsBuffer::addRepeatedRects(const Rect& dest, const Rect& src) void CoordsBuffer::addRepeatedRects(const Rect& dest, const Rect& src)
@ -83,28 +77,38 @@ void CoordsBuffer::addRepeatedRects(const Rect& dest, const Rect& src)
} }
partialDest.translate(dest.topLeft()); partialDest.translate(dest.topLeft());
m_destRects << partialDest; m_vertexBuffer.addRect(partialDest);
m_srcRects << partialSrc; m_textureVertexBuffer.addRect(partialSrc);
} }
} }
m_updateCache = true; m_hardwareCached = false;
} }
void CoordsBuffer::cacheVertexArrays() void CoordsBuffer::enableHardwareCaching(HardwareBuffer::UsagePattern usagePattern)
{ {
if(!m_updateCache) m_hardwareCacheMode = usagePattern;
m_hardwareCaching = true;
m_hardwareCached = false;
}
void CoordsBuffer::updateCaches()
{
if(!m_hardwareCaching || m_hardwareCached)
return; return;
int numDestRects = m_destRects.size(); if(m_vertexBuffer.vertexCount() > 0) {
int numSrcRects = m_srcRects.size(); if(!m_hardwareVertexBuffer && m_vertexBuffer.vertexCount() > 0)
m_vertices.clear(); m_hardwareVertexBuffer = new HardwareBuffer(HardwareBuffer::VertexBuffer);
m_textureCoords.clear(); m_hardwareVertexBuffer->bind();
m_hardwareVertexBuffer->write((void*)m_vertexBuffer.vertices(), m_vertexBuffer.size() * sizeof(float), m_hardwareCacheMode);
for(register int i=0;i<numDestRects;++i) {
m_vertices.addRect(m_destRects[i]);
if(numSrcRects == numDestRects)
m_textureCoords.addRect(m_srcRects[i]);
} }
m_updateCache = false; if(m_textureVertexBuffer.vertexCount() > 0) {
if(!m_hardwareTextureVertexBuffer && m_textureVertexBuffer.vertexCount() > 0)
m_hardwareTextureVertexBuffer = new HardwareBuffer(HardwareBuffer::VertexBuffer);
m_hardwareTextureVertexBuffer->bind();
m_hardwareTextureVertexBuffer->write((void*)m_textureVertexBuffer.vertices(), m_textureVertexBuffer.size() * sizeof(float), m_hardwareCacheMode);
}
m_hardwareCached = true;
} }

View File

@ -24,33 +24,53 @@
#define COORDSBUFFER_H #define COORDSBUFFER_H
#include "vertexarray.h" #include "vertexarray.h"
#include "hardwarebuffer.h"
class CoordsBuffer class CoordsBuffer
{ {
public: public:
void clear(); CoordsBuffer();
~CoordsBuffer();
void clear() {
m_textureVertexBuffer.clear();
m_vertexBuffer.clear();
m_hardwareCached = false;
}
void addRect(const Rect& dest) {
m_vertexBuffer.addRect(dest);
m_hardwareCached = false;
}
void addRect(const Rect& dest, const Rect& src) {
m_vertexBuffer.addRect(dest);
m_textureVertexBuffer.addRect(src);
m_hardwareCached = false;
}
// no texture
void addRect(const Rect& dest);
void addBoudingRect(const Rect& dest, int innerLineWidth); void addBoudingRect(const Rect& dest, int innerLineWidth);
// textured
void addRect(const Rect& dest, const Rect& src);
void addRepeatedRects(const Rect& dest, const Rect& src); void addRepeatedRects(const Rect& dest, const Rect& src);
void cacheVertexArrays(); void enableHardwareCaching(HardwareBuffer::UsagePattern usagePattern = HardwareBuffer::DynamicDraw);
void updateCaches();
bool isHardwareCached() { return m_hardwareCached; }
float *getVertices() const { return m_vertices.vertices(); } float *getVertexBuffer() const { return m_vertexBuffer.vertices(); }
float *getTextureCoords() const { return m_textureCoords.vertices(); } float *getTextureVertexBuffer() const { return m_textureVertexBuffer.vertices(); }
int getVertexCount() const { return m_vertices.vertexCount(); } int getVertexCount() const { return m_vertexBuffer.vertexCount(); }
int getTextureCoordsCount() const { return m_textureCoords.vertexCount(); } int getTextureVertexCount() const { return m_textureVertexBuffer.vertexCount(); }
HardwareBuffer *getHardwareVertexBuffer() { return m_hardwareVertexBuffer; }
HardwareBuffer *getHardwareTextureVertexBuffer() { return m_hardwareTextureVertexBuffer; }
private: private:
DataBuffer<Rect> m_destRects; HardwareBuffer *m_hardwareVertexBuffer;
DataBuffer<Rect> m_srcRects; HardwareBuffer *m_hardwareTextureVertexBuffer;
VertexArray m_vertices; HardwareBuffer::UsagePattern m_hardwareCacheMode;
VertexArray m_textureCoords; VertexArray m_vertexBuffer;
Boolean<true> m_updateCache; VertexArray m_textureVertexBuffer;
bool m_hardwareCached;
bool m_hardwareCaching;
}; };
#endif #endif

View File

@ -61,20 +61,23 @@ void Font::load(const OTMLNodePtr& fontNode)
} }
} }
void Font::renderText(const std::string& text, void Font::drawText(const std::string& text, const Point& startPos)
const Point& startPos,
const Color& color)
{ {
Size boxSize = g_graphics.getViewportSize() - startPos.toSize(); Size boxSize = g_graphics.getViewportSize() - startPos.toSize();
Rect screenCoords(startPos, boxSize); Rect screenCoords(startPos, boxSize);
renderText(text, screenCoords, Fw::AlignTopLeft, color); drawText(text, screenCoords, Fw::AlignTopLeft);
} }
void Font::drawText(const std::string& text, const Rect& screenCoords, Fw::AlignmentFlag align)
{
static CoordsBuffer coordsBuffer;
coordsBuffer.clear();
void Font::renderText(const std::string& text, calculateDrawTextCoords(coordsBuffer, text, screenCoords, align);
const Rect& screenCoords, g_painter.drawTextureCoords(coordsBuffer, m_texture);
Fw::AlignmentFlag align, }
const Color& color)
void Font::calculateDrawTextCoords(CoordsBuffer& coordsBuffer, const std::string& text, const Rect& screenCoords, Fw::AlignmentFlag align)
{ {
// prevent glitches from invalid rects // prevent glitches from invalid rects
if(!screenCoords.isValid() || !m_texture) if(!screenCoords.isValid() || !m_texture)
@ -86,8 +89,6 @@ void Font::renderText(const std::string& text,
Size textBoxSize; Size textBoxSize;
const std::vector<Point>& glyphsPositions = calculateGlyphsPositions(text, align, &textBoxSize); const std::vector<Point>& glyphsPositions = calculateGlyphsPositions(text, align, &textBoxSize);
g_painter.setColor(color);
for(int i = 0; i < textLenght; ++i) { for(int i = 0; i < textLenght; ++i) {
int glyph = (uchar)text[i]; int glyph = (uchar)text[i];
@ -148,7 +149,7 @@ void Font::renderText(const std::string& text,
} }
// render glyph // render glyph
g_painter.drawTexturedRect(glyphScreenCoords, m_texture, glyphTextureCoords); coordsBuffer.addRect(glyphScreenCoords, glyphTextureCoords);
} }
} }

View File

@ -26,6 +26,7 @@
#include "declarations.h" #include "declarations.h"
#include <framework/otml/declarations.h> #include <framework/otml/declarations.h>
#include <framework/graphics/coordsbuffer.h>
class Font class Font
{ {
@ -36,15 +37,12 @@ public:
void load(const OTMLNodePtr& fontNode); void load(const OTMLNodePtr& fontNode);
/// Simple text render starting at startPos /// Simple text render starting at startPos
void renderText(const std::string& text, void drawText(const std::string& text, const Point& startPos);
const Point& startPos,
const Color& color = Color::white);
/// Advanced text render delimited by a screen region and alignment /// Advanced text render delimited by a screen region and alignment
void renderText(const std::string& text, void drawText(const std::string& text, const Rect& screenCoords, Fw::AlignmentFlag align = Fw::AlignTopLeft);
const Rect& screenCoords,
Fw::AlignmentFlag align = Fw::AlignTopLeft, void calculateDrawTextCoords(CoordsBuffer& coordsBuffer, const std::string& text, const Rect& screenCoords, Fw::AlignmentFlag align = Fw::AlignTopLeft);
const Color& color = Color::white);
/// Calculate glyphs positions to use on render, also calculates textBoxSize if wanted /// Calculate glyphs positions to use on render, also calculates textBoxSize if wanted
const std::vector<Point>& calculateGlyphsPositions(const std::string& text, const std::vector<Point>& calculateGlyphsPositions(const std::string& text,

View File

@ -1,25 +0,0 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "hardwarebuffer.h"

View File

@ -24,8 +24,46 @@
#ifndef HARDWAREBUFFER_H #ifndef HARDWAREBUFFER_H
#define HARDWAREBUFFER_H #define HARDWAREBUFFER_H
#include "declarations.h"
class HardwareBuffer class HardwareBuffer
{ {
public:
enum Type {
VertexBuffer = GL_ARRAY_BUFFER,
IndexBuffer = GL_ELEMENT_ARRAY_BUFFER
};
enum UsagePattern {
StreamDraw = GL_STREAM_DRAW,
StreamRead = GL_STREAM_READ,
StreamCopy = GL_STREAM_COPY,
StaticDraw = GL_STATIC_DRAW,
StaticRead = GL_STATIC_READ,
StaticCopy = GL_STATIC_COPY,
DynamicDraw = GL_DYNAMIC_DRAW,
DynamicRead = GL_DYNAMIC_READ,
DynamicCopy = GL_DYNAMIC_COPY
};
HardwareBuffer(Type type ) {
m_type = type;
m_id = 0;
glGenBuffers(1, &m_id);
assert(m_id != 0);
}
~HardwareBuffer() {
glDeleteBuffers(1, &m_id);
}
void bind() { glBindBuffer(m_type, m_id); }
static void unbind(Type type) { glBindBuffer(type, 0); }
void write(void *data, int count, UsagePattern usage) { glBufferData(m_type, count, data, usage); }
//void read(void *data, int count);
private:
Type m_type;
GLuint m_id;
}; };
#endif #endif

View File

@ -55,7 +55,6 @@ void Painter::terminate()
void Painter::drawProgram(const PainterShaderProgramPtr& program, CoordsBuffer& coordsBuffer, PainterShaderProgram::DrawMode drawMode) void Painter::drawProgram(const PainterShaderProgramPtr& program, CoordsBuffer& coordsBuffer, PainterShaderProgram::DrawMode drawMode)
{ {
coordsBuffer.cacheVertexArrays();
if(coordsBuffer.getVertexCount() == 0) if(coordsBuffer.getVertexCount() == 0)
return; return;

View File

@ -79,41 +79,38 @@ void PainterShaderProgram::setTexture(const TexturePtr& texture)
if(!texture) if(!texture)
return; return;
float w = texture->getWidth();
float h = texture->getHeight();
Matrix2 textureTransformMatrix = { 1.0f/w, 0.0f,
0.0f, 1.0f/h };
textureTransformMatrix.transpose();
bind(); bind();
setUniformTexture(TEXTURE_UNIFORM, texture, 0); setUniformTexture(TEXTURE_UNIFORM, texture, 0);
setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, textureTransformMatrix); setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, texture->getTransformMatrix());
} }
void PainterShaderProgram::draw(const CoordsBuffer& coordsBuffer, DrawMode drawMode) void PainterShaderProgram::draw(CoordsBuffer& coordsBuffer, DrawMode drawMode)
{ {
bind(); bind();
setUniformValue(TIME_UNIFORM, g_clock.timeElapsed(m_startTime)); setUniformValue(TIME_UNIFORM, g_clock.timeElapsed(m_startTime));
int numVertices = coordsBuffer.getVertexCount(); int vertexCount = coordsBuffer.getVertexCount();
if(numVertices == 0) if(vertexCount == 0)
return; return;
bool mustDisableVertexArray = false; coordsBuffer.updateCaches();
if(coordsBuffer.getVertexCount() > 0) { bool hardwareCached = coordsBuffer.isHardwareCached();
enableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR); enableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR);
setAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR, coordsBuffer.getVertices(), 2); if(hardwareCached)
mustDisableVertexArray = true; coordsBuffer.getHardwareVertexBuffer()->bind();
setAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR, hardwareCached ? 0 : coordsBuffer.getVertexBuffer(), 2);
if(coordsBuffer.getTextureVertexCount() != 0) {
enableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR);
if(hardwareCached)
coordsBuffer.getHardwareTextureVertexBuffer()->bind();
setAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR, hardwareCached ? 0 : coordsBuffer.getTextureVertexBuffer(), 2);
} }
bool mustDisableTexCoordsArray = false; if(hardwareCached)
if(coordsBuffer.getTextureCoordsCount() > 0) { HardwareBuffer::unbind(HardwareBuffer::VertexBuffer);
enableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR);
setAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR, coordsBuffer.getTextureCoords(), 2);
mustDisableTexCoordsArray = true;
}
for(int i=0;i<(int)m_textures.size();++i) { for(int i=0;i<(int)m_textures.size();++i) {
int location = std::get<0>(m_textures[i]); int location = std::get<0>(m_textures[i]);
@ -127,14 +124,11 @@ void PainterShaderProgram::draw(const CoordsBuffer& coordsBuffer, DrawMode drawM
} }
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glDrawArrays(drawMode, 0, numVertices); glDrawArrays(drawMode, 0, vertexCount);
if(mustDisableVertexArray)
disableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR); disableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR);
if(mustDisableTexCoordsArray) if(coordsBuffer.getTextureVertexCount() != 0)
disableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR); disableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR);
//release();
} }

View File

@ -54,7 +54,7 @@ public:
void setOpacity(float opacity); void setOpacity(float opacity);
void setTexture(const TexturePtr& texture); void setTexture(const TexturePtr& texture);
void setUniformTexture(int location, const TexturePtr& texture, int index); void setUniformTexture(int location, const TexturePtr& texture, int index);
void draw(const CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); void draw(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
private: private:
DrawMode m_drawMode; DrawMode m_drawMode;

View File

@ -45,6 +45,8 @@ Texture::~Texture()
uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int height) uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int height)
{ {
m_size.resize(width, height); m_size.resize(width, height);
m_transformMatrix = { 1.0f/width, 0.0f,
0.0f, 1.0f/height };
// gets max texture size supported by the driver // gets max texture size supported by the driver
static GLint maxTexSize = -1; static GLint maxTexSize = -1;
@ -63,6 +65,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
// generate gl texture // generate gl texture
GLuint id; GLuint id;
glGenTextures(1, &id); glGenTextures(1, &id);
assert(id != 0);
glBindTexture(GL_TEXTURE_2D, id); glBindTexture(GL_TEXTURE_2D, id);
// detect pixels GL format // detect pixels GL format

View File

@ -47,6 +47,7 @@ public:
int getWidth() { return m_size.width(); } int getWidth() { return m_size.width(); }
int getHeight() { return m_size.height(); } int getHeight() { return m_size.height(); }
const Size& getSize() { return m_size; } const Size& getSize() { return m_size; }
const Matrix2& getTransformMatrix() { return m_transformMatrix; }
bool isEmpty() { return m_textureId == 0; } bool isEmpty() { return m_textureId == 0; }
bool hasMipmaps() { return m_hasMipmaps; } bool hasMipmaps() { return m_hasMipmaps; }
@ -57,6 +58,7 @@ protected:
GLuint m_textureId; GLuint m_textureId;
Size m_size; Size m_size;
Matrix2 m_transformMatrix;
Boolean<false> m_hasMipmaps; Boolean<false> m_hasMipmaps;
Boolean<false> m_smooth; Boolean<false> m_smooth;
}; };

View File

@ -59,6 +59,7 @@ public:
void clear() { m_buffer.reset(); } void clear() { m_buffer.reset(); }
float *vertices() const { return m_buffer.data(); } float *vertices() const { return m_buffer.data(); }
int vertexCount() const { return m_buffer.size() / 2; } int vertexCount() const { return m_buffer.size() / 2; }
int size() const { return m_buffer.size(); }
private: private:
DataBuffer<float> m_buffer; DataBuffer<float> m_buffer;

View File

@ -47,7 +47,8 @@ void UIFrameCounter::draw()
} }
m_frameCount++; m_frameCount++;
m_font->renderText(m_fpsText, m_rect, m_align, Color::white); g_painter.setColor(Color::white);
m_font->drawText(m_fpsText, m_rect, m_align);
} }
void UIFrameCounter::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode) void UIFrameCounter::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)

View File

@ -362,7 +362,7 @@ public:
// image // image
private: private:
void initImage() { } void initImage();
void parseImageStyle(const OTMLNodePtr& styleNode); void parseImageStyle(const OTMLNodePtr& styleNode);
void updateImageCache() { m_imageMustRecache = true; } void updateImageCache() { m_imageMustRecache = true; }
@ -427,8 +427,8 @@ private:
void parseTextStyle(const OTMLNodePtr& styleNode); void parseTextStyle(const OTMLNodePtr& styleNode);
Boolean<true> m_textMustRecache; Boolean<true> m_textMustRecache;
FrameBufferPtr m_textFramebuffer; CoordsBuffer m_textCoordsBuffer;
Size m_textCachedBoxSize; Rect m_textCachedScreenCoords;
protected: protected:
void drawText(const Rect& screenCoords); void drawText(const Rect& screenCoords);

View File

@ -25,6 +25,11 @@
#include <framework/graphics/texture.h> #include <framework/graphics/texture.h>
#include <framework/graphics/texturemanager.h> #include <framework/graphics/texturemanager.h>
void UIWidget::initImage()
{
m_imageCoordsBuffer.enableHardwareCaching();
}
void UIWidget::parseImageStyle(const OTMLNodePtr& styleNode) void UIWidget::parseImageStyle(const OTMLNodePtr& styleNode)
{ {
for(const OTMLNodePtr& node : styleNode->children()) { for(const OTMLNodePtr& node : styleNode->children()) {

View File

@ -30,6 +30,7 @@ void UIWidget::initText()
{ {
m_font = g_fonts.getDefaultFont(); m_font = g_fonts.getDefaultFont();
m_textAlign = Fw::AlignCenter; m_textAlign = Fw::AlignCenter;
m_textCoordsBuffer.enableHardwareCaching();
} }
void UIWidget::parseTextStyle(const OTMLNodePtr& styleNode) void UIWidget::parseTextStyle(const OTMLNodePtr& styleNode)
@ -51,36 +52,16 @@ void UIWidget::drawText(const Rect& screenCoords)
if(m_text.length() == 0 || m_color.aF() == 0.0f) if(m_text.length() == 0 || m_color.aF() == 0.0f)
return; return;
#if 0 if(screenCoords != m_textCachedScreenCoords || m_textMustRecache) {
//TODO: creating framebuffers on the fly was slowing down the render
// we should use vertex arrys instead of this method
Size boxSize = screenCoords.size();
if(boxSize != m_textCachedBoxSize || m_textMustRecache) {
if(!m_textFramebuffer)
m_textFramebuffer = FrameBufferPtr(new FrameBuffer(boxSize));
else
m_textFramebuffer->resize(boxSize);
m_textFramebuffer->bind();
Rect virtualTextRect(0, 0, boxSize);
virtualTextRect.translate(m_textOffset);
g_painter.saveAndResetState();
g_painter.setCompositionMode(Painter::CompositionMode_DestBlending);
m_font->renderText(m_text, virtualTextRect, m_textAlign, Color::white);
g_painter.restoreSavedState();
m_textFramebuffer->release();
m_textMustRecache = false; m_textMustRecache = false;
m_textCachedBoxSize = boxSize; m_textCachedScreenCoords = screenCoords;
m_textCoordsBuffer.clear();
m_font->calculateDrawTextCoords(m_textCoordsBuffer, m_text, screenCoords, m_textAlign);
} }
g_painter.setColor(m_color); g_painter.setColor(m_color);
m_textFramebuffer->draw(screenCoords); g_painter.drawTextureCoords(m_textCoordsBuffer, m_font->getTexture());
#else
Rect textRect = screenCoords;
textRect.translate(m_textOffset);
m_font->renderText(m_text, textRect, m_textAlign, m_color);
#endif
} }
void UIWidget::onTextChange(const std::string& text, const std::string& oldText) void UIWidget::onTextChange(const std::string& text, const std::string& oldText)

View File

@ -40,7 +40,8 @@ void AnimatedText::draw(const Point& dest, const Rect& visibleRect)
if(visibleRect.contains(rect)) { if(visibleRect.contains(rect)) {
//TODO: cache into a framebuffer //TODO: cache into a framebuffer
m_font->renderText(m_text, rect, Fw::AlignLeft, m_color); g_painter.setColor(m_color);
m_font->drawText(m_text, rect, Fw::AlignLeft);
} }
} }

View File

@ -232,7 +232,7 @@ void Creature::drawInformation(const Point& point, bool useGray, const Rect& par
g_painter.drawFilledRect(healthRect); g_painter.drawFilledRect(healthRect);
if(m_informationFont) if(m_informationFont)
m_informationFont->renderText(m_name, textRect, Fw::AlignTopCenter, fillColor); m_informationFont->drawText(m_name, textRect, Fw::AlignTopCenter);
if(m_skull != Otc::SkullNone && m_skullTexture) { if(m_skull != Otc::SkullNone && m_skullTexture) {
g_painter.setColor(Color::white); g_painter.setColor(Color::white);

View File

@ -40,7 +40,8 @@ void StaticText::draw(const Point& dest, const Rect& parentRect)
// draw only if the real center is not too far from the parent center, or its a yell // draw only if the real center is not too far from the parent center, or its a yell
if((boundRect.center() - rect.center()).length() < parentRect.width() / 15 || isYell()) { if((boundRect.center() - rect.center()).length() < parentRect.width() / 15 || isYell()) {
//TODO: cache into a framebuffer //TODO: cache into a framebuffer
m_font->renderText(m_text, boundRect, Fw::AlignCenter, m_color); g_painter.setColor(m_color);
m_font->drawText(m_text, boundRect, Fw::AlignCenter);
} }
} }

View File

@ -42,7 +42,8 @@ void UIItem::draw()
if(m_font && m_item->isStackable() && m_item->getCount() > 1) { if(m_font && m_item->isStackable() && m_item->getCount() > 1) {
std::string count = Fw::tostring(m_item->getCount()); std::string count = Fw::tostring(m_item->getCount());
m_font->renderText(count, Rect(m_rect.topLeft(), m_rect.bottomRight() - Point(3, 0)), Fw::AlignBottomRight, Color(231, 231, 231)); g_painter.setColor(Color(231, 231, 231));
m_font->drawText(count, Rect(m_rect.topLeft(), m_rect.bottomRight() - Point(3, 0)), Fw::AlignBottomRight);
} }
//m_font->renderText(Fw::unsafeCast<std::string>(m_item->getId()), m_rect); //m_font->renderText(Fw::unsafeCast<std::string>(m_item->getId()), m_rect);