Cache the bound VBO/index buffer in glstate.

Though, the index buffer is actually part of VAO state (unlike VBOs...),
so that might change when we implement VAOs.
This commit is contained in:
Unknown W. Brackets 2015-01-11 16:52:37 -08:00
parent 84ed01df53
commit 7a5e182fd1
3 changed files with 44 additions and 32 deletions

View File

@ -75,6 +75,9 @@ void OpenGLState::Restore() {
logicOp.restore(); count++;
#endif
arrayBuffer.restore(); count++;
elementArrayBuffer.restore(); count++;
if (count != state_count) {
FLOG("OpenGLState::Restore is missing some states");
}

View File

@ -109,7 +109,7 @@ private:
public: \
SavedState1_##func() : p1(p1def) { \
OpenGLState::state_count++; \
}; \
} \
void set(p1type newp1) { \
if(newp1 != p1) { \
p1 = newp1; \
@ -128,7 +128,7 @@ private:
public: \
SavedState2_##func() : p1(p1def), p2(p2def) { \
OpenGLState::state_count++; \
}; \
} \
inline void set(p1type newp1, p2type newp2) { \
if(newp1 != p1 || newp2 != p2) { \
p1 = newp1; \
@ -141,27 +141,7 @@ private:
} \
}
#define STATE2_4(func, p1type, p2type, p1def, p2def, p3def, p4def) \
class SavedState2_##func { \
p1type p1; \
p2type p2; \
public: \
SavedState2_##func() : p1(p1def), p2(p2def) { \
OpenGLState::state_count++; \
}; \
inline void set(p1type newp1, p2type newp2) { \
if(newp1 != p1 || newp2 != p2) { \
p1 = newp1; \
p2 = newp2; \
func(p1, p2, p3def, p4def); \
} \
} \
inline void restore() { \
func(p1, p2, p3def, p4def); \
} \
}
#define STATE3(func, p1type, p2type, p3type, p1def, p2def, p3def) \
#define STATE3(func, p1type, p2type, p3type, p1def, p2def, p3def) \
class SavedState3_##func { \
p1type p1; \
p2type p2; \
@ -169,7 +149,7 @@ private:
public: \
SavedState3_##func() : p1(p1def), p2(p2def), p3(p3def) { \
OpenGLState::state_count++; \
}; \
} \
inline void set(p1type newp1, p2type newp2, p3type newp3) { \
if(newp1 != p1 || newp2 != p2 || newp3 != p3) { \
p1 = newp1; \
@ -192,7 +172,7 @@ private:
public: \
SavedState4_##func() : p1(p1def), p2(p2def), p3(p3def), p4(p4def) { \
OpenGLState::state_count++; \
}; \
} \
inline void set(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \
if(newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \
p1 = newp1; \
@ -214,7 +194,7 @@ private:
SavedState4_##func() { \
for (int i = 0; i < 4; i++) {p[i] = def;} \
OpenGLState::state_count++; \
}; \
} \
inline void set(const float v[4]) { \
if(memcmp(p,v,sizeof(float)*4)) { \
memcpy(p,v,sizeof(float)*4); \
@ -226,6 +206,28 @@ private:
} \
}
#define STATEBIND(func, target) \
class SavedBind_##func_##target { \
GLuint val_; \
public: \
SavedBind_##func_##target() { \
val_ = 0; \
OpenGLState::state_count++; \
} \
inline void bind(GLuint val) { \
if (val_ != val) { \
func(target, val); \
val_ = val; \
} \
} \
inline void unbind() { \
bind(0); \
} \
inline void restore() { \
func(target, val_); \
} \
}
bool initialized;
public:
@ -284,6 +286,9 @@ public:
STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc;
STATE1(glStencilMask, GLuint, 0xFF) stencilMask;
STATEBIND(glBindBuffer, GL_ARRAY_BUFFER) arrayBuffer;
STATEBIND(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER) elementArrayBuffer;
// Only works on Win32, all other platforms are "force-vsync"
void SetVSyncInterval(int interval); // one of the above VSYNC, or a higher number for multi-frame waits (could be useful for 30hz games)
};

View File

@ -142,13 +142,13 @@ public:
}
void SetData(const uint8_t *data, size_t size) override {
glBindBuffer(target_, buffer_);
Bind();
glBufferData(target_, size, data, usage_);
knownSize_ = size;
}
void SubData(const uint8_t *data, size_t offset, size_t size) override {
glBindBuffer(target_, buffer_);
Bind();
if (size > knownSize_) {
// Allocate the buffer.
glBufferData(target_, size + offset, NULL, usage_);
@ -157,7 +157,11 @@ public:
glBufferSubData(target_, offset, size, data);
}
void Bind() {
glBindBuffer(target_, buffer_);
if (target_ == GL_ARRAY_BUFFER) {
glstate.arrayBuffer.bind(buffer_);
} else {
glstate.elementArrayBuffer.bind(buffer_);
}
}
void GLLost() override {
@ -712,7 +716,7 @@ void Thin3DGLContext::Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DV
pipe->Unapply();
fmt->Unapply();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glstate.arrayBuffer.unbind();
}
void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) {
@ -731,8 +735,8 @@ void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline,
pipe->Unapply();
fmt->Unapply();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glstate.arrayBuffer.unbind();
glstate.elementArrayBuffer.unbind();
}
void Thin3DGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) {