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, see <https://www.gnu.org/licenses/>.
21 */
22
28
30#include <gal/opengl/utils.h>
31
32#include <gal/color4d.h>
33
34#include <glsl_xor_diff_frag.h>
35#include <glsl_xor_diff_vert.h>
36
37#include <cassert>
38#include <memory>
39#include <stdexcept>
40#include <wx/log.h>
41#include <wx/debug.h>
42
43// Trace mask for XOR/difference mode debugging
44static const wxChar* const traceGalXorMode = wxT( "KICAD_GAL_XOR_MODE" );
45
46using namespace KIGFX;
47
62
63
65{
66 if( m_initialized )
67 {
68 try
69 {
70 clean();
71 }
72 catch( const std::runtime_error& exc )
73 {
74 wxLogError( wxT( "Run time exception `%s` occurred in OPENGL_COMPOSITOR destructor." ),
75 exc.what() );
76 }
77 }
78}
79
80
88
89
94
95
97{
98 if( m_initialized )
99 return;
100
102 {
104 m_antialiasing = std::make_unique<ANTIALIASING_SMAA>( this );
105 break;
107 m_antialiasing = std::make_unique<ANTIALIASING_SUPERSAMPLING>( this );
108 break;
109 default:
110 m_antialiasing = std::make_unique<ANTIALIASING_NONE>( this );
111 break;
112 }
113
114 VECTOR2I dims = m_antialiasing->GetInternalBufferSize();
115 assert( dims.x != 0 && dims.y != 0 );
116
117 GLint maxBufSize;
118 glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE, &maxBufSize );
119
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" );
122
123 // We need framebuffer objects for drawing the screen contents
124 // Generate framebuffer and a depth buffer
125 glGenFramebuffers( 1, &m_mainFbo );
126 checkGlError( "generating framebuffer", __FILE__, __LINE__ );
127 bindFb( m_mainFbo );
128
129 // Allocate memory for the depth buffer
130 // Attach the depth buffer to the framebuffer
131 glGenRenderbuffers( 1, &m_depthBuffer );
132 checkGlError( "generating renderbuffer", __FILE__, __LINE__ );
133 glBindRenderbuffer( GL_RENDERBUFFER, m_depthBuffer );
134 checkGlError( "binding renderbuffer", __FILE__, __LINE__ );
135
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,
139 GL_RENDERBUFFER, m_depthBuffer );
140 checkGlError( "attaching renderbuffer", __FILE__, __LINE__ );
141
142 // Unbind the framebuffer, so by default all the rendering goes directly to the display
144
145 m_initialized = true;
146
147 m_antialiasing->Init();
148}
149
150
151void OPENGL_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight )
152{
153 if( m_initialized )
154 clean();
155
156 m_antialiasing->OnLostBuffers();
157
158 m_width = aWidth;
159 m_height = aHeight;
160}
161
162
164{
165 return m_antialiasing->CreateBuffer();
166}
167
168
169unsigned int OPENGL_COMPOSITOR::CreateBuffer( VECTOR2I aDimensions )
170{
171 assert( m_initialized );
172
173 int maxBuffers, maxTextureSize;
174
175 // Get the maximum number of buffers
176 glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &maxBuffers );
177
178 if( (int) usedBuffers() >= maxBuffers )
179 {
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." );
182 }
183
184 glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*) &maxTextureSize );
185
186 if( maxTextureSize < (int) aDimensions.x || maxTextureSize < (int) aDimensions.y )
187 {
188 throw std::runtime_error( "Requested texture size is not supported. Could not create a buffer." );
189 }
190
191 // GL_COLOR_ATTACHMENTn are consecutive integers
192 GLuint attachmentPoint = GL_COLOR_ATTACHMENT0 + usedBuffers();
193 GLuint textureTarget;
194
195 // Generate the texture for the pixel storage
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__ );
201
202 // Set texture parameters
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 );
208
209 // Bind the texture to the specific attachment point, clear and rebind the screen
210 bindFb( m_mainFbo );
211 glFramebufferTexture2D( GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, textureTarget, 0 );
212
213 // Check the status, exit if the framebuffer can't be created
214 GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
215
216 if( status != GL_FRAMEBUFFER_COMPLETE )
217 {
218 switch( status )
219 {
220 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
221 throw std::runtime_error( "The framebuffer attachment points are incomplete." );
222
223 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
224 throw std::runtime_error( "No images attached to the framebuffer." );
225
226 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
227 throw std::runtime_error( "The framebuffer does not have at least one image attached to it." );
228
229 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
230 throw std::runtime_error( "The framebuffer read buffer is incomplete." );
231
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." );
235
236 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
237 throw std::runtime_error( "GL_RENDERBUFFER_SAMPLES is not the same for all attached renderbuffers" );
238
239 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
240 throw std::runtime_error( "Framebuffer incomplete layer targets errors." );
241
242 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
243 throw std::runtime_error( "Framebuffer attachments have different dimensions" );
244
245 default:
246 throw std::runtime_error( "Unknown error occurred when creating the framebuffer." );
247 }
248 }
249
251
252 // Return to direct rendering (we were asked only to create a buffer, not switch to one)
254
255 // Store the new buffer
256 OPENGL_BUFFER buffer = { aDimensions, textureTarget, attachmentPoint };
257 m_buffers.push_back( buffer );
258
259 return usedBuffers();
260}
261
262
263GLenum OPENGL_COMPOSITOR::GetBufferTexture( unsigned int aBufferHandle )
264{
265 wxCHECK( aBufferHandle > 0 && aBufferHandle <= usedBuffers(), 0 );
266 return m_buffers[aBufferHandle - 1].textureTarget;
267}
268
269
270void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
271{
272 wxCHECK( m_initialized && aBufferHandle <= usedBuffers(), /* void */ );
273
274 // Either unbind the FBO for direct rendering, or bind the one with target textures
275 bindFb( aBufferHandle == DIRECT_RENDERING ? DIRECT_RENDERING : m_mainFbo );
276
277 // Switch the target texture
279 {
280 m_curBuffer = aBufferHandle - 1;
281 glDrawBuffer( m_buffers[m_curBuffer].attachmentPoint );
282 checkGlError( "setting draw buffer", __FILE__, __LINE__ );
283
284 glViewport( 0, 0, m_buffers[m_curBuffer].dimensions.x, m_buffers[m_curBuffer].dimensions.y );
285 }
286 else
287 {
288 glViewport( 0, 0, GetScreenSize().x, GetScreenSize().y );
289 }
290}
291
292
294{
295 wxCHECK( m_initialized, /* void */ );
296
297 glClearColor( aColor.r, aColor.g, aColor.b, m_curFbo == DIRECT_RENDERING ? 1.0f : 0.0f );
298 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
299}
300
301
303{
304 typedef VECTOR2I::coord_type coord_t;
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() ) );
307
308 return { static_cast<coord_t>( m_width ), static_cast<coord_t>( m_height ) };
309}
310
311
313{
314 m_antialiasing->Begin();
315}
316
317
318void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
319{
320 m_antialiasing->DrawBuffer( aBufferHandle );
321}
322
323
324void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aSourceHandle, unsigned int aDestHandle )
325{
326 wxCHECK( m_initialized && aSourceHandle != 0 && aSourceHandle <= usedBuffers(), /* void */ );
327 wxCHECK( aDestHandle <= usedBuffers(), /* void */ );
328
329 // Switch to the destination buffer and blit the scene
330 SetBuffer( aDestHandle );
331
332 // Depth test has to be disabled to make transparency working
333 glDisable( GL_DEPTH_TEST );
334 glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
335
336 // Enable texturing and bind the main texture
337 glEnable( GL_TEXTURE_2D );
338 glBindTexture( GL_TEXTURE_2D, m_buffers[aSourceHandle - 1].textureTarget );
339
340 // Draw a full screen quad with the texture
341 glMatrixMode( GL_MODELVIEW );
342 glPushMatrix();
343 glLoadIdentity();
344 glMatrixMode( GL_PROJECTION );
345 glPushMatrix();
346 glLoadIdentity();
347
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 );
355
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 );
362 glEnd();
363
364 glPopMatrix();
365 glMatrixMode( GL_MODELVIEW );
366 glPopMatrix();
367}
368
369
371{
372 m_antialiasing->Present();
373}
374
375
376void OPENGL_COMPOSITOR::bindFb( unsigned int aFb )
377{
378 // Currently there are only 2 valid FBOs
379 wxASSERT( aFb == DIRECT_RENDERING || aFb == m_mainFbo );
380
381 if( m_curFbo != aFb )
382 {
383 glBindFramebuffer( GL_FRAMEBUFFER, aFb );
384 checkGlError( "switching framebuffer", __FILE__, __LINE__ );
385 m_curFbo = aFb;
386 }
387}
388
389
391{
392 wxCHECK( m_initialized, /* void */ );
393
395
396 for( const OPENGL_BUFFER& buffer : m_buffers )
397 glDeleteTextures( 1, &buffer.textureTarget );
398
399 m_buffers.clear();
400
401 if( glDeleteFramebuffers )
402 glDeleteFramebuffers( 1, &m_mainFbo );
403
404 if( glDeleteRenderbuffers )
405 glDeleteRenderbuffers( 1, &m_depthBuffer );
406
407 // Clean up difference shader
409 {
410 glDeleteProgram( m_differenceShader );
413 }
414
415 m_initialized = false;
416}
417
418
420{
422 {
424 default: return 1;
425 }
426}
427
428
430{
432 {
433 case GAL_ANTIALIASING_MODE::AA_HIGHQUALITY: return VECTOR2D( 0.5, -0.5 );
434 default: return VECTOR2D( 0, 0 );
435 }
436}
437
438
440{
441 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader() called, initialized=%d" ),
443
445 {
446 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): already initialized, returning" ) );
447 return true;
448 }
449
450 const char* vertexShaderSrc = BUILTIN_SHADERS::glsl_xor_diff_vert.c_str();
451 const char* fragmentShaderSrc = BUILTIN_SHADERS::glsl_xor_diff_frag.c_str();
452
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 );
456
457 GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
458 GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
459
460 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): vertexShader=%u, fragmentShader=%u" ),
461 vertexShader, fragmentShader );
462
463 // Compile vertex shader
464 glShaderSource( vertexShader, 1, &vertexShaderSrc, nullptr );
465 glCompileShader( vertexShader );
466
467 GLint compiled;
468 glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &compiled );
469
470 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): vertex shader compile status=%d" ), compiled );
471
472 if( !compiled )
473 {
474 GLint logLen;
475 glGetShaderiv( vertexShader, GL_INFO_LOG_LENGTH, &logLen );
476
477 if( logLen > 0 )
478 {
479 char* log = new char[logLen];
480 glGetShaderInfoLog( vertexShader, logLen, nullptr, log );
481 wxLogTrace( traceGalXorMode, wxT( "Vertex shader compile error:\n%s" ), log );
482 delete[] log;
483 }
484
485 glDeleteShader( vertexShader );
486 glDeleteShader( fragmentShader );
487 return false;
488 }
489
490 // Compile fragment shader
491 glShaderSource( fragmentShader, 1, &fragmentShaderSrc, nullptr );
492 glCompileShader( fragmentShader );
493
494 glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &compiled );
495
496 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): fragment shader compile status=%d" ), compiled );
497
498 if( !compiled )
499 {
500 GLint logLen;
501 glGetShaderiv( fragmentShader, GL_INFO_LOG_LENGTH, &logLen );
502
503 if( logLen > 0 )
504 {
505 char* log = new char[logLen];
506 glGetShaderInfoLog( fragmentShader, logLen, nullptr, log );
507 wxLogTrace( traceGalXorMode, wxT( "Fragment shader compile error:\n%s" ), log );
508 delete[] log;
509 }
510
511 glDeleteShader( vertexShader );
512 glDeleteShader( fragmentShader );
513 return false;
514 }
515
516 // Create and link program
517 m_differenceShader = glCreateProgram();
518 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): created program=%u" ), m_differenceShader );
519
520 glAttachShader( m_differenceShader, vertexShader );
521 glAttachShader( m_differenceShader, fragmentShader );
522 glLinkProgram( m_differenceShader );
523
524 GLint linked;
525 glGetProgramiv( m_differenceShader, GL_LINK_STATUS, &linked );
526
527 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): link status=%d" ), linked );
528
529 // Clean up shader objects (they're now part of the program)
530 glDeleteShader( vertexShader );
531 glDeleteShader( fragmentShader );
532
533 if( !linked )
534 {
535 GLint logLen;
536 glGetProgramiv( m_differenceShader, GL_INFO_LOG_LENGTH, &logLen );
537
538 if( logLen > 0 )
539 {
540 char* log = new char[logLen];
541 glGetProgramInfoLog( m_differenceShader, logLen, nullptr, log );
542 wxLogTrace( traceGalXorMode, wxT( "Shader program link error:\n%s" ), log );
543 delete[] log;
544 }
545
546 glDeleteProgram( m_differenceShader );
548 return false;
549 }
550
551 // Get uniform locations
552 m_diffSrcTexUniform = glGetUniformLocation( m_differenceShader, "srcTex" );
553 m_diffDstTexUniform = glGetUniformLocation( m_differenceShader, "dstTex" );
554
555 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): srcTexUniform=%d, dstTexUniform=%d" ),
557
559 wxLogTrace( traceGalXorMode, wxT( "initDifferenceShader(): SUCCESS" ) );
560 return true;
561}
562
563
565{
566 glMatrixMode( GL_MODELVIEW );
567 glPushMatrix();
568 glLoadIdentity();
569 glMatrixMode( GL_PROJECTION );
570 glPushMatrix();
571 glLoadIdentity();
572
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 );
580
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 );
587 glEnd();
588
589 glPopMatrix();
590 glMatrixMode( GL_MODELVIEW );
591 glPopMatrix();
592}
593
594
595void OPENGL_COMPOSITOR::DrawBufferDifference( unsigned int aSourceHandle, unsigned int aDestHandle )
596{
597 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference() called: src=%u, dst=%u" ),
598 aSourceHandle, aDestHandle );
599 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): initialized=%d, usedBuffers=%u" ),
601
602 wxCHECK( m_initialized && aSourceHandle != 0 && aSourceHandle <= usedBuffers(), /* void */ );
603 wxCHECK( aDestHandle != 0 && aDestHandle <= usedBuffers(), /* void */ );
604
605 // Initialize shader on first use
606 if( !initDifferenceShader() )
607 {
608 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): shader init FAILED, falling back" ) );
609 // Fallback to regular DrawBuffer if shader fails
610 DrawBuffer( aSourceHandle, aDestHandle );
611 return;
612 }
613
614 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): shader initialized OK" ) );
615
616 // Get the texture targets directly from the buffers
617 GLuint srcTexture = m_buffers[aSourceHandle - 1].textureTarget;
618 GLuint dstTexture = m_buffers[aDestHandle - 1].textureTarget;
619
620 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): srcTexture=%u, dstTexture=%u" ),
621 srcTexture, dstTexture );
622
623 // We only need to copy the destination since we're writing to it.
624 // The source can be read directly via texture sampling
625 VECTOR2I dims = m_buffers[aDestHandle - 1].dimensions;
626 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): buffer dims=%dx%d" ), dims.x, dims.y );
627
628 // Create temp texture for destination copy (we can't read and write same texture)
629 GLuint dstTempTex;
630 glGenTextures( 1, &dstTempTex );
631 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): created dstTempTex=%u" ), dstTempTex );
632
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__ );
639
640 // Copy destination buffer to temp texture
641 bindFb( m_mainFbo );
642 GLenum destAttachment = m_buffers[aDestHandle - 1].attachmentPoint;
643 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): dest attachment point=0x%X" ), destAttachment );
644
645 glReadBuffer( destAttachment );
646 checkGlError( "setting read buffer for dst copy", __FILE__, __LINE__ );
647
648 glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, dims.x, dims.y );
649 checkGlError( "copying dest to temp texture", __FILE__, __LINE__ );
650
651 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): copied dest buffer to dstTempTex" ) );
652
653 // Set up for rendering with difference shader
654 SetBuffer( aDestHandle );
655 glDisable( GL_DEPTH_TEST );
656 glDisable( GL_BLEND );
657
658 // Use the difference shader
659 glUseProgram( m_differenceShader );
660 checkGlError( "using difference shader program", __FILE__, __LINE__ );
661
662 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): activated shader program=%u" ),
664
665 // Bind source texture to unit 0
666 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): binding srcTexture=%u to unit 0" ), srcTexture );
667
668 glActiveTexture( GL_TEXTURE0 );
669 glBindTexture( GL_TEXTURE_2D, srcTexture );
670 glUniform1i( m_diffSrcTexUniform, 0 );
671 checkGlError( "binding source texture for XOR mode", __FILE__, __LINE__ );
672
673 // Bind destination copy to unit 1
674 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): binding dstTempTex=%u to unit 1" ), dstTempTex );
675
676 glActiveTexture( GL_TEXTURE1 );
677 glBindTexture( GL_TEXTURE_2D, dstTempTex );
678 glUniform1i( m_diffDstTexUniform, 1 );
679 checkGlError( "binding dest texture for XOR mode", __FILE__, __LINE__ );
680
681 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): drawing fullscreen quad" ) );
682
683 // Important: Set GL_TEXTURE0 as active before drawing so that glTexCoord2f
684 // sets gl_MultiTexCoord0 (which the vertex shader reads), not gl_MultiTexCoord1
685 glActiveTexture( GL_TEXTURE0 );
686
687 // Draw the fullscreen quad
689 checkGlError( "drawing fullscreen quad for XOR mode", __FILE__, __LINE__ );
690
691 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): cleanup" ) );
692
693 // Cleanup
694 glUseProgram( 0 );
695 glDeleteTextures( 1, &dstTempTex );
696
697 glActiveTexture( GL_TEXTURE0 );
698 glEnable( GL_BLEND );
699 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
700
701 wxLogTrace( traceGalXorMode, wxT( "DrawBufferDifference(): COMPLETE" ) );
702}
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
double r
Red component.
Definition color4d.h:389
double g
Green component.
Definition color4d.h:390
static const COLOR4D BLACK
Definition color4d.h:402
double b
Blue component.
Definition color4d.h:391
unsigned int m_height
Height of the buffer (in pixels)
Definition compositor.h:109
unsigned int m_width
Width of the buffer (in pixels)
Definition compositor.h:108
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:70
The Cairo implementation of the graphics abstraction layer.
Definition eda_group.h:29
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:44
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682