Commit 618a5f0e authored by Maciej Suminski's avatar Maciej Suminski

OpenGL multitarget rendering (compositing).

parent a8f47913
...@@ -29,11 +29,15 @@ add_custom_target( ...@@ -29,11 +29,15 @@ add_custom_target(
) )
set(GAL_SRCS set(GAL_SRCS
# Common part
drawpanel_gal.cpp drawpanel_gal.cpp
painter.cpp painter.cpp
gal/graphics_abstraction_layer.cpp gal/graphics_abstraction_layer.cpp
gal/stroke_font.cpp gal/stroke_font.cpp
gal/color4d.cpp gal/color4d.cpp
view/wx_view_controls.cpp
# OpenGL GAL
gal/opengl/opengl_gal.cpp gal/opengl/opengl_gal.cpp
gal/opengl/shader.cpp gal/opengl/shader.cpp
gal/opengl/vertex_item.cpp gal/opengl/vertex_item.cpp
...@@ -42,8 +46,10 @@ set(GAL_SRCS ...@@ -42,8 +46,10 @@ set(GAL_SRCS
gal/opengl/noncached_container.cpp gal/opengl/noncached_container.cpp
gal/opengl/vertex_manager.cpp gal/opengl/vertex_manager.cpp
gal/opengl/gpu_manager.cpp gal/opengl/gpu_manager.cpp
gal/opengl/opengl_compositor.cpp
# Cairo GAL
gal/cairo/cairo_gal.cpp gal/cairo/cairo_gal.cpp
view/wx_view_controls.cpp
) )
add_library(gal STATIC ${GAL_SRCS}) add_library(gal STATIC ${GAL_SRCS})
......
...@@ -280,6 +280,12 @@ void CAIRO_GAL::RestoreScreen() ...@@ -280,6 +280,12 @@ void CAIRO_GAL::RestoreScreen()
} }
void CAIRO_GAL::SetTarget( RenderTarget aTarget )
{
wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
}
void CAIRO_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) void CAIRO_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{ {
cairo_move_to( cairoImage, aStartPoint.x, aStartPoint.y ); cairo_move_to( cairoImage, aStartPoint.x, aStartPoint.y );
......
...@@ -62,6 +62,8 @@ void GAL::DrawGrid() ...@@ -62,6 +62,8 @@ void GAL::DrawGrid()
if( !gridVisibility ) if( !gridVisibility )
return; return;
SetTarget( TARGET_NONCACHED );
// The grid consists of lines // The grid consists of lines
// For the drawing the start points, end points and increments have to be calculated in world coordinates // For the drawing the start points, end points and increments have to be calculated in world coordinates
VECTOR2D screenStartPoint( 0, 0 ); VECTOR2D screenStartPoint( 0, 0 );
......
...@@ -77,9 +77,11 @@ void GPU_MANAGER::SetShader( SHADER& aShader ) ...@@ -77,9 +77,11 @@ void GPU_MANAGER::SetShader( SHADER& aShader )
// Cached manager // Cached manager
GPU_CACHED_MANAGER::GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ) : GPU_CACHED_MANAGER::GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
GPU_MANAGER( aContainer ), m_buffersInitialized( false ), m_indicesPtr( NULL ), GPU_MANAGER( aContainer ), m_buffersInitialized( false ),
m_indicesSize( 0 ) m_indicesSize( 0 )
{ {
// Allocate the biggest possible buffer for indices
m_indices.reset( new GLuint[aContainer->GetSize()] );
} }
...@@ -252,7 +254,6 @@ void GPU_NONCACHED_MANAGER::EndDrawing() ...@@ -252,7 +254,6 @@ void GPU_NONCACHED_MANAGER::EndDrawing()
VERTEX* vertices = m_container->GetAllVertices(); VERTEX* vertices = m_container->GetAllVertices();
GLfloat* coordinates = (GLfloat*) ( vertices ); GLfloat* coordinates = (GLfloat*) ( vertices );
GLubyte* colors = (GLubyte*) ( vertices ) + ColorOffset; GLubyte* colors = (GLubyte*) ( vertices ) + ColorOffset;
GLfloat* shaders = (GLfloat*) ( vertices ) + ShaderOffset / sizeof(GLfloat);
// Prepare buffers // Prepare buffers
glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_VERTEX_ARRAY );
...@@ -263,6 +264,8 @@ void GPU_NONCACHED_MANAGER::EndDrawing() ...@@ -263,6 +264,8 @@ void GPU_NONCACHED_MANAGER::EndDrawing()
if( m_shader != NULL ) // Use shader if applicable if( m_shader != NULL ) // Use shader if applicable
{ {
GLfloat* shaders = (GLfloat*) ( vertices ) + ShaderOffset / sizeof(GLfloat);
m_shader->Use(); m_shader->Use();
glEnableVertexAttribArray( m_shaderAttrib ); glEnableVertexAttribArray( m_shaderAttrib );
glVertexAttribPointer( m_shaderAttrib, ShaderStride, GL_FLOAT, GL_FALSE, glVertexAttribPointer( m_shaderAttrib, ShaderStride, GL_FLOAT, GL_FALSE,
......
/*i
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http:O//www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file opengl_compositor.cpp
* @brief Class that handles multitarget rendering (ie. to different textures/surfaces) and
* later compositing into a single image (OpenGL flavour).
*/
#include <gal/opengl/opengl_compositor.h>
#include <wx/log.h>
using namespace KiGfx;
OPENGL_COMPOSITOR::OPENGL_COMPOSITOR() :
m_initialized( false ), m_current( 0 )
{
}
OPENGL_COMPOSITOR::~OPENGL_COMPOSITOR()
{
if( m_initialized )
clean();
}
void OPENGL_COMPOSITOR::Initialize()
{
if( m_initialized )
return;
// Get the maximum number of buffers
glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &m_maxBuffers );
// We need framebuffer objects for drawing the screen contents
// Generate framebuffer and a depth buffer
glGenFramebuffers( 1, &m_framebuffer );
glBindFramebuffer( GL_FRAMEBUFFER, m_framebuffer );
m_currentFbo = m_framebuffer;
// Allocate memory for the depth buffer
// Attach the depth buffer to the framebuffer
glGenRenderbuffers( 1, &m_depthBuffer );
glBindRenderbuffer( GL_RENDERBUFFER, m_depthBuffer );
// Use here a size of 24 bits for the depth buffer, 8 bits for the stencil buffer
// this is required later for anti-aliasing
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_STENCIL, m_width, m_height );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, m_depthBuffer );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, m_depthBuffer );
// Check the status, exit if the framebuffer can't be created
GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
if( status != GL_FRAMEBUFFER_COMPLETE )
{
wxLogFatalError( wxT( "Cannot create the framebuffer." ) );
}
// Unbind the framebuffer, so by default all the rendering goes directly to the display
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
m_currentFbo = 0;
m_initialized = true;
}
void OPENGL_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight )
{
if( m_initialized )
clean();
m_width = aWidth;
m_height = aHeight;
}
unsigned int OPENGL_COMPOSITOR::GetBuffer()
{
wxASSERT( m_initialized );
if( m_buffers.size() < m_maxBuffers )
{
// GL_COLOR_ATTACHMENTn are consecutive integers
GLuint attachmentPoint = GL_COLOR_ATTACHMENT0 + usedBuffers();
GLuint textureTarget;
// Generate the texture for the pixel storage
glGenTextures( 1, &textureTarget );
glBindTexture( GL_TEXTURE_2D, textureTarget );
// Set texture parameters
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, NULL );
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
glBindFramebuffer( GL_FRAMEBUFFER, m_framebuffer );
m_currentFbo = m_framebuffer;
glFramebufferTexture2D( GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, textureTarget, 0 );
ClearBuffer();
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
m_currentFbo = 0;
// Store the new buffer
BUFFER_ITEM buffer = { textureTarget, attachmentPoint };
m_buffers.push_back( buffer );
return usedBuffers();
}
// Unfortunately we have no more buffers left
return 0;
}
void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
{
if( aBufferHandle <= usedBuffers() )
{
// Change the rendering destination to the selected attachment point
if( m_currentFbo != m_framebuffer )
{
glBindFramebuffer( GL_FRAMEBUFFER, m_framebuffer );
m_currentFbo = m_framebuffer;
}
if( m_current != aBufferHandle - 1 )
{
glDrawBuffer( m_buffers[m_current].attachmentPoint );
m_current = aBufferHandle - 1;
}
}
}
void OPENGL_COMPOSITOR::ClearBuffer()
{
wxASSERT( m_initialized );
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
}
void OPENGL_COMPOSITOR::BlitBuffer( unsigned int aBufferHandle )
{
wxASSERT( m_initialized );
wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
}
void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle, double aDepth )
{
wxASSERT( m_initialized );
// Switch to the main framebuffer and blit the scene
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
m_currentFbo = 0;
// Depth test has to be disabled to make transparency working
glDisable( GL_DEPTH_TEST );
glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
// Enable texturing and bind the main texture
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, m_buffers[aBufferHandle - 1].textureTarget );
// Draw a full screen quad with the texture
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
glBegin( GL_TRIANGLES );
glTexCoord2f( 0.0f, 1.0f );
glVertex3f( -1.0f, -1.0f, aDepth );
glTexCoord2f( 1.0f, 1.0f );
glVertex3f( 1.0f, -1.0f, aDepth );
glTexCoord2f( 1.0f, 0.0f );
glVertex3f( 1.0f, 1.0f, aDepth );
glTexCoord2f( 0.0f, 1.0f );
glVertex3f( -1.0f, -1.0f, aDepth );
glTexCoord2f( 1.0f, 0.0f );
glVertex3f( 1.0f, 1.0f, aDepth );
glTexCoord2f( 0.0f, 0.0f );
glVertex3f( -1.0f, 1.0f, aDepth );
glEnd();
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
}
void OPENGL_COMPOSITOR::clean()
{
wxASSERT( m_initialized );
glDeleteFramebuffers( 1, &m_framebuffer );
glDeleteRenderbuffers( 1, &m_depthBuffer );
Buffers::const_iterator it;
for( it = m_buffers.begin(); it != m_buffers.end(); ++it )
{
glDeleteTextures( 1, &it->textureTarget );
}
m_buffers.clear();
m_initialized = false;
}
GLuint OPENGL_COMPOSITOR::m_currentFbo = 0;
This diff is collapsed.
...@@ -43,14 +43,14 @@ void VIEW::AddLayer( int aLayer, bool aDisplayOnly ) ...@@ -43,14 +43,14 @@ void VIEW::AddLayer( int aLayer, bool aDisplayOnly )
{ {
if( m_layers.find( aLayer ) == m_layers.end() ) if( m_layers.find( aLayer ) == m_layers.end() )
{ {
m_layers[aLayer] = VIEW_LAYER(); m_layers[aLayer] = VIEW_LAYER();
m_layers[aLayer].id = aLayer; m_layers[aLayer].id = aLayer;
m_layers[aLayer].items = new VIEW_RTREE(); m_layers[aLayer].items = new VIEW_RTREE();
m_layers[aLayer].renderingOrder = aLayer; m_layers[aLayer].renderingOrder = aLayer;
m_layers[aLayer].enabled = true; m_layers[aLayer].enabled = true;
m_layers[aLayer].cached = true;
m_layers[aLayer].isDirty = false; m_layers[aLayer].isDirty = false;
m_layers[aLayer].displayOnly = aDisplayOnly; m_layers[aLayer].displayOnly = aDisplayOnly;
m_layers[aLayer].target = TARGET_CACHED;
} }
sortLayers(); sortLayers();
...@@ -136,7 +136,7 @@ int VIEW::Query( const BOX2I& aRect, std::vector<LayerItemPair>& aResult ) ...@@ -136,7 +136,7 @@ int VIEW::Query( const BOX2I& aRect, std::vector<LayerItemPair>& aResult )
VIEW::VIEW( bool aIsDynamic ) : VIEW::VIEW( bool aIsDynamic ) :
m_enableOrderModifier( false ), m_enableOrderModifier( false ),
m_scale ( 1.0 ), m_scale( 1.0 ),
m_painter( NULL ), m_painter( NULL ),
m_gal( NULL ), m_gal( NULL ),
m_dynamic( aIsDynamic ) m_dynamic( aIsDynamic )
...@@ -321,7 +321,7 @@ struct VIEW::updateItemsColor ...@@ -321,7 +321,7 @@ struct VIEW::updateItemsColor
void VIEW::UpdateLayerColor( int aLayer ) void VIEW::UpdateLayerColor( int aLayer )
{ {
// There is no point in updating non-cached layers // There is no point in updating non-cached layers
if( !m_layers[aLayer].cached ) if( m_layers[aLayer].target != TARGET_CACHED )
return; return;
BOX2I r; BOX2I r;
...@@ -344,7 +344,7 @@ void VIEW::UpdateAllLayersColor() ...@@ -344,7 +344,7 @@ void VIEW::UpdateAllLayersColor()
VIEW_LAYER* l = &( ( *i ).second ); VIEW_LAYER* l = &( ( *i ).second );
// There is no point in updating non-cached layers // There is no point in updating non-cached layers
if( !m_layers[l->id].cached ) if( l->target != TARGET_CACHED )
continue; continue;
updateItemsColor visitor( l->id, m_painter, m_gal ); updateItemsColor visitor( l->id, m_painter, m_gal );
...@@ -376,7 +376,7 @@ struct VIEW::changeItemsDepth ...@@ -376,7 +376,7 @@ struct VIEW::changeItemsDepth
void VIEW::ChangeLayerDepth( int aLayer, int aDepth ) void VIEW::ChangeLayerDepth( int aLayer, int aDepth )
{ {
// There is no point in updating non-cached layers // There is no point in updating non-cached layers
if( !m_layers[aLayer].cached ) if( m_layers[aLayer].target != TARGET_CACHED )
return; return;
BOX2I r; BOX2I r;
...@@ -483,7 +483,7 @@ struct VIEW::drawItem ...@@ -483,7 +483,7 @@ struct VIEW::drawItem
if( !drawCondition ) if( !drawCondition )
return; return;
if( currentLayer->cached ) if( currentLayer->target == TARGET_CACHED )
{ {
// Draw using cached information or create one // Draw using cached information or create one
int group = aItem->getGroup( currentLayer->id ); int group = aItem->getGroup( currentLayer->id );
...@@ -521,6 +521,7 @@ void VIEW::redrawRect( const BOX2I& aRect ) ...@@ -521,6 +521,7 @@ void VIEW::redrawRect( const BOX2I& aRect )
{ {
drawItem drawFunc( this, l ); drawItem drawFunc( this, l );
m_gal->SetTarget( l->target );
m_gal->SetLayerDepth( l->renderingOrder ); m_gal->SetLayerDepth( l->renderingOrder );
l->items->Query( aRect, drawFunc ); l->items->Query( aRect, drawFunc );
l->isDirty = false; l->isDirty = false;
...@@ -709,8 +710,10 @@ void VIEW::RecacheAllItems( bool aImmediately ) ...@@ -709,8 +710,10 @@ void VIEW::RecacheAllItems( bool aImmediately )
{ {
VIEW_LAYER* l = & ( ( *i ).second ); VIEW_LAYER* l = & ( ( *i ).second );
if( l->cached ) // Obviously, there is only one cached target that has to be recomputed
if( l->target == TARGET_CACHED )
{ {
m_gal->SetTarget( l->target );
m_gal->SetLayerDepth( l->renderingOrder ); m_gal->SetLayerDepth( l->renderingOrder );
recacheLayer visitor( this, m_gal, l->id, aImmediately ); recacheLayer visitor( this, m_gal, l->id, aImmediately );
l->items->Query( r, visitor ); l->items->Query( r, visitor );
......
...@@ -252,6 +252,9 @@ public: ...@@ -252,6 +252,9 @@ public:
/// @copydoc GAL::RestoreScreen() /// @copydoc GAL::RestoreScreen()
virtual void RestoreScreen(); virtual void RestoreScreen();
/// @copydoc GAL::SetTarget()
virtual void SetTarget( RenderTarget aTarget );
// ------- // -------
// Cursor // Cursor
// ------- // -------
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file compositor.h
* @brief Class that handles multitarget rendering (ie. to different textures/surfaces) and
* later compositing into a single image.
*/
#ifndef COMPOSITOR_H_
#define COMPOSITOR_H_
namespace KiGfx
{
class COMPOSITOR
{
public:
virtual ~COMPOSITOR()
{
}
/**
* Function Reset()
* performs primary initialiation, necessary to use the object.
*/
virtual void Initialize() = 0;
/**
* Function Resize()
* clears the state of COMPOSITOR, so it has to be reinitialized again with the new dimensions.
*
* @param aWidth is the framebuffer width (in pixels).
* @param aHeight is the framebuffer height (in pixels).
*/
virtual void Resize( unsigned int aWidth, unsigned int aHeight ) = 0;
/**
* Function GetBuffer()
* prepares a new buffer that may be used as a rendering target.
*
* @return is the handle of the buffer. In case of failure 0 (zero) is returned as the handle.
*/
virtual unsigned int GetBuffer() = 0;
/**
* Function SetBuffer()
* sets the selected buffer as the rendering target. All the following drawing functions are
* going to be rendered in the selected buffer.
*
* @param aBufferHandle is the handle of the buffer or 0 in case of rendering directly to the
* display.
*/
virtual void SetBuffer( unsigned int aBufferHandle ) = 0;
/**
* Function ClearBuffer()
* clears the selected buffer (set by the SetBuffer() function).
*/
virtual void ClearBuffer() = 0;
/**
* Function BlitBuffer()
* pastes the content of the buffer to the current buffer (set by SetBuffer() function).
*
* @param aBufferHandle is the handle to the buffer that is going to be pasted.
*/
virtual void BlitBuffer( unsigned int aBufferHandle ) = 0;
/**
* Function DrawBuffer()
* draws the selected buffer on the screen.
*
* @param aBufferHandle is the handle of the buffer to be drawn.
* @param aDepth is the depth on which the buffer should be drawn. // TODO mention if higher depth value means close to the screen or is it opposite
*/
virtual void DrawBuffer( unsigned int aBufferHandle, double aDepth ) = 0;
protected:
unsigned int m_width; ///< Width of the buffer (in pixels)
unsigned int m_height; ///< Height of the buffer (in pixels)
};
} // namespace KiGfx
#endif /* COMPOSITOR_H_ */
...@@ -31,4 +31,17 @@ ...@@ -31,4 +31,17 @@
#define SWAP( varA, condition, varB ) if( varA condition varB ) { double tmp = varA; varA = varB; \ #define SWAP( varA, condition, varB ) if( varA condition varB ) { double tmp = varA; varA = varB; \
varB = tmp; } varB = tmp; }
namespace KiGfx
{
/**
* RenderTarget: Possible rendering targets
*/
enum RenderTarget
{
TARGET_CACHED, ///< Main rendering target (cached)
TARGET_NONCACHED, ///< Auxiliary rendering target (noncached)
TARGET_OVERLAY ///< Items that may change while the view stays the same (noncached)
};
}
#endif /* DEFINITIONS_H_ */ #endif /* DEFINITIONS_H_ */
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <math/matrix3x3.h> #include <math/matrix3x3.h>
#include <gal/color4d.h> #include <gal/color4d.h>
#include <gal/definitions.h>
#include <gal/stroke_font.h> #include <gal/stroke_font.h>
#include <newstroke_font.h> #include <newstroke_font.h>
...@@ -546,16 +547,27 @@ public: ...@@ -546,16 +547,27 @@ public:
return worldScale; return worldScale;
} }
// ---------------------------
// Buffer manipulation methods
// ---------------------------
/** /**
* @brief Save the screen contents. * @brief Save the screen contents.
*/ */
virtual void SaveScreen() = 0; virtual void SaveScreen() = 0;
/** /**
* @brief Save the screen contents. * @brief Restore the screen contents.
*/ */
virtual void RestoreScreen() = 0; virtual void RestoreScreen() = 0;
/**
* @brief Sets the target for rendering.
*
* @param aTarget is the new target for rendering.
*/
virtual void SetTarget( RenderTarget aTarget ) = 0;
// ------------- // -------------
// Grid methods // Grid methods
// ------------- // -------------
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file opengl_compositor.h
* @brief Class that handles multitarget rendering (ie. to different textures/surfaces) and
* later compositing into a single image (OpenGL flavour).
*/
#ifndef OPENGL_COMPOSITOR_H_
#define OPENGL_COMPOSITOR_H_
#include <gal/compositor.h>
#include <GL/glew.h>
#include <vector>
namespace KiGfx
{
class OPENGL_COMPOSITOR : public COMPOSITOR
{
public:
OPENGL_COMPOSITOR();
virtual ~OPENGL_COMPOSITOR();
///< @copydoc COMPOSITOR::Initialize()
virtual void Initialize();
///< @copydoc COMPOSITOR::Resize()
virtual void Resize( unsigned int aWidth, unsigned int aHeight );
///< @copydoc COMPOSITOR::GetBuffer()
virtual unsigned int GetBuffer();
///< @copydoc COMPOSITOR::SetBuffer()
virtual void SetBuffer( unsigned int aBufferHandle );
///< @copydoc COMPOSITOR::ClearBuffer()
virtual void ClearBuffer();
///< @copydoc COMPOSITOR::BlitBuffer()
virtual void BlitBuffer( unsigned int aBufferHandle );
///< @copydoc COMPOSITOR::DrawBuffer()
virtual void DrawBuffer( unsigned int aBufferHandle, double aDepth );
protected:
typedef struct
{
GLuint textureTarget; ///< Main texture handle
GLuint attachmentPoint;
} BUFFER_ITEM;
bool m_initialized;
unsigned int m_current;
GLuint m_framebuffer; ///< Main FBO handle
GLuint m_depthBuffer; ///< Depth buffer handle
unsigned int m_maxBuffers; ///< Maximal amount of buffers
typedef std::vector<BUFFER_ITEM> Buffers;
Buffers m_buffers;
/// Store the currently used FBO name in case there was more than one compositor used
static GLuint m_currentFbo;
/**
* Function clean()
* performs freeing of resources.
*/
void clean();
///< Returns number of used buffers
unsigned int usedBuffers()
{
return m_buffers.size();
}
};
} // namespace KiGfx
#endif /* COMPOSITOR_H_ */
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <gal/opengl/vertex_manager.h> #include <gal/opengl/vertex_manager.h>
#include <gal/opengl/vertex_item.h> #include <gal/opengl/vertex_item.h>
#include <gal/opengl/noncached_container.h> #include <gal/opengl/noncached_container.h>
#include <gal/opengl/opengl_compositor.h>
#include <wx/wx.h> #include <wx/wx.h>
#include <wx/glcanvas.h> #include <wx/glcanvas.h>
...@@ -268,6 +269,9 @@ public: ...@@ -268,6 +269,9 @@ public:
/// @copydoc GAL::RestoreScreen() /// @copydoc GAL::RestoreScreen()
virtual void RestoreScreen(); virtual void RestoreScreen();
/// @copydoc GAL::SetTarget()
virtual void SetTarget( RenderTarget aTarget );
// ------- // -------
// Cursor // Cursor
// ------- // -------
...@@ -328,8 +332,8 @@ private: ...@@ -328,8 +332,8 @@ private:
wxEvtHandler* mouseListener; wxEvtHandler* mouseListener;
wxEvtHandler* paintListener; wxEvtHandler* paintListener;
// VBO buffered vertices for faster circle & semicircle drawing // Precomputed vertices for faster circle & semicircle drawing
NONCACHED_CONTAINER circleContainer; ///< Container for storing circle vertices NONCACHED_CONTAINER circleContainer; ///< Container for storing circle vertices
// Vertex buffer objects related fields // Vertex buffer objects related fields
typedef std::map< unsigned int, boost::shared_ptr<VERTEX_ITEM> > GroupsMap; typedef std::map< unsigned int, boost::shared_ptr<VERTEX_ITEM> > GroupsMap;
...@@ -338,6 +342,12 @@ private: ...@@ -338,6 +342,12 @@ private:
VERTEX_MANAGER* currentManager; ///< Currently used VERTEX_MANAGER (for storing VERTEX_ITEMs) VERTEX_MANAGER* currentManager; ///< Currently used VERTEX_MANAGER (for storing VERTEX_ITEMs)
VERTEX_MANAGER cachedManager; ///< Container for storing cached VERTEX_ITEMs VERTEX_MANAGER cachedManager; ///< Container for storing cached VERTEX_ITEMs
VERTEX_MANAGER nonCachedManager; ///< Container for storing non-cached VERTEX_ITEMs VERTEX_MANAGER nonCachedManager; ///< Container for storing non-cached VERTEX_ITEMs
VERTEX_MANAGER overlayManager; ///< Container for storing overlaid VERTEX_ITEMs
// Framebuffer & compositing
OPENGL_COMPOSITOR compositor; ///< Handles multiple rendering targets
unsigned int mainBuffer; ///< Main rendering target
unsigned int overlayBuffer; ///< Auxiliary rendering target (for menus etc.)
// Polygon tesselation // Polygon tesselation
GLUtesselator* tesselator; ///< Pointer to the tesselator GLUtesselator* tesselator; ///< Pointer to the tesselator
...@@ -350,20 +360,11 @@ private: ...@@ -350,20 +360,11 @@ private:
int cursorSize; ///< Size of the cursor in pixels int cursorSize; ///< Size of the cursor in pixels
GLubyte* cursorShape; ///< Cursor pixel storage GLubyte* cursorShape; ///< Cursor pixel storage
GLubyte* cursorSave; ///< Saved cursor pixels GLubyte* cursorSave; ///< Saved cursor pixels
bool isDeleteSavedPixels; ///< Flag for deleting saved pixels
VECTOR2D savedCursorPosition; ///< Last saved cursor position VECTOR2D savedCursorPosition; ///< Last saved cursor position
// Frame buffer
GLuint frameBuffer; ///< Main FBO handle
GLuint depthBuffer; ///< Depth buffer handle
GLuint texture; ///< Main texture handle
GLuint frameBufferBackup; ///< Backup FBO handle
GLuint depthBufferBackup; ///< Backup depth buffer handle
GLuint textureBackup; ///< Backup texture handle
// Internal flags // Internal flags
bool isGlewInitialized; ///< Is GLEW initialized? bool isGlewInitialized; ///< Is GLEW initialized?
bool isFrameBufferInitialized; ///< Are the frame buffers initialized? bool isFramebufferInitialized; ///< Are the framebuffers initialized?
bool isShaderInitialized; ///< Was the shader initialized? bool isShaderInitialized; ///< Was the shader initialized?
bool isUseShader; ///< Should the shaders be used? bool isUseShader; ///< Should the shaders be used?
bool isGrouping; ///< Was a group started? bool isGrouping; ///< Was a group started?
...@@ -434,34 +435,6 @@ private: ...@@ -434,34 +435,6 @@ private:
*/ */
void initCursor( int aCursorSize ); void initCursor( int aCursorSize );
/**
* @brief Blit the main texture to the screen.
*
* @param aIsClearFrameBuffer if true, the frame buffer is cleared as well.
*/
void blitMainTexture( bool aIsClearFrameBuffer );
/// @brief Initialize the frame buffers for main contents and backup storage.
void initFrameBuffers();
/**
* @brief Generate a frame buffer for the screen contents.
*
* @param aFrameBuffer is the pointer to the frame buffer handle.
* @param aDepthBuffer is the pointer to the depth buffer handle.
* @param aTexture is the pointer to the texture handle.
*/
void generateFrameBuffer( GLuint* aFrameBuffer, GLuint* aDepthBuffer, GLuint* aTexture );
/**
* @brief Delete the frame buffer for the screen contents.
*
* @param aFrameBuffer is the pointer to the frame buffer handle.
* @param aDepthBuffer is the pointer to the depth buffer handle.
* @param aTexture is the pointer to the texture handle.
*/
void deleteFrameBuffer( GLuint* aFrameBuffer, GLuint* aDepthBuffer, GLuint* aTexture );
/** /**
* @brief Draw a quad for the line. * @brief Draw a quad for the line.
* *
......
...@@ -43,7 +43,7 @@ enum SHADER_TYPE ...@@ -43,7 +43,7 @@ enum SHADER_TYPE
SHADER_STROKED_CIRCLE, SHADER_STROKED_CIRCLE,
}; };
typedef struct VERTEX typedef struct
{ {
GLfloat x, y, z; // Coordinates GLfloat x, y, z; // Coordinates
GLubyte r, g, b, a; // Color GLubyte r, g, b, a; // Color
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
namespace KiGfx namespace KiGfx
{ {
class VERTEX;
class VERTEX_ITEM; class VERTEX_ITEM;
class SHADER; class SHADER;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <boost/unordered/unordered_map.hpp> #include <boost/unordered/unordered_map.hpp>
#include <math/box2.h> #include <math/box2.h>
#include <gal/definitions.h>
namespace KiGfx namespace KiGfx
{ {
...@@ -258,14 +259,14 @@ public: ...@@ -258,14 +259,14 @@ public:
} }
/** /**
* Function SetLayerCached() * Function SetLayerTarget()
* Turns on or off the cached parameter of a particular layer. * Changes the rendering target for a particular layer.
* @param aLayer: the layer * @param aLayer is the layer.
* @param aCached: the new parameter value * @param aTarget is the rendering target.
*/ */
inline void SetLayerCached( int aLayer, bool aCached = true ) inline void SetLayerTarget( int aLayer, RenderTarget aTarget )
{ {
m_layers[aLayer].cached = aCached; m_layers[aLayer].target = aTarget;
} }
/** /**
...@@ -367,14 +368,13 @@ private: ...@@ -367,14 +368,13 @@ private:
bool enabled; ///* is the layer to be rendered? bool enabled; ///* is the layer to be rendered?
bool isDirty; ///* does it contain any dirty items (updated since last redraw) bool isDirty; ///* does it contain any dirty items (updated since last redraw)
bool displayOnly; ///* is the layer display only? bool displayOnly; ///* is the layer display only?
bool cached; ///* items on non-cached layers are displayed in
///* immediate mode
VIEW_RTREE* items; ///* R-tree indexing all items on this layer. VIEW_RTREE* items; ///* R-tree indexing all items on this layer.
std::vector<VIEW_ITEM*> dirtyItems; ///* set of dirty items collected since last redraw std::vector<VIEW_ITEM*> dirtyItems; ///* set of dirty items collected since last redraw
int renderingOrder; ///* rendering order of this layer int renderingOrder; ///* rendering order of this layer
int id; ///* layer ID int id; ///* layer ID
BOX2I extents; ///* sum of bboxes of all items on the layer BOX2I extents; ///* sum of bboxes of all items on the layer
BOX2I dirtyExtents; ///* sum of bboxes of all dirty items on the layer BOX2I dirtyExtents; ///* sum of bboxes of all dirty items on the layer
RenderTarget target; ///* where the layer should be rendered
}; };
// Convenience typedefs // Convenience typedefs
......
...@@ -207,7 +207,7 @@ void PCB_BASE_FRAME::SetBoard( BOARD* aBoard ) ...@@ -207,7 +207,7 @@ void PCB_BASE_FRAME::SetBoard( BOARD* aBoard )
// so there is no point in caching them // so there is no point in caching them
for( LAYER_NUM layer = FIRST_NETNAME_LAYER; layer <= LAST_NETNAME_LAYER; ++layer ) for( LAYER_NUM layer = FIRST_NETNAME_LAYER; layer <= LAST_NETNAME_LAYER; ++layer )
{ {
view->SetLayerCached( layer, false ); view->SetLayerTarget( layer, KiGfx::TARGET_NONCACHED );
} }
// Load layer & elements visibility settings // Load layer & elements visibility settings
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment