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) {
823 if(!ACG::compatibilityProfile())
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
1149 void QueryObject::begin()
1150 {
1151 if (!id_)
1152 glGenQueries(1, &id_);
1153
1154 glBeginQuery(type_, id_);
1155 state_ = 0;
1156 }
1157
1158 void QueryObject::end()
1159 {
1160 if (!state_)
1161 {
1162 glEndQuery(type_);
1163 state_ = 1;
1164 }
1165 }
1166
1167 bool QueryObject::available() const
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
1227 GLuint64 QueryCounter::elapsedNs()
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
1248 GLuint64 QueryCounter::elapsedMs()
1249 {
1250 return elapsedNs() / 1000;
1251 }
1252
1253 float QueryCounter::elapsedSecs()
1254 {
1255 GLuint64 ms = elapsedMs();
1256
1257 return float(ms) / 1000.0f;
1258 }
1259
1260 bool QueryCounter::isSupported()
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 {
1390 VertexBufferObject::bind();
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 {
1406 VertexBufferObject::bind();
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 */
ACG::QueryObject::begin
void begin()
begin measuring the query
Definition: globjects.cc:1149
ACG::QueryCounter::elapsedNs
GLuint64 elapsedNs()
elapsed gpu time since restart() in nanosecs
Definition: globjects.cc:1227
ACG::Vec2i
VectorT< signed int, 2 > Vec2i
Definition: VectorT.hh:98
ACG::QueryCounter::isSupported
static bool isSupported()
check hw support
Definition: globjects.cc:1260
ACG::GLFormatInfo
Definition: GLFormatInfo.hh:70
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
ACG::Vec4f
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:138
Texture
Definition: TextureData.hh:68
OpenMesh::VectorT
Definition: Vector11T.hh:83
OpenMesh::VectorT::data
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:200
GLSL::Program::getUniformBlockIndex
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
Definition: GLSLShader.cc:767
GLSL::Program::getUniformBlockOffsets
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
Definition: GLSLShader.cc:834
GLSL::Program
GLSL program class.
Definition: GLSLShader.hh:211
ACG::openGLVersion
bool openGLVersion(const int _major, const int _minor, bool _verbose)
Definition: gl.cc:129
ACG::QueryObject::result
GLuint result() const
get the measurement of the query between the begin() end() calls (waits for the gpu) ...
Definition: globjects.cc:1175
ACG::QueryCounter::elapsedMs
GLuint64 elapsedMs()
elapsed gpu time in millisecs
Definition: globjects.cc:1248
OpenMesh::Kernel_OSG::bind
bool bind(osg::GeometryPtr &_geo, Mesh &_mesh)
Definition: bindT.hh:101
GLSL::Program::getUniformBlockSize
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
Definition: GLSLShader.cc:807
ACG::QueryObject::end
void end()
stop measuring the query
Definition: globjects.cc:1158
VectorT< unsigned int, 4 >
ACG::checkExtensionSupported
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:107
ACG::compatibilityProfile
void compatibilityProfile(bool _enableCoreProfile)
Store opengl core profile setting.
Definition: gl.cc:166
ACG::QueryCounter::elapsedSecs
float elapsedSecs()
elapsed gpu time in seconds
Definition: globjects.cc:1253
ACG::QueryObject::available
bool available() const
check if the result is available (does not wait for gpu to finish)
Definition: globjects.cc:1167