Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / Texture.cpp
1 //
2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // Texture.cpp: Implements the gl::Texture class and its derived classes
8 // Texture2D and TextureCubeMap. Implements GL texture objects and related
9 // functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
10
11 #include "libGLESv2/Texture.h"
12 #include "libGLESv2/main.h"
13 #include "libGLESv2/Context.h"
14 #include "libGLESv2/formatutils.h"
15 #include "libGLESv2/ImageIndex.h"
16 #include "libGLESv2/Renderbuffer.h"
17 #include "libGLESv2/renderer/Image.h"
18 #include "libGLESv2/renderer/d3d/TextureStorage.h"
19
20 #include "libEGL/Surface.h"
21
22 #include "common/mathutil.h"
23 #include "common/utilities.h"
24
25 namespace gl
26 {
27
28 bool IsMipmapFiltered(const gl::SamplerState &samplerState)
29 {
30     switch (samplerState.minFilter)
31     {
32       case GL_NEAREST:
33       case GL_LINEAR:
34         return false;
35       case GL_NEAREST_MIPMAP_NEAREST:
36       case GL_LINEAR_MIPMAP_NEAREST:
37       case GL_NEAREST_MIPMAP_LINEAR:
38       case GL_LINEAR_MIPMAP_LINEAR:
39         return true;
40       default: UNREACHABLE();
41         return false;
42     }
43 }
44
45 bool IsPointSampled(const gl::SamplerState &samplerState)
46 {
47     return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
48 }
49
50 unsigned int Texture::mCurrentTextureSerial = 1;
51
52 Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
53     : RefCountObject(id),
54       mTexture(impl),
55       mTextureSerial(issueTextureSerial()),
56       mUsage(GL_NONE),
57       mImmutableLevelCount(0),
58       mTarget(target)
59 {
60 }
61
62 Texture::~Texture()
63 {
64     SafeDelete(mTexture);
65 }
66
67 GLenum Texture::getTarget() const
68 {
69     return mTarget;
70 }
71
72 void Texture::setUsage(GLenum usage)
73 {
74     mUsage = usage;
75     getImplementation()->setUsage(usage);
76 }
77
78 GLenum Texture::getUsage() const
79 {
80     return mUsage;
81 }
82
83 GLint Texture::getBaseLevelWidth() const
84 {
85     const rx::Image *baseImage = getBaseLevelImage();
86     return (baseImage ? baseImage->getWidth() : 0);
87 }
88
89 GLint Texture::getBaseLevelHeight() const
90 {
91     const rx::Image *baseImage = getBaseLevelImage();
92     return (baseImage ? baseImage->getHeight() : 0);
93 }
94
95 GLint Texture::getBaseLevelDepth() const
96 {
97     const rx::Image *baseImage = getBaseLevelImage();
98     return (baseImage ? baseImage->getDepth() : 0);
99 }
100
101 // Note: "base level image" is loosely defined to be any image from the base level,
102 // where in the base of 2D array textures and cube maps there are several. Don't use
103 // the base level image for anything except querying texture format and size.
104 GLenum Texture::getBaseLevelInternalFormat() const
105 {
106     const rx::Image *baseImage = getBaseLevelImage();
107     return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
108 }
109
110 GLsizei Texture::getWidth(const ImageIndex &index) const
111 {
112     rx::Image *image = mTexture->getImage(index);
113     return image->getWidth();
114 }
115
116 GLsizei Texture::getHeight(const ImageIndex &index) const
117 {
118     rx::Image *image = mTexture->getImage(index);
119     return image->getHeight();
120 }
121
122 GLenum Texture::getInternalFormat(const ImageIndex &index) const
123 {
124     rx::Image *image = mTexture->getImage(index);
125     return image->getInternalFormat();
126 }
127
128 GLenum Texture::getActualFormat(const ImageIndex &index) const
129 {
130     rx::Image *image = mTexture->getImage(index);
131     return image->getActualFormat();
132 }
133
134 Error Texture::generateMipmaps()
135 {
136     return getImplementation()->generateMipmaps();
137 }
138
139 Error Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
140                            GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
141 {
142     return mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
143 }
144
145 unsigned int Texture::getTextureSerial() const
146 {
147     return mTextureSerial;
148 }
149
150 unsigned int Texture::issueTextureSerial()
151 {
152     return mCurrentTextureSerial++;
153 }
154
155 bool Texture::isImmutable() const
156 {
157     return (mImmutableLevelCount > 0);
158 }
159
160 int Texture::immutableLevelCount()
161 {
162     return mImmutableLevelCount;
163 }
164
165 int Texture::mipLevels() const
166 {
167     return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
168 }
169
170 const rx::Image *Texture::getBaseLevelImage() const
171 {
172     return (getImplementation()->getLayerCount(0) > 0 ? getImplementation()->getImage(0, 0) : NULL);
173 }
174
175 Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id)
176     : Texture(impl, id, GL_TEXTURE_2D)
177 {
178     mSurface = NULL;
179 }
180
181 Texture2D::~Texture2D()
182 {
183     if (mSurface)
184     {
185         mSurface->setBoundTexture(NULL);
186         mSurface = NULL;
187     }
188 }
189
190 GLsizei Texture2D::getWidth(GLint level) const
191 {
192     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
193         return mTexture->getImage(level, 0)->getWidth();
194     else
195         return 0;
196 }
197
198 GLsizei Texture2D::getHeight(GLint level) const
199 {
200     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
201         return mTexture->getImage(level, 0)->getHeight();
202     else
203         return 0;
204 }
205
206 GLenum Texture2D::getInternalFormat(GLint level) const
207 {
208     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
209         return mTexture->getImage(level, 0)->getInternalFormat();
210     else
211         return GL_NONE;
212 }
213
214 GLenum Texture2D::getActualFormat(GLint level) const
215 {
216     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
217         return mTexture->getImage(level, 0)->getActualFormat();
218     else
219         return GL_NONE;
220 }
221
222 Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
223 {
224     releaseTexImage();
225
226     return mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels);
227 }
228
229 void Texture2D::bindTexImage(egl::Surface *surface)
230 {
231     releaseTexImage();
232
233     mTexture->bindTexImage(surface);
234
235     mSurface = surface;
236     mSurface->setBoundTexture(this);
237 }
238
239 void Texture2D::releaseTexImage()
240 {
241     if (mSurface)
242     {
243         mSurface->setBoundTexture(NULL);
244         mSurface = NULL;
245
246         mTexture->releaseTexImage();
247     }
248 }
249
250 Error Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize,
251                                     const PixelUnpackState &unpack, const void *pixels)
252 {
253     releaseTexImage();
254
255     return mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, unpack, pixels);
256 }
257
258 Error Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
259 {
260     return mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
261 }
262
263 Error Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
264                                     GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
265 {
266     return mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels);
267 }
268
269 Error Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height,
270                            Framebuffer *source)
271 {
272     releaseTexImage();
273
274     return mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source);
275 }
276
277 Error Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
278 {
279     Error error = mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1);
280     if (error.isError())
281     {
282         return error;
283     }
284
285     mImmutableLevelCount = levels;
286
287     return Error(GL_NO_ERROR);
288 }
289
290 // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
291 bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
292 {
293     GLsizei width = getBaseLevelWidth();
294     GLsizei height = getBaseLevelHeight();
295
296     if (width <= 0 || height <= 0)
297     {
298         return false;
299     }
300
301     if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
302     {
303         return false;
304     }
305
306     bool npotSupport = extensions.textureNPOT;
307
308     if (!npotSupport)
309     {
310         if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
311             (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
312         {
313             return false;
314         }
315     }
316
317     if (IsMipmapFiltered(samplerState))
318     {
319         if (!npotSupport)
320         {
321             if (!gl::isPow2(width) || !gl::isPow2(height))
322             {
323                 return false;
324             }
325         }
326
327         if (!isMipmapComplete())
328         {
329             return false;
330         }
331     }
332
333     // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
334     // The internalformat specified for the texture arrays is a sized internal depth or
335     // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
336     // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
337     // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
338     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(0));
339     if (formatInfo.depthBits > 0 && clientVersion > 2)
340     {
341         if (samplerState.compareMode == GL_NONE)
342         {
343             if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
344                 samplerState.magFilter != GL_NEAREST)
345             {
346                 return false;
347             }
348         }
349     }
350
351     return true;
352 }
353
354 bool Texture2D::isCompressed(GLint level) const
355 {
356     return GetInternalFormatInfo(getInternalFormat(level)).compressed;
357 }
358
359 bool Texture2D::isDepth(GLint level) const
360 {
361     return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
362 }
363
364 Error Texture2D::generateMipmaps()
365 {
366     releaseTexImage();
367
368     return mTexture->generateMipmaps();
369 }
370
371 // Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
372 bool Texture2D::isMipmapComplete() const
373 {
374     int levelCount = mipLevels();
375
376     for (int level = 0; level < levelCount; level++)
377     {
378         if (!isLevelComplete(level))
379         {
380             return false;
381         }
382     }
383
384     return true;
385 }
386
387 bool Texture2D::isLevelComplete(int level) const
388 {
389     if (isImmutable())
390     {
391         return true;
392     }
393
394     const rx::Image *baseImage = getBaseLevelImage();
395
396     GLsizei width = baseImage->getWidth();
397     GLsizei height = baseImage->getHeight();
398
399     if (width <= 0 || height <= 0)
400     {
401         return false;
402     }
403
404     // The base image level is complete if the width and height are positive
405     if (level == 0)
406     {
407         return true;
408     }
409
410     ASSERT(level >= 1 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
411     rx::Image *image = mTexture->getImage(level, 0);
412
413     if (image->getInternalFormat() != baseImage->getInternalFormat())
414     {
415         return false;
416     }
417
418     if (image->getWidth() != std::max(1, width >> level))
419     {
420         return false;
421     }
422
423     if (image->getHeight() != std::max(1, height >> level))
424     {
425         return false;
426     }
427
428     return true;
429 }
430
431 TextureCubeMap::TextureCubeMap(rx::TextureImpl *impl, GLuint id)
432     : Texture(impl, id, GL_TEXTURE_CUBE_MAP)
433 {
434 }
435
436 TextureCubeMap::~TextureCubeMap()
437 {
438 }
439
440 GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
441 {
442     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
443         return mTexture->getImage(level, targetToLayerIndex(target))->getWidth();
444     else
445         return 0;
446 }
447
448 GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
449 {
450     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
451         return mTexture->getImage(level, targetToLayerIndex(target))->getHeight();
452     else
453         return 0;
454 }
455
456 GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
457 {
458     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
459         return mTexture->getImage(level, targetToLayerIndex(target))->getInternalFormat();
460     else
461         return GL_NONE;
462 }
463
464 GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const
465 {
466     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
467         return mTexture->getImage(level, targetToLayerIndex(target))->getActualFormat();
468     else
469         return GL_NONE;
470 }
471
472 Error TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
473 {
474     return mTexture->setImage(target, level, width, height, 1, internalFormat, format, type, unpack, pixels);
475 }
476
477 Error TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height,
478                                          GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
479 {
480     return mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, unpack, pixels);
481 }
482
483 Error TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
484 {
485     return mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
486 }
487
488 Error TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset,
489                                          GLsizei width, GLsizei height, GLenum format,
490                                          GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
491 {
492     return mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels);
493 }
494
495 // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
496 bool TextureCubeMap::isCubeComplete() const
497 {
498     int    baseWidth  = getBaseLevelWidth();
499     int    baseHeight = getBaseLevelHeight();
500     GLenum baseFormat = getBaseLevelInternalFormat();
501
502     if (baseWidth <= 0 || baseWidth != baseHeight)
503     {
504         return false;
505     }
506
507     for (int faceIndex = 1; faceIndex < 6; faceIndex++)
508     {
509         const rx::Image *faceBaseImage = mTexture->getImage(0, faceIndex);
510
511         if (faceBaseImage->getWidth()          != baseWidth  ||
512             faceBaseImage->getHeight()         != baseHeight ||
513             faceBaseImage->getInternalFormat() != baseFormat )
514         {
515             return false;
516         }
517     }
518
519     return true;
520 }
521
522 bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
523 {
524     return GetInternalFormatInfo(getInternalFormat(target, level)).compressed;
525 }
526
527 bool TextureCubeMap::isDepth(GLenum target, GLint level) const
528 {
529     return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0;
530 }
531
532 Error TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y,
533                                 GLsizei width, GLsizei height, Framebuffer *source)
534 {
535     return mTexture->copyImage(target, level, format, x, y, width, height, source);
536 }
537
538 Error TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
539 {
540     Error error = mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1);
541     if (error.isError())
542     {
543         return error;
544     }
545
546     mImmutableLevelCount = levels;
547
548     return Error(GL_NO_ERROR);
549 }
550
551 // Tests for texture sampling completeness
552 bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
553 {
554     int size = getBaseLevelWidth();
555
556     bool mipmapping = IsMipmapFiltered(samplerState);
557
558     if (!textureCaps.get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable && !IsPointSampled(samplerState))
559     {
560         return false;
561     }
562
563     if (!gl::isPow2(size) && !extensions.textureNPOT)
564     {
565         if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
566         {
567             return false;
568         }
569     }
570
571     if (!mipmapping)
572     {
573         if (!isCubeComplete())
574         {
575             return false;
576         }
577     }
578     else
579     {
580         if (!isMipmapComplete())   // Also tests for isCubeComplete()
581         {
582             return false;
583         }
584     }
585
586     return true;
587 }
588
589 int TextureCubeMap::targetToLayerIndex(GLenum target)
590 {
591     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
592     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
593     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
594     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
595     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
596
597     return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
598 }
599
600 GLenum TextureCubeMap::layerIndexToTarget(GLint layer)
601 {
602     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
603     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
604     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
605     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
606     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
607
608     return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
609 }
610
611 bool TextureCubeMap::isMipmapComplete() const
612 {
613     if (isImmutable())
614     {
615         return true;
616     }
617
618     if (!isCubeComplete())
619     {
620         return false;
621     }
622
623     int levelCount = mipLevels();
624
625     for (int face = 0; face < 6; face++)
626     {
627         for (int level = 1; level < levelCount; level++)
628         {
629             if (!isFaceLevelComplete(face, level))
630             {
631                 return false;
632             }
633         }
634     }
635
636     return true;
637 }
638
639 bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const
640 {
641     ASSERT(level >= 0 && faceIndex < 6 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, faceIndex) != NULL);
642
643     if (isImmutable())
644     {
645         return true;
646     }
647
648     int baseSize = getBaseLevelWidth();
649
650     if (baseSize <= 0)
651     {
652         return false;
653     }
654
655     // "isCubeComplete" checks for base level completeness and we must call that
656     // to determine if any face at level 0 is complete. We omit that check here
657     // to avoid re-checking cube-completeness for every face at level 0.
658     if (level == 0)
659     {
660         return true;
661     }
662
663     // Check that non-zero levels are consistent with the base level.
664     const rx::Image *faceLevelImage = mTexture->getImage(level, faceIndex);
665
666     if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
667     {
668         return false;
669     }
670
671     if (faceLevelImage->getWidth() != std::max(1, baseSize >> level))
672     {
673         return false;
674     }
675
676     return true;
677 }
678
679
680 Texture3D::Texture3D(rx::TextureImpl *impl, GLuint id)
681     : Texture(impl, id, GL_TEXTURE_3D)
682 {
683 }
684
685 Texture3D::~Texture3D()
686 {
687 }
688
689 GLsizei Texture3D::getWidth(GLint level) const
690 {
691     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getWidth() : 0;
692 }
693
694 GLsizei Texture3D::getHeight(GLint level) const
695 {
696     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getHeight() : 0;
697 }
698
699 GLsizei Texture3D::getDepth(GLint level) const
700 {
701     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getDepth() : 0;
702 }
703
704 GLenum Texture3D::getInternalFormat(GLint level) const
705 {
706     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
707 }
708
709 GLenum Texture3D::getActualFormat(GLint level) const
710 {
711     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE;
712 }
713
714 bool Texture3D::isCompressed(GLint level) const
715 {
716     return GetInternalFormatInfo(getInternalFormat(level)).compressed;
717 }
718
719 bool Texture3D::isDepth(GLint level) const
720 {
721     return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
722 }
723
724 Error Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
725 {
726     return mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels);
727 }
728
729 Error Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
730                                     GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
731 {
732     return mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, unpack, pixels);
733 }
734
735 Error Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
736 {
737     return mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
738 }
739
740 Error Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
741                                     GLsizei width, GLsizei height, GLsizei depth, GLenum format,
742                                     GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
743 {
744     return mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels);
745 }
746
747 Error Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
748 {
749     Error error = mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth);
750     if (error.isError())
751     {
752         return error;
753     }
754
755     mImmutableLevelCount = levels;
756
757     return Error(GL_NO_ERROR);
758 }
759
760 bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
761 {
762     GLsizei width = getBaseLevelWidth();
763     GLsizei height = getBaseLevelHeight();
764     GLsizei depth = getBaseLevelDepth();
765
766     if (width <= 0 || height <= 0 || depth <= 0)
767     {
768         return false;
769     }
770
771     if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
772     {
773         return false;
774     }
775
776     if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
777     {
778         return false;
779     }
780
781     return true;
782 }
783
784 bool Texture3D::isMipmapComplete() const
785 {
786     int levelCount = mipLevels();
787
788     for (int level = 0; level < levelCount; level++)
789     {
790         if (!isLevelComplete(level))
791         {
792             return false;
793         }
794     }
795
796     return true;
797 }
798
799 bool Texture3D::isLevelComplete(int level) const
800 {
801     ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
802
803     if (isImmutable())
804     {
805         return true;
806     }
807
808     GLsizei width = getBaseLevelWidth();
809     GLsizei height = getBaseLevelHeight();
810     GLsizei depth = getBaseLevelDepth();
811
812     if (width <= 0 || height <= 0 || depth <= 0)
813     {
814         return false;
815     }
816
817     if (level == 0)
818     {
819         return true;
820     }
821
822     rx::Image *levelImage = mTexture->getImage(level, 0);
823
824     if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
825     {
826         return false;
827     }
828
829     if (levelImage->getWidth() != std::max(1, width >> level))
830     {
831         return false;
832     }
833
834     if (levelImage->getHeight() != std::max(1, height >> level))
835     {
836         return false;
837     }
838
839     if (levelImage->getDepth() != std::max(1, depth >> level))
840     {
841         return false;
842     }
843
844     return true;
845 }
846
847 Texture2DArray::Texture2DArray(rx::TextureImpl *impl, GLuint id)
848     : Texture(impl, id, GL_TEXTURE_2D_ARRAY)
849 {
850 }
851
852 Texture2DArray::~Texture2DArray()
853 {
854 }
855
856 GLsizei Texture2DArray::getWidth(GLint level) const
857 {
858     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getWidth() : 0;
859 }
860
861 GLsizei Texture2DArray::getHeight(GLint level) const
862 {
863     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getHeight() : 0;
864 }
865
866 GLsizei Texture2DArray::getLayers(GLint level) const
867 {
868     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getLayerCount(level) : 0;
869 }
870
871 GLenum Texture2DArray::getInternalFormat(GLint level) const
872 {
873     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
874 }
875
876 GLenum Texture2DArray::getActualFormat(GLint level) const
877 {
878     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE;
879 }
880
881 bool Texture2DArray::isCompressed(GLint level) const
882 {
883     return GetInternalFormatInfo(getInternalFormat(level)).compressed;
884 }
885
886 bool Texture2DArray::isDepth(GLint level) const
887 {
888     return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
889 }
890
891 Error Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
892 {
893     return mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels);
894 }
895
896 Error Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
897                                          GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
898 {
899     return mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, unpack, pixels);
900 }
901
902 Error Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
903 {
904     return mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
905 }
906
907 Error Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
908                                          GLsizei width, GLsizei height, GLsizei depth, GLenum format,
909                                          GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
910 {
911     return mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels);
912 }
913
914 Error Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
915 {
916     Error error = mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth);
917     if (error.isError())
918     {
919         return error;
920     }
921
922     mImmutableLevelCount = levels;
923
924     return Error(GL_NO_ERROR);
925 }
926
927 bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
928 {
929     GLsizei width = getBaseLevelWidth();
930     GLsizei height = getBaseLevelHeight();
931     GLsizei depth = getLayers(0);
932
933     if (width <= 0 || height <= 0 || depth <= 0)
934     {
935         return false;
936     }
937
938     if (!textureCaps.get(getBaseLevelInternalFormat()).filterable && !IsPointSampled(samplerState))
939     {
940         return false;
941     }
942
943     if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
944     {
945         return false;
946     }
947
948     return true;
949 }
950
951 bool Texture2DArray::isMipmapComplete() const
952 {
953     int levelCount = mipLevels();
954
955     for (int level = 1; level < levelCount; level++)
956     {
957         if (!isLevelComplete(level))
958         {
959             return false;
960         }
961     }
962
963     return true;
964 }
965
966 bool Texture2DArray::isLevelComplete(int level) const
967 {
968     ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
969
970     if (isImmutable())
971     {
972         return true;
973     }
974
975     GLsizei width = getBaseLevelWidth();
976     GLsizei height = getBaseLevelHeight();
977     GLsizei layers = getLayers(0);
978
979     if (width <= 0 || height <= 0 || layers <= 0)
980     {
981         return false;
982     }
983
984     if (level == 0)
985     {
986         return true;
987     }
988
989     if (getInternalFormat(level) != getInternalFormat(0))
990     {
991         return false;
992     }
993
994     if (getWidth(level) != std::max(1, width >> level))
995     {
996         return false;
997     }
998
999     if (getHeight(level) != std::max(1, height >> level))
1000     {
1001         return false;
1002     }
1003
1004     if (getLayers(level) != layers)
1005     {
1006         return false;
1007     }
1008
1009     return true;
1010 }
1011
1012 }