diff --git a/src/framework/graphics/coordsbuffer.cpp b/src/framework/graphics/coordsbuffer.cpp index df92a3b7..e6dff913 100644 --- a/src/framework/graphics/coordsbuffer.cpp +++ b/src/framework/graphics/coordsbuffer.cpp @@ -86,6 +86,10 @@ void CoordsBuffer::addRepeatedRects(const Rect& dest, const Rect& src) void CoordsBuffer::enableHardwareCaching(HardwareBuffer::UsagePattern usagePattern) { +#ifndef OPENGL_ES2 + if(!GL_ARB_vertex_buffer_object) + return; +#endif m_hardwareCacheMode = usagePattern; m_hardwareCaching = true; m_hardwareCached = false; diff --git a/src/framework/graphics/framebuffer.cpp b/src/framework/graphics/framebuffer.cpp index 5d1dad19..43e81681 100644 --- a/src/framework/graphics/framebuffer.cpp +++ b/src/framework/graphics/framebuffer.cpp @@ -25,30 +25,52 @@ #include "texture.h" uint FrameBuffer::boundFbo = 0; +std::vector auxBuffers; FrameBuffer::FrameBuffer() { m_clearColor = Color::alpha; - - glGenFramebuffers(1, &m_fbo); - if(!m_fbo) - logFatal("Unable to create framebuffer object"); + internalCreate(); } FrameBuffer::FrameBuffer(const Size& size) { m_clearColor = Color::alpha; - - glGenFramebuffers(1, &m_fbo); - if(!m_fbo) - logFatal("Unable to create framebuffer object"); - + internalCreate(); 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;igetSize() == size) return; - internalBind(); m_texture = TexturePtr(new Texture(size.width(), size.height(), 4)); m_texture->setSmooth(true); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture->getId(), 0); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if(status != GL_FRAMEBUFFER_COMPLETE) - logFatal("Unable to setup framebuffer object"); - internalRelease(); + if(g_graphics.hasFBO()) { + internalBind(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture->getId(), 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if(status != GL_FRAMEBUFFER_COMPLETE) + logFatal("Unable to setup framebuffer object"); + internalRelease(); + } + } void FrameBuffer::bind(bool clear) @@ -115,7 +141,15 @@ void FrameBuffer::internalBind() if(boundFbo == m_fbo) return; 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; boundFbo = m_fbo; } @@ -123,6 +157,18 @@ void FrameBuffer::internalBind() void FrameBuffer::internalRelease() { 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; } diff --git a/src/framework/graphics/framebuffer.h b/src/framework/graphics/framebuffer.h index 321350b3..969dc514 100644 --- a/src/framework/graphics/framebuffer.h +++ b/src/framework/graphics/framebuffer.h @@ -46,6 +46,7 @@ public: const Size& getSize() { return m_texture->getSize(); } private: + void internalCreate(); void internalBind(); void internalRelease(); diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp index 35951227..5635d771 100644 --- a/src/framework/graphics/graphics.cpp +++ b/src/framework/graphics/graphics.cpp @@ -37,9 +37,8 @@ void Graphics::init() logFatal("Unable to init GLEW: ", glewGetErrorString(err)); if(!GLEW_ARB_vertex_program || !GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_program || !GLEW_ARB_fragment_shader || - !GLEW_ARB_framebuffer_object || - !GLEW_ARB_multitexture) - logFatal("Your video driver is not supported"); + !GLEW_ARB_texture_non_power_of_two || !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."); #endif glEnable(GL_BLEND); @@ -59,11 +58,13 @@ void Graphics::terminate() m_emptyTexture.reset(); } -bool Graphics::isExtensionSupported(const char *extension) +bool Graphics::hasFBO() { - std::string extensionsString = (const char*)glGetString(GL_EXTENSIONS); - auto extensions = Fw::split(extensionsString); - return std::find(extensions.begin(), extensions.end(), extension) != extensions.end(); +#ifndef OPENGL_ES2 + return GLEW_ARB_framebuffer_object; +#else + return true; +#endif } void Graphics::resize(const Size& size) diff --git a/src/framework/graphics/graphics.h b/src/framework/graphics/graphics.h index 122588df..228b338d 100644 --- a/src/framework/graphics/graphics.h +++ b/src/framework/graphics/graphics.h @@ -32,7 +32,7 @@ public: void init(); void terminate(); - bool isExtensionSupported(const char *extension); + bool hasFBO(); void resize(const Size& size); void beginRender();