OPENGL_GAL: optimized JP's bitmap drawing function to use textures

(cherry picked from commit 516cf47946)
This commit is contained in:
Tomasz Wlostowski 2018-07-30 00:11:47 +02:00 committed by Seth Hillbrand
parent 7b596f0365
commit a43ec3e3f0
3 changed files with 132 additions and 27 deletions

View File

@ -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<const BITMAP_BASE*, CACHED_BITMAP> 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<BITMAP_BASE*>( 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();
}
@ -1357,6 +1456,8 @@ void OPENGL_GAL::DeleteGroup( int aGroupNumber )
void OPENGL_GAL::ClearCache()
{
bitmapCache.reset( new GL_BITMAP_CACHE );
groups.clear();
if( isInitialized )

View File

@ -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<GL_BITMAP_CACHE> bitmapCache;
///< Update handler for OpenGL settings
bool updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions ) override;

View File

@ -482,6 +482,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 );