root/OpenSceneGraph/trunk/src/osg/Texture2DArray.cpp @ 9062

Revision 9062, 24.2 kB (checked in by robert, 5 years ago)

Various warning fixes

Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13#include <osg/GLExtensions>
14#include <osg/Texture2DArray>
15#include <osg/State>
16#include <osg/ImageSequence>
17#include <osg/Notify>
18
19#include <string.h>
20
21
22using namespace osg;
23
24Texture2DArray::Texture2DArray():
25            _textureWidth(0),
26            _textureHeight(0),
27            _textureDepth(0),
28            _numMipmapLevels(0)
29{
30}
31
32Texture2DArray::Texture2DArray(const Texture2DArray& text,const CopyOp& copyop):
33            Texture(text,copyop),
34            _textureWidth(text._textureWidth),
35            _textureHeight(text._textureHeight),
36            _textureDepth(text._textureDepth),
37            _numMipmapLevels(text._numMipmapLevels),
38            _subloadCallback(text._subloadCallback)
39{
40    // copy all images by iterating through all of them
41    for (int i=0; i < text._textureDepth; i++)
42    {
43        _images.push_back(copyop(text._images[i].get()));
44        _modifiedCount.push_back(ImageModifiedCount());
45    }
46}
47
48Texture2DArray::~Texture2DArray()
49{
50}
51
52int Texture2DArray::compare(const StateAttribute& sa) const
53{
54    // check the types are equal and then create the rhs variable
55    // used by the COMPARE_StateAttribute_Parameter macro's below.
56    COMPARE_StateAttribute_Types(Texture2DArray,sa)
57
58    bool noImages = true;
59    for (int n=0; n < _textureDepth; n++)
60    {
61        if (noImages && _images[n].valid()) noImages = false;
62        if (noImages && rhs._images[n].valid()) noImages = false;
63   
64        if (_images[n]!=rhs._images[n]) // smart pointer comparison.
65        {
66            if (_images[n].valid())
67            {
68                if (rhs._images[n].valid())
69                {
70                    int result = _images[n]->compare(*rhs._images[n]);
71                    if (result!=0) return result;
72                }
73                else
74                {
75                    return 1; // valid lhs._image is greater than null.
76                }
77            }
78            else if (rhs._images[n].valid())
79            {
80                return -1; // valid rhs._image is greater than null.
81            }
82        }
83    }
84
85   
86    if (noImages)
87    {
88        int result = compareTextureObjects(rhs);
89        if (result!=0) return result;
90    }
91
92    int result = compareTexture(rhs);
93    if (result!=0) return result;
94
95    // compare each parameter in turn against the rhs.
96    COMPARE_StateAttribute_Parameter(_textureWidth)
97    COMPARE_StateAttribute_Parameter(_textureHeight)
98    COMPARE_StateAttribute_Parameter(_textureDepth)
99    COMPARE_StateAttribute_Parameter(_subloadCallback)
100
101    return 0; // passed all the above comparison macro's, must be equal.
102}
103
104void Texture2DArray::setImage(unsigned int layer, Image* image)
105{
106    // check if the layer exceeds the texture depth
107    if (static_cast<int>(layer) >= _textureDepth)
108    {
109        // print warning and do nothing
110        notify(WARN)<<"Warning: Texture2DArray::setImage(..) failed, the given layer number is bigger then the size of the texture array."<<std::endl;
111        return;
112    }
113   
114    if (_images[layer] == image) return;
115
116    unsigned numImageSequencesBefore = 0;
117    for (unsigned int i=0; i<getNumImages(); ++i)
118    {
119        osg::ImageSequence* is = dynamic_cast<osg::ImageSequence*>(_images[i].get());
120        if (is) ++numImageSequencesBefore;
121    }
122
123    // set image
124    _images[layer] = image;
125   _modifiedCount[layer].setAllElementsTo(0);
126
127    // find out if we need to reset the update callback to handle the animation of ImageSequence
128    unsigned numImageSequencesAfter = 0;
129    for (unsigned int i=0; i<getNumImages(); ++i)
130    {
131        osg::ImageSequence* is = dynamic_cast<osg::ImageSequence*>(_images[i].get());
132        if (is) ++numImageSequencesAfter;
133    }
134
135    if (numImageSequencesBefore>0)
136    {
137        if (numImageSequencesAfter==0)
138        {
139            setUpdateCallback(0);
140            setDataVariance(osg::Object::STATIC);
141        }
142    }
143    else if (numImageSequencesAfter>0)
144    {
145        setUpdateCallback(new ImageSequence::UpdateCallback());
146        setDataVariance(osg::Object::DYNAMIC);
147    }
148}
149 
150void Texture2DArray::setTextureSize(int width, int height, int depth)
151{
152    // set dimensions
153    _textureWidth = width;
154    _textureHeight = height;
155    setTextureDepth(depth);
156}
157
158void Texture2DArray::setTextureDepth(int depth)
159{   
160    // if we decrease the number of layers, then delete non-used
161    if (depth < _textureDepth)
162    {
163        _images.resize(depth);
164        _modifiedCount.resize(depth);
165    }
166   
167    // if we increase the array, then add new empty elements
168    if (depth > _textureDepth)
169    {
170        _images.resize(depth, ref_ptr<Image>(0));
171        _modifiedCount.resize(depth, ImageModifiedCount());
172    }
173       
174    // resize the texture array
175    _textureDepth = depth;
176}
177
178Image* Texture2DArray::getImage(unsigned int layer)
179{
180    return _images[layer].get();
181}
182
183const Image* Texture2DArray::getImage(unsigned int layer) const
184{
185    return _images[layer].get();
186}
187
188bool Texture2DArray::imagesValid() const
189{
190    if (_textureDepth < 1) return false;
191    for (int n=0; n < _textureDepth; n++)
192    {
193        if (!_images[n].valid() || !_images[n]->data())
194            return false;
195    }
196    return true;
197}
198
199void Texture2DArray::computeInternalFormat() const
200{
201    if (imagesValid()) computeInternalFormatWithImage(*_images[0]);
202    else computeInternalFormatType();
203}
204
205
206void Texture2DArray::apply(State& state) const
207{
208    // get the contextID (user defined ID of 0 upwards) for the
209    // current OpenGL context.
210    const unsigned int contextID = state.getContextID();
211    const Extensions* extensions = getExtensions(contextID,true);
212
213    // if not supported, then return
214    if (!extensions->isTexture2DArraySupported() || !extensions->isTexture3DSupported())
215    {
216        notify(WARN)<<"Warning: Texture2DArray::apply(..) failed, 2D texture arrays are not support by OpenGL driver."<<std::endl;
217        return;
218    }
219   
220    // get the texture object for the current contextID.
221    TextureObject* textureObject = getTextureObject(contextID);
222
223    // if we already have an texture object, then
224    if (textureObject != 0)
225    {
226        // bind texture object
227        textureObject->bind();
228
229        // if texture parameters changed, then reset them
230        if (getTextureParameterDirty(state.getContextID())) applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT,state);
231
232        // if subload is specified, then use it to subload the images to GPU memory
233        if (_subloadCallback.valid())
234        {
235            _subloadCallback->subload(*this,state);
236        }
237        else
238        {
239            // for each image of the texture array do
240            for (GLsizei n=0; n < _textureDepth; n++)
241            {
242                osg::Image* image = _images[n].get();
243               
244                // if image content is modified, then upload it to the GPU memory
245                if (image && getModifiedCount(n,contextID) != image->getModifiedCount())
246                {
247                    applyTexImage2DArray_subload(state, image, _textureWidth, _textureHeight, n, _internalFormat, _numMipmapLevels);
248                    getModifiedCount(n,contextID) = image->getModifiedCount();
249                }
250            }
251        }
252
253    }
254   
255    // there is no texture object, but exists a subload callback, so use it to upload images
256    else if (_subloadCallback.valid())
257    {
258        // generate texture (i.e. glGenTexture) and apply parameters
259        _textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID, GL_TEXTURE_2D_ARRAY_EXT);
260        textureObject->bind();
261        applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT, state);
262        _subloadCallback->load(*this,state);
263    }
264   
265    // nothing before, but we have valid images, so do manual upload and create texture object manually
266    // TODO: we assume _images[0] is valid, however this may not be always the case
267    //       some kind of checking for the first valid image is required (Art, may 2008)
268    else if (imagesValid())
269    {
270        // compute the internal texture format, this set the _internalFormat to an appropriate value.
271        computeInternalFormat();
272
273        // compute the dimensions of the texture.
274        computeRequiredTextureDimensions(state,*_images[0],_textureWidth, _textureHeight, _numMipmapLevels);
275
276        // create texture object
277        textureObject = generateTextureObject(
278                contextID,GL_TEXTURE_2D_ARRAY_EXT,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
279       
280        // bind texture
281        textureObject->bind();
282        applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT, state);
283
284        // first we need to allocate the texture memory
285        extensions->glTexImage3D( GL_TEXTURE_2D_ARRAY_EXT, 0, _internalFormat,
286                     _textureWidth, _textureHeight, _textureDepth,
287                     _borderWidth,
288                     _sourceFormat ? _sourceFormat : _internalFormat,
289                     _sourceType ? _sourceType : GL_UNSIGNED_BYTE,
290                     0);
291
292        // now for each layer we upload it into the memory
293        for (GLsizei n=0; n<_textureDepth; n++)
294        {
295            // if image is valid then upload it to the texture memory
296            osg::Image* image = _images[n].get();
297            if (image)
298            {
299                // now load the image data into the memory, this will also check if image do have valid properties
300                applyTexImage2DArray_subload(state, image, _textureWidth, _textureHeight, n, _internalFormat, _numMipmapLevels);
301                getModifiedCount(n,contextID) = image->getModifiedCount();
302            }
303        }
304        textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
305
306        _textureObjectBuffer[contextID] = textureObject;
307       
308        // no idea what this for ;-)
309        if (_unrefImageDataAfterApply && areAllTextureObjectsLoaded())
310        {
311            Texture2DArray* non_const_this = const_cast<Texture2DArray*>(this);
312            for (int n=0; n<_textureDepth; n++)
313            {               
314                if (_images[n].valid() && _images[n]->getDataVariance()==STATIC)
315                {
316                    non_const_this->_images[n] = 0;
317                }
318            }
319        }
320       
321    }
322   
323    // No images present, but dimensions are set. So create empty texture
324    else if ( (_textureWidth > 0) && (_textureHeight > 0) && (_textureDepth > 0) && (_internalFormat!=0) )
325    {
326        // generate texture
327        _textureObjectBuffer[contextID] = textureObject = generateTextureObject(
328                contextID, GL_TEXTURE_2D_ARRAY_EXT,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
329       
330        textureObject->bind();
331        applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT,state);
332       
333        extensions->glTexImage3D( GL_TEXTURE_2D_ARRAY_EXT, 0, _internalFormat,
334                     _textureWidth, _textureHeight, _textureDepth,
335                     _borderWidth,
336                     _sourceFormat ? _sourceFormat : _internalFormat,
337                     _sourceType ? _sourceType : GL_UNSIGNED_BYTE,
338                     0);
339       
340    }
341   
342    // nothing before, so just unbind the texture target
343    else
344    {
345        glBindTexture( GL_TEXTURE_2D_ARRAY_EXT, 0 );
346    }
347
348    // if texture object is now valid and we have to allocate mipmap levels, then
349    if (textureObject != 0 && _texMipmapGenerationDirtyList[contextID])
350    {
351        generateMipmap(state);
352    }
353}
354
355void Texture2DArray::applyTexImage2DArray_subload(State& state, Image* image, GLsizei inwidth, GLsizei inheight, GLsizei indepth, GLint inInternalFormat, GLsizei& numMipmapLevels) const
356{
357    // if we don't have a valid image we can't create a texture!
358    if (!imagesValid())
359        return;
360
361    // get the contextID (user defined ID of 0 upwards) for the
362    // current OpenGL context.
363    const unsigned int contextID = state.getContextID();
364    const Extensions* extensions = getExtensions(contextID,true);   
365    const Texture::Extensions* texExtensions = Texture::getExtensions(contextID,true);
366    GLenum target = GL_TEXTURE_2D_ARRAY_EXT;
367   
368    // compute the internal texture format, this set the _internalFormat to an appropriate value.
369    computeInternalFormat();
370
371    // select the internalFormat required for the texture.
372    // bool compressed = isCompressedInternalFormat(_internalFormat);
373    bool compressed_image = isCompressedInternalFormat((GLenum)image->getPixelFormat());
374
375    // if the required layer is exceeds the maximum allowed layer sizes
376    if (indepth > extensions->maxLayerCount())
377    {
378        // we give a warning and do nothing
379        notify(WARN)<<"Warning: Texture2DArray::applyTexImage2DArray_subload(..) the given layer number exceeds the maximum number of supported layers."<<std::endl;
380        return;       
381    }
382
383    //Rescale if resize hint is set or NPOT not supported or dimensions exceed max size
384    if( _resizeNonPowerOfTwoHint || !texExtensions->isNonPowerOfTwoTextureSupported(_min_filter)
385        || inwidth > extensions->max2DSize()
386        || inheight > extensions->max2DSize())
387        image->ensureValidSizeForTexturing(extensions->max2DSize());
388
389    // image size or format has changed, this is not allowed, hence return
390    if (image->s()!=inwidth ||
391        image->t()!=inheight ||
392        image->getInternalTextureFormat()!=inInternalFormat )
393    {
394        notify(WARN)<<"Warning: Texture2DArray::applyTexImage2DArray_subload(..) given image do have wrong dimension or internal format."<<std::endl;
395        return;       
396    }   
397   
398    glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking());
399
400    // if no special mipmapping is required, then
401    if( _min_filter == LINEAR || _min_filter == NEAREST )
402    {
403        numMipmapLevels = 1;
404
405        // upload non-compressed image
406        if (!compressed_image)
407        {
408            extensions->glTexSubImage3D( target, 0,
409                                      0, 0, indepth,
410                                      inwidth, inheight, 1,
411                                      (GLenum)image->getPixelFormat(),
412                                      (GLenum)image->getDataType(),
413                                      image->data() );
414        }
415       
416        // if we support compression and image is compressed, then
417        else if (extensions->isCompressedTexImage3DSupported())
418        {
419            // notify(WARN)<<"glCompressedTexImage3D "<<inwidth<<", "<<inheight<<", "<<indepth<<std::endl;
420            numMipmapLevels = 1;
421
422            GLint blockSize, size;
423            getCompressedSize(_internalFormat, inwidth, inheight, indepth, blockSize,size);
424
425            extensions->glCompressedTexSubImage3D(target, 0,
426                0, 0, indepth, 
427                inwidth, inheight, 1,
428                (GLenum)image->getPixelFormat(),
429                size,
430                image->data());
431        }
432
433    // we want to use mipmapping, so enable it
434    }else
435    {
436        // image does not provide mipmaps, so we have to create them
437        if(!image->isMipmap())
438        {
439            notify(WARN)<<"Warning: Texture2DArray::applyTexImage2DArray_subload(..) automagic mipmap generation is currently not implemented. Check texture's min/mag filters."<<std::endl;
440
441        // the image object does provide mipmaps, so upload the in the certain levels of a layer
442        }else
443        {
444            numMipmapLevels = image->getNumMipmapLevels();
445
446            int width  = image->s();
447            int height = image->t();
448           
449            for( GLsizei k = 0 ; k < numMipmapLevels  && (width || height ) ;k++)
450            {
451
452                if (width == 0)
453                    width = 1;
454                if (height == 0)
455                    height = 1;
456
457                extensions->glTexSubImage3D( target, k, 0, 0, indepth,
458                                          width, height, 1,
459                                          (GLenum)image->getPixelFormat(),
460                                          (GLenum)image->getDataType(),
461                                          image->getMipmapData(k));
462
463                width >>= 1;
464                height >>= 1;
465            }
466        }
467
468    }
469}
470
471
472void Texture2DArray::copyTexSubImage2DArray(State& state, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height )
473{
474    const unsigned int contextID = state.getContextID();
475    const Extensions* extensions = getExtensions(contextID,true);
476
477    // get the texture object for the current contextID.
478    TextureObject* textureObject = getTextureObject(contextID);
479
480    // if texture object is valid
481    if (textureObject != 0)
482    {
483        textureObject->bind();
484
485        applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT,state);
486        extensions->glCopyTexSubImage3D( GL_TEXTURE_2D_ARRAY_EXT, 0, xoffset,yoffset,zoffset, x, y, width, height);
487
488        // inform state that this texture is the current one bound.
489        state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), this);
490
491    }
492    else
493    {
494        notify(WARN)<<"Warning: Texture2DArray::copyTexSubImage2DArray(..) failed, cannot not copy to a non existant texture."<<std::endl;
495    }
496}
497
498void Texture2DArray::allocateMipmap(State& state) const
499{
500    const unsigned int contextID = state.getContextID();
501
502    // get the texture object for the current contextID.
503    TextureObject* textureObject = getTextureObject(contextID);
504   
505    if (textureObject && _textureWidth != 0 && _textureHeight != 0 && _textureDepth != 0)
506    {
507        const Extensions* extensions = getExtensions(contextID,true);
508        // const Texture::Extensions* texExtensions = Texture::getExtensions(contextID,true);
509       
510        // bind texture
511        textureObject->bind();
512
513        // compute number of mipmap levels
514        int width = _textureWidth;
515        int height = _textureHeight;
516        int numMipmapLevels = Image::computeNumberOfMipmapLevels(width, height);
517
518        // we do not reallocate the level 0, since it was already allocated
519        width >>= 1;
520        height >>= 1;
521       
522        for( GLsizei k = 1; k < numMipmapLevels  && (width || height); k++)
523        {
524            if (width == 0)
525                width = 1;
526            if (height == 0)
527                height = 1;
528
529            extensions->glTexImage3D( GL_TEXTURE_2D_ARRAY_EXT, k, _internalFormat,
530                     width, height, _textureDepth, _borderWidth,
531                     _sourceFormat ? _sourceFormat : _internalFormat,
532                     _sourceType ? _sourceType : GL_UNSIGNED_BYTE, NULL);
533
534            width >>= 1;
535            height >>= 1;
536        }
537               
538        // inform state that this texture is the current one bound.
539        state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), this);       
540    }
541}
542
543typedef buffered_value< ref_ptr<Texture2DArray::Extensions> > BufferedExtensions;
544static BufferedExtensions s_extensions;
545
546Texture2DArray::Extensions* Texture2DArray::getExtensions(unsigned int contextID,bool createIfNotInitalized)
547{
548    if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Extensions(contextID);
549    return s_extensions[contextID].get();
550}
551
552void Texture2DArray::setExtensions(unsigned int contextID,Extensions* extensions)
553{
554    s_extensions[contextID] = extensions;
555}
556
557Texture2DArray::Extensions::Extensions(unsigned int contextID)
558{
559    setupGLExtensions(contextID);
560}
561
562Texture2DArray::Extensions::Extensions(const Extensions& rhs):
563    Referenced()
564{
565    _isTexture3DSupported = rhs._isTexture3DSupported;
566    _isTexture2DArraySupported = rhs._isTexture2DArraySupported;
567   
568    _max2DSize = rhs._max2DSize;
569    _maxLayerCount = rhs._maxLayerCount;
570   
571    _glTexImage3D = rhs._glTexImage3D;
572    _glTexSubImage3D = rhs._glTexSubImage3D;
573    _glCopyTexSubImage3D = rhs._glCopyTexSubImage3D;
574    _glCompressedTexImage3D = rhs._glCompressedTexImage3D;
575    _glCompressedTexSubImage3D = rhs._glCompressedTexSubImage3D;;
576}
577
578void Texture2DArray::Extensions::lowestCommonDenominator(const Extensions& rhs)
579{
580    if (!rhs._isTexture3DSupported)                 _isTexture3DSupported = false;
581    if (!rhs._isTexture2DArraySupported)            _isTexture2DArraySupported = false;
582    if (rhs._max2DSize<_max2DSize)                  _max2DSize = rhs._max2DSize;
583    if (rhs._maxLayerCount<_maxLayerCount)          _maxLayerCount = rhs._maxLayerCount;
584
585    if (!rhs._glTexImage3D)                         _glTexImage3D = 0;
586    if (!rhs._glTexSubImage3D)                      _glTexSubImage3D = 0;
587    if (!rhs._glCompressedTexImage3D)               _glTexImage3D = 0;
588    if (!rhs._glCompressedTexSubImage3D)            _glTexSubImage3D = 0;
589    if (!rhs._glCopyTexSubImage3D)                  _glCopyTexSubImage3D = 0;
590}
591
592void Texture2DArray::Extensions::setupGLExtensions(unsigned int contextID)
593{
594    _isTexture3DSupported = isGLExtensionSupported(contextID,"GL_EXT_texture3D");
595    _isTexture2DArraySupported = isGLExtensionSupported(contextID,"GL_EXT_texture_array");
596
597    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_max2DSize);
598    glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, &_maxLayerCount);
599
600    setGLExtensionFuncPtr(_glTexImage3D, "glTexImage3D","glTexImage3DEXT");
601    setGLExtensionFuncPtr(_glTexSubImage3D, "glTexSubImage3D","glTexSubImage3DEXT");
602    setGLExtensionFuncPtr(_glCompressedTexImage3D, "glCompressedTexImage3D","glCompressedTexImage3DARB");
603    setGLExtensionFuncPtr(_glCompressedTexSubImage3D, "glCompressedTexSubImage3D","glCompressedTexSubImage3DARB");
604    setGLExtensionFuncPtr(_glCopyTexSubImage3D, "glCopyTexSubImage3D","glCopyTexSubImage3DEXT");
605}
606
607void Texture2DArray::Extensions::glTexImage3D( GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) const
608{
609    if (_glTexImage3D)
610    {
611        _glTexImage3D( target, level, internalFormat, width, height, depth, border, format, type, pixels);
612    }
613    else
614    {
615        notify(WARN)<<"Error: glTexImage3D not supported by OpenGL driver"<<std::endl;
616    }
617}
618
619void Texture2DArray::Extensions::glTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) const
620{
621    if (_glTexSubImage3D)
622    {
623        _glTexSubImage3D( target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
624    }
625    else
626    {
627        notify(WARN)<<"Error: glTexSubImage3D not supported by OpenGL driver"<<std::endl;
628    }
629}
630
631void Texture2DArray::Extensions::glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) const
632{
633    if (_glCompressedTexImage3D)
634    {
635        _glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data);
636    }
637    else
638    {
639        notify(WARN)<<"Error: glCompressedTexImage3D not supported by OpenGL driver"<<std::endl;
640    }
641}
642
643void Texture2DArray::Extensions::glCompressedTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data ) const
644{
645    if (_glCompressedTexSubImage3D)
646    {
647        _glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
648    }
649    else
650    {
651        notify(WARN)<<"Error: glCompressedTexImage2D not supported by OpenGL driver"<<std::endl;
652    }
653}
654
655void Texture2DArray::Extensions::glCopyTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ) const
656{
657    if (_glCopyTexSubImage3D)
658    {
659        _glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
660    }
661    else
662    {
663        notify(WARN)<<"Error: glCopyTexSubImage3D not supported by OpenGL driver"<<std::endl;
664    }
665}
Note: See TracBrowser for help on using the browser.