blob: ebba7733995814d7a8e256f0110539db4f32a62f [file] [log] [blame]
daniel@transgaming.com95a758f2012-07-12 15:17:06 +00001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com95a758f2012-07-12 15:17:06 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Texture.cpp: Implements the gl::Texture class and its derived classes
8// Texture2D and TextureCubeMap. Implements GL texture objects and related
9// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
10
11#include "libGLESv2/Texture.h"
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000012#include "libGLESv2/main.h"
Brandon Jones6053a522014-07-25 16:22:09 -070013#include "libGLESv2/Context.h"
shannonwoods@chromium.org4ad58e02013-05-30 00:08:11 +000014#include "libGLESv2/formatutils.h"
Jamie Madillfeda4d22014-09-17 13:03:29 -040015#include "libGLESv2/ImageIndex.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000016#include "libGLESv2/Renderbuffer.h"
17#include "libGLESv2/renderer/Image.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040018#include "libGLESv2/renderer/d3d/TextureStorage.h"
19
20#include "libEGL/Surface.h"
21
22#include "common/mathutil.h"
23#include "common/utilities.h"
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000024
25namespace gl
26{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000027
Brandon Jones6053a522014-07-25 16:22:09 -070028bool IsMipmapFiltered(const gl::SamplerState &samplerState)
29{
30 switch (samplerState.minFilter)
31 {
32 case GL_NEAREST:
33 case GL_LINEAR:
34 return false;
35 case GL_NEAREST_MIPMAP_NEAREST:
36 case GL_LINEAR_MIPMAP_NEAREST:
37 case GL_NEAREST_MIPMAP_LINEAR:
38 case GL_LINEAR_MIPMAP_LINEAR:
39 return true;
40 default: UNREACHABLE();
41 return false;
42 }
43}
44
45bool IsPointSampled(const gl::SamplerState &samplerState)
46{
47 return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
48}
49
50Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
Brandon Jonesf47bebc2014-07-09 14:28:42 -070051 : RefCountObject(id),
Brandon Jones6053a522014-07-25 16:22:09 -070052 mTexture(impl),
Brandon Jonesf47bebc2014-07-09 14:28:42 -070053 mUsage(GL_NONE),
54 mImmutable(false),
55 mTarget(target)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000056{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000057}
58
59Texture::~Texture()
60{
Brandon Jones6053a522014-07-25 16:22:09 -070061 SafeDelete(mTexture);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000062}
63
Geoff Lang4907f2c2013-07-25 12:53:57 -040064GLenum Texture::getTarget() const
65{
66 return mTarget;
67}
68
Geoff Lang63b5f1f2013-09-23 14:52:14 -040069void Texture::setUsage(GLenum usage)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000070{
Geoff Lang63b5f1f2013-09-23 14:52:14 -040071 mUsage = usage;
Brandon Jonescef06ff2014-08-05 13:27:48 -070072 getImplementation()->setUsage(usage);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000073}
74
Brandon Jonesa328d562014-07-01 13:52:40 -070075void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler)
daniel@transgaming.comebf139f2012-10-31 18:07:32 +000076{
77 *sampler = mSamplerState;
Nicolas Capens8de68282014-04-04 11:10:27 -040078
79 // Offset the effective base level by the texture storage's top level
Jamie Madill2f06dbf2014-09-18 15:08:50 -040080 rx::TextureStorage *texture = getNativeTexture();
Nicolas Capens8de68282014-04-04 11:10:27 -040081 int topLevel = texture ? texture->getTopLevel() : 0;
82 sampler->baseLevel = topLevel + mSamplerState.baseLevel;
daniel@transgaming.com07ab8412012-07-12 15:17:09 +000083}
84
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000085GLenum Texture::getUsage() const
86{
87 return mUsage;
88}
89
Jamie Madilld3d2a342013-10-07 10:46:35 -040090GLint Texture::getBaseLevelWidth() const
91{
92 const rx::Image *baseImage = getBaseLevelImage();
93 return (baseImage ? baseImage->getWidth() : 0);
94}
95
96GLint Texture::getBaseLevelHeight() const
97{
98 const rx::Image *baseImage = getBaseLevelImage();
99 return (baseImage ? baseImage->getHeight() : 0);
100}
101
102GLint Texture::getBaseLevelDepth() const
103{
104 const rx::Image *baseImage = getBaseLevelImage();
105 return (baseImage ? baseImage->getDepth() : 0);
106}
107
Jamie Madillb8f8b892014-01-07 10:12:50 -0500108// Note: "base level image" is loosely defined to be any image from the base level,
109// where in the base of 2D array textures and cube maps there are several. Don't use
110// the base level image for anything except querying texture format and size.
Jamie Madilld3d2a342013-10-07 10:46:35 -0400111GLenum Texture::getBaseLevelInternalFormat() const
112{
113 const rx::Image *baseImage = getBaseLevelImage();
114 return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
115}
116
Jamie Madill945f7322014-09-03 15:07:14 -0400117GLsizei Texture::getWidth(const ImageIndex &index) const
118{
Jamie Madillfeda4d22014-09-17 13:03:29 -0400119 rx::Image *image = mTexture->getImage(index);
Jamie Madill945f7322014-09-03 15:07:14 -0400120 return image->getWidth();
121}
122
123GLsizei Texture::getHeight(const ImageIndex &index) const
124{
Jamie Madillfeda4d22014-09-17 13:03:29 -0400125 rx::Image *image = mTexture->getImage(index);
Jamie Madill945f7322014-09-03 15:07:14 -0400126 return image->getHeight();
127}
128
129GLenum Texture::getInternalFormat(const ImageIndex &index) const
130{
Jamie Madillfeda4d22014-09-17 13:03:29 -0400131 rx::Image *image = mTexture->getImage(index);
Jamie Madill945f7322014-09-03 15:07:14 -0400132 return image->getInternalFormat();
133}
134
135GLenum Texture::getActualFormat(const ImageIndex &index) const
136{
Jamie Madillfeda4d22014-09-17 13:03:29 -0400137 rx::Image *image = mTexture->getImage(index);
Jamie Madill945f7322014-09-03 15:07:14 -0400138 return image->getActualFormat();
139}
140
Jamie Madill2f06dbf2014-09-18 15:08:50 -0400141rx::TextureStorage *Texture::getNativeTexture()
Brandon Jones6b19b002014-07-16 14:32:05 -0700142{
143 return getImplementation()->getNativeTexture();
144}
145
Brandon Jonescef06ff2014-08-05 13:27:48 -0700146void Texture::generateMipmaps()
147{
148 getImplementation()->generateMipmaps();
149}
150
Brandon Jones6b19b002014-07-16 14:32:05 -0700151void Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
152{
153 getImplementation()->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
154}
155
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700156unsigned int Texture::getTextureSerial()
157{
Jamie Madill2f06dbf2014-09-18 15:08:50 -0400158 rx::TextureStorage *texture = getNativeTexture();
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700159 return texture ? texture->getTextureSerial() : 0;
160}
161
162bool Texture::isImmutable() const
163{
164 return mImmutable;
165}
166
167int Texture::immutableLevelCount()
168{
Jamie Madill2f06dbf2014-09-18 15:08:50 -0400169 return (mImmutable ? getNativeTexture()->getLevelCount() : 0);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700170}
171
172int Texture::mipLevels() const
173{
174 return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
175}
176
Brandon Jonescef06ff2014-08-05 13:27:48 -0700177const rx::Image *Texture::getBaseLevelImage() const
178{
179 return (getImplementation()->getLayerCount(0) > 0 ? getImplementation()->getImage(0, 0) : NULL);
180}
181
Brandon Jones6053a522014-07-25 16:22:09 -0700182Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id)
183 : Texture(impl, id, GL_TEXTURE_2D)
Jamie Madill22f843a2013-10-24 17:49:36 -0400184{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000185 mSurface = NULL;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000186}
187
188Texture2D::~Texture2D()
189{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000190 if (mSurface)
191 {
192 mSurface->setBoundTexture(NULL);
193 mSurface = NULL;
194 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700195}
daniel@transgaming.comd9ec9022012-12-20 20:52:16 +0000196
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000197GLsizei Texture2D::getWidth(GLint level) const
198{
199 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700200 return mTexture->getImage(level, 0)->getWidth();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000201 else
202 return 0;
203}
204
205GLsizei Texture2D::getHeight(GLint level) const
206{
207 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700208 return mTexture->getImage(level, 0)->getHeight();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000209 else
210 return 0;
211}
212
213GLenum Texture2D::getInternalFormat(GLint level) const
214{
215 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700216 return mTexture->getImage(level, 0)->getInternalFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000217 else
218 return GL_NONE;
219}
220
daniel@transgaming.com20d36662012-10-31 19:51:43 +0000221GLenum Texture2D::getActualFormat(GLint level) const
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000222{
223 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700224 return mTexture->getImage(level, 0)->getActualFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000225 else
Geoff Langcbf727a2014-02-10 12:50:45 -0500226 return GL_NONE;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000227}
228
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400229Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000230{
231 releaseTexImage();
shannon.woods@transgaming.com8a406682013-02-28 23:15:26 +0000232
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400233 return mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000234}
235
236void Texture2D::bindTexImage(egl::Surface *surface)
237{
238 releaseTexImage();
239
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700240 mTexture->bindTexImage(surface);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000241
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000242 mSurface = surface;
243 mSurface->setBoundTexture(this);
244}
245
246void Texture2D::releaseTexImage()
247{
248 if (mSurface)
249 {
250 mSurface->setBoundTexture(NULL);
251 mSurface = NULL;
252
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700253 mTexture->releaseTexImage();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000254 }
255}
256
257void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
258{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700259 releaseTexImage();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000260
Brandon Jonescef06ff2014-08-05 13:27:48 -0700261 mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000262}
263
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400264Error Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000265{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400266 return mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000267}
268
269void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
270{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700271 mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000272}
273
274void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
275{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700276 releaseTexImage();
Geoff Lang5d601382014-07-22 15:14:06 -0400277
Brandon Jonescef06ff2014-08-05 13:27:48 -0700278 mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000279}
280
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000281void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
282{
Jamie Madill73b5d062013-10-24 17:49:38 -0400283 mImmutable = true;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000284
Brandon Jonescef06ff2014-08-05 13:27:48 -0700285 mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000286}
287
Brandon Jones6053a522014-07-25 16:22:09 -0700288// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
289bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
290{
291 GLsizei width = getBaseLevelWidth();
292 GLsizei height = getBaseLevelHeight();
293
294 if (width <= 0 || height <= 0)
295 {
296 return false;
297 }
298
299 if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
300 {
301 return false;
302 }
303
304 bool npotSupport = extensions.textureNPOT;
305
306 if (!npotSupport)
307 {
308 if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
309 (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
310 {
311 return false;
312 }
313 }
314
315 if (IsMipmapFiltered(samplerState))
316 {
317 if (!npotSupport)
318 {
319 if (!gl::isPow2(width) || !gl::isPow2(height))
320 {
321 return false;
322 }
323 }
324
325 if (!isMipmapComplete())
326 {
327 return false;
328 }
329 }
330
331 // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
332 // The internalformat specified for the texture arrays is a sized internal depth or
333 // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
334 // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
335 // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
336 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(0));
337 if (formatInfo.depthBits > 0 && clientVersion > 2)
338 {
339 if (samplerState.compareMode == GL_NONE)
340 {
341 if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
342 samplerState.magFilter != GL_NEAREST)
343 {
344 return false;
345 }
346 }
347 }
348
349 return true;
350}
351
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000352bool Texture2D::isCompressed(GLint level) const
353{
Geoff Lang5d601382014-07-22 15:14:06 -0400354 return GetInternalFormatInfo(getInternalFormat(level)).compressed;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000355}
356
357bool Texture2D::isDepth(GLint level) const
358{
Geoff Lang5d601382014-07-22 15:14:06 -0400359 return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000360}
361
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000362void Texture2D::generateMipmaps()
363{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700364 releaseTexImage();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000365
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700366 mTexture->generateMipmaps();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000367}
368
Brandon Jones6053a522014-07-25 16:22:09 -0700369// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
370bool Texture2D::isMipmapComplete() const
371{
372 int levelCount = mipLevels();
373
374 for (int level = 0; level < levelCount; level++)
375 {
376 if (!isLevelComplete(level))
377 {
378 return false;
379 }
380 }
381
382 return true;
383}
384
385bool Texture2D::isLevelComplete(int level) const
386{
387 if (isImmutable())
388 {
389 return true;
390 }
391
392 const rx::Image *baseImage = getBaseLevelImage();
393
394 GLsizei width = baseImage->getWidth();
395 GLsizei height = baseImage->getHeight();
396
397 if (width <= 0 || height <= 0)
398 {
399 return false;
400 }
401
402 // The base image level is complete if the width and height are positive
403 if (level == 0)
404 {
405 return true;
406 }
407
408 ASSERT(level >= 1 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
409 rx::Image *image = mTexture->getImage(level, 0);
410
411 if (image->getInternalFormat() != baseImage->getInternalFormat())
412 {
413 return false;
414 }
415
416 if (image->getWidth() != std::max(1, width >> level))
417 {
418 return false;
419 }
420
421 if (image->getHeight() != std::max(1, height >> level))
422 {
423 return false;
424 }
425
426 return true;
427}
428
429TextureCubeMap::TextureCubeMap(rx::TextureImpl *impl, GLuint id)
430 : Texture(impl, id, GL_TEXTURE_CUBE_MAP)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000431{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000432}
433
434TextureCubeMap::~TextureCubeMap()
435{
Brandon Jones0511e802014-07-14 16:27:26 -0700436}
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000437
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000438GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
439{
440 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700441 return mTexture->getImage(level, targetToLayerIndex(target))->getWidth();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000442 else
443 return 0;
444}
445
446GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
447{
448 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700449 return mTexture->getImage(level, targetToLayerIndex(target))->getHeight();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000450 else
451 return 0;
452}
453
454GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
455{
456 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700457 return mTexture->getImage(level, targetToLayerIndex(target))->getInternalFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000458 else
459 return GL_NONE;
460}
461
daniel@transgaming.com20d36662012-10-31 19:51:43 +0000462GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000463{
464 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700465 return mTexture->getImage(level, targetToLayerIndex(target))->getActualFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000466 else
Geoff Langcbf727a2014-02-10 12:50:45 -0500467 return GL_NONE;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000468}
469
Geoff Lang8376cea2014-09-02 11:47:07 -0400470Error TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000471{
Geoff Lang8376cea2014-09-02 11:47:07 -0400472 return mTexture->setImage(target, level, width, height, 1, internalFormat, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000473}
474
Jamie Madill2db197c2013-10-24 17:49:35 -0400475void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000476{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700477 mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000478}
479
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400480Error TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000481{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400482 return mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000483}
484
485void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
486{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700487 mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000488}
489
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000490// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
491bool TextureCubeMap::isCubeComplete() const
492{
Brandon Jones6053a522014-07-25 16:22:09 -0700493 int baseWidth = getBaseLevelWidth();
494 int baseHeight = getBaseLevelHeight();
495 GLenum baseFormat = getBaseLevelInternalFormat();
496
497 if (baseWidth <= 0 || baseWidth != baseHeight)
498 {
499 return false;
500 }
501
502 for (int faceIndex = 1; faceIndex < 6; faceIndex++)
503 {
504 const rx::Image *faceBaseImage = mTexture->getImage(0, faceIndex);
505
506 if (faceBaseImage->getWidth() != baseWidth ||
507 faceBaseImage->getHeight() != baseHeight ||
508 faceBaseImage->getInternalFormat() != baseFormat )
509 {
510 return false;
511 }
512 }
513
514 return true;
Jamie Madill07edd442013-07-19 16:36:58 -0400515}
516
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000517bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
518{
Geoff Lang5d601382014-07-22 15:14:06 -0400519 return GetInternalFormatInfo(getInternalFormat(target, level)).compressed;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000520}
521
Geoff Lang8040f572013-07-25 16:49:54 -0400522bool TextureCubeMap::isDepth(GLenum target, GLint level) const
523{
Geoff Lang5d601382014-07-22 15:14:06 -0400524 return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0;
Geoff Lang8040f572013-07-25 16:49:54 -0400525}
526
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000527void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
528{
Brandon Jones0511e802014-07-14 16:27:26 -0700529 mTexture->copyImage(target, level, format, x, y, width, height, source);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000530}
531
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000532void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
533{
Jamie Madill3c0989c2013-10-24 17:49:39 -0400534 mImmutable = true;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000535
Brandon Jonescef06ff2014-08-05 13:27:48 -0700536 mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1);
Jamie Madill2ebab852013-10-24 17:49:42 -0400537}
538
Brandon Jones6053a522014-07-25 16:22:09 -0700539// Tests for texture sampling completeness
540bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
541{
542 int size = getBaseLevelWidth();
543
544 bool mipmapping = IsMipmapFiltered(samplerState);
545
546 if (!textureCaps.get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable && !IsPointSampled(samplerState))
547 {
548 return false;
549 }
550
551 if (!gl::isPow2(size) && !extensions.textureNPOT)
552 {
553 if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
554 {
555 return false;
556 }
557 }
558
559 if (!mipmapping)
560 {
561 if (!isCubeComplete())
562 {
563 return false;
564 }
565 }
566 else
567 {
568 if (!isMipmapComplete()) // Also tests for isCubeComplete()
569 {
570 return false;
571 }
572 }
573
574 return true;
575}
576
Brandon Jonescef06ff2014-08-05 13:27:48 -0700577int TextureCubeMap::targetToLayerIndex(GLenum target)
578{
579 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
580 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
581 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
582 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
583 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
584
585 return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
586}
587
588GLenum TextureCubeMap::layerIndexToTarget(GLint layer)
589{
590 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
591 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
592 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
593 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
594 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
595
596 return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
Geoff Lang8040f572013-07-25 16:49:54 -0400597}
598
Brandon Jones6053a522014-07-25 16:22:09 -0700599bool TextureCubeMap::isMipmapComplete() const
600{
601 if (isImmutable())
602 {
603 return true;
604 }
605
606 if (!isCubeComplete())
607 {
608 return false;
609 }
610
611 int levelCount = mipLevels();
612
613 for (int face = 0; face < 6; face++)
614 {
615 for (int level = 1; level < levelCount; level++)
616 {
617 if (!isFaceLevelComplete(face, level))
618 {
619 return false;
620 }
621 }
622 }
623
624 return true;
625}
626
627bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const
628{
629 ASSERT(level >= 0 && faceIndex < 6 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, faceIndex) != NULL);
630
631 if (isImmutable())
632 {
633 return true;
634 }
635
636 int baseSize = getBaseLevelWidth();
637
638 if (baseSize <= 0)
639 {
640 return false;
641 }
642
643 // "isCubeComplete" checks for base level completeness and we must call that
644 // to determine if any face at level 0 is complete. We omit that check here
645 // to avoid re-checking cube-completeness for every face at level 0.
646 if (level == 0)
647 {
648 return true;
649 }
650
651 // Check that non-zero levels are consistent with the base level.
652 const rx::Image *faceLevelImage = mTexture->getImage(level, faceIndex);
653
654 if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
655 {
656 return false;
657 }
658
659 if (faceLevelImage->getWidth() != std::max(1, baseSize >> level))
660 {
661 return false;
662 }
663
664 return true;
665}
666
667
668Texture3D::Texture3D(rx::TextureImpl *impl, GLuint id)
669 : Texture(impl, id, GL_TEXTURE_3D)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000670{
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000671}
672
673Texture3D::~Texture3D()
674{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700675}
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000676
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000677GLsizei Texture3D::getWidth(GLint level) const
678{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700679 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getWidth() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000680}
681
682GLsizei Texture3D::getHeight(GLint level) const
683{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700684 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getHeight() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000685}
686
687GLsizei Texture3D::getDepth(GLint level) const
688{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700689 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getDepth() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000690}
691
692GLenum Texture3D::getInternalFormat(GLint level) const
693{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700694 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000695}
696
697GLenum Texture3D::getActualFormat(GLint level) const
698{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700699 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000700}
701
702bool Texture3D::isCompressed(GLint level) const
703{
Geoff Lang5d601382014-07-22 15:14:06 -0400704 return GetInternalFormatInfo(getInternalFormat(level)).compressed;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000705}
706
707bool Texture3D::isDepth(GLint level) const
708{
Geoff Lang5d601382014-07-22 15:14:06 -0400709 return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000710}
711
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400712Error Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000713{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400714 return mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000715}
716
717void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
718{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700719 mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, pixels);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000720}
721
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400722Error 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)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000723{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400724 return mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000725}
726
727void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
728{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700729 mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000730}
731
732void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
733{
Jamie Madille664e202013-10-24 17:49:40 -0400734 mImmutable = true;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000735
Brandon Jonescef06ff2014-08-05 13:27:48 -0700736 mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth);
Jamie Madill2ebab852013-10-24 17:49:42 -0400737}
738
Brandon Jones6053a522014-07-25 16:22:09 -0700739bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
740{
741 GLsizei width = getBaseLevelWidth();
742 GLsizei height = getBaseLevelHeight();
743 GLsizei depth = getBaseLevelDepth();
744
745 if (width <= 0 || height <= 0 || depth <= 0)
746 {
747 return false;
748 }
749
750 if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
751 {
752 return false;
753 }
754
755 if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
756 {
757 return false;
758 }
759
760 return true;
761}
762
Brandon Jones6053a522014-07-25 16:22:09 -0700763bool Texture3D::isMipmapComplete() const
764{
765 int levelCount = mipLevels();
766
767 for (int level = 0; level < levelCount; level++)
768 {
769 if (!isLevelComplete(level))
770 {
771 return false;
772 }
773 }
774
775 return true;
776}
777
778bool Texture3D::isLevelComplete(int level) const
779{
780 ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
781
782 if (isImmutable())
783 {
784 return true;
785 }
786
787 GLsizei width = getBaseLevelWidth();
788 GLsizei height = getBaseLevelHeight();
789 GLsizei depth = getBaseLevelDepth();
790
791 if (width <= 0 || height <= 0 || depth <= 0)
792 {
793 return false;
794 }
795
796 if (level == 0)
797 {
798 return true;
799 }
800
801 rx::Image *levelImage = mTexture->getImage(level, 0);
802
803 if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
804 {
805 return false;
806 }
807
808 if (levelImage->getWidth() != std::max(1, width >> level))
809 {
810 return false;
811 }
812
813 if (levelImage->getHeight() != std::max(1, height >> level))
814 {
815 return false;
816 }
817
818 if (levelImage->getDepth() != std::max(1, depth >> level))
819 {
820 return false;
821 }
822
823 return true;
824}
825
826Texture2DArray::Texture2DArray(rx::TextureImpl *impl, GLuint id)
827 : Texture(impl, id, GL_TEXTURE_2D_ARRAY)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000828{
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000829}
830
831Texture2DArray::~Texture2DArray()
832{
Jamie Madill884a4622013-10-24 17:49:41 -0400833}
834
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000835GLsizei Texture2DArray::getWidth(GLint level) const
836{
Brandon Jones142ec422014-07-16 10:31:30 -0700837 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getWidth() : 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000838}
839
840GLsizei Texture2DArray::getHeight(GLint level) const
841{
Brandon Jones142ec422014-07-16 10:31:30 -0700842 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getHeight() : 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000843}
844
Jamie Madillb8f8b892014-01-07 10:12:50 -0500845GLsizei Texture2DArray::getLayers(GLint level) const
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000846{
Brandon Jones142ec422014-07-16 10:31:30 -0700847 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getLayerCount(level) : 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000848}
849
850GLenum Texture2DArray::getInternalFormat(GLint level) const
851{
Brandon Jones142ec422014-07-16 10:31:30 -0700852 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000853}
854
855GLenum Texture2DArray::getActualFormat(GLint level) const
856{
Brandon Jones142ec422014-07-16 10:31:30 -0700857 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000858}
859
860bool Texture2DArray::isCompressed(GLint level) const
861{
Geoff Lang5d601382014-07-22 15:14:06 -0400862 return GetInternalFormatInfo(getInternalFormat(level)).compressed;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000863}
864
865bool Texture2DArray::isDepth(GLint level) const
866{
Geoff Lang5d601382014-07-22 15:14:06 -0400867 return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000868}
869
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400870Error Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000871{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400872 return mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000873}
874
875void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
876{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700877 mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, pixels);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000878}
879
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400880Error 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)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000881{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400882 return mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000883}
884
885void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
886{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700887 mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000888}
889
890void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
891{
Jamie Madill884a4622013-10-24 17:49:41 -0400892 mImmutable = true;
Brandon Jones142ec422014-07-16 10:31:30 -0700893
Brandon Jonescef06ff2014-08-05 13:27:48 -0700894 mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth);
Jamie Madill2ebab852013-10-24 17:49:42 -0400895}
896
Brandon Jones6053a522014-07-25 16:22:09 -0700897bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
898{
899 GLsizei width = getBaseLevelWidth();
900 GLsizei height = getBaseLevelHeight();
901 GLsizei depth = getLayers(0);
902
903 if (width <= 0 || height <= 0 || depth <= 0)
904 {
905 return false;
906 }
907
908 if (!textureCaps.get(getBaseLevelInternalFormat()).filterable && !IsPointSampled(samplerState))
909 {
910 return false;
911 }
912
913 if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
914 {
915 return false;
916 }
917
918 return true;
919}
920
Brandon Jones6053a522014-07-25 16:22:09 -0700921bool Texture2DArray::isMipmapComplete() const
922{
923 int levelCount = mipLevels();
924
925 for (int level = 1; level < levelCount; level++)
926 {
927 if (!isLevelComplete(level))
928 {
929 return false;
930 }
931 }
932
933 return true;
934}
935
936bool Texture2DArray::isLevelComplete(int level) const
937{
938 ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
939
940 if (isImmutable())
941 {
942 return true;
943 }
944
945 GLsizei width = getBaseLevelWidth();
946 GLsizei height = getBaseLevelHeight();
947 GLsizei layers = getLayers(0);
948
949 if (width <= 0 || height <= 0 || layers <= 0)
950 {
951 return false;
952 }
953
954 if (level == 0)
955 {
956 return true;
957 }
958
959 if (getInternalFormat(level) != getInternalFormat(0))
960 {
961 return false;
962 }
963
964 if (getWidth(level) != std::max(1, width >> level))
965 {
966 return false;
967 }
968
969 if (getHeight(level) != std::max(1, height >> level))
970 {
971 return false;
972 }
973
974 if (getLayers(level) != layers)
975 {
976 return false;
977 }
978
979 return true;
980}
981
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000982}