Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
1154 void QueryObject::begin()
1155 {
1156 if (!id_)
1157 glGenQueries(1, &id_);
1158
1159 glBeginQuery(type_, id_);
1160 state_ = 0;
1161 }
1162
1163 void QueryObject::end()
1164 {
1165 if (!state_)
1166 {
1167 glEndQuery(type_);
1168 state_ = 1;
1169 }
1170 }
1171
1172 bool QueryObject::available() const
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
1232 GLuint64 QueryCounter::elapsedNs()
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
1253 GLuint64 QueryCounter::elapsedMs()
1254 {
1255 return elapsedNs() / 1000;
1256 }
1257
1258 float QueryCounter::elapsedSecs()
1259 {
1260 GLuint64 ms = elapsedMs();
1261
1262 return float(ms) / 1000.0f;
1263 }
1264
1265 bool QueryCounter::isSupported()
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 {
1395 VertexBufferObject::bind();
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 {
1411 VertexBufferObject::bind();
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 */
ACG::QueryCounter::elapsedNs
GLuint64 elapsedNs()
elapsed gpu time since restart() in nanosecs
Definition: globjects.cc:1232
ACG
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
ACG::Vec2i
VectorT< signed int, 2 > Vec2i
Definition: VectorT.hh:104
VectorT< signed int, 4 >
ACG::GLFormatInfo
Definition: GLFormatInfo.hh:78
ACG::QueryCounter::elapsedMs
GLuint64 elapsedMs()
elapsed gpu time in millisecs
Definition: globjects.cc:1253
ACG::Vec4f
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:144
ACG::openGLVersion
bool openGLVersion(const int _major, const int _minor)
Definition: gl.cc:95
GLSL::Program::getUniformBlockSize
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
Definition: GLSLShader.cc:813
ACG::checkExtensionSupported
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:73
GLSL::Program::getUniformBlockIndex
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
Definition: GLSLShader.cc:773
ACG::QueryObject::result
GLuint result() const
get the measurement of the query between the begin() end() calls (waits for the gpu) ...
Definition: globjects.cc:1180
OpenMesh::VectorT
Definition: Vector11T.hh:83
Texture
Definition: TextureData.hh:74
ACG::QueryCounter::elapsedSecs
float elapsedSecs()
elapsed gpu time in seconds
Definition: globjects.cc:1258
GLSL::Program
GLSL program class.
Definition: GLSLShader.hh:217
GLSL::Program::getUniformBlockOffsets
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
Definition: GLSLShader.cc:840
ACG::QueryObject::begin
void begin()
begin measuring the query
Definition: globjects.cc:1154
OpenMesh::Kernel_OSG::bind
bool bind(osg::GeometryPtr &_geo, Mesh &_mesh)
Definition: bindT.hh:106
ACG::QueryObject::available
bool available() const
check if the result is available (does not wait for gpu to finish)
Definition: globjects.cc:1172
ACG::QueryCounter::isSupported
static bool isSupported()
check hw support
Definition: globjects.cc:1265
ACG::QueryObject::end
void end()
stop measuring the query
Definition: globjects.cc:1163