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 #include <ACG/GL/acg_glew.hh>
43 #include <ACG/GL/globjects.hh>
44 #include <ACG/GL/GLFormatInfo.hh>
45 #include <ACG/ShaderUtils/GLSLShader.hh>
46 #include <ACG/Utils/ImageConversion.hh>
47 
48 #include <QImage>
49 #include <QGLWidget>
50 
51 namespace ACG {
52 
53 
54 //-----------------------------------------------------------------------------
55 
56 Texture::Texture( GLenum tgt, GLenum _unit )
57  : target(tgt), unit(_unit), valid(false), texture(0u), internalFormat_(0)
58 {
59 }
60 
61 void Texture::bindAsImage(GLuint _index, GLenum _access)
62 {
63 #if defined(GL_ARB_shader_image_load_store)
64  if (is_valid())
65  glBindImageTexture(_index, id(), 0, GL_FALSE, 0, _access, getInternalFormat());
66  else
67  std::cerr << "Texture::bindAsImage - error: texture not initialized!" << std::endl;
68 #else
69  std::cerr << "Texture::bindAsImage - glBindImageTexture symbol not loaded!" << std::endl;
70 #endif
71 }
72 
73 
74 GLint Texture::getInternalFormat()
75 {
76  if (!internalFormat_)
77  {
78  bind();
79  glGetTexLevelParameteriv(target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat_);
80  }
81 
82  return internalFormat_;
83 }
84 //
85 // bool Texture::clear( float _color )
86 // {
87 // #ifdef GL_ARB_clear_texture
88 // if (supportsClearTexture() && texture)
89 // {
90 // glClearTexImage(texture, 0, GL_R32F, GL_FLOAT, &_color);
91 // return true;
92 // }
93 // #endif
94 // return false;
95 // }
96 //
97 // bool Texture::clear( const ACG::Vec2f& _color )
98 // {
99 // #ifdef GL_ARB_clear_texture
100 // if (supportsClearTexture() && texture)
101 // {
102 // glClearTexImage(texture, 0, GL_RG32F, GL_FLOAT, _color.data());
103 // return true;
104 // }
105 // #endif
106 // return false;
107 // }
108 //
109 // bool Texture::clear( const ACG::Vec3f& _color )
110 // {
111 // #ifdef GL_ARB_clear_texture
112 // if (supportsClearTexture() && texture)
113 // {
114 // glClearTexImage(texture, 0, GL_RGB32F, GL_FLOAT, _color.data());
115 // return true;
116 // }
117 // #endif
118 // return false;
119 // }
120 
121 bool Texture::clear( const ACG::Vec4f& _color )
122 {
123 #ifdef GL_ARB_clear_texture
124  if (supportsClearTexture() && texture)
125  {
126  glClearTexImage(texture, 0, GL_RGBA, GL_FLOAT, _color.data());
127  return true;
128  }
129 #endif
130  return false;
131 }
132 
133 bool Texture::clear( const ACG::Vec4ui& _color )
134 {
135 #ifdef GL_ARB_clear_texture
136  if (supportsClearTexture() && texture)
137  {
138  glClearTexImage(texture, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, _color.data());
139  return true;
140  }
141 #endif
142  return false;
143 }
144 
145 bool Texture::clear( const ACG::Vec4i& _color )
146 {
147 #ifdef GL_ARB_clear_texture
148  if (supportsClearTexture() && texture)
149  {
150  glClearTexImage(texture, 0, GL_RGBA_INTEGER, GL_INT, _color.data());
151  return true;
152  }
153 #endif
154  return false;
155 }
156 
157 bool Texture::supportsImageLoadStore()
158 {
159  static int status = -1;
160 
161  if (status < 0)
162  {
163 #if defined(GL_ARB_shader_image_load_store)
164  // core in version 4.2
165  status = checkExtensionSupported("ARB_shader_image_load_store") || openGLVersion(4,2);
166 #else
167  // symbol missing, install latest glew version
168  status = 0;
169 #endif
170  }
171 
172  return status > 0;
173 }
174 
175 
176 bool Texture::supportsTextureBuffer()
177 {
178  static int status = -1;
179 
180  if (status < 0)
181  {
182  // core in version 3.0
183  status = checkExtensionSupported("EXT_texture_buffer") || openGLVersion(3,1);
184  }
185 
186  return status > 0;
187 }
188 
189 
190 bool Texture::supportsClearTexture()
191 {
192  static int status = -1;
193 
194  if (status < 0)
195  {
196 #if defined(GL_ARB_clear_texture)
197  status = checkExtensionSupported("ARB_clear_texture");
198 #else
199  // symbol missing, install latest glew version
200  status = 0;
201 #endif
202  }
203 
204  return status > 0;
205 }
206 
207 bool Texture::supportsGenerateMipmap()
208 {
209  static int status = -1;
210 
211  if (status < 0)
212  {
213 #if defined(GL_SGIS_generate_mipmap)
214  status = checkExtensionSupported("GL_SGIS_generate_mipmap");
215 #else
216  // symbol missing, install latest glew version
217  status = 0;
218 #endif
219  }
220 
221  return status > 0;
222 }
223 
224 //-----------------------------------------------------------------------------
225 
226 
227 Texture1D::Texture1D( GLenum unit ) : Texture(GL_TEXTURE_1D, unit),
228  width_(0),
229  format_(0), type_(0)
230 {}
231 
232 void Texture1D::setData(GLint _level,
233  GLint _internalFormat,
234  GLsizei _width,
235  GLenum _format,
236  GLenum _type,
237  const GLvoid* _data) {
238 
239  bind();
240 
241  glTexImage1D(GL_TEXTURE_1D, _level, _internalFormat, _width, 0, _format, _type, _data);
242 
243  width_ = _width;
244  internalFormat_ = _internalFormat;
245  format_ = _format;
246  type_ = _type;
247 }
248 
249 
250 void Texture1D::setStorage( GLsizei _levels, GLenum _internalFormat, GLsizei _width ) {
251 #ifdef GL_ARB_texture_storage
252  bind();
253  glTexStorage1D(GL_TEXTURE_1D, _levels, _internalFormat, _width);
254 
255  width_ = _width;
256  internalFormat_ = _internalFormat;
257 
258  GLFormatInfo finfo(_internalFormat);
259  format_ = finfo.format();
260  type_ = finfo.type();
261 #endif // GL_ARB_texture_storage
262 }
263 
264 
265 bool Texture1D::getData( GLint _level, void* _dst ) {
266  if (is_valid()) {
267  GLint curTex = 0;
268  glGetIntegerv(GL_TEXTURE_BINDING_1D, &curTex);
269 
270  bind();
271  glGetTexImage(GL_TEXTURE_1D, _level, format_, type_, _dst);
272 
273  glBindTexture(GL_TEXTURE_1D, curTex);
274 
275  return true;
276  }
277  return false;
278 }
279 
280 bool Texture1D::getData( GLint _level, std::vector<char>& _dst ) {
281  if (is_valid()) {
282 
283  GLFormatInfo finfo(internalFormat_);
284 
285  if (finfo.isValid()) {
286  size_t bufSize = finfo.elemSize() * width_;
287 
288  if (_dst.size() < bufSize)
289  _dst.resize(bufSize);
290 
291  if (!_dst.empty())
292  return getData(_level, &_dst[0]);
293  }
294  }
295  return false;
296 }
297 
298 
299 
300 
301 
302 //-----------------------------------------------------------------------------
303 
304 Texture2D::Texture2D(GLenum unit)
305  : Texture(GL_TEXTURE_2D, unit),
306  width_(0), height_(0),
307  format_(0), type_(0),
308  buildMipsCPU_(false)
309 {}
310 
311 //-----------------------------------------------------------------------------
312 
313 bool Texture2D::autogenerateMipMaps()
314 {
315  if(openGLVersion(3,0))
316  {
317  // From OpenGL 3.0, glGenerateMipmap is supported and we should use that
318  // but glGenerateMipmap must be called AFTER the data was uploaded.
319  return false;
320  }
321 
322 #ifdef GL_SGIS_generate_mipmap
323  if (supportsGenerateMipmap())
324  {
325  parameter(GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
326  return true;
327  }
328 #endif
329  // hardware accelerated generation is not available, fall back to software implementation
330  buildMipsCPU_ = true;
331  return false;
332 }
333 
334 //-----------------------------------------------------------------------------
335 
336 void Texture2D::disableAutogenerateMipMaps()
337 {
338 #ifdef GL_SGIS_generate_mipmap
339  if (supportsGenerateMipmap())
340  parameter(GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
341 #endif
342  buildMipsCPU_ = false;
343 }
344 
345 //-----------------------------------------------------------------------------
346 
347 void Texture2D::setData(GLint _level,
348  GLint _internalFormat,
349  GLsizei _width,
350  GLsizei _height,
351  GLenum _format,
352  GLenum _type,
353  const GLvoid* _data,
354  bool _mipmaps) {
355 
356  if (getUnit() == GL_NONE)
357  setUnit(GL_TEXTURE0);
358 
359  bind();
360 
361  if (buildMipsCPU_ && _level == 0)
362  buildMipMaps(_internalFormat, _width, _height, _format, _type, _data);
363  else
364  glTexImage2D(GL_TEXTURE_2D, _level, _internalFormat, _width, _height, 0, _format, _type, _data);
365 
366  // If mip maps should not be built on cpu and the OpenGL version is high enough, we go the default way
367  if(_mipmaps && !buildMipsCPU_ && openGLVersion(3,0))
368  glGenerateMipmap(GL_TEXTURE_2D);
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 = ACG::Util::convertToGLFormat(qtex);
644 
645  setData(0, GL_RGBA, gltex.width(), gltex.height(), GL_RGBA, GL_UNSIGNED_BYTE, gltex.bits(), mipmaps);
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_VERSION_1_5)
741 
742 void VertexBufferObject::del() {
743  if (valid)
744  glDeleteBuffers(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  glBufferData(target, size, data, usage);
757 }
758 
759 void VertexBufferObject::uploadSubData(
760  GLuint _offset, GLuint _size, const GLvoid* _data ) {
761 
762  glBufferSubData(target, _offset, _size, _data);
763 }
764 
765 void VertexBufferObject::gen() {
766  glGenBuffers(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 Texture(GL_TEXTURE_BUFFER, u),
786  bufferSize_(0), buffer_(0), usage_(0), fmt_(0) {
787 }
788 
789 
790 TextureBuffer::~TextureBuffer() {
791  if (buffer_)
792  glDeleteBuffers(1, &buffer_);
793 }
794 
795 void TextureBuffer::setBufferData(
796  size_t _size, const void* _data, GLenum _internalFormat, GLenum _usage) {
797  if (supportsTextureBuffer()) {
798  // setup buffer object
799  if (!buffer_)
800  glGenBuffers(1, &buffer_);
801 
802  glBindBuffer(GL_TEXTURE_BUFFER, buffer_);
803  glBufferData(GL_TEXTURE_BUFFER, static_cast<GLsizei>(_size), _data, _usage);
804 
805  usage_ = _usage;
806  fmt_ = _internalFormat;
807 
808  // bind buffer to texture
809  if (getUnit() == GL_NONE)
810  setUnit(GL_TEXTURE0);
811 
812  bind();
813 
814  glTexBuffer(GL_TEXTURE_BUFFER, _internalFormat, buffer_);
815 
816  bufferSize_ = _size;
817  }
818  else
819  std::cerr << "TextureBuffer::setData - gpu does not support buffer textures!" << std::endl;
820 }
821 
822 bool TextureBuffer::getBufferData(void* _dst) {
824 {
825  if (buffer_) {
826  glBindBuffer(GL_TEXTURE_BUFFER, buffer_);
827  glGetBufferSubData(GL_TEXTURE_BUFFER, 0, bufferSize_, _dst);
828  return true;
829  }
830  else
831  std::cerr << "TextureBuffer::getBufferData - gpu does not support buffer textures!" << std::endl;
832 }else{
833  std::cerr << "TextureBuffer::getBufferData - currently only in core profile available!" << std::endl;
834 }
835  return false;
836 }
837 
838 bool TextureBuffer::getBufferData(std::vector<char>& _dst) {
839  if (_dst.size() < size_t(bufferSize_))
840  _dst.resize(bufferSize_);
841 
842  if (!_dst.empty())
843  return getBufferData(&_dst[0]);
844 
845  return false;
846 }
847 
848 
849 
850 //-----------------------------------------------------------------------------
851 
852 
853 #if defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program)
854 
855 void ProgramBaseNV::bind() {
856  if (!valid)
857  gen();
858  glBindProgramARB(target, program);
859 }
860 
861 void ProgramBaseNV::unbind() {
862  glBindProgramARB(target, 0);
863 }
864 
865 bool ProgramBaseNV::load(const char* prog_text) {
866  int size = int(strlen(prog_text));
867  if (!valid)
868  gen();
869  glLoadProgramNV(target, program, size, (const GLubyte *) prog_text);
870  GLint errpos;
871  glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV, &errpos);
872  if (errpos != -1) {
873  fprintf(stderr, "\nprogram error:\n");
874  int bgn = std::max(0, errpos - 10), end = std::min(size, bgn + 30);
875  for (int i = bgn; i < end; ++i)
876  fputc(prog_text[i], stderr);
877  fputc('\n', stderr);
878  return false;
879  }
880  return true;
881 }
882 
883 
884 void ProgramBaseNV::gen() {
885  glGenProgramsARB(1, &program);
886  valid = true;
887 }
888 
889 void ProgramBaseNV::del() {
890  if (valid)
891  glDeleteProgramsARB(1, &program);
892  valid = false;
893 }
894 
895 #endif
896 
897 #if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program)
898 
899 void ProgramBaseARB::bind() {
900  if (!valid)
901  gen();
902  glBindProgramARB(target, program);
903 }
904 void ProgramBaseARB::unbind() {
905  glBindProgramARB(target, 0);
906 }
907 
908 bool ProgramBaseARB::load(const char* prog_text) {
909  int size = int(strlen(prog_text));
910  if (!valid)
911  gen();
912  bind();
913  glProgramStringARB(target, GL_PROGRAM_FORMAT_ASCII_ARB, size, prog_text);
914  GLint errpos;
915  glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errpos);
916  if (errpos != -1) {
917  fprintf(stderr, "\nprogram error:\n");
918  int bgn = std::max(0, errpos - 10), end = std::min(size, bgn + 30);
919  for (int i = bgn; i < end; ++i)
920  fputc(prog_text[i], stderr);
921  fputc('\n', stderr);
922  return false;
923  }
924  return true;
925 }
926 
927 void ProgramBaseARB::gen() {
928  glGenProgramsARB(1, &program);
929  valid = true;
930 }
931 void ProgramBaseARB::del() {
932  if (valid)
933  glDeleteProgramsARB(1, &program);
934  valid = false;
935 }
936 
937 #endif // GL_ARB_vertex_program
938 
939 
940 //-----------------------------------------------------------------------------
941 
942 // support state unknown : -1
943 int VertexArrayObject::supportStatus_ = -1;
944 
945 VertexArrayObject::VertexArrayObject()
946  : id_(0)
947 {
948 }
949 
950 VertexArrayObject::~VertexArrayObject()
951 {
952 #ifdef GL_ARB_vertex_array_object
953  if (id_)
954  glDeleteVertexArrays(1, &id_);
955 #endif
956 }
957 
958 
959 void VertexArrayObject::bind()
960 {
961 #ifdef GL_ARB_vertex_array_object
962  if (!id_)
963  init();
964 
965  if (id_)
966  glBindVertexArray(id_);
967 #endif
968 }
969 
970 void VertexArrayObject::unbind()
971 {
972 #ifdef GL_ARB_vertex_array_object
973  glBindVertexArray(0);
974 #endif
975 }
976 
977 void VertexArrayObject::init()
978 {
979 #ifdef GL_ARB_vertex_array_object
980  if (id_)
981  glDeleteVertexArrays(1, &id_);
982 
983  glGenVertexArrays(1, &id_);
984 #endif
985 }
986 
987 bool VertexArrayObject::isSupported()
988 {
989 #ifndef GL_ARB_vertex_array_object
990  // missing definition in gl header!
991  supportStatus_ = 0;
992 #else
993 
994  if (supportStatus_ < 0)
995  supportStatus_ = checkExtensionSupported("GL_ARB_vertex_array_object") ? 1 : 0;
996  if( openGLVersion(3,2) )
997  return true;
998 #endif
999 
1000  return supportStatus_ > 0;
1001 }
1002 
1003 
1004 
1005 //-----------------------------------------------------------------------------
1006 
1007 
1008 
1009 // support state unknown : -1
1010 int AtomicCounter::supportStatus_ = -1;
1011 
1012 AtomicCounter::AtomicCounter(int _numCounters)
1013  : numCounters_(_numCounters), buffer_(0)
1014 {
1015 }
1016 
1017 AtomicCounter::~AtomicCounter()
1018 {
1019  if (buffer_)
1020  glDeleteBuffers(1, &buffer_);
1021 }
1022 
1023 void AtomicCounter::init()
1024 {
1025  // check support and initialize
1026 #ifdef GL_ARB_shader_atomic_counters
1027  if (isSupported() && numCounters_ > 0)
1028  {
1029  glGenBuffers(1, &buffer_);
1030  bind();
1031  glBufferData(GL_ATOMIC_COUNTER_BUFFER, numCounters_ * sizeof(unsigned int), 0, GL_DYNAMIC_COPY);
1032  unbind();
1033  }
1034 #endif
1035 
1036  if (!isValid())
1037  std::cerr << "atomic counter failed to initialize!" << std::endl;
1038 }
1039 
1040 void AtomicCounter::bind()
1041 {
1042 #ifdef GL_ARB_shader_atomic_counters
1043  // implicit initialization
1044  if (!isValid())
1045  init();
1046 
1047  if (isValid())
1048  glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1049 #endif
1050 }
1051 
1052 void AtomicCounter::bind(GLuint _index)
1053 {
1054 #ifdef GL_ARB_shader_atomic_counters
1055  // implicit initialization
1056  if (!isValid())
1057  init();
1058 
1059  if (isValid())
1060  glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, _index, buffer_);
1061 #endif
1062 }
1063 
1064 void AtomicCounter::unbind()
1065 {
1066 #ifdef GL_ARB_shader_atomic_counters
1067  glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1068 #endif
1069 }
1070 
1071 void AtomicCounter::set(unsigned int _value)
1072 {
1073 #ifdef GL_ARB_shader_atomic_counters
1074  // implicit initialization
1075  bind();
1076 
1077  if (isValid())
1078  {
1079  const size_t bufSize = numCounters_ * sizeof(unsigned int);
1080  // unsigned int* bufData = new unsigned int[numCounters_];
1081  // memset(bufData, int(_value), bufSize);
1082  //
1083  // glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, bufSize, bufData);
1084  // delete [] bufData;
1085 
1086  void* bufPtr = glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, bufSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
1087  memset(bufPtr, int(_value), bufSize);
1088  glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1089 
1090  unbind();
1091  }
1092 #endif
1093 }
1094 
1095 void AtomicCounter::get(unsigned int* _out)
1096 {
1097 #ifdef GL_ARB_shader_atomic_counters
1098  if (isValid())
1099  {
1100  bind();
1101 
1102  const size_t bufSize = numCounters_ * sizeof(unsigned int);
1103 
1104  // doesnt work, driver crash on ati:
1105  // glGetBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, bufSize, _out);
1106 
1107  void* bufPtr = glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, bufSize, GL_MAP_READ_BIT);
1108  memcpy(_out, bufPtr, bufSize);
1109  glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1110 
1111  unbind();
1112  }
1113 #endif
1114 }
1115 
1116 bool AtomicCounter::isSupported()
1117 {
1118 #ifndef GL_ARB_shader_atomic_counters
1119  // missing definition in gl header!
1120  supportStatus_ = 0;
1121 #else
1122 
1123  if (supportStatus_ < 0)
1124  supportStatus_ = checkExtensionSupported("GL_ARB_shader_atomic_counters") ? 1 : 0;
1125 #endif
1126 
1127  return supportStatus_ > 0;
1128 }
1129 
1130 bool AtomicCounter::isValid() const
1131 {
1132  return buffer_ && numCounters_ > 0;
1133 }
1134 
1135 //-----------------------------------------------------------------------------
1136 
1137 QueryObject::QueryObject(GLenum _type)
1138  : id_(0), state_(-1), type_(_type)
1139 {
1140 
1141 }
1142 
1143 QueryObject::~QueryObject()
1144 {
1145  if (id_)
1146  glDeleteQueries(1, &id_);
1147 }
1148 
1150 {
1151  if (!id_)
1152  glGenQueries(1, &id_);
1153 
1154  glBeginQuery(type_, id_);
1155  state_ = 0;
1156 }
1157 
1159 {
1160  if (!state_)
1161  {
1162  glEndQuery(type_);
1163  state_ = 1;
1164  }
1165 }
1166 
1168 {
1169  GLint r = GL_FALSE;
1170  if (state_ > 0)
1171  glGetQueryObjectiv(id_, GL_QUERY_RESULT_AVAILABLE, &r);
1172  return r != GL_FALSE;
1173 }
1174 
1175 GLuint QueryObject::result() const
1176 {
1177  GLuint r = 0xffffffff;
1178  if (state_ > 0)
1179  glGetQueryObjectuiv(id_, GL_QUERY_RESULT, &r);
1180  return r;
1181 }
1182 
1183 
1184 //-----------------------------------------------------------------------------
1185 
1186 int QueryCounter::supportStatus_ = -1;
1187 
1188 QueryCounter::QueryCounter()
1189  : state_(-1)
1190 {
1191  queryObjects_[0] = queryObjects_[1] = 0;
1192 }
1193 
1194 QueryCounter::~QueryCounter()
1195 {
1196  if (queryObjects_[0])
1197  glDeleteQueries(2, queryObjects_);
1198 }
1199 
1200 
1201 void QueryCounter::restart()
1202 {
1203 #ifdef GL_ARB_timer_query
1204  if (isSupported())
1205  {
1206  state_ = 0;
1207 
1208  if (!queryObjects_[0])
1209  glGenQueries(2, queryObjects_);
1210 
1211  glQueryCounter(queryObjects_[0], GL_TIMESTAMP);
1212  }
1213 #endif
1214 }
1215 
1216 void QueryCounter::stop()
1217 {
1218 #ifdef GL_ARB_timer_query
1219  if (state_ == 0)
1220  {
1221  glQueryCounter(queryObjects_[1], GL_TIMESTAMP);
1222  ++state_;
1223  }
1224 #endif
1225 }
1226 
1228 {
1229  GLuint64 timing = 0;
1230 #ifdef GL_ARB_timer_query
1231  stop();
1232 
1233  if (state_ == 1)
1234  {
1235  GLint available = 0;
1236  while (!available)
1237  glGetQueryObjectiv(queryObjects_[1], GL_QUERY_RESULT_AVAILABLE, &available);
1238 
1239  GLuint64 timeStart;
1240  glGetQueryObjectui64v(queryObjects_[0], GL_QUERY_RESULT, &timeStart);
1241  glGetQueryObjectui64v(queryObjects_[1], GL_QUERY_RESULT, &timing);
1242  timing -= timeStart;
1243  }
1244 #endif
1245  return timing;
1246 }
1247 
1249 {
1250  return elapsedNs() / 1000;
1251 }
1252 
1254 {
1255  GLuint64 ms = elapsedMs();
1256 
1257  return float(ms) / 1000.0f;
1258 }
1259 
1261 {
1262 #ifndef GL_ARB_timer_query
1263  // missing definition in gl header!
1264  supportStatus_ = 0;
1265 #else
1266 
1267  if (supportStatus_ < 0)
1268  supportStatus_ = checkExtensionSupported("GL_ARB_timer_query") || openGLVersion(3,2) ? 1 : 0;
1269 #endif
1270 
1271  return supportStatus_ > 0;
1272 }
1273 
1274 
1275 //-----------------------------------------------------------------------------
1276 
1277 
1278 // support state unknown : -1
1279 int UniformBufferObject::supportStatus_ = -1;
1280 int UniformBufferObject::maxBlockSize_ = -1;
1281 int UniformBufferObject::maxBindings_ = -1;
1282 int UniformBufferObject::maxCombinedShaderBlocks_ = -1;
1283 int UniformBufferObject::offsetAlignment_ = -1;
1284 
1285 UniformBufferObject::UniformBufferObject()
1286  : VertexBufferObject(
1287 #ifndef GL_ARB_uniform_buffer_object
1288  GL_NONE
1289 #else
1290  GL_UNIFORM_BUFFER
1291 #endif
1292  ),
1293  data_(0)
1294 {
1295 }
1296 
1297 UniformBufferObject::~UniformBufferObject()
1298 {
1299 }
1300 
1301 void UniformBufferObject::bind( GLuint _index )
1302 {
1303 #ifdef GL_ARB_uniform_buffer_object
1304  glBindBufferBase(GL_UNIFORM_BUFFER, _index, id());
1305 #endif
1306 }
1307 
1308 
1309 bool UniformBufferObject::isSupported()
1310 {
1311 #ifndef GL_ARB_uniform_buffer_object
1312  // missing definition in gl header!
1313  supportStatus_ = 0;
1314 #else
1315 
1316  if (supportStatus_ < 0)
1317  supportStatus_ = checkExtensionSupported("GL_ARB_uniform_buffer_object") ? 1 : 0;
1318 #endif
1319 
1320  return supportStatus_ > 0;
1321 }
1322 
1323 void UniformBufferObject::queryCaps()
1324 {
1325 #ifdef GL_ARB_uniform_buffer_object
1326  if (isSupported())
1327  {
1328  glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxBindings_);
1329  glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxBlockSize_);
1330  glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &maxCombinedShaderBlocks_);
1331  glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offsetAlignment_);
1332  }
1333 #endif
1334 }
1335 
1336 int UniformBufferObject::getMaxBindings()
1337 {
1338  if (maxBindings_ < 0)
1339  queryCaps();
1340 
1341  return maxBindings_;
1342 }
1343 
1344 int UniformBufferObject::getMaxBlocksize()
1345 {
1346  if (maxBlockSize_ < 0)
1347  queryCaps();
1348 
1349  return maxBlockSize_;
1350 }
1351 
1352 int UniformBufferObject::getMaxCombinedShaderBlocks()
1353 {
1354  if (maxCombinedShaderBlocks_ < 0)
1355  queryCaps();
1356 
1357  return maxCombinedShaderBlocks_;
1358 }
1359 
1360 int UniformBufferObject::getOffsetAlignment()
1361 {
1362  if (offsetAlignment_ < 0)
1363  queryCaps();
1364 
1365  return offsetAlignment_;
1366 }
1367 
1368 void UniformBufferObject::setUniformData( GLSL::Program* _prog, const char* _bufferName, const char* _uniformName, const void* _data, int _datasize, bool _delay )
1369 {
1370  if (_prog && _bufferName && _uniformName && _data)
1371  {
1372  GLuint idx = _prog->getUniformBlockIndex(_bufferName);
1373 
1374  if (idx != GL_INVALID_INDEX)
1375  {
1376  size_t bufsize = size_t(_prog->getUniformBlockSize(idx));
1377 
1378  if (data_.size() != bufsize)
1379  data_.resize(bufsize, 0);
1380 
1381  int offset = -1;
1382  _prog->getUniformBlockOffsets(1, &_uniformName, &offset);
1383 
1384  if (offset >= 0)
1385  {
1386  memcpy(&data_[offset], _data, _datasize);
1387 
1388  if (!_delay)
1389  {
1391 
1392  if (size() != int(bufsize))
1393  VertexBufferObject::upload(bufsize, &data_[0], GL_DYNAMIC_DRAW);
1394  else
1395  uploadSubData(offset, _datasize, _data);
1396  }
1397  }
1398  }
1399  }
1400 }
1401 
1402 void UniformBufferObject::upload()
1403 {
1404  if (!data_.empty())
1405  {
1407 
1408  VertexBufferObject::upload(data_.size(), &data_[0], GL_DYNAMIC_DRAW);
1409  }
1410 }
1411 
1412 
1413 //-----------------------------------------------------------------------------
1414 
1415 
1416 
1417 // support state unknown : -1
1418 int ShaderStorageBufferObject::supportStatus_ = -1;
1419 int ShaderStorageBufferObject::maxBlockSize_ = -1;
1420 int ShaderStorageBufferObject::maxBindings_ = -1;
1421 int ShaderStorageBufferObject::maxCombinedShaderBlocks_ = -1;
1422 
1423 ShaderStorageBufferObject::ShaderStorageBufferObject()
1424  : VertexBufferObject(
1425 #ifndef GL_ARB_shader_storage_buffer_object
1426  GL_NONE
1427 #else
1428  GL_SHADER_STORAGE_BUFFER
1429 #endif
1430  )
1431 {
1432 }
1433 
1434 ShaderStorageBufferObject::~ShaderStorageBufferObject()
1435 {
1436 }
1437 
1438 void ShaderStorageBufferObject::bind( GLuint _index )
1439 {
1440 #ifdef GL_ARB_shader_storage_buffer_object
1441  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, _index, id());
1442 #endif
1443 }
1444 
1445 bool ShaderStorageBufferObject::isSupported()
1446 {
1447 #ifndef GL_ARB_shader_storage_buffer_object
1448  // missing definition in gl header!
1449  supportStatus_ = 0;
1450 #else
1451 
1452  if (supportStatus_ < 0)
1453  supportStatus_ = checkExtensionSupported("GL_ARB_shader_storage_buffer_object") ? 1 : 0;
1454 #endif
1455 
1456  return supportStatus_ > 0;
1457 }
1458 
1459 void ShaderStorageBufferObject::queryCaps()
1460 {
1461 #ifdef GL_ARB_shader_storage_buffer_object
1462  if (isSupported())
1463  {
1464  glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxBindings_);
1465  glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxBlockSize_);
1466  glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderBlocks_);
1467  }
1468 #endif
1469 }
1470 
1471 int ShaderStorageBufferObject::getMaxBindings()
1472 {
1473  if (maxBindings_ < 0)
1474  queryCaps();
1475 
1476  return maxBindings_;
1477 }
1478 
1479 int ShaderStorageBufferObject::getMaxBlocksize()
1480 {
1481  if (maxBlockSize_ < 0)
1482  queryCaps();
1483 
1484  return maxBlockSize_;
1485 }
1486 
1487 int ShaderStorageBufferObject::getMaxCombinedShaderBlocks()
1488 {
1489  if (maxCombinedShaderBlocks_ < 0)
1490  queryCaps();
1491 
1492  return maxCombinedShaderBlocks_;
1493 }
1494 
1495 
1496 
1497 
1498 
1499 } /* namespace ACG */
void begin()
begin measuring the query
Definition: globjects.cc:1149
GLuint64 elapsedNs()
elapsed gpu time since restart() in nanosecs
Definition: globjects.cc:1227
VectorT< signed int, 2 > Vec2i
Definition: VectorT.hh:98
static bool isSupported()
check hw support
Definition: globjects.cc:1260
Namespace providing different geometric functions concerning angles.
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:138
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:200
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
Definition: GLSLShader.cc:767
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
Definition: GLSLShader.cc:834
GLSL program class.
Definition: GLSLShader.hh:211
bool openGLVersion(const int _major, const int _minor, bool _verbose)
Definition: gl.cc:129
GLuint result() const
get the measurement of the query between the begin() end() calls (waits for the gpu) ...
Definition: globjects.cc:1175
GLuint64 elapsedMs()
elapsed gpu time in millisecs
Definition: globjects.cc:1248
bool bind(osg::GeometryPtr &_geo, Mesh &_mesh)
Definition: bindT.hh:101
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
Definition: GLSLShader.cc:807
void end()
stop measuring the query
Definition: globjects.cc:1158
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:107
void compatibilityProfile(bool _enableCoreProfile)
Store opengl core profile setting.
Definition: gl.cc:166
float elapsedSecs()
elapsed gpu time in seconds
Definition: globjects.cc:1253
bool available() const
check if the result is available (does not wait for gpu to finish)
Definition: globjects.cc:1167