From 190ed58568fff40bf88af5b7c506259e21d88fc7 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 | 574 ++++++------- 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 | 971 ++++++++++------------ 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, 886 insertions(+), 1089 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,38 +253,53 @@ void CAIRO_GAL::DrawPolygon( const std::deque& aPointList ) } -void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) +void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA, + const VECTOR2D& aControlPointB, 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_curve_to( currentContext, aControlPointA.x, aControlPointA.y, aControlPointB.x, + aControlPointB.y, aEndPoint.x, aEndPoint.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 ) +void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight ) { - cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y ); - cairo_curve_to( currentContext, aControlPointA.x, aControlPointA.y, aControlPointB.x, - aControlPointB.y, aEndPoint.x, aEndPoint.y ); - cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y ); + screenSize = VECTOR2D( aWidth, aHeight ); - isElementAdded = true; + // 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::SetBackgroundColor( const COLOR4D& aColor ) +void CAIRO_GAL::ClearScreen() { - backgroundColor = aColor; + 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,39 +542,10 @@ void CAIRO_GAL::EndGroup() } -void CAIRO_GAL::ClearCache() +void CAIRO_GAL::DrawGroup( int aGroupNumber ) { - 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 - // are executed; nested calling is also possible + // This method implements a small Virtual Machine - all stored commands + // are executed; nested calling is also possible storePath(); @@ -828,31 +655,147 @@ 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; + + 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::ClearCache() +{ + for( int i = groups.size() - 1; i >= 0; --i ) + { + DeleteGroup( i ); + } +} + + +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 ); +} + + +VECTOR2D CAIRO_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition ) +{ + MATRIX3x3D inverseMatrix = worldScreenMatrix.Inverse(); + VECTOR2D cursorPositionWorld = inverseMatrix * aCursorPosition; + + return cursorPositionWorld; } -void CAIRO_GAL::ComputeWorldScreenMatrix() +void CAIRO_GAL::DrawCursor( VECTOR2D aCursorPosition ) { - ComputeWorldScale(); + if( !IsShownOnScreen() ) + return; + + wxClientDC clientDC( this ); + wxMemoryDC cursorSave( *cursorPixelsSaved ); + wxMemoryDC cursorShape( *cursorPixels ); + + // Snap to grid + VECTOR2D cursorPositionWorld = ComputeCursorToWorld( aCursorPosition ); - worldScreenMatrix.SetIdentity(); + cursorPositionWorld.x = round( cursorPositionWorld.x / gridSize.x ) * gridSize.x; + cursorPositionWorld.y = round( cursorPositionWorld.y / gridSize.y ) * gridSize.y; + aCursorPosition = worldScreenMatrix * cursorPositionWorld; + aCursorPosition = aCursorPosition - VECTOR2D( cursorSize / 2, cursorSize / 2 ); + + if( !isDeleteSavedPixels ) + { + clientDC.Blit( savedCursorPosition.x, savedCursorPosition.y, cursorSize, cursorSize, + &cursorSave, 0, 0 ); + } + else + { + isDeleteSavedPixels = false; + } + + cursorSave.Blit( 0, 0, cursorSize, cursorSize, &clientDC, aCursorPosition.x, + aCursorPosition.y ); - MATRIX3x3D translation; - translation.SetIdentity(); - translation.SetTranslation( 0.5 * screenSize ); + clientDC.Blit( aCursorPosition.x, aCursorPosition.y, cursorSize, cursorSize, &cursorShape, 0, + 0, wxOR ); - MATRIX3x3D scale; - scale.SetIdentity(); - scale.SetScale( VECTOR2D( worldScale, worldScale ) ); + savedCursorPosition.x = (wxCoord) aCursorPosition.x; + savedCursorPosition.y = (wxCoord) aCursorPosition.y; +} - MATRIX3x3D lookat; - lookat.SetIdentity(); - lookat.SetTranslation( -lookAtPoint ); - worldScreenMatrix = translation * scale * lookat * worldScreenMatrix; +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 ); + cairo_set_source_rgb( currentContext, gridColor.r, gridColor.g, gridColor.b ); + cairo_stroke( currentContext ); } @@ -872,7 +815,8 @@ void CAIRO_GAL::storePath() if( isStrokeEnabled ) { - cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g, strokeColor.b ); + cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g, + strokeColor.b ); cairo_stroke_preserve( currentContext ); } } @@ -903,9 +847,18 @@ void CAIRO_GAL::storePath() } -// --------------- -// Cursor handling -// --------------- +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 ) @@ -919,7 +872,7 @@ void CAIRO_GAL::initCursor( int aCursorSize ) 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 ); + wxPen pen = wxPen( color ); cursorShape.SetPen( pen ); cursorShape.Clear(); @@ -928,88 +881,103 @@ void CAIRO_GAL::initCursor( int aCursorSize ) } -VECTOR2D CAIRO_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition ) +void CAIRO_GAL::allocateBitmaps() { - MATRIX3x3D inverseMatrix = worldScreenMatrix.Inverse(); - VECTOR2D cursorPositionWorld = inverseMatrix * aCursorPosition; + // Create buffer, use the system independent Cairo context backend + stride = cairo_format_stride_for_width( GAL_FORMAT, screenSize.x ); + bufferSize = stride * screenSize.y; - return cursorPositionWorld; + bitmapBuffer = new unsigned int[bufferSize]; + bitmapBufferBackup = new unsigned int[bufferSize]; + wxOutput = new unsigned char[bufferSize * 3]; } -void CAIRO_GAL::DrawCursor( VECTOR2D aCursorPosition ) +void CAIRO_GAL::deleteBitmaps() { - if( !IsShownOnScreen() ) - return; + delete[] bitmapBuffer; + delete[] bitmapBufferBackup; + delete[] wxOutput; +} - wxClientDC clientDC( this ); - wxMemoryDC cursorSave( *cursorPixelsSaved ); - wxMemoryDC cursorShape( *cursorPixels ); - // Snap to grid - VECTOR2D cursorPositionWorld = ComputeCursorToWorld( aCursorPosition ); +void CAIRO_GAL::initSurface() +{ + wxASSERT( !isInitialized ); - cursorPositionWorld.x = round( cursorPositionWorld.x / gridSize.x ) * gridSize.x; - cursorPositionWorld.y = round( cursorPositionWorld.y / gridSize.y ) * gridSize.y; - aCursorPosition = worldScreenMatrix * cursorPositionWorld; - aCursorPosition = aCursorPosition - VECTOR2D( cursorSize / 2, cursorSize / 2 ); + // 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; - if( !isDeleteSavedPixels ) - { - clientDC.Blit( savedCursorPosition.x, savedCursorPosition.y, cursorSize, cursorSize, - &cursorSave, 0, 0 ); - } - else - { - isDeleteSavedPixels = false; - } + cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL ); - cursorSave.Blit( 0, 0, cursorSize, cursorSize, &clientDC, aCursorPosition.x, - aCursorPosition.y ); + // Clear the screen + ClearScreen(); - clientDC.Blit( aCursorPosition.x, aCursorPosition.y, cursorSize, cursorSize, &cursorShape, 0, - 0, wxOR ); + // Compute the world <-> screen transformations + ComputeWorldScreenMatrix(); - savedCursorPosition.x = (wxCoord) aCursorPosition.x; - savedCursorPosition.y = (wxCoord) aCursorPosition.y; -} + 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 ); -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 ); - cairo_set_source_rgb( currentContext, gridColor.r, gridColor.g, gridColor.b ); - cairo_stroke( currentContext ); + // 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::allocateBitmaps() +void CAIRO_GAL::deinitSurface() { - // Create buffer, use the system independent Cairo context backend - stride = cairo_format_stride_for_width( GAL_FORMAT, screenSize.x ); - bufferSize = stride * screenSize.y; + if( !isInitialized ) + return; - bitmapBuffer = new unsigned int[bufferSize]; - bitmapBufferBackup = new unsigned int[bufferSize]; - wxOutput = new unsigned char[bufferSize * 3]; + // Destroy Cairo objects + cairo_destroy( context ); + cairo_surface_destroy( surface ); + + isInitialized = false; } -void CAIRO_GAL::deleteBitmaps() +void CAIRO_GAL::setCompositor() { - delete[] bitmapBuffer; - delete[] bitmapBufferBackup; - delete[] wxOutput; + // 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(); } -bool CAIRO_GAL::Show( bool aShow ) +unsigned int CAIRO_GAL::getNewGroupNumber() { - bool s = wxWindow::Show( aShow ); + wxASSERT_MSG( groups.size() < std::numeric_limits::max(), + wxT( "There are no free slots to store a group" ) ); - if( aShow ) - wxWindow::Raise(); + while( groups.find( groupCounter ) != groups.end() ) + { + groupCounter++; + } - return s; + 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; - - if( lineLength <= 0.0 ) - return; - - // 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 + const VECTOR2D startEndVector = aEndPoint - aStartPoint; + double lineAngle = startEndVector.Angle(); - currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth ); - currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v3 + drawLineQuad( aStartPoint, aEndPoint ); - 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,53 +287,124 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP } -unsigned int OPENGL_GAL::getNewGroupNumber() +void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) { - wxASSERT_MSG( groups.size() < std::numeric_limits::max(), - wxT( "There are no free slots to store a group" ) ); - - while( groups.find( groupCounter ) != groups.end() ) + if( isFillEnabled ) { - groupCounter++; + 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 + */ + currentManager->Shader( SHADER_FILLED_CIRCLE, 1.0 ); + 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 ), // v1 + aCenterPoint.y - aRadius, layerDepth ); + + currentManager->Shader( SHADER_FILLED_CIRCLE, 3.0 ); + currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + aRadius * 2.0f, // v2 + layerDepth ); } - return groupCounter++; + if( isStrokeEnabled ) + { + 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 + */ + 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 ); + + currentManager->Shader( SHADER_STROKED_CIRCLE, 2.0, aRadius, lineWidth ); + 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, // v2 + layerDepth ); + } } -void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) +void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, + double aEndAngle ) { - const VECTOR2D startEndVector = aEndPoint - aStartPoint; - double lineAngle = startEndVector.Angle(); + if( aRadius <= 0 ) + return; - drawLineQuad( aStartPoint, aEndPoint ); + // Swap the angles, if start angle is greater than end angle + SWAP( aStartAngle, >, aEndAngle ); - // Line caps - drawFilledSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 ); - drawFilledSemiCircle( aEndPoint, lineWidth / 2, lineAngle - M_PI / 2 ); -} + VECTOR2D startPoint( cos( aStartAngle ), sin( aStartAngle ) ); + VECTOR2D endPoint( cos( aEndAngle ), sin( aEndAngle ) ); + VECTOR2D startEndPoint = startPoint + endPoint; + VECTOR2D middlePoint = 0.5 * startEndPoint; + Save(); + currentManager->Translate( aCenterPoint.x, aCenterPoint.y, layerDepth ); -void OPENGL_GAL::DrawPolyline( std::deque& aPointList ) -{ - std::deque::const_iterator it = aPointList.begin(); + if( isStrokeEnabled ) + { + double alphaIncrement = 2.0 * M_PI / CIRCLE_POINTS; + currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); - // Start from the second point - for( it++; it != aPointList.end(); it++ ) + VECTOR2D p( cos( aStartAngle ) * aRadius, sin( aStartAngle ) * aRadius ); + double alpha; + for( alpha = aStartAngle + alphaIncrement; alpha < aEndAngle; alpha += alphaIncrement ) + { + VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius ); + DrawLine( p, p_next ); + + p = p_next; + } + + // Draw the last missing part + if( alpha != aEndAngle ) + { + VECTOR2D p_last( cos( aEndAngle ) * aRadius, sin( aEndAngle ) * aRadius ); + DrawLine( p, p_last ); + } + } + + if( isFillEnabled ) { - const VECTOR2D startEndVector = ( *it - *( it - 1 ) ); - double lineAngle = startEndVector.Angle(); + double alphaIncrement = 2 * M_PI / CIRCLE_POINTS; + double alpha; + currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); - drawLineQuad( *( it - 1 ), *it ); + for( alpha = aStartAngle; ( alpha + alphaIncrement ) < aEndAngle; ) + { + currentManager->Vertex( middlePoint.x, middlePoint.y, 0.0 ); + currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 ); + alpha += alphaIncrement; + currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 ); + } - // There is no need to draw line caps on both ends of polyline's segments - drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle + M_PI / 2 ); + currentManager->Vertex( middlePoint.x, middlePoint.y, 0.0 ); + currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 ); + currentManager->Vertex( endPoint.x, endPoint.y, 0.0 ); } - // ..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 ); + Restore(); } @@ -501,234 +445,29 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn } -void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) +void OPENGL_GAL::DrawPolyline( std::deque& aPointList ) { - if( isFillEnabled ) + std::deque::const_iterator it = aPointList.begin(); + + // Start from the second point + for( it++; it != aPointList.end(); it++ ) { - currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); + const VECTOR2D startEndVector = ( *it - *( it - 1 ) ); + double lineAngle = startEndVector.Angle(); - /* 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 - */ - currentManager->Shader( SHADER_FILLED_CIRCLE, 1.0 ); - currentManager->Vertex( aCenterPoint.x - aRadius * sqrt( 3.0f ), // v0 - aCenterPoint.y - aRadius, layerDepth ); + drawLineQuad( *( it - 1 ), *it ); - currentManager->Shader( SHADER_FILLED_CIRCLE, 2.0 ); - 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 - layerDepth ); - } - - if( isStrokeEnabled ) - { - 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 - */ - 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 ); - - currentManager->Shader( SHADER_STROKED_CIRCLE, 2.0, aRadius, lineWidth ); - 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, // v2 - layerDepth ); - } -} - - -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 ) -{ - if( aRadius <= 0 ) - return; - - // Swap the angles, if start angle is greater than end angle - SWAP( aStartAngle, >, aEndAngle ); - - VECTOR2D startPoint( cos( aStartAngle ), sin( aStartAngle ) ); - VECTOR2D endPoint( cos( aEndAngle ), sin( aEndAngle ) ); - VECTOR2D startEndPoint = startPoint + endPoint; - VECTOR2D middlePoint = 0.5 * startEndPoint; - - Save(); - currentManager->Translate( aCenterPoint.x, aCenterPoint.y, layerDepth ); - - if( isStrokeEnabled ) - { - double alphaIncrement = 2.0 * M_PI / CIRCLE_POINTS; - currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); - - VECTOR2D p( cos( aStartAngle ) * aRadius, sin( aStartAngle ) * aRadius ); - double alpha; - for( alpha = aStartAngle + alphaIncrement; alpha < aEndAngle; alpha += alphaIncrement ) - { - VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius ); - DrawLine( p, p_next ); - - p = p_next; - } - - // Draw the last missing part - if( alpha != aEndAngle ) - { - VECTOR2D p_last( cos( aEndAngle ) * aRadius, sin( aEndAngle ) * aRadius ); - DrawLine( p, p_last ); - } - } - - if( isFillEnabled ) - { - double alphaIncrement = 2 * M_PI / CIRCLE_POINTS; - double alpha; - currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); - - for( alpha = aStartAngle; ( alpha + alphaIncrement ) < aEndAngle; ) - { - currentManager->Vertex( middlePoint.x, middlePoint.y, 0.0 ); - currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 ); - alpha += alphaIncrement; - currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 ); - } - - currentManager->Vertex( middlePoint.x, middlePoint.y, 0.0 ); - currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 ); - currentManager->Vertex( endPoint.x, endPoint.y, 0.0 ); + // There is no need to draw line caps on both ends of polyline's segments + drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle + M_PI / 2 ); } - Restore(); + // ..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 ); } -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; -}; - - void OPENGL_GAL::DrawPolygon( const std::deque& aPointList ) { // Any non convex polygon needs to be tesselated @@ -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(); -void OPENGL_GAL::SetBackgroundColor( const COLOR4D& aColor ) -{ - isSetAttributes = true; - backgroundColor = aColor; + return s; } -void OPENGL_GAL::SetLineWidth( double aLineWidth ) +void OPENGL_GAL::Flush() { - 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,140 +677,65 @@ 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 ) - { - vertex->x = 0.0f; - vertex->y = 0.0f; - vertex->z = 0.0f; - vertex++; - - 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++; - - 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++; - } + +void OPENGL_GAL::ClearCache() +{ + groups.clear(); + cachedManager.Clear(); } -void OPENGL_GAL::ComputeWorldScreenMatrix() +void OPENGL_GAL::SaveScreen() { - ComputeWorldScale(); + wxASSERT_MSG( false, wxT( "Not implemented yet" ) ); +} - worldScreenMatrix.SetIdentity(); - MATRIX3x3D translation; - translation.SetIdentity(); - translation.SetTranslation( 0.5 * screenSize ); +void OPENGL_GAL::RestoreScreen() +{ + wxASSERT_MSG( false, wxT( "Not implemented yet" ) ); +} - MATRIX3x3D scale; - scale.SetIdentity(); - scale.SetScale( VECTOR2D( worldScale, worldScale ) ); - MATRIX3x3D flip; - flip.SetIdentity(); - flip.SetScale( VECTOR2D( 1.0, 1.0 ) ); +void OPENGL_GAL::SetTarget( RenderTarget aTarget ) +{ + switch( aTarget ) + { + default: + case TARGET_CACHED: + currentManager = &cachedManager; + break; - MATRIX3x3D lookat; - lookat.SetIdentity(); - lookat.SetTranslation( -lookAtPoint ); + case TARGET_NONCACHED: + currentManager = &nonCachedManager; + break; - worldScreenMatrix = translation * flip * scale * lookat * worldScreenMatrix; + case TARGET_OVERLAY: + currentManager = &overlayManager; + break; + } } -// ------------------------------------- -// Callback functions for the tesselator -// ------------------------------------- +VECTOR2D OPENGL_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition ) +{ + VECTOR2D cursorPosition = aCursorPosition; + cursorPosition.y = screenSize.y - aCursorPosition.y; + MATRIX3x3D inverseMatrix = worldScreenMatrix.Inverse(); + VECTOR2D cursorPositionWorld = inverseMatrix * cursorPosition; -// 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; - cursorPosition.y = screenSize.y - aCursorPosition.y; - MATRIX3x3D inverseMatrix = worldScreenMatrix.Inverse(); - VECTOR2D cursorPositionWorld = inverseMatrix * cursorPosition; - - return cursorPositionWorld; -} + return cursorPositionWorld; +} 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