1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-11-25 17:53:47 +00:00
Aquaria/BBGE/FrameBuffer.cpp
2016-05-05 19:57:50 +02:00

340 lines
10 KiB
C++

/*
Copyright (C) 2007, 2010 - Bit-Blot
This file is part of Aquaria.
Aquaria is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "FrameBuffer.h"
#include "Core.h"
//WARNING: FrameBuffer objects have to have reloadDevice/unloadDevice called manually!
#ifdef BBGE_BUILD_FRAMEBUFFER
PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT = NULL;
PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;
PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;
PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;
PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;
PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT = NULL;
PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT = NULL;
PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL;
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL;
PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL;
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL;
PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT = NULL;
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL;
PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL;
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL;
PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL;
#endif
FrameBuffer::FrameBuffer()
{
inited = false;
enabled = false;
w = 0;
h = 0;
g_frameBuffer = 0;
g_depthRenderBuffer = 0;
g_dynamicTextureID = 0;
_w = _h = 0;
}
FrameBuffer::~FrameBuffer()
{
unloadDevice();
}
float FrameBuffer::getWidthP()
{
float px=0;
int sw=core->getWindowWidth();
px = (float)sw/(float)w;
return px;
}
float FrameBuffer::getHeightP()
{
float py=0;
int sh=core->getWindowHeight();
py = (float)sh/(float)h;
return py;
}
bool FrameBuffer::init(int width, int height, bool fitToScreen, GLint filter)
{
// !!! FIXME: check for common GMA GL_RENDERER strings on Linux, too.
#ifdef BBGE_BUILD_MACOSX
std::ostringstream oss;
oss << "Vendor: [" << glGetString(GL_VENDOR) << "] Renderer: [" << glGetString(GL_RENDERER) << "]";
debugLog(oss.str());
std::string renderer = (const char*)glGetString(GL_RENDERER);
if (renderer.find("Intel GMA 950") != std::string::npos)
{
debugLog("Video Card is Intel GMA 950. Disabling FrameBuffer Effects.");
return false;
}
#endif
#ifdef BBGE_BUILD_FRAMEBUFFER
_w = width;
_h = height;
if (width == -1)
width = core->width;
if (height == -1)
height = core->height;
if (fitToScreen)
{
sizePowerOf2Texture(width);
sizePowerOf2Texture(height);
}
_fitToScreen = fitToScreen;
if (width == 0 || height == 0)
return false;
w=width;
h=height;
char *ext = (char*)glGetString( GL_EXTENSIONS );
std::ostringstream os;
os << "Loading EXT_framebuffer_object (" << w << ", " << h << ")";
debugLog(os.str());
if( strstr( ext, "EXT_framebuffer_object" ) == NULL )
{
debugLog("EXT_framebuffer_object extension was not found");
return false;
}
else
{
if (!glIsRenderbufferEXT)
{
glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)SDL_GL_GetProcAddress("glIsRenderbufferEXT");
glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)SDL_GL_GetProcAddress("glBindRenderbufferEXT");
glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)SDL_GL_GetProcAddress("glDeleteRenderbuffersEXT");
glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)SDL_GL_GetProcAddress("glGenRenderbuffersEXT");
glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)SDL_GL_GetProcAddress("glRenderbufferStorageEXT");
glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)SDL_GL_GetProcAddress("glGetRenderbufferParameterivEXT");
glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)SDL_GL_GetProcAddress("glIsFramebufferEXT");
glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)SDL_GL_GetProcAddress("glBindFramebufferEXT");
glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)SDL_GL_GetProcAddress("glGenFramebuffersEXT");
glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)SDL_GL_GetProcAddress("glFramebufferTexture1DEXT");
glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)SDL_GL_GetProcAddress("glFramebufferTexture3DEXT");
glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)SDL_GL_GetProcAddress("glFramebufferRenderbufferEXT");
glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)SDL_GL_GetProcAddress("glGetFramebufferAttachmentParameterivEXT");
glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)SDL_GL_GetProcAddress("glGenerateMipmapEXT");
}
if( !glIsRenderbufferEXT || !glBindRenderbufferEXT || !glDeleteRenderbuffersEXT ||
!glGenRenderbuffersEXT || !glRenderbufferStorageEXT || !glGetRenderbufferParameterivEXT ||
!glIsFramebufferEXT || !glBindFramebufferEXT || !glDeleteFramebuffersEXT ||
!glGenFramebuffersEXT || !glCheckFramebufferStatusEXT || !glFramebufferTexture1DEXT ||
!glFramebufferTexture2DEXT || !glFramebufferTexture3DEXT || !glFramebufferRenderbufferEXT||
!glGetFramebufferAttachmentParameterivEXT || !glGenerateMipmapEXT )
{
debugLog("One or more EXT_framebuffer_object functions were not found");
return false;
}
//
// Create a frame-buffer object and a render-buffer object...
//
glGenFramebuffersEXT( 1, &g_frameBuffer );
glGenRenderbuffersEXT( 1, &g_depthRenderBuffer );
// Initialize the render-buffer for usage as a depth buffer.
// We don't really need this to render things into the frame-buffer object,
// but without it the geometry will not be sorted properly.
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, g_depthRenderBuffer );
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height );
//
// Check for errors...
//
GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
switch( status )
{
case GL_FRAMEBUFFER_COMPLETE_EXT:
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
debugLog("GL_FRAMEBUFFER_UNSUPPORTED_EXT!");
return false;
break;
default:
return false;
}
glGenTextures( 1, &g_dynamicTextureID );
glBindTexture( GL_TEXTURE_2D, g_dynamicTextureID );
// GL_LINEAR
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB,
width, height,
0, GL_BGR, GL_UNSIGNED_BYTE, 0 );
}
glBindTexture(GL_TEXTURE_2D, 0);
debugLog("Done");
inited = true;
enabled = true;
return true;
#endif
return false;
}
void FrameBuffer::unloadDevice()
{
debugLog("frameBuffer::unloadDevice");
#ifdef BBGE_BUILD_FRAMEBUFFER
if (glDeleteFramebuffersEXT == NULL)
{
debugLog("Already shut down the GL, don't delete framebuffers");
return;
}
if (g_frameBuffer)
{
debugLog("bind 0");
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
debugLog("frameBuffer handle present, deleting");
glDeleteFramebuffersEXT(1, &g_frameBuffer);
g_frameBuffer = 0;
}
if (g_dynamicTextureID)
{
debugLog("bind 0");
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
debugLog("dynamic texture ID handle present, deleting");
glDeleteTextures(1, &g_dynamicTextureID);
g_dynamicTextureID = 0;
}
if (g_depthRenderBuffer)
{
debugLog("bind 0");
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
debugLog("depth render buffer handle present, deleting");
glDeleteRenderbuffersEXT(1, &g_depthRenderBuffer);
g_depthRenderBuffer = 0;
}
#endif
debugLog("done");
}
void FrameBuffer::resetOpenGL()
{
#if defined(BBGE_BUILD_FRAMEBUFFER)
// set these back to NULL and reload them upon reinit, otherwise they
// might point to a bogus address when the shared library is reloaded.
glIsRenderbufferEXT = NULL;
glBindRenderbufferEXT = NULL;
glDeleteRenderbuffersEXT = NULL;
glGenRenderbuffersEXT = NULL;
glRenderbufferStorageEXT = NULL;
glGetRenderbufferParameterivEXT = NULL;
glIsFramebufferEXT = NULL;
glBindFramebufferEXT = NULL;
glDeleteFramebuffersEXT = NULL;
glGenFramebuffersEXT = NULL;
glCheckFramebufferStatusEXT = NULL;
glFramebufferTexture1DEXT = NULL;
glFramebufferTexture2DEXT = NULL;
glFramebufferTexture3DEXT = NULL;
glFramebufferRenderbufferEXT = NULL;
glGetFramebufferAttachmentParameterivEXT = NULL;
glGenerateMipmapEXT = NULL;
#endif
}
void FrameBuffer::reloadDevice()
{
debugLog("frameBuffer::reloadDevice");
init(_w, _h, _fitToScreen);
}
void FrameBuffer::startCapture()
{
#ifdef BBGE_BUILD_FRAMEBUFFER
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, g_frameBuffer );
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, g_dynamicTextureID, 0 );
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, g_depthRenderBuffer );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
#endif
}
void FrameBuffer::endCapture()
{
#ifdef BBGE_BUILD_FRAMEBUFFER
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
#endif
}
void FrameBuffer::bindTexture()
{
#ifdef BBGE_BUILD_FRAMEBUFFER
glBindTexture( GL_TEXTURE_2D, g_dynamicTextureID );
#endif
}
void FrameBuffer::setEnabled(bool e)
{
enabled = e;
}