KiCad PCB EDA Suite
Loading...
Searching...
No Matches
utils.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) 2016-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
23#include <confirm.h> // DisplayError
24
25#include <kicad_gl/kiglad.h> // Must be included first
26
27#include <gal/opengl/utils.h>
28
29#include <algorithm>
30#include <stdexcept>
31#include <wx/log.h> // wxLogTrace
32
33
41static const wxChar* const traceGalOpenGlError = wxT( "KICAD_GAL_OPENGL_ERROR" );
42
43
44int checkGlError( const std::string& aInfo, const char* aFile, int aLine, bool aThrow )
45{
46 int result = glGetError();
47 wxString errorMsg;
48
49 switch( result )
50 {
51 case GL_NO_ERROR:
52 // all good
53 break;
54
55 case GL_INVALID_ENUM:
56 errorMsg = wxString::Format( "Error: %s: invalid enum", aInfo );
57 break;
58
59 case GL_INVALID_VALUE:
60 errorMsg = wxString::Format( "Error: %s: invalid value", aInfo );
61 break;
62
63 case GL_INVALID_OPERATION:
64 errorMsg = wxString::Format( "Error: %s: invalid operation", aInfo );
65 break;
66
67 case GL_INVALID_FRAMEBUFFER_OPERATION:
68 {
69 GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
70
71 if( status != GL_FRAMEBUFFER_COMPLETE )
72 {
73 switch( status )
74 {
75 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
76 errorMsg = "The framebuffer attachment points are incomplete.";
77 break;
78
79 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
80 errorMsg = "No images attached to the framebuffer.";
81 break;
82
83 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
84 errorMsg = "The framebuffer does not have at least one image attached to it.";
85 break;
86
87 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
88 errorMsg = "The framebuffer read buffer is incomplete.";
89 break;
90
91 case GL_FRAMEBUFFER_UNSUPPORTED:
92 errorMsg = "The combination of internal formats of the attached images violates "
93 "an implementation dependent set of restrictions.";
94 break;
95
96 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
97 errorMsg = "GL_RENDERBUFFER_SAMPLES is not the same for all attached render "
98 "buffers.";
99 break;
100
101 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
102 errorMsg = "Framebuffer incomplete layer targets errors.";
103 break;
104
105 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
106 errorMsg = "Framebuffer attachments have different dimensions";
107 break;
108
109 default:
110 errorMsg.Printf( "Unknown incomplete framebuffer error id %X", status );
111 }
112 }
113 else
114 {
115 errorMsg = wxString::Format( "Error: %s: invalid framebuffer operation", aInfo );
116 }
117 }
118 break;
119
120 case GL_OUT_OF_MEMORY:
121 errorMsg = wxString::Format( "Error: %s: out of memory", aInfo );
122 break;
123
124 case GL_STACK_UNDERFLOW:
125 errorMsg = wxString::Format( "Error: %s: stack underflow", aInfo );
126 break;
127
128 case GL_STACK_OVERFLOW:
129 errorMsg = wxString::Format( "Error: %s: stack overflow", aInfo );
130 break;
131
132 default:
133 errorMsg = wxString::Format( "Error: %s: unknown error", aInfo );
134 break;
135 }
136
137 if( result != GL_NO_ERROR )
138 {
139 if( aThrow )
140 {
141 wxLogTrace( traceGalOpenGlError, wxT( "Throwing exception for glGetError() '%s' "
142 "in file '%s' on line %d." ),
143 errorMsg,
144 aFile,
145 aLine );
146
147 throw std::runtime_error( (const char*) errorMsg.char_str() );
148 }
149 else
150 {
151 wxString msg = wxString::Format( wxT( "glGetError() '%s' in file '%s' on line %d." ),
152 errorMsg,
153 aFile,
154 aLine );
155
156 DisplayErrorMessage( nullptr, "OpenGL Error", msg );
157 }
158 }
159
160 return result;
161}
162
163
164// debugMsgCallback is a callback function for glDebugMessageCallback.
165// It must have the right type ( GLAPIENTRY )
166static void GLAPIENTRY debugMsgCallback( GLenum aSource, GLenum aType, GLuint aId, GLenum aSeverity,
167 GLsizei aLength, const GLchar* aMessage,
168 const void* aUserParam )
169{
170 switch( aSeverity )
171 {
172 case GL_DEBUG_SEVERITY_HIGH:
173 wxLogTrace( traceGalOpenGlError, wxS( "OpenGL ERROR: %s" ), aMessage );
174 break;
175 case GL_DEBUG_SEVERITY_MEDIUM:
176 wxLogTrace( traceGalOpenGlError, wxS( "OpenGL WARNING: %s" ), aMessage );
177 break;
178 case GL_DEBUG_SEVERITY_LOW:
179 wxLogTrace( traceGalOpenGlError, wxS( "OpenGL INFO: %s" ), aMessage );
180 break;
181 case GL_DEBUG_SEVERITY_NOTIFICATION:
182 return;
183 }
184}
185
186
187void enableGlDebug( bool aEnable )
188{
189 if( aEnable )
190 {
191 glEnable( GL_DEBUG_OUTPUT );
192 glDebugMessageCallback( (GLDEBUGPROC) debugMsgCallback, nullptr );
193 }
194 else
195 {
196 glDisable( GL_DEBUG_OUTPUT );
197 }
198}
199
200
201namespace KIGFX
202{
203
205{
206 GLint availableKiB = 0;
207
208 if( GLAD_GL_NVX_gpu_memory_info )
209 {
210 glGetIntegerv( GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &availableKiB );
211 }
212 else if( GLAD_GL_ATI_meminfo )
213 {
214 GLint info[4] = { 0, 0, 0, 0 };
215 glGetIntegerv( GL_VBO_FREE_MEMORY_ATI, info );
216 availableKiB = info[0];
217 }
218 else
219 {
220 return 0;
221 }
222
223 // Swallow any error a driver that advertises but mishandles the query may raise, so it
224 // does not leak into the next checkGlError().
225 glGetError();
226
227 if( availableKiB <= 0 )
228 return 0;
229
230 return static_cast<size_t>( availableKiB ) * 1024;
231}
232
233
234VRAM_RESIZE_STRATEGY chooseResizeStrategy( size_t aFreeVRAM, size_t aOldBytes, size_t aNewBytes,
235 double aMarginFrac )
236{
237 // With no driver information, keep the historical fast path so non-NVIDIA/AMD GPUs are
238 // unaffected.
239 if( aFreeVRAM == 0 )
241
242 const double margin = 1.0 + std::max( 0.0, aMarginFrac );
243
244 if( static_cast<double>( aFreeVRAM ) >= static_cast<double>( aOldBytes + aNewBytes ) * margin )
246
247 if( static_cast<double>( aFreeVRAM ) >= static_cast<double>( aNewBytes ) * margin )
249
251}
252
253} // namespace KIGFX
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
This file is part of the common library.
static const wxChar *const traceGalOpenGlError
Flag to enable debug output of the GAL OpenGL error checking.
Definition utils.cpp:41
The Cairo implementation of the graphics abstraction layer.
Definition eda_group.h:29
VRAM_RESIZE_STRATEGY
Strategy for growing a GPU vertex buffer, trading copy speed against peak video memory.
Definition utils.h:58
@ REFUSE
Neither path fits; the caller should fall back to software rendering.
Definition utils.h:61
@ GPU_COPY
Fast GPU-side copy; the old and new buffers are briefly co-resident.
Definition utils.h:59
@ RAM_STAGE
Stage through host memory so only the larger of the two buffers is resident.
Definition utils.h:60
VRAM_RESIZE_STRATEGY chooseResizeStrategy(size_t aFreeVRAM, size_t aOldBytes, size_t aNewBytes, double aMarginFrac)
Decide how to grow a GPU vertex buffer given the free video memory budget.
Definition utils.cpp:234
size_t queryFreeVideoMemoryBytes()
Query the amount of free video memory the driver reports.
Definition utils.cpp:204
wxString result
Test unit parsing edge cases and error handling.
void enableGlDebug(bool aEnable)
Enable or disable OpenGL driver messages output.
Definition utils.cpp:187
static void GLAPIENTRY debugMsgCallback(GLenum aSource, GLenum aType, GLuint aId, GLenum aSeverity, GLsizei aLength, const GLchar *aMessage, const void *aUserParam)
Definition utils.cpp:166
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