OpenGL multitarget rendering (compositing).
This commit is contained in:
parent
a8f4791395
commit
618a5f0e75
|
@ -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})
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 <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;
|
|
@ -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<VERTEX_ITEM> 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 );
|
||||
|
||||
|
|
|
@ -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<LayerItemPair>& 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 );
|
||||
|
|
|
@ -252,6 +252,9 @@ public:
|
|||
/// @copydoc GAL::RestoreScreen()
|
||||
virtual void RestoreScreen();
|
||||
|
||||
/// @copydoc GAL::SetTarget()
|
||||
virtual void SetTarget( RenderTarget aTarget );
|
||||
|
||||
// -------
|
||||
// Cursor
|
||||
// -------
|
||||
|
|
|
@ -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 <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 @@
|
|||
#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_ */
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <math/matrix3x3.h>
|
||||
|
||||
#include <gal/color4d.h>
|
||||
#include <gal/definitions.h>
|
||||
#include <gal/stroke_font.h>
|
||||
#include <newstroke_font.h>
|
||||
|
||||
|
@ -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
|
||||
// -------------
|
||||
|
|
|
@ -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 <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 @@
|
|||
#include <gal/opengl/vertex_manager.h>
|
||||
#include <gal/opengl/vertex_item.h>
|
||||
#include <gal/opengl/noncached_container.h>
|
||||
#include <gal/opengl/opengl_compositor.h>
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/glcanvas.h>
|
||||
|
@ -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<VERTEX_ITEM> > 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.
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
|
||||
namespace KiGfx
|
||||
{
|
||||
class VERTEX;
|
||||
class VERTEX_ITEM;
|
||||
class SHADER;
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <boost/unordered/unordered_map.hpp>
|
||||
|
||||
#include <math/box2.h>
|
||||
#include <gal/definitions.h>
|
||||
|
||||
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<VIEW_ITEM*> 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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue