You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
8.4 KiB

11 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright 2013-2017 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. #include <gal/opengl/gpu_manager.h>
  25. #include <gal/opengl/cached_container_gpu.h>
  26. #include <gal/opengl/cached_container_ram.h>
  27. #include <gal/opengl/noncached_container.h>
  28. #include <gal/opengl/shader.h>
  29. #include <gal/opengl/utils.h>
  30. #include <typeinfo>
  31. #include <confirm.h>
  32. #ifdef __WXDEBUG__
  33. #include <profile.h>
  34. #include <wx/log.h>
  35. #endif /* __WXDEBUG__ */
  36. using namespace KIGFX;
  37. GPU_MANAGER* GPU_MANAGER::MakeManager( VERTEX_CONTAINER* aContainer )
  38. {
  39. if( aContainer->IsCached() )
  40. return new GPU_CACHED_MANAGER( aContainer );
  41. else
  42. return new GPU_NONCACHED_MANAGER( aContainer );
  43. }
  44. GPU_MANAGER::GPU_MANAGER( VERTEX_CONTAINER* aContainer ) :
  45. m_isDrawing( false ), m_container( aContainer ), m_shader( NULL ), m_shaderAttrib( 0 ), m_enableDepthTest( true )
  46. {
  47. }
  48. GPU_MANAGER::~GPU_MANAGER()
  49. {
  50. }
  51. void GPU_MANAGER::SetShader( SHADER& aShader )
  52. {
  53. m_shader = &aShader;
  54. m_shaderAttrib = m_shader->GetAttribute( "attrShaderParams" );
  55. if( m_shaderAttrib == -1 )
  56. {
  57. DisplayError( NULL, wxT( "Could not get the shader attribute location" ) );
  58. }
  59. }
  60. // Cached manager
  61. GPU_CACHED_MANAGER::GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
  62. GPU_MANAGER( aContainer ), m_buffersInitialized( false ), m_indicesPtr( NULL ),
  63. m_indicesBuffer( 0 ), m_indicesSize( 0 ), m_indicesCapacity( 0 )
  64. {
  65. // Allocate the biggest possible buffer for indices
  66. resizeIndices( aContainer->GetSize() );
  67. }
  68. GPU_CACHED_MANAGER::~GPU_CACHED_MANAGER()
  69. {
  70. if( m_buffersInitialized )
  71. {
  72. if( glBindBuffer )
  73. glBindBuffer( GL_ARRAY_BUFFER, 0 );
  74. if( glDeleteBuffers )
  75. glDeleteBuffers( 1, &m_indicesBuffer );
  76. }
  77. }
  78. void GPU_CACHED_MANAGER::BeginDrawing()
  79. {
  80. wxASSERT( !m_isDrawing );
  81. if( !m_buffersInitialized )
  82. {
  83. glGenBuffers( 1, &m_indicesBuffer );
  84. checkGlError( "generating vertices buffer" );
  85. m_buffersInitialized = true;
  86. }
  87. if( m_container->IsDirty() )
  88. resizeIndices( m_container->GetSize() );
  89. // Number of vertices to be drawn in the EndDrawing()
  90. m_indicesSize = 0;
  91. // Set the indices pointer to the beginning of the indices-to-draw buffer
  92. m_indicesPtr = m_indices.get();
  93. m_isDrawing = true;
  94. }
  95. void GPU_CACHED_MANAGER::DrawIndices( unsigned int aOffset, unsigned int aSize )
  96. {
  97. wxASSERT( m_isDrawing );
  98. // Copy indices of items that should be drawn to GPU memory
  99. for( unsigned int i = aOffset; i < aOffset + aSize; *m_indicesPtr++ = i++ );
  100. m_indicesSize += aSize;
  101. }
  102. void GPU_CACHED_MANAGER::DrawAll()
  103. {
  104. wxASSERT( m_isDrawing );
  105. for( unsigned int i = 0; i < m_indicesSize; *m_indicesPtr++ = i++ );
  106. m_indicesSize = m_container->GetSize();
  107. }
  108. void GPU_CACHED_MANAGER::EndDrawing()
  109. {
  110. #ifdef __WXDEBUG__
  111. PROF_COUNTER totalRealTime;
  112. #endif /* __WXDEBUG__ */
  113. wxASSERT( m_isDrawing );
  114. CACHED_CONTAINER* cached = static_cast<CACHED_CONTAINER*>( m_container );
  115. if( cached->IsMapped() )
  116. cached->Unmap();
  117. if( m_indicesSize == 0 )
  118. {
  119. m_isDrawing = false;
  120. return;
  121. }
  122. if( m_enableDepthTest )
  123. glEnable( GL_DEPTH_TEST );
  124. else
  125. glDisable( GL_DEPTH_TEST );
  126. // Prepare buffers
  127. glEnableClientState( GL_VERTEX_ARRAY );
  128. glEnableClientState( GL_COLOR_ARRAY );
  129. // Bind vertices data buffers
  130. glBindBuffer( GL_ARRAY_BUFFER, cached->GetBufferHandle() );
  131. glVertexPointer( COORD_STRIDE, GL_FLOAT, VERTEX_SIZE, (GLvoid*) COORD_OFFSET );
  132. glColorPointer( COLOR_STRIDE, GL_UNSIGNED_BYTE, VERTEX_SIZE, (GLvoid*) COLOR_OFFSET );
  133. if( m_shader != NULL ) // Use shader if applicable
  134. {
  135. m_shader->Use();
  136. glEnableVertexAttribArray( m_shaderAttrib );
  137. glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE,
  138. VERTEX_SIZE, (GLvoid*) SHADER_OFFSET );
  139. }
  140. glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indicesBuffer );
  141. glBufferData( GL_ELEMENT_ARRAY_BUFFER, m_indicesSize * sizeof(int),
  142. (GLvoid*) m_indices.get(), GL_DYNAMIC_DRAW );
  143. glDrawElements( GL_TRIANGLES, m_indicesSize, GL_UNSIGNED_INT, 0 );
  144. #ifdef __WXDEBUG__
  145. wxLogTrace( "GAL_PROFILE", wxT( "Cached manager size: %d" ), m_indicesSize );
  146. #endif /* __WXDEBUG__ */
  147. glBindBuffer( GL_ARRAY_BUFFER, 0 );
  148. glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
  149. cached->ClearDirty();
  150. // Deactivate vertex array
  151. glDisableClientState( GL_COLOR_ARRAY );
  152. glDisableClientState( GL_VERTEX_ARRAY );
  153. if( m_shader != NULL )
  154. {
  155. glDisableVertexAttribArray( m_shaderAttrib );
  156. m_shader->Deactivate();
  157. }
  158. m_isDrawing = false;
  159. #ifdef __WXDEBUG__
  160. totalRealTime.Stop();
  161. wxLogTrace( "GAL_PROFILE",
  162. wxT( "GPU_CACHED_MANAGER::EndDrawing(): %.1f ms" ), totalRealTime.msecs() );
  163. #endif /* __WXDEBUG__ */
  164. }
  165. void GPU_CACHED_MANAGER::resizeIndices( unsigned int aNewSize )
  166. {
  167. if( aNewSize > m_indicesCapacity )
  168. {
  169. m_indicesCapacity = aNewSize;
  170. m_indices.reset( new GLuint[m_indicesCapacity] );
  171. }
  172. }
  173. // Noncached manager
  174. GPU_NONCACHED_MANAGER::GPU_NONCACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
  175. GPU_MANAGER( aContainer )
  176. {
  177. }
  178. void GPU_NONCACHED_MANAGER::BeginDrawing()
  179. {
  180. // Nothing has to be prepared
  181. }
  182. void GPU_NONCACHED_MANAGER::DrawIndices( unsigned int aOffset, unsigned int aSize )
  183. {
  184. wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
  185. }
  186. void GPU_NONCACHED_MANAGER::DrawAll()
  187. {
  188. // This is the default use case, nothing has to be done
  189. // The real rendering takes place in the EndDrawing() function
  190. }
  191. void GPU_NONCACHED_MANAGER::EndDrawing()
  192. {
  193. #ifdef __WXDEBUG__
  194. PROF_COUNTER totalRealTime;
  195. #endif /* __WXDEBUG__ */
  196. if( m_container->GetSize() == 0 )
  197. return;
  198. VERTEX* vertices = m_container->GetAllVertices();
  199. GLfloat* coordinates = (GLfloat*) ( vertices );
  200. GLubyte* colors = (GLubyte*) ( vertices ) + COLOR_OFFSET;
  201. if( m_enableDepthTest )
  202. glEnable( GL_DEPTH_TEST );
  203. else
  204. glDisable( GL_DEPTH_TEST );
  205. // Prepare buffers
  206. glEnableClientState( GL_VERTEX_ARRAY );
  207. glEnableClientState( GL_COLOR_ARRAY );
  208. glVertexPointer( COORD_STRIDE, GL_FLOAT, VERTEX_SIZE, coordinates );
  209. glColorPointer( COLOR_STRIDE, GL_UNSIGNED_BYTE, VERTEX_SIZE, colors );
  210. if( m_shader != NULL ) // Use shader if applicable
  211. {
  212. GLfloat* shaders = (GLfloat*) ( vertices ) + SHADER_OFFSET / sizeof(GLfloat);
  213. m_shader->Use();
  214. glEnableVertexAttribArray( m_shaderAttrib );
  215. glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE,
  216. VERTEX_SIZE, shaders );
  217. }
  218. glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() );
  219. #ifdef __WXDEBUG__
  220. wxLogTrace( "GAL_PROFILE", wxT( "Noncached manager size: %d" ), m_container->GetSize() );
  221. #endif /* __WXDEBUG__ */
  222. // Deactivate vertex array
  223. glDisableClientState( GL_COLOR_ARRAY );
  224. glDisableClientState( GL_VERTEX_ARRAY );
  225. if( m_shader != NULL )
  226. {
  227. glDisableVertexAttribArray( m_shaderAttrib );
  228. m_shader->Deactivate();
  229. }
  230. m_container->Clear();
  231. #ifdef __WXDEBUG__
  232. totalRealTime.Stop();
  233. wxLogTrace( "GAL_PROFILE",
  234. wxT( "GPU_NONCACHED_MANAGER::EndDrawing(): %.1f ms" ), totalRealTime.msecs() );
  235. #endif /* __WXDEBUG__ */
  236. }
  237. void GPU_MANAGER::EnableDepthTest( bool aEnabled )
  238. {
  239. m_enableDepthTest = aEnabled;
  240. }