34#include <glsl_xor_diff_frag.h>
35#include <glsl_xor_diff_vert.h>
72 catch(
const std::runtime_error& exc )
74 wxLogError( wxT(
"Run time exception `%s` occurred in OPENGL_COMPOSITOR destructor." ),
107 m_antialiasing = std::make_unique<ANTIALIASING_SUPERSAMPLING>(
this );
115 assert( dims.
x != 0 && dims.
y != 0 );
118 glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE, &maxBufSize );
120 if( dims.
x < 0 || dims.
y < 0 || dims.
x > maxBufSize || dims.
y >= maxBufSize )
121 throw std::runtime_error(
"Requested render buffer size is not supported" );
126 checkGlError(
"generating framebuffer", __FILE__, __LINE__ );
132 checkGlError(
"generating renderbuffer", __FILE__, __LINE__ );
134 checkGlError(
"binding renderbuffer", __FILE__, __LINE__ );
136 glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, dims.
x, dims.
y );
137 checkGlError(
"creating renderbuffer storage", __FILE__, __LINE__ );
138 glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
140 checkGlError(
"attaching renderbuffer", __FILE__, __LINE__ );
173 int maxBuffers, maxTextureSize;
176 glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &maxBuffers );
180 throw std::runtime_error(
"Cannot create more framebuffers. OpenGL rendering backend requires at "
181 "least 3 framebuffers. You may try to update/change your graphic drivers." );
184 glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*) &maxTextureSize );
186 if( maxTextureSize < (
int) aDimensions.
x || maxTextureSize < (
int) aDimensions.
y )
188 throw std::runtime_error(
"Requested texture size is not supported. Could not create a buffer." );
192 GLuint attachmentPoint = GL_COLOR_ATTACHMENT0 +
usedBuffers();
193 GLuint textureTarget;
196 glActiveTexture( GL_TEXTURE0 );
197 glGenTextures( 1, &textureTarget );
198 checkGlError(
"generating framebuffer texture target", __FILE__, __LINE__ );
199 glBindTexture( GL_TEXTURE_2D, textureTarget );
200 checkGlError(
"binding framebuffer texture target", __FILE__, __LINE__ );
203 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
204 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, aDimensions.
x, aDimensions.
y, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr );
205 checkGlError(
"creating framebuffer texture", __FILE__, __LINE__ );
206 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
207 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
211 glFramebufferTexture2D( GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, textureTarget, 0 );
214 GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
216 if( status != GL_FRAMEBUFFER_COMPLETE )
220 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
221 throw std::runtime_error(
"The framebuffer attachment points are incomplete." );
223 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
224 throw std::runtime_error(
"No images attached to the framebuffer." );
226 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
227 throw std::runtime_error(
"The framebuffer does not have at least one image attached to it." );
229 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
230 throw std::runtime_error(
"The framebuffer read buffer is incomplete." );
232 case GL_FRAMEBUFFER_UNSUPPORTED:
233 throw std::runtime_error(
"The combination of internal formats of the attached images violates "
234 "an implementation-dependent set of restrictions." );
236 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
237 throw std::runtime_error(
"GL_RENDERBUFFER_SAMPLES is not the same for all attached renderbuffers" );
239 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
240 throw std::runtime_error(
"Framebuffer incomplete layer targets errors." );
242 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
243 throw std::runtime_error(
"Framebuffer attachments have different dimensions" );
246 throw std::runtime_error(
"Unknown error occurred when creating the framebuffer." );
256 OPENGL_BUFFER buffer = { aDimensions, textureTarget, attachmentPoint };
265 wxCHECK( aBufferHandle > 0 && aBufferHandle <=
usedBuffers(), 0 );
266 return m_buffers[aBufferHandle - 1].textureTarget;
282 checkGlError(
"setting draw buffer", __FILE__, __LINE__ );
298 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
305 wxASSERT(
m_width <=
static_cast<unsigned int>( std::numeric_limits<coord_t>::max() ) );
306 wxASSERT(
m_height <=
static_cast<unsigned int>( std::numeric_limits<coord_t>::max() ) );
308 return {
static_cast<coord_t
>(
m_width ),
static_cast<coord_t
>(
m_height ) };
333 glDisable( GL_DEPTH_TEST );
334 glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
337 glEnable( GL_TEXTURE_2D );
338 glBindTexture( GL_TEXTURE_2D,
m_buffers[aSourceHandle - 1].textureTarget );
341 glMatrixMode( GL_MODELVIEW );
344 glMatrixMode( GL_PROJECTION );
348 glBegin( GL_TRIANGLES );
349 glTexCoord2f( 0.0f, 1.0f );
350 glVertex2f( -1.0f, 1.0f );
351 glTexCoord2f( 0.0f, 0.0f );
352 glVertex2f( -1.0f, -1.0f );
353 glTexCoord2f( 1.0f, 1.0f );
354 glVertex2f( 1.0f, 1.0f );
356 glTexCoord2f( 1.0f, 1.0f );
357 glVertex2f( 1.0f, 1.0f );
358 glTexCoord2f( 0.0f, 0.0f );
359 glVertex2f( -1.0f, -1.0f );
360 glTexCoord2f( 1.0f, 0.0f );
361 glVertex2f( 1.0f, -1.0f );
365 glMatrixMode( GL_MODELVIEW );
383 glBindFramebuffer( GL_FRAMEBUFFER, aFb );
384 checkGlError(
"switching framebuffer", __FILE__, __LINE__ );
397 glDeleteTextures( 1, &buffer.textureTarget );
401 if( glDeleteFramebuffers )
404 if( glDeleteRenderbuffers )
441 wxLogTrace(
traceGalXorMode, wxT(
"initDifferenceShader() called, initialized=%d" ),
446 wxLogTrace(
traceGalXorMode, wxT(
"initDifferenceShader(): already initialized, returning" ) );
450 const char* vertexShaderSrc = BUILTIN_SHADERS::glsl_xor_diff_vert.c_str();
451 const char* fragmentShaderSrc = BUILTIN_SHADERS::glsl_xor_diff_frag.c_str();
453 wxLogTrace(
traceGalXorMode, wxT(
"initDifferenceShader(): creating shaders" ) );
454 wxLogTrace(
traceGalXorMode, wxT(
"Vertex shader source:\n%s" ), vertexShaderSrc );
455 wxLogTrace(
traceGalXorMode, wxT(
"Fragment shader source:\n%s" ), fragmentShaderSrc );
457 GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
458 GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
460 wxLogTrace(
traceGalXorMode, wxT(
"initDifferenceShader(): vertexShader=%u, fragmentShader=%u" ),
461 vertexShader, fragmentShader );
464 glShaderSource( vertexShader, 1, &vertexShaderSrc,
nullptr );
465 glCompileShader( vertexShader );
468 glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &compiled );
470 wxLogTrace(
traceGalXorMode, wxT(
"initDifferenceShader(): vertex shader compile status=%d" ), compiled );
475 glGetShaderiv( vertexShader, GL_INFO_LOG_LENGTH, &logLen );
479 char* log =
new char[logLen];
480 glGetShaderInfoLog( vertexShader, logLen,
nullptr, log );
481 wxLogTrace(
traceGalXorMode, wxT(
"Vertex shader compile error:\n%s" ), log );
485 glDeleteShader( vertexShader );
486 glDeleteShader( fragmentShader );
491 glShaderSource( fragmentShader, 1, &fragmentShaderSrc,
nullptr );
492 glCompileShader( fragmentShader );
494 glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &compiled );
496 wxLogTrace(
traceGalXorMode, wxT(
"initDifferenceShader(): fragment shader compile status=%d" ), compiled );
501 glGetShaderiv( fragmentShader, GL_INFO_LOG_LENGTH, &logLen );
505 char* log =
new char[logLen];
506 glGetShaderInfoLog( fragmentShader, logLen,
nullptr, log );
507 wxLogTrace(
traceGalXorMode, wxT(
"Fragment shader compile error:\n%s" ), log );
511 glDeleteShader( vertexShader );
512 glDeleteShader( fragmentShader );
527 wxLogTrace(
traceGalXorMode, wxT(
"initDifferenceShader(): link status=%d" ), linked );
530 glDeleteShader( vertexShader );
531 glDeleteShader( fragmentShader );
540 char* log =
new char[logLen];
542 wxLogTrace(
traceGalXorMode, wxT(
"Shader program link error:\n%s" ), log );
555 wxLogTrace(
traceGalXorMode, wxT(
"initDifferenceShader(): srcTexUniform=%d, dstTexUniform=%d" ),
559 wxLogTrace(
traceGalXorMode, wxT(
"initDifferenceShader(): SUCCESS" ) );
566 glMatrixMode( GL_MODELVIEW );
569 glMatrixMode( GL_PROJECTION );
573 glBegin( GL_TRIANGLES );
574 glTexCoord2f( 0.0f, 1.0f );
575 glVertex2f( -1.0f, 1.0f );
576 glTexCoord2f( 0.0f, 0.0f );
577 glVertex2f( -1.0f, -1.0f );
578 glTexCoord2f( 1.0f, 1.0f );
579 glVertex2f( 1.0f, 1.0f );
581 glTexCoord2f( 1.0f, 1.0f );
582 glVertex2f( 1.0f, 1.0f );
583 glTexCoord2f( 0.0f, 0.0f );
584 glVertex2f( -1.0f, -1.0f );
585 glTexCoord2f( 1.0f, 0.0f );
586 glVertex2f( 1.0f, -1.0f );
590 glMatrixMode( GL_MODELVIEW );
597 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference() called: src=%u, dst=%u" ),
598 aSourceHandle, aDestHandle );
599 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): initialized=%d, usedBuffers=%u" ),
603 wxCHECK( aDestHandle != 0 && aDestHandle <=
usedBuffers(), );
608 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): shader init FAILED, falling back" ) );
614 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): shader initialized OK" ) );
617 GLuint srcTexture =
m_buffers[aSourceHandle - 1].textureTarget;
618 GLuint dstTexture =
m_buffers[aDestHandle - 1].textureTarget;
620 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): srcTexture=%u, dstTexture=%u" ),
621 srcTexture, dstTexture );
626 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): buffer dims=%dx%d" ), dims.
x, dims.
y );
630 glGenTextures( 1, &dstTempTex );
631 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): created dstTempTex=%u" ), dstTempTex );
633 glActiveTexture( GL_TEXTURE1 );
634 glBindTexture( GL_TEXTURE_2D, dstTempTex );
635 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
636 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
637 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, dims.
x, dims.
y, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr );
638 checkGlError(
"allocating dst temp texture", __FILE__, __LINE__ );
642 GLenum destAttachment =
m_buffers[aDestHandle - 1].attachmentPoint;
643 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): dest attachment point=0x%X" ), destAttachment );
645 glReadBuffer( destAttachment );
646 checkGlError(
"setting read buffer for dst copy", __FILE__, __LINE__ );
648 glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, dims.
x, dims.
y );
649 checkGlError(
"copying dest to temp texture", __FILE__, __LINE__ );
651 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): copied dest buffer to dstTempTex" ) );
655 glDisable( GL_DEPTH_TEST );
656 glDisable( GL_BLEND );
660 checkGlError(
"using difference shader program", __FILE__, __LINE__ );
662 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): activated shader program=%u" ),
666 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): binding srcTexture=%u to unit 0" ), srcTexture );
668 glActiveTexture( GL_TEXTURE0 );
669 glBindTexture( GL_TEXTURE_2D, srcTexture );
671 checkGlError(
"binding source texture for XOR mode", __FILE__, __LINE__ );
674 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): binding dstTempTex=%u to unit 1" ), dstTempTex );
676 glActiveTexture( GL_TEXTURE1 );
677 glBindTexture( GL_TEXTURE_2D, dstTempTex );
679 checkGlError(
"binding dest texture for XOR mode", __FILE__, __LINE__ );
681 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): drawing fullscreen quad" ) );
685 glActiveTexture( GL_TEXTURE0 );
689 checkGlError(
"drawing fullscreen quad for XOR mode", __FILE__, __LINE__ );
691 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): cleanup" ) );
695 glDeleteTextures( 1, &dstTempTex );
697 glActiveTexture( GL_TEXTURE0 );
698 glEnable( GL_BLEND );
699 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
701 wxLogTrace(
traceGalXorMode, wxT(
"DrawBufferDifference(): COMPLETE" ) );
A color representation with 4 components: red, green, blue, alpha.
static const COLOR4D BLACK
unsigned int m_height
Height of the buffer (in pixels)
unsigned int m_width
Width of the buffer (in pixels)
GAL_ANTIALIASING_MODE m_currentAntialiasingMode
virtual ~OPENGL_COMPOSITOR()
VECTOR2D GetAntialiasRenderingOffset() const
virtual void Begin() override
Call this at the beginning of each frame.
unsigned int usedBuffers()
Returns number of used buffers.
void SetAntialiasingMode(GAL_ANTIALIASING_MODE aMode)
static const unsigned int DIRECT_RENDERING
VECTOR2I GetScreenSize() const
void clean()
Perform freeing of resources.
GLint m_diffDstTexUniform
Destination texture uniform location.
bool initDifferenceShader()
Initialize the difference shader program.
virtual void Present() override
Call this to present the output buffer to the screen.
bool m_initialized
Initialization status flag.
GLint m_diffSrcTexUniform
Source texture uniform location.
void bindFb(unsigned int aFb)
Binds a specific Framebuffer Object.
GAL_ANTIALIASING_MODE GetAntialiasingMode() const
GLuint m_curFbo
Store the used FBO name in case there was more than one compositor used.
virtual void Initialize() override
Perform primary initialization, necessary to use the object.
void drawFullScreenQuad()
Draw a fullscreen quad for compositing.
void DrawBufferDifference(unsigned int aSourceHandle, unsigned int aDestHandle)
Draw buffer with difference blending (XOR-style for gerbview).
GLuint m_depthBuffer
Depth buffer handle.
virtual void ClearBuffer(const COLOR4D &aColor) override
Clear the selected buffer (set by the SetBuffer() function).
std::unique_ptr< OPENGL_PRESENTOR > m_antialiasing
GLuint m_differenceShader
Difference shader program.
virtual void Resize(unsigned int aWidth, unsigned int aHeight) override
Clear the state of COMPOSITOR, so it has to be reinitialized again with the new dimensions.
OPENGL_BUFFERS m_buffers
Stores information about initialized buffers.
bool m_differenceShaderInitialized
virtual void DrawBuffer(unsigned int aBufferHandle) override
Draw the selected buffer to the output buffer.
GLuint m_mainFbo
Main FBO handle (storing all target textures)
int GetAntialiasSupersamplingFactor() const
unsigned int m_curBuffer
Currently used buffer handle.
GLenum GetBufferTexture(unsigned int aBufferHandle)
virtual void SetBuffer(unsigned int aBufferHandle) override
Set the selected buffer as the rendering target.
virtual unsigned int CreateBuffer() override
Prepare a new buffer that may be used as a rendering target.
The Cairo implementation of the graphics abstraction layer.
static const wxChar *const traceGalXorMode
Handle multitarget rendering (ie.
int checkGlError(const std::string &aInfo, const char *aFile, int aLine, bool aThrow)
Check if a recent OpenGL operation has failed.
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D