support for OpenGL 2.0

* use OpenGL 2.0 auxiliary buffers when FBO is not supported, thus this means that OpenGL 3 is not a requirement anymore, so otclient might work in older video cards
* map zooming will never work well with Opengl 2.0 because of glCopyTexSubImage2D limitation
This commit is contained in:
Eduardo Bart 2012-03-20 19:26:07 -03:00
parent 5c35938a92
commit 01d5fad315
5 changed files with 78 additions and 26 deletions

View File

@ -86,6 +86,10 @@ void CoordsBuffer::addRepeatedRects(const Rect& dest, const Rect& src)
void CoordsBuffer::enableHardwareCaching(HardwareBuffer::UsagePattern usagePattern) void CoordsBuffer::enableHardwareCaching(HardwareBuffer::UsagePattern usagePattern)
{ {
#ifndef OPENGL_ES2
if(!GL_ARB_vertex_buffer_object)
return;
#endif
m_hardwareCacheMode = usagePattern; m_hardwareCacheMode = usagePattern;
m_hardwareCaching = true; m_hardwareCaching = true;
m_hardwareCached = false; m_hardwareCached = false;

View File

@ -25,30 +25,52 @@
#include "texture.h" #include "texture.h"
uint FrameBuffer::boundFbo = 0; uint FrameBuffer::boundFbo = 0;
std::vector<bool> auxBuffers;
FrameBuffer::FrameBuffer() FrameBuffer::FrameBuffer()
{ {
m_clearColor = Color::alpha; m_clearColor = Color::alpha;
internalCreate();
glGenFramebuffers(1, &m_fbo);
if(!m_fbo)
logFatal("Unable to create framebuffer object");
} }
FrameBuffer::FrameBuffer(const Size& size) FrameBuffer::FrameBuffer(const Size& size)
{ {
m_clearColor = Color::alpha; m_clearColor = Color::alpha;
internalCreate();
glGenFramebuffers(1, &m_fbo);
if(!m_fbo)
logFatal("Unable to create framebuffer object");
resize(size); resize(size);
} }
void FrameBuffer::internalCreate()
{
if(g_graphics.hasFBO()) {
glGenFramebuffers(1, &m_fbo);
if(!m_fbo)
logFatal("Unable to create framebuffer object");
} else { // use auxiliar buffers when FBOs are not supported
m_fbo = 0;
if(auxBuffers.size() == 0) {
int maxAuxs;
glGetIntegerv(GL_AUX_BUFFERS, &maxAuxs);
auxBuffers.resize(maxAuxs+1, false);
}
for(uint i=1;i<auxBuffers.size();++i) {
if(auxBuffers[i] == false) {
m_fbo = i;
auxBuffers[i] = true;
}
}
if(!m_fbo)
logFatal("There is no available auxiliar buffer for a new framebuffer");
}
}
FrameBuffer::~FrameBuffer() FrameBuffer::~FrameBuffer()
{ {
glDeleteFramebuffers(1, &m_fbo); if(g_graphics.hasFBO()) {
glDeleteFramebuffers(1, &m_fbo);
} else {
auxBuffers[m_fbo] = false;
}
} }
void FrameBuffer::resize(const Size& size) void FrameBuffer::resize(const Size& size)
@ -59,15 +81,19 @@ void FrameBuffer::resize(const Size& size)
if(m_texture && m_texture->getSize() == size) if(m_texture && m_texture->getSize() == size)
return; return;
internalBind();
m_texture = TexturePtr(new Texture(size.width(), size.height(), 4)); m_texture = TexturePtr(new Texture(size.width(), size.height(), 4));
m_texture->setSmooth(true); m_texture->setSmooth(true);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture->getId(), 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(g_graphics.hasFBO()) {
if(status != GL_FRAMEBUFFER_COMPLETE) internalBind();
logFatal("Unable to setup framebuffer object"); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture->getId(), 0);
internalRelease();
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
logFatal("Unable to setup framebuffer object");
internalRelease();
}
} }
void FrameBuffer::bind(bool clear) void FrameBuffer::bind(bool clear)
@ -115,7 +141,15 @@ void FrameBuffer::internalBind()
if(boundFbo == m_fbo) if(boundFbo == m_fbo)
return; return;
assert(boundFbo != m_fbo); assert(boundFbo != m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
if(g_graphics.hasFBO()) {
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
} else {
int buffer = GL_AUX0 + m_fbo - 1;
glDrawBuffer(buffer);
glReadBuffer(buffer);
}
m_prevBoundFbo = boundFbo; m_prevBoundFbo = boundFbo;
boundFbo = m_fbo; boundFbo = m_fbo;
} }
@ -123,6 +157,18 @@ void FrameBuffer::internalBind()
void FrameBuffer::internalRelease() void FrameBuffer::internalRelease()
{ {
assert(boundFbo == m_fbo); assert(boundFbo == m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_prevBoundFbo); if(g_graphics.hasFBO()) {
glBindFramebuffer(GL_FRAMEBUFFER, m_prevBoundFbo);
} else {
m_texture->bind();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_texture->getWidth(), m_texture->getHeight());
int buffer = GL_BACK;
if(m_prevBoundFbo != 0)
buffer = GL_AUX0 + m_fbo - 1;
glDrawBuffer(buffer);
glReadBuffer(buffer);
}
boundFbo = m_prevBoundFbo; boundFbo = m_prevBoundFbo;
} }

View File

@ -46,6 +46,7 @@ public:
const Size& getSize() { return m_texture->getSize(); } const Size& getSize() { return m_texture->getSize(); }
private: private:
void internalCreate();
void internalBind(); void internalBind();
void internalRelease(); void internalRelease();

View File

@ -37,9 +37,8 @@ void Graphics::init()
logFatal("Unable to init GLEW: ", glewGetErrorString(err)); logFatal("Unable to init GLEW: ", glewGetErrorString(err));
if(!GLEW_ARB_vertex_program || !GLEW_ARB_vertex_shader || if(!GLEW_ARB_vertex_program || !GLEW_ARB_vertex_shader ||
!GLEW_ARB_fragment_program || !GLEW_ARB_fragment_shader || !GLEW_ARB_fragment_program || !GLEW_ARB_fragment_shader ||
!GLEW_ARB_framebuffer_object || !GLEW_ARB_texture_non_power_of_two || !GLEW_ARB_multitexture)
!GLEW_ARB_multitexture) logFatal("Some OpenGL 2.0 extensions is not supported by your system graphics, please try updating your video drivers or buy a new hardware.");
logFatal("Your video driver is not supported");
#endif #endif
glEnable(GL_BLEND); glEnable(GL_BLEND);
@ -59,11 +58,13 @@ void Graphics::terminate()
m_emptyTexture.reset(); m_emptyTexture.reset();
} }
bool Graphics::isExtensionSupported(const char *extension) bool Graphics::hasFBO()
{ {
std::string extensionsString = (const char*)glGetString(GL_EXTENSIONS); #ifndef OPENGL_ES2
auto extensions = Fw::split(extensionsString); return GLEW_ARB_framebuffer_object;
return std::find(extensions.begin(), extensions.end(), extension) != extensions.end(); #else
return true;
#endif
} }
void Graphics::resize(const Size& size) void Graphics::resize(const Size& size)

View File

@ -32,7 +32,7 @@ public:
void init(); void init();
void terminate(); void terminate();
bool isExtensionSupported(const char *extension); bool hasFBO();
void resize(const Size& size); void resize(const Size& size);
void beginRender(); void beginRender();