backup current work on TextRenderer

This commit is contained in:
Sam Gateau 2014-10-07 23:52:00 -07:00
parent 0d5f81c062
commit dda7c6699e
4 changed files with 404 additions and 3 deletions

View file

@ -197,6 +197,11 @@ static TextRenderer* textRenderer(int mono) {
}
}
void renderTextRenderer(int mono) {
textRenderer(mono)->executeDrawBatch();
textRenderer(mono)->clearDrawBatch();
}
int widthText(float scale, int mono, char const* string) {
return textRenderer(mono)->computeWidth(string) * (scale / 0.10);
}

View file

@ -31,6 +31,8 @@ float widthChar(float scale, int mono, char ch);
void drawText(int x, int y, float scale, float radians, int mono,
char const* string, const float* color);
void renderTextRenderer(int mono);
void drawvec3(int x, int y, float scale, float radians, float thick, int mono, glm::vec3 vec,
float r=1.0, float g=1.0, float b=1.0);

View file

@ -100,12 +100,25 @@ int TextRenderer::draw(int x, int y, const char* str) {
glTexCoord2f(ls, tt);
glVertex2f(left, top);
glEnd();
/*
const int NUM_COORDS_PER_GLYPH = 16;
float vertexBuffer[NUM_COORDS_PER_GLYPH] = { ls, bt, left, bottom, rs, bt, right, bottom, rs, tt, right, top, ls, tt, left, top };
gpu::Buffer::Size offset = sizeof(vertexBuffer)*_numGlyphsBatched;
if ((offset + sizeof(vertexBuffer)) > _glyphsBuffer.getSize()) {
_glyphsBuffer.append(sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer);
} else {
_glyphsBuffer.setSubData(offset, sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer);
}
_numGlyphsBatched++;
*/
x += glyph.width();
}
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
// executeDrawBatch();
// clearDrawBatch();
return maxHeight;
}
@ -131,8 +144,10 @@ TextRenderer::TextRenderer(const Properties& properties) :
_x(IMAGE_SIZE),
_y(IMAGE_SIZE),
_rowHeight(0),
_color(properties.color) {
_color(properties.color),
_glyphsBuffer(),
_numGlyphsBatched(0)
{
_font.setKerning(false);
}
@ -228,9 +243,248 @@ const Glyph& TextRenderer::getGlyph(char c) {
return glyph;
}
void TextRenderer::executeDrawBatch() {
if (_numGlyphsBatched<=0) {
return;
}
glEnable(GL_TEXTURE_2D);
GLuint textureID = 0;
glBindTexture(GL_TEXTURE_2D, textureID);
gpu::backend::syncGPUObject(_glyphsBuffer);
GLuint vbo = _glyphsBuffer.getGLBufferObject();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
const int NUM_POS_COORDS = 2;
const int NUM_TEX_COORDS = 2;
const int VERTEX_STRIDE = (NUM_POS_COORDS + NUM_TEX_COORDS) * sizeof(float);
const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float);
glVertexPointer(2, GL_FLOAT, VERTEX_STRIDE, 0);
glTexCoordPointer(2, GL_FLOAT, VERTEX_STRIDE, (GLvoid*) VERTEX_TEXCOORD_OFFSET );
glDrawArrays(GL_QUADS, 0, _numGlyphsBatched * 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
void TextRenderer::clearDrawBatch() {
_numGlyphsBatched = 0;
}
QHash<TextRenderer::Properties, TextRenderer*> TextRenderer::_instances;
Glyph::Glyph(int textureID, const QPoint& location, const QRect& bounds, int width) :
_textureID(textureID), _location(location), _bounds(bounds), _width(width) {
}
using namespace gpu;
Buffer::Size Buffer::Sysmem::allocateMemory(Byte** dataAllocated, Size size) {
if ( !dataAllocated ) {
qWarning() << "Buffer::Sysmem::allocateMemory() : Must have a valid dataAllocated pointer.";
return NOT_ALLOCATED;
}
// Try to allocate if needed
Size newSize = 0;
if (size > 0) {
// Try allocating as much as the required size + one block of memory
newSize = size;
(*dataAllocated) = new Byte[newSize];
// Failed?
if (!(*dataAllocated)) {
qWarning() << "Buffer::Sysmem::allocate() : Can't allocate a system memory buffer of " << newSize << "bytes. Fails to create the buffer Sysmem.";
return NOT_ALLOCATED;
}
}
// Return what's actually allocated
return newSize;
}
void Buffer::Sysmem::deallocateMemory(Byte* dataAllocated, Size size) {
if (dataAllocated) {
delete[] dataAllocated;
}
}
Buffer::Sysmem::Sysmem() :
_data(NULL),
_size(0),
_stamp(0)
{
}
Buffer::Sysmem::Sysmem(Size size, const Byte* bytes) :
_data(NULL),
_size(0),
_stamp(0)
{
if (size > 0) {
_size = allocateMemory(&_data, size);
if (_size >= size) {
if (bytes) {
memcpy(_data, bytes, size);
}
}
}
}
Buffer::Sysmem::~Sysmem() {
deallocateMemory( _data, _size );
_data = NULL;
_size = 0;
}
Buffer::Size Buffer::Sysmem::allocate(Size size) {
if (size != _size) {
Byte* newData = 0;
Size newSize = 0;
if (size > 0) {
Size allocated = allocateMemory(&newData, size);
if (allocated == NOT_ALLOCATED) {
// early exit because allocation failed
return 0;
}
newSize = allocated;
}
// Allocation was successful, can delete previous data
deallocateMemory(_data, _size);
_data = newData;
_size = newSize;
_stamp++;
}
return _size;
}
Buffer::Size Buffer::Sysmem::resize(Size size) {
if (size != _size) {
Byte* newData = 0;
Size newSize = 0;
if (size > 0) {
Size allocated = allocateMemory(&newData, size);
if (allocated == NOT_ALLOCATED) {
// early exit because allocation failed
return _size;
}
newSize = allocated;
// Restore back data from old buffer in the new one
if (_data) {
Size copySize = ((newSize < _size)? newSize: _size);
memcpy( newData, _data, copySize);
}
}
// Reallocation was successful, can delete previous data
deallocateMemory(_data, _size);
_data = newData;
_size = newSize;
_stamp++;
}
return _size;
}
Buffer::Size Buffer::Sysmem::setData( Size size, const Byte* bytes ) {
if (allocate(size) == size) {
if (bytes) {
memcpy( _data, bytes, _size );
_stamp++;
}
}
return _size;
}
Buffer::Size Buffer::Sysmem::setSubData( Size offset, Size size, const Byte* bytes) {
if (((offset + size) <= getSize()) && bytes) {
memcpy( _data + offset, bytes, size );
_stamp++;
return size;
}
return 0;
}
Buffer::Size Buffer::Sysmem::append(Size size, const Byte* bytes) {
if (size > 0) {
Size oldSize = getSize();
Size totalSize = oldSize + size;
if (resize(totalSize) == totalSize) {
return setSubData(oldSize, size, bytes);
}
}
return 0;
}
Buffer::Buffer() :
_sysmem(NULL),
_gpuObject(NULL) {
_sysmem = new Sysmem();
}
Buffer::~Buffer() {
if (_sysmem) {
delete _sysmem;
_sysmem = 0;
}
if (_gpuObject) {
delete _gpuObject;
_gpuObject = 0;
}
}
Buffer::Size Buffer::resize(Size size) {
return editSysmem().resize(size);
}
Buffer::Size Buffer::setData(Size size, const Byte* data) {
return editSysmem().setData(size, data);
}
Buffer::Size Buffer::setSubData(Size offset, Size size, const Byte* data) {
return editSysmem().setSubData( offset, size, data);
}
Buffer::Size Buffer::append(Size size, const Byte* data) {
return editSysmem().append( size, data);
}
namespace gpu {
namespace backend {
void syncGPUObject(const Buffer& buffer) {
BufferObject* object = buffer.getGPUObject();
if (object && (object->_stamp == buffer.getSysmem().getStamp())) {
return;
}
// need to have a gpu object?
if (!object) {
object = new BufferObject();
glGenBuffers(1, &object->_buffer);
buffer.setGPUObject(object);
}
// Now let's update the content of the bo with the sysmem version
//if (object->_size < buffer.getSize()) {
glBindBuffer(GL_COPY_WRITE_BUFFER, object->_buffer);
glBufferData(GL_COPY_WRITE_BUFFER, buffer.getSysmem().getSize(), buffer.getSysmem().read(), GL_STATIC_DRAW);
glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
object->_stamp = buffer.getSysmem().getStamp();
object->_size = buffer.getSysmem().getSize();
//}
}
};
};

View file

@ -19,6 +19,8 @@
#include <QImage>
#include <QVector>
#include <assert.h>
#include "InterfaceConfig.h"
// a special "character" that renders as a solid block
@ -35,6 +37,138 @@ const char SOLID_BLOCK_CHAR = 127;
class Glyph;
namespace gpu {
class Buffer;
typedef int Stamp;
namespace backend {
class BufferObject {
public:
Stamp _stamp;
GLuint _buffer;
GLuint _size;
BufferObject() :
_stamp(0),
_buffer(0),
_size(0)
{}
};
void syncGPUObject(const Buffer& buffer);
};
class Buffer {
public:
typedef unsigned char Byte;
typedef unsigned int Size;
static const Size MIN_ALLOCATION_BLOCK_SIZE = 256;
static const Size NOT_ALLOCATED = -1;
Buffer();
Buffer(const Buffer& buf );
~Buffer();
// The size in bytes of data stored in the buffer
inline Size getSize() const { return getSysmem().getSize(); }
inline const Byte* getData() const { return getSysmem().read(); }
// Resize the buffer
// Keep previous data [0 to min(pSize, mSize)]
Size resize(Size pSize);
// Assign data bytes and size (allocate for size, then copy bytes if exists)
Size setData(Size size, const Byte* data);
// Assign data bytes and size (allocate for size, then copy bytes if exists)
Size setSubData(Size offset, Size size, const Byte* data);
// Append new data at the end of the current buffer
// do a resize( size + getSIze) and copy the new data
// \return the number of bytes copied
Size append(Size size, const Byte* data);
// this is a temporary hack so the current rendering code can access the underneath gl Buffer Object
// TODO: remove asap, when the backend is doing more of the gl features
inline GLuint getGLBufferObject() const { backend::syncGPUObject(*this); return getGPUObject()->_buffer; }
protected:
// Sysmem is the underneath cache for the data in ram.
class Sysmem {
public:
Sysmem();
Sysmem(Size size , const Byte* bytes);
~Sysmem();
Size getSize() const { return _size; }
// Allocate the byte array
// \param pSize The nb of bytes to allocate, if already exist, content is lost.
// \return The nb of bytes allocated, nothing if allready the appropriate size.
Size allocate(Size pSize);
// Resize the byte array
// Keep previous data [0 to min(pSize, mSize)]
Size resize(Size pSize);
// Assign data bytes and size (allocate for size, then copy bytes if exists)
Size setData( Size size, const Byte* bytes );
// Update Sub data,
// doesn't allocate and only copy size * bytes at the offset location
// only if all fits in the existing allocated buffer
Size setSubData( Size offset, Size size, const Byte* bytes);
// Append new data at the end of the current buffer
// do a resize( size + getSIze) and copy the new data
// \return the number of bytes copied
Size append(Size size, const Byte* data);
// Access the byte array.
// The edit version allow to map data.
inline const Byte* read() const { return _data; }
inline Byte* edit() { _stamp++; return _data; }
template< typename T >
const T* read() const { return reinterpret_cast< T* > ( _data ); }
template< typename T >
T* edit() const { _stamp++; return reinterpret_cast< T* > ( _data ); }
// Access the current version of the sysmem, used to compare if copies are in sync
inline Stamp getStamp() const { return _stamp; }
static Size allocateMemory(Byte** memAllocated, Size size);
static void deallocateMemory(Byte* memDeallocated, Size size);
private:
Sysmem(const Sysmem& sysmem) {}
Sysmem &operator=(const Sysmem &other) {return *this;}
Byte* _data;
Size _size;
Stamp _stamp;
};
Sysmem* _sysmem;
typedef backend::BufferObject GPUObject;
mutable backend::BufferObject* _gpuObject;
inline const Sysmem& getSysmem() const { assert(_sysmem); return (*_sysmem); }
inline Sysmem& editSysmem() { assert(_sysmem); return (*_sysmem); }
inline GPUObject* getGPUObject() const { return _gpuObject; }
inline void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
friend void backend::syncGPUObject(const Buffer& buffer);
};
};
class TextRenderer {
public:
@ -64,6 +198,8 @@ public:
int computeWidth(char ch);
int computeWidth(const char* str);
void executeDrawBatch();
void clearDrawBatch();
private:
TextRenderer(const Properties& properties);
@ -100,6 +236,10 @@ private:
// text color
QColor _color;
// Graphics Buffer containing the current accumulated glyphs to render
gpu::Buffer _glyphsBuffer;
int _numGlyphsBatched;
static QHash<Properties, TextRenderer*> _instances;
};