diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index b6adf0d275..9e28a9fb3b 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -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 @@ -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}) diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp index ba944e842f..e6a2a59d82 100644 --- a/common/gal/cairo/cairo_gal.cpp +++ b/common/gal/cairo/cairo_gal.cpp @@ -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 ); diff --git a/common/gal/graphics_abstraction_layer.cpp b/common/gal/graphics_abstraction_layer.cpp index 93ce880bf7..88855fa5c6 100644 --- a/common/gal/graphics_abstraction_layer.cpp +++ b/common/gal/graphics_abstraction_layer.cpp @@ -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 ); diff --git a/common/gal/opengl/gpu_manager.cpp b/common/gal/opengl/gpu_manager.cpp index dea8e76f91..04341ed0d4 100644 --- a/common/gal/opengl/gpu_manager.cpp +++ b/common/gal/opengl/gpu_manager.cpp @@ -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()] ); } @@ -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 ); @@ -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, diff --git a/common/gal/opengl/opengl_compositor.cpp b/common/gal/opengl/opengl_compositor.cpp new file mode 100644 index 0000000000..1b768388c8 --- /dev/null +++ b/common/gal/opengl/opengl_compositor.cpp @@ -0,0 +1,242 @@ +/*i + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Maciej Suminski + * + * 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 +#include + +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; diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index 19d50d2244..bac3c92280 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -54,7 +54,8 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, wxGLCanvas( aParent, wxID_ANY, (int*) glAttributes, wxDefaultPosition, wxDefaultSize, wxEXPAND, aName ), cachedManager( true ), - nonCachedManager( false ) + nonCachedManager( false ), + overlayManager( false ) { // Create the OpenGL-Context glContext = new wxGLContext( this ); @@ -67,9 +68,8 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, SetCursorColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) ); // Initialize the flags - isDeleteSavedPixels = true; isGlewInitialized = false; - isFrameBufferInitialized = false; + isFramebufferInitialized = false; isUseShader = isUseShaders; isShaderInitialized = false; isGrouping = false; @@ -109,9 +109,6 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, // Compute the unit circle vertices and store them in a buffer for faster drawing computeCircle(); - - // By default we draw non-cached objects, it changes on BeginGroup()/EndGroup() - currentManager = &nonCachedManager; } @@ -119,13 +116,6 @@ OPENGL_GAL::~OPENGL_GAL() { glFlush(); - // Delete the buffers - if( isFrameBufferInitialized ) - { - deleteFrameBuffer( &frameBuffer, &depthBuffer, &texture ); - deleteFrameBuffer( &frameBufferBackup, &depthBufferBackup, &textureBackup ); - } - gluDeleteTess( tesselator ); ClearCache(); @@ -143,15 +133,9 @@ void OPENGL_GAL::ResizeScreen( int aWidth, int aHeight ) { screenSize = VECTOR2D( aWidth, aHeight ); - // Delete old buffers for resizing - if( isFrameBufferInitialized ) - { - deleteFrameBuffer( &frameBuffer, &depthBuffer, &texture ); - deleteFrameBuffer( &frameBufferBackup, &depthBufferBackup, &textureBackup ); - - // This flag is used for recreating the buffers - isFrameBufferInitialized = false; - } + // Resize framebuffers + compositor.Resize( aWidth, aHeight ); + isFramebufferInitialized = false; wxGLCanvas::SetSize( aWidth, aHeight ); } @@ -165,86 +149,35 @@ void OPENGL_GAL::skipMouseEvent( wxMouseEvent& aEvent ) } -void OPENGL_GAL::generateFrameBuffer( GLuint* aFrameBuffer, GLuint* aDepthBuffer, - GLuint* aTexture ) -{ - // We need frame buffer objects for drawing the screen contents - - // Generate frame buffer and a depth buffer - glGenFramebuffersEXT( 1, aFrameBuffer ); - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, *aFrameBuffer ); - - // Allocate memory for the depth buffer - // Attach the depth buffer to the frame buffer - glGenRenderbuffersEXT( 1, aDepthBuffer ); - glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, *aDepthBuffer ); - - // 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_STENCIL_EXT, screenSize.x, - screenSize.y ); - glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, - *aDepthBuffer ); - glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, *aDepthBuffer ); - - // Generate the texture for the pixel storage - // Attach the texture to the frame buffer - glGenTextures( 1, aTexture ); - glBindTexture( GL_TEXTURE_2D, *aTexture ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, screenSize.x, screenSize.y, 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 ); - glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, - *aTexture, 0 ); - - // Check the status, exit if the frame buffer can't be created - GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); - - if( status != GL_FRAMEBUFFER_COMPLETE_EXT ) - { - wxLogError( wxT( "Can't create the frame buffer." ) ); - exit( 1 ); - } - - isFrameBufferInitialized = true; -} - - -void OPENGL_GAL::deleteFrameBuffer( GLuint* aFrameBuffer, GLuint* aDepthBuffer, GLuint* aTexture ) -{ - glDeleteFramebuffers( 1, aFrameBuffer ); - glDeleteRenderbuffers( 1, aDepthBuffer ); - glDeleteTextures( 1, aTexture ); -} - - -void OPENGL_GAL::initFrameBuffers() -{ - generateFrameBuffer( &frameBuffer, &depthBuffer, &texture ); - generateFrameBuffer( &frameBufferBackup, &depthBufferBackup, &textureBackup ); -} - - void OPENGL_GAL::SaveScreen() { - glBindFramebuffer( GL_DRAW_FRAMEBUFFER, frameBufferBackup ); - glBindFramebuffer( GL_READ_FRAMEBUFFER, frameBuffer ); - glBlitFramebuffer( 0, 0, screenSize.x, screenSize.y, 0, 0, screenSize.x, screenSize.y, - GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, - GL_NEAREST ); - glBindFramebuffer( GL_DRAW_FRAMEBUFFER, frameBuffer ); + wxASSERT_MSG( false, wxT( "Not implemented yet" ) ); } void OPENGL_GAL::RestoreScreen() { - glBindFramebuffer( GL_DRAW_FRAMEBUFFER, frameBuffer ); - glBindFramebuffer( GL_READ_FRAMEBUFFER, frameBufferBackup ); - glBlitFramebuffer( 0, 0, screenSize.x, screenSize.y, 0, 0, screenSize.x, screenSize.y, - GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, - GL_NEAREST ); + wxASSERT_MSG( false, wxT( "Not implemented yet" ) ); +} + + +void OPENGL_GAL::SetTarget( RenderTarget aTarget ) +{ + switch( aTarget ) + { + default: + case TARGET_CACHED: + currentManager = &cachedManager; + break; + + case TARGET_NONCACHED: + currentManager = &nonCachedManager; + break; + + case TARGET_OVERLAY: + currentManager = &overlayManager; + break; + } } @@ -275,7 +208,7 @@ void OPENGL_GAL::initGlew() exit( 1 ); } - // Frame buffers have to be supported + // Framebuffers have to be supported if( !GLEW_ARB_framebuffer_object ) { wxLogError( wxT( "Framebuffer objects are not supported!" ) ); @@ -303,8 +236,23 @@ void OPENGL_GAL::BeginDrawing() if( !isGlewInitialized ) initGlew(); - if( !isFrameBufferInitialized ) - initFrameBuffers(); + if( !isFramebufferInitialized ) + { + // Set up the view port + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y ); + + // Create the screen transformation + glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y, -depthRange.x, -depthRange.y ); + + // Prepare rendering target buffers + compositor.Initialize(); + mainBuffer = compositor.GetBuffer(); + overlayBuffer = compositor.GetBuffer(); + + isFramebufferInitialized = true; + } // Compile the shaders if( !isShaderInitialized && isUseShader ) @@ -321,19 +269,18 @@ void OPENGL_GAL::BeginDrawing() // Make VBOs use shaders cachedManager.SetShader( shader ); nonCachedManager.SetShader( shader ); + overlayManager.SetShader( shader ); isShaderInitialized = true; } - // Bind the main frame buffer object - all contents are drawn there - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, frameBuffer ); - // Disable 2D Textures glDisable( GL_TEXTURE_2D ); // Enable the depth buffer glEnable( GL_DEPTH_TEST ); glDepthFunc( GL_LESS ); + // Setup blending, required for transparent objects glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); @@ -341,14 +288,6 @@ void OPENGL_GAL::BeginDrawing() // Enable smooth lines glEnable( GL_LINE_SMOOTH ); - // Set up the view port - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y ); - - // Create the screen transformation - glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y, -depthRange.x, -depthRange.y ); - glMatrixMode( GL_MODELVIEW ); // Set up the world <-> screen transformation @@ -368,69 +307,34 @@ void OPENGL_GAL::BeginDrawing() // Set defaults SetFillColor( fillColor ); SetStrokeColor( strokeColor ); - isDeleteSavedPixels = true; + // Prepare buffers for drawing nonCachedManager.Clear(); + overlayManager.Clear(); cachedManager.BeginDrawing(); nonCachedManager.BeginDrawing(); -} - - -void OPENGL_GAL::blitMainTexture( bool aIsClearFrameBuffer ) -{ - // Don't use blending for the final blitting - glDisable( GL_BLEND ); - - glColor4d( 1.0, 1.0, 1.0, 1.0 ); - - // Switch to the main frame buffer and blit the scene - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); - - if( aIsClearFrameBuffer ) - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); - - // Enable texturing and bind the main texture - glEnable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, texture ); - - // Draw a full screen quad with the texture - glMatrixMode( GL_MODELVIEW ); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode( GL_PROJECTION ); - glPushMatrix(); - glLoadIdentity(); - - glBegin( GL_TRIANGLES ); - glTexCoord2i( 0, 1 ); - glVertex3i( -1, -1, 0 ); - glTexCoord2i( 1, 1 ); - glVertex3i( 1, -1, 0 ); - glTexCoord2i( 1, 0 ); - glVertex3i( 1, 1, 0 ); - - glTexCoord2i( 0, 1 ); - glVertex3i( -1, -1, 0 ); - glTexCoord2i( 1, 0 ); - glVertex3i( 1, 1, 0 ); - glTexCoord2i( 0, 0 ); - glVertex3i( -1, 1, 0 ); - glEnd(); - glPopMatrix(); - glMatrixMode( GL_MODELVIEW ); - glPopMatrix(); + overlayManager.BeginDrawing(); } void OPENGL_GAL::EndDrawing() { + // Cached & non-cached containers are rendered to the same buffer + compositor.SetBuffer( mainBuffer ); + compositor.ClearBuffer(); nonCachedManager.EndDrawing(); cachedManager.EndDrawing(); - // Draw the remaining contents, blit the main texture to the screen, swap the buffers + // Overlay container is rendered to a different buffer + compositor.SetBuffer( overlayBuffer ); + compositor.ClearBuffer(); + overlayManager.EndDrawing(); + + // Draw the remaining contents, blit the rendering targets to the screen, swap the buffers glFlush(); - blitMainTexture( true ); + compositor.DrawBuffer( mainBuffer, -1.0 ); + compositor.DrawBuffer( overlayBuffer, 0.0 ); SwapBuffers(); delete clientDC; @@ -530,8 +434,10 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP VECTOR2D( lineLength, -aWidth / 2.0 ) ); // Draw line caps - drawStrokedSemiCircle( VECTOR2D( 0.0, 0.0 ), ( aWidth + lineWidth ) / 2, M_PI / 2 ); - drawStrokedSemiCircle( VECTOR2D( lineLength, 0.0 ), ( aWidth + lineWidth ) / 2, -M_PI / 2 ); + drawStrokedSemiCircle( VECTOR2D( 0.0, 0.0 ), + ( aWidth + lineWidth ) / 2, M_PI / 2 ); + drawStrokedSemiCircle( VECTOR2D( lineLength, 0.0 ), + ( aWidth + lineWidth ) / 2, -M_PI / 2 ); Restore(); } @@ -643,15 +549,16 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) v0 /_\/_\ v1 */ currentManager->Shader( SHADER_FILLED_CIRCLE, 1.0 ); - currentManager->Vertex( aCenterPoint.x - aRadius * sqrt( 3.0f ), - aCenterPoint.y - aRadius, layerDepth ); // v0 + currentManager->Vertex( aCenterPoint.x - aRadius * sqrt( 3.0f ), // v0 + aCenterPoint.y - aRadius, layerDepth ); currentManager->Shader( SHADER_FILLED_CIRCLE, 2.0 ); - currentManager->Vertex( aCenterPoint.x + aRadius* sqrt( 3.0f ), - aCenterPoint.y - aRadius, layerDepth ); // v1 + currentManager->Vertex( aCenterPoint.x + aRadius* sqrt( 3.0f ), // v1 + aCenterPoint.y - aRadius, layerDepth ); currentManager->Shader( SHADER_FILLED_CIRCLE, 3.0 ); - currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + aRadius * 2.0f, layerDepth ); // v2 + currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + aRadius * 2.0f, // v2 + layerDepth ); } if( isStrokeEnabled ) @@ -661,8 +568,8 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) /* Draw a triangle that contains the circle, then shade it leaving only the circle. Parameters given to setShader are indices of the triangle's vertices (if you want to understand more, check the vertex shader source [shader.vert]). - and the line width. Shader uses this coordinates to determine if fragments are inside - the circle or not. + and the line width. Shader uses this coordinates to determine if fragments are + inside the circle or not. v2 /\ //\\ @@ -670,15 +577,16 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) */ double outerRadius = aRadius + ( lineWidth / 2 ); currentManager->Shader( SHADER_STROKED_CIRCLE, 1.0, aRadius, lineWidth ); - currentManager->Vertex( aCenterPoint.x - outerRadius * sqrt( 3.0f ), - aCenterPoint.y - outerRadius, layerDepth ); // v0 + currentManager->Vertex( aCenterPoint.x - outerRadius * sqrt( 3.0f ), // v0 + aCenterPoint.y - outerRadius, layerDepth ); currentManager->Shader( SHADER_STROKED_CIRCLE, 2.0, aRadius, lineWidth ); - currentManager->Vertex( aCenterPoint.x + outerRadius * sqrt( 3.0f ), - aCenterPoint.y - outerRadius, layerDepth ); // v1 + currentManager->Vertex( aCenterPoint.x + outerRadius * sqrt( 3.0f ), // v1 + aCenterPoint.y - outerRadius, layerDepth ); currentManager->Shader( SHADER_STROKED_CIRCLE, 3.0, aRadius, lineWidth ); - currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + outerRadius * 2.0f, layerDepth ); // v2 + currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + outerRadius * 2.0f, // v2 + layerDepth ); } } else @@ -716,7 +624,8 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) if( i % 3 == 0 ) { i++; - // Depending on the vertex, next circle point may be stored in the next vertex.. + // Depending on the vertex, next circle point + // may be stored in the next vertex.. next = i + 1; } else @@ -750,7 +659,7 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) } } - // Filled circles are easy to draw by using the stored vertices list, scaling and translating + // Filled circles are easy to draw by using the stored vertices list if( isFillEnabled ) { currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); @@ -790,8 +699,8 @@ void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRad currentManager->Translate( aCenterPoint.x, aCenterPoint.y, 0.0f ); currentManager->Rotate( aAngle, 0.0f, 0.0f, 1.0f ); - /* Draw a triangle that contains the semicircle, then shade it to leave only the semicircle. - Parameters given to setShader are indices of the triangle's vertices + /* Draw a triangle that contains the semicircle, then shade it to leave only + * the semicircle. Parameters given to setShader are indices of the triangle's vertices (if you want to understand more, check the vertex shader source [shader.vert]). Shader uses this coordinates to determine if fragments are inside the semicircle or not. v2 @@ -800,13 +709,13 @@ void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRad v0 //__\\ v1 */ currentManager->Shader( SHADER_FILLED_CIRCLE, 4.0f ); - currentManager->Vertex( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0 + currentManager->Vertex( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0 currentManager->Shader( SHADER_FILLED_CIRCLE, 5.0f ); - currentManager->Vertex( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1 + currentManager->Vertex( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1 currentManager->Shader( SHADER_FILLED_CIRCLE, 6.0f ); - currentManager->Vertex( 0.0f, aRadius * 2.0f, layerDepth ); // v2 + currentManager->Vertex( 0.0f, aRadius * 2.0f, layerDepth ); // v2 Restore(); } @@ -836,8 +745,8 @@ void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRa currentManager->Translate( aCenterPoint.x, aCenterPoint.y, 0.0f ); currentManager->Rotate( aAngle, 0.0f, 0.0f, 1.0f ); - /* Draw a triangle that contains the semicircle, then shade it to leave only the semicircle. - Parameters given to setShader are indices of the triangle's vertices + /* Draw a triangle that contains the semicircle, then shade it to leave only + * the semicircle. Parameters given to setShader are indices of the triangle's vertices (if you want to understand more, check the vertex shader source [shader.vert]), the radius and the line width. Shader uses this coordinates to determine if fragments are inside the semicircle or not. @@ -847,13 +756,13 @@ void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRa v0 //__\\ v1 */ currentManager->Shader( SHADER_STROKED_CIRCLE, 4.0f, aRadius, lineWidth ); - currentManager->Vertex( -outerRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0 + currentManager->Vertex( -outerRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0 currentManager->Shader( SHADER_STROKED_CIRCLE, 5.0f, aRadius, lineWidth ); - currentManager->Vertex( outerRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1 + currentManager->Vertex( outerRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1 currentManager->Shader( SHADER_STROKED_CIRCLE, 6.0f, aRadius, lineWidth ); - currentManager->Vertex( 0.0f, outerRadius * 2.0f, layerDepth ); // v2 + currentManager->Vertex( 0.0f, outerRadius * 2.0f, layerDepth ); // v2 Restore(); } @@ -957,10 +866,9 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a outerScale += 1.0; innerScale += 1.0; - double alphaIncrement = 2 * M_PI / CIRCLE_POINTS; + double alphaIncrement = 2.0 * M_PI / CIRCLE_POINTS; currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); - for( double alpha = aStartAngle; alpha < aEndAngle; ) { double v0[] = { cos( alpha ) * innerScale, sin( alpha ) * innerScale }; @@ -1155,8 +1063,7 @@ void OPENGL_GAL::ClearScreen() { // Clear screen glClearColor( backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a ); - - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } @@ -1219,7 +1126,6 @@ int OPENGL_GAL::BeginGroup() isGrouping = true; boost::shared_ptr newItem( new VERTEX_ITEM( cachedManager ) ); - currentManager = &cachedManager; int groupNumber = getNewGroupNumber(); groups.insert( std::make_pair( groupNumber, newItem ) ); @@ -1229,8 +1135,6 @@ int OPENGL_GAL::BeginGroup() void OPENGL_GAL::EndGroup() { - currentManager = &nonCachedManager; - isGrouping = false; } @@ -1399,6 +1303,8 @@ VECTOR2D OPENGL_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition ) void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition ) { + wxLogWarning( wxT( "Not tested ") ); + SetCurrent( *glContext ); // Draw the cursor on the surface @@ -1409,14 +1315,12 @@ void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition ) aCursorPosition = worldScreenMatrix * cursorPositionWorld; - // Switch to the main frame buffer and blit the scene - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + // Switch to the main framebuffer and blit the scene + //glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + //glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); - blitMainTexture( false ); - glDisable( GL_TEXTURE_2D ); glColor4d( cursorColor.r, cursorColor.g, cursorColor.b, cursorColor.a ); diff --git a/common/view/view.cpp b/common/view/view.cpp index 8e1b031d31..ead82c46e8 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -43,14 +43,14 @@ void VIEW::AddLayer( int aLayer, bool aDisplayOnly ) { if( m_layers.find( aLayer ) == m_layers.end() ) { - m_layers[aLayer] = VIEW_LAYER(); - m_layers[aLayer].id = aLayer; - m_layers[aLayer].items = new VIEW_RTREE(); + m_layers[aLayer] = VIEW_LAYER(); + m_layers[aLayer].id = aLayer; + m_layers[aLayer].items = new VIEW_RTREE(); m_layers[aLayer].renderingOrder = aLayer; m_layers[aLayer].enabled = true; - m_layers[aLayer].cached = true; m_layers[aLayer].isDirty = false; m_layers[aLayer].displayOnly = aDisplayOnly; + m_layers[aLayer].target = TARGET_CACHED; } sortLayers(); @@ -136,7 +136,7 @@ int VIEW::Query( const BOX2I& aRect, std::vector& aResult ) VIEW::VIEW( bool aIsDynamic ) : m_enableOrderModifier( false ), - m_scale ( 1.0 ), + m_scale( 1.0 ), m_painter( NULL ), m_gal( NULL ), m_dynamic( aIsDynamic ) @@ -321,7 +321,7 @@ struct VIEW::updateItemsColor void VIEW::UpdateLayerColor( int aLayer ) { // There is no point in updating non-cached layers - if( !m_layers[aLayer].cached ) + if( m_layers[aLayer].target != TARGET_CACHED ) return; BOX2I r; @@ -344,7 +344,7 @@ void VIEW::UpdateAllLayersColor() VIEW_LAYER* l = &( ( *i ).second ); // There is no point in updating non-cached layers - if( !m_layers[l->id].cached ) + if( l->target != TARGET_CACHED ) continue; updateItemsColor visitor( l->id, m_painter, m_gal ); @@ -376,7 +376,7 @@ struct VIEW::changeItemsDepth void VIEW::ChangeLayerDepth( int aLayer, int aDepth ) { // There is no point in updating non-cached layers - if( !m_layers[aLayer].cached ) + if( m_layers[aLayer].target != TARGET_CACHED ) return; BOX2I r; @@ -483,7 +483,7 @@ struct VIEW::drawItem if( !drawCondition ) return; - if( currentLayer->cached ) + if( currentLayer->target == TARGET_CACHED ) { // Draw using cached information or create one int group = aItem->getGroup( currentLayer->id ); @@ -521,6 +521,7 @@ void VIEW::redrawRect( const BOX2I& aRect ) { drawItem drawFunc( this, l ); + m_gal->SetTarget( l->target ); m_gal->SetLayerDepth( l->renderingOrder ); l->items->Query( aRect, drawFunc ); l->isDirty = false; @@ -709,8 +710,10 @@ void VIEW::RecacheAllItems( bool aImmediately ) { 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 ); recacheLayer visitor( this, m_gal, l->id, aImmediately ); l->items->Query( r, visitor ); diff --git a/include/gal/cairo/cairo_gal.h b/include/gal/cairo/cairo_gal.h index 96035763de..35e3188d07 100644 --- a/include/gal/cairo/cairo_gal.h +++ b/include/gal/cairo/cairo_gal.h @@ -252,6 +252,9 @@ public: /// @copydoc GAL::RestoreScreen() virtual void RestoreScreen(); + /// @copydoc GAL::SetTarget() + virtual void SetTarget( RenderTarget aTarget ); + // ------- // Cursor // ------- diff --git a/include/gal/compositor.h b/include/gal/compositor.h new file mode 100644 index 0000000000..e678b00bdc --- /dev/null +++ b/include/gal/compositor.h @@ -0,0 +1,107 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Maciej Suminski + * + * 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_ */ diff --git a/include/gal/definitions.h b/include/gal/definitions.h index b6a66c584c..5e9059a2df 100644 --- a/include/gal/definitions.h +++ b/include/gal/definitions.h @@ -31,4 +31,17 @@ #define SWAP( varA, condition, varB ) if( varA condition varB ) { double tmp = varA; varA = varB; \ 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_ */ diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index d4142c3237..bb256f684a 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -546,16 +547,27 @@ public: return worldScale; } + // --------------------------- + // Buffer manipulation methods + // --------------------------- + /** * @brief Save the screen contents. */ virtual void SaveScreen() = 0; /** - * @brief Save the screen contents. + * @brief Restore the screen contents. */ 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 // ------------- diff --git a/include/gal/opengl/opengl_compositor.h b/include/gal/opengl/opengl_compositor.h new file mode 100644 index 0000000000..f58cd493d9 --- /dev/null +++ b/include/gal/opengl/opengl_compositor.h @@ -0,0 +1,101 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Maciej Suminski + * + * 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 +#include +#include + +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 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_ */ diff --git a/include/gal/opengl/opengl_gal.h b/include/gal/opengl/opengl_gal.h index 9338b44187..b44d338fa8 100644 --- a/include/gal/opengl/opengl_gal.h +++ b/include/gal/opengl/opengl_gal.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -268,6 +269,9 @@ public: /// @copydoc GAL::RestoreScreen() virtual void RestoreScreen(); + /// @copydoc GAL::SetTarget() + virtual void SetTarget( RenderTarget aTarget ); + // ------- // Cursor // ------- @@ -328,8 +332,8 @@ private: wxEvtHandler* mouseListener; wxEvtHandler* paintListener; - // VBO buffered vertices for faster circle & semicircle drawing - NONCACHED_CONTAINER circleContainer; ///< Container for storing circle vertices + // Precomputed vertices for faster circle & semicircle drawing + NONCACHED_CONTAINER circleContainer; ///< Container for storing circle vertices // Vertex buffer objects related fields typedef std::map< unsigned int, boost::shared_ptr > GroupsMap; @@ -338,6 +342,12 @@ private: VERTEX_MANAGER* currentManager; ///< Currently used VERTEX_MANAGER (for storing VERTEX_ITEMs) VERTEX_MANAGER cachedManager; ///< Container for storing 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 GLUtesselator* tesselator; ///< Pointer to the tesselator @@ -350,20 +360,11 @@ private: int cursorSize; ///< Size of the cursor in pixels GLubyte* cursorShape; ///< Cursor pixel storage GLubyte* cursorSave; ///< Saved cursor pixels - bool isDeleteSavedPixels; ///< Flag for deleting saved pixels 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 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 isUseShader; ///< Should the shaders be used? bool isGrouping; ///< Was a group started? @@ -434,34 +435,6 @@ private: */ 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. * diff --git a/include/gal/opengl/vertex_common.h b/include/gal/opengl/vertex_common.h index a718ef4ea8..ef8c6d2046 100644 --- a/include/gal/opengl/vertex_common.h +++ b/include/gal/opengl/vertex_common.h @@ -43,7 +43,7 @@ enum SHADER_TYPE SHADER_STROKED_CIRCLE, }; -typedef struct VERTEX +typedef struct { GLfloat x, y, z; // Coordinates GLubyte r, g, b, a; // Color diff --git a/include/gal/opengl/vertex_container.h b/include/gal/opengl/vertex_container.h index 1714040022..3cf544c473 100644 --- a/include/gal/opengl/vertex_container.h +++ b/include/gal/opengl/vertex_container.h @@ -34,7 +34,6 @@ namespace KiGfx { -class VERTEX; class VERTEX_ITEM; class SHADER; diff --git a/include/view/view.h b/include/view/view.h index da43b591ca..8df37a162e 100644 --- a/include/view/view.h +++ b/include/view/view.h @@ -30,6 +30,7 @@ #include #include +#include namespace KiGfx { @@ -258,14 +259,14 @@ public: } /** - * Function SetLayerCached() - * Turns on or off the cached parameter of a particular layer. - * @param aLayer: the layer - * @param aCached: the new parameter value + * Function SetLayerTarget() + * Changes the rendering target for a particular layer. + * @param aLayer is the layer. + * @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: bool enabled; ///* is the layer to be rendered? bool isDirty; ///* does it contain any dirty items (updated since last redraw) 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. std::vector dirtyItems; ///* set of dirty items collected since last redraw int renderingOrder; ///* rendering order of this layer int id; ///* layer ID BOX2I extents; ///* sum of bboxes of all 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 diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index 59949e8746..cc21eaf0cf 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -207,7 +207,7 @@ void PCB_BASE_FRAME::SetBoard( BOARD* aBoard ) // so there is no point in caching them 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