mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-07-03 06:24:32 +00:00
initial support for static vertex buffers. TileRender uses that now.
This commit is contained in:
parent
e9e81e5ef9
commit
704981dd00
14 changed files with 448 additions and 61 deletions
|
@ -116,6 +116,8 @@ set(BBGE_SRCS
|
|||
TileRender.h
|
||||
Tileset.cpp
|
||||
Tileset.h
|
||||
VertexBuffer.cpp
|
||||
VertexBuffer.h
|
||||
Vector.cpp
|
||||
Vector.h
|
||||
Window.cpp
|
||||
|
|
|
@ -145,7 +145,8 @@ void Core::setup_opengl()
|
|||
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
|
||||
glClearDepth(1.0); // Depth Buffer Setup
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glLoadIdentity();
|
||||
|
||||
setClearColor(clearColor);
|
||||
|
@ -153,6 +154,8 @@ void Core::setup_opengl()
|
|||
frameBuffer.init(-1, -1, true);
|
||||
if(afterEffectManager)
|
||||
afterEffectManager->updateDevice();
|
||||
|
||||
defaultQuadVertexBuf.initQuadVertices(0, 0, 1, 1);
|
||||
}
|
||||
|
||||
void Core::resizeWindow(int w, int h, int full, int bpp, int vsync, int display, int hz)
|
||||
|
@ -276,7 +279,7 @@ static bool checkWritable(const std::string& path, bool warn, bool critical)
|
|||
|
||||
|
||||
Core::Core(const std::string &filesystem, const std::string& extraDataDir, int numRenderLayers, const std::string &appName, int particleSize, std::string userDataSubFolder)
|
||||
: ActionMapper(), StateManager(), appName(appName)
|
||||
: ActionMapper(), StateManager(), appName(appName), defaultQuadVertexBuf(GPUBUF_STATIC | GPUBUF_VERTEXBUF)
|
||||
{
|
||||
window = NULL;
|
||||
sound = NULL;
|
||||
|
@ -1917,6 +1920,8 @@ void Core::shutdown()
|
|||
frameBuffer.unloadDevice();
|
||||
debugLog("OK");
|
||||
|
||||
defaultQuadVertexBuf.dropBuffer();
|
||||
|
||||
debugLog("Shutdown Graphics Library...");
|
||||
shutdownGraphicsLibrary();
|
||||
debugLog("OK");
|
||||
|
|
|
@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "Localization.h"
|
||||
#include "Window.h"
|
||||
#include "TextureMgr.h"
|
||||
|
||||
#include "VertexBuffer.h"
|
||||
#include "DarkLayer.h"
|
||||
|
||||
#include "GameKeys.h"
|
||||
|
@ -413,6 +413,8 @@ public:
|
|||
|
||||
TextureMgr texmgr;
|
||||
|
||||
inline const DynamicGPUBuffer *getDefaultQuadVertexBuffer() const { return &defaultQuadVertexBuf; }
|
||||
|
||||
protected:
|
||||
|
||||
CoreWindow *window;
|
||||
|
@ -490,6 +492,8 @@ protected:
|
|||
virtual void updateActionButtons();
|
||||
void clearActionButtons();
|
||||
|
||||
DynamicGPUBuffer defaultQuadVertexBuf;
|
||||
|
||||
public:
|
||||
// inclusive!
|
||||
inline int getMaxActionStatusIndex() const { return int(actionStatus.size()) - 2; }
|
||||
|
|
|
@ -68,9 +68,19 @@ PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL;
|
|||
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
|
||||
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL;
|
||||
|
||||
// ARB_vertex_buffer_object
|
||||
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
|
||||
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
|
||||
PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
|
||||
PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB = NULL;
|
||||
PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
|
||||
PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
|
||||
PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
|
||||
|
||||
// extern
|
||||
unsigned g_dbg_numRenderCalls = 0;
|
||||
bool g_has_GL_GENERATE_MIPMAP = false;
|
||||
bool g_has_GL_BUFFERS = false;
|
||||
|
||||
|
||||
#define GL_FUNC(ret,fn,params,call,rt) \
|
||||
|
@ -164,6 +174,15 @@ bool lookup_all_glsyms()
|
|||
glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC)SDL_GL_GetProcAddress("glUniform3ivARB");
|
||||
glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC)SDL_GL_GetProcAddress("glUniform4ivARB");
|
||||
|
||||
// VBOs
|
||||
glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)SDL_GL_GetProcAddress("glGenBuffersARB");
|
||||
glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)SDL_GL_GetProcAddress("glDeleteBuffersARB");
|
||||
glBufferDataARB = (PFNGLBUFFERDATAARBPROC)SDL_GL_GetProcAddress("glBufferData");
|
||||
glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)SDL_GL_GetProcAddress("glBufferSubData");
|
||||
glBindBufferARB = (PFNGLBINDBUFFERARBPROC)SDL_GL_GetProcAddress("glBindBufferARB");
|
||||
glMapBufferARB = (PFNGLMAPBUFFERARBPROC)SDL_GL_GetProcAddress("glMapBufferARB");
|
||||
glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)SDL_GL_GetProcAddress("glUnmapBufferARB");
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -217,6 +236,15 @@ void unload_all_glsyms()
|
|||
glUniform2ivARB = NULL;
|
||||
glUniform3ivARB = NULL;
|
||||
glUniform4ivARB = NULL;
|
||||
|
||||
glGenBuffersARB = NULL;
|
||||
glDeleteBuffersARB = NULL;
|
||||
glBufferDataARB = NULL;
|
||||
glBufferSubDataARB = NULL;
|
||||
glBindBufferARB = NULL;
|
||||
glMapBufferARB = NULL;
|
||||
glUnmapBufferARB = NULL;
|
||||
|
||||
}
|
||||
|
||||
#endif // BBGE_BUILD_OPENGL_STATIC
|
||||
|
|
|
@ -26,14 +26,15 @@ GL_FUNC(void,glClear,(GLbitfield a),(a),)
|
|||
GL_FUNC(void,glClearColor,(GLclampf r,GLclampf g,GLclampf b,GLclampf a),(r,g,b,a),)
|
||||
GL_FUNC(void,glColor4f,(GLfloat r,GLfloat g,GLfloat b,GLfloat a),(r,g,b,a),)
|
||||
GL_FUNC(void,glColor4ub,(GLubyte r,GLubyte g,GLubyte b,GLubyte a),(r,g,b,a),)
|
||||
GL_FUNC(void,glColorPointer,(GLint size,GLenum type,GLsizei stride,const GLvoid* pointer),(size,type,stride,pointer),);
|
||||
GL_FUNC(void,glCopyPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type),(x,y,width,height,type),)
|
||||
GL_FUNC(void,glCopyTexImage2D,(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border),(target, level, internalFormat, x, y, width, height, border),)
|
||||
GL_FUNC(void,glCopyTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height),(target, level, xoffset, yoffset, x, y, width, height),)
|
||||
GL_FUNC(void,glDeleteTextures,(GLsizei n, const GLuint *textures),(n,textures),)
|
||||
GL_FUNC(void,glDisable,(GLenum cap),(cap),)
|
||||
GL_FUNC(void,glDisableClientState,(GLenum array),(array),)
|
||||
//GL_FUNC(void,glDrawArrays,(GLenum mode, GLint first, GLsizei count),(mode,first,count),)
|
||||
//GL_FUNC(void,glDrawElements,(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices),(mode,count,type,indices),)
|
||||
GL_FUNC(void,glDrawArrays,(GLenum mode, GLint first, GLsizei count),(mode,first,count),)
|
||||
GL_FUNC(void,glDrawElements,(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices),(mode,count,type,indices),)
|
||||
GL_FUNC(void,glEnable,(GLenum cap),(cap),)
|
||||
GL_FUNC(void,glEnableClientState,(GLenum array),(array),)
|
||||
GL_FUNC(void,glFinish,(void),(),)
|
||||
|
@ -70,7 +71,6 @@ GL_FUNC(void,glEnd,(void),(),)
|
|||
GL_FUNC(void,glClearDepth,(GLclampd x),(x),)
|
||||
GL_FUNC(void,glColor3f,(GLfloat r,GLfloat g,GLfloat b),(r,g,b),)
|
||||
//GL_FUNC(void,glDeleteLists,(GLuint list, GLsizei range),(list,range),)
|
||||
GL_FUNC(void,glDrawArrays,(GLenum mode, GLint first, GLsizei count), (mode,first,count),)
|
||||
//GL_FUNC(void,glDrawPixels,(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels),(width,height,format,type,pixels),)
|
||||
//GL_FUNC(GLuint,glGenLists,(GLsizei range),(range),return)
|
||||
//GL_FUNC(void,glNewList,(GLuint list, GLenum mode),(list,mode),)
|
||||
|
|
|
@ -39,7 +39,7 @@ extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
|
|||
extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
|
||||
extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
|
||||
extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB;
|
||||
extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB ;
|
||||
extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB;
|
||||
extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
|
||||
extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
|
||||
extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
|
||||
|
@ -65,6 +65,12 @@ extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT;
|
|||
extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
|
||||
extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT;
|
||||
|
||||
|
||||
extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
|
||||
extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
|
||||
extern PFNGLBUFFERDATAARBPROC glBufferDataARB;
|
||||
extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB;
|
||||
extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
|
||||
extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
|
||||
extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -531,6 +531,11 @@ bool TileData::isCoordinateInside(float cx, float cy, float minsize) const
|
|||
&& cy >= y - hh && cy <= y + hh;
|
||||
}
|
||||
|
||||
TileRepeatData::TileRepeatData()
|
||||
: vertexbuf(GPUBUF_STATIC | GPUBUF_VERTEXBUF)
|
||||
{
|
||||
}
|
||||
|
||||
void TileRepeatData::refresh(const ElementTemplate& et, float scalex, float scaley)
|
||||
{
|
||||
float tw, th;
|
||||
|
@ -555,14 +560,7 @@ void TileRepeatData::refresh(const ElementTemplate& et, float scalex, float scal
|
|||
this->tu2 = tu2;
|
||||
this->tv2 = tv2;
|
||||
|
||||
texcoords[0] = tu1;
|
||||
texcoords[1] = 1.0f-tv1;
|
||||
texcoords[2] = tu2;
|
||||
texcoords[3] = 1.0f-tv1;
|
||||
texcoords[4] = tu2;
|
||||
texcoords[5] = 1.0f-tv2;
|
||||
texcoords[6] = tu1;
|
||||
texcoords[7] = 1.0f-tv2;
|
||||
vertexbuf.initQuadVertices(tu1, tv1, tu2, tv2);
|
||||
}
|
||||
|
||||
TileRepeatData* TileData::setRepeatOn(float texscalex, float texscaley, float offx, float offy)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <vector>
|
||||
#include "Vector.h"
|
||||
#include "EngineEnums.h"
|
||||
#include "VertexBuffer.h"
|
||||
|
||||
// A Tile is a very stripped down RenderObject that bypasses the default
|
||||
// rendering pipeline for efficiency reasons.
|
||||
|
@ -132,8 +133,10 @@ private:
|
|||
|
||||
struct TileRepeatData
|
||||
{
|
||||
TileRepeatData();
|
||||
|
||||
// written via refresh()
|
||||
float texcoords[8];
|
||||
DynamicGPUBuffer vertexbuf;
|
||||
float tu1, tv1, tu2, tv2;
|
||||
|
||||
// set by user
|
||||
|
|
|
@ -41,24 +41,11 @@ static inline const Vector& getTagColor(int tag)
|
|||
|
||||
}
|
||||
|
||||
static const float s_quadVerts[] =
|
||||
{
|
||||
-0.5f, +0.5f,
|
||||
+0.5f, +0.5f,
|
||||
+0.5f, -0.5f,
|
||||
-0.5f, -0.5f,
|
||||
};
|
||||
|
||||
void TileRender::onRender(const RenderState& rs) const
|
||||
{
|
||||
if(storage.tiles.empty())
|
||||
return;
|
||||
|
||||
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, s_quadVerts);
|
||||
|
||||
RenderState rx(rs);
|
||||
|
||||
// prepare. get parallax scroll factors
|
||||
|
@ -78,7 +65,7 @@ void TileRender::onRender(const RenderState& rs) const
|
|||
const bool renderExtras = renderBorders || RenderObject::renderCollisionShape;
|
||||
const TileEffectData *prevEff = ((TileEffectData*)NULL)+1; // initial value is different from anything else
|
||||
const RenderGrid *grid = NULL;
|
||||
const float *lastTexcoordBuf = NULL;
|
||||
const DynamicGPUBuffer *lastVertexBuf = NULL;
|
||||
|
||||
for(size_t i = 0; i < storage.tiles.size(); ++i)
|
||||
{
|
||||
|
@ -181,16 +168,16 @@ void TileRender::onRender(const RenderState& rs) const
|
|||
|
||||
if(!grid)
|
||||
{
|
||||
const float *tcbuf = (tile.flags & TILEFLAG_REPEAT)
|
||||
? &tile.rep->texcoords[0]
|
||||
: tile.et->texcoordQuadPtr;
|
||||
assert(tcbuf);
|
||||
if(lastTexcoordBuf != tcbuf)
|
||||
const DynamicGPUBuffer *vb = !(tile.flags & TILEFLAG_REPEAT)
|
||||
? tile.et->vertexbuf
|
||||
: &tile.rep->vertexbuf;
|
||||
assert(vb);
|
||||
if(vb != lastVertexBuf)
|
||||
{
|
||||
lastTexcoordBuf = tcbuf;
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, tcbuf);
|
||||
lastVertexBuf = vb;
|
||||
vb->apply();
|
||||
}
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
vb->DrawArrays(GL_TRIANGLE_FAN, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -248,7 +235,7 @@ void TileRender::onRender(const RenderState& rs) const
|
|||
glPopMatrix();
|
||||
}
|
||||
|
||||
glPopClientAttrib();
|
||||
glBindBufferARB(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
RenderObject::lastTextureApplied = lastTexId;
|
||||
RenderObject::lastTextureRepeat = !!lastTexRepeat;
|
||||
|
|
|
@ -18,8 +18,6 @@ public:
|
|||
virtual void onUpdate(float dt) OVERRIDE;
|
||||
|
||||
bool renderBorders;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -169,13 +169,12 @@ const ElementTemplate* Tileset::getAdjacent(size_t idx, int direction, bool wrap
|
|||
return et;
|
||||
}
|
||||
|
||||
static const float s_defaultTexcoordBuf[] =
|
||||
|
||||
ElementTemplate::~ElementTemplate()
|
||||
{
|
||||
0, 1,
|
||||
1, 1,
|
||||
1, 0,
|
||||
0, 0
|
||||
};
|
||||
if(ownsVertexbuf)
|
||||
delete const_cast<DynamicGPUBuffer*>(vertexbuf);
|
||||
}
|
||||
|
||||
void ElementTemplate::finalize()
|
||||
{
|
||||
|
@ -197,18 +196,19 @@ void ElementTemplate::finalize()
|
|||
}
|
||||
|
||||
if(tu1 == 0 && tv1 == 0 && tu2 == 1 && tv2 == 1)
|
||||
texcoordQuadPtr = s_defaultTexcoordBuf;
|
||||
{
|
||||
// this avoids buffer switches later on
|
||||
vertexbuf = core->getDefaultQuadVertexBuffer();
|
||||
ownsVertexbuf = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
texcoordQuadPtr = &texcoordQuadBuffer[0];
|
||||
texcoordQuadBuffer[0] = tu1;
|
||||
texcoordQuadBuffer[1] = 1.0f-tv1;
|
||||
texcoordQuadBuffer[2] = tu2;
|
||||
texcoordQuadBuffer[3] = 1.0f-tv1;
|
||||
texcoordQuadBuffer[4] = tu2;
|
||||
texcoordQuadBuffer[5] = 1.0f-tv2;
|
||||
texcoordQuadBuffer[6] = tu1;
|
||||
texcoordQuadBuffer[7] = 1.0f-tv2;
|
||||
DynamicGPUBuffer *vb = ownsVertexbuf
|
||||
? const_cast<DynamicGPUBuffer*>(vertexbuf)
|
||||
: new DynamicGPUBuffer(GPUBUF_STATIC | GPUBUF_VERTEXBUF);
|
||||
vb->initQuadVertices(tu1, tv1, tu2, tv2);
|
||||
vertexbuf = vb;
|
||||
ownsVertexbuf = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
#include "Vector.h"
|
||||
#include <vector>
|
||||
#include "Texture.h"
|
||||
#include "VertexBuffer.h"
|
||||
|
||||
class ElementTemplate
|
||||
{
|
||||
public:
|
||||
ElementTemplate() { w=0; h=0; idx=-1; tu1=tv1=0; tu2=tv2=1; texcoordQuadPtr=NULL; }
|
||||
ElementTemplate() { w=0; h=0; idx=-1; tu1=tv1=0; tu2=tv2=1; vertexbuf = NULL; ownsVertexbuf = false; }
|
||||
~ElementTemplate();
|
||||
inline bool operator<(const ElementTemplate& o) const { return idx < o.idx; }
|
||||
|
||||
void finalize(); // call after settings params
|
||||
|
@ -16,8 +18,8 @@ public:
|
|||
// lazily assigned when tex is loaded
|
||||
CountedPtr<Texture> tex; // NULL if failed to load or not yet loaded
|
||||
float w,h; // custom size if used, otherwise texture size
|
||||
const float *texcoordQuadPtr;
|
||||
float texcoordQuadBuffer[8];
|
||||
const DynamicGPUBuffer * vertexbuf; // never NULL
|
||||
bool ownsVertexbuf;
|
||||
|
||||
// fixed
|
||||
float tu1, tu2, tv1, tv2; // texcoords
|
||||
|
@ -26,6 +28,7 @@ public:
|
|||
|
||||
private:
|
||||
ElementTemplate(const ElementTemplate&); // no copy
|
||||
ElementTemplate& operator=(const ElementTemplate&); // no assign
|
||||
};
|
||||
|
||||
class Tileset
|
||||
|
|
262
BBGE/VertexBuffer.cpp
Normal file
262
BBGE/VertexBuffer.cpp
Normal file
|
@ -0,0 +1,262 @@
|
|||
#include "VertexBuffer.h"
|
||||
#include "RenderBase.h"
|
||||
#include "Base.h"
|
||||
#include <assert.h>
|
||||
|
||||
bool DynamicGPUBuffer::_HasARB = false;
|
||||
|
||||
static unsigned s_lastVertexBuffer = 0;
|
||||
static unsigned s_lastIndexBuffer = 0;
|
||||
static void *s_lastHostPtr = NULL;
|
||||
static BufDataType s_lastDataType = BufDataType(-1);
|
||||
static unsigned s_lastState = 0; // StateBits
|
||||
|
||||
enum StateBits
|
||||
{
|
||||
SB_COLOR_FROM_BUFFER = 0x01
|
||||
};
|
||||
|
||||
static unsigned toGlUsage(unsigned usage)
|
||||
{
|
||||
if(usage & GPUBUF_STATIC)
|
||||
return GL_STATIC_DRAW_ARB;
|
||||
return GL_DYNAMIC_DRAW;
|
||||
}
|
||||
|
||||
void DynamicGPUBuffer::StaticInit()
|
||||
{
|
||||
_HasARB = glGenBuffersARB && glDeleteBuffersARB
|
||||
&& glBufferDataARB && glBufferSubDataARB
|
||||
&& glBindBufferARB && glMapBufferARB && glUnmapBufferARB;
|
||||
}
|
||||
|
||||
DynamicGPUBuffer::DynamicGPUBuffer(unsigned usage)
|
||||
: _bufid(0)
|
||||
, _binding((usage & GPUBUF_INDEXBUF) ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB)
|
||||
, _size(0)
|
||||
, _cap(0)
|
||||
, _h_data(NULL)
|
||||
, _d_map(NULL)
|
||||
, _usage(toGlUsage(usage))
|
||||
, _datatype(BufDataType(-1))
|
||||
{
|
||||
}
|
||||
|
||||
DynamicGPUBuffer::~DynamicGPUBuffer()
|
||||
{
|
||||
dropBuffer();
|
||||
}
|
||||
|
||||
void* DynamicGPUBuffer::_allocBytes(size_t bytes)
|
||||
{
|
||||
if(s_lastHostPtr == _h_data)
|
||||
s_lastHostPtr = NULL;
|
||||
|
||||
void *p = realloc(_h_data, bytes);
|
||||
if(p)
|
||||
{
|
||||
_cap = bytes;
|
||||
_h_data = p;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void* DynamicGPUBuffer::_ensureBytes(size_t bytes)
|
||||
{
|
||||
if(bytes < _cap)
|
||||
return _h_data;
|
||||
|
||||
size_t newsize = 2 * _size;
|
||||
if(newsize < bytes)
|
||||
newsize += bytes;
|
||||
|
||||
return _allocBytes(newsize);
|
||||
}
|
||||
|
||||
void* DynamicGPUBuffer::beginWrite(BufDataType type, size_t newsize, unsigned access)
|
||||
{
|
||||
_size = newsize;
|
||||
_datatype = type;
|
||||
|
||||
if(_HasARB)
|
||||
{
|
||||
glBindBufferARB(_binding, _ensureDBuf());
|
||||
glBufferDataARB(_binding, newsize, NULL, _usage); // orphan buffer
|
||||
if(!(access & GPUACCESS_HOSTCOPY))
|
||||
{
|
||||
void *p = glMapBufferARB(_binding, GL_WRITE_ONLY_ARB);
|
||||
_d_map = p;
|
||||
if(p)
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return _ensureBytes(newsize);
|
||||
}
|
||||
|
||||
bool DynamicGPUBuffer::commitWrite()
|
||||
{
|
||||
if(_HasARB)
|
||||
{
|
||||
if(_d_map)
|
||||
{
|
||||
_d_map = NULL;
|
||||
return glUnmapBufferARB(_binding); // can fail
|
||||
}
|
||||
// otherwise, the prev. call to glMapBufferARB failed (or GPUACCESS_NOMAP was set).
|
||||
// -> didn't map, but wrote to host memory. upload it.
|
||||
assert(_h_data);
|
||||
glBufferSubDataARB(_binding, 0, _size, _h_data);
|
||||
}
|
||||
// else nothing to do
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DynamicGPUBuffer::upload(BufDataType type, const void* data, size_t size)
|
||||
{
|
||||
_datatype = type;
|
||||
|
||||
if(_HasARB)
|
||||
{
|
||||
glBindBufferARB(_binding, _ensureDBuf());
|
||||
glBufferDataARB(_binding, size, data, _usage);
|
||||
}
|
||||
else
|
||||
memcpy(_ensureBytes(size), data, size);
|
||||
}
|
||||
|
||||
static const unsigned s_gltype[] =
|
||||
{
|
||||
GL_SHORT,
|
||||
GL_FLOAT,
|
||||
};
|
||||
|
||||
struct BufPtrConfig
|
||||
{
|
||||
uintptr_t bufidOrPtr;
|
||||
BufDataType datatype;
|
||||
|
||||
};
|
||||
|
||||
void DynamicGPUBuffer::apply(BufDataType usetype) const
|
||||
{
|
||||
if(!usetype)
|
||||
usetype = _datatype;
|
||||
|
||||
void *p;
|
||||
if(_HasARB)
|
||||
{
|
||||
unsigned bufid = this->_bufid;
|
||||
assert(bufid != s_lastVertexBuffer); // check that it's no redundant state change
|
||||
if(bufid == s_lastVertexBuffer && usetype == s_lastDataType)
|
||||
return;
|
||||
p = NULL;
|
||||
s_lastVertexBuffer = bufid;
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufid);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = (void*)this->_h_data;
|
||||
assert(p != s_lastHostPtr); // check that it's no redundant state change
|
||||
if(p == s_lastHostPtr && usetype == s_lastDataType) // don't need to check for datatype since that's const for the buffer with that ptr
|
||||
return;
|
||||
}
|
||||
|
||||
s_lastDataType = usetype;
|
||||
|
||||
assert((ty & 0xf) < Countof(s_gltype));
|
||||
const unsigned gltype = s_gltype[usetype & 0xf];
|
||||
const unsigned scalars = (usetype >> 4) & 0xf;
|
||||
const unsigned stride = (usetype >> 8) & 0xff;
|
||||
const unsigned tcoffset = (usetype >> 16) & 0xff;
|
||||
const unsigned coloroffset = usetype >> 24;
|
||||
|
||||
// vertex and texcoords are always enabled
|
||||
glVertexPointer(scalars, gltype, stride, p);
|
||||
if(tcoffset)
|
||||
glTexCoordPointer(2, gltype, stride, (void*)((uintptr_t)p + tcoffset));
|
||||
|
||||
unsigned wantedstate = 0;
|
||||
if(coloroffset)
|
||||
{
|
||||
wantedstate |= SB_COLOR_FROM_BUFFER;
|
||||
glColorPointer(4, gltype, stride, (void*)((uintptr_t)p + coloroffset));
|
||||
}
|
||||
|
||||
unsigned wrongbits = wantedstate ^ s_lastState;
|
||||
if(wrongbits)
|
||||
{
|
||||
if(wrongbits & SB_COLOR_FROM_BUFFER)
|
||||
{
|
||||
if(wantedstate & SB_COLOR_FROM_BUFFER)
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
else
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
s_lastState = wantedstate;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned DynamicGPUBuffer::_ensureDBuf()
|
||||
{
|
||||
assert(_HasARB);
|
||||
if(!_bufid)
|
||||
glGenBuffersARB(1, &_bufid);
|
||||
return _bufid;
|
||||
}
|
||||
|
||||
void DynamicGPUBuffer::dropBuffer()
|
||||
{
|
||||
if(s_lastHostPtr == _h_data)
|
||||
s_lastHostPtr = NULL;
|
||||
free(_h_data);
|
||||
_h_data = NULL;
|
||||
if(_bufid)
|
||||
{
|
||||
if(s_lastVertexBuffer == _bufid)
|
||||
s_lastVertexBuffer = 0;
|
||||
if(s_lastIndexBuffer == _bufid)
|
||||
s_lastIndexBuffer = 0;
|
||||
|
||||
glDeleteBuffersARB(1, &_bufid);
|
||||
_bufid = 0;
|
||||
}
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
void DynamicGPUBuffer::DrawArrays(unsigned glmode, size_t n, size_t first)
|
||||
{
|
||||
glDrawArrays(glmode, first, n);
|
||||
}
|
||||
|
||||
void DynamicGPUBuffer::drawElements(unsigned glmode, size_t n, size_t first)
|
||||
{
|
||||
assert(_binding == GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
assert(s_gltype[_datatype & 0xf] == GL_SHORT);
|
||||
|
||||
if(s_lastIndexBuffer != _bufid)
|
||||
{
|
||||
s_lastIndexBuffer = _bufid;
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _bufid);
|
||||
}
|
||||
|
||||
glDrawElements(glmode, n, GL_SHORT, NULL);
|
||||
}
|
||||
|
||||
void DynamicGPUBuffer::initQuadVertices(float tu1, float tv1, float tu2, float tv2)
|
||||
{
|
||||
do
|
||||
{
|
||||
float *p = (float*)beginWrite(GPUBUFTYPE_VEC2_TC, (4*4) * sizeof(float), GPUACCESS_DEFAULT);
|
||||
*p++ = -0.5f; *p++ = +0.5f; // xy
|
||||
*p++ = tu1; *p++ = 1.0f-tv1; // uv
|
||||
*p++ = +0.5f; *p++ = +0.5f; // xy
|
||||
*p++ = tu2; *p++ = 1.0f-tv1; // uv
|
||||
*p++ = +0.5f; *p++ = -0.5f; // xy
|
||||
*p++ = tu2; *p++ = 1.0f-tv2; // uv
|
||||
*p++ = -0.5f; *p++ = -0.5f; // xy
|
||||
*p++ = tu1; *p++ = 1.0f-tv2; // uv
|
||||
}
|
||||
while(!commitWrite());
|
||||
}
|
91
BBGE/VertexBuffer.h
Normal file
91
BBGE/VertexBuffer.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
#ifndef BBGE_VERTEXBUFFER_H
|
||||
#define BBGE_VERTEXBUFFER_H
|
||||
|
||||
#include <stdlib.h> // size_t
|
||||
|
||||
enum BufUsage
|
||||
{
|
||||
// usage
|
||||
GPUBUF_DYNAMIC = 0x00,
|
||||
GPUBUF_STATIC = 0x01,
|
||||
// binding point
|
||||
GPUBUF_VERTEXBUF = 0x00,
|
||||
GPUBUF_INDEXBUF = 0x02
|
||||
};
|
||||
|
||||
enum BufDataType
|
||||
{
|
||||
GPUBUFTYPE_NONE = 0,
|
||||
/* ccoossnt --
|
||||
^-- type of each scalar
|
||||
^-- number of coordinate scalars (eg. xyz would be 3)
|
||||
^^-- stride (distance to next vertex), in bytes
|
||||
^^-- offset of texcoords, in bytes, if present
|
||||
^^-- offset of colors, if present */
|
||||
GPUBUFTYPE_U16 = 0x00000010, // densely packed u16, for indexing
|
||||
GPUBUFTYPE_VEC2_TC = 0x00081021, // xyuv xyuv xyuv
|
||||
GPUBUFTYPE_VEC2_TC_RGBA = 0x10082021, // xyuvrgba xyuvrgba xyuvrgba
|
||||
// ccoossnt
|
||||
GPUBUFTYPE_VEC2_TC_RGBA_BUT_NO_COLOR = GPUBUFTYPE_VEC2_TC_RGBA & 0xffffff
|
||||
};
|
||||
|
||||
enum AccessFlags
|
||||
{
|
||||
// Use whatever works. May directly map in GPU memory so that there is no
|
||||
// copy on the host; or if there is a previous copy, it may remain untouched.
|
||||
GPUACCESS_DEFAULT = 0x00,
|
||||
|
||||
// Don't use memory mapping. Prepare buffer on the host and upload it in one go.
|
||||
// The copy remains on the host.
|
||||
GPUACCESS_HOSTCOPY = 0x01
|
||||
};
|
||||
|
||||
|
||||
class DynamicGPUBuffer
|
||||
{
|
||||
friend class BufMapW;
|
||||
public:
|
||||
void StaticInit();
|
||||
DynamicGPUBuffer(unsigned usage);
|
||||
~DynamicGPUBuffer();
|
||||
void dropBuffer();
|
||||
|
||||
size_t size() const { return _size; }
|
||||
|
||||
// beginWrite(), then write exactly newsize bytes, then commit
|
||||
void *beginWrite(BufDataType type, size_t newsize, unsigned access); // AccessFlags
|
||||
bool commitWrite();
|
||||
|
||||
void upload(BufDataType type, const void *data, size_t size);
|
||||
|
||||
static void DrawArrays(unsigned glmode, size_t n, size_t first = 0); // uses last applied buffer for drawing
|
||||
|
||||
// uses own data for indexing and prev. applied buffer for the data to draw
|
||||
void drawElements(unsigned glmode, size_t n, size_t first = 0);
|
||||
|
||||
|
||||
void apply(BufDataType usetype = GPUBUFTYPE_NONE) const;
|
||||
|
||||
// Inteded for use with DrawArrays(4) and GL_TRIANGLE_FAN or GL_QUADS (both work)
|
||||
void initQuadVertices(float tu1, float tu2, float tv1, float tv2);
|
||||
|
||||
private:
|
||||
|
||||
void* _allocBytes(size_t bytes);
|
||||
void* _ensureBytes(size_t bytes);
|
||||
unsigned _ensureDBuf();
|
||||
|
||||
unsigned _bufid;
|
||||
unsigned _binding;
|
||||
size_t _size;
|
||||
size_t _cap;
|
||||
void *_h_data;
|
||||
void *_d_map;
|
||||
const unsigned _usage;
|
||||
BufDataType _datatype;
|
||||
|
||||
static bool _HasARB;
|
||||
};
|
||||
|
||||
|
||||
#endif // BBGE_VERTEXBUFFER_H
|
Loading…
Add table
Add a link
Reference in a new issue