From 2f0ae47c8ec3cbcf17dab32a0ad2631bf4fd2af2 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 30 Jul 2013 18:29:54 +0200 Subject: [PATCH] Code refactoring. --- common/gal/cairo/cairo_compositor.cpp | 5 +- common/gal/cairo/cairo_gal.cpp | 600 +++++++-------- common/gal/graphics_abstraction_layer.cpp | 31 +- common/gal/opengl/gpu_manager.cpp | 2 +- common/gal/opengl/opengl_compositor.cpp | 4 +- common/gal/opengl/opengl_gal.cpp | 887 ++++++++++------------ common/gal/opengl/shader.cpp | 17 +- common/gal/opengl/vertex_manager.cpp | 11 +- common/view/wx_view_controls.cpp | 1 - include/gal/cairo/cairo_compositor.h | 18 +- include/gal/cairo/cairo_gal.h | 101 +-- include/gal/graphics_abstraction_layer.h | 10 +- include/gal/opengl/cached_container.h | 12 +- include/gal/opengl/opengl_compositor.h | 2 - include/gal/opengl/opengl_gal.h | 209 ++--- include/gal/opengl/vertex_common.h | 7 +- 16 files changed, 857 insertions(+), 1060 deletions(-) diff --git a/common/gal/cairo/cairo_compositor.cpp b/common/gal/cairo/cairo_compositor.cpp index fa6b6918f7..d5b101493a 100644 --- a/common/gal/cairo/cairo_compositor.cpp +++ b/common/gal/cairo/cairo_compositor.cpp @@ -34,7 +34,7 @@ using namespace KiGfx; CAIRO_COMPOSITOR::CAIRO_COMPOSITOR( cairo_t** aMainContext ) : - m_current( 0 ), m_currentContext( aMainContext ), m_mainContext( *aMainContext ) + m_current( 0 ), m_currentContext( aMainContext ), m_mainContext( *aMainContext ) { // Obtain the transformation matrix used in the main context cairo_get_matrix( m_mainContext, &m_matrix ); @@ -69,6 +69,7 @@ unsigned int CAIRO_COMPOSITOR::GetBuffer() { // Pixel storage BitmapPtr bitmap( new unsigned int[m_bufferSize] ); + memset( bitmap.get(), 0x00, m_bufferSize * sizeof(int) ); // Create the Cairo surface @@ -105,6 +106,7 @@ void CAIRO_COMPOSITOR::SetBuffer( unsigned int aBufferHandle ) m_current = aBufferHandle - 1; *m_currentContext = m_buffers[m_current].context; } + #ifdef __WXDEBUG__ else wxLogDebug( wxT( "Tried to use a not existing buffer" ) ); @@ -141,6 +143,7 @@ void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle ) // Restore the transformation matrix cairo_set_matrix( m_mainContext, &m_matrix ); } + #ifdef __WXDEBUG__ else wxLogDebug( wxT( "Tried to use a not existing buffer" ) ); diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp index 6e8a225d93..c7e4f6b8ed 100644 --- a/common/gal/cairo/cairo_gal.cpp +++ b/common/gal/cairo/cairo_gal.cpp @@ -87,117 +87,7 @@ CAIRO_GAL::~CAIRO_GAL() } -void CAIRO_GAL::onPaint( wxPaintEvent& aEvent ) -{ - PostPaint(); -} - - -void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight ) -{ - screenSize = VECTOR2D( aWidth, aHeight ); - - // Recreate the bitmaps - deleteBitmaps(); - allocateBitmaps(); - - SetSize( wxSize( aWidth, aHeight ) ); -} - - -void CAIRO_GAL::skipMouseEvent( wxMouseEvent& aEvent ) -{ - // Post the mouse event to the event listener registered in constructor, if any - if( mouseListener ) - wxPostEvent( mouseListener, aEvent ); -} - - -void CAIRO_GAL::initSurface() -{ - wxASSERT( !isInitialized ); - - // Create the Cairo surface - surface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer, GAL_FORMAT, - screenSize.x, screenSize.y, stride ); - context = cairo_create( surface ); -#ifdef __WXDEBUG__ - cairo_status_t status = cairo_status( context ); - wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, "Cairo context creation error" ); -#endif /* __WXDEBUG__ */ - currentContext = context; - - cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL ); - - // Clear the screen - ClearScreen(); - - // Compute the world <-> screen transformations - ComputeWorldScreenMatrix(); - - cairo_matrix_init( &cairoWorldScreenMatrix, worldScreenMatrix.m_data[0][0], - worldScreenMatrix.m_data[1][0], worldScreenMatrix.m_data[0][1], - worldScreenMatrix.m_data[1][1], worldScreenMatrix.m_data[0][2], - worldScreenMatrix.m_data[1][2] ); - - cairo_set_matrix( context, &cairoWorldScreenMatrix ); - - isSetAttributes = false; - - // Start drawing with a new path - cairo_new_path( context ); - isElementAdded = true; - - cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND ); - cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND ); - - lineWidth = 0; - - isDeleteSavedPixels = true; - isInitialized = true; -} - - -void CAIRO_GAL::deinitSurface() -{ - if( !isInitialized ) - return; - - // Destroy Cairo objects - cairo_destroy( context ); - cairo_surface_destroy( surface ); - - isInitialized = false; -} - - -void CAIRO_GAL::setCompositor() -{ - // Recreate the compositor with the new Cairo context - compositor.reset( new CAIRO_COMPOSITOR( ¤tContext ) ); - compositor->Resize( screenSize.x, screenSize.y ); - - // Prepare buffers - mainBuffer = compositor->GetBuffer(); - overlayBuffer = compositor->GetBuffer(); -} - - -unsigned int CAIRO_GAL::getNewGroupNumber() -{ - wxASSERT_MSG( groups.size() < std::numeric_limits::max(), - wxT( "There are no free slots to store a group" ) ); - - while( groups.find( groupCounter ) != groups.end() ) - { - groupCounter++; - } - - return groupCounter++; -} - - -void CAIRO_GAL::BeginDrawing() throw( int ) +void CAIRO_GAL::BeginDrawing() { initSurface(); setCompositor(); @@ -245,65 +135,6 @@ void CAIRO_GAL::EndDrawing() } -void CAIRO_GAL::SaveScreen() -{ - // Copy the current bitmap to the backup buffer - int offset = 0; - - for( int j = 0; j < screenSize.y; j++ ) - { - for( int i = 0; i < stride; i++ ) - { - bitmapBufferBackup[offset + i] = bitmapBuffer[offset + i]; - offset += stride; - } - } -} - - -void CAIRO_GAL::RestoreScreen() -{ - int offset = 0; - - for( int j = 0; j < screenSize.y; j++ ) - { - for( int i = 0; i < stride; i++ ) - { - bitmapBuffer[offset + i] = bitmapBufferBackup[offset + i]; - offset += stride; - } - } -} - - -void CAIRO_GAL::SetTarget( RenderTarget aTarget ) -{ - // If the compositor is not set, that means that there is a recaching process going on - // and we do not need the compositor now - if( !compositor ) - return; - - // Cairo grouping prevents display of overlapping items on the same layer in the lighter color - cairo_pop_group_to_source( currentContext ); - cairo_paint_with_alpha( currentContext, fillColor.a ); - - switch( aTarget ) - { - default: - case TARGET_CACHED: - case TARGET_NONCACHED: - compositor->SetBuffer( mainBuffer ); - break; - - case TARGET_OVERLAY: - compositor->SetBuffer( overlayBuffer ); - break; - } - - cairo_push_group( currentContext ); -} - - void CAIRO_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) { cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y ); @@ -335,7 +166,7 @@ void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPo cairo_translate( currentContext, aStartPoint.x, aStartPoint.y ); cairo_rotate( currentContext, lineAngle ); - cairo_arc( currentContext, 0.0, 0.0, aWidth / 2.0, M_PI / 2.0, 3.0 * M_PI / 2.0 ); + cairo_arc( currentContext, 0.0, 0.0, aWidth / 2.0, M_PI / 2.0, 3.0 * M_PI / 2.0 ); cairo_arc( currentContext, lineLength, 0.0, aWidth / 2.0, -M_PI / 2.0, M_PI / 2.0 ); cairo_move_to( currentContext, 0.0, aWidth / 2.0 ); @@ -373,12 +204,30 @@ void CAIRO_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aS } +void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) +{ + // Calculate the diagonal points + VECTOR2D diagonalPointA( aEndPoint.x, aStartPoint.y ); + VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y ); + + // The path is composed from 4 segments + cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y ); + cairo_line_to( currentContext, diagonalPointA.x, diagonalPointA.y ); + cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y ); + cairo_line_to( currentContext, diagonalPointB.x, diagonalPointB.y ); + cairo_close_path( currentContext ); + + isElementAdded = true; +} + + void CAIRO_GAL::DrawPolyline( std::deque& aPointList ) { // Iterate over the point list and draw the segments std::deque::const_iterator it = aPointList.begin(); cairo_move_to( currentContext, it->x, it->y ); + for( ++it; it != aPointList.end(); ++it ) { cairo_line_to( currentContext, it->x, it->y ); @@ -394,6 +243,7 @@ void CAIRO_GAL::DrawPolygon( const std::deque& aPointList ) std::deque::const_iterator it = aPointList.begin(); cairo_move_to( currentContext, it->x, it->y ); + for( ++it; it != aPointList.end(); ++it ) { cairo_line_to( currentContext, it->x, it->y ); @@ -403,23 +253,6 @@ void CAIRO_GAL::DrawPolygon( const std::deque& aPointList ) } -void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) -{ - // Calculate the diagonal points - VECTOR2D diagonalPointA( aEndPoint.x, aStartPoint.y ); - VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y ); - - // The path is composed from 4 segments - cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y ); - cairo_line_to( currentContext, diagonalPointA.x, diagonalPointA.y ); - cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y ); - cairo_line_to( currentContext, diagonalPointB.x, diagonalPointB.y ); - cairo_close_path( currentContext ); - - isElementAdded = true; -} - - void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA, const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint ) { @@ -432,9 +265,41 @@ void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControl } -void CAIRO_GAL::SetBackgroundColor( const COLOR4D& aColor ) +void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight ) { - backgroundColor = aColor; + screenSize = VECTOR2D( aWidth, aHeight ); + + // Recreate the bitmaps + deleteBitmaps(); + allocateBitmaps(); + + SetSize( wxSize( aWidth, aHeight ) ); +} + + +bool CAIRO_GAL::Show( bool aShow ) +{ + bool s = wxWindow::Show( aShow ); + + if( aShow ) + wxWindow::Raise(); + + return s; +} + + +void CAIRO_GAL::Flush() +{ + storePath(); +} + + +void CAIRO_GAL::ClearScreen() +{ + cairo_set_source_rgb( currentContext, + backgroundColor.r, backgroundColor.g, backgroundColor.b ); + cairo_rectangle( currentContext, 0.0, 0.0, screenSize.x, screenSize.y ); + cairo_fill( currentContext ); } @@ -528,15 +393,6 @@ void CAIRO_GAL::SetLineWidth( double aLineWidth ) } -void CAIRO_GAL::ClearScreen() -{ - cairo_set_source_rgb( currentContext, - backgroundColor.r, backgroundColor.g, backgroundColor.b ); - cairo_rectangle( currentContext, 0.0, 0.0, screenSize.x, screenSize.y ); - cairo_fill( currentContext ); -} - - void CAIRO_GAL::SetLayerDepth( double aLayerDepth ) { super::SetLayerDepth( aLayerDepth ); @@ -686,35 +542,6 @@ void CAIRO_GAL::EndGroup() } -void CAIRO_GAL::ClearCache() -{ - for( int i = groups.size() - 1; i >= 0; --i ) - { - DeleteGroup( i ); - } -} - - -void CAIRO_GAL::DeleteGroup( int aGroupNumber ) -{ - storePath(); - - // Delete the Cairo paths - std::deque::iterator it, end; - - for( it = groups[aGroupNumber].begin(), end = groups[aGroupNumber].end(); it != end; ++it ) - { - if( it->command == CMD_FILL_PATH || it->command == CMD_STROKE_PATH ) - { - cairo_path_destroy( it->cairoPath ); - } - } - - // Delete the group - groups.erase( aGroupNumber ); -} - - void CAIRO_GAL::DrawGroup( int aGroupNumber ) { // This method implements a small Virtual Machine - all stored commands @@ -828,103 +655,91 @@ void CAIRO_GAL::ChangeGroupDepth( int aGroupNumber, int aDepth ) } -void CAIRO_GAL::Flush() +void CAIRO_GAL::DeleteGroup( int aGroupNumber ) { storePath(); -} + // Delete the Cairo paths + std::deque::iterator it, end; -void CAIRO_GAL::ComputeWorldScreenMatrix() -{ - ComputeWorldScale(); - - worldScreenMatrix.SetIdentity(); - - MATRIX3x3D translation; - translation.SetIdentity(); - translation.SetTranslation( 0.5 * screenSize ); - - MATRIX3x3D scale; - scale.SetIdentity(); - scale.SetScale( VECTOR2D( worldScale, worldScale ) ); - - MATRIX3x3D lookat; - lookat.SetIdentity(); - lookat.SetTranslation( -lookAtPoint ); - - worldScreenMatrix = translation * scale * lookat * worldScreenMatrix; -} - - -void CAIRO_GAL::storePath() -{ - if( isElementAdded ) + for( it = groups[aGroupNumber].begin(), end = groups[aGroupNumber].end(); it != end; ++it ) { - isElementAdded = false; - - if( !isGrouping ) + if( it->command == CMD_FILL_PATH || it->command == CMD_STROKE_PATH ) { - if( isFillEnabled ) - { - cairo_set_source_rgb( currentContext, fillColor.r, fillColor.g, fillColor.b ); - cairo_fill_preserve( currentContext ); - } - - if( isStrokeEnabled ) - { - cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g, strokeColor.b ); - cairo_stroke_preserve( currentContext ); - } + cairo_path_destroy( it->cairoPath ); } - else - { - // Copy the actual path, append it to the global path list - // then check, if the path needs to be stroked/filled and - // add this command to the group list; - if( isStrokeEnabled ) - { - GroupElement groupElement; - groupElement.cairoPath = cairo_copy_path( currentContext ); - groupElement.command = CMD_STROKE_PATH; - currentGroup->push_back( groupElement ); - } + } - if( isFillEnabled ) - { - GroupElement groupElement; - groupElement.cairoPath = cairo_copy_path( currentContext ); - groupElement.command = CMD_FILL_PATH; - currentGroup->push_back( groupElement ); - } - } + // Delete the group + groups.erase( aGroupNumber ); +} - cairo_new_path( currentContext ); + +void CAIRO_GAL::ClearCache() +{ + for( int i = groups.size() - 1; i >= 0; --i ) + { + DeleteGroup( i ); } } -// --------------- -// Cursor handling -// --------------- - - -void CAIRO_GAL::initCursor( int aCursorSize ) +void CAIRO_GAL::SaveScreen() { - cursorPixels = new wxBitmap( aCursorSize, aCursorSize ); - cursorPixelsSaved = new wxBitmap( aCursorSize, aCursorSize ); - cursorSize = aCursorSize; + // Copy the current bitmap to the backup buffer + int offset = 0; - wxMemoryDC cursorShape( *cursorPixels ); + for( int j = 0; j < screenSize.y; j++ ) + { + for( int i = 0; i < stride; i++ ) + { + bitmapBufferBackup[offset + i] = bitmapBuffer[offset + i]; + offset += stride; + } + } +} - cursorShape.SetBackground( *wxTRANSPARENT_BRUSH ); - wxColour color( cursorColor.r * cursorColor.a * 255, cursorColor.g * cursorColor.a * 255, - cursorColor.b * cursorColor.a * 255, 255 ); - wxPen pen = wxPen( color ); - cursorShape.SetPen( pen ); - cursorShape.Clear(); - cursorShape.DrawLine( 0, aCursorSize / 2, aCursorSize, aCursorSize / 2 ); - cursorShape.DrawLine( aCursorSize / 2, 0, aCursorSize / 2, aCursorSize ); +void CAIRO_GAL::RestoreScreen() +{ + int offset = 0; + + for( int j = 0; j < screenSize.y; j++ ) + { + for( int i = 0; i < stride; i++ ) + { + bitmapBuffer[offset + i] = bitmapBufferBackup[offset + i]; + offset += stride; + } + } +} + + +void CAIRO_GAL::SetTarget( RenderTarget aTarget ) +{ + // If the compositor is not set, that means that there is a recaching process going on + // and we do not need the compositor now + if( !compositor ) + return; + + // Cairo grouping prevents display of overlapping items on the same layer in the lighter color + cairo_pop_group_to_source( currentContext ); + cairo_paint_with_alpha( currentContext, fillColor.a ); + + switch( aTarget ) + { + default: + case TARGET_CACHED: + case TARGET_NONCACHED: + compositor->SetBuffer( mainBuffer ); + break; + + case TARGET_OVERLAY: + compositor->SetBuffer( overlayBuffer ); + break; + } + + cairo_push_group( currentContext ); } @@ -975,7 +790,7 @@ void CAIRO_GAL::DrawCursor( VECTOR2D aCursorPosition ) } -void CAIRO_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) +void CAIRO_GAL::drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) { cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y ); cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y ); @@ -984,14 +799,96 @@ void CAIRO_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP } +void CAIRO_GAL::storePath() +{ + if( isElementAdded ) + { + isElementAdded = false; + + if( !isGrouping ) + { + if( isFillEnabled ) + { + cairo_set_source_rgb( currentContext, fillColor.r, fillColor.g, fillColor.b ); + cairo_fill_preserve( currentContext ); + } + + if( isStrokeEnabled ) + { + cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g, + strokeColor.b ); + cairo_stroke_preserve( currentContext ); + } + } + else + { + // Copy the actual path, append it to the global path list + // then check, if the path needs to be stroked/filled and + // add this command to the group list; + if( isStrokeEnabled ) + { + GroupElement groupElement; + groupElement.cairoPath = cairo_copy_path( currentContext ); + groupElement.command = CMD_STROKE_PATH; + currentGroup->push_back( groupElement ); + } + + if( isFillEnabled ) + { + GroupElement groupElement; + groupElement.cairoPath = cairo_copy_path( currentContext ); + groupElement.command = CMD_FILL_PATH; + currentGroup->push_back( groupElement ); + } + } + + cairo_new_path( currentContext ); + } +} + + +void CAIRO_GAL::onPaint( wxPaintEvent& aEvent ) +{ + PostPaint(); +} + + +void CAIRO_GAL::skipMouseEvent( wxMouseEvent& aEvent ) +{ + // Post the mouse event to the event listener registered in constructor, if any + if( mouseListener ) + wxPostEvent( mouseListener, aEvent ); +} + + +void CAIRO_GAL::initCursor( int aCursorSize ) +{ + cursorPixels = new wxBitmap( aCursorSize, aCursorSize ); + cursorPixelsSaved = new wxBitmap( aCursorSize, aCursorSize ); + cursorSize = aCursorSize; + + wxMemoryDC cursorShape( *cursorPixels ); + + cursorShape.SetBackground( *wxTRANSPARENT_BRUSH ); + wxColour color( cursorColor.r * cursorColor.a * 255, cursorColor.g * cursorColor.a * 255, + cursorColor.b * cursorColor.a * 255, 255 ); + wxPen pen = wxPen( color ); + cursorShape.SetPen( pen ); + cursorShape.Clear(); + + cursorShape.DrawLine( 0, aCursorSize / 2, aCursorSize, aCursorSize / 2 ); + cursorShape.DrawLine( aCursorSize / 2, 0, aCursorSize / 2, aCursorSize ); +} + + void CAIRO_GAL::allocateBitmaps() { // Create buffer, use the system independent Cairo context backend stride = cairo_format_stride_for_width( GAL_FORMAT, screenSize.x ); bufferSize = stride * screenSize.y; - bitmapBuffer = new unsigned int[bufferSize]; - bitmapBufferBackup = new unsigned int[bufferSize]; + bitmapBuffer = new unsigned int[bufferSize]; + bitmapBufferBackup = new unsigned int[bufferSize]; wxOutput = new unsigned char[bufferSize * 3]; } @@ -1004,12 +901,83 @@ void CAIRO_GAL::deleteBitmaps() } -bool CAIRO_GAL::Show( bool aShow ) +void CAIRO_GAL::initSurface() { - bool s = wxWindow::Show( aShow ); + wxASSERT( !isInitialized ); - if( aShow ) - wxWindow::Raise(); + // Create the Cairo surface + surface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer, GAL_FORMAT, + screenSize.x, screenSize.y, stride ); + context = cairo_create( surface ); +#ifdef __WXDEBUG__ + cairo_status_t status = cairo_status( context ); + wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, "Cairo context creation error" ); +#endif /* __WXDEBUG__ */ + currentContext = context; - return s; + cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL ); + + // Clear the screen + ClearScreen(); + + // Compute the world <-> screen transformations + ComputeWorldScreenMatrix(); + + cairo_matrix_init( &cairoWorldScreenMatrix, worldScreenMatrix.m_data[0][0], + worldScreenMatrix.m_data[1][0], worldScreenMatrix.m_data[0][1], + worldScreenMatrix.m_data[1][1], worldScreenMatrix.m_data[0][2], + worldScreenMatrix.m_data[1][2] ); + + cairo_set_matrix( context, &cairoWorldScreenMatrix ); + + // Start drawing with a new path + cairo_new_path( context ); + isElementAdded = true; + + cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND ); + cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND ); + + lineWidth = 0; + + isDeleteSavedPixels = true; + isInitialized = true; +} + + +void CAIRO_GAL::deinitSurface() +{ + if( !isInitialized ) + return; + + // Destroy Cairo objects + cairo_destroy( context ); + cairo_surface_destroy( surface ); + + isInitialized = false; +} + + +void CAIRO_GAL::setCompositor() +{ + // Recreate the compositor with the new Cairo context + compositor.reset( new CAIRO_COMPOSITOR( ¤tContext ) ); + compositor->Resize( screenSize.x, screenSize.y ); + + // Prepare buffers + mainBuffer = compositor->GetBuffer(); + overlayBuffer = compositor->GetBuffer(); +} + + +unsigned int CAIRO_GAL::getNewGroupNumber() +{ + wxASSERT_MSG( groups.size() < std::numeric_limits::max(), + wxT( "There are no free slots to store a group" ) ); + + while( groups.find( groupCounter ) != groups.end() ) + { + groupCounter++; + } + + return groupCounter++; } diff --git a/common/gal/graphics_abstraction_layer.cpp b/common/gal/graphics_abstraction_layer.cpp index a3bd5cff0f..2f718647ae 100644 --- a/common/gal/graphics_abstraction_layer.cpp +++ b/common/gal/graphics_abstraction_layer.cpp @@ -63,6 +63,33 @@ GAL::~GAL() } +void GAL::ComputeWorldScreenMatrix() +{ + ComputeWorldScale(); + + worldScreenMatrix.SetIdentity(); + + MATRIX3x3D translation; + translation.SetIdentity(); + translation.SetTranslation( 0.5 * screenSize ); + + MATRIX3x3D scale; + scale.SetIdentity(); + scale.SetScale( VECTOR2D( worldScale, worldScale ) ); + + MATRIX3x3D flip; + flip.SetIdentity(); + flip.SetScale( VECTOR2D( 1.0, 1.0 ) ); + + MATRIX3x3D lookat; + lookat.SetIdentity(); + lookat.SetTranslation( -lookAtPoint ); + + worldScreenMatrix = translation * flip * scale * lookat * worldScreenMatrix; +} + + + void GAL::DrawGrid() { if( !gridVisibility ) @@ -136,7 +163,7 @@ void GAL::DrawGrid() if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridDrawThreshold ) || gridScreenSizeDense > gridDrawThreshold ) { - DrawGridLine( VECTOR2D( gridStartX * gridSize.x, j * gridSize.y ), + drawGridLine( VECTOR2D( gridStartX * gridSize.x, j * gridSize.y ), VECTOR2D( gridEndX * gridSize.x, j * gridSize.y ) ); } } @@ -155,7 +182,7 @@ void GAL::DrawGrid() if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridDrawThreshold ) || gridScreenSizeDense > gridDrawThreshold ) { - DrawGridLine( VECTOR2D( i * gridSize.x, gridStartY * gridSize.y ), + drawGridLine( VECTOR2D( i * gridSize.x, gridStartY * gridSize.y ), VECTOR2D( i * gridSize.x, gridEndY * gridSize.y ) ); } } diff --git a/common/gal/opengl/gpu_manager.cpp b/common/gal/opengl/gpu_manager.cpp index 255d6b0a26..d5d263a930 100644 --- a/common/gal/opengl/gpu_manager.cpp +++ b/common/gal/opengl/gpu_manager.cpp @@ -52,7 +52,7 @@ GPU_MANAGER* GPU_MANAGER::MakeManager( VERTEX_CONTAINER* aContainer ) GPU_MANAGER::GPU_MANAGER( VERTEX_CONTAINER* aContainer ) : - m_isDrawing( false ), m_container( aContainer ), m_shader( NULL ) + m_isDrawing( false ), m_container( aContainer ), m_shader( NULL ) { } diff --git a/common/gal/opengl/opengl_compositor.cpp b/common/gal/opengl/opengl_compositor.cpp index 2ff733e978..91b757cb98 100644 --- a/common/gal/opengl/opengl_compositor.cpp +++ b/common/gal/opengl/opengl_compositor.cpp @@ -104,7 +104,7 @@ unsigned int OPENGL_COMPOSITOR::GetBuffer() wxASSERT( m_initialized ); if( m_buffers.size() >= m_maxBuffers ) - return 0; // Unfortunately we have no more free buffers left + return 0; // Unfortunately we have no more free buffers left // GL_COLOR_ATTACHMENTn are consecutive integers GLuint attachmentPoint = GL_COLOR_ATTACHMENT0 + usedBuffers(); @@ -229,9 +229,11 @@ void OPENGL_COMPOSITOR::clean() { 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 9acb2d7f65..3a94d33e50 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -36,7 +36,6 @@ #endif /* __WXDEBUG__ */ #include -#include #ifndef CALLBACK #define CALLBACK @@ -94,9 +93,6 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, tesselator = gluNewTess(); InitTesselatorCallbacks( tesselator ); gluTessProperty( tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE ); - - // Compute the unit circle vertices and store them in a buffer for faster drawing - computeCircle(); } @@ -111,109 +107,6 @@ OPENGL_GAL::~OPENGL_GAL() } -void OPENGL_GAL::onPaint( wxPaintEvent& aEvent ) -{ - PostPaint(); -} - - -void OPENGL_GAL::ResizeScreen( int aWidth, int aHeight ) -{ - screenSize = VECTOR2D( aWidth, aHeight ); - - // Resize framebuffers - compositor.Resize( aWidth, aHeight ); - isFramebufferInitialized = false; - - wxGLCanvas::SetSize( aWidth, aHeight ); -} - - -void OPENGL_GAL::skipMouseEvent( wxMouseEvent& aEvent ) -{ - // Post the mouse event to the event listener registered in constructor, if any - if( mouseListener ) - wxPostEvent( mouseListener, aEvent ); -} - - -void OPENGL_GAL::SaveScreen() -{ - wxASSERT_MSG( false, wxT( "Not implemented yet" ) ); -} - - -void OPENGL_GAL::RestoreScreen() -{ - 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; - } -} - - -void OPENGL_GAL::initGlew() -{ - // Initialize GLEW library - GLenum err = glewInit(); - - if( GLEW_OK != err ) - { - wxLogError( wxString::FromUTF8( (char*) glewGetErrorString( err ) ) ); - exit( 1 ); - } - else - { - wxLogDebug( wxString( wxT( "Status: Using GLEW " ) ) + - FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) ); - } - - // Check the OpenGL version (minimum 2.1 is required) - if( GLEW_VERSION_2_1 ) - { - wxLogInfo( wxT( "OpenGL Version 2.1 supported." ) ); - } - else - { - wxLogError( wxT( "OpenGL Version 2.1 is not supported!" ) ); - exit( 1 ); - } - - // Framebuffers have to be supported - if( !GLEW_ARB_framebuffer_object ) - { - wxLogError( wxT( "Framebuffer objects are not supported!" ) ); - exit( 1 ); - } - - // Vertex buffer have to be supported - if( !GLEW_ARB_vertex_buffer_object ) - { - wxLogError( wxT( "Vertex buffer objects are not supported!" ) ); - exit( 1 ); - } - - isGlewInitialized = true; -} - - void OPENGL_GAL::BeginDrawing() { SetCurrent( *glContext ); @@ -232,7 +125,8 @@ void OPENGL_GAL::BeginDrawing() 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 ); + glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y, + -depthRange.x, -depthRange.y ); // Prepare rendering target buffers compositor.Initialize(); @@ -301,7 +195,7 @@ void OPENGL_GAL::BeginDrawing() compositor.ClearBuffer(); compositor.SetBuffer( overlayBuffer ); compositor.ClearBuffer(); - compositor.SetBuffer( 0 ); // Unbind buffers + compositor.SetBuffer( 0 ); // Unbind buffers nonCachedManager.Clear(); overlayManager.Clear(); @@ -333,37 +227,16 @@ void OPENGL_GAL::EndDrawing() } -inline void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) +void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) { - VECTOR2D startEndVector = aEndPoint - aStartPoint; - double lineLength = startEndVector.EuclideanNorm(); - double scale = 0.5 * lineWidth / lineLength; + const VECTOR2D startEndVector = aEndPoint - aStartPoint; + double lineAngle = startEndVector.Angle(); - if( lineLength <= 0.0 ) - return; + drawLineQuad( aStartPoint, aEndPoint ); - // The perpendicular vector also needs transformations - glm::vec4 vector = currentManager->GetTransformation() * - glm::vec4( -startEndVector.y * scale, startEndVector.x * scale, 0.0, 0.0 ); - - // Line width is maintained by the vertex shader - currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth ); - currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v0 - - currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth ); - currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v1 - - currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth ); - currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v3 - - currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth ); - currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v0 - - currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth ); - currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v3 - - currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth ); - currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v2 + // Line caps + drawFilledSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 ); + drawFilledSemiCircle( aEndPoint, lineWidth / 2, lineAngle - M_PI / 2 ); } @@ -414,93 +287,6 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP } -unsigned int OPENGL_GAL::getNewGroupNumber() -{ - wxASSERT_MSG( groups.size() < std::numeric_limits::max(), - wxT( "There are no free slots to store a group" ) ); - - while( groups.find( groupCounter ) != groups.end() ) - { - groupCounter++; - } - - return groupCounter++; -} - - -void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) -{ - const VECTOR2D startEndVector = aEndPoint - aStartPoint; - double lineAngle = startEndVector.Angle(); - - drawLineQuad( aStartPoint, aEndPoint ); - - // Line caps - drawFilledSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 ); - drawFilledSemiCircle( aEndPoint, lineWidth / 2, lineAngle - M_PI / 2 ); -} - - -void OPENGL_GAL::DrawPolyline( std::deque& aPointList ) -{ - std::deque::const_iterator it = aPointList.begin(); - - // Start from the second point - for( it++; it != aPointList.end(); it++ ) - { - const VECTOR2D startEndVector = ( *it - *( it - 1 ) ); - double lineAngle = startEndVector.Angle(); - - drawLineQuad( *( it - 1 ), *it ); - - // There is no need to draw line caps on both ends of polyline's segments - drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle + M_PI / 2 ); - } - - // ..and now - draw the ending cap - const VECTOR2D startEndVector = ( *( it - 1 ) - *( it - 2 ) ); - double lineAngle = startEndVector.Angle(); - drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle - M_PI / 2 ); -} - - -void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) -{ - // Compute the diagonal points of the rectangle - VECTOR2D diagonalPointA( aEndPoint.x, aStartPoint.y ); - VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y ); - - // Stroke the outline - if( isStrokeEnabled ) - { - currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); - - std::deque pointList; - pointList.push_back( aStartPoint ); - pointList.push_back( diagonalPointA ); - pointList.push_back( aEndPoint ); - pointList.push_back( diagonalPointB ); - pointList.push_back( aStartPoint ); - DrawPolyline( pointList ); - } - - // Fill the rectangle - if( isFillEnabled ) - { - currentManager->Shader( SHADER_NONE ); - currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); - - currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); - currentManager->Vertex( diagonalPointA.x, diagonalPointA.y, layerDepth ); - currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); - - currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); - currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); - currentManager->Vertex( diagonalPointB.x, diagonalPointB.y, layerDepth ); - } -} - - void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) { if( isFillEnabled ) @@ -508,21 +294,21 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); /* 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]). - Shader uses this coordinates to determine if fragments are inside the circle or not. - v2 - /\ - //\\ - v0 /_\/_\ v1 - */ + * 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 circle or not. + * v2 + * /\ + * //\\ + * v0 /_\/_\ v1 + */ currentManager->Shader( SHADER_FILLED_CIRCLE, 1.0 ); currentManager->Vertex( aCenterPoint.x - aRadius * sqrt( 3.0f ), // v0 - aCenterPoint.y - aRadius, layerDepth ); + aCenterPoint.y - aRadius, layerDepth ); currentManager->Shader( SHADER_FILLED_CIRCLE, 2.0 ); - currentManager->Vertex( aCenterPoint.x + aRadius* sqrt( 3.0f ), // v1 - aCenterPoint.y - aRadius, layerDepth ); + 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, // v2 @@ -534,23 +320,23 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); /* 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. - v2 - /\ - //\\ - v0 /_\/_\ v1 - */ + * 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. + * v2 + * /\ + * //\\ + * v0 /_\/_\ v1 + */ double outerRadius = aRadius + ( lineWidth / 2 ); currentManager->Shader( SHADER_STROKED_CIRCLE, 1.0, aRadius, lineWidth ); currentManager->Vertex( aCenterPoint.x - outerRadius * sqrt( 3.0f ), // v0 - aCenterPoint.y - outerRadius, layerDepth ); + aCenterPoint.y - outerRadius, layerDepth ); currentManager->Shader( SHADER_STROKED_CIRCLE, 2.0, aRadius, lineWidth ); currentManager->Vertex( aCenterPoint.x + outerRadius * sqrt( 3.0f ), // v1 - aCenterPoint.y - outerRadius, layerDepth ); + aCenterPoint.y - outerRadius, layerDepth ); currentManager->Shader( SHADER_STROKED_CIRCLE, 3.0, aRadius, lineWidth ); currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + outerRadius * 2.0f, // v2 @@ -559,84 +345,6 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) } -void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ) -{ - if( isFillEnabled ) - { - currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); - drawFilledSemiCircle( aCenterPoint, aRadius, aAngle ); - } - - if( isStrokeEnabled ) - { - currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); - drawStrokedSemiCircle( aCenterPoint, aRadius, aAngle ); - } -} - - -void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, - double aAngle ) -{ - Save(); - 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 - (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 - /\ - /__\ - v0 //__\\ v1 - */ - currentManager->Shader( SHADER_FILLED_CIRCLE, 4.0f ); - 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->Shader( SHADER_FILLED_CIRCLE, 6.0f ); - currentManager->Vertex( 0.0f, aRadius * 2.0f, layerDepth ); // v2 - - Restore(); -} - - -void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, - double aAngle ) -{ - double outerRadius = aRadius + ( lineWidth / 2 ); - - Save(); - 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 - (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. - v2 - /\ - /__\ - v0 //__\\ v1 - */ - currentManager->Shader( SHADER_STROKED_CIRCLE, 4.0f, aRadius, lineWidth ); - 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->Shader( SHADER_STROKED_CIRCLE, 6.0f, aRadius, lineWidth ); - currentManager->Vertex( 0.0f, outerRadius * 2.0f, layerDepth ); // v2 - - Restore(); -} - - -// FIXME Optimize void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, double aEndAngle ) { @@ -700,33 +408,64 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a } -struct OGLPOINT +void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) { - OGLPOINT() : - x( 0.0 ), y( 0.0 ), z( 0.0 ) - {} + // Compute the diagonal points of the rectangle + VECTOR2D diagonalPointA( aEndPoint.x, aStartPoint.y ); + VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y ); - OGLPOINT( const char* fastest ) + // Stroke the outline + if( isStrokeEnabled ) { - // do nothing for fastest speed, and keep inline + currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); + + std::deque pointList; + pointList.push_back( aStartPoint ); + pointList.push_back( diagonalPointA ); + pointList.push_back( aEndPoint ); + pointList.push_back( diagonalPointB ); + pointList.push_back( aStartPoint ); + DrawPolyline( pointList ); } - OGLPOINT( const VECTOR2D& aPoint ) : - x( aPoint.x ), y( aPoint.y ), z( 0.0 ) - {} - - OGLPOINT& operator=( const VECTOR2D& aPoint ) + // Fill the rectangle + if( isFillEnabled ) { - x = aPoint.x; - y = aPoint.y; - z = 0.0; - return *this; + currentManager->Shader( SHADER_NONE ); + currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); + + currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); + currentManager->Vertex( diagonalPointA.x, diagonalPointA.y, layerDepth ); + currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); + + currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); + currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); + currentManager->Vertex( diagonalPointB.x, diagonalPointB.y, layerDepth ); + } +} + + +void OPENGL_GAL::DrawPolyline( std::deque& aPointList ) +{ + std::deque::const_iterator it = aPointList.begin(); + + // Start from the second point + for( it++; it != aPointList.end(); it++ ) + { + const VECTOR2D startEndVector = ( *it - *( it - 1 ) ); + double lineAngle = startEndVector.Angle(); + + drawLineQuad( *( it - 1 ), *it ); + + // There is no need to draw line caps on both ends of polyline's segments + drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle + M_PI / 2 ); } - GLdouble x; - GLdouble y; - GLdouble z; -}; + // ..and now - draw the ending cap + const VECTOR2D startEndVector = ( *( it - 1 ) - *( it - 2 ) ); + double lineAngle = startEndVector.Angle(); + drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle - M_PI / 2 ); +} void OPENGL_GAL::DrawPolygon( const std::deque& aPointList ) @@ -808,34 +547,32 @@ void OPENGL_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aContro } -void OPENGL_GAL::SetStrokeColor( const COLOR4D& aColor ) +void OPENGL_GAL::ResizeScreen( int aWidth, int aHeight ) { - isSetAttributes = true; - strokeColor = aColor; + screenSize = VECTOR2D( aWidth, aHeight ); - // This is the default drawing color - currentManager->Color( aColor.r, aColor.g, aColor.b, aColor.a ); + // Resize framebuffers + compositor.Resize( aWidth, aHeight ); + isFramebufferInitialized = false; + + wxGLCanvas::SetSize( aWidth, aHeight ); } -void OPENGL_GAL::SetFillColor( const COLOR4D& aColor ) +bool OPENGL_GAL::Show( bool aShow ) { - isSetAttributes = true; - fillColor = aColor; + bool s = wxGLCanvas::Show( aShow ); + + if( aShow ) + wxGLCanvas::Raise(); + + return s; } -void OPENGL_GAL::SetBackgroundColor( const COLOR4D& aColor ) +void OPENGL_GAL::Flush() { - isSetAttributes = true; - backgroundColor = aColor; -} - - -void OPENGL_GAL::SetLineWidth( double aLineWidth ) -{ - isSetAttributes = true; - lineWidth = aLineWidth; + glFlush(); } @@ -847,6 +584,15 @@ void OPENGL_GAL::ClearScreen() } +void OPENGL_GAL::SetStrokeColor( const COLOR4D& aColor ) +{ + strokeColor = aColor; + + // This is the default drawing color + currentManager->Color( aColor.r, aColor.g, aColor.b, aColor.a ); +} + + void OPENGL_GAL::Transform( MATRIX3x3D aTransformation ) { GLdouble matrixData[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; @@ -883,12 +629,6 @@ void OPENGL_GAL::Scale( const VECTOR2D& aScale ) } -void OPENGL_GAL::Flush() -{ - glFlush(); -} - - void OPENGL_GAL::Save() { currentManager->PushMatrix(); @@ -919,19 +659,6 @@ void OPENGL_GAL::EndGroup() } -void OPENGL_GAL::ClearCache() -{ - groups.clear(); - cachedManager.Clear(); -} - - -void OPENGL_GAL::DeleteGroup( int aGroupNumber ) -{ - groups.erase( aGroupNumber ); -} - - void OPENGL_GAL::DrawGroup( int aGroupNumber ) { cachedManager.DrawItem( *groups[aGroupNumber] ); @@ -950,126 +677,51 @@ void OPENGL_GAL::ChangeGroupDepth( int aGroupNumber, int aDepth ) } -void OPENGL_GAL::computeCircle() +void OPENGL_GAL::DeleteGroup( int aGroupNumber ) { - VERTEX* vertex = circleContainer.Allocate( CIRCLE_POINTS ); + groups.erase( aGroupNumber ); +} - // Compute the circle points for a given number of segments - for( int i = 0; i < CIRCLE_POINTS; ++i ) + +void OPENGL_GAL::ClearCache() +{ + groups.clear(); + cachedManager.Clear(); +} + + +void OPENGL_GAL::SaveScreen() +{ + wxASSERT_MSG( false, wxT( "Not implemented yet" ) ); +} + + +void OPENGL_GAL::RestoreScreen() +{ + wxASSERT_MSG( false, wxT( "Not implemented yet" ) ); +} + + +void OPENGL_GAL::SetTarget( RenderTarget aTarget ) +{ + switch( aTarget ) { - vertex->x = 0.0f; - vertex->y = 0.0f; - vertex->z = 0.0f; - vertex++; + default: + case TARGET_CACHED: + currentManager = &cachedManager; + break; - vertex->x = cos( 2.0 * M_PI / CIRCLE_POINTS * i ); - vertex->y = sin( 2.0 * M_PI / CIRCLE_POINTS * i ); - vertex->z = 0.0f; - vertex++; + case TARGET_NONCACHED: + currentManager = &nonCachedManager; + break; - vertex->x = cos( 2.0 * M_PI / CIRCLE_POINTS * ( i + 1 ) ); - vertex->y = sin( 2.0 * M_PI / CIRCLE_POINTS * ( i + 1 ) ); - vertex->z = 0.0f; - vertex++; + case TARGET_OVERLAY: + currentManager = &overlayManager; + break; } } -void OPENGL_GAL::ComputeWorldScreenMatrix() -{ - ComputeWorldScale(); - - worldScreenMatrix.SetIdentity(); - - MATRIX3x3D translation; - translation.SetIdentity(); - translation.SetTranslation( 0.5 * screenSize ); - - MATRIX3x3D scale; - scale.SetIdentity(); - scale.SetScale( VECTOR2D( worldScale, worldScale ) ); - - MATRIX3x3D flip; - flip.SetIdentity(); - flip.SetScale( VECTOR2D( 1.0, 1.0 ) ); - - MATRIX3x3D lookat; - lookat.SetIdentity(); - lookat.SetTranslation( -lookAtPoint ); - - worldScreenMatrix = translation * flip * scale * lookat * worldScreenMatrix; -} - - -// ------------------------------------- -// Callback functions for the tesselator -// ------------------------------------- - -// Compare Redbook Chapter 11 - - -void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData ) -{ - GLdouble* vertex = static_cast( aVertexPtr ); - OPENGL_GAL::TessParams* param = static_cast( aData ); - VERTEX_MANAGER* vboManager = param->vboManager; - - if( vboManager ) - vboManager->Vertex( vertex[0], vertex[1], vertex[2] ); -} - - -void CALLBACK CombineCallback( GLdouble coords[3], - GLdouble* vertex_data[4], - GLfloat weight[4], GLdouble** dataOut, void* aData ) -{ - GLdouble* vertex = new GLdouble[3]; - OPENGL_GAL::TessParams* param = static_cast( aData ); - - // Save the pointer so we can delete it later - param->intersectPoints.push_back( vertex ); - - memcpy( vertex, coords, 3 * sizeof(GLdouble) ); - - *dataOut = vertex; -} - - -void CALLBACK EdgeCallback(void) -{ - // This callback is needed to force GLU tesselator to use triangles only -} - - -void CALLBACK ErrorCallback( GLenum aErrorCode ) -{ - const GLubyte* estring; - - estring = gluErrorString( aErrorCode ); - wxLogError( wxT( "Tessellation Error: %s" ), (char*) estring ); -} - - -void InitTesselatorCallbacks( GLUtesselator* aTesselator ) -{ - gluTessCallback( aTesselator, GLU_TESS_VERTEX_DATA, ( void (CALLBACK*)() )VertexCallback ); - gluTessCallback( aTesselator, GLU_TESS_COMBINE_DATA, ( void (CALLBACK*)() )CombineCallback ); - gluTessCallback( aTesselator, GLU_TESS_EDGE_FLAG, ( void (CALLBACK*)() )EdgeCallback ); - gluTessCallback( aTesselator, GLU_TESS_ERROR_DATA, ( void (CALLBACK*)() )ErrorCallback ); -} - - -// --------------- -// Cursor handling -// --------------- - - -void OPENGL_GAL::initCursor( int aCursorSize ) -{ - cursorSize = aCursorSize; -} - - VECTOR2D OPENGL_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition ) { VECTOR2D cursorPosition = aCursorPosition; @@ -1083,7 +735,7 @@ VECTOR2D OPENGL_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition ) void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition ) { - wxLogWarning( wxT( "Not tested ") ); + wxLogWarning( wxT( "Not tested" ) ); SetCurrent( *glContext ); @@ -1096,8 +748,8 @@ void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition ) aCursorPosition = worldScreenMatrix * cursorPositionWorld; // Switch to the main framebuffer and blit the scene - //glBindFramebuffer( GL_FRAMEBUFFER, 0 ); - //glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + // glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + // glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); @@ -1140,7 +792,7 @@ void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition ) } -void OPENGL_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) +void OPENGL_GAL::drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) { compositor.SetBuffer( mainBuffer ); @@ -1165,12 +817,247 @@ void OPENGL_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd } -bool OPENGL_GAL::Show( bool aShow ) +inline void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) { - bool s = wxGLCanvas::Show( aShow ); + VECTOR2D startEndVector = aEndPoint - aStartPoint; + double lineLength = startEndVector.EuclideanNorm(); + double scale = 0.5 * lineWidth / lineLength; - if( aShow ) - wxGLCanvas::Raise(); + if( lineLength <= 0.0 ) + return; - return s; + // The perpendicular vector also needs transformations + glm::vec4 vector = currentManager->GetTransformation() * + glm::vec4( -startEndVector.y * scale, startEndVector.x * scale, 0.0, 0.0 ); + + // Line width is maintained by the vertex shader + currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth ); + currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v0 + + currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth ); + currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v1 + + currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth ); + currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v3 + + currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth ); + currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v0 + + currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth ); + currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v3 + + currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth ); + currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v2 +} + + +void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ) +{ + if( isFillEnabled ) + { + currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); + drawFilledSemiCircle( aCenterPoint, aRadius, aAngle ); + } + + if( isStrokeEnabled ) + { + currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); + drawStrokedSemiCircle( aCenterPoint, aRadius, aAngle ); + } +} + + +void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, + double aAngle ) +{ + Save(); + 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 + * (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 + * /\ + * /__\ + * v0 //__\\ v1 + */ + currentManager->Shader( SHADER_FILLED_CIRCLE, 4.0f ); + 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->Shader( SHADER_FILLED_CIRCLE, 6.0f ); + currentManager->Vertex( 0.0f, aRadius * 2.0f, layerDepth ); // v2 + + Restore(); +} + + +void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, + double aAngle ) +{ + double outerRadius = aRadius + ( lineWidth / 2 ); + + Save(); + 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 + * (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. + * v2 + * /\ + * /__\ + * v0 //__\\ v1 + */ + currentManager->Shader( SHADER_STROKED_CIRCLE, 4.0f, aRadius, lineWidth ); + 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->Shader( SHADER_STROKED_CIRCLE, 6.0f, aRadius, lineWidth ); + currentManager->Vertex( 0.0f, outerRadius * 2.0f, layerDepth ); // v2 + + Restore(); +} + + +void OPENGL_GAL::onPaint( wxPaintEvent& aEvent ) +{ + PostPaint(); +} + + +void OPENGL_GAL::skipMouseEvent( wxMouseEvent& aEvent ) +{ + // Post the mouse event to the event listener registered in constructor, if any + if( mouseListener ) + wxPostEvent( mouseListener, aEvent ); +} + + +void OPENGL_GAL::initGlew() +{ + // Initialize GLEW library + GLenum err = glewInit(); + + if( GLEW_OK != err ) + { + wxLogError( wxString::FromUTF8( (char*) glewGetErrorString( err ) ) ); + exit( 1 ); + } + else + { + wxLogDebug( wxString( wxT( "Status: Using GLEW " ) ) + + FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) ); + } + + // Check the OpenGL version (minimum 2.1 is required) + if( GLEW_VERSION_2_1 ) + { + wxLogInfo( wxT( "OpenGL Version 2.1 supported." ) ); + } + else + { + wxLogError( wxT( "OpenGL Version 2.1 is not supported!" ) ); + exit( 1 ); + } + + // Framebuffers have to be supported + if( !GLEW_ARB_framebuffer_object ) + { + wxLogError( wxT( "Framebuffer objects are not supported!" ) ); + exit( 1 ); + } + + // Vertex buffer have to be supported + if( !GLEW_ARB_vertex_buffer_object ) + { + wxLogError( wxT( "Vertex buffer objects are not supported!" ) ); + exit( 1 ); + } + + isGlewInitialized = true; +} + + +void OPENGL_GAL::initCursor( int aCursorSize ) +{ + cursorSize = aCursorSize; +} + + +unsigned int OPENGL_GAL::getNewGroupNumber() +{ + wxASSERT_MSG( groups.size() < std::numeric_limits::max(), + wxT( "There are no free slots to store a group" ) ); + + while( groups.find( groupCounter ) != groups.end() ) + { + groupCounter++; + } + + return groupCounter++; +} + + +// ------------------------------------- +// Callback functions for the tesselator +// ------------------------------------- + +// Compare Redbook Chapter 11 +void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData ) +{ + GLdouble* vertex = static_cast( aVertexPtr ); + OPENGL_GAL::TessParams* param = static_cast( aData ); + VERTEX_MANAGER* vboManager = param->vboManager; + + if( vboManager ) + vboManager->Vertex( vertex[0], vertex[1], vertex[2] ); +} + + +void CALLBACK CombineCallback( GLdouble coords[3], + GLdouble* vertex_data[4], + GLfloat weight[4], GLdouble** dataOut, void* aData ) +{ + GLdouble* vertex = new GLdouble[3]; + OPENGL_GAL::TessParams* param = static_cast( aData ); + + // Save the pointer so we can delete it later + param->intersectPoints.push_back( vertex ); + + memcpy( vertex, coords, 3 * sizeof(GLdouble) ); + + *dataOut = vertex; +} + + +void CALLBACK EdgeCallback() +{ + // This callback is needed to force GLU tesselator to use triangles only +} + + +void CALLBACK ErrorCallback( GLenum aErrorCode ) +{ + const GLubyte* estring; + + estring = gluErrorString( aErrorCode ); + wxLogError( wxT( "Tessellation Error: %s" ), (char*) estring ); +} + + +void InitTesselatorCallbacks( GLUtesselator* aTesselator ) +{ + gluTessCallback( aTesselator, GLU_TESS_VERTEX_DATA, ( void (CALLBACK*)() )VertexCallback ); + gluTessCallback( aTesselator, GLU_TESS_COMBINE_DATA, ( void (CALLBACK*)() )CombineCallback ); + gluTessCallback( aTesselator, GLU_TESS_EDGE_FLAG, ( void (CALLBACK*)() )EdgeCallback ); + gluTessCallback( aTesselator, GLU_TESS_ERROR_DATA, ( void (CALLBACK*)() )ErrorCallback ); } diff --git a/common/gal/opengl/shader.cpp b/common/gal/opengl/shader.cpp index a535f1be69..5fbd8378da 100644 --- a/common/gal/opengl/shader.cpp +++ b/common/gal/opengl/shader.cpp @@ -37,12 +37,12 @@ using namespace KiGfx; SHADER::SHADER() : - isProgramCreated( false ), - isShaderLinked( false ), - active( false ), - maximumVertices( 4 ), - geomInputType( GL_LINES ), - geomOutputType( GL_LINES ) + isProgramCreated( false ), + isShaderLinked( false ), + active( false ), + maximumVertices( 4 ), + geomInputType( GL_LINES ), + geomOutputType( GL_LINES ) { } @@ -97,7 +97,8 @@ bool SHADER::Link() programInfo( programNumber ); // Check the Link state - glGetObjectParameterivARB( programNumber, GL_OBJECT_LINK_STATUS_ARB, (GLint*) &isShaderLinked ); + glGetObjectParameterivARB( programNumber, GL_OBJECT_LINK_STATUS_ARB, + (GLint*) &isShaderLinked ); #ifdef __WXDEBUG__ if( !isShaderLinked ) @@ -253,6 +254,7 @@ bool SHADER::addSource( const std::string& aShaderSource, ShaderType aShaderType glCompileShader( shaderNumber ); GLint status; glGetShaderiv( shaderNumber, GL_COMPILE_STATUS, &status ); + if( status != GL_TRUE ) { wxLogError( wxT( "Shader compilation error" ) ); @@ -275,4 +277,3 @@ bool SHADER::addSource( const std::string& aShaderSource, ShaderType aShaderType return true; } - diff --git a/common/gal/opengl/vertex_manager.cpp b/common/gal/opengl/vertex_manager.cpp index 7ffdd74922..876a793241 100644 --- a/common/gal/opengl/vertex_manager.cpp +++ b/common/gal/opengl/vertex_manager.cpp @@ -37,7 +37,7 @@ using namespace KiGfx; VERTEX_MANAGER::VERTEX_MANAGER( bool aCached ) : - m_noTransform( true ), m_transform( 1.0f ) + m_noTransform( true ), m_transform( 1.0f ) { m_container.reset( VERTEX_CONTAINER::MakeContainer( aCached ) ); m_gpu.reset( GPU_MANAGER::MakeManager( m_container.get() ) ); @@ -52,6 +52,7 @@ void VERTEX_MANAGER::Vertex( GLfloat aX, GLfloat aY, GLfloat aZ ) const { // Obtain the pointer to the vertex in the currently used container VERTEX* newVertex = m_container->Allocate( 1 ); + if( newVertex == NULL ) { wxLogError( wxT( "Vertex allocation error" ) ); @@ -66,6 +67,7 @@ void VERTEX_MANAGER::Vertices( const VERTEX aVertices[], unsigned int aSize ) co { // Obtain pointer to the vertex in currently used container VERTEX* newVertex = m_container->Allocate( aSize ); + if( newVertex == NULL ) { wxLogError( wxT( "Vertex allocation error" ) ); @@ -95,7 +97,7 @@ void VERTEX_MANAGER::FreeItem( VERTEX_ITEM& aItem ) const void VERTEX_MANAGER::ChangeItemColor( const VERTEX_ITEM& aItem, const COLOR4D& aColor ) const { - unsigned int size = aItem.GetSize(); + unsigned int size = aItem.GetSize(); unsigned int offset = aItem.GetOffset(); VERTEX* vertex = m_container->GetVertices( offset ); @@ -114,7 +116,7 @@ void VERTEX_MANAGER::ChangeItemColor( const VERTEX_ITEM& aItem, const COLOR4D& a void VERTEX_MANAGER::ChangeItemDepth( const VERTEX_ITEM& aItem, GLfloat aDepth ) const { - unsigned int size = aItem.GetSize(); + unsigned int size = aItem.GetSize(); unsigned int offset = aItem.GetOffset(); VERTEX* vertex = m_container->GetVertices( offset ); @@ -131,7 +133,7 @@ void VERTEX_MANAGER::ChangeItemDepth( const VERTEX_ITEM& aItem, GLfloat aDepth ) VERTEX* VERTEX_MANAGER::GetVertices( const VERTEX_ITEM& aItem ) const { if( aItem.GetSize() == 0 ) - return NULL; // The item is not stored in the container + return NULL; // The item is not stored in the container return m_container->GetVertices( aItem.GetOffset() ); } @@ -158,6 +160,7 @@ void VERTEX_MANAGER::BeginDrawing() const void VERTEX_MANAGER::DrawItem( const VERTEX_ITEM& aItem ) const { int size = aItem.GetSize(); + if( size > 0 ) { int offset = aItem.GetOffset(); diff --git a/common/view/wx_view_controls.cpp b/common/view/wx_view_controls.cpp index a4b56d0052..43727c376b 100644 --- a/common/view/wx_view_controls.cpp +++ b/common/view/wx_view_controls.cpp @@ -85,7 +85,6 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& event ) else scrollSpeed = scrollVec.y; - VECTOR2D t = m_view->GetScreenPixelSize(); VECTOR2D delta( event.ControlDown() ? -scrollSpeed : 0.0, event.ShiftDown() ? -scrollSpeed : 0.0 ); diff --git a/include/gal/cairo/cairo_compositor.h b/include/gal/cairo/cairo_compositor.h index 24b730b28c..b638b56a0a 100644 --- a/include/gal/cairo/cairo_compositor.h +++ b/include/gal/cairo/cairo_compositor.h @@ -38,7 +38,6 @@ namespace KiGfx { - class CAIRO_COMPOSITOR : public COMPOSITOR { public: @@ -67,25 +66,25 @@ protected: typedef boost::shared_array BitmapPtr; typedef struct { - cairo_t* context; ///< Main texture handle - cairo_surface_t* surface; ///< Point to which an image from texture is attached - BitmapPtr bitmap; ///< Pixel storage + cairo_t* context; ///< Main texture handle + cairo_surface_t* surface; ///< Point to which an image from texture is attached + BitmapPtr bitmap; ///< Pixel storage } CAIRO_BUFFER; - unsigned int m_current; ///< Currently used buffer handle + unsigned int m_current; ///< Currently used buffer handle typedef std::deque CAIRO_BUFFERS; /// Pointer to the current context, so it can be changed - cairo_t** m_currentContext; + cairo_t** m_currentContext; /// Rendering target used for compositing (the main display) - cairo_t* m_mainContext; + cairo_t* m_mainContext; /// Transformation matrix - cairo_matrix_t m_matrix; + cairo_matrix_t m_matrix; /// Stores information about initialized buffers - CAIRO_BUFFERS m_buffers; + CAIRO_BUFFERS m_buffers; unsigned int m_stride; ///< Stride to use given the desired format and width unsigned int m_bufferSize; ///< Amount of memory needed to store a buffer @@ -102,7 +101,6 @@ protected: return m_buffers.size(); } }; - } // namespace KiGfx #endif /* COMPOSITOR_H_ */ diff --git a/include/gal/cairo/cairo_gal.h b/include/gal/cairo/cairo_gal.h index df3d977502..14d4ca9827 100644 --- a/include/gal/cairo/cairo_gal.h +++ b/include/gal/cairo/cairo_gal.h @@ -45,9 +45,6 @@ #endif #endif -#define EXCEPTION_ZERO_CLIENT_RECTANGLE 0 -#define EXCEPTION_ZERO_CONTEXT 1 - /** * @brief Class CAIRO_GAL is the cairo implementation of the graphics abstraction layer. * @@ -92,7 +89,7 @@ public: // --------------- /// @copydoc GAL::BeginDrawing() - virtual void BeginDrawing() throw (int); + virtual void BeginDrawing(); /// @copydoc GAL::EndDrawing() virtual void EndDrawing(); @@ -103,19 +100,19 @@ public: /// @copydoc GAL::DrawSegment() virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth ); - /// @copydoc GAL::DrawPolyline() - virtual void DrawPolyline( std::deque& aPointList ); - /// @copydoc GAL::DrawCircle() virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ); /// @copydoc GAL::DrawArc() - virtual void - DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, double aEndAngle ); + virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius, + double aStartAngle, double aEndAngle ); /// @copydoc GAL::DrawRectangle() virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); + /// @copydoc GAL::DrawPolyline() + virtual void DrawPolyline( std::deque& aPointList ); + /// @copydoc GAL::DrawPolygon() virtual void DrawPolygon( const std::deque& aPointList ); @@ -149,24 +146,15 @@ public: /// @copydoc GAL::SetIsStroke() virtual void SetIsStroke( bool aIsStrokeEnabled ); - /// @copydoc GAL::SetFillColor() - virtual void SetFillColor( const COLOR4D& aColor ); - /// @copydoc GAL::SetStrokeColor() virtual void SetStrokeColor( const COLOR4D& aColor ); - /// @copydoc GAL::GetStrokeColor() - COLOR4D GetStrokeColor(); - - /// @copydoc GAL::SetBackgroundColor() - virtual void SetBackgroundColor( const COLOR4D& aColor ); + /// @copydoc GAL::SetFillColor() + virtual void SetFillColor( const COLOR4D& aColor ); /// @copydoc GAL::SetLineWidth() virtual void SetLineWidth( double aLineWidth ); - /// @copydoc GAL::GetLineWidth() - double GetLineWidth(); - /// @copydoc GAL::SetLayerDepth() virtual void SetLayerDepth( double aLayerDepth ); @@ -221,33 +209,6 @@ public: // Handling the world <-> screen transformation // -------------------------------------------------------- - /// @copydoc GAL::ComputeWorldScreenMatrix() - virtual void ComputeWorldScreenMatrix(); - - /// @copydoc GAL::GetWorldScreenMatrix() - MATRIX3x3D GetWorldScreenMatrix(); - - /// @copydoc GAL::SetWorldScreenMatrix() - void SetWorldScreenMatrix( MATRIX3x3D aMatrix ); - - /// @copydoc GAL::SetWorldUnitLength() - void SetWorldUnitLength( double aWorldUnitLength ); - - /// @copydoc GAL::SetScreenDPI() - void SetScreenDPI( double aScreenDPI ); - - /// @copydoc GAL::SetLookAtPoint() - void SetLookAtPoint( const VECTOR2D& aPoint ); - - /// @copydoc GAL::GetLookAtPoint() - VECTOR2D GetLookAtPoint(); - - /// @copydoc GAL::SetZoomFactor() - void SetZoomFactor( double aZoomFactor ); - - /// @copydoc GAL::GetZoomFactor() - double GetZoomFactor(); - /// @copydoc GAL::SaveScreen() virtual void SaveScreen(); @@ -264,9 +225,6 @@ public: /// @copydoc GAL::ComputeCursorToWorld() virtual VECTOR2D ComputeCursorToWorld( const VECTOR2D& aCursorPosition ); - /// @copydoc GAL::SetIsCursorEnabled() - void SetIsCursorEnabled( bool aIsCursorEnabled ); - /// @copydoc GAL::DrawCursor() virtual void DrawCursor( VECTOR2D aCursorPosition ); @@ -295,7 +253,7 @@ public: } protected: - virtual void DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); + virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); private: /// Super class definition @@ -303,30 +261,29 @@ private: // Compositing variables boost::shared_ptr compositor; ///< Object for layers compositing - unsigned int mainBuffer; ///< Handle to the main buffer - unsigned int overlayBuffer; ///< Handle to the overlay buffer + unsigned int mainBuffer; ///< Handle to the main buffer + unsigned int overlayBuffer; ///< Handle to the overlay buffer // Variables related to wxWidgets - wxWindow* parentWindow; ///< Parent window - wxEvtHandler* mouseListener; ///< Mouse listener - wxEvtHandler* paintListener; ///< Paint listener - unsigned int bufferSize; ///< Size of buffers cairoOutput, bitmapBuffers - unsigned char* wxOutput; ///< wxImage comaptible buffer + wxWindow* parentWindow; ///< Parent window + wxEvtHandler* mouseListener; ///< Mouse listener + wxEvtHandler* paintListener; ///< Paint listener + unsigned int bufferSize; ///< Size of buffers cairoOutput, bitmapBuffers + unsigned char* wxOutput; ///< wxImage comaptible buffer // Cursor variables - std::deque savedCursorPixels; ///< Saved pixels of the cursor - bool isDeleteSavedPixels; ///< True, if the saved pixels can be discarded - wxPoint savedCursorPosition; ///< The last cursor position - wxBitmap* cursorPixels; ///< Cursor pixels - wxBitmap* cursorPixelsSaved; ///< Saved cursor pixels - int cursorSize; ///< Cursor size + std::deque savedCursorPixels; ///< Saved pixels of the cursor + bool isDeleteSavedPixels; ///< True, if the saved pixels can be discarded + wxPoint savedCursorPosition; ///< The last cursor position + wxBitmap* cursorPixels; ///< Cursor pixels + wxBitmap* cursorPixelsSaved; ///< Saved cursor pixels + int cursorSize; ///< Cursor size /// Maximum number of arguments for one command static const int MAX_CAIRO_ARGUMENTS = 6; /// Definitions for the command recorder - enum GraphicsCommand - { + enum GraphicsCommand { CMD_SET_FILL, ///< Enable/disable filling CMD_SET_STROKE, ///< Enable/disable stroking CMD_SET_FILLCOLOR, ///< Set the fill color @@ -392,18 +349,18 @@ private: /// @copydoc GAL::initCursor() virtual void initCursor( int aCursorSize ); - /// Allocate the bitmaps for drawing - void allocateBitmaps(); - - /// Allocate the bitmaps for drawing - void deleteBitmaps(); - /// Prepare Cairo surfaces for drawing void initSurface(); /// Destroy Cairo surfaces when are not needed anymore void deinitSurface(); + /// Allocate the bitmaps for drawing + void allocateBitmaps(); + + /// Allocate the bitmaps for drawing + void deleteBitmaps(); + /// Prepare the compositor void setCompositor(); diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index 0f51d607a3..f7b02c0ce8 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -231,7 +231,10 @@ public: * * @param aColor is the color for background filling. */ - virtual void SetBackgroundColor( const COLOR4D& aColor ) = 0; + inline virtual void SetBackgroundColor( const COLOR4D& aColor ) + { + backgroundColor = aColor; + } /** * @brief Set the line width. @@ -417,7 +420,7 @@ public: // -------------------------------------------------------- /// @brief Compute the world <-> screen transformation matrix - virtual void ComputeWorldScreenMatrix() = 0; + virtual void ComputeWorldScreenMatrix(); /** * @brief Get the world <-> screen transformation matrix. @@ -745,7 +748,6 @@ protected: bool isFillEnabled; ///< Is filling of graphic objects enabled ? bool isStrokeEnabled; ///< Are the outlines stroked ? - bool isSetAttributes; ///< True, if the attributes have been set COLOR4D backgroundColor; ///< The background color COLOR4D fillColor; ///< The fill color @@ -784,7 +786,7 @@ protected: * @param aStartPoint is the start point of the line. * @param aEndPoint is the end point of the line. */ - virtual void DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) = 0; + virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) = 0; /** * @brief Initialize the cursor. diff --git a/include/gal/opengl/cached_container.h b/include/gal/opengl/cached_container.h index 6c2c8b92bf..6409d34356 100644 --- a/include/gal/opengl/cached_container.h +++ b/include/gal/opengl/cached_container.h @@ -94,12 +94,12 @@ protected: unsigned int m_itemSize; /** - * Function reallocate() - * resizes the chunk that stores the current item to the given size. - * - * @param aSize is the number of vertices to be stored. - * @return offset of the new chunk. - */ + * Function reallocate() + * resizes the chunk that stores the current item to the given size. + * + * @param aSize is the number of vertices to be stored. + * @return offset of the new chunk. + */ virtual unsigned int reallocate( unsigned int aSize ); /** diff --git a/include/gal/opengl/opengl_compositor.h b/include/gal/opengl/opengl_compositor.h index bccb6231bb..88d36f91fa 100644 --- a/include/gal/opengl/opengl_compositor.h +++ b/include/gal/opengl/opengl_compositor.h @@ -37,7 +37,6 @@ namespace KiGfx { - class OPENGL_COMPOSITOR : public COMPOSITOR { public: @@ -94,7 +93,6 @@ protected: 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 4fd7a7c375..402f8fc133 100644 --- a/include/gal/opengl/opengl_gal.h +++ b/include/gal/opengl/opengl_gal.h @@ -104,19 +104,19 @@ public: /// @copydoc GAL::DrawSegment() virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth ); - /// @copydoc GAL::DrawPolyline() - virtual void DrawPolyline( std::deque& aPointList ); - /// @copydoc GAL::DrawCircle() virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ); /// @copydoc GAL::DrawArc() - virtual void - DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, double aEndAngle ); + virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius, + double aStartAngle, double aEndAngle ); /// @copydoc GAL::DrawRectangle() virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); + /// @copydoc GAL::DrawPolyline() + virtual void DrawPolyline( std::deque& aPointList ); + /// @copydoc GAL::DrawPolygon() virtual void DrawPolygon( const std::deque& aPointList ); @@ -129,7 +129,7 @@ public: // -------------- /// @brief Resizes the canvas. - virtual void ResizeScreen ( int aWidth, int aHeight ); + virtual void ResizeScreen( int aWidth, int aHeight ); /// @brief Shows/hides the GAL canvas virtual bool Show( bool aShow ); @@ -144,42 +144,9 @@ public: // Attribute setting // ----------------- - /// @copydoc GAL::SetIsFill() - virtual void SetIsFill( bool aIsFillEnabled ) - { - isFillEnabled = aIsFillEnabled; - } - - /// @copydoc GAL::SetIsStroke() - virtual void SetIsStroke( bool aIsStrokeEnabled ) - { - isStrokeEnabled = aIsStrokeEnabled; - } - - /// @copydoc GAL::SetFillColor() - virtual void SetFillColor( const COLOR4D& aColor ); - /// @copydoc GAL::SetStrokeColor() virtual void SetStrokeColor( const COLOR4D& aColor ); - /// @copydoc GAL::GetStrokeColor() - COLOR4D GetStrokeColor(); - - /// @copydoc GAL::SetBackgroundColor() - virtual void SetBackgroundColor( const COLOR4D& aColor ); - - /// @copydoc GAL::SetLineWidth() - virtual void SetLineWidth( double aLineWidth ); - - /// @copydoc GAL::GetLineWidth() - double GetLineWidth(); - - /// @copydoc GAL::SetLayerDepth() - virtual void SetLayerDepth( double aLayerDepth ) - { - super::SetLayerDepth( aLayerDepth ); - } - // -------------- // Transformation // -------------- @@ -231,33 +198,6 @@ public: // Handling the world <-> screen transformation // -------------------------------------------------------- - /// @copydoc GAL::ComputeWorldScreenMatrix() - virtual void ComputeWorldScreenMatrix(); - - /// @copydoc GAL::GetWorldScreenMatrix() - MATRIX3x3D GetWorldScreenMatrix(); - - /// @copydoc GAL::SetWorldScreenMatrix() - void SetWorldScreenMatrix( MATRIX3x3D aMatrix ); - - /// @copydoc GAL::SetWorldUnitLength() - void SetWorldUnitLength( double aWorldUnitLength ); - - /// @copydoc GAL::SetScreenDPI() - void SetScreenDPI( double aScreenDPI ); - - /// @copydoc GAL::SetLookAtPoint() - void SetLookAtPoint( const VECTOR2D& aPoint ); - - /// @copydoc GAL::GetLookAtPoint() - VECTOR2D GetLookAtPoint(); - - /// @copydoc GAL::SetZoomFactor() - void SetZoomFactor( double aZoomFactor ); - - /// @copydoc GAL::GetZoomFactor() - double GetZoomFactor(); - /// @copydoc GAL::SaveScreen() virtual void SaveScreen(); @@ -274,9 +214,6 @@ public: /// @copydoc GAL::ComputeCursorToWorld() virtual VECTOR2D ComputeCursorToWorld( const VECTOR2D& aCursorPosition ); - /// @copydoc GAL::SetIsCursorEnabled() - void SetIsCursorEnabled( bool aIsCursorEnabled ); - /// @copydoc GAL::DrawCursor() virtual void DrawCursor( VECTOR2D aCursorPosition ); @@ -312,7 +249,7 @@ public: } TessParams; protected: - virtual void DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); + virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); private: /// Super class definition @@ -321,90 +258,114 @@ private: static const int CIRCLE_POINTS = 64; ///< The number of points for circle approximation static const int CURVE_POINTS = 32; ///< The number of points for curve approximation - wxClientDC* clientDC; ///< Drawing context - wxGLContext* glContext; ///< OpenGL context of wxWidgets - wxWindow* parentWindow; ///< Parent window - wxEvtHandler* mouseListener; - wxEvtHandler* paintListener; - - // Precomputed vertices for faster circle & semicircle drawing - NONCACHED_CONTAINER circleContainer; ///< Container for storing circle vertices + wxClientDC* clientDC; ///< Drawing context + wxGLContext* glContext; ///< OpenGL context of wxWidgets + wxWindow* parentWindow; ///< Parent window + wxEvtHandler* mouseListener; + wxEvtHandler* paintListener; // Vertex buffer objects related fields typedef std::map< unsigned int, boost::shared_ptr > GroupsMap; - GroupsMap groups; ///< Stores informations about VBO objects (groups) - unsigned int groupCounter; ///< Counter used for generating keys for groups - 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 + GroupsMap groups; ///< Stores informations about VBO objects (groups) + unsigned int groupCounter; ///< Counter used for generating keys for groups + 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 - std::vector tessIntersects; ///< Storage of intersecting points + OPENGL_COMPOSITOR compositor; ///< Handles multiple rendering targets + unsigned int mainBuffer; ///< Main rendering target + unsigned int overlayBuffer; ///< Auxiliary rendering target (for menus etc.) // Shader - SHADER shader; ///< There is only one shader used for different objects + SHADER shader; ///< There is only one shader used for different objects // Cursor - int cursorSize; ///< Size of the cursor in pixels - GLubyte* cursorShape; ///< Cursor pixel storage - GLubyte* cursorSave; ///< Saved cursor pixels - VECTOR2D savedCursorPosition; ///< Last saved cursor position + int cursorSize; ///< Size of the cursor in pixels + GLubyte* cursorShape; ///< Cursor pixel storage + GLubyte* cursorSave; ///< Saved cursor pixels + VECTOR2D savedCursorPosition; ///< Last saved cursor position // Internal flags - bool isGlewInitialized; ///< Is GLEW initialized? - bool isFramebufferInitialized; ///< Are the framebuffers initialized? - bool isShaderInitialized; ///< Was the shader initialized? - bool isGrouping; ///< Was a group started? + bool isGlewInitialized; ///< Is GLEW initialized? + bool isFramebufferInitialized; ///< Are the framebuffers initialized? + bool isShaderInitialized; ///< Was the shader initialized? + bool isGrouping; ///< Was a group started? + + // Polygon tesselation + GLUtesselator* tesselator; ///< Pointer to the tesselator + std::vector tessIntersects; ///< Storage of intersecting points + + // Structure used for tesselation of polygons + struct OGLPOINT + { + OGLPOINT() : + x( 0.0 ), y( 0.0 ), z( 0.0 ) + {} + + OGLPOINT( const char* fastest ) + { + // do nothing for fastest speed, and keep inline + } + + OGLPOINT( const VECTOR2D& aPoint ) : + x( aPoint.x ), y( aPoint.y ), z( 0.0 ) + {} + + OGLPOINT& operator=( const VECTOR2D& aPoint ) + { + x = aPoint.x; + y = aPoint.y; + z = 0.0; + return *this; + } + + GLdouble x; + GLdouble y; + GLdouble z; + }; /** - * @brief Draw a semi circle. Depending on settings (isStrokeEnabled & isFilledEnabled) it runs + * @brief Draw a quad for the line. + * + * @param aStartPoint is the start point of the line. + * @param aEndPoint is the end point of the line. + */ + inline void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); + + /** + * @brief Draw a semicircle. Depending on settings (isStrokeEnabled & isFilledEnabled) it runs * the proper function (drawStrokedSemiCircle or drawFilledSemiCircle). * * @param aCenterPoint is the center point. - * @param aRadius is the radius of the semi-circle. - * @param aAngle is the angle of the semi-circle. + * @param aRadius is the radius of the semicircle. + * @param aAngle is the angle of the semicircle. * */ void drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ); /** - * @brief Draw a filled semi circle. + * @brief Draw a filled semicircle. * * @param aCenterPoint is the center point. - * @param aRadius is the radius of the semi-circle. - * @param aAngle is the angle of the semi-circle. + * @param aRadius is the radius of the semicircle. + * @param aAngle is the angle of the semicircle. * */ void drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ); /** - * @brief Draw a stroked semi circle. + * @brief Draw a stroked semicircle. * * @param aCenterPoint is the center point. - * @param aRadius is the radius of the semi-circle. - * @param aAngle is the angle of the semi-circle. + * @param aRadius is the radius of the semicircle. + * @param aAngle is the angle of the semicircle. * */ void drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ); - /// Compute the points of the unit circle and store them in VBO. - void computeCircle(); - // Event handling - /** - * @brief This is the window creation event handler. - * - * @param aEvent is the window creation event. - */ - void onCreate( wxWindowCreateEvent& aEvent ); - /** * @brief This is the OnPaint event handler. * @@ -419,20 +380,12 @@ private: */ void skipMouseEvent( wxMouseEvent& aEvent ); - /// Initialize GLEW. + /// Initialize GLEW void initGlew(); /// @copydoc GAL::initCursor() virtual void initCursor( int aCursorSize ); - /** - * @brief Draw a quad for the line. - * - * @param aStartPoint is the start point of the line. - * @param aEndPoint is the end point of the line. - */ - inline void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); - /** * @brief Returns a valid key that can be used as a new group number. * diff --git a/include/gal/opengl/vertex_common.h b/include/gal/opengl/vertex_common.h index ef8c6d2046..626ed5a6cf 100644 --- a/include/gal/opengl/vertex_common.h +++ b/include/gal/opengl/vertex_common.h @@ -35,9 +35,8 @@ namespace KiGfx { // Possible types of shaders -enum SHADER_TYPE -{ - SHADER_NONE = 0, +enum SHADER_TYPE { + SHADER_NONE = 0, SHADER_LINE, SHADER_FILLED_CIRCLE, SHADER_STROKED_CIRCLE, @@ -60,7 +59,7 @@ const unsigned int CoordStride = CoordSize / sizeof(GLfloat); // Offset of color data from the beginning of each vertex data const unsigned int ColorOffset = offsetof(VERTEX, r); const unsigned int ColorSize = sizeof(VERTEX().r) + sizeof(VERTEX().g) + - sizeof(VERTEX().b) + sizeof(VERTEX().a); + sizeof(VERTEX().b) + sizeof(VERTEX().a); const unsigned int ColorStride = ColorSize / sizeof(GLubyte); // Shader attributes