Loading common/CMakeLists.txt +7 −1 Original line number Diff line number Diff line Loading @@ -29,11 +29,15 @@ add_custom_target( ) set(GAL_SRCS # Common part drawpanel_gal.cpp painter.cpp gal/graphics_abstraction_layer.cpp gal/stroke_font.cpp gal/color4d.cpp view/wx_view_controls.cpp # OpenGL GAL gal/opengl/opengl_gal.cpp gal/opengl/shader.cpp gal/opengl/vertex_item.cpp Loading @@ -42,8 +46,10 @@ set(GAL_SRCS gal/opengl/noncached_container.cpp gal/opengl/vertex_manager.cpp gal/opengl/gpu_manager.cpp gal/opengl/opengl_compositor.cpp # Cairo GAL gal/cairo/cairo_gal.cpp view/wx_view_controls.cpp ) add_library(gal STATIC ${GAL_SRCS}) Loading common/gal/cairo/cairo_gal.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -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 ) { cairo_move_to( cairoImage, aStartPoint.x, aStartPoint.y ); Loading common/gal/graphics_abstraction_layer.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ void GAL::DrawGrid() if( !gridVisibility ) return; SetTarget( TARGET_NONCACHED ); // The grid consists of lines // For the drawing the start points, end points and increments have to be calculated in world coordinates VECTOR2D screenStartPoint( 0, 0 ); Loading common/gal/opengl/gpu_manager.cpp +5 −2 Original line number Diff line number Diff line Loading @@ -77,9 +77,11 @@ void GPU_MANAGER::SetShader( SHADER& aShader ) // Cached manager 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 ) { // Allocate the biggest possible buffer for indices m_indices.reset( new GLuint[aContainer->GetSize()] ); } Loading Loading @@ -252,7 +254,6 @@ void GPU_NONCACHED_MANAGER::EndDrawing() VERTEX* vertices = m_container->GetAllVertices(); GLfloat* coordinates = (GLfloat*) ( vertices ); GLubyte* colors = (GLubyte*) ( vertices ) + ColorOffset; GLfloat* shaders = (GLfloat*) ( vertices ) + ShaderOffset / sizeof(GLfloat); // Prepare buffers glEnableClientState( GL_VERTEX_ARRAY ); Loading @@ -263,6 +264,8 @@ void GPU_NONCACHED_MANAGER::EndDrawing() if( m_shader != NULL ) // Use shader if applicable { GLfloat* shaders = (GLfloat*) ( vertices ) + ShaderOffset / sizeof(GLfloat); m_shader->Use(); glEnableVertexAttribArray( m_shaderAttrib ); glVertexAttribPointer( m_shaderAttrib, ShaderStride, GL_FLOAT, GL_FALSE, Loading common/gal/opengl/opengl_compositor.cpp 0 → 100644 +242 −0 Original line number Diff line number Diff line /*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; Loading
common/CMakeLists.txt +7 −1 Original line number Diff line number Diff line Loading @@ -29,11 +29,15 @@ add_custom_target( ) set(GAL_SRCS # Common part drawpanel_gal.cpp painter.cpp gal/graphics_abstraction_layer.cpp gal/stroke_font.cpp gal/color4d.cpp view/wx_view_controls.cpp # OpenGL GAL gal/opengl/opengl_gal.cpp gal/opengl/shader.cpp gal/opengl/vertex_item.cpp Loading @@ -42,8 +46,10 @@ set(GAL_SRCS gal/opengl/noncached_container.cpp gal/opengl/vertex_manager.cpp gal/opengl/gpu_manager.cpp gal/opengl/opengl_compositor.cpp # Cairo GAL gal/cairo/cairo_gal.cpp view/wx_view_controls.cpp ) add_library(gal STATIC ${GAL_SRCS}) Loading
common/gal/cairo/cairo_gal.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -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 ) { cairo_move_to( cairoImage, aStartPoint.x, aStartPoint.y ); Loading
common/gal/graphics_abstraction_layer.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ void GAL::DrawGrid() if( !gridVisibility ) return; SetTarget( TARGET_NONCACHED ); // The grid consists of lines // For the drawing the start points, end points and increments have to be calculated in world coordinates VECTOR2D screenStartPoint( 0, 0 ); Loading
common/gal/opengl/gpu_manager.cpp +5 −2 Original line number Diff line number Diff line Loading @@ -77,9 +77,11 @@ void GPU_MANAGER::SetShader( SHADER& aShader ) // Cached manager 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 ) { // Allocate the biggest possible buffer for indices m_indices.reset( new GLuint[aContainer->GetSize()] ); } Loading Loading @@ -252,7 +254,6 @@ void GPU_NONCACHED_MANAGER::EndDrawing() VERTEX* vertices = m_container->GetAllVertices(); GLfloat* coordinates = (GLfloat*) ( vertices ); GLubyte* colors = (GLubyte*) ( vertices ) + ColorOffset; GLfloat* shaders = (GLfloat*) ( vertices ) + ShaderOffset / sizeof(GLfloat); // Prepare buffers glEnableClientState( GL_VERTEX_ARRAY ); Loading @@ -263,6 +264,8 @@ void GPU_NONCACHED_MANAGER::EndDrawing() if( m_shader != NULL ) // Use shader if applicable { GLfloat* shaders = (GLfloat*) ( vertices ) + ShaderOffset / sizeof(GLfloat); m_shader->Use(); glEnableVertexAttribArray( m_shaderAttrib ); glVertexAttribPointer( m_shaderAttrib, ShaderStride, GL_FLOAT, GL_FALSE, Loading
common/gal/opengl/opengl_compositor.cpp 0 → 100644 +242 −0 Original line number Diff line number Diff line /*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;