Minor OPENGL_COMPOSITOR refactoring.
This commit is contained in:
parent
1927f3a787
commit
4cca3bc368
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2015 CERN
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -29,6 +29,7 @@
|
|||
*/
|
||||
|
||||
#include <gal/opengl/opengl_compositor.h>
|
||||
#include <gal/opengl/utils.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
@ -36,11 +37,9 @@
|
|||
using namespace KIGFX;
|
||||
|
||||
OPENGL_COMPOSITOR::OPENGL_COMPOSITOR() :
|
||||
m_initialized( false ), m_current( 0 ), m_currentFbo( DIRECT_RENDERING )
|
||||
m_initialized( false ), m_curBuffer( 0 ),
|
||||
m_mainFbo( 0 ), m_depthBuffer( 0 ), m_curFbo( DIRECT_RENDERING )
|
||||
{
|
||||
// Avoid not initialized members:
|
||||
m_framebuffer = 0;
|
||||
m_depthBuffer = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -58,24 +57,25 @@ void OPENGL_COMPOSITOR::Initialize()
|
|||
|
||||
// We need framebuffer objects for drawing the screen contents
|
||||
// Generate framebuffer and a depth buffer
|
||||
glGenFramebuffersEXT( 1, &m_framebuffer );
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER, m_framebuffer );
|
||||
m_currentFbo = m_framebuffer;
|
||||
glGenFramebuffersEXT( 1, &m_mainFbo );
|
||||
checkGlError( "generating framebuffer" );
|
||||
bindFb( m_mainFbo );
|
||||
|
||||
// Allocate memory for the depth buffer
|
||||
// Attach the depth buffer to the framebuffer
|
||||
glGenRenderbuffersEXT( 1, &m_depthBuffer );
|
||||
checkGlError( "generating renderbuffer" );
|
||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_depthBuffer );
|
||||
checkGlError( "binding renderbuffer" );
|
||||
|
||||
// Use here a size of 24 bits for the depth buffer, 8 bits for the stencil buffer
|
||||
// this is required later for anti-aliasing
|
||||
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, m_width, m_height );
|
||||
checkGlError( "creating renderbuffer storage" );
|
||||
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT,
|
||||
GL_RENDERBUFFER_EXT, m_depthBuffer );
|
||||
checkGlError( "attaching renderbuffer" );
|
||||
|
||||
// Unbind the framebuffer, so by default all the rendering goes directly to the display
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, DIRECT_RENDERING );
|
||||
m_currentFbo = DIRECT_RENDERING;
|
||||
bindFb( DIRECT_RENDERING );
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
@ -95,36 +95,46 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer()
|
|||
{
|
||||
assert( m_initialized );
|
||||
|
||||
unsigned int maxBuffers;
|
||||
int maxBuffers, maxTextureSize;
|
||||
|
||||
// Get the maximum number of buffers
|
||||
glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &maxBuffers );
|
||||
|
||||
if( usedBuffers() >= maxBuffers )
|
||||
if( (int) usedBuffers() >= maxBuffers )
|
||||
{
|
||||
throw std::runtime_error( "Cannot create more framebuffers. OpenGL rendering "
|
||||
"backend requires at least 3 framebuffers. You may try to update/change "
|
||||
"your graphic drivers." );
|
||||
}
|
||||
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*) &maxTextureSize );
|
||||
|
||||
if( maxTextureSize < (int) m_width || maxTextureSize < (int) m_height )
|
||||
{
|
||||
throw std::runtime_error( "Requested texture size is not supported. "
|
||||
"Could not create a buffer." );
|
||||
}
|
||||
|
||||
// GL_COLOR_ATTACHMENTn are consecutive integers
|
||||
GLuint attachmentPoint = GL_COLOR_ATTACHMENT0 + usedBuffers();
|
||||
GLuint textureTarget;
|
||||
|
||||
// Generate the texture for the pixel storage
|
||||
glGenTextures( 1, &textureTarget );
|
||||
checkGlError( "generating framebuffer texture target" );
|
||||
glBindTexture( GL_TEXTURE_2D, textureTarget );
|
||||
checkGlError( "binding framebuffer texture target" );
|
||||
|
||||
// Set texture parameters
|
||||
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, NULL );
|
||||
checkGlError( "creating framebuffer texture" );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
||||
|
||||
// Bind the texture to the specific attachment point, clear and rebind the screen
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_framebuffer );
|
||||
m_currentFbo = m_framebuffer;
|
||||
bindFb( m_mainFbo );
|
||||
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachmentPoint,
|
||||
GL_TEXTURE_2D, textureTarget, 0 );
|
||||
|
||||
|
@ -177,8 +187,7 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer()
|
|||
ClearBuffer();
|
||||
|
||||
// Return to direct rendering (we were asked only to create a buffer, not switch to one)
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, DIRECT_RENDERING );
|
||||
m_currentFbo = DIRECT_RENDERING;
|
||||
bindFb( DIRECT_RENDERING );
|
||||
|
||||
// Store the new buffer
|
||||
OPENGL_BUFFER buffer = { textureTarget, attachmentPoint };
|
||||
|
@ -190,24 +199,18 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer()
|
|||
|
||||
void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
|
||||
{
|
||||
if( aBufferHandle > usedBuffers() )
|
||||
return;
|
||||
assert( m_initialized );
|
||||
assert( aBufferHandle <= usedBuffers() );
|
||||
|
||||
// Change the rendering destination to the selected attachment point
|
||||
if( aBufferHandle == DIRECT_RENDERING )
|
||||
{
|
||||
m_currentFbo = DIRECT_RENDERING;
|
||||
}
|
||||
else if( m_currentFbo != m_framebuffer )
|
||||
{
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_framebuffer );
|
||||
m_currentFbo = m_framebuffer;
|
||||
}
|
||||
// Either unbind the FBO for direct rendering, or bind the one with target textures
|
||||
bindFb( aBufferHandle == DIRECT_RENDERING ? DIRECT_RENDERING : m_mainFbo );
|
||||
|
||||
if( m_currentFbo != DIRECT_RENDERING )
|
||||
// Switch the target texture
|
||||
if( m_curFbo != DIRECT_RENDERING )
|
||||
{
|
||||
m_current = aBufferHandle - 1;
|
||||
glDrawBuffer( m_buffers[m_current].attachmentPoint );
|
||||
m_curBuffer = aBufferHandle - 1;
|
||||
glDrawBuffer( m_buffers[m_curBuffer].attachmentPoint );
|
||||
checkGlError( "setting draw buffer" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,8 +230,7 @@ void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
|
|||
assert( aBufferHandle != 0 && aBufferHandle <= usedBuffers() );
|
||||
|
||||
// Switch to the main framebuffer and blit the scene
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER, DIRECT_RENDERING );
|
||||
m_currentFbo = DIRECT_RENDERING;
|
||||
bindFb( DIRECT_RENDERING );
|
||||
|
||||
// Depth test has to be disabled to make transparency working
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
|
@ -268,23 +270,33 @@ void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
|
|||
}
|
||||
|
||||
|
||||
void OPENGL_COMPOSITOR::bindFb( unsigned int aFb ) {
|
||||
// Currently there are only 2 valid FBOs
|
||||
assert( aFb == DIRECT_RENDERING || aFb == m_mainFbo );
|
||||
|
||||
if( m_curFbo != aFb )
|
||||
{
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER, aFb );
|
||||
checkGlError( "switching framebuffer" );
|
||||
m_curFbo = aFb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_COMPOSITOR::clean()
|
||||
{
|
||||
assert( m_initialized );
|
||||
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER, DIRECT_RENDERING );
|
||||
m_currentFbo = DIRECT_RENDERING;
|
||||
bindFb( DIRECT_RENDERING );
|
||||
|
||||
OPENGL_BUFFERS::const_iterator it;
|
||||
|
||||
for( it = m_buffers.begin(); it != m_buffers.end(); ++it )
|
||||
for( OPENGL_BUFFERS::const_iterator it = m_buffers.begin(); it != m_buffers.end(); ++it )
|
||||
{
|
||||
glDeleteTextures( 1, &it->textureTarget );
|
||||
}
|
||||
|
||||
m_buffers.clear();
|
||||
|
||||
glDeleteFramebuffersEXT( 1, &m_framebuffer );
|
||||
glDeleteFramebuffersEXT( 1, &m_mainFbo );
|
||||
glDeleteRenderbuffersEXT( 1, &m_depthBuffer );
|
||||
|
||||
m_initialized = false;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -58,10 +58,10 @@ public:
|
|||
/// @copydoc COMPOSITOR::GetBuffer()
|
||||
inline virtual unsigned int GetBuffer() const
|
||||
{
|
||||
if( m_currentFbo == DIRECT_RENDERING )
|
||||
if( m_curFbo == DIRECT_RENDERING )
|
||||
return DIRECT_RENDERING;
|
||||
|
||||
return m_current + 1;
|
||||
return m_curBuffer + 1;
|
||||
}
|
||||
|
||||
/// @copydoc COMPOSITOR::ClearBuffer()
|
||||
|
@ -74,6 +74,7 @@ public:
|
|||
static const unsigned int DIRECT_RENDERING = 0;
|
||||
|
||||
protected:
|
||||
// Buffers are simply textures storing a result of certain target rendering.
|
||||
typedef struct
|
||||
{
|
||||
GLuint textureTarget; ///< Main texture handle
|
||||
|
@ -81,16 +82,19 @@ protected:
|
|||
} OPENGL_BUFFER;
|
||||
|
||||
bool m_initialized; ///< Initialization status flag
|
||||
unsigned int m_current; ///< Currently used buffer handle
|
||||
GLuint m_framebuffer; ///< Main FBO handle
|
||||
unsigned int m_curBuffer; ///< Currently used buffer handle
|
||||
GLuint m_mainFbo; ///< Main FBO handle (storing all target textures)
|
||||
GLuint m_depthBuffer; ///< Depth buffer handle
|
||||
typedef std::deque<OPENGL_BUFFER> OPENGL_BUFFERS;
|
||||
|
||||
/// Stores information about initialized buffers
|
||||
OPENGL_BUFFERS m_buffers;
|
||||
|
||||
/// Store the currently used FBO name in case there was more than one compositor used
|
||||
GLuint m_currentFbo;
|
||||
/// Store the used FBO name in case there was more than one compositor used
|
||||
GLuint m_curFbo;
|
||||
|
||||
/// Binds a specific Framebuffer Object.
|
||||
void bindFb( unsigned int aFb );
|
||||
|
||||
/**
|
||||
* Function clean()
|
||||
|
|
Loading…
Reference in New Issue