KiCad PCB EDA Suite
gpu_manager.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-2016 CERN
5  * @author Maciej Suminski <maciej.suminski@cern.ch>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
30 #include <gal/opengl/gpu_manager.h>
33 #include <gal/opengl/shader.h>
34 #include <gal/opengl/utils.h>
35 
36 #include <typeinfo>
37 #include <confirm.h>
38 
39 #ifdef __WXDEBUG__
40 #include <profile.h>
41 #include <wx/log.h>
42 #endif /* __WXDEBUG__ */
43 
44 using namespace KIGFX;
45 
47 {
48  if( typeid( *aContainer ) == typeid( CACHED_CONTAINER ) )
49  return new GPU_CACHED_MANAGER( aContainer );
50  else if( typeid( *aContainer ) == typeid( NONCACHED_CONTAINER ) )
51  return new GPU_NONCACHED_MANAGER( aContainer );
52 
53  wxASSERT_MSG( false, wxT( "Not handled container type" ) );
54  return NULL;
55 }
56 
57 
59  m_isDrawing( false ), m_container( aContainer ), m_shader( NULL ), m_shaderAttrib( 0 )
60 {
61 }
62 
63 
65 {
66 }
67 
68 
70 {
71  m_shader = &aShader;
72  m_shaderAttrib = m_shader->GetAttribute( "attrShaderParams" );
73 
74  if( m_shaderAttrib == -1 )
75  {
76  DisplayError( NULL, wxT( "Could not get the shader attribute location" ) );
77  }
78 }
79 
80 
81 // Cached manager
83  GPU_MANAGER( aContainer ), m_buffersInitialized( false ), m_indicesPtr( NULL ),
84  m_indicesBuffer( 0 ), m_indicesSize( 0 ), m_indicesCapacity( 0 )
85 {
86  // Allocate the biggest possible buffer for indices
87  resizeIndices( aContainer->GetSize() );
88 }
89 
90 
92 {
94  {
95  glBindBuffer( GL_ARRAY_BUFFER, 0 );
96  glDeleteBuffers( 1, &m_indicesBuffer );
97  }
98 }
99 
100 
102 {
103  wxASSERT( !m_isDrawing );
104 
105  if( !m_buffersInitialized )
106  {
107  glGenBuffers( 1, &m_indicesBuffer );
108  checkGlError( "generating vertices buffer" );
109  m_buffersInitialized = true;
110  }
111 
112  if( m_container->IsDirty() )
114 
115  // Number of vertices to be drawn in the EndDrawing()
116  m_indicesSize = 0;
117  // Set the indices pointer to the beginning of the indices-to-draw buffer
118  m_indicesPtr = m_indices.get();
119 
120  m_isDrawing = true;
121 }
122 
123 
124 void GPU_CACHED_MANAGER::DrawIndices( unsigned int aOffset, unsigned int aSize )
125 {
126  wxASSERT( m_isDrawing );
127 
128  // Copy indices of items that should be drawn to GPU memory
129  for( unsigned int i = aOffset; i < aOffset + aSize; *m_indicesPtr++ = i++ );
130 
131  m_indicesSize += aSize;
132 }
133 
134 
136 {
137  wxASSERT( m_isDrawing );
138 
139  for( unsigned int i = 0; i < m_indicesSize; *m_indicesPtr++ = i++ );
140 
141  m_indicesSize = m_container->GetSize();
142 }
143 
144 
146 {
147 #ifdef __WXDEBUG__
148  PROF_COUNTER totalRealTime;
149 #endif /* __WXDEBUG__ */
150 
151  wxASSERT( m_isDrawing );
152 
153  CACHED_CONTAINER* cached = static_cast<CACHED_CONTAINER*>( m_container );
154 
155  if( cached->IsMapped() )
156  cached->Unmap();
157 
158  if( m_indicesSize == 0 )
159  {
160  m_isDrawing = false;
161  return;
162  }
163 
164  // Prepare buffers
165  glEnableClientState( GL_VERTEX_ARRAY );
166  glEnableClientState( GL_COLOR_ARRAY );
167 
168  // Bind vertices data buffers
169  glBindBuffer( GL_ARRAY_BUFFER, cached->GetBufferHandle() );
170  glVertexPointer( CoordStride, GL_FLOAT, VertexSize, 0 );
171  glColorPointer( ColorStride, GL_UNSIGNED_BYTE, VertexSize, (GLvoid*) ColorOffset );
172 
173  if( m_shader != NULL ) // Use shader if applicable
174  {
175  m_shader->Use();
176  glEnableVertexAttribArray( m_shaderAttrib );
177  glVertexAttribPointer( m_shaderAttrib, ShaderStride, GL_FLOAT, GL_FALSE,
178  VertexSize, (GLvoid*) ShaderOffset );
179  }
180 
181  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indicesBuffer );
182  glBufferData( GL_ELEMENT_ARRAY_BUFFER, m_indicesSize * sizeof(int),
183  (GLvoid*) m_indices.get(), GL_DYNAMIC_DRAW );
184 
185  glDrawElements( GL_TRIANGLES, m_indicesSize, GL_UNSIGNED_INT, 0 );
186 
187 #ifdef __WXDEBUG__
188  wxLogTrace( "GAL_PROFILE", wxT( "Cached manager size: %d" ), m_indicesSize );
189 #endif /* __WXDEBUG__ */
190 
191  glBindBuffer( GL_ARRAY_BUFFER, 0 );
192  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
193 
194  // Deactivate vertex array
195  glDisableClientState( GL_COLOR_ARRAY );
196  glDisableClientState( GL_VERTEX_ARRAY );
197 
198  if( m_shader != NULL )
199  {
200  glDisableVertexAttribArray( m_shaderAttrib );
201  m_shader->Deactivate();
202  }
203 
204  m_isDrawing = false;
205 
206 #ifdef __WXDEBUG__
207  totalRealTime.Stop();
208  wxLogTrace( "GAL_PROFILE",
209  wxT( "GPU_CACHED_MANAGER::EndDrawing(): %.1f ms" ), totalRealTime.msecs() );
210 #endif /* __WXDEBUG__ */
211 }
212 
213 
214 void GPU_CACHED_MANAGER::resizeIndices( unsigned int aNewSize )
215 {
216  if( aNewSize > m_indicesCapacity )
217  {
218  m_indicesCapacity = aNewSize;
219  m_indices.reset( new GLuint[m_indicesCapacity] );
220  }
221 }
222 
223 
224 // Noncached manager
226  GPU_MANAGER( aContainer )
227 {
228 }
229 
230 
232 {
233  // Nothing has to be prepared
234 }
235 
236 
237 void GPU_NONCACHED_MANAGER::DrawIndices( unsigned int aOffset, unsigned int aSize )
238 {
239  wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
240 }
241 
242 
244 {
245  // This is the default use case, nothing has to be done
246  // The real rendering takes place in the EndDrawing() function
247 }
248 
249 
251 {
252 #ifdef __WXDEBUG__
253  PROF_COUNTER totalRealTime;
254 #endif /* __WXDEBUG__ */
255 
256  if( m_container->GetSize() == 0 )
257  return;
258 
259  VERTEX* vertices = m_container->GetAllVertices();
260  GLfloat* coordinates = (GLfloat*) ( vertices );
261  GLubyte* colors = (GLubyte*) ( vertices ) + ColorOffset;
262 
263  // Prepare buffers
264  glEnableClientState( GL_VERTEX_ARRAY );
265  glEnableClientState( GL_COLOR_ARRAY );
266 
267  glVertexPointer( CoordStride, GL_FLOAT, VertexSize, coordinates );
268  glColorPointer( ColorStride, GL_UNSIGNED_BYTE, VertexSize, colors );
269 
270  if( m_shader != NULL ) // Use shader if applicable
271  {
272  GLfloat* shaders = (GLfloat*) ( vertices ) + ShaderOffset / sizeof(GLfloat);
273 
274  m_shader->Use();
275  glEnableVertexAttribArray( m_shaderAttrib );
276  glVertexAttribPointer( m_shaderAttrib, ShaderStride, GL_FLOAT, GL_FALSE,
277  VertexSize, shaders );
278  }
279 
280  glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() );
281 
282 #ifdef __WXDEBUG__
283  wxLogTrace( "GAL_PROFILE", wxT( "Noncached manager size: %d" ), m_container->GetSize() );
284 #endif /* __WXDEBUG__ */
285 
286  // Deactivate vertex array
287  glDisableClientState( GL_COLOR_ARRAY );
288  glDisableClientState( GL_VERTEX_ARRAY );
289 
290  if( m_shader != NULL )
291  {
292  glDisableVertexAttribArray( m_shaderAttrib );
293  m_shader->Deactivate();
294  }
295 
296 #ifdef __WXDEBUG__
297  totalRealTime.Stop();
298  wxLogTrace( "GAL_PROFILE",
299  wxT( "GPU_NONCACHED_MANAGER::EndDrawing(): %.1f ms" ), totalRealTime.msecs() );
300 #endif /* __WXDEBUG__ */
301 }
const size_t VertexSize
Definition: vertex_common.h:57
void Stop()
save the time when this function was called, and set the counter stane to stop
Definition: profile.h:82
const size_t CoordStride
Definition: vertex_common.h:61
virtual ~GPU_MANAGER()
Definition: gpu_manager.cpp:64
virtual void SetShader(SHADER &aShader)
Function SetShader() Allows using shaders with the stored data.
Definition: gpu_manager.cpp:69
unsigned int m_indicesCapacity
Current indices buffer size
Definition: gpu_manager.h:144
Class CAIRO_GAL is the cairo implementation of the graphics abstraction layer.
Definition: class_module.h:56
This file is part of the common library.
int m_shaderAttrib
Location of shader attributes (for glVertexAttribPointer)
Definition: gpu_manager.h:96
Class to handle uploading vertices and indices to GPU in drawing purposes.
void Use()
Use the shader.
Definition: shader.h:130
unsigned int GetBufferHandle() const
Function GetBufferHandle() returns handle to the vertex buffer.
int checkGlError(const std::string &aInfo, bool aThrow)
Checks if one of recent OpenGL operations has failed.
Definition: utils.cpp:30
Class to store instances of VERTEX with caching.
bool m_buffersInitialized
Buffers initialization flag
Definition: gpu_manager.h:129
const size_t ShaderOffset
Definition: vertex_common.h:70
The class PROF_COUNTER is a small class to help profiling.
Definition: profile.h:45
VERTEX_CONTAINER * m_container
Container that stores vertices data.
Definition: gpu_manager.h:90
virtual VERTEX * GetAllVertices() const
Function GetAllVertices() returns all the vertices stored in the container.
virtual void EndDrawing() override
>
unsigned int m_indicesSize
Number of indices stored in the indices buffer
Definition: gpu_manager.h:141
virtual void DrawIndices(unsigned int aOffset, unsigned int aSize) override
>
GLuint m_indicesBuffer
Handle to indices buffer
Definition: gpu_manager.h:138
GLuint * m_indicesPtr
Pointer to the first free cell in the indices buffer
Definition: gpu_manager.h:135
GPU_NONCACHED_MANAGER(VERTEX_CONTAINER *aContainer)
virtual void DrawAll() override
>
virtual void BeginDrawing() override
>
static GPU_MANAGER * MakeManager(VERTEX_CONTAINER *aContainer)
Definition: gpu_manager.cpp:46
void Deactivate()
Deactivate the shader and use the default OpenGL program.
Definition: shader.h:139
const size_t ShaderStride
Definition: vertex_common.h:72
Class SHADER provides the access to the OpenGL shaders.
Definition: shader.h:74
int GetAttribute(const std::string &aAttributeName) const
Gets an attribute location.
Definition: shader.cpp:160
GPU_CACHED_MANAGER(VERTEX_CONTAINER *aContainer)
Definition: gpu_manager.cpp:82
virtual unsigned int GetSize() const
Function GetSize() returns amount of vertices currently stored in the container.
bool IsDirty()
Function IsDirty() returns information about container cache state.
virtual void DrawAll() override
>
double msecs() const
Definition: profile.h:124
virtual void EndDrawing() override
>
bool m_isDrawing
Drawing status flag.
Definition: gpu_manager.h:87
Class to store instances of VERTEX without caching.
virtual void DrawIndices(unsigned int aOffset, unsigned int aSize) override
>
const size_t ColorStride
Definition: vertex_common.h:67
SHADER * m_shader
Shader handling
Definition: gpu_manager.h:93
void resizeIndices(unsigned int aNewSize)
Resizes the indices buffer to aNewSize if necessary
GPU_MANAGER(VERTEX_CONTAINER *aContainer)
Definition: gpu_manager.cpp:58
bool IsMapped() const
Function IsMapped() returns true if vertex buffer is currently mapped.
virtual void BeginDrawing() override
>
const size_t ColorOffset
Definition: vertex_common.h:64
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:69
boost::scoped_array< GLuint > m_indices
Pointer to the current indices buffer
Definition: gpu_manager.h:132
static VRML_COLOR colors[VRML_COLOR_LAST]