From 871826bb2a29fa68b4c22e09524c78c81b87080c Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Wed, 26 Jul 2006 19:18:21 +0000 Subject: [PATCH] use GL_EXT_framebuffer_object --- stepmania/src/RageDisplay_OGL.cpp | 120 +++++++++++++++++++++- stepmania/src/RageDisplay_OGL_Helpers.cpp | 28 +++++ stepmania/src/RageDisplay_OGL_Helpers.h | 20 ++++ 3 files changed, 166 insertions(+), 2 deletions(-) diff --git a/stepmania/src/RageDisplay_OGL.cpp b/stepmania/src/RageDisplay_OGL.cpp index c8e2f0e63e..b66de23c67 100644 --- a/stepmania/src/RageDisplay_OGL.cpp +++ b/stepmania/src/RageDisplay_OGL.cpp @@ -1881,9 +1881,114 @@ void RageDisplay_OGL::UpdateTexture( delete pImg; } +class RenderTarget_FramebufferObject: public RenderTarget +{ +public: + RenderTarget_FramebufferObject(); + ~RenderTarget_FramebufferObject(); + void Create( const RenderTargetParam ¶m, int &iTextureWidthOut, int &iTextureHeightOut ); + unsigned GetTexture() const { return m_iTexHandle; } + void StartRenderingTo(); + void FinishRenderingTo(); + +private: + unsigned int m_iFrameBufferHandle; + unsigned int m_iTexHandle; + unsigned int m_iDepthBufferHandle; +}; + +RenderTarget_FramebufferObject::RenderTarget_FramebufferObject() +{ + m_iFrameBufferHandle = 0; + m_iTexHandle = 0; + m_iDepthBufferHandle = 0; +} + +RenderTarget_FramebufferObject::~RenderTarget_FramebufferObject() +{ + if( m_iDepthBufferHandle ) + GLExt.glDeleteRenderbuffersEXT( 1, reinterpret_cast(&m_iDepthBufferHandle) ); + if( m_iFrameBufferHandle ) + GLExt.glDeleteFramebuffersEXT( 1, reinterpret_cast(&m_iFrameBufferHandle) ); + if( m_iTexHandle ) + glDeleteTextures( 1, reinterpret_cast(&m_iTexHandle) ); +} + +void RenderTarget_FramebufferObject::Create( const RenderTargetParam ¶m, int &iTextureWidthOut, int &iTextureHeightOut ) +{ + FlushGLErrors(); + + // Allocate OpenGL texture resource + glGenTextures( 1, reinterpret_cast(&m_iTexHandle) ); + ASSERT( m_iTexHandle ); + + int iTextureWidth = power_of_two( param.iWidth ); + int iTextureHeight = power_of_two( param.iHeight ); + + iTextureWidthOut = iTextureWidth; + iTextureHeightOut = iTextureHeight; + + glBindTexture( GL_TEXTURE_2D, m_iTexHandle ); + glTexImage2D( GL_TEXTURE_2D, 0, param.bWithAlpha? GL_RGBA8:GL_RGB8, + iTextureWidth, iTextureHeight, 0, param.bWithAlpha? GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, NULL ); + AssertNoGLError(); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + /* Create the framebuffer object. */ + GLExt.glGenFramebuffersEXT( 1, reinterpret_cast(&m_iFrameBufferHandle) ); + ASSERT( m_iFrameBufferHandle ); + + /* Attach the texture to it. */ + GLExt.glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_iFrameBufferHandle ); + GLExt.glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_iTexHandle, 0 ); + AssertNoGLError(); + + /* Attach a depth buffer, if requested. */ + if( param.bWithDepthBuffer ) + { + GLExt.glGenRenderbuffersEXT( 1, reinterpret_cast(&m_iDepthBufferHandle) ); + ASSERT( m_iDepthBufferHandle ); + + GLExt.glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, iTextureWidth, iTextureHeight ); + GLExt.glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_iDepthBufferHandle ); + } + + GLenum status = GLExt.glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); + switch(status) + { + case GL_FRAMEBUFFER_COMPLETE_EXT: + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + FAIL_M( "GL_FRAMEBUFFER_UNSUPPORTED_EXT" ); + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: FAIL_M( "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT" ); break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: FAIL_M( "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT" ); break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: FAIL_M( "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT" ); break; + case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: FAIL_M( "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT" ); break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: FAIL_M( "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT" ); break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: FAIL_M( "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT" ); break; + default: + ASSERT(0); + } +} + +void RenderTarget_FramebufferObject::StartRenderingTo() +{ + GLExt.glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_iFrameBufferHandle ); +} + +void RenderTarget_FramebufferObject::FinishRenderingTo() +{ + GLExt.glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); +} + bool RageDisplay_OGL::SupportsRenderToTexture() const { - return g_pWind->SupportsRenderToTexture(); + return GLExt.m_bGL_EXT_framebuffer_object || g_pWind->SupportsRenderToTexture(); } /* @@ -1894,7 +1999,18 @@ bool RageDisplay_OGL::SupportsRenderToTexture() const unsigned RageDisplay_OGL::CreateRenderTarget( const RenderTargetParam ¶m, int &iTextureWidthOut, int &iTextureHeightOut ) { - RenderTarget *pTarget = g_pWind->CreateRenderTarget( param, iTextureWidthOut, iTextureHeightOut ); + RenderTarget *pTarget; + if( GLExt.m_bGL_EXT_framebuffer_object ) + { + RenderTarget_FramebufferObject *pTargetFBO = new RenderTarget_FramebufferObject; + pTargetFBO->Create( param, iTextureWidthOut, iTextureHeightOut ); + pTarget = pTargetFBO; + } + else + { + pTarget = g_pWind->CreateRenderTarget( param, iTextureWidthOut, iTextureHeightOut ); + } + unsigned iTexture = pTarget->GetTexture(); ASSERT( g_mapRenderTargets.find(iTexture) == g_mapRenderTargets.end() ); diff --git a/stepmania/src/RageDisplay_OGL_Helpers.cpp b/stepmania/src/RageDisplay_OGL_Helpers.cpp index d544b9a95a..e9b9349449 100644 --- a/stepmania/src/RageDisplay_OGL_Helpers.cpp +++ b/stepmania/src/RageDisplay_OGL_Helpers.cpp @@ -210,6 +210,34 @@ void GLExt_t::Load( LowLevelWindow *pWind ) LOG->Info( "OpenGL shading language: %s", pzVersion ); } } + + m_bGL_EXT_framebuffer_object = HasExtension("GL_EXT_framebuffer_object"); + if( m_bGL_EXT_framebuffer_object ) + { + func_t funcs[] = { + F( glIsRenderbufferEXT ), + F( glBindRenderbufferEXT ), + F( glDeleteRenderbuffersEXT ), + F( glGenRenderbuffersEXT ), + F( glRenderbufferStorageEXT ), + F( glGetRenderbufferParameterivEXT ), + F( glIsFramebufferEXT ), + F( glBindFramebufferEXT ), + F( glDeleteFramebuffersEXT ), + F( glGenFramebuffersEXT ), + F( glCheckFramebufferStatusEXT ), + F( glFramebufferTexture1DEXT ), + F( glFramebufferTexture2DEXT ), + F( glFramebufferTexture3DEXT ), + F( glFramebufferRenderbufferEXT ), + F( glGetFramebufferAttachmentParameterivEXT ), + F( glGenerateMipmapEXT ), + { NULL, NULL } + }; + + if( !LoadAllOrNothing(funcs, pWind) ) + m_bGL_EXT_framebuffer_object = false; + } } /* diff --git a/stepmania/src/RageDisplay_OGL_Helpers.h b/stepmania/src/RageDisplay_OGL_Helpers.h index ddbaf140c4..ac012b8f7f 100644 --- a/stepmania/src/RageDisplay_OGL_Helpers.h +++ b/stepmania/src/RageDisplay_OGL_Helpers.h @@ -95,6 +95,26 @@ struct GLExt_t bool m_bGL_ARB_shading_language_100; int m_iShadingLanguageVersion; /* * 100 */ + // GL_EXT_framebuffer_object: + bool m_bGL_EXT_framebuffer_object; + PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; + PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; + PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; + PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; + PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; + PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; + PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; + PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; + PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; + PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; + PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; + PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; + PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; + PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; + PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; + PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; + PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; + void Load( LowLevelWindow *pWind ); bool HasExtension( const RString &sExt ) const;