diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index aedee10056..a3f91a6a91 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -64,6 +64,94 @@ GLuint OPENGL_GAL::fontTexture = 0; bool OPENGL_GAL::isBitmapFontLoaded = false; SHADER* OPENGL_GAL::shader = NULL; +namespace KIGFX { +class GL_BITMAP_CACHE +{ +public: + GL_BITMAP_CACHE() + { + } + + ~GL_BITMAP_CACHE(); + + GLuint RequestBitmap( const BITMAP_BASE* aBitmap ); + +private: + + struct CACHED_BITMAP + { + GLuint id; + int w, h; + }; + + GLuint cacheBitmap( const BITMAP_BASE* aBitmap ); + + std::map m_bitmaps; +}; + +}; + +GL_BITMAP_CACHE::~GL_BITMAP_CACHE() +{ + for ( auto b = m_bitmaps.begin(); b != m_bitmaps.end(); ++b ) + { + glDeleteTextures( 1, &b->second.id ); + } +} + +GLuint GL_BITMAP_CACHE::RequestBitmap( const BITMAP_BASE* aBitmap ) +{ + auto it = m_bitmaps.find( aBitmap) ; + + if ( it != m_bitmaps.end() ) + { + return it->second.id; + } + else + { + return cacheBitmap( aBitmap ); + } +} + + +GLuint GL_BITMAP_CACHE::cacheBitmap( const BITMAP_BASE* aBitmap ) +{ + CACHED_BITMAP bmp; + + bmp.w = aBitmap->GetSizePixels().x; + bmp.h = aBitmap->GetSizePixels().y; + + GLuint textureID; + glGenTextures(1, &textureID); + + uint8_t *buf = new uint8_t [ bmp.w * bmp.h * 3]; + auto imgData = const_cast( aBitmap )->GetImageData(); + + for( int y=0; y < bmp.h; y++ ) + for( int x = 0; x < bmp.w;x++) + { + auto *p = buf + ( bmp.w * y + x ) * 3; + + p[0] = imgData->GetRed( x, y ); + p[1] = imgData->GetGreen( x, y ); + p[2] = imgData->GetBlue( x, y ); + } + + glBindTexture( GL_TEXTURE_2D, textureID ); + + glTexImage2D( GL_TEXTURE_2D, 0,GL_RGB, bmp.w, bmp.h, 0, GL_RGB, GL_UNSIGNED_BYTE, buf ); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + + delete [] buf; + + bmp.id = textureID; + + m_bitmaps[ aBitmap ] = bmp; + + return textureID; +} OPENGL_GAL::OPENGL_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, wxWindow* aParent, wxEvtHandler* aMouseListener, wxEvtHandler* aPaintListener, @@ -103,6 +191,8 @@ OPENGL_GAL::OPENGL_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, wxWindow* aParent, ++instanceCounter; + bitmapCache.reset( new GL_BITMAP_CACHE ); + compositor = new OPENGL_COMPOSITOR; compositor->SetAntialiasingMode( options.gl_antialiasing_mode ); @@ -903,40 +993,49 @@ void OPENGL_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aContro void OPENGL_GAL::DrawBitmap( const BITMAP_BASE& aBitmap ) { int ppi = aBitmap.GetPPI(); - double worldIU_per_mm = 1/(worldUnitLength/2.54)/1000; - double pix_size_iu = worldIU_per_mm * ( 25.4 / ppi ); + double worldIU_per_mm = 1.0 / ( worldUnitLength / 2.54 )/ 1000; + double pix_size_iu = worldIU_per_mm * ( 25.4 / ppi ); - Save(); + double w = aBitmap.GetSizePixels().x * pix_size_iu; + double h = aBitmap.GetSizePixels().y * pix_size_iu; + + auto xform = currentManager->GetTransformation(); - // Set the pixel scaling factor: - currentManager->Scale( pix_size_iu, pix_size_iu, 0 ); - // The position of the bitmap is the bitmap center. - // move the draw origin to the top left bitmap corner: - currentManager->Translate( -aBitmap.GetSizePixels().x/2, -aBitmap.GetSizePixels().y/2, 0 ); + glm::vec4 v0 = xform * glm::vec4( -w/2, -h/2, 0.0, 0.0 ); + glm::vec4 v1 = xform * glm::vec4( w/2, h/2, 0.0, 0.0 ); + glm::vec4 trans = xform[3]; - isFillEnabled = true; - isStrokeEnabled = false; + auto id = bitmapCache->RequestBitmap( &aBitmap ); - // The pixel buffer of the initial bitmap: - auto bm_pix_buffer = (( BITMAP_BASE&)aBitmap).GetImageData(); + auto oldTarget = GetTarget(); - for( int row = 0; row < aBitmap.GetSizePixels().y; row++ ) - { - VECTOR2D pos( 0, row ); + glPushMatrix(); + glTranslated( trans.x, trans.y, trans.z ); - for( int col = 0; col < aBitmap.GetSizePixels().x; col++ ) - { - pos.x = col; - SetFillColor( COLOR4D( bm_pix_buffer->GetRed( col, row )/255.0, - bm_pix_buffer->GetGreen( col, row )/255.0, - bm_pix_buffer->GetBlue( col, row )/255.0, - 1.0 ) ); - VECTOR2D end = pos + 1.0; // Size of the rectangle = 1 pixel - DrawRectangle( pos, end ); - } - } + SetTarget( TARGET_NONCACHED ); + glEnable(GL_TEXTURE_2D); + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, id ); + + glBegin( GL_QUADS ); + glColor4f(1.0, 1.0, 1.0, 1.0); + glTexCoord2f(0.0, 0.0); + glVertex3f( v0.x, v0.y, layerDepth ); + glColor4f(1.0, 1.0, 1.0, 1.0); + glTexCoord2f(1.0, 0.0); + glVertex3f( v1.x, v0.y, layerDepth ); + glColor4f(1.0, 1.0, 1.0, 1.0); + glTexCoord2f(1.0, 1.0); + glVertex3f( v1.x, v1.y, layerDepth ); + glColor4f(1.0, 1.0, 1.0, 1.0); + glTexCoord2f(0.0, 1.0); + glVertex3f( v0.x, v1.y, layerDepth ); + glEnd(); - Restore(); + SetTarget( oldTarget ); + glBindTexture( GL_TEXTURE_2D, 0 ); + + glPopMatrix(); } @@ -1354,6 +1453,8 @@ void OPENGL_GAL::DeleteGroup( int aGroupNumber ) void OPENGL_GAL::ClearCache() { + bitmapCache.reset( new GL_BITMAP_CACHE ); + groups.clear(); if( isInitialized ) diff --git a/include/gal/opengl/opengl_gal.h b/include/gal/opengl/opengl_gal.h index a732fa8f6c..8b542f37f7 100644 --- a/include/gal/opengl/opengl_gal.h +++ b/include/gal/opengl/opengl_gal.h @@ -53,6 +53,7 @@ struct bitmap_glyph; namespace KIGFX { class SHADER; +class GL_BITMAP_CACHE; /** * @brief Class OpenGL_GAL is the OpenGL implementation of the Graphics Abstraction Layer. @@ -326,6 +327,8 @@ private: ///< when the window is visible bool isGrouping; ///< Was a group started? + std::unique_ptr bitmapCache; + ///< Update handler for OpenGL settings bool updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions ) override; diff --git a/pcbnew/pcb_draw_panel_gal.cpp b/pcbnew/pcb_draw_panel_gal.cpp index 532fa83aa9..3bbfdc0ca8 100644 --- a/pcbnew/pcb_draw_panel_gal.cpp +++ b/pcbnew/pcb_draw_panel_gal.cpp @@ -459,6 +459,7 @@ void PCB_DRAW_PANEL_GAL::setDefaultLayerDeps() m_view->SetLayerTarget( LAYER_RATSNEST, KIGFX::TARGET_OVERLAY ); m_view->SetLayerDisplayOnly( LAYER_RATSNEST ); + m_view->SetLayerTarget( LAYER_WORKSHEET, KIGFX::TARGET_NONCACHED ); m_view->SetLayerDisplayOnly( LAYER_WORKSHEET ) ; m_view->SetLayerDisplayOnly( LAYER_GRID ); m_view->SetLayerDisplayOnly( LAYER_DRC );