KiCad PCB EDA Suite
Loading...
Searching...
No Matches
opengl_compositor.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2013-2017 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Maciej Suminski <[email protected]>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
32
34#include <gal/opengl/utils.h>
35
36#include <gal/color4d.h>
37
38#include <glsl_xor_diff_frag.h>
39#include <glsl_xor_diff_vert.h>
40
41#include <cassert>
42#include <memory>
43#include <stdexcept>
44#include <wx/log.h>
45#include <wx/debug.h>
46
47// Trace mask for XOR/difference mode debugging
48static const wxChar* const traceGalXorMode = wxT( "KICAD_GAL_XOR_MODE" );
49
50using namespace KIGFX;
51
66
67
69{
70 if( m_initialized )
71 {
72 try
73 {
74 clean();
75 }
76 catch( const std::runtime_error& exc )
77 {
78 wxLogError( wxT( "Run time exception `%s` occurred in OPENGL_COMPOSITOR destructor." ),
79 exc.what() );
80 }
81 }
82}
83
84
92
93
98
99
101{
102 if( m_initialized )
103 return;
104
106 {
108 m_antialiasing = std::make_unique<ANTIALIASING_SMAA>( this );
109 break;
111 m_antialiasing = std::make_unique<ANTIALIASING_SUPERSAMPLING>( this );
112 break;
113 default:
114 m_antialiasing = std::make_unique<ANTIALIASING_NONE>( this );
115 break;
116 }
117
118 VECTOR2I dims = m_antialiasing->GetInternalBufferSize();
119 assert( dims.x != 0 && dims.y != 0 );
120
121 GLint maxBufSize;
122 glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE_EXT, &maxBufSize );
123
124 if( dims.x < 0 || dims.y < 0 || dims.x > maxBufSize || dims.y >= maxBufSize )
125 throw std::runtime_error( "Requested render buffer size is not supported" );
126
127 // We need framebuffer objects for drawing the screen contents
128 // Generate framebuffer and a depth buffer
129 glGenFramebuffersEXT( 1, &m_mainFbo );
130 checkGlError( "generating framebuffer", __FILE__, __LINE__ );
131 bindFb( m_mainFbo );
132
133 // Allocate memory for the depth buffer
134 // Attach the depth buffer to the framebuffer
135 glGenRenderbuffersEXT( 1, &m_depthBuffer );
136 checkGlError( "generating renderbuffer", __FILE__, __LINE__ );
137 glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_depthBuffer );
138 checkGlError( "binding renderbuffer", __FILE__, __LINE__ );
139
140 glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, dims.x, dims.y );
141 checkGlError( "creating renderbuffer storage", __FILE__, __LINE__ );
142 glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT,
143 GL_RENDERBUFFER_EXT, m_depthBuffer );
144 checkGlError( "attaching renderbuffer", __FILE__, __LINE__ );
145
146 // Unbind the framebuffer, so by default all the rendering goes directly to the display
148
149 m_initialized = true;
150
151 m_antialiasing->Init();
152}
153
154
155void OPENGL_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight )
156{
157 if( m_initialized )
158 clean();
159
160 m_antialiasing->OnLostBuffers();
161
162 m_width = aWidth;
163 m_height = aHeight;
164}
165
166
168{
169 return m_antialiasing->CreateBuffer();
170}
171
172
173unsigned int OPENGL_COMPOSITOR::CreateBuffer( VECTOR2I aDimensions )
174{
175 assert( m_initialized );
176
177 int maxBuffers, maxTextureSize;
178
179 // Get the maximum number of buffers
180 glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &maxBuffers );
181
182 if( (int) usedBuffers() >= maxBuffers )
183 {
184 throw std::runtime_error( "Cannot create more framebuffers. OpenGL rendering backend requires at "
185 "least 3 framebuffers. You may try to update/change your graphic drivers." );
186 }
187
188 glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*) &maxTextureSize );
189
190 if( maxTextureSize < (int) aDimensions.x || maxTextureSize < (int) aDimensions.y )
191 {
192 throw std::runtime_error( "Requested texture size is not supported. Could not create a buffer." );
193 }
194
195 // GL_COLOR_ATTACHMENTn are consecutive integers
196 GLuint attachmentPoint = GL_COLOR_ATTACHMENT0 + usedBuffers();
197 GLuint textureTarget;
198
199 // Generate the texture for the pixel storage
200 glActiveTexture( GL_TEXTURE0 );
201 glGenTextures( 1, &textureTarget );
202 checkGlError( "generating framebuffer texture target", __FILE__, __LINE__ );
203 glBindTexture( GL_TEXTURE_2D, textureTarget );
204 checkGlError( "binding framebuffer texture target", __FILE__, __LINE__ );
205
206 // Set texture parameters
207 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
208 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, aDimensions.x, aDimensions.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr );
209 checkGlError( "creating framebuffer texture", __FILE__, __LINE__ );
210 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
211 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
212
213 // Bind the texture to the specific attachment point, clear and rebind the screen
214 bindFb( m_mainFbo );
215 glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachmentPoint, GL_TEXTURE_2D, textureTarget, 0 );
216
217 // Check the status, exit if the framebuffer can't be created
218 GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
219
220 if( status != GL_FRAMEBUFFER_COMPLETE_EXT )
221 {
222 switch( status )
223 {
224 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
225 throw std::runtime_error( "The framebuffer attachment points are incomplete." );
226
227 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
228 throw std::runtime_error( "No images attached to the framebuffer." );
229
230 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
231 throw std::runtime_error( "The framebuffer does not have at least one image attached to it." );
232
233 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
234 throw std::runtime_error( "The framebuffer read buffer is incomplete." );
235
236 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
237 throw std::runtime_error( "The combination of internal formats of the attached images violates "
238 "an implementation-dependent set of restrictions." );
239
240 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
241 throw std::runtime_error( "GL_RENDERBUFFER_SAMPLES is not the same for all attached renderbuffers" );
242
243 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT:
244 throw std::runtime_error( "Framebuffer incomplete layer targets errors." );
245
246 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
247 throw std::runtime_error( "Framebuffer attachments have different dimensions" );
248
249 default:
250 throw std::runtime_error( "Unknown error occurred when creating the framebuffer." );
251 }
252 }
253
255
256 // Return to direct rendering (we were asked only to create a buffer, not switch to one)
258
259 // Store the new buffer
260 OPENGL_BUFFER buffer = { aDimensions, textureTarget, attachmentPoint };
261 m_buffers.push_back( buffer );
262
263 return usedBuffers();
264}
265
266
267GLenum OPENGL_COMPOSITOR::GetBufferTexture( unsigned int aBufferHandle )
268{
269 wxCHECK( aBufferHandle > 0 && aBufferHandle <= usedBuffers(), 0 );
270 return m_buffers[aBufferHandle - 1].textureTarget;
271}
272
273
274void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
275{
276 wxCHECK( m_initialized && aBufferHandle <= usedBuffers(), /* void */ );
277
278 // Either unbind the FBO for direct rendering, or bind the one with target textures
279 bindFb( aBufferHandle == DIRECT_RENDERING ? DIRECT_RENDERING : m_mainFbo );
280
281 // Switch the target texture
283 {
284 m_curBuffer = aBufferHandle - 1;
285 glDrawBuffer( m_buffers[m_curBuffer].attachmentPoint );
286 checkGlError( "setting draw buffer", __FILE__, __LINE__ );
287
288 glViewport( 0, 0, m_buffers[m_curBuffer].dimensions.x, m_buffers[m_curBuffer].dimensions.y );
289 }
290 else
291 {
292 glViewport( 0, 0, GetScreenSize().x, GetScreenSize().y );
293 }
294}
295
296
298{
299 wxCHECK( m_initialized, /* void */ );
300
301 glClearColor( aColor.r, aColor.g, aColor.b, m_curFbo == DIRECT_RENDERING ? 1.0f : 0.0f );
302 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
303}
304
305
307{
308 typedef VECTOR2I::coord_type coord_t;
309 wxASSERT( m_width <= static_cast<unsigned int>( std::numeric_limits<coord_t>::max() ) );
310 wxASSERT( m_height <= static_cast<unsigned int>( std::numeric_limits<coord_t>::max() ) );
311
312 return { static_cast<coord_t>( m_width ), static_cast<coord_t>( m_height ) };
313}
314
315
317{
318 m_antialiasing->Begin();
319}
320
321
322void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
323{
324 m_antialiasing->DrawBuffer( aBufferHandle );
325}
326
327
328void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aSourceHandle, unsigned int aDestHandle )
329{
330 wxCHECK( m_initialized && aSourceHandle != 0 && aSourceHandle <= usedBuffers(), /* void */ );
331 wxCHECK( aDestHandle <= usedBuffers(), /* void */ );
332
333 // Switch to the destination buffer and blit the scene
334 SetBuffer( aDestHandle );
335
336 // Depth test has to be disabled to make transparency working
337 glDisable( GL_DEPTH_TEST );
338 glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
339
340 // Enable texturing and bind the main texture
341 glEnable( GL_TEXTURE_2D );
342 glBindTexture( GL_TEXTURE_2D, m_buffers[aSourceHandle - 1].textureTarget );
343
344 // Draw a full screen quad with the texture
345 glMatrixMode( GL_MODELVIEW );
346 glPushMatrix();
347 glLoadIdentity();
348 glMatrixMode( GL_PROJECTION );
349 glPushMatrix();
350 glLoadIdentity();
351
352 glBegin( GL_TRIANGLES );
353 glTexCoord2f( 0.0f, 1.0f );
354 glVertex2f( -1.0f, 1.0f );
355 glTexCoord2f( 0.0f, 0.0f );
356 glVertex2f( -1.0f, -1.0f );
357 glTexCoord2f( 1.0f, 1.0f );
358 glVertex2f( 1.0f, 1.0f );
359
360 glTexCoord2f( 1.0f, 1.0f );
361 glVertex2f( 1.0f, 1.0f );
362 glTexCoord2f( 0.0f, 0.0f );
363 glVertex2f( -1.0f, -1.0f );
364 glTexCoord2f( 1.0f, 0.0f );
365 glVertex2f( 1.0f, -1.0f );
366 glEnd();
367
368 glPopMatrix();
369 glMatrixMode( GL_MODELVIEW );
370 glPopMatrix();
371}
372
373
375{
376 m_antialiasing->Present();
377}
378
379
380void OPENGL_COMPOSITOR::bindFb( unsigned int aFb )
381{
382 // Currently there are only 2 valid FBOs
383 wxASSERT( aFb == DIRECT_RENDERING || aFb == m_mainFbo );
384
385 if( m_curFbo != aFb )
386 {
387 glBindFramebufferEXT( GL_FRAMEBUFFER, aFb );
388 checkGlError( "switching framebuffer", __FILE__, __LINE__ );
389 m_curFbo = aFb;
390 }
391}
392
393
395{
396 wxCHECK( m_initialized, /* void */ );
397
399
400 for( const OPENGL_BUFFER& buffer : m_buffers )
401 glDeleteTextures( 1, &buffer.textureTarget );
402
403 m_buffers.clear();
404
405 if( glDeleteFramebuffersEXT )
406 glDeleteFramebuffersEXT( 1, &m_mainFbo );
407
408 if( glDeleteRenderbuffersEXT )
409 glDeleteRenderbuffersEXT( 1, &m_depthBuffer );
410
411 // Clean up difference shader
413 {
414 glDeleteProgram( m_differenceShader );
417 }
418
419 m_initialized = false;
420}
421
422
424{
426 {
428 default: return 1;
429 }
430}
431
432
434{
436 {
437 case GAL_ANTIALIASING_MODE::AA_HIGHQUALITY: return VECTOR2D( 0.5, -0.5 );
438 default: return VECTOR2D( 0, 0 );
439 }
440}
441
442
444{
445 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader() called, initialized=%d" ),
447
449 {
450 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): already initialized, returning" ) );
451 return true;
452 }
453
454 const char* vertexShaderSrc = BUILTIN_SHADERS::glsl_xor_diff_vert.c_str();
455 const char* fragmentShaderSrc = BUILTIN_SHADERS::glsl_xor_diff_frag.c_str();
456
457 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): creating shaders" ) );
458 wxLogTrace( traceGalXorMode, wxT( "Vertex shader source:\n%s" ), vertexShaderSrc );
459 wxLogTrace( traceGalXorMode, wxT( "Fragment shader source:\n%s" ), fragmentShaderSrc );
460
461 GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
462 GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
463
464 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): vertexShader=%u, fragmentShader=%u" ),
465 vertexShader, fragmentShader );
466
467 // Compile vertex shader
468 glShaderSource( vertexShader, 1, &vertexShaderSrc, nullptr );
469 glCompileShader( vertexShader );
470
471 GLint compiled;
472 glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &compiled );
473
474 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): vertex shader compile status=%d" ), compiled );
475
476 if( !compiled )
477 {
478 GLint logLen;
479 glGetShaderiv( vertexShader, GL_INFO_LOG_LENGTH, &logLen );
480
481 if( logLen > 0 )
482 {
483 char* log = new char[logLen];
484 glGetShaderInfoLog( vertexShader, logLen, nullptr, log );
485 wxLogTrace( traceGalXorMode, wxT( "Vertex shader compile error:\n%s" ), log );
486 delete[] log;
487 }
488
489 glDeleteShader( vertexShader );
490 glDeleteShader( fragmentShader );
491 return false;
492 }
493
494 // Compile fragment shader
495 glShaderSource( fragmentShader, 1, &fragmentShaderSrc, nullptr );
496 glCompileShader( fragmentShader );
497
498 glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &compiled );
499
500 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): fragment shader compile status=%d" ), compiled );
501
502 if( !compiled )
503 {
504 GLint logLen;
505 glGetShaderiv( fragmentShader, GL_INFO_LOG_LENGTH, &logLen );
506
507 if( logLen > 0 )
508 {
509 char* log = new char[logLen];
510 glGetShaderInfoLog( fragmentShader, logLen, nullptr, log );
511 wxLogTrace( traceGalXorMode, wxT( "Fragment shader compile error:\n%s" ), log );
512 delete[] log;
513 }
514
515 glDeleteShader( vertexShader );
516 glDeleteShader( fragmentShader );
517 return false;
518 }
519
520 // Create and link program
521 m_differenceShader = glCreateProgram();
522 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): created program=%u" ), m_differenceShader );
523
524 glAttachShader( m_differenceShader, vertexShader );
525 glAttachShader( m_differenceShader, fragmentShader );
526 glLinkProgram( m_differenceShader );
527
528 GLint linked;
529 glGetProgramiv( m_differenceShader, GL_LINK_STATUS, &linked );
530
531 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): link status=%d" ), linked );
532
533 // Clean up shader objects (they're now part of the program)
534 glDeleteShader( vertexShader );
535 glDeleteShader( fragmentShader );
536
537 if( !linked )
538 {
539 GLint logLen;
540 glGetProgramiv( m_differenceShader, GL_INFO_LOG_LENGTH, &logLen );
541
542 if( logLen > 0 )
543 {
544 char* log = new char[logLen];
545 glGetProgramInfoLog( m_differenceShader, logLen, nullptr, log );
546 wxLogTrace( traceGalXorMode, wxT( "Shader program link error:\n%s" ), log );
547 delete[] log;
548 }
549
550 glDeleteProgram( m_differenceShader );
552 return false;
553 }
554
555 // Get uniform locations
556 m_diffSrcTexUniform = glGetUniformLocation( m_differenceShader, "srcTex" );
557 m_diffDstTexUniform = glGetUniformLocation( m_differenceShader, "dstTex" );
558
559 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): srcTexUniform=%d, dstTexUniform=%d" ),
561
563 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): SUCCESS" ) );
564 return true;
565}
566
567
569{
570 glMatrixMode( GL_MODELVIEW );
571 glPushMatrix();
572 glLoadIdentity();
573 glMatrixMode( GL_PROJECTION );
574 glPushMatrix();
575 glLoadIdentity();
576
577 glBegin( GL_TRIANGLES );
578 glTexCoord2f( 0.0f, 1.0f );
579 glVertex2f( -1.0f, 1.0f );
580 glTexCoord2f( 0.0f, 0.0f );
581 glVertex2f( -1.0f, -1.0f );
582 glTexCoord2f( 1.0f, 1.0f );
583 glVertex2f( 1.0f, 1.0f );
584
585 glTexCoord2f( 1.0f, 1.0f );
586 glVertex2f( 1.0f, 1.0f );
587 glTexCoord2f( 0.0f, 0.0f );
588 glVertex2f( -1.0f, -1.0f );
589 glTexCoord2f( 1.0f, 0.0f );
590 glVertex2f( 1.0f, -1.0f );
591 glEnd();
592
593 glPopMatrix();
594 glMatrixMode( GL_MODELVIEW );
595 glPopMatrix();
596}
597
598
599void OPENGL_COMPOSITOR::DrawBufferDifference( unsigned int aSourceHandle, unsigned int aDestHandle )
600{
601 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference() called: src=%u, dst=%u" ),
602 aSourceHandle, aDestHandle );
603 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): initialized=%d, usedBuffers=%u" ),
605
606 wxCHECK( m_initialized && aSourceHandle != 0 && aSourceHandle <= usedBuffers(), /* void */ );
607 wxCHECK( aDestHandle != 0 && aDestHandle <= usedBuffers(), /* void */ );
608
609 // Initialize shader on first use
610 if( !initDifferenceShader() )
611 {
612 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): shader init FAILED, falling back" ) );
613 // Fallback to regular DrawBuffer if shader fails
614 DrawBuffer( aSourceHandle, aDestHandle );
615 return;
616 }
617
618 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): shader initialized OK" ) );
619
620 // Get the texture targets directly from the buffers
621 GLuint srcTexture = m_buffers[aSourceHandle - 1].textureTarget;
622 GLuint dstTexture = m_buffers[aDestHandle - 1].textureTarget;
623
624 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): srcTexture=%u, dstTexture=%u" ),
625 srcTexture, dstTexture );
626
627 // We only need to copy the destination since we're writing to it.
628 // The source can be read directly via texture sampling
629 VECTOR2I dims = m_buffers[aDestHandle - 1].dimensions;
630 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): buffer dims=%dx%d" ), dims.x, dims.y );
631
632 // Create temp texture for destination copy (we can't read and write same texture)
633 GLuint dstTempTex;
634 glGenTextures( 1, &dstTempTex );
635 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): created dstTempTex=%u" ), dstTempTex );
636
637 glActiveTexture( GL_TEXTURE1 );
638 glBindTexture( GL_TEXTURE_2D, dstTempTex );
639 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
640 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
641 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, dims.x, dims.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr );
642 checkGlError( "allocating dst temp texture", __FILE__, __LINE__ );
643
644 // Copy destination buffer to temp texture
645 bindFb( m_mainFbo );
646 GLenum destAttachment = m_buffers[aDestHandle - 1].attachmentPoint;
647 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): dest attachment point=0x%X" ), destAttachment );
648
649 glReadBuffer( destAttachment );
650 checkGlError( "setting read buffer for dst copy", __FILE__, __LINE__ );
651
652 glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, dims.x, dims.y );
653 checkGlError( "copying dest to temp texture", __FILE__, __LINE__ );
654
655 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): copied dest buffer to dstTempTex" ) );
656
657 // Set up for rendering with difference shader
658 SetBuffer( aDestHandle );
659 glDisable( GL_DEPTH_TEST );
660 glDisable( GL_BLEND );
661
662 // Use the difference shader
663 glUseProgram( m_differenceShader );
664 checkGlError( "using difference shader program", __FILE__, __LINE__ );
665
666 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): activated shader program=%u" ),
668
669 // Bind source texture to unit 0
670 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): binding srcTexture=%u to unit 0" ), srcTexture );
671
672 glActiveTexture( GL_TEXTURE0 );
673 glBindTexture( GL_TEXTURE_2D, srcTexture );
674 glUniform1i( m_diffSrcTexUniform, 0 );
675 checkGlError( "binding source texture for XOR mode", __FILE__, __LINE__ );
676
677 // Bind destination copy to unit 1
678 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): binding dstTempTex=%u to unit 1" ), dstTempTex );
679
680 glActiveTexture( GL_TEXTURE1 );
681 glBindTexture( GL_TEXTURE_2D, dstTempTex );
682 glUniform1i( m_diffDstTexUniform, 1 );
683 checkGlError( "binding dest texture for XOR mode", __FILE__, __LINE__ );
684
685 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): drawing fullscreen quad" ) );
686
687 // Important: Set GL_TEXTURE0 as active before drawing so that glTexCoord2f
688 // sets gl_MultiTexCoord0 (which the vertex shader reads), not gl_MultiTexCoord1
689 glActiveTexture( GL_TEXTURE0 );
690
691 // Draw the fullscreen quad
693 checkGlError( "drawing fullscreen quad for XOR mode", __FILE__, __LINE__ );
694
695 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): cleanup" ) );
696
697 // Cleanup
698 glUseProgram( 0 );
699 glDeleteTextures( 1, &dstTempTex );
700
701 glActiveTexture( GL_TEXTURE0 );
702 glEnable( GL_BLEND );
703 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
704
705 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): COMPLETE" ) );
706}
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
double r
Red component.
Definition color4d.h:393
double g
Green component.
Definition color4d.h:394
static const COLOR4D BLACK
Definition color4d.h:406
double b
Blue component.
Definition color4d.h:395
unsigned int m_height
Height of the buffer (in pixels)
Definition compositor.h:113
unsigned int m_width
Width of the buffer (in pixels)
Definition compositor.h:112
GAL_ANTIALIASING_MODE m_currentAntialiasingMode
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
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.
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)
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.
int32_t coord_type
Definition vector2d.h:74
The Cairo implementation of the graphics abstraction layer.
Definition eda_group.h:33
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.
Definition utils.cpp:45
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694