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