baa5bc68a9638e149abf8f1683e0fc3268bb909b
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / Texture.cpp
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 }