Developer Documentation
globjects.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40  \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44  * $Revision$ *
45  * $LastChangedBy$ *
46  * $Date$ *
47  * *
48  \*===========================================================================*/
49 
50 #include <ACG/GL/acg_glew.hh>
51 #include <ACG/GL/globjects.hh>
52 #include <ACG/GL/GLFormatInfo.hh>
53 #include <ACG/ShaderUtils/GLSLShader.hh>
54 
55 #include <QImage>
56 #include <QGLWidget>
57 
58 namespace ACG {
59 
60 
61 //-----------------------------------------------------------------------------
62 
63 Texture::Texture( GLenum tgt, GLenum _unit )
64  : target(tgt), unit(_unit), valid(false), texture(0u), internalFormat_(0)
65 {
66 }
67 
68 void Texture::bindAsImage(GLuint _index, GLenum _access)
69 {
70 #if defined(GL_ARB_shader_image_load_store)
71  if (is_valid())
72  glBindImageTexture(_index, id(), 0, GL_FALSE, 0, _access, getInternalFormat());
73  else
74  std::cerr << "Texture::bindAsImage - error: texture not initialized!" << std::endl;
75 #else
76  std::cerr << "Texture::bindAsImage - glBindImageTexture symbol not loaded!" << std::endl;
77 #endif
78 }
79 
80 
81 GLint Texture::getInternalFormat()
82 {
83  if (!internalFormat_)
84  {
85  bind();
86  glGetTexLevelParameteriv(target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat_);
87  }
88 
89  return internalFormat_;
90 }
91 //
92 // bool Texture::clear( float _color )
93 // {
94 // #ifdef GL_ARB_clear_texture
95 // if (supportsClearTexture() && texture)
96 // {
97 // glClearTexImage(texture, 0, GL_R32F, GL_FLOAT, &_color);
98 // return true;
99 // }
100 // #endif
101 // return false;
102 // }
103 //
104 // bool Texture::clear( const ACG::Vec2f& _color )
105 // {
106 // #ifdef GL_ARB_clear_texture
107 // if (supportsClearTexture() && texture)
108 // {
109 // glClearTexImage(texture, 0, GL_RG32F, GL_FLOAT, _color.data());
110 // return true;
111 // }
112 // #endif
113 // return false;
114 // }
115 //
116 // bool Texture::clear( const ACG::Vec3f& _color )
117 // {
118 // #ifdef GL_ARB_clear_texture
119 // if (supportsClearTexture() && texture)
120 // {
121 // glClearTexImage(texture, 0, GL_RGB32F, GL_FLOAT, _color.data());
122 // return true;
123 // }
124 // #endif
125 // return false;
126 // }
127 
128 bool Texture::clear( const ACG::Vec4f& _color )
129 {
130 #ifdef GL_ARB_clear_texture
131  if (supportsClearTexture() && texture)
132  {
133  glClearTexImage(texture, 0, GL_RGBA, GL_FLOAT, _color.data());
134  return true;
135  }
136 #endif
137  return false;
138 }
139 
140 bool Texture::clear( const ACG::Vec4ui& _color )
141 {
142 #ifdef GL_ARB_clear_texture
143  if (supportsClearTexture() && texture)
144  {
145  glClearTexImage(texture, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, _color.data());
146  return true;
147  }
148 #endif
149  return false;
150 }
151 
152 bool Texture::clear( const ACG::Vec4i& _color )
153 {
154 #ifdef GL_ARB_clear_texture
155  if (supportsClearTexture() && texture)
156  {
157  glClearTexImage(texture, 0, GL_RGBA_INTEGER, GL_INT, _color.data());
158  return true;
159  }
160 #endif
161  return false;
162 }
163 
164 bool Texture::supportsImageLoadStore()
165 {
166  static int status = -1;
167 
168  if (status < 0)
169  {
170 #if defined(GL_ARB_shader_image_load_store)
171  // core in version 4.2
172  status = checkExtensionSupported("ARB_shader_image_load_store") || openGLVersion(4,2);
173 #else
174  // symbol missing, install latest glew version
175  status = 0;
176 #endif
177  }
178 
179  return status > 0;
180 }
181 
182 
183 bool Texture::supportsTextureBuffer()
184 {
185  static int status = -1;
186 
187  if (status < 0)
188  {
189 #if defined(GL_ARB_texture_buffer_object)
190  // core in version 3.0
191  status = checkExtensionSupported("ARB_texture_buffer_object") || openGLVersion(3,0);
192 #else
193  // symbol missing, install latest glew version
194  status = 0;
195 #endif
196  }
197 
198  return status > 0;
199 }
200 
201 
202 bool Texture::supportsClearTexture()
203 {
204  static int status = -1;
205 
206  if (status < 0)
207  {
208 #if defined(GL_ARB_clear_texture)
209  status = checkExtensionSupported("ARB_clear_texture");
210 #else
211  // symbol missing, install latest glew version
212  status = 0;
213 #endif
214  }
215 
216  return status > 0;
217 }
218 
219 bool Texture::supportsGenerateMipmap()
220 {
221  static int status = -1;
222 
223  if (status < 0)
224  {
225 #if defined(GL_SGIS_generate_mipmap)
226  status = checkExtensionSupported("GL_SGIS_generate_mipmap");
227 #else
228  // symbol missing, install latest glew version
229  status = 0;
230 #endif
231  }
232 
233  return status > 0;
234 }
235 
236 //-----------------------------------------------------------------------------
237 
238 
239 Texture1D::Texture1D( GLenum unit ) : Texture(GL_TEXTURE_1D, unit),
240  width_(0),
241  format_(0), type_(0)
242 {}
243 
244 void Texture1D::setData(GLint _level,
245  GLint _internalFormat,
246  GLsizei _width,
247  GLenum _format,
248  GLenum _type,
249  const GLvoid* _data) {
250 
251  bind();
252 
253  glTexImage1D(GL_TEXTURE_1D, _level, _internalFormat, _width, 0, _format, _type, _data);
254 
255  width_ = _width;
256  internalFormat_ = _internalFormat;
257  format_ = _format;
258  type_ = _type;
259 }
260 
261 
262 void Texture1D::setStorage( GLsizei _levels, GLenum _internalFormat, GLsizei _width ) {
263 #ifdef GL_ARB_texture_storage
264  bind();
265  glTexStorage1D(GL_TEXTURE_1D, _levels, _internalFormat, _width);
266 
267  width_ = _width;
268  internalFormat_ = _internalFormat;
269 
270  GLFormatInfo finfo(_internalFormat);
271  format_ = finfo.format();
272  type_ = finfo.type();
273 #endif // GL_ARB_texture_storage
274 }
275 
276 
277 bool Texture1D::getData( GLint _level, void* _dst ) {
278  if (is_valid()) {
279  GLint curTex = 0;
280  glGetIntegerv(GL_TEXTURE_BINDING_1D, &curTex);
281 
282  bind();
283  glGetTexImage(GL_TEXTURE_1D, _level, format_, type_, _dst);
284 
285  glBindTexture(GL_TEXTURE_1D, curTex);
286 
287  return true;
288  }
289  return false;
290 }
291 
292 bool Texture1D::getData( GLint _level, std::vector<char>& _dst ) {
293  if (is_valid()) {
294 
295  GLFormatInfo finfo(internalFormat_);
296 
297  if (finfo.isValid()) {
298  size_t bufSize = finfo.elemSize() * width_;
299 
300  if (_dst.size() < bufSize)
301  _dst.resize(bufSize);
302 
303  if (!_dst.empty())
304  return getData(_level, &_dst[0]);
305  }
306  }
307  return false;
308 }
309 
310 
311 
312 
313 
314 //-----------------------------------------------------------------------------
315 
316 Texture2D::Texture2D(GLenum unit)
317  : Texture(GL_TEXTURE_2D, unit),
318  width_(0), height_(0),
319  format_(0), type_(0),
320  buildMipsCPU_(false)
321 {}
322 
323 //-----------------------------------------------------------------------------
324 
325 bool Texture2D::autogenerateMipMaps()
326 {
327 #ifdef GL_SGIS_generate_mipmap
328  if (supportsGenerateMipmap())
329  {
330  parameter(GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
331  return true;
332  }
333 #endif
334  // hardware accelerated generation is not available, fall back to software implementation
335  buildMipsCPU_ = true;
336  return false;
337 }
338 
339 //-----------------------------------------------------------------------------
340 
341 void Texture2D::disableAutogenerateMipMaps()
342 {
343 #ifdef GL_SGIS_generate_mipmap
344  if (supportsGenerateMipmap())
345  parameter(GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
346 #endif
347  buildMipsCPU_ = false;
348 }
349 
350 //-----------------------------------------------------------------------------
351 
352 void Texture2D::setData(GLint _level,
353  GLint _internalFormat,
354  GLsizei _width,
355  GLsizei _height,
356  GLenum _format,
357  GLenum _type,
358  const GLvoid* _data) {
359 
360  if (getUnit() == GL_NONE)
361  setUnit(GL_TEXTURE0);
362 
363  bind();
364 
365  if (buildMipsCPU_ && _level == 0)
366  buildMipMaps(_internalFormat, _width, _height, _format, _type, _data);
367  else
368  glTexImage2D(GL_TEXTURE_2D, _level, _internalFormat, _width, _height, 0, _format, _type, _data);
369 
370  width_ = _width;
371  height_ = _height;
372  internalFormat_ = _internalFormat;
373  format_ = _format;
374  type_ = _type;
375 }
376 
377 
378 void Texture2D::setStorage( GLsizei _levels, GLenum _internalFormat, GLsizei _width, GLsizei _height ) {
379 #ifdef GL_ARB_texture_storage
380  bind();
381  glTexStorage2D(GL_TEXTURE_2D, _levels, _internalFormat, _width, _height);
382 
383  width_ = _width;
384  height_ = _height;
385  internalFormat_ = _internalFormat;
386 
387  GLFormatInfo finfo(_internalFormat);
388  format_ = finfo.format();
389  type_ = finfo.type();
390 #endif // GL_ARB_texture_storage
391 }
392 
393 
394 bool Texture2D::getData( GLint _level, void* _dst ) {
395  if (is_valid()) {
396  GLint curTex = 0;
397  glGetIntegerv(GL_TEXTURE_BINDING_2D, &curTex);
398 
399  bind();
400  glGetTexImage(GL_TEXTURE_2D, _level, format_, type_, _dst);
401 
402  glBindTexture(GL_TEXTURE_2D, curTex);
403 
404  return true;
405  }
406  return false;
407 }
408 
409 bool Texture2D::getData( GLint _level, std::vector<char>& _dst ) {
410  if (is_valid()) {
411 
412  GLFormatInfo finfo(internalFormat_);
413 
414  if (finfo.isValid()) {
415  size_t bufSize = finfo.elemSize() * width_ * height_;
416 
417  if (_dst.size() < bufSize)
418  _dst.resize(bufSize);
419 
420  if (!_dst.empty())
421  return getData(_level, &_dst[0]);
422  }
423  }
424  return false;
425 }
426 
427 template<class T>
428 void Texture2D_buildMipMaps_DataInterpreter(Vec4f* _dst, int _numChannels, int _srcOffset, const void* _src)
429 {
430  const T* dataT = static_cast<const T*>(_src);
431 
432  for (int i = 0; i < _numChannels; ++i)
433  (*_dst)[i] = float(dataT[_srcOffset + i]);
434 }
435 
436 void Texture2D::buildMipMaps( GLenum _internalfmt,
437  GLint _width,
438  GLint _height,
439  GLenum _format,
440  GLenum _type,
441  const void* _data )
442 {
443 // gluBuild2DMipmaps(_target, _internalfmt, _width, _height, _format, _type, _data);
444 // return;
445 //
446  if (_data)
447  {
448  GLFormatInfo finfo(_internalfmt);
449 
450  if (finfo.isValid() && (finfo.isFloat() || finfo.isNormalized()))
451  {
452  int numChannels = finfo.channelCount();
453 
454 
455  // avoid quantization error for smaller mipmaps
456  // -> treat image data as floats instead of normalized ubytes
457 
458 
459  // compute number of mipmaps
460 
461  Vec2i curSize = Vec2i(_width, _height);
462 
463  std::vector<int> mipMemsize(1, 0);
464  std::vector<Vec2i> mipSize(1, curSize);
465  // mipmap count is usually a small number, so push_back() shouldn't be problematic
466  mipMemsize.reserve(16);
467  mipSize.reserve(16);
468 
469  int numMips = 1; // first level
470 
471  // downscale width and height by 2 until 1x1 texture
472  while (curSize[0] > 1 || curSize[1] > 1)
473  {
474  for (int k = 0; k < 2; ++k)
475  curSize[k] = std::max(1, curSize[k] >> 1);
476 
477  // tex dimension
478  mipSize.push_back(curSize);
479 
480  // size in bytes
481  int numPixels = curSize[0] * curSize[1];
482  mipMemsize.push_back(numPixels * numChannels * 4);
483 
484  ++numMips;
485  }
486 
487  // compute size in bytes required for the complete mipmap chain starting at level 1
488  std::vector<int> mipOffset; // offset in bytes
489  mipOffset.reserve(16);
490  int totalMemSize = 0;
491  for (int mipID = 0; mipID < numMips; ++mipID)
492  {
493  mipOffset.push_back(totalMemSize);
494  totalMemSize += mipMemsize[mipID];
495  }
496 
497 
498  // alloc memory block for the mipmaps
499  std::vector<float> mipData(totalMemSize / 4);
500 
501  // downsample
502  for (int mipID = 1; mipID < numMips; ++mipID)
503  {
504  Vec2i srcSize = mipSize[mipID-1];
505  Vec2i dstSize = mipSize[mipID];
506 
507  int srcOffset = mipOffset[mipID-1];
508  int dstOffset = mipOffset[mipID];
509 
510  int dstNumPixels = dstSize[0] * dstSize[1];
511 
512  // loop is parallelizable, but synchronization overhead is too high
513 // #ifdef USE_OPENMP
514 // #pragma omp parallel for
515 // #endif // USE_OPENMP
516  for (int dstPixel = 0; dstPixel < dstNumPixels; ++dstPixel)
517  {
518  int x = dstPixel % dstSize[0];
519  int y = dstPixel / dstSize[0];
520 
521  Vec4f pixelData[4];
522 
523  Vec2i srcPixelPos[4] =
524  {
525  Vec2i(x * 2, y * 2), Vec2i(x * 2 + 1, y * 2),
526  Vec2i(x * 2, y * 2 + 1), Vec2i(x * 2 + 1, y * 2 + 1)
527  };
528 
529  Vec4f avgColor = Vec4f(0.0f, 0.0f, 0.0f, 0.0f);
530 
531  // load the four source pixels
532  for (int srcPixel = 0; srcPixel < 4; ++srcPixel)
533  {
534  // init with black
535  pixelData[srcPixel] = Vec4f(0.0f, 0.0f, 0.0f, 1.0f);
536 
537  // clamp pixel position
538  srcPixelPos[srcPixel][0] = std::min(srcPixelPos[srcPixel][0], srcSize[0] - 1);
539  srcPixelPos[srcPixel][1] = std::min(srcPixelPos[srcPixel][1], srcSize[1] - 1);
540 
541  // linear position of 2d pixel pos, row-major
542  int srcPixelPosLinear = srcSize[0] * srcPixelPos[srcPixel][1] + srcPixelPos[srcPixel][0];
543 
544  // interpret pixel of the input image based on type
545  if (mipID == 1)
546  {
547  switch ( _type )
548  {
549  case GL_DOUBLE: Texture2D_buildMipMaps_DataInterpreter<double>(pixelData + srcPixel, numChannels, srcPixelPosLinear * numChannels, _data); break;
550  case GL_FLOAT: Texture2D_buildMipMaps_DataInterpreter<float>(pixelData + srcPixel, numChannels, srcPixelPosLinear * numChannels, _data); break;
551  case GL_INT: Texture2D_buildMipMaps_DataInterpreter<int>(pixelData + srcPixel, numChannels, srcPixelPosLinear * numChannels, _data); break;
552  case GL_UNSIGNED_INT: Texture2D_buildMipMaps_DataInterpreter<unsigned int>(pixelData + srcPixel, numChannels, srcPixelPosLinear * numChannels, _data); break;
553  case GL_SHORT: Texture2D_buildMipMaps_DataInterpreter<short>(pixelData + srcPixel, numChannels, srcPixelPosLinear * numChannels, _data); break;
554  case GL_UNSIGNED_SHORT: Texture2D_buildMipMaps_DataInterpreter<unsigned short>(pixelData + srcPixel, numChannels, srcPixelPosLinear * numChannels, _data); break;
555  case GL_BYTE:
556  {
557  Texture2D_buildMipMaps_DataInterpreter<char>(pixelData + srcPixel, numChannels, srcPixelPosLinear * numChannels, _data);
558 
559  if (finfo.isNormalized())
560  pixelData[srcPixel] /= 127.0f;
561  } break;
562  case GL_UNSIGNED_BYTE:
563  {
564  Texture2D_buildMipMaps_DataInterpreter<unsigned char>(pixelData + srcPixel, numChannels, srcPixelPosLinear * numChannels, _data);
565 
566  if (finfo.isNormalized())
567  pixelData[srcPixel] /= 255.0f;
568  } break;
569 
570  default: std::cerr << "MipMaps: unknown data type: " << _type << std::endl;
571  }
572  }
573  else
574  {
575  // load from previously computed mipmap
576 
577  for (int c = 0; c < numChannels; ++c)
578  pixelData[srcPixel][c] = mipData[srcOffset/4 + srcPixelPosLinear * numChannels + c];
579  }
580 
581  avgColor += pixelData[srcPixel];
582  }
583 
584  avgColor *= 0.25f;
585 
586  // store average of the source pixels
587  int dstPixelPosLinear = y * dstSize[0] + x;
588  for (int c = 0; c < numChannels; ++c)
589  mipData[dstOffset / 4 + dstPixelPosLinear * numChannels + c] = avgColor[c];
590  }
591 
592  }
593 
594 
595  // upload mipmaps to gpu
596 
597  for (int mipID = 0; mipID < numMips; ++mipID)
598  {
599  // inpute image at level 0
600  const void* mipDataPtr = _data;
601  GLenum mipDataType = _type;
602 
603  if (mipID > 0)
604  {
605  // downsampled image at lower levels
606  // these are stored as float textures in memory
607  // glTexImage2D converts float data to the requested internal format
608  mipDataPtr = &mipData[mipOffset[mipID] / 4];
609  mipDataType = GL_FLOAT;
610  }
611 
612  glTexImage2D(getTarget(), mipID, _internalfmt, mipSize[mipID][0], mipSize[mipID][1], 0, _format, mipDataType, mipDataPtr);
613  }
614  }
615  }
616 }
617 
618 
619 bool Texture2D::loadFromFile( const std::string& _filename, GLenum _minFilter, GLenum _magFilter )
620 {
621  bool success = false;
622 
623  const int numMipmapEnums = 4;
624  GLenum mipmapEnums[numMipmapEnums] = {GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR};
625  bool mipmaps = false;
626 
627  for (int i = 0; i < numMipmapEnums; ++i)
628  mipmaps = mipmaps || _minFilter == mipmapEnums[i];
629 
630  if (!_filename.empty())
631  {
632  bind();
633 
634  QImage qtex;
635 
636  if (qtex.load(_filename.c_str()))
637  {
638  success = true;
639 
640  if (mipmaps)
641  autogenerateMipMaps();
642 
643  QImage gltex = QGLWidget::convertToGLFormat ( qtex );
644 
645  setData(0, GL_RGBA, gltex.width(), gltex.height(), GL_RGBA, GL_UNSIGNED_BYTE, gltex.bits());
646  }
647 
648  }
649 
650  if (success)
651  {
652  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _minFilter);
653  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _magFilter);
654  }
655 
656  return success;
657 }
658 
659 
660 void Texture2D::loadRandom( GLint _internalFormat, GLsizei _width, GLsizei _height )
661 {
662  ACG::GLFormatInfo finfo(_internalFormat);
663 
664  if (finfo.isValid() && _width && _height)
665  {
666  int n = _width * _height * finfo.channelCount();
667 
668  GLvoid* dataPtr = 0;
669 
670  std::vector<float> randF;
671  std::vector<int> randI;
672 
673  GLenum gltype = 0;
674 
675  if (finfo.isFloat() || finfo.isNormalized())
676  {
677  randF.resize(n);
678 
679  bool isSigned = finfo.isInt();
680 
681  for (int i = 0; i < n; ++i)
682  {
683  float r = float(rand()) / float(RAND_MAX);
684 
685  if (isSigned)
686  r = r * 2.0f - 1.0f;
687 
688  randF[i] = r;
689  }
690 
691  dataPtr = &randF[0];
692  gltype = GL_FLOAT;
693  }
694  else
695  {
696  randI.resize(n);
697 
698  for (int i = 0; i < n; ++i)
699  randI[i] = rand();
700 
701  dataPtr = &randI[0];
702  gltype = GL_INT;
703  }
704 
705  bind();
706  setData(0, _internalFormat, _width, _height, finfo.format(), gltype, dataPtr);
707  }
708 }
709 
710 bool Texture2D::checkTextureMem( GLenum _internalFormat, GLsizei _width, GLsizei _height, GLenum _format)
711 {
712  GLuint t = 0;
713  glGenTextures(1, &t);
714 
715  bool res = false;
716 
717  if (t)
718  {
719  GLint savedTex = 0;
720  glGetIntegerv(GL_TEXTURE_BINDING_2D, &savedTex);
721 
722 
723  glBindTexture(GL_TEXTURE_2D, t);
724  glTexImage2D(GL_PROXY_TEXTURE_2D, 0, _internalFormat, _width, _height, 0, _format, GL_FLOAT, 0);
725 
726  GLint w = 0;
727  glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
728  if (w)
729  res = true;
730 
731  glBindTexture(GL_TEXTURE_2D, savedTex);
732  glDeleteTextures(1, &t);
733  }
734 
735  return res;
736 }
737 
738 //-----------------------------------------------------------------------------
739 
740 #if defined(GL_ARB_vertex_buffer_object)
741 
742 void VertexBufferObject::del() {
743  if (valid)
744  glDeleteBuffersARB(1, &vbo);
745  valid = false;
746 }
747 
748 void VertexBufferObject::upload(
749  GLsizeiptr size, const GLvoid* data, GLenum usage) {
750 
751  if (!valid)
752  gen();
753 
754  bind();
755 
756  glBufferDataARB(target, size, data, usage);
757 }
758 
759 void VertexBufferObject::uploadSubData(
760  GLuint _offset, GLuint _size, const GLvoid* _data ) {
761 
762  glBufferSubDataARB(target, _offset, _size, _data);
763 }
764 
765 void VertexBufferObject::gen() {
766  glGenBuffersARB(1, &vbo);
767  if(vbo > 0u)
768  valid = true;
769 }
770 
771 int VertexBufferObject::size() {
772  bind();
773  int bufsize = 0;
774  glGetBufferParameteriv(target, GL_BUFFER_SIZE, &bufsize);
775  return bufsize;
776 }
777 
778 #endif
779 
780 
781 //-----------------------------------------------------------------------------
782 
783 TextureBuffer::TextureBuffer(GLenum u)
784  :
785 #if defined(GL_ARB_texture_buffer_object)
786 Texture(GL_TEXTURE_BUFFER, u),
787 #else
788 Texture(0, u),
789 #endif
790  bufferSize_(0), buffer_(0), usage_(0), fmt_(0) {
791 }
792 
793 
794 TextureBuffer::~TextureBuffer() {
795  if (buffer_)
796  glDeleteBuffers(1, &buffer_);
797 }
798 
799 void TextureBuffer::setBufferData(
800  int _size, const void* _data, GLenum _internalFormat, GLenum _usage) {
801 #if defined(GL_ARB_texture_buffer_object)
802  if (supportsTextureBuffer()) {
803  // setup buffer object
804  if (!buffer_)
805  glGenBuffers(1, &buffer_);
806 
807  glBindBuffer(GL_TEXTURE_BUFFER, buffer_);
808  glBufferData(GL_TEXTURE_BUFFER, _size, _data, _usage);
809 
810  usage_ = _usage;
811  fmt_ = _internalFormat;
812 
813  // bind buffer to texture
814  if (getUnit() == GL_NONE)
815  setUnit(GL_TEXTURE0);
816 
817  bind();
818 
819  glTexBuffer(GL_TEXTURE_BUFFER, _internalFormat, buffer_);
820 
821  bufferSize_ = _size;
822  }
823  else
824  std::cerr << "TextureBuffer::setData - gpu does not support buffer textures!" << std::endl;
825 #else
826  std::cerr << "TextureBuffer::setData - glew version too old, rebuild with latest glew!" << std::endl;
827 #endif
828 }
829 
830 bool TextureBuffer::getBufferData(void* _dst) {
831 #if defined(GL_ARB_texture_buffer_object)
832  if (buffer_) {
833  glBindBuffer(GL_TEXTURE_BUFFER, buffer_);
834  glGetBufferSubData(GL_TEXTURE_BUFFER, 0, bufferSize_, _dst);
835  return true;
836  }
837  else
838  std::cerr << "TextureBuffer::getBufferData - gpu does not support buffer textures!" << std::endl;
839 #else
840  std::cerr << "TextureBuffer::getBufferData - glew version too old, rebuild with latest glew!" << std::endl;
841 #endif
842  return false;
843 }
844 
845 bool TextureBuffer::getBufferData(std::vector<char>& _dst) {
846  if (_dst.size() < size_t(bufferSize_))
847  _dst.resize(bufferSize_);
848 
849  if (!_dst.empty())
850  return getBufferData(&_dst[0]);
851 
852  return false;
853 }
854 
855 
856 
857 //-----------------------------------------------------------------------------
858 
859 
860 #if defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program)
861 
862 void ProgramBaseNV::bind() {
863  if (!valid)
864  gen();
865  glBindProgramNV(target, program);
866 }
867 
868 void ProgramBaseNV::unbind() {
869  glBindProgramNV(target, 0);
870 }
871 
872 bool ProgramBaseNV::load(const char* prog_text) {
873  int size = int(strlen(prog_text));
874  if (!valid)
875  gen();
876  glLoadProgramNV(target, program, size, (const GLubyte *) prog_text);
877  GLint errpos;
878  glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV, &errpos);
879  if (errpos != -1) {
880  fprintf(stderr, "\nprogram error:\n");
881  int bgn = std::max(0, errpos - 10), end = std::min(size, bgn + 30);
882  for (int i = bgn; i < end; ++i)
883  fputc(prog_text[i], stderr);
884  fputc('\n', stderr);
885  return false;
886  }
887  return true;
888 }
889 
890 
891 void ProgramBaseNV::gen() {
892  glGenProgramsNV(1, &program);
893  valid = true;
894 }
895 
896 void ProgramBaseNV::del() {
897  if (valid)
898  glDeleteProgramsNV(1, &program);
899  valid = false;
900 }
901 
902 #endif
903 
904 #if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program)
905 
906 void ProgramBaseARB::bind() {
907  if (!valid)
908  gen();
909  glBindProgramARB(target, program);
910 }
911 void ProgramBaseARB::unbind() {
912  glBindProgramARB(target, 0);
913 }
914 
915 bool ProgramBaseARB::load(const char* prog_text) {
916  int size = int(strlen(prog_text));
917  if (!valid)
918  gen();
919  bind();
920  glProgramStringARB(target, GL_PROGRAM_FORMAT_ASCII_ARB, size, prog_text);
921  GLint errpos;
922  glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errpos);
923  if (errpos != -1) {
924  fprintf(stderr, "\nprogram error:\n");
925  int bgn = std::max(0, errpos - 10), end = std::min(size, bgn + 30);
926  for (int i = bgn; i < end; ++i)
927  fputc(prog_text[i], stderr);
928  fputc('\n', stderr);
929  return false;
930  }
931  return true;
932 }
933 
934 void ProgramBaseARB::gen() {
935  glGenProgramsARB(1, &program);
936  valid = true;
937 }
938 void ProgramBaseARB::del() {
939  if (valid)
940  glDeleteProgramsARB(1, &program);
941  valid = false;
942 }
943 
944 #endif // GL_ARB_vertex_program
945 
946 
947 //-----------------------------------------------------------------------------
948 
949 // support state unknown : -1
950 int VertexArrayObject::supportStatus_ = -1;
951 
952 VertexArrayObject::VertexArrayObject()
953  : id_(0)
954 {
955 }
956 
957 VertexArrayObject::~VertexArrayObject()
958 {
959 #ifdef GL_ARB_vertex_array_object
960  if (id_)
961  glDeleteVertexArrays(1, &id_);
962 #endif
963 }
964 
965 
966 void VertexArrayObject::bind()
967 {
968 #ifdef GL_ARB_vertex_array_object
969  if (!id_)
970  init();
971 
972  if (id_)
973  glBindVertexArray(id_);
974 #endif
975 }
976 
977 void VertexArrayObject::unbind()
978 {
979 #ifdef GL_ARB_vertex_array_object
980  glBindVertexArray(0);
981 #endif
982 }
983 
984 void VertexArrayObject::init()
985 {
986 #ifdef GL_ARB_vertex_array_object
987  if (id_)
988  glDeleteVertexArrays(1, &id_);
989 
990  glGenVertexArrays(1, &id_);
991 #endif
992 }
993 
994 bool VertexArrayObject::isSupported()
995 {
996 #ifndef GL_ARB_vertex_array_object
997  // missing definition in gl header!
998  supportStatus_ = 0;
999 #else
1000 
1001  if (supportStatus_ < 0)
1002  supportStatus_ = checkExtensionSupported("GL_ARB_vertex_array_object") ? 1 : 0;
1003 #endif
1004 
1005  return supportStatus_ > 0;
1006 }
1007 
1008 
1009 
1010 //-----------------------------------------------------------------------------
1011 
1012 
1013 
1014 // support state unknown : -1
1015 int AtomicCounter::supportStatus_ = -1;
1016 
1017 AtomicCounter::AtomicCounter(int _numCounters)
1018  : numCounters_(_numCounters), buffer_(0)
1019 {
1020 }
1021 
1022 AtomicCounter::~AtomicCounter()
1023 {
1024  if (buffer_)
1025  glDeleteBuffers(1, &buffer_);
1026 }
1027 
1028 void AtomicCounter::init()
1029 {
1030  // check support and initialize
1031 #ifdef GL_ARB_shader_atomic_counters
1032  if (isSupported() && numCounters_ > 0)
1033  {
1034  glGenBuffers(1, &buffer_);
1035  bind();
1036  glBufferData(GL_ATOMIC_COUNTER_BUFFER, numCounters_ * sizeof(unsigned int), 0, GL_DYNAMIC_COPY);
1037  unbind();
1038  }
1039 #endif
1040 
1041  if (!isValid())
1042  std::cerr << "atomic counter failed to initialize!" << std::endl;
1043 }
1044 
1045 void AtomicCounter::bind()
1046 {
1047 #ifdef GL_ARB_shader_atomic_counters
1048  // implicit initialization
1049  if (!isValid())
1050  init();
1051 
1052  if (isValid())
1053  glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1054 #endif
1055 }
1056 
1057 void AtomicCounter::bind(GLuint _index)
1058 {
1059 #ifdef GL_ARB_shader_atomic_counters
1060  // implicit initialization
1061  if (!isValid())
1062  init();
1063 
1064  if (isValid())
1065  glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, _index, buffer_);
1066 #endif
1067 }
1068 
1069 void AtomicCounter::unbind()
1070 {
1071 #ifdef GL_ARB_shader_atomic_counters
1072  glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1073 #endif
1074 }
1075 
1076 void AtomicCounter::set(unsigned int _value)
1077 {
1078 #ifdef GL_ARB_shader_atomic_counters
1079  // implicit initialization
1080  bind();
1081 
1082  if (isValid())
1083  {
1084  const size_t bufSize = numCounters_ * sizeof(unsigned int);
1085  // unsigned int* bufData = new unsigned int[numCounters_];
1086  // memset(bufData, int(_value), bufSize);
1087  //
1088  // glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, bufSize, bufData);
1089  // delete [] bufData;
1090 
1091  void* bufPtr = glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, bufSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
1092  memset(bufPtr, int(_value), bufSize);
1093  glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1094 
1095  unbind();
1096  }
1097 #endif
1098 }
1099 
1100 void AtomicCounter::get(unsigned int* _out)
1101 {
1102 #ifdef GL_ARB_shader_atomic_counters
1103  if (isValid())
1104  {
1105  bind();
1106 
1107  const size_t bufSize = numCounters_ * sizeof(unsigned int);
1108 
1109  // doesnt work, driver crash on ati:
1110  // glGetBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, bufSize, _out);
1111 
1112  void* bufPtr = glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, bufSize, GL_MAP_READ_BIT);
1113  memcpy(_out, bufPtr, bufSize);
1114  glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1115 
1116  unbind();
1117  }
1118 #endif
1119 }
1120 
1121 bool AtomicCounter::isSupported()
1122 {
1123 #ifndef GL_ARB_shader_atomic_counters
1124  // missing definition in gl header!
1125  supportStatus_ = 0;
1126 #else
1127 
1128  if (supportStatus_ < 0)
1129  supportStatus_ = checkExtensionSupported("GL_ARB_shader_atomic_counters") ? 1 : 0;
1130 #endif
1131 
1132  return supportStatus_ > 0;
1133 }
1134 
1135 bool AtomicCounter::isValid() const
1136 {
1137  return buffer_ && numCounters_ > 0;
1138 }
1139 
1140 //-----------------------------------------------------------------------------
1141 
1142 QueryObject::QueryObject(GLenum _type)
1143  : id_(0), state_(-1), type_(_type)
1144 {
1145 
1146 }
1147 
1148 QueryObject::~QueryObject()
1149 {
1150  if (id_)
1151  glDeleteQueries(1, &id_);
1152 }
1153 
1155 {
1156  if (!id_)
1157  glGenQueries(1, &id_);
1158 
1159  glBeginQuery(type_, id_);
1160  state_ = 0;
1161 }
1162 
1164 {
1165  if (!state_)
1166  {
1167  glEndQuery(type_);
1168  state_ = 1;
1169  }
1170 }
1171 
1173 {
1174  GLint r = GL_FALSE;
1175  if (state_ > 0)
1176  glGetQueryObjectiv(id_, GL_QUERY_RESULT_AVAILABLE, &r);
1177  return r != GL_FALSE;
1178 }
1179 
1180 GLuint QueryObject::result() const
1181 {
1182  GLuint r = 0xffffffff;
1183  if (state_ > 0)
1184  glGetQueryObjectuiv(id_, GL_QUERY_RESULT, &r);
1185  return r;
1186 }
1187 
1188 
1189 //-----------------------------------------------------------------------------
1190 
1191 int QueryCounter::supportStatus_ = -1;
1192 
1193 QueryCounter::QueryCounter()
1194  : state_(-1)
1195 {
1196  queryObjects_[0] = queryObjects_[1] = 0;
1197 }
1198 
1199 QueryCounter::~QueryCounter()
1200 {
1201  if (queryObjects_[0])
1202  glDeleteQueries(2, queryObjects_);
1203 }
1204 
1205 
1206 void QueryCounter::restart()
1207 {
1208 #ifdef GL_ARB_timer_query
1209  if (isSupported())
1210  {
1211  state_ = 0;
1212 
1213  if (!queryObjects_[0])
1214  glGenQueries(2, queryObjects_);
1215 
1216  glQueryCounter(queryObjects_[0], GL_TIMESTAMP);
1217  }
1218 #endif
1219 }
1220 
1221 void QueryCounter::stop()
1222 {
1223 #ifdef GL_ARB_timer_query
1224  if (state_ == 0)
1225  {
1226  glQueryCounter(queryObjects_[1], GL_TIMESTAMP);
1227  ++state_;
1228  }
1229 #endif
1230 }
1231 
1233 {
1234  GLuint64 timing = 0;
1235 #ifdef GL_ARB_timer_query
1236  stop();
1237 
1238  if (state_ == 1)
1239  {
1240  GLint available = 0;
1241  while (!available)
1242  glGetQueryObjectiv(queryObjects_[1], GL_QUERY_RESULT_AVAILABLE, &available);
1243 
1244  GLuint64 timeStart;
1245  glGetQueryObjectui64v(queryObjects_[0], GL_QUERY_RESULT, &timeStart);
1246  glGetQueryObjectui64v(queryObjects_[1], GL_QUERY_RESULT, &timing);
1247  timing -= timeStart;
1248  }
1249 #endif
1250  return timing;
1251 }
1252 
1254 {
1255  return elapsedNs() / 1000;
1256 }
1257 
1259 {
1260  GLuint64 ms = elapsedMs();
1261 
1262  return float(ms) / 1000.0f;
1263 }
1264 
1266 {
1267 #ifndef GL_ARB_timer_query
1268  // missing definition in gl header!
1269  supportStatus_ = 0;
1270 #else
1271 
1272  if (supportStatus_ < 0)
1273  supportStatus_ = checkExtensionSupported("GL_ARB_timer_query") || openGLVersion(3,2) ? 1 : 0;
1274 #endif
1275 
1276  return supportStatus_ > 0;
1277 }
1278 
1279 
1280 //-----------------------------------------------------------------------------
1281 
1282 
1283 // support state unknown : -1
1284 int UniformBufferObject::supportStatus_ = -1;
1285 int UniformBufferObject::maxBlockSize_ = -1;
1286 int UniformBufferObject::maxBindings_ = -1;
1287 int UniformBufferObject::maxCombinedShaderBlocks_ = -1;
1288 int UniformBufferObject::offsetAlignment_ = -1;
1289 
1290 UniformBufferObject::UniformBufferObject()
1291  : VertexBufferObject(
1292 #ifndef GL_ARB_uniform_buffer_object
1293  GL_NONE
1294 #else
1295  GL_UNIFORM_BUFFER
1296 #endif
1297  ),
1298  data_(0)
1299 {
1300 }
1301 
1302 UniformBufferObject::~UniformBufferObject()
1303 {
1304 }
1305 
1306 void UniformBufferObject::bind( GLuint _index )
1307 {
1308 #ifdef GL_ARB_uniform_buffer_object
1309  glBindBufferBase(GL_UNIFORM_BUFFER, _index, id());
1310 #endif
1311 }
1312 
1313 
1314 bool UniformBufferObject::isSupported()
1315 {
1316 #ifndef GL_ARB_uniform_buffer_object
1317  // missing definition in gl header!
1318  supportStatus_ = 0;
1319 #else
1320 
1321  if (supportStatus_ < 0)
1322  supportStatus_ = checkExtensionSupported("GL_ARB_uniform_buffer_object") ? 1 : 0;
1323 #endif
1324 
1325  return supportStatus_ > 0;
1326 }
1327 
1328 void UniformBufferObject::queryCaps()
1329 {
1330 #ifdef GL_ARB_uniform_buffer_object
1331  if (isSupported())
1332  {
1333  glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxBindings_);
1334  glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxBlockSize_);
1335  glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &maxCombinedShaderBlocks_);
1336  glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offsetAlignment_);
1337  }
1338 #endif
1339 }
1340 
1341 int UniformBufferObject::getMaxBindings()
1342 {
1343  if (maxBindings_ < 0)
1344  queryCaps();
1345 
1346  return maxBindings_;
1347 }
1348 
1349 int UniformBufferObject::getMaxBlocksize()
1350 {
1351  if (maxBlockSize_ < 0)
1352  queryCaps();
1353 
1354  return maxBlockSize_;
1355 }
1356 
1357 int UniformBufferObject::getMaxCombinedShaderBlocks()
1358 {
1359  if (maxCombinedShaderBlocks_ < 0)
1360  queryCaps();
1361 
1362  return maxCombinedShaderBlocks_;
1363 }
1364 
1365 int UniformBufferObject::getOffsetAlignment()
1366 {
1367  if (offsetAlignment_ < 0)
1368  queryCaps();
1369 
1370  return offsetAlignment_;
1371 }
1372 
1373 void UniformBufferObject::setUniformData( GLSL::Program* _prog, const char* _bufferName, const char* _uniformName, const void* _data, int _datasize, bool _delay )
1374 {
1375  if (_prog && _bufferName && _uniformName && _data)
1376  {
1377  GLuint idx = _prog->getUniformBlockIndex(_bufferName);
1378 
1379  if (idx != GL_INVALID_INDEX)
1380  {
1381  size_t bufsize = size_t(_prog->getUniformBlockSize(idx));
1382 
1383  if (data_.size() != bufsize)
1384  data_.resize(bufsize, 0);
1385 
1386  int offset = -1;
1387  _prog->getUniformBlockOffsets(1, &_uniformName, &offset);
1388 
1389  if (offset >= 0)
1390  {
1391  memcpy(&data_[offset], _data, _datasize);
1392 
1393  if (!_delay)
1394  {
1396 
1397  if (size() != int(bufsize))
1398  VertexBufferObject::upload(bufsize, &data_[0], GL_DYNAMIC_DRAW);
1399  else
1400  uploadSubData(offset, _datasize, _data);
1401  }
1402  }
1403  }
1404  }
1405 }
1406 
1407 void UniformBufferObject::upload()
1408 {
1409  if (!data_.empty())
1410  {
1412 
1413  VertexBufferObject::upload(data_.size(), &data_[0], GL_DYNAMIC_DRAW);
1414  }
1415 }
1416 
1417 
1418 //-----------------------------------------------------------------------------
1419 
1420 
1421 
1422 // support state unknown : -1
1423 int ShaderStorageBufferObject::supportStatus_ = -1;
1424 int ShaderStorageBufferObject::maxBlockSize_ = -1;
1425 int ShaderStorageBufferObject::maxBindings_ = -1;
1426 int ShaderStorageBufferObject::maxCombinedShaderBlocks_ = -1;
1427 
1428 ShaderStorageBufferObject::ShaderStorageBufferObject()
1429  : VertexBufferObject(
1430 #ifndef GL_ARB_shader_storage_buffer_object
1431  GL_NONE
1432 #else
1433  GL_SHADER_STORAGE_BUFFER
1434 #endif
1435  )
1436 {
1437 }
1438 
1439 ShaderStorageBufferObject::~ShaderStorageBufferObject()
1440 {
1441 }
1442 
1443 void ShaderStorageBufferObject::bind( GLuint _index )
1444 {
1445 #ifdef GL_ARB_shader_storage_buffer_object
1446  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, _index, id());
1447 #endif
1448 }
1449 
1450 bool ShaderStorageBufferObject::isSupported()
1451 {
1452 #ifndef GL_ARB_shader_storage_buffer_object
1453  // missing definition in gl header!
1454  supportStatus_ = 0;
1455 #else
1456 
1457  if (supportStatus_ < 0)
1458  supportStatus_ = checkExtensionSupported("GL_ARB_shader_storage_buffer_object") ? 1 : 0;
1459 #endif
1460 
1461  return supportStatus_ > 0;
1462 }
1463 
1464 void ShaderStorageBufferObject::queryCaps()
1465 {
1466 #ifdef GL_ARB_shader_storage_buffer_object
1467  if (isSupported())
1468  {
1469  glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxBindings_);
1470  glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxBlockSize_);
1471  glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderBlocks_);
1472  }
1473 #endif
1474 }
1475 
1476 int ShaderStorageBufferObject::getMaxBindings()
1477 {
1478  if (maxBindings_ < 0)
1479  queryCaps();
1480 
1481  return maxBindings_;
1482 }
1483 
1484 int ShaderStorageBufferObject::getMaxBlocksize()
1485 {
1486  if (maxBlockSize_ < 0)
1487  queryCaps();
1488 
1489  return maxBlockSize_;
1490 }
1491 
1492 int ShaderStorageBufferObject::getMaxCombinedShaderBlocks()
1493 {
1494  if (maxCombinedShaderBlocks_ < 0)
1495  queryCaps();
1496 
1497  return maxCombinedShaderBlocks_;
1498 }
1499 
1500 
1501 
1502 
1503 
1504 } /* namespace ACG */
static bool isSupported()
check hw support
Definition: globjects.cc:1265
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:144
GLuint64 elapsedMs()
elapsed gpu time in millisecs
Definition: globjects.cc:1253
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
Definition: GLSLShader.cc:773
void begin()
begin measuring the query
Definition: globjects.cc:1154
bool openGLVersion(const int _major, const int _minor)
Definition: gl.cc:95
VectorT< signed int, 2 > Vec2i
Definition: VectorT.hh:104
bool bind(osg::GeometryPtr &_geo, Mesh &_mesh)
Definition: bindT.hh:106
GLuint64 elapsedNs()
elapsed gpu time since restart() in nanosecs
Definition: globjects.cc:1232
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
Definition: GLSLShader.cc:840
GLuint result() const
get the measurement of the query between the begin() end() calls (waits for the gpu) ...
Definition: globjects.cc:1180
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
Definition: GLSLShader.cc:813
bool available() const
check if the result is available (does not wait for gpu to finish)
Definition: globjects.cc:1172
void end()
stop measuring the query
Definition: globjects.cc:1163
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:73
GLSL program class.
Definition: GLSLShader.hh:217
float elapsedSecs()
elapsed gpu time in seconds
Definition: globjects.cc:1258
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:193