Home | History | Annotate | Download | only in libGLESv2
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 //
      7 
      8 // Texture.cpp: Implements the gl::Texture class and its derived classes
      9 // Texture2D and TextureCubeMap. Implements GL texture objects and related
     10 // functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
     11 
     12 #include "libGLESv2/Texture.h"
     13 
     14 #include "libGLESv2/main.h"
     15 #include "common/mathutil.h"
     16 #include "common/utilities.h"
     17 #include "libGLESv2/formatutils.h"
     18 #include "libGLESv2/Renderbuffer.h"
     19 #include "libGLESv2/renderer/Image.h"
     20 #include "libGLESv2/renderer/Renderer.h"
     21 #include "libGLESv2/renderer/TextureStorage.h"
     22 #include "libEGL/Surface.h"
     23 #include "libGLESv2/Buffer.h"
     24 #include "libGLESv2/renderer/BufferStorage.h"
     25 #include "libGLESv2/renderer/RenderTarget.h"
     26 
     27 namespace gl
     28 {
     29 
     30 bool IsMipmapFiltered(const SamplerState &samplerState)
     31 {
     32     switch (samplerState.minFilter)
     33     {
     34       case GL_NEAREST:
     35       case GL_LINEAR:
     36         return false;
     37       case GL_NEAREST_MIPMAP_NEAREST:
     38       case GL_LINEAR_MIPMAP_NEAREST:
     39       case GL_NEAREST_MIPMAP_LINEAR:
     40       case GL_LINEAR_MIPMAP_LINEAR:
     41         return true;
     42       default: UNREACHABLE();
     43         return false;
     44     }
     45 }
     46 
     47 bool IsRenderTargetUsage(GLenum usage)
     48 {
     49     return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
     50 }
     51 
     52 Texture::Texture(rx::Renderer *renderer, GLuint id, GLenum target) : RefCountObject(id)
     53 {
     54     mRenderer = renderer;
     55 
     56     mSamplerState.minFilter = GL_NEAREST_MIPMAP_LINEAR;
     57     mSamplerState.magFilter = GL_LINEAR;
     58     mSamplerState.wrapS = GL_REPEAT;
     59     mSamplerState.wrapT = GL_REPEAT;
     60     mSamplerState.wrapR = GL_REPEAT;
     61     mSamplerState.maxAnisotropy = 1.0f;
     62     mSamplerState.baseLevel = 0;
     63     mSamplerState.maxLevel = 1000;
     64     mSamplerState.minLod = -1000.0f;
     65     mSamplerState.maxLod = 1000.0f;
     66     mSamplerState.compareMode = GL_NONE;
     67     mSamplerState.compareFunc = GL_LEQUAL;
     68     mSamplerState.swizzleRed = GL_RED;
     69     mSamplerState.swizzleGreen = GL_GREEN;
     70     mSamplerState.swizzleBlue = GL_BLUE;
     71     mSamplerState.swizzleAlpha = GL_ALPHA;
     72     mUsage = GL_NONE;
     73 
     74     mDirtyImages = true;
     75 
     76     mImmutable = false;
     77 
     78     mTarget = target;
     79 }
     80 
     81 Texture::~Texture()
     82 {
     83 }
     84 
     85 GLenum Texture::getTarget() const
     86 {
     87     return mTarget;
     88 }
     89 
     90 void Texture::addProxyRef(const FramebufferAttachment *proxy)
     91 {
     92     mRenderbufferProxies.addRef(proxy);
     93 }
     94 
     95 void Texture::releaseProxy(const FramebufferAttachment *proxy)
     96 {
     97     mRenderbufferProxies.release(proxy);
     98 }
     99 
    100 void Texture::setMinFilter(GLenum filter)
    101 {
    102     mSamplerState.minFilter = filter;
    103 }
    104 
    105 void Texture::setMagFilter(GLenum filter)
    106 {
    107     mSamplerState.magFilter = filter;
    108 }
    109 
    110 void Texture::setWrapS(GLenum wrap)
    111 {
    112     mSamplerState.wrapS = wrap;
    113 }
    114 
    115 void Texture::setWrapT(GLenum wrap)
    116 {
    117     mSamplerState.wrapT = wrap;
    118 }
    119 
    120 void Texture::setWrapR(GLenum wrap)
    121 {
    122     mSamplerState.wrapR = wrap;
    123 }
    124 
    125 void Texture::setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy)
    126 {
    127     mSamplerState.maxAnisotropy = std::min(textureMaxAnisotropy, contextMaxAnisotropy);
    128 }
    129 
    130 void Texture::setCompareMode(GLenum mode)
    131 {
    132     mSamplerState.compareMode = mode;
    133 }
    134 
    135 void Texture::setCompareFunc(GLenum func)
    136 {
    137     mSamplerState.compareFunc = func;
    138 }
    139 
    140 void Texture::setSwizzleRed(GLenum swizzle)
    141 {
    142     mSamplerState.swizzleRed = swizzle;
    143 }
    144 
    145 void Texture::setSwizzleGreen(GLenum swizzle)
    146 {
    147     mSamplerState.swizzleGreen = swizzle;
    148 }
    149 
    150 void Texture::setSwizzleBlue(GLenum swizzle)
    151 {
    152     mSamplerState.swizzleBlue = swizzle;
    153 }
    154 
    155 void Texture::setSwizzleAlpha(GLenum swizzle)
    156 {
    157     mSamplerState.swizzleAlpha = swizzle;
    158 }
    159 
    160 void Texture::setBaseLevel(GLint baseLevel)
    161 {
    162     mSamplerState.baseLevel = baseLevel;
    163 }
    164 
    165 void Texture::setMaxLevel(GLint maxLevel)
    166 {
    167     mSamplerState.maxLevel = maxLevel;
    168 }
    169 
    170 void Texture::setMinLod(GLfloat minLod)
    171 {
    172     mSamplerState.minLod = minLod;
    173 }
    174 
    175 void Texture::setMaxLod(GLfloat maxLod)
    176 {
    177     mSamplerState.maxLod = maxLod;
    178 }
    179 
    180 void Texture::setUsage(GLenum usage)
    181 {
    182     mUsage = usage;
    183 }
    184 
    185 GLenum Texture::getMinFilter() const
    186 {
    187     return mSamplerState.minFilter;
    188 }
    189 
    190 GLenum Texture::getMagFilter() const
    191 {
    192     return mSamplerState.magFilter;
    193 }
    194 
    195 GLenum Texture::getWrapS() const
    196 {
    197     return mSamplerState.wrapS;
    198 }
    199 
    200 GLenum Texture::getWrapT() const
    201 {
    202     return mSamplerState.wrapT;
    203 }
    204 
    205 GLenum Texture::getWrapR() const
    206 {
    207     return mSamplerState.wrapR;
    208 }
    209 
    210 float Texture::getMaxAnisotropy() const
    211 {
    212     return mSamplerState.maxAnisotropy;
    213 }
    214 
    215 GLenum Texture::getSwizzleRed() const
    216 {
    217     return mSamplerState.swizzleRed;
    218 }
    219 
    220 GLenum Texture::getSwizzleGreen() const
    221 {
    222     return mSamplerState.swizzleGreen;
    223 }
    224 
    225 GLenum Texture::getSwizzleBlue() const
    226 {
    227     return mSamplerState.swizzleBlue;
    228 }
    229 
    230 GLenum Texture::getSwizzleAlpha() const
    231 {
    232     return mSamplerState.swizzleAlpha;
    233 }
    234 
    235 GLint Texture::getBaseLevel() const
    236 {
    237     return mSamplerState.baseLevel;
    238 }
    239 
    240 GLint Texture::getMaxLevel() const
    241 {
    242     return mSamplerState.maxLevel;
    243 }
    244 
    245 GLfloat Texture::getMinLod() const
    246 {
    247     return mSamplerState.minLod;
    248 }
    249 
    250 GLfloat Texture::getMaxLod() const
    251 {
    252     return mSamplerState.maxLod;
    253 }
    254 
    255 bool Texture::isSwizzled() const
    256 {
    257     return mSamplerState.swizzleRed   != GL_RED   ||
    258            mSamplerState.swizzleGreen != GL_GREEN ||
    259            mSamplerState.swizzleBlue  != GL_BLUE  ||
    260            mSamplerState.swizzleAlpha != GL_ALPHA;
    261 }
    262 
    263 void Texture::getSamplerState(SamplerState *sampler)
    264 {
    265     *sampler = mSamplerState;
    266 
    267     // Offset the effective base level by the texture storage's top level
    268     rx::TextureStorageInterface *texture = getNativeTexture();
    269     int topLevel = texture ? texture->getTopLevel() : 0;
    270     sampler->baseLevel = topLevel + mSamplerState.baseLevel;
    271 }
    272 
    273 GLenum Texture::getUsage() const
    274 {
    275     return mUsage;
    276 }
    277 
    278 GLint Texture::getBaseLevelWidth() const
    279 {
    280     const rx::Image *baseImage = getBaseLevelImage();
    281     return (baseImage ? baseImage->getWidth() : 0);
    282 }
    283 
    284 GLint Texture::getBaseLevelHeight() const
    285 {
    286     const rx::Image *baseImage = getBaseLevelImage();
    287     return (baseImage ? baseImage->getHeight() : 0);
    288 }
    289 
    290 GLint Texture::getBaseLevelDepth() const
    291 {
    292     const rx::Image *baseImage = getBaseLevelImage();
    293     return (baseImage ? baseImage->getDepth() : 0);
    294 }
    295 
    296 // Note: "base level image" is loosely defined to be any image from the base level,
    297 // where in the base of 2D array textures and cube maps there are several. Don't use
    298 // the base level image for anything except querying texture format and size.
    299 GLenum Texture::getBaseLevelInternalFormat() const
    300 {
    301     const rx::Image *baseImage = getBaseLevelImage();
    302     return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
    303 }
    304 
    305 void Texture::setImage(const PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image)
    306 {
    307     // No-op
    308     if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
    309     {
    310         return;
    311     }
    312 
    313     // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
    314     // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
    315     const void *pixelData = pixels;
    316 
    317     if (unpack.pixelBuffer.id() != 0)
    318     {
    319         // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported
    320         Buffer *pixelBuffer = unpack.pixelBuffer.get();
    321         ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
    322         const void *bufferData = pixelBuffer->getStorage()->getData();
    323         pixelData = static_cast<const unsigned char *>(bufferData) + offset;
    324     }
    325 
    326     if (pixelData != NULL)
    327     {
    328         image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData);
    329         mDirtyImages = true;
    330     }
    331 }
    332 
    333 bool Texture::isFastUnpackable(const PixelUnpackState &unpack, GLenum sizedInternalFormat)
    334 {
    335     return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
    336 }
    337 
    338 bool Texture::fastUnpackPixels(const PixelUnpackState &unpack, const void *pixels, const Box &destArea,
    339                                GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget)
    340 {
    341     if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
    342     {
    343         return true;
    344     }
    345 
    346     // In order to perform the fast copy through the shader, we must have the right format, and be able
    347     // to create a render target.
    348     ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat));
    349 
    350     unsigned int offset = reinterpret_cast<unsigned int>(pixels);
    351 
    352     return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
    353 }
    354 
    355 void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image)
    356 {
    357     if (pixels != NULL)
    358     {
    359         image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels);
    360         mDirtyImages = true;
    361     }
    362 }
    363 
    364 bool Texture::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
    365                        GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels, rx::Image *image)
    366 {
    367     const void *pixelData = pixels;
    368 
    369     // CPU readback & copy where direct GPU copy is not supported
    370     if (unpack.pixelBuffer.id() != 0)
    371     {
    372         Buffer *pixelBuffer = unpack.pixelBuffer.get();
    373         unsigned int offset = reinterpret_cast<unsigned int>(pixels);
    374         const void *bufferData = pixelBuffer->getStorage()->getData();
    375         pixelData = static_cast<const unsigned char *>(bufferData) + offset;
    376     }
    377 
    378     if (pixelData != NULL)
    379     {
    380         image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, type, pixelData);
    381         mDirtyImages = true;
    382     }
    383 
    384     return true;
    385 }
    386 
    387 bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
    388                                  GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image)
    389 {
    390     if (pixels != NULL)
    391     {
    392         image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels);
    393         mDirtyImages = true;
    394     }
    395 
    396     return true;
    397 }
    398 
    399 rx::TextureStorageInterface *Texture::getNativeTexture()
    400 {
    401     // ensure the underlying texture is created
    402     initializeStorage(false);
    403 
    404     rx::TextureStorageInterface *storage = getBaseLevelStorage();
    405     if (storage)
    406     {
    407         updateStorage();
    408     }
    409 
    410     return storage;
    411 }
    412 
    413 bool Texture::hasDirtyImages() const
    414 {
    415     return mDirtyImages;
    416 }
    417 
    418 void Texture::resetDirty()
    419 {
    420     mDirtyImages = false;
    421 }
    422 
    423 unsigned int Texture::getTextureSerial()
    424 {
    425     rx::TextureStorageInterface *texture = getNativeTexture();
    426     return texture ? texture->getTextureSerial() : 0;
    427 }
    428 
    429 bool Texture::isImmutable() const
    430 {
    431     return mImmutable;
    432 }
    433 
    434 int Texture::immutableLevelCount()
    435 {
    436     return (mImmutable ? getNativeTexture()->getStorageInstance()->getLevelCount() : 0);
    437 }
    438 
    439 GLint Texture::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
    440 {
    441     if ((isPow2(width) && isPow2(height) && isPow2(depth)) || mRenderer->getNonPower2TextureSupport())
    442     {
    443         // Maximum number of levels
    444         return log2(std::max(std::max(width, height), depth)) + 1;
    445     }
    446     else
    447     {
    448         // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
    449         return 1;
    450     }
    451 }
    452 
    453 int Texture::mipLevels() const
    454 {
    455     return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
    456 }
    457 
    458 Texture2D::Texture2D(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_2D)
    459 {
    460     mTexStorage = NULL;
    461     mSurface = NULL;
    462 
    463     for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
    464     {
    465         mImageArray[i] = renderer->createImage();
    466     }
    467 }
    468 
    469 Texture2D::~Texture2D()
    470 {
    471     delete mTexStorage;
    472     mTexStorage = NULL;
    473 
    474     if (mSurface)
    475     {
    476         mSurface->setBoundTexture(NULL);
    477         mSurface = NULL;
    478     }
    479 
    480     for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
    481     {
    482         delete mImageArray[i];
    483     }
    484 }
    485 
    486 GLsizei Texture2D::getWidth(GLint level) const
    487 {
    488     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    489         return mImageArray[level]->getWidth();
    490     else
    491         return 0;
    492 }
    493 
    494 GLsizei Texture2D::getHeight(GLint level) const
    495 {
    496     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    497         return mImageArray[level]->getHeight();
    498     else
    499         return 0;
    500 }
    501 
    502 GLenum Texture2D::getInternalFormat(GLint level) const
    503 {
    504     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    505         return mImageArray[level]->getInternalFormat();
    506     else
    507         return GL_NONE;
    508 }
    509 
    510 GLenum Texture2D::getActualFormat(GLint level) const
    511 {
    512     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    513         return mImageArray[level]->getActualFormat();
    514     else
    515         return GL_NONE;
    516 }
    517 
    518 void Texture2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height)
    519 {
    520     releaseTexImage();
    521 
    522     // If there currently is a corresponding storage texture image, it has these parameters
    523     const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
    524     const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
    525     const GLenum storageFormat = getBaseLevelInternalFormat();
    526 
    527     mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false);
    528 
    529     if (mTexStorage)
    530     {
    531         const int storageLevels = mTexStorage->getLevelCount();
    532 
    533         if ((level >= storageLevels && storageLevels != 0) ||
    534             width != storageWidth ||
    535             height != storageHeight ||
    536             internalformat != storageFormat)   // Discard mismatched storage
    537         {
    538             for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    539             {
    540                 mImageArray[i]->markDirty();
    541             }
    542 
    543             delete mTexStorage;
    544             mTexStorage = NULL;
    545             mDirtyImages = true;
    546         }
    547     }
    548 }
    549 
    550 void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
    551 {
    552     GLuint clientVersion = mRenderer->getCurrentClientVersion();
    553     GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat, clientVersion) ? internalFormat
    554                                                                                       : GetSizedInternalFormat(format, type, clientVersion);
    555     redefineImage(level, sizedInternalFormat, width, height);
    556 
    557     bool fastUnpacked = false;
    558 
    559     // Attempt a fast gpu copy of the pixel data to the surface
    560     if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level))
    561     {
    562         // Will try to create RT storage if it does not exist
    563         rx::RenderTarget *destRenderTarget = getRenderTarget(level);
    564         Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
    565 
    566         if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget))
    567         {
    568             // Ensure we don't overwrite our newly initialized data
    569             mImageArray[level]->markClean();
    570 
    571             fastUnpacked = true;
    572         }
    573     }
    574 
    575     if (!fastUnpacked)
    576     {
    577         Texture::setImage(unpack, type, pixels, mImageArray[level]);
    578     }
    579 }
    580 
    581 void Texture2D::bindTexImage(egl::Surface *surface)
    582 {
    583     releaseTexImage();
    584 
    585     GLenum internalformat = surface->getFormat();
    586 
    587     mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true);
    588 
    589     delete mTexStorage;
    590     mTexStorage = new rx::TextureStorageInterface2D(mRenderer, surface->getSwapChain());
    591 
    592     mDirtyImages = true;
    593     mSurface = surface;
    594     mSurface->setBoundTexture(this);
    595 }
    596 
    597 void Texture2D::releaseTexImage()
    598 {
    599     if (mSurface)
    600     {
    601         mSurface->setBoundTexture(NULL);
    602         mSurface = NULL;
    603 
    604         if (mTexStorage)
    605         {
    606             delete mTexStorage;
    607             mTexStorage = NULL;
    608         }
    609 
    610         for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    611         {
    612             mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
    613         }
    614     }
    615 }
    616 
    617 void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
    618 {
    619     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
    620     redefineImage(level, format, width, height);
    621 
    622     Texture::setCompressedImage(imageSize, pixels, mImageArray[level]);
    623 }
    624 
    625 void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
    626 {
    627     if (isValidLevel(level))
    628     {
    629         rx::Image *image = mImageArray[level];
    630         if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, width, height))
    631         {
    632             image->markClean();
    633         }
    634     }
    635 }
    636 
    637 void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
    638 {
    639     bool fastUnpacked = false;
    640 
    641     if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
    642     {
    643         rx::RenderTarget *renderTarget = getRenderTarget(level);
    644         Box destArea(xoffset, yoffset, 0, width, height, 1);
    645 
    646         if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget))
    647         {
    648             // Ensure we don't overwrite our newly initialized data
    649             mImageArray[level]->markClean();
    650 
    651             fastUnpacked = true;
    652         }
    653     }
    654 
    655     if (!fastUnpacked && Texture::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[level]))
    656     {
    657         commitRect(level, xoffset, yoffset, width, height);
    658     }
    659 }
    660 
    661 void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
    662 {
    663     if (Texture::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[level]))
    664     {
    665         commitRect(level, xoffset, yoffset, width, height);
    666     }
    667 }
    668 
    669 void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
    670 {
    671     GLuint clientVersion = mRenderer->getCurrentClientVersion();
    672     GLenum sizedInternalFormat = IsSizedInternalFormat(format, clientVersion) ? format
    673                                                                               : GetSizedInternalFormat(format, GL_UNSIGNED_BYTE, clientVersion);
    674     redefineImage(level, sizedInternalFormat, width, height);
    675 
    676     if (!mImageArray[level]->isRenderableFormat())
    677     {
    678         mImageArray[level]->copy(0, 0, 0, x, y, width, height, source);
    679         mDirtyImages = true;
    680     }
    681     else
    682     {
    683         ensureRenderTarget();
    684         mImageArray[level]->markClean();
    685 
    686         if (width != 0 && height != 0 && isValidLevel(level))
    687         {
    688             gl::Rectangle sourceRect;
    689             sourceRect.x = x;
    690             sourceRect.width = width;
    691             sourceRect.y = y;
    692             sourceRect.height = height;
    693 
    694             mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level);
    695         }
    696     }
    697 }
    698 
    699 void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
    700 {
    701     // can only make our texture storage to a render target if level 0 is defined (with a width & height) and
    702     // the current level we're copying to is defined (with appropriate format, width & height)
    703     bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
    704 
    705     if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
    706     {
    707         mImageArray[level]->copy(xoffset, yoffset, 0, x, y, width, height, source);
    708         mDirtyImages = true;
    709     }
    710     else
    711     {
    712         ensureRenderTarget();
    713 
    714         if (isValidLevel(level))
    715         {
    716             updateStorageLevel(level);
    717 
    718             GLuint clientVersion = mRenderer->getCurrentClientVersion();
    719 
    720             gl::Rectangle sourceRect;
    721             sourceRect.x = x;
    722             sourceRect.width = width;
    723             sourceRect.y = y;
    724             sourceRect.height = height;
    725 
    726             mRenderer->copyImage(source, sourceRect,
    727                                  gl::GetFormat(getBaseLevelInternalFormat(), clientVersion),
    728                                  xoffset, yoffset, mTexStorage, level);
    729         }
    730     }
    731 }
    732 
    733 void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
    734 {
    735     for (int level = 0; level < levels; level++)
    736     {
    737         GLsizei levelWidth = std::max(1, width >> level);
    738         GLsizei levelHeight = std::max(1, height >> level);
    739         mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, levelWidth, levelHeight, 1, true);
    740     }
    741 
    742     for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
    743     {
    744         mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
    745     }
    746 
    747     mImmutable = true;
    748 
    749     setCompleteTexStorage(new rx::TextureStorageInterface2D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, levels));
    750 }
    751 
    752 void Texture2D::setCompleteTexStorage(rx::TextureStorageInterface2D *newCompleteTexStorage)
    753 {
    754     SafeDelete(mTexStorage);
    755     mTexStorage = newCompleteTexStorage;
    756 
    757     if (mTexStorage && mTexStorage->isManaged())
    758     {
    759         for (int level = 0; level < mTexStorage->getLevelCount(); level++)
    760         {
    761             mImageArray[level]->setManagedSurface(mTexStorage, level);
    762         }
    763     }
    764 
    765     mDirtyImages = true;
    766 }
    767 
    768 // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
    769 bool Texture2D::isSamplerComplete(const SamplerState &samplerState) const
    770 {
    771     GLsizei width = getBaseLevelWidth();
    772     GLsizei height = getBaseLevelHeight();
    773 
    774     if (width <= 0 || height <= 0)
    775     {
    776         return false;
    777     }
    778 
    779     if (!IsTextureFilteringSupported(getInternalFormat(0), mRenderer))
    780     {
    781         if (samplerState.magFilter != GL_NEAREST ||
    782             (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
    783         {
    784             return false;
    785         }
    786     }
    787 
    788     bool npotSupport = mRenderer->getNonPower2TextureSupport();
    789 
    790     if (!npotSupport)
    791     {
    792         if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !isPow2(width)) ||
    793             (samplerState.wrapT != GL_CLAMP_TO_EDGE && !isPow2(height)))
    794         {
    795             return false;
    796         }
    797     }
    798 
    799     if (IsMipmapFiltered(samplerState))
    800     {
    801         if (!npotSupport)
    802         {
    803             if (!isPow2(width) || !isPow2(height))
    804             {
    805                 return false;
    806             }
    807         }
    808 
    809         if (!isMipmapComplete())
    810         {
    811             return false;
    812         }
    813     }
    814 
    815     // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
    816     // The internalformat specified for the texture arrays is a sized internal depth or
    817     // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
    818     // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
    819     // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
    820     if (gl::GetDepthBits(getInternalFormat(0), mRenderer->getCurrentClientVersion()) > 0 &&
    821         mRenderer->getCurrentClientVersion() > 2)
    822     {
    823         if (mSamplerState.compareMode == GL_NONE)
    824         {
    825             if ((mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
    826                 mSamplerState.magFilter != GL_NEAREST)
    827             {
    828                 return false;
    829             }
    830         }
    831     }
    832 
    833     return true;
    834 }
    835 
    836 // Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
    837 bool Texture2D::isMipmapComplete() const
    838 {
    839     int levelCount = mipLevels();
    840 
    841     for (int level = 0; level < levelCount; level++)
    842     {
    843         if (!isLevelComplete(level))
    844         {
    845             return false;
    846         }
    847     }
    848 
    849     return true;
    850 }
    851 
    852 bool Texture2D::isLevelComplete(int level) const
    853 {
    854     if (isImmutable())
    855     {
    856         return true;
    857     }
    858 
    859     const rx::Image *baseImage = getBaseLevelImage();
    860 
    861     GLsizei width = baseImage->getWidth();
    862     GLsizei height = baseImage->getHeight();
    863 
    864     if (width <= 0 || height <= 0)
    865     {
    866         return false;
    867     }
    868 
    869     // The base image level is complete if the width and height are positive
    870     if (level == 0)
    871     {
    872         return true;
    873     }
    874 
    875     ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
    876     rx::Image *image = mImageArray[level];
    877 
    878     if (image->getInternalFormat() != baseImage->getInternalFormat())
    879     {
    880         return false;
    881     }
    882 
    883     if (image->getWidth() != std::max(1, width >> level))
    884     {
    885         return false;
    886     }
    887 
    888     if (image->getHeight() != std::max(1, height >> level))
    889     {
    890         return false;
    891     }
    892 
    893     return true;
    894 }
    895 
    896 bool Texture2D::isCompressed(GLint level) const
    897 {
    898     return IsFormatCompressed(getInternalFormat(level), mRenderer->getCurrentClientVersion());
    899 }
    900 
    901 bool Texture2D::isDepth(GLint level) const
    902 {
    903     return GetDepthBits(getInternalFormat(level), mRenderer->getCurrentClientVersion()) > 0;
    904 }
    905 
    906 // Constructs a native texture resource from the texture images
    907 void Texture2D::initializeStorage(bool renderTarget)
    908 {
    909     // Only initialize the first time this texture is used as a render target or shader resource
    910     if (mTexStorage)
    911     {
    912         return;
    913     }
    914 
    915     // do not attempt to create storage for nonexistant data
    916     if (!isLevelComplete(0))
    917     {
    918         return;
    919     }
    920 
    921     bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
    922 
    923     setCompleteTexStorage(createCompleteStorage(createRenderTarget));
    924     ASSERT(mTexStorage);
    925 
    926     // flush image data to the storage
    927     updateStorage();
    928 }
    929 
    930 rx::TextureStorageInterface2D *Texture2D::createCompleteStorage(bool renderTarget) const
    931 {
    932     GLsizei width = getBaseLevelWidth();
    933     GLsizei height = getBaseLevelHeight();
    934 
    935     ASSERT(width > 0 && height > 0);
    936 
    937     // use existing storage level count, when previously specified by TexStorage*D
    938     GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
    939 
    940     return new rx::TextureStorageInterface2D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, levels);
    941 }
    942 
    943 void Texture2D::updateStorage()
    944 {
    945     ASSERT(mTexStorage != NULL);
    946     GLint storageLevels = mTexStorage->getLevelCount();
    947     for (int level = 0; level < storageLevels; level++)
    948     {
    949         if (mImageArray[level]->isDirty() && isLevelComplete(level))
    950         {
    951             updateStorageLevel(level);
    952         }
    953     }
    954 }
    955 
    956 void Texture2D::updateStorageLevel(int level)
    957 {
    958     ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
    959     ASSERT(isLevelComplete(level));
    960 
    961     if (mImageArray[level]->isDirty())
    962     {
    963         commitRect(level, 0, 0, getWidth(level), getHeight(level));
    964     }
    965 }
    966 
    967 bool Texture2D::ensureRenderTarget()
    968 {
    969     initializeStorage(true);
    970 
    971     if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0)
    972     {
    973         ASSERT(mTexStorage);
    974         if (!mTexStorage->isRenderTarget())
    975         {
    976             rx::TextureStorageInterface2D *newRenderTargetStorage = createCompleteStorage(true);
    977 
    978             if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage))
    979             {
    980                 delete newRenderTargetStorage;
    981                 return gl::error(GL_OUT_OF_MEMORY, false);
    982             }
    983 
    984             setCompleteTexStorage(newRenderTargetStorage);
    985         }
    986     }
    987 
    988     return (mTexStorage && mTexStorage->isRenderTarget());
    989 }
    990 
    991 void Texture2D::generateMipmaps()
    992 {
    993     // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
    994     int levelCount = mipLevels();
    995     for (int level = 1; level < levelCount; level++)
    996     {
    997         redefineImage(level, getBaseLevelInternalFormat(),
    998                       std::max(getBaseLevelWidth() >> level, 1),
    999                       std::max(getBaseLevelHeight() >> level, 1));
   1000     }
   1001 
   1002     if (mTexStorage && mTexStorage->isRenderTarget())
   1003     {
   1004         for (int level = 1; level < levelCount; level++)
   1005         {
   1006             mTexStorage->generateMipmap(level);
   1007 
   1008             mImageArray[level]->markClean();
   1009         }
   1010     }
   1011     else
   1012     {
   1013         for (int level = 1; level < levelCount; level++)
   1014         {
   1015             mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]);
   1016         }
   1017     }
   1018 }
   1019 
   1020 const rx::Image *Texture2D::getBaseLevelImage() const
   1021 {
   1022     return mImageArray[0];
   1023 }
   1024 
   1025 rx::TextureStorageInterface *Texture2D::getBaseLevelStorage()
   1026 {
   1027     return mTexStorage;
   1028 }
   1029 
   1030 FramebufferAttachment *Texture2D::getAttachment(GLint level)
   1031 {
   1032     FramebufferAttachment *attachment = mRenderbufferProxies.get(level, 0);
   1033     if (!attachment)
   1034     {
   1035         attachment = new FramebufferAttachment(mRenderer, id(), new Texture2DAttachment(this, level));
   1036         mRenderbufferProxies.add(level, 0, attachment);
   1037     }
   1038 
   1039     return attachment;
   1040 }
   1041 
   1042 unsigned int Texture2D::getRenderTargetSerial(GLint level)
   1043 {
   1044     return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level) : 0);
   1045 }
   1046 
   1047 rx::RenderTarget *Texture2D::getRenderTarget(GLint level)
   1048 {
   1049     // ensure the underlying texture is created
   1050     if (!ensureRenderTarget())
   1051     {
   1052         return NULL;
   1053     }
   1054 
   1055     updateStorageLevel(level);
   1056 
   1057     // ensure this is NOT a depth texture
   1058     if (isDepth(level))
   1059     {
   1060         return NULL;
   1061     }
   1062 
   1063     return mTexStorage->getRenderTarget(level);
   1064 }
   1065 
   1066 rx::RenderTarget *Texture2D::getDepthSencil(GLint level)
   1067 {
   1068     // ensure the underlying texture is created
   1069     if (!ensureRenderTarget())
   1070     {
   1071         return NULL;
   1072     }
   1073 
   1074     updateStorageLevel(level);
   1075 
   1076     // ensure this is actually a depth texture
   1077     if (!isDepth(level))
   1078     {
   1079         return NULL;
   1080     }
   1081 
   1082     return mTexStorage->getRenderTarget(level);
   1083 }
   1084 
   1085 bool Texture2D::isValidLevel(int level) const
   1086 {
   1087     return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false);
   1088 }
   1089 
   1090 TextureCubeMap::TextureCubeMap(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_CUBE_MAP)
   1091 {
   1092     mTexStorage = NULL;
   1093     for (int i = 0; i < 6; i++)
   1094     {
   1095         for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
   1096         {
   1097             mImageArray[i][j] = renderer->createImage();
   1098         }
   1099     }
   1100 }
   1101 
   1102 TextureCubeMap::~TextureCubeMap()
   1103 {
   1104     for (int i = 0; i < 6; i++)
   1105     {
   1106         for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
   1107         {
   1108             delete mImageArray[i][j];
   1109         }
   1110     }
   1111 
   1112     delete mTexStorage;
   1113     mTexStorage = NULL;
   1114 }
   1115 
   1116 GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
   1117 {
   1118     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   1119         return mImageArray[targetToIndex(target)][level]->getWidth();
   1120     else
   1121         return 0;
   1122 }
   1123 
   1124 GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
   1125 {
   1126     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   1127         return mImageArray[targetToIndex(target)][level]->getHeight();
   1128     else
   1129         return 0;
   1130 }
   1131 
   1132 GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
   1133 {
   1134     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   1135         return mImageArray[targetToIndex(target)][level]->getInternalFormat();
   1136     else
   1137         return GL_NONE;
   1138 }
   1139 
   1140 GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const
   1141 {
   1142     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   1143         return mImageArray[targetToIndex(target)][level]->getActualFormat();
   1144     else
   1145         return GL_NONE;
   1146 }
   1147 
   1148 void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
   1149 {
   1150     setImage(0, level, width, height, internalFormat, format, type, unpack, pixels);
   1151 }
   1152 
   1153 void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
   1154 {
   1155     setImage(1, level, width, height, internalFormat, format, type, unpack, pixels);
   1156 }
   1157 
   1158 void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
   1159 {
   1160     setImage(2, level, width, height, internalFormat, format, type, unpack, pixels);
   1161 }
   1162 
   1163 void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
   1164 {
   1165     setImage(3, level, width, height, internalFormat, format, type, unpack, pixels);
   1166 }
   1167 
   1168 void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
   1169 {
   1170     setImage(4, level, width, height, internalFormat, format, type, unpack, pixels);
   1171 }
   1172 
   1173 void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
   1174 {
   1175     setImage(5, level, width, height, internalFormat, format, type, unpack, pixels);
   1176 }
   1177 
   1178 void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
   1179 {
   1180     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
   1181     int faceIndex = targetToIndex(target);
   1182     redefineImage(faceIndex, level, format, width, height);
   1183 
   1184     Texture::setCompressedImage(imageSize, pixels, mImageArray[faceIndex][level]);
   1185 }
   1186 
   1187 void TextureCubeMap::commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
   1188 {
   1189     if (isValidFaceLevel(faceIndex, level))
   1190     {
   1191         rx::Image *image = mImageArray[faceIndex][level];
   1192         if (image->copyToStorage(mTexStorage, faceIndex, level, xoffset, yoffset, width, height))
   1193             image->markClean();
   1194     }
   1195 }
   1196 
   1197 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)
   1198 {
   1199     int faceIndex = targetToIndex(target);
   1200     if (Texture::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[faceIndex][level]))
   1201     {
   1202         commitRect(faceIndex, level, xoffset, yoffset, width, height);
   1203     }
   1204 }
   1205 
   1206 void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
   1207 {
   1208     int faceIndex = targetToIndex(target);
   1209     if (Texture::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex][level]))
   1210     {
   1211         commitRect(faceIndex, level, xoffset, yoffset, width, height);
   1212     }
   1213 }
   1214 
   1215 // Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86.
   1216 bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState) const
   1217 {
   1218     int size = getBaseLevelWidth();
   1219 
   1220     bool mipmapping = IsMipmapFiltered(samplerState);
   1221 
   1222     if (!IsTextureFilteringSupported(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0), mRenderer))
   1223     {
   1224         if (samplerState.magFilter != GL_NEAREST ||
   1225             (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
   1226         {
   1227             return false;
   1228         }
   1229     }
   1230 
   1231     if (!isPow2(size) && !mRenderer->getNonPower2TextureSupport())
   1232     {
   1233         if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
   1234         {
   1235             return false;
   1236         }
   1237     }
   1238 
   1239     if (!mipmapping)
   1240     {
   1241         if (!isCubeComplete())
   1242         {
   1243             return false;
   1244         }
   1245     }
   1246     else
   1247     {
   1248         if (!isMipmapCubeComplete())   // Also tests for isCubeComplete()
   1249         {
   1250             return false;
   1251         }
   1252     }
   1253 
   1254     return true;
   1255 }
   1256 
   1257 // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
   1258 bool TextureCubeMap::isCubeComplete() const
   1259 {
   1260     int    baseWidth  = getBaseLevelWidth();
   1261     int    baseHeight = getBaseLevelHeight();
   1262     GLenum baseFormat = getBaseLevelInternalFormat();
   1263 
   1264     if (baseWidth <= 0 || baseWidth != baseHeight)
   1265     {
   1266         return false;
   1267     }
   1268 
   1269     for (int faceIndex = 1; faceIndex < 6; faceIndex++)
   1270     {
   1271         const rx::Image &faceBaseImage = *mImageArray[faceIndex][0];
   1272 
   1273         if (faceBaseImage.getWidth()          != baseWidth  ||
   1274             faceBaseImage.getHeight()         != baseHeight ||
   1275             faceBaseImage.getInternalFormat() != baseFormat )
   1276         {
   1277             return false;
   1278         }
   1279     }
   1280 
   1281     return true;
   1282 }
   1283 
   1284 bool TextureCubeMap::isMipmapCubeComplete() const
   1285 {
   1286     if (isImmutable())
   1287     {
   1288         return true;
   1289     }
   1290 
   1291     if (!isCubeComplete())
   1292     {
   1293         return false;
   1294     }
   1295 
   1296     int levelCount = mipLevels();
   1297 
   1298     for (int face = 0; face < 6; face++)
   1299     {
   1300         for (int level = 1; level < levelCount; level++)
   1301         {
   1302             if (!isFaceLevelComplete(face, level))
   1303             {
   1304                 return false;
   1305             }
   1306         }
   1307     }
   1308 
   1309     return true;
   1310 }
   1311 
   1312 bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const
   1313 {
   1314     ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL);
   1315 
   1316     if (isImmutable())
   1317     {
   1318         return true;
   1319     }
   1320 
   1321     int baseSize = getBaseLevelWidth();
   1322 
   1323     if (baseSize <= 0)
   1324     {
   1325         return false;
   1326     }
   1327 
   1328     // "isCubeComplete" checks for base level completeness and we must call that
   1329     // to determine if any face at level 0 is complete. We omit that check here
   1330     // to avoid re-checking cube-completeness for every face at level 0.
   1331     if (level == 0)
   1332     {
   1333         return true;
   1334     }
   1335 
   1336     // Check that non-zero levels are consistent with the base level.
   1337     const rx::Image *faceLevelImage = mImageArray[faceIndex][level];
   1338 
   1339     if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
   1340     {
   1341         return false;
   1342     }
   1343 
   1344     if (faceLevelImage->getWidth() != std::max(1, baseSize >> level))
   1345     {
   1346         return false;
   1347     }
   1348 
   1349     return true;
   1350 }
   1351 
   1352 bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
   1353 {
   1354     return IsFormatCompressed(getInternalFormat(target, level), mRenderer->getCurrentClientVersion());
   1355 }
   1356 
   1357 bool TextureCubeMap::isDepth(GLenum target, GLint level) const
   1358 {
   1359     return GetDepthBits(getInternalFormat(target, level), mRenderer->getCurrentClientVersion()) > 0;
   1360 }
   1361 
   1362 void TextureCubeMap::initializeStorage(bool renderTarget)
   1363 {
   1364     // Only initialize the first time this texture is used as a render target or shader resource
   1365     if (mTexStorage)
   1366     {
   1367         return;
   1368     }
   1369 
   1370     // do not attempt to create storage for nonexistant data
   1371     if (!isFaceLevelComplete(0, 0))
   1372     {
   1373         return;
   1374     }
   1375 
   1376     bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
   1377 
   1378     setCompleteTexStorage(createCompleteStorage(createRenderTarget));
   1379     ASSERT(mTexStorage);
   1380 
   1381     // flush image data to the storage
   1382     updateStorage();
   1383 }
   1384 
   1385 rx::TextureStorageInterfaceCube *TextureCubeMap::createCompleteStorage(bool renderTarget) const
   1386 {
   1387     GLsizei size = getBaseLevelWidth();
   1388 
   1389     ASSERT(size > 0);
   1390 
   1391     // use existing storage level count, when previously specified by TexStorage*D
   1392     GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1));
   1393 
   1394     return new rx::TextureStorageInterfaceCube(mRenderer, getBaseLevelInternalFormat(), renderTarget, size, levels);
   1395 }
   1396 
   1397 void TextureCubeMap::setCompleteTexStorage(rx::TextureStorageInterfaceCube *newCompleteTexStorage)
   1398 {
   1399     SafeDelete(mTexStorage);
   1400     mTexStorage = newCompleteTexStorage;
   1401 
   1402     if (mTexStorage && mTexStorage->isManaged())
   1403     {
   1404         for (int faceIndex = 0; faceIndex < 6; faceIndex++)
   1405         {
   1406             for (int level = 0; level < mTexStorage->getLevelCount(); level++)
   1407             {
   1408                 mImageArray[faceIndex][level]->setManagedSurface(mTexStorage, faceIndex, level);
   1409             }
   1410         }
   1411     }
   1412 
   1413     mDirtyImages = true;
   1414 }
   1415 
   1416 void TextureCubeMap::updateStorage()
   1417 {
   1418     ASSERT(mTexStorage != NULL);
   1419     GLint storageLevels = mTexStorage->getLevelCount();
   1420     for (int face = 0; face < 6; face++)
   1421     {
   1422         for (int level = 0; level < storageLevels; level++)
   1423         {
   1424             if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level))
   1425             {
   1426                 updateStorageFaceLevel(face, level);
   1427             }
   1428         }
   1429     }
   1430 }
   1431 
   1432 void TextureCubeMap::updateStorageFaceLevel(int faceIndex, int level)
   1433 {
   1434     ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL);
   1435     rx::Image *image = mImageArray[faceIndex][level];
   1436 
   1437     if (image->isDirty())
   1438     {
   1439         commitRect(faceIndex, level, 0, 0, image->getWidth(), image->getHeight());
   1440     }
   1441 }
   1442 
   1443 bool TextureCubeMap::ensureRenderTarget()
   1444 {
   1445     initializeStorage(true);
   1446 
   1447     if (getBaseLevelWidth() > 0)
   1448     {
   1449         ASSERT(mTexStorage);
   1450         if (!mTexStorage->isRenderTarget())
   1451         {
   1452             rx::TextureStorageInterfaceCube *newRenderTargetStorage = createCompleteStorage(true);
   1453 
   1454             if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage))
   1455             {
   1456                 delete newRenderTargetStorage;
   1457                 return gl::error(GL_OUT_OF_MEMORY, false);
   1458             }
   1459 
   1460             setCompleteTexStorage(newRenderTargetStorage);
   1461         }
   1462     }
   1463 
   1464     return (mTexStorage && mTexStorage->isRenderTarget());
   1465 }
   1466 
   1467 void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
   1468 {
   1469     GLuint clientVersion = mRenderer->getCurrentClientVersion();
   1470     GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat, clientVersion) ? internalFormat
   1471                                                                                       : GetSizedInternalFormat(format, type, clientVersion);
   1472 
   1473     redefineImage(faceIndex, level, sizedInternalFormat, width, height);
   1474 
   1475     Texture::setImage(unpack, type, pixels, mImageArray[faceIndex][level]);
   1476 }
   1477 
   1478 int TextureCubeMap::targetToIndex(GLenum target)
   1479 {
   1480     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
   1481     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
   1482     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
   1483     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
   1484     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
   1485 
   1486     return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
   1487 }
   1488 
   1489 void TextureCubeMap::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height)
   1490 {
   1491     // If there currently is a corresponding storage texture image, it has these parameters
   1492     const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
   1493     const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
   1494     const GLenum storageFormat = getBaseLevelInternalFormat();
   1495 
   1496     mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, width, height, 1, false);
   1497 
   1498     if (mTexStorage)
   1499     {
   1500         const int storageLevels = mTexStorage->getLevelCount();
   1501 
   1502         if ((level >= storageLevels && storageLevels != 0) ||
   1503             width != storageWidth ||
   1504             height != storageHeight ||
   1505             internalformat != storageFormat)   // Discard mismatched storage
   1506         {
   1507             for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
   1508             {
   1509                 for (int faceIndex = 0; faceIndex < 6; faceIndex++)
   1510                 {
   1511                     mImageArray[faceIndex][level]->markDirty();
   1512                 }
   1513             }
   1514 
   1515             delete mTexStorage;
   1516             mTexStorage = NULL;
   1517 
   1518             mDirtyImages = true;
   1519         }
   1520     }
   1521 }
   1522 
   1523 void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
   1524 {
   1525     int faceIndex = targetToIndex(target);
   1526     GLuint clientVersion = mRenderer->getCurrentClientVersion();
   1527     GLenum sizedInternalFormat = IsSizedInternalFormat(format, clientVersion) ? format
   1528                                                                               : GetSizedInternalFormat(format, GL_UNSIGNED_BYTE, clientVersion);
   1529     redefineImage(faceIndex, level, sizedInternalFormat, width, height);
   1530 
   1531     if (!mImageArray[faceIndex][level]->isRenderableFormat())
   1532     {
   1533         mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source);
   1534         mDirtyImages = true;
   1535     }
   1536     else
   1537     {
   1538         ensureRenderTarget();
   1539         mImageArray[faceIndex][level]->markClean();
   1540 
   1541         ASSERT(width == height);
   1542 
   1543         if (width > 0 && isValidFaceLevel(faceIndex, level))
   1544         {
   1545             gl::Rectangle sourceRect;
   1546             sourceRect.x = x;
   1547             sourceRect.width = width;
   1548             sourceRect.y = y;
   1549             sourceRect.height = height;
   1550 
   1551             mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, target, level);
   1552         }
   1553     }
   1554 }
   1555 
   1556 void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
   1557 {
   1558     int faceIndex = targetToIndex(target);
   1559 
   1560     // We can only make our texture storage to a render target if the level we're copying *to* is complete
   1561     // and the base level is cube-complete. The base level must be cube complete (common case) because we cannot
   1562     // rely on the "getBaseLevel*" methods reliably otherwise.
   1563     bool canCreateRenderTarget = isFaceLevelComplete(faceIndex, level) && isCubeComplete();
   1564 
   1565     if (!mImageArray[faceIndex][level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
   1566     {
   1567         mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source);
   1568         mDirtyImages = true;
   1569     }
   1570     else
   1571     {
   1572         ensureRenderTarget();
   1573 
   1574         if (isValidFaceLevel(faceIndex, level))
   1575         {
   1576             updateStorageFaceLevel(faceIndex, level);
   1577 
   1578             GLuint clientVersion = mRenderer->getCurrentClientVersion();
   1579 
   1580             gl::Rectangle sourceRect;
   1581             sourceRect.x = x;
   1582             sourceRect.width = width;
   1583             sourceRect.y = y;
   1584             sourceRect.height = height;
   1585 
   1586             mRenderer->copyImage(source, sourceRect, gl::GetFormat(getBaseLevelInternalFormat(), clientVersion),
   1587                                  xoffset, yoffset, mTexStorage, target, level);
   1588         }
   1589     }
   1590 }
   1591 
   1592 void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
   1593 {
   1594     for (int level = 0; level < levels; level++)
   1595     {
   1596         GLsizei mipSize = std::max(1, size >> level);
   1597         for (int faceIndex = 0; faceIndex < 6; faceIndex++)
   1598         {
   1599             mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, mipSize, mipSize, 1, true);
   1600         }
   1601     }
   1602 
   1603     for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
   1604     {
   1605         for (int faceIndex = 0; faceIndex < 6; faceIndex++)
   1606         {
   1607             mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, GL_NONE, 0, 0, 0, true);
   1608         }
   1609     }
   1610 
   1611     mImmutable = true;
   1612 
   1613     setCompleteTexStorage(new rx::TextureStorageInterfaceCube(mRenderer, internalformat, IsRenderTargetUsage(mUsage), size, levels));
   1614 }
   1615 
   1616 void TextureCubeMap::generateMipmaps()
   1617 {
   1618     // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
   1619     int levelCount = mipLevels();
   1620     for (int faceIndex = 0; faceIndex < 6; faceIndex++)
   1621     {
   1622         for (int level = 1; level < levelCount; level++)
   1623         {
   1624             int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1));
   1625             redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), faceLevelSize, faceLevelSize);
   1626         }
   1627     }
   1628 
   1629     if (mTexStorage && mTexStorage->isRenderTarget())
   1630     {
   1631         for (int faceIndex = 0; faceIndex < 6; faceIndex++)
   1632         {
   1633             for (int level = 1; level < levelCount; level++)
   1634             {
   1635                 mTexStorage->generateMipmap(faceIndex, level);
   1636 
   1637                 mImageArray[faceIndex][level]->markClean();
   1638             }
   1639         }
   1640     }
   1641     else
   1642     {
   1643         for (int faceIndex = 0; faceIndex < 6; faceIndex++)
   1644         {
   1645             for (int level = 1; level < levelCount; level++)
   1646             {
   1647                 mRenderer->generateMipmap(mImageArray[faceIndex][level], mImageArray[faceIndex][level - 1]);
   1648             }
   1649         }
   1650     }
   1651 }
   1652 
   1653 const rx::Image *TextureCubeMap::getBaseLevelImage() const
   1654 {
   1655     // Note: if we are not cube-complete, there is no single base level image that can describe all
   1656     // cube faces, so this method is only well-defined for a cube-complete base level.
   1657     return mImageArray[0][0];
   1658 }
   1659 
   1660 rx::TextureStorageInterface *TextureCubeMap::getBaseLevelStorage()
   1661 {
   1662     return mTexStorage;
   1663 }
   1664 
   1665 FramebufferAttachment *TextureCubeMap::getAttachment(GLenum target, GLint level)
   1666 {
   1667     ASSERT(!IsCubemapTextureTarget(target));
   1668     int faceIndex = targetToIndex(target);
   1669 
   1670     FramebufferAttachment *attachment = mRenderbufferProxies.get(level, faceIndex);
   1671     if (!attachment)
   1672     {
   1673         attachment = new FramebufferAttachment(mRenderer, id(), new TextureCubeMapAttachment(this, target, level));
   1674         mRenderbufferProxies.add(level, faceIndex, attachment);
   1675     }
   1676 
   1677     return attachment;
   1678 }
   1679 
   1680 unsigned int TextureCubeMap::getRenderTargetSerial(GLenum target, GLint level)
   1681 {
   1682     return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(target, level) : 0);
   1683 }
   1684 
   1685 rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target, GLint level)
   1686 {
   1687     ASSERT(IsCubemapTextureTarget(target));
   1688 
   1689     // ensure the underlying texture is created
   1690     if (!ensureRenderTarget())
   1691     {
   1692         return NULL;
   1693     }
   1694 
   1695     updateStorageFaceLevel(targetToIndex(target), level);
   1696 
   1697     // ensure this is NOT a depth texture
   1698     if (isDepth(target, level))
   1699     {
   1700         return NULL;
   1701     }
   1702 
   1703     return mTexStorage->getRenderTarget(target, level);
   1704 }
   1705 
   1706 rx::RenderTarget *TextureCubeMap::getDepthStencil(GLenum target, GLint level)
   1707 {
   1708     ASSERT(IsCubemapTextureTarget(target));
   1709 
   1710     // ensure the underlying texture is created
   1711     if (!ensureRenderTarget())
   1712     {
   1713         return NULL;
   1714     }
   1715 
   1716     updateStorageFaceLevel(targetToIndex(target), level);
   1717 
   1718     // ensure this is a depth texture
   1719     if (!isDepth(target, level))
   1720     {
   1721         return NULL;
   1722     }
   1723 
   1724     return mTexStorage->getRenderTarget(target, level);
   1725 }
   1726 
   1727 bool TextureCubeMap::isValidFaceLevel(int faceIndex, int level) const
   1728 {
   1729     return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
   1730 }
   1731 
   1732 Texture3D::Texture3D(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_3D)
   1733 {
   1734     mTexStorage = NULL;
   1735 
   1736     for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
   1737     {
   1738         mImageArray[i] = renderer->createImage();
   1739     }
   1740 }
   1741 
   1742 Texture3D::~Texture3D()
   1743 {
   1744     delete mTexStorage;
   1745     mTexStorage = NULL;
   1746 
   1747     for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
   1748     {
   1749         delete mImageArray[i];
   1750     }
   1751 }
   1752 
   1753 GLsizei Texture3D::getWidth(GLint level) const
   1754 {
   1755     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getWidth() : 0;
   1756 }
   1757 
   1758 GLsizei Texture3D::getHeight(GLint level) const
   1759 {
   1760     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getHeight() : 0;
   1761 }
   1762 
   1763 GLsizei Texture3D::getDepth(GLint level) const
   1764 {
   1765     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getDepth() : 0;
   1766 }
   1767 
   1768 GLenum Texture3D::getInternalFormat(GLint level) const
   1769 {
   1770     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getInternalFormat() : GL_NONE;
   1771 }
   1772 
   1773 GLenum Texture3D::getActualFormat(GLint level) const
   1774 {
   1775     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getActualFormat() : GL_NONE;
   1776 }
   1777 
   1778 bool Texture3D::isCompressed(GLint level) const
   1779 {
   1780     return IsFormatCompressed(getInternalFormat(level), mRenderer->getCurrentClientVersion());
   1781 }
   1782 
   1783 bool Texture3D::isDepth(GLint level) const
   1784 {
   1785     return GetDepthBits(getInternalFormat(level), mRenderer->getCurrentClientVersion()) > 0;
   1786 }
   1787 
   1788 void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
   1789 {
   1790     GLuint clientVersion = mRenderer->getCurrentClientVersion();
   1791     GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat, clientVersion) ? internalFormat
   1792                                                                                       : GetSizedInternalFormat(format, type, clientVersion);
   1793     redefineImage(level, sizedInternalFormat, width, height, depth);
   1794 
   1795     bool fastUnpacked = false;
   1796 
   1797     // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
   1798     if (isFastUnpackable(unpack, sizedInternalFormat))
   1799     {
   1800         // Will try to create RT storage if it does not exist
   1801         rx::RenderTarget *destRenderTarget = getRenderTarget(level);
   1802         Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
   1803 
   1804         if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget))
   1805         {
   1806             // Ensure we don't overwrite our newly initialized data
   1807             mImageArray[level]->markClean();
   1808 
   1809             fastUnpacked = true;
   1810         }
   1811     }
   1812 
   1813     if (!fastUnpacked)
   1814     {
   1815         Texture::setImage(unpack, type, pixels, mImageArray[level]);
   1816     }
   1817 }
   1818 
   1819 void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
   1820 {
   1821     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
   1822     redefineImage(level, format, width, height, depth);
   1823 
   1824     Texture::setCompressedImage(imageSize, pixels, mImageArray[level]);
   1825 }
   1826 
   1827 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)
   1828 {
   1829     bool fastUnpacked = false;
   1830 
   1831     // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
   1832     if (isFastUnpackable(unpack, getInternalFormat(level)))
   1833     {
   1834         rx::RenderTarget *destRenderTarget = getRenderTarget(level);
   1835         Box destArea(xoffset, yoffset, zoffset, width, height, depth);
   1836 
   1837         if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget))
   1838         {
   1839             // Ensure we don't overwrite our newly initialized data
   1840             mImageArray[level]->markClean();
   1841 
   1842             fastUnpacked = true;
   1843         }
   1844     }
   1845 
   1846     if (!fastUnpacked && Texture::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, mImageArray[level]))
   1847     {
   1848         commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
   1849     }
   1850 }
   1851 
   1852 void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
   1853 {
   1854     if (Texture::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level]))
   1855     {
   1856         commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
   1857     }
   1858 }
   1859 
   1860 void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
   1861 {
   1862     for (int level = 0; level < levels; level++)
   1863     {
   1864         GLsizei levelWidth = std::max(1, width >> level);
   1865         GLsizei levelHeight = std::max(1, height >> level);
   1866         GLsizei levelDepth = std::max(1, depth >> level);
   1867         mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, levelWidth, levelHeight, levelDepth, true);
   1868     }
   1869 
   1870     for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
   1871     {
   1872         mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true);
   1873     }
   1874 
   1875     mImmutable = true;
   1876 
   1877     setCompleteTexStorage(new rx::TextureStorageInterface3D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels));
   1878 }
   1879 
   1880 void Texture3D::generateMipmaps()
   1881 {
   1882     // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
   1883     int levelCount = mipLevels();
   1884     for (int level = 1; level < levelCount; level++)
   1885     {
   1886         redefineImage(level, getBaseLevelInternalFormat(),
   1887                       std::max(getBaseLevelWidth() >> level, 1),
   1888                       std::max(getBaseLevelHeight() >> level, 1),
   1889                       std::max(getBaseLevelDepth() >> level, 1));
   1890     }
   1891 
   1892     if (mTexStorage && mTexStorage->isRenderTarget())
   1893     {
   1894         for (int level = 1; level < levelCount; level++)
   1895         {
   1896             mTexStorage->generateMipmap(level);
   1897 
   1898             mImageArray[level]->markClean();
   1899         }
   1900     }
   1901     else
   1902     {
   1903         for (int level = 1; level < levelCount; level++)
   1904         {
   1905             mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]);
   1906         }
   1907     }
   1908 }
   1909 
   1910 const rx::Image *Texture3D::getBaseLevelImage() const
   1911 {
   1912     return mImageArray[0];
   1913 }
   1914 
   1915 rx::TextureStorageInterface *Texture3D::getBaseLevelStorage()
   1916 {
   1917     return mTexStorage;
   1918 }
   1919 
   1920 void Texture3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
   1921 {
   1922     // can only make our texture storage to a render target if level 0 is defined (with a width & height) and
   1923     // the current level we're copying to is defined (with appropriate format, width & height)
   1924     bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
   1925 
   1926     if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
   1927     {
   1928         mImageArray[level]->copy(xoffset, yoffset, zoffset, x, y, width, height, source);
   1929         mDirtyImages = true;
   1930     }
   1931     else
   1932     {
   1933         ensureRenderTarget();
   1934 
   1935         if (isValidLevel(level))
   1936         {
   1937             updateStorageLevel(level);
   1938 
   1939             gl::Rectangle sourceRect;
   1940             sourceRect.x = x;
   1941             sourceRect.width = width;
   1942             sourceRect.y = y;
   1943             sourceRect.height = height;
   1944 
   1945             GLuint clientVersion = mRenderer->getCurrentClientVersion();
   1946 
   1947             mRenderer->copyImage(source, sourceRect,
   1948                                  gl::GetFormat(getBaseLevelInternalFormat(), clientVersion),
   1949                                  xoffset, yoffset, zoffset, mTexStorage, level);
   1950         }
   1951     }
   1952 }
   1953 
   1954 bool Texture3D::isSamplerComplete(const SamplerState &samplerState) const
   1955 {
   1956     GLsizei width = getBaseLevelWidth();
   1957     GLsizei height = getBaseLevelHeight();
   1958     GLsizei depth = getBaseLevelDepth();
   1959 
   1960     if (width <= 0 || height <= 0 || depth <= 0)
   1961     {
   1962         return false;
   1963     }
   1964 
   1965     if (!IsTextureFilteringSupported(getInternalFormat(0), mRenderer))
   1966     {
   1967         if (samplerState.magFilter != GL_NEAREST ||
   1968             (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
   1969         {
   1970             return false;
   1971         }
   1972     }
   1973 
   1974     if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
   1975     {
   1976         return false;
   1977     }
   1978 
   1979     return true;
   1980 }
   1981 
   1982 bool Texture3D::isMipmapComplete() const
   1983 {
   1984     int levelCount = mipLevels();
   1985 
   1986     for (int level = 0; level < levelCount; level++)
   1987     {
   1988         if (!isLevelComplete(level))
   1989         {
   1990             return false;
   1991         }
   1992     }
   1993 
   1994     return true;
   1995 }
   1996 
   1997 bool Texture3D::isLevelComplete(int level) const
   1998 {
   1999     ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
   2000 
   2001     if (isImmutable())
   2002     {
   2003         return true;
   2004     }
   2005 
   2006     GLsizei width = getBaseLevelWidth();
   2007     GLsizei height = getBaseLevelHeight();
   2008     GLsizei depth = getBaseLevelDepth();
   2009 
   2010     if (width <= 0 || height <= 0 || depth <= 0)
   2011     {
   2012         return false;
   2013     }
   2014 
   2015     if (level == 0)
   2016     {
   2017         return true;
   2018     }
   2019 
   2020     rx::Image *levelImage = mImageArray[level];
   2021 
   2022     if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
   2023     {
   2024         return false;
   2025     }
   2026 
   2027     if (levelImage->getWidth() != std::max(1, width >> level))
   2028     {
   2029         return false;
   2030     }
   2031 
   2032     if (levelImage->getHeight() != std::max(1, height >> level))
   2033     {
   2034         return false;
   2035     }
   2036 
   2037     if (levelImage->getDepth() != std::max(1, depth >> level))
   2038     {
   2039         return false;
   2040     }
   2041 
   2042     return true;
   2043 }
   2044 
   2045 FramebufferAttachment *Texture3D::getAttachment(GLint level, GLint layer)
   2046 {
   2047     FramebufferAttachment *attachment = mRenderbufferProxies.get(level, layer);
   2048     if (!attachment)
   2049     {
   2050         attachment = new FramebufferAttachment(mRenderer, id(), new Texture3DAttachment(this, level, layer));
   2051         mRenderbufferProxies.add(level, 0, attachment);
   2052     }
   2053 
   2054     return attachment;
   2055 }
   2056 
   2057 unsigned int Texture3D::getRenderTargetSerial(GLint level, GLint layer)
   2058 {
   2059     return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0);
   2060 }
   2061 
   2062 bool Texture3D::isValidLevel(int level) const
   2063 {
   2064     return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
   2065 }
   2066 
   2067 void Texture3D::initializeStorage(bool renderTarget)
   2068 {
   2069     // Only initialize the first time this texture is used as a render target or shader resource
   2070     if (mTexStorage)
   2071     {
   2072         return;
   2073     }
   2074 
   2075     // do not attempt to create storage for nonexistant data
   2076     if (!isLevelComplete(0))
   2077     {
   2078         return;
   2079     }
   2080 
   2081     bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
   2082 
   2083     setCompleteTexStorage(createCompleteStorage(createRenderTarget));
   2084     ASSERT(mTexStorage);
   2085 
   2086     // flush image data to the storage
   2087     updateStorage();
   2088 }
   2089 
   2090 rx::TextureStorageInterface3D *Texture3D::createCompleteStorage(bool renderTarget) const
   2091 {
   2092     GLsizei width = getBaseLevelWidth();
   2093     GLsizei height = getBaseLevelHeight();
   2094     GLsizei depth = getBaseLevelDepth();
   2095 
   2096     ASSERT(width > 0 && height > 0 && depth > 0);
   2097 
   2098     // use existing storage level count, when previously specified by TexStorage*D
   2099     GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth));
   2100 
   2101     return new rx::TextureStorageInterface3D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels);
   2102 }
   2103 
   2104 void Texture3D::setCompleteTexStorage(rx::TextureStorageInterface3D *newCompleteTexStorage)
   2105 {
   2106     SafeDelete(mTexStorage);
   2107     mTexStorage = newCompleteTexStorage;
   2108     mDirtyImages = true;
   2109 
   2110     // We do not support managed 3D storage, as that is D3D9/ES2-only
   2111     ASSERT(!mTexStorage->isManaged());
   2112 }
   2113 
   2114 void Texture3D::updateStorage()
   2115 {
   2116     ASSERT(mTexStorage != NULL);
   2117     GLint storageLevels = mTexStorage->getLevelCount();
   2118     for (int level = 0; level < storageLevels; level++)
   2119     {
   2120         if (mImageArray[level]->isDirty() && isLevelComplete(level))
   2121         {
   2122             updateStorageLevel(level);
   2123         }
   2124     }
   2125 }
   2126 
   2127 void Texture3D::updateStorageLevel(int level)
   2128 {
   2129     ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
   2130     ASSERT(isLevelComplete(level));
   2131 
   2132     if (mImageArray[level]->isDirty())
   2133     {
   2134         commitRect(level, 0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
   2135     }
   2136 }
   2137 
   2138 bool Texture3D::ensureRenderTarget()
   2139 {
   2140     initializeStorage(true);
   2141 
   2142     if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getBaseLevelDepth() > 0)
   2143     {
   2144         ASSERT(mTexStorage);
   2145         if (!mTexStorage->isRenderTarget())
   2146         {
   2147             rx::TextureStorageInterface3D *newRenderTargetStorage = createCompleteStorage(true);
   2148 
   2149             if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage))
   2150             {
   2151                 delete newRenderTargetStorage;
   2152                 return gl::error(GL_OUT_OF_MEMORY, false);
   2153             }
   2154 
   2155             setCompleteTexStorage(newRenderTargetStorage);
   2156         }
   2157     }
   2158 
   2159     return (mTexStorage && mTexStorage->isRenderTarget());
   2160 }
   2161 
   2162 rx::RenderTarget *Texture3D::getRenderTarget(GLint level)
   2163 {
   2164     // ensure the underlying texture is created
   2165     if (!ensureRenderTarget())
   2166     {
   2167         return NULL;
   2168     }
   2169 
   2170     updateStorageLevel(level);
   2171 
   2172     // ensure this is NOT a depth texture
   2173     if (isDepth(level))
   2174     {
   2175         return NULL;
   2176     }
   2177 
   2178     return mTexStorage->getRenderTarget(level);
   2179 }
   2180 
   2181 rx::RenderTarget *Texture3D::getRenderTarget(GLint level, GLint layer)
   2182 {
   2183     // ensure the underlying texture is created
   2184     if (!ensureRenderTarget())
   2185     {
   2186         return NULL;
   2187     }
   2188 
   2189     updateStorage();
   2190 
   2191     // ensure this is NOT a depth texture
   2192     if (isDepth(level))
   2193     {
   2194         return NULL;
   2195     }
   2196 
   2197     return mTexStorage->getRenderTarget(level, layer);
   2198 }
   2199 
   2200 rx::RenderTarget *Texture3D::getDepthStencil(GLint level, GLint layer)
   2201 {
   2202     // ensure the underlying texture is created
   2203     if (!ensureRenderTarget())
   2204     {
   2205         return NULL;
   2206     }
   2207 
   2208     updateStorageLevel(level);
   2209 
   2210     // ensure this is a depth texture
   2211     if (!isDepth(level))
   2212     {
   2213         return NULL;
   2214     }
   2215 
   2216     return mTexStorage->getRenderTarget(level, layer);
   2217 }
   2218 
   2219 void Texture3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
   2220 {
   2221     // If there currently is a corresponding storage texture image, it has these parameters
   2222     const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
   2223     const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
   2224     const int storageDepth = std::max(1, getBaseLevelDepth() >> level);
   2225     const GLenum storageFormat = getBaseLevelInternalFormat();
   2226 
   2227     mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false);
   2228 
   2229     if (mTexStorage)
   2230     {
   2231         const int storageLevels = mTexStorage->getLevelCount();
   2232 
   2233         if ((level >= storageLevels && storageLevels != 0) ||
   2234             width != storageWidth ||
   2235             height != storageHeight ||
   2236             depth != storageDepth ||
   2237             internalformat != storageFormat)   // Discard mismatched storage
   2238         {
   2239             for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
   2240             {
   2241                 mImageArray[i]->markDirty();
   2242             }
   2243 
   2244             delete mTexStorage;
   2245             mTexStorage = NULL;
   2246             mDirtyImages = true;
   2247         }
   2248     }
   2249 }
   2250 
   2251 void Texture3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
   2252 {
   2253     if (isValidLevel(level))
   2254     {
   2255         rx::Image *image = mImageArray[level];
   2256         if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth))
   2257         {
   2258             image->markClean();
   2259         }
   2260     }
   2261 }
   2262 
   2263 Texture2DArray::Texture2DArray(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_2D_ARRAY)
   2264 {
   2265     mTexStorage = NULL;
   2266 
   2267     for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
   2268     {
   2269         mLayerCounts[level] = 0;
   2270         mImageArray[level] = NULL;
   2271     }
   2272 }
   2273 
   2274 Texture2DArray::~Texture2DArray()
   2275 {
   2276     delete mTexStorage;
   2277     mTexStorage = NULL;
   2278 
   2279     deleteImages();
   2280 }
   2281 
   2282 void Texture2DArray::deleteImages()
   2283 {
   2284     for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
   2285     {
   2286         for (int layer = 0; layer < mLayerCounts[level]; ++layer)
   2287         {
   2288             delete mImageArray[level][layer];
   2289         }
   2290         delete[] mImageArray[level];
   2291         mImageArray[level] = NULL;
   2292         mLayerCounts[level] = 0;
   2293     }
   2294 }
   2295 
   2296 GLsizei Texture2DArray::getWidth(GLint level) const
   2297 {
   2298     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getWidth() : 0;
   2299 }
   2300 
   2301 GLsizei Texture2DArray::getHeight(GLint level) const
   2302 {
   2303     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0;
   2304 }
   2305 
   2306 GLsizei Texture2DArray::getLayers(GLint level) const
   2307 {
   2308     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mLayerCounts[level] : 0;
   2309 }
   2310 
   2311 GLenum Texture2DArray::getInternalFormat(GLint level) const
   2312 {
   2313     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE;
   2314 }
   2315 
   2316 GLenum Texture2DArray::getActualFormat(GLint level) const
   2317 {
   2318     return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getActualFormat() : GL_NONE;
   2319 }
   2320 
   2321 bool Texture2DArray::isCompressed(GLint level) const
   2322 {
   2323     return IsFormatCompressed(getInternalFormat(level), mRenderer->getCurrentClientVersion());
   2324 }
   2325 
   2326 bool Texture2DArray::isDepth(GLint level) const
   2327 {
   2328     return GetDepthBits(getInternalFormat(level), mRenderer->getCurrentClientVersion()) > 0;
   2329 }
   2330 
   2331 void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
   2332 {
   2333     GLuint clientVersion = mRenderer->getCurrentClientVersion();
   2334     GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat, clientVersion) ? internalFormat
   2335                                                                                       : GetSizedInternalFormat(format, type, clientVersion);
   2336     redefineImage(level, sizedInternalFormat, width, height, depth);
   2337 
   2338     GLsizei inputDepthPitch = gl::GetDepthPitch(sizedInternalFormat, type, clientVersion, width, height, unpack.alignment);
   2339 
   2340     for (int i = 0; i < depth; i++)
   2341     {
   2342         const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
   2343         Texture::setImage(unpack, type, layerPixels, mImageArray[level][i]);
   2344     }
   2345 }
   2346 
   2347 void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
   2348 {
   2349     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
   2350     redefineImage(level, format, width, height, depth);
   2351 
   2352     GLuint clientVersion = mRenderer->getCurrentClientVersion();
   2353     GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, clientVersion, width, height, 1);
   2354 
   2355     for (int i = 0; i < depth; i++)
   2356     {
   2357         const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
   2358         Texture::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]);
   2359     }
   2360 }
   2361 
   2362 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)
   2363 {
   2364     GLenum internalformat = getInternalFormat(level);
   2365     GLuint clientVersion =  mRenderer->getCurrentClientVersion();
   2366     GLsizei inputDepthPitch = gl::GetDepthPitch(internalformat, type, clientVersion, width, height, unpack.alignment);
   2367 
   2368     for (int i = 0; i < depth; i++)
   2369     {
   2370         int layer = zoffset + i;
   2371         const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
   2372 
   2373         if (Texture::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, mImageArray[level][layer]))
   2374         {
   2375             commitRect(level, xoffset, yoffset, layer, width, height);
   2376         }
   2377     }
   2378 }
   2379 
   2380 void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
   2381 {
   2382     GLuint clientVersion = mRenderer->getCurrentClientVersion();
   2383     GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, clientVersion, width, height, 1);
   2384 
   2385     for (int i = 0; i < depth; i++)
   2386     {
   2387         int layer = zoffset + i;
   2388         const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
   2389 
   2390         if (Texture::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer]))
   2391         {
   2392             commitRect(level, xoffset, yoffset, layer, width, height);
   2393         }
   2394     }
   2395 }
   2396 
   2397 void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
   2398 {
   2399     deleteImages();
   2400 
   2401     for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
   2402     {
   2403         GLsizei levelWidth = std::max(1, width >> level);
   2404         GLsizei levelHeight = std::max(1, height >> level);
   2405 
   2406         mLayerCounts[level] = (level < levels ? depth : 0);
   2407 
   2408         if (mLayerCounts[level] > 0)
   2409         {
   2410             // Create new images for this level
   2411             mImageArray[level] = new rx::Image*[mLayerCounts[level]];
   2412 
   2413             for (int layer = 0; layer < mLayerCounts[level]; layer++)
   2414             {
   2415                 mImageArray[level][layer] = mRenderer->createImage();
   2416                 mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, levelWidth,
   2417                                                     levelHeight, 1, true);
   2418             }
   2419         }
   2420     }
   2421 
   2422     mImmutable = true;
   2423     setCompleteTexStorage(new rx::TextureStorageInterface2DArray(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels));
   2424 }
   2425 
   2426 void Texture2DArray::generateMipmaps()
   2427 {
   2428     int baseWidth = getBaseLevelWidth();
   2429     int baseHeight = getBaseLevelHeight();
   2430     int baseDepth = getBaseLevelDepth();
   2431     GLenum baseFormat = getBaseLevelInternalFormat();
   2432 
   2433     // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
   2434     int levelCount = mipLevels();
   2435     for (int level = 1; level < levelCount; level++)
   2436     {
   2437         redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth);
   2438     }
   2439 
   2440     if (mTexStorage && mTexStorage->isRenderTarget())
   2441     {
   2442         for (int level = 1; level < levelCount; level++)
   2443         {
   2444             mTexStorage->generateMipmap(level);
   2445 
   2446             for (int layer = 0; layer < mLayerCounts[level]; layer++)
   2447             {
   2448                 mImageArray[level][layer]->markClean();
   2449             }
   2450         }
   2451     }
   2452     else
   2453     {
   2454         for (int level = 1; level < levelCount; level++)
   2455         {
   2456             for (int layer = 0; layer < mLayerCounts[level]; layer++)
   2457             {
   2458                 mRenderer->generateMipmap(mImageArray[level][layer], mImageArray[level - 1][layer]);
   2459             }
   2460         }
   2461     }
   2462 }
   2463 
   2464 const rx::Image *Texture2DArray::getBaseLevelImage() const
   2465 {
   2466     return (mLayerCounts[0] > 0 ? mImageArray[0][0] : NULL);
   2467 }
   2468 
   2469 rx::TextureStorageInterface *Texture2DArray::getBaseLevelStorage()
   2470 {
   2471     return mTexStorage;
   2472 }
   2473 
   2474 void Texture2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
   2475 {
   2476     // can only make our texture storage to a render target if level 0 is defined (with a width & height) and
   2477     // the current level we're copying to is defined (with appropriate format, width & height)
   2478     bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
   2479 
   2480     if (!mImageArray[level][0]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
   2481     {
   2482         mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, x, y, width, height, source);
   2483         mDirtyImages = true;
   2484     }
   2485     else
   2486     {
   2487         ensureRenderTarget();
   2488 
   2489         if (isValidLevel(level))
   2490         {
   2491             updateStorageLevel(level);
   2492 
   2493             GLuint clientVersion = mRenderer->getCurrentClientVersion();
   2494 
   2495             gl::Rectangle sourceRect;
   2496             sourceRect.x = x;
   2497             sourceRect.width = width;
   2498             sourceRect.y = y;
   2499             sourceRect.height = height;
   2500 
   2501             mRenderer->copyImage(source, sourceRect, gl::GetFormat(getInternalFormat(0), clientVersion),
   2502                                  xoffset, yoffset, zoffset, mTexStorage, level);
   2503         }
   2504     }
   2505 }
   2506 
   2507 bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState) const
   2508 {
   2509     GLsizei width = getBaseLevelWidth();
   2510     GLsizei height = getBaseLevelHeight();
   2511     GLsizei depth = getLayers(0);
   2512 
   2513     if (width <= 0 || height <= 0 || depth <= 0)
   2514     {
   2515         return false;
   2516     }
   2517 
   2518     if (!IsTextureFilteringSupported(getBaseLevelInternalFormat(), mRenderer))
   2519     {
   2520         if (samplerState.magFilter != GL_NEAREST ||
   2521             (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
   2522         {
   2523             return false;
   2524         }
   2525     }
   2526 
   2527     if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
   2528     {
   2529         return false;
   2530     }
   2531 
   2532     return true;
   2533 }
   2534 
   2535 bool Texture2DArray::isMipmapComplete() const
   2536 {
   2537     int levelCount = mipLevels();
   2538 
   2539     for (int level = 1; level < levelCount; level++)
   2540     {
   2541         if (!isLevelComplete(level))
   2542         {
   2543             return false;
   2544         }
   2545     }
   2546 
   2547     return true;
   2548 }
   2549 
   2550 bool Texture2DArray::isLevelComplete(int level) const
   2551 {
   2552     ASSERT(level >= 0 && level < (int)ArraySize(mImageArray));
   2553 
   2554     if (isImmutable())
   2555     {
   2556         return true;
   2557     }
   2558 
   2559     GLsizei width = getBaseLevelWidth();
   2560     GLsizei height = getBaseLevelHeight();
   2561     GLsizei layers = getLayers(0);
   2562 
   2563     if (width <= 0 || height <= 0 || layers <= 0)
   2564     {
   2565         return false;
   2566     }
   2567 
   2568     if (level == 0)
   2569     {
   2570         return true;
   2571     }
   2572 
   2573     if (getInternalFormat(level) != getInternalFormat(0))
   2574     {
   2575         return false;
   2576     }
   2577 
   2578     if (getWidth(level) != std::max(1, width >> level))
   2579     {
   2580         return false;
   2581     }
   2582 
   2583     if (getHeight(level) != std::max(1, height >> level))
   2584     {
   2585         return false;
   2586     }
   2587 
   2588     if (getLayers(level) != layers)
   2589     {
   2590         return false;
   2591     }
   2592 
   2593     return true;
   2594 }
   2595 
   2596 FramebufferAttachment *Texture2DArray::getAttachment(GLint level, GLint layer)
   2597 {
   2598     FramebufferAttachment *attachment = mRenderbufferProxies.get(level, layer);
   2599     if (!attachment)
   2600     {
   2601         attachment = new FramebufferAttachment(mRenderer, id(), new Texture2DArrayAttachment(this, level, layer));
   2602         mRenderbufferProxies.add(level, 0, attachment);
   2603     }
   2604 
   2605     return attachment;
   2606 }
   2607 
   2608 unsigned int Texture2DArray::getRenderTargetSerial(GLint level, GLint layer)
   2609 {
   2610     return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0);
   2611 }
   2612 
   2613 bool Texture2DArray::isValidLevel(int level) const
   2614 {
   2615     return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
   2616 }
   2617 
   2618 void Texture2DArray::initializeStorage(bool renderTarget)
   2619 {
   2620     // Only initialize the first time this texture is used as a render target or shader resource
   2621     if (mTexStorage)
   2622     {
   2623         return;
   2624     }
   2625 
   2626     // do not attempt to create storage for nonexistant data
   2627     if (!isLevelComplete(0))
   2628     {
   2629         return;
   2630     }
   2631 
   2632     bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
   2633 
   2634     setCompleteTexStorage(createCompleteStorage(createRenderTarget));
   2635     ASSERT(mTexStorage);
   2636 
   2637     // flush image data to the storage
   2638     updateStorage();
   2639 }
   2640 
   2641 rx::TextureStorageInterface2DArray *Texture2DArray::createCompleteStorage(bool renderTarget) const
   2642 {
   2643     GLsizei width = getBaseLevelWidth();
   2644     GLsizei height = getBaseLevelHeight();
   2645     GLsizei depth = getLayers(0);
   2646 
   2647     ASSERT(width > 0 && height > 0 && depth > 0);
   2648 
   2649     // use existing storage level count, when previously specified by TexStorage*D
   2650     GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
   2651 
   2652     return new rx::TextureStorageInterface2DArray(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels);
   2653 }
   2654 
   2655 void Texture2DArray::setCompleteTexStorage(rx::TextureStorageInterface2DArray *newCompleteTexStorage)
   2656 {
   2657     SafeDelete(mTexStorage);
   2658     mTexStorage = newCompleteTexStorage;
   2659     mDirtyImages = true;
   2660 
   2661     // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only
   2662     ASSERT(!mTexStorage->isManaged());
   2663 }
   2664 
   2665 void Texture2DArray::updateStorage()
   2666 {
   2667     ASSERT(mTexStorage != NULL);
   2668     GLint storageLevels = mTexStorage->getLevelCount();
   2669     for (int level = 0; level < storageLevels; level++)
   2670     {
   2671         if (isLevelComplete(level))
   2672         {
   2673             updateStorageLevel(level);
   2674         }
   2675     }
   2676 }
   2677 
   2678 void Texture2DArray::updateStorageLevel(int level)
   2679 {
   2680     ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts));
   2681     ASSERT(isLevelComplete(level));
   2682 
   2683     for (int layer = 0; layer < mLayerCounts[level]; layer++)
   2684     {
   2685         ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL);
   2686         if (mImageArray[level][layer]->isDirty())
   2687         {
   2688             commitRect(level, 0, 0, layer, getWidth(level), getHeight(level));
   2689         }
   2690     }
   2691 }
   2692 
   2693 bool Texture2DArray::ensureRenderTarget()
   2694 {
   2695     initializeStorage(true);
   2696 
   2697     if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getLayers(0) > 0)
   2698     {
   2699         ASSERT(mTexStorage);
   2700         if (!mTexStorage->isRenderTarget())
   2701         {
   2702             rx::TextureStorageInterface2DArray *newRenderTargetStorage = createCompleteStorage(true);
   2703 
   2704             if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage))
   2705             {
   2706                 delete newRenderTargetStorage;
   2707                 return gl::error(GL_OUT_OF_MEMORY, false);
   2708             }
   2709 
   2710             setCompleteTexStorage(newRenderTargetStorage);
   2711         }
   2712     }
   2713 
   2714     return (mTexStorage && mTexStorage->isRenderTarget());
   2715 }
   2716 
   2717 rx::RenderTarget *Texture2DArray::getRenderTarget(GLint level, GLint layer)
   2718 {
   2719     // ensure the underlying texture is created
   2720     if (!ensureRenderTarget())
   2721     {
   2722         return NULL;
   2723     }
   2724 
   2725     updateStorageLevel(level);
   2726 
   2727     // ensure this is NOT a depth texture
   2728     if (isDepth(level))
   2729     {
   2730         return NULL;
   2731     }
   2732 
   2733     return mTexStorage->getRenderTarget(level, layer);
   2734 }
   2735 
   2736 rx::RenderTarget *Texture2DArray::getDepthStencil(GLint level, GLint layer)
   2737 {
   2738     // ensure the underlying texture is created
   2739     if (!ensureRenderTarget())
   2740     {
   2741         return NULL;
   2742     }
   2743 
   2744     updateStorageLevel(level);
   2745 
   2746     // ensure this is a depth texture
   2747     if (!isDepth(level))
   2748     {
   2749         return NULL;
   2750     }
   2751 
   2752     return mTexStorage->getRenderTarget(level, layer);
   2753 }
   2754 
   2755 void Texture2DArray::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
   2756 {
   2757     // If there currently is a corresponding storage texture image, it has these parameters
   2758     const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
   2759     const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
   2760     const int storageDepth = getLayers(0);
   2761     const GLenum storageFormat = getBaseLevelInternalFormat();
   2762 
   2763     for (int layer = 0; layer < mLayerCounts[level]; layer++)
   2764     {
   2765         delete mImageArray[level][layer];
   2766     }
   2767     delete[] mImageArray[level];
   2768     mImageArray[level] = NULL;
   2769     mLayerCounts[level] = depth;
   2770 
   2771     if (depth > 0)
   2772     {
   2773         mImageArray[level] = new rx::Image*[depth]();
   2774 
   2775         for (int layer = 0; layer < mLayerCounts[level]; layer++)
   2776         {
   2777             mImageArray[level][layer] = mRenderer->createImage();
   2778             mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, width, height, 1, false);
   2779         }
   2780     }
   2781 
   2782     if (mTexStorage)
   2783     {
   2784         const int storageLevels = mTexStorage->getLevelCount();
   2785 
   2786         if ((level >= storageLevels && storageLevels != 0) ||
   2787             width != storageWidth ||
   2788             height != storageHeight ||
   2789             depth != storageDepth ||
   2790             internalformat != storageFormat)   // Discard mismatched storage
   2791         {
   2792             for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
   2793             {
   2794                 for (int layer = 0; layer < mLayerCounts[level]; layer++)
   2795                 {
   2796                     mImageArray[level][layer]->markDirty();
   2797                 }
   2798             }
   2799 
   2800             delete mTexStorage;
   2801             mTexStorage = NULL;
   2802             mDirtyImages = true;
   2803         }
   2804     }
   2805 }
   2806 
   2807 void Texture2DArray::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height)
   2808 {
   2809     if (isValidLevel(level) && layerTarget < getLayers(level))
   2810     {
   2811         rx::Image *image = mImageArray[level][layerTarget];
   2812         if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, layerTarget, width, height))
   2813         {
   2814             image->markClean();
   2815         }
   2816     }
   2817 }
   2818 
   2819 }
   2820