blob: b34fc785aac1e77eaa2a6f4f5682a36c8b065723 [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
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Texture.h"
12#include "libANGLE/Context.h"
13#include "libANGLE/formatutils.h"
14#include "libANGLE/ImageIndex.h"
15#include "libANGLE/Renderbuffer.h"
16#include "libANGLE/renderer/Image.h"
17#include "libANGLE/renderer/d3d/TextureStorage.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040018
Geoff Lang2b5420c2014-11-19 14:20:15 -050019#include "libANGLE/Surface.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040020
21#include "common/mathutil.h"
22#include "common/utilities.h"
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000023
24namespace gl
25{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000026
Brandon Jones6053a522014-07-25 16:22:09 -070027bool IsMipmapFiltered(const gl::SamplerState &samplerState)
28{
29 switch (samplerState.minFilter)
30 {
31 case GL_NEAREST:
32 case GL_LINEAR:
33 return false;
34 case GL_NEAREST_MIPMAP_NEAREST:
35 case GL_LINEAR_MIPMAP_NEAREST:
36 case GL_NEAREST_MIPMAP_LINEAR:
37 case GL_LINEAR_MIPMAP_LINEAR:
38 return true;
39 default: UNREACHABLE();
40 return false;
41 }
42}
43
44bool IsPointSampled(const gl::SamplerState &samplerState)
45{
46 return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
47}
48
Jamie Madill10ef2152014-10-20 17:04:34 -040049unsigned int Texture::mCurrentTextureSerial = 1;
50
Brandon Jones6053a522014-07-25 16:22:09 -070051Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
Brandon Jonesf47bebc2014-07-09 14:28:42 -070052 : RefCountObject(id),
Brandon Jones6053a522014-07-25 16:22:09 -070053 mTexture(impl),
Jamie Madill10ef2152014-10-20 17:04:34 -040054 mTextureSerial(issueTextureSerial()),
Brandon Jonesf47bebc2014-07-09 14:28:42 -070055 mUsage(GL_NONE),
Jamie Madill6948e302014-10-20 17:04:33 -040056 mImmutableLevelCount(0),
Brandon Jonesf47bebc2014-07-09 14:28:42 -070057 mTarget(target)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000058{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000059}
60
61Texture::~Texture()
62{
Brandon Jones6053a522014-07-25 16:22:09 -070063 SafeDelete(mTexture);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000064}
65
Geoff Lang4907f2c2013-07-25 12:53:57 -040066GLenum Texture::getTarget() const
67{
68 return mTarget;
69}
70
Geoff Lang63b5f1f2013-09-23 14:52:14 -040071void Texture::setUsage(GLenum usage)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000072{
Geoff Lang63b5f1f2013-09-23 14:52:14 -040073 mUsage = usage;
Brandon Jonescef06ff2014-08-05 13:27:48 -070074 getImplementation()->setUsage(usage);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000075}
76
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000077GLenum Texture::getUsage() const
78{
79 return mUsage;
80}
81
Jamie Madilld3d2a342013-10-07 10:46:35 -040082GLint Texture::getBaseLevelWidth() const
83{
84 const rx::Image *baseImage = getBaseLevelImage();
85 return (baseImage ? baseImage->getWidth() : 0);
86}
87
88GLint Texture::getBaseLevelHeight() const
89{
90 const rx::Image *baseImage = getBaseLevelImage();
91 return (baseImage ? baseImage->getHeight() : 0);
92}
93
94GLint Texture::getBaseLevelDepth() const
95{
96 const rx::Image *baseImage = getBaseLevelImage();
97 return (baseImage ? baseImage->getDepth() : 0);
98}
99
Jamie Madillb8f8b892014-01-07 10:12:50 -0500100// Note: "base level image" is loosely defined to be any image from the base level,
101// where in the base of 2D array textures and cube maps there are several. Don't use
102// the base level image for anything except querying texture format and size.
Jamie Madilld3d2a342013-10-07 10:46:35 -0400103GLenum Texture::getBaseLevelInternalFormat() const
104{
105 const rx::Image *baseImage = getBaseLevelImage();
106 return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
107}
108
Jamie Madill945f7322014-09-03 15:07:14 -0400109GLsizei Texture::getWidth(const ImageIndex &index) const
110{
Jamie Madillfeda4d22014-09-17 13:03:29 -0400111 rx::Image *image = mTexture->getImage(index);
Jamie Madill945f7322014-09-03 15:07:14 -0400112 return image->getWidth();
113}
114
115GLsizei Texture::getHeight(const ImageIndex &index) const
116{
Jamie Madillfeda4d22014-09-17 13:03:29 -0400117 rx::Image *image = mTexture->getImage(index);
Jamie Madill945f7322014-09-03 15:07:14 -0400118 return image->getHeight();
119}
120
121GLenum Texture::getInternalFormat(const ImageIndex &index) const
122{
Jamie Madillfeda4d22014-09-17 13:03:29 -0400123 rx::Image *image = mTexture->getImage(index);
Jamie Madill945f7322014-09-03 15:07:14 -0400124 return image->getInternalFormat();
125}
126
Geoff Lang06ecf3d2014-09-23 16:39:50 -0400127Error Texture::generateMipmaps()
Brandon Jonescef06ff2014-08-05 13:27:48 -0700128{
Geoff Lang06ecf3d2014-09-23 16:39:50 -0400129 return getImplementation()->generateMipmaps();
Brandon Jonescef06ff2014-08-05 13:27:48 -0700130}
131
Geoff Langef7b0162014-09-04 13:29:23 -0400132Error Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
133 GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
Brandon Jones6b19b002014-07-16 14:32:05 -0700134{
Geoff Langef7b0162014-09-04 13:29:23 -0400135 return mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Brandon Jones6b19b002014-07-16 14:32:05 -0700136}
137
Jamie Madill10ef2152014-10-20 17:04:34 -0400138unsigned int Texture::getTextureSerial() const
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700139{
Jamie Madill10ef2152014-10-20 17:04:34 -0400140 return mTextureSerial;
141}
142
143unsigned int Texture::issueTextureSerial()
144{
145 return mCurrentTextureSerial++;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700146}
147
148bool Texture::isImmutable() const
149{
Jamie Madill6948e302014-10-20 17:04:33 -0400150 return (mImmutableLevelCount > 0);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700151}
152
153int Texture::immutableLevelCount()
154{
Jamie Madill6948e302014-10-20 17:04:33 -0400155 return mImmutableLevelCount;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700156}
157
158int Texture::mipLevels() const
159{
160 return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
161}
162
Brandon Jonescef06ff2014-08-05 13:27:48 -0700163const rx::Image *Texture::getBaseLevelImage() const
164{
165 return (getImplementation()->getLayerCount(0) > 0 ? getImplementation()->getImage(0, 0) : NULL);
166}
167
Brandon Jones6053a522014-07-25 16:22:09 -0700168Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id)
169 : Texture(impl, id, GL_TEXTURE_2D)
Jamie Madill22f843a2013-10-24 17:49:36 -0400170{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000171 mSurface = NULL;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000172}
173
174Texture2D::~Texture2D()
175{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000176 if (mSurface)
177 {
Jamie Madillfb0580a2014-11-27 14:03:52 -0500178 mSurface->releaseTexImage(EGL_BACK_BUFFER);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000179 mSurface = NULL;
180 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700181}
daniel@transgaming.comd9ec9022012-12-20 20:52:16 +0000182
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000183GLsizei Texture2D::getWidth(GLint level) const
184{
185 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700186 return mTexture->getImage(level, 0)->getWidth();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000187 else
188 return 0;
189}
190
191GLsizei Texture2D::getHeight(GLint level) const
192{
193 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700194 return mTexture->getImage(level, 0)->getHeight();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000195 else
196 return 0;
197}
198
199GLenum Texture2D::getInternalFormat(GLint level) const
200{
201 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700202 return mTexture->getImage(level, 0)->getInternalFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000203 else
204 return GL_NONE;
205}
206
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400207Error 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 +0000208{
209 releaseTexImage();
shannon.woods@transgaming.com8a406682013-02-28 23:15:26 +0000210
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400211 return mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000212}
213
214void Texture2D::bindTexImage(egl::Surface *surface)
215{
216 releaseTexImage();
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700217 mTexture->bindTexImage(surface);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000218 mSurface = surface;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000219}
220
221void Texture2D::releaseTexImage()
222{
223 if (mSurface)
224 {
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000225 mSurface = NULL;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700226 mTexture->releaseTexImage();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000227 }
228}
229
Geoff Langb5348332014-09-02 13:16:34 -0400230Error Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize,
Jamie Madillc751d1e2014-10-21 17:46:29 -0400231 const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000232{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700233 releaseTexImage();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000234
Jamie Madillc751d1e2014-10-21 17:46:29 -0400235 return mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000236}
237
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400238Error 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 +0000239{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400240 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 +0000241}
242
Geoff Langb5348332014-09-02 13:16:34 -0400243Error Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Jamie Madillc751d1e2014-10-21 17:46:29 -0400244 GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000245{
Jamie Madillc751d1e2014-10-21 17:46:29 -0400246 return mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000247}
248
Geoff Langef7b0162014-09-04 13:29:23 -0400249Error Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height,
250 Framebuffer *source)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000251{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700252 releaseTexImage();
Geoff Lang5d601382014-07-22 15:14:06 -0400253
Geoff Langef7b0162014-09-04 13:29:23 -0400254 return mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000255}
256
Geoff Lang1f8532b2014-09-05 09:46:13 -0400257Error Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000258{
Geoff Lang1f8532b2014-09-05 09:46:13 -0400259 Error error = mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1);
260 if (error.isError())
261 {
262 return error;
263 }
264
Jamie Madill6948e302014-10-20 17:04:33 -0400265 mImmutableLevelCount = levels;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000266
Geoff Lang1f8532b2014-09-05 09:46:13 -0400267 return Error(GL_NO_ERROR);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000268}
269
Brandon Jones6053a522014-07-25 16:22:09 -0700270// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
Geoff Langf4134d22014-12-15 10:29:47 -0500271bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
Brandon Jones6053a522014-07-25 16:22:09 -0700272{
273 GLsizei width = getBaseLevelWidth();
274 GLsizei height = getBaseLevelHeight();
275
276 if (width <= 0 || height <= 0)
277 {
278 return false;
279 }
280
Geoff Langf4134d22014-12-15 10:29:47 -0500281 if (!data.textureCaps->get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
Brandon Jones6053a522014-07-25 16:22:09 -0700282 {
283 return false;
284 }
285
Geoff Langf4134d22014-12-15 10:29:47 -0500286 bool npotSupport = data.extensions->textureNPOT;
Brandon Jones6053a522014-07-25 16:22:09 -0700287 if (!npotSupport)
288 {
289 if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
290 (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
291 {
292 return false;
293 }
294 }
295
296 if (IsMipmapFiltered(samplerState))
297 {
298 if (!npotSupport)
299 {
300 if (!gl::isPow2(width) || !gl::isPow2(height))
301 {
302 return false;
303 }
304 }
305
306 if (!isMipmapComplete())
307 {
308 return false;
309 }
310 }
311
312 // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
313 // The internalformat specified for the texture arrays is a sized internal depth or
314 // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
315 // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
316 // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
317 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(0));
Geoff Langf4134d22014-12-15 10:29:47 -0500318 if (formatInfo.depthBits > 0 && data.clientVersion > 2)
Brandon Jones6053a522014-07-25 16:22:09 -0700319 {
320 if (samplerState.compareMode == GL_NONE)
321 {
322 if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
323 samplerState.magFilter != GL_NEAREST)
324 {
325 return false;
326 }
327 }
328 }
329
330 return true;
331}
332
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000333bool Texture2D::isCompressed(GLint level) const
334{
Geoff Lang5d601382014-07-22 15:14:06 -0400335 return GetInternalFormatInfo(getInternalFormat(level)).compressed;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000336}
337
338bool Texture2D::isDepth(GLint level) const
339{
Geoff Lang5d601382014-07-22 15:14:06 -0400340 return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000341}
342
Geoff Lang06ecf3d2014-09-23 16:39:50 -0400343Error Texture2D::generateMipmaps()
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000344{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700345 releaseTexImage();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000346
Geoff Lang06ecf3d2014-09-23 16:39:50 -0400347 return mTexture->generateMipmaps();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000348}
349
Brandon Jones6053a522014-07-25 16:22:09 -0700350// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
351bool Texture2D::isMipmapComplete() const
352{
353 int levelCount = mipLevels();
354
355 for (int level = 0; level < levelCount; level++)
356 {
357 if (!isLevelComplete(level))
358 {
359 return false;
360 }
361 }
362
363 return true;
364}
365
366bool Texture2D::isLevelComplete(int level) const
367{
368 if (isImmutable())
369 {
370 return true;
371 }
372
373 const rx::Image *baseImage = getBaseLevelImage();
374
375 GLsizei width = baseImage->getWidth();
376 GLsizei height = baseImage->getHeight();
377
378 if (width <= 0 || height <= 0)
379 {
380 return false;
381 }
382
383 // The base image level is complete if the width and height are positive
384 if (level == 0)
385 {
386 return true;
387 }
388
389 ASSERT(level >= 1 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
390 rx::Image *image = mTexture->getImage(level, 0);
391
392 if (image->getInternalFormat() != baseImage->getInternalFormat())
393 {
394 return false;
395 }
396
397 if (image->getWidth() != std::max(1, width >> level))
398 {
399 return false;
400 }
401
402 if (image->getHeight() != std::max(1, height >> level))
403 {
404 return false;
405 }
406
407 return true;
408}
409
410TextureCubeMap::TextureCubeMap(rx::TextureImpl *impl, GLuint id)
411 : Texture(impl, id, GL_TEXTURE_CUBE_MAP)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000412{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000413}
414
415TextureCubeMap::~TextureCubeMap()
416{
Brandon Jones0511e802014-07-14 16:27:26 -0700417}
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000418
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000419GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
420{
421 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700422 return mTexture->getImage(level, targetToLayerIndex(target))->getWidth();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000423 else
424 return 0;
425}
426
427GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
428{
429 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700430 return mTexture->getImage(level, targetToLayerIndex(target))->getHeight();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000431 else
432 return 0;
433}
434
435GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
436{
437 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700438 return mTexture->getImage(level, targetToLayerIndex(target))->getInternalFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000439 else
440 return GL_NONE;
441}
442
Geoff Lang8376cea2014-09-02 11:47:07 -0400443Error 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 +0000444{
Geoff Lang8376cea2014-09-02 11:47:07 -0400445 return mTexture->setImage(target, level, width, height, 1, internalFormat, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000446}
447
Geoff Langb5348332014-09-02 13:16:34 -0400448Error TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height,
Jamie Madillc751d1e2014-10-21 17:46:29 -0400449 GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000450{
Jamie Madillc751d1e2014-10-21 17:46:29 -0400451 return mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000452}
453
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400454Error 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 +0000455{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400456 return mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000457}
458
Geoff Langb5348332014-09-02 13:16:34 -0400459Error TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset,
460 GLsizei width, GLsizei height, GLenum format,
Jamie Madillc751d1e2014-10-21 17:46:29 -0400461 GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000462{
Jamie Madillc751d1e2014-10-21 17:46:29 -0400463 return mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000464}
465
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000466// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
467bool TextureCubeMap::isCubeComplete() const
468{
Brandon Jones6053a522014-07-25 16:22:09 -0700469 int baseWidth = getBaseLevelWidth();
470 int baseHeight = getBaseLevelHeight();
471 GLenum baseFormat = getBaseLevelInternalFormat();
472
473 if (baseWidth <= 0 || baseWidth != baseHeight)
474 {
475 return false;
476 }
477
478 for (int faceIndex = 1; faceIndex < 6; faceIndex++)
479 {
480 const rx::Image *faceBaseImage = mTexture->getImage(0, faceIndex);
481
482 if (faceBaseImage->getWidth() != baseWidth ||
483 faceBaseImage->getHeight() != baseHeight ||
484 faceBaseImage->getInternalFormat() != baseFormat )
485 {
486 return false;
487 }
488 }
489
490 return true;
Jamie Madill07edd442013-07-19 16:36:58 -0400491}
492
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000493bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
494{
Geoff Lang5d601382014-07-22 15:14:06 -0400495 return GetInternalFormatInfo(getInternalFormat(target, level)).compressed;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000496}
497
Geoff Lang8040f572013-07-25 16:49:54 -0400498bool TextureCubeMap::isDepth(GLenum target, GLint level) const
499{
Geoff Lang5d601382014-07-22 15:14:06 -0400500 return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0;
Geoff Lang8040f572013-07-25 16:49:54 -0400501}
502
Geoff Langef7b0162014-09-04 13:29:23 -0400503Error TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y,
504 GLsizei width, GLsizei height, Framebuffer *source)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000505{
Geoff Langef7b0162014-09-04 13:29:23 -0400506 return mTexture->copyImage(target, level, format, x, y, width, height, source);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000507}
508
Geoff Lang1f8532b2014-09-05 09:46:13 -0400509Error TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000510{
Geoff Lang1f8532b2014-09-05 09:46:13 -0400511 Error error = mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1);
512 if (error.isError())
513 {
514 return error;
515 }
516
Jamie Madill6948e302014-10-20 17:04:33 -0400517 mImmutableLevelCount = levels;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000518
Geoff Lang1f8532b2014-09-05 09:46:13 -0400519 return Error(GL_NO_ERROR);
Jamie Madill2ebab852013-10-24 17:49:42 -0400520}
521
Brandon Jones6053a522014-07-25 16:22:09 -0700522// Tests for texture sampling completeness
Geoff Langf4134d22014-12-15 10:29:47 -0500523bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
Brandon Jones6053a522014-07-25 16:22:09 -0700524{
525 int size = getBaseLevelWidth();
526
527 bool mipmapping = IsMipmapFiltered(samplerState);
528
Geoff Langf4134d22014-12-15 10:29:47 -0500529 if (!data.textureCaps->get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable && !IsPointSampled(samplerState))
Brandon Jones6053a522014-07-25 16:22:09 -0700530 {
531 return false;
532 }
533
Geoff Langf4134d22014-12-15 10:29:47 -0500534 if (!gl::isPow2(size) && !data.extensions->textureNPOT)
Brandon Jones6053a522014-07-25 16:22:09 -0700535 {
536 if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
537 {
538 return false;
539 }
540 }
541
542 if (!mipmapping)
543 {
544 if (!isCubeComplete())
545 {
546 return false;
547 }
548 }
549 else
550 {
551 if (!isMipmapComplete()) // Also tests for isCubeComplete()
552 {
553 return false;
554 }
555 }
556
557 return true;
558}
559
Brandon Jonescef06ff2014-08-05 13:27:48 -0700560int TextureCubeMap::targetToLayerIndex(GLenum target)
561{
562 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
563 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
564 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
565 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
566 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
567
568 return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
569}
570
571GLenum TextureCubeMap::layerIndexToTarget(GLint layer)
572{
573 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
574 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
575 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
576 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
577 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
578
579 return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
Geoff Lang8040f572013-07-25 16:49:54 -0400580}
581
Brandon Jones6053a522014-07-25 16:22:09 -0700582bool TextureCubeMap::isMipmapComplete() const
583{
584 if (isImmutable())
585 {
586 return true;
587 }
588
589 if (!isCubeComplete())
590 {
591 return false;
592 }
593
594 int levelCount = mipLevels();
595
596 for (int face = 0; face < 6; face++)
597 {
598 for (int level = 1; level < levelCount; level++)
599 {
600 if (!isFaceLevelComplete(face, level))
601 {
602 return false;
603 }
604 }
605 }
606
607 return true;
608}
609
610bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const
611{
612 ASSERT(level >= 0 && faceIndex < 6 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, faceIndex) != NULL);
613
614 if (isImmutable())
615 {
616 return true;
617 }
618
619 int baseSize = getBaseLevelWidth();
620
621 if (baseSize <= 0)
622 {
623 return false;
624 }
625
626 // "isCubeComplete" checks for base level completeness and we must call that
627 // to determine if any face at level 0 is complete. We omit that check here
628 // to avoid re-checking cube-completeness for every face at level 0.
629 if (level == 0)
630 {
631 return true;
632 }
633
634 // Check that non-zero levels are consistent with the base level.
635 const rx::Image *faceLevelImage = mTexture->getImage(level, faceIndex);
636
637 if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
638 {
639 return false;
640 }
641
642 if (faceLevelImage->getWidth() != std::max(1, baseSize >> level))
643 {
644 return false;
645 }
646
647 return true;
648}
649
650
651Texture3D::Texture3D(rx::TextureImpl *impl, GLuint id)
652 : Texture(impl, id, GL_TEXTURE_3D)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000653{
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000654}
655
656Texture3D::~Texture3D()
657{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700658}
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000659
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000660GLsizei Texture3D::getWidth(GLint level) const
661{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700662 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getWidth() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000663}
664
665GLsizei Texture3D::getHeight(GLint level) const
666{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700667 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getHeight() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000668}
669
670GLsizei Texture3D::getDepth(GLint level) const
671{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700672 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getDepth() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000673}
674
675GLenum Texture3D::getInternalFormat(GLint level) const
676{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700677 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000678}
679
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000680bool Texture3D::isCompressed(GLint level) const
681{
Geoff Lang5d601382014-07-22 15:14:06 -0400682 return GetInternalFormatInfo(getInternalFormat(level)).compressed;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000683}
684
685bool Texture3D::isDepth(GLint level) const
686{
Geoff Lang5d601382014-07-22 15:14:06 -0400687 return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000688}
689
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400690Error 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 +0000691{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400692 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 +0000693}
694
Geoff Langb5348332014-09-02 13:16:34 -0400695Error Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
Jamie Madillc751d1e2014-10-21 17:46:29 -0400696 GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000697{
Jamie Madillc751d1e2014-10-21 17:46:29 -0400698 return mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, unpack, pixels);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000699}
700
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400701Error 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 +0000702{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400703 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 +0000704}
705
Geoff Langb5348332014-09-02 13:16:34 -0400706Error Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
707 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
Jamie Madillc751d1e2014-10-21 17:46:29 -0400708 GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000709{
Jamie Madillc751d1e2014-10-21 17:46:29 -0400710 return mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000711}
712
Geoff Lang1f8532b2014-09-05 09:46:13 -0400713Error Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000714{
Geoff Lang1f8532b2014-09-05 09:46:13 -0400715 Error error = mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth);
716 if (error.isError())
717 {
718 return error;
719 }
720
Jamie Madill6948e302014-10-20 17:04:33 -0400721 mImmutableLevelCount = levels;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000722
Geoff Lang1f8532b2014-09-05 09:46:13 -0400723 return Error(GL_NO_ERROR);
Jamie Madill2ebab852013-10-24 17:49:42 -0400724}
725
Geoff Langf4134d22014-12-15 10:29:47 -0500726bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
Brandon Jones6053a522014-07-25 16:22:09 -0700727{
728 GLsizei width = getBaseLevelWidth();
729 GLsizei height = getBaseLevelHeight();
730 GLsizei depth = getBaseLevelDepth();
731
732 if (width <= 0 || height <= 0 || depth <= 0)
733 {
734 return false;
735 }
736
Geoff Langf4134d22014-12-15 10:29:47 -0500737 if (!data.textureCaps->get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
Brandon Jones6053a522014-07-25 16:22:09 -0700738 {
739 return false;
740 }
741
742 if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
743 {
744 return false;
745 }
746
747 return true;
748}
749
Brandon Jones6053a522014-07-25 16:22:09 -0700750bool Texture3D::isMipmapComplete() const
751{
752 int levelCount = mipLevels();
753
754 for (int level = 0; level < levelCount; level++)
755 {
756 if (!isLevelComplete(level))
757 {
758 return false;
759 }
760 }
761
762 return true;
763}
764
765bool Texture3D::isLevelComplete(int level) const
766{
767 ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
768
769 if (isImmutable())
770 {
771 return true;
772 }
773
774 GLsizei width = getBaseLevelWidth();
775 GLsizei height = getBaseLevelHeight();
776 GLsizei depth = getBaseLevelDepth();
777
778 if (width <= 0 || height <= 0 || depth <= 0)
779 {
780 return false;
781 }
782
783 if (level == 0)
784 {
785 return true;
786 }
787
788 rx::Image *levelImage = mTexture->getImage(level, 0);
789
790 if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
791 {
792 return false;
793 }
794
795 if (levelImage->getWidth() != std::max(1, width >> level))
796 {
797 return false;
798 }
799
800 if (levelImage->getHeight() != std::max(1, height >> level))
801 {
802 return false;
803 }
804
805 if (levelImage->getDepth() != std::max(1, depth >> level))
806 {
807 return false;
808 }
809
810 return true;
811}
812
813Texture2DArray::Texture2DArray(rx::TextureImpl *impl, GLuint id)
814 : Texture(impl, id, GL_TEXTURE_2D_ARRAY)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000815{
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000816}
817
818Texture2DArray::~Texture2DArray()
819{
Jamie Madill884a4622013-10-24 17:49:41 -0400820}
821
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000822GLsizei Texture2DArray::getWidth(GLint level) const
823{
Brandon Jones142ec422014-07-16 10:31:30 -0700824 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 +0000825}
826
827GLsizei Texture2DArray::getHeight(GLint level) const
828{
Brandon Jones142ec422014-07-16 10:31:30 -0700829 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 +0000830}
831
Jamie Madillb8f8b892014-01-07 10:12:50 -0500832GLsizei Texture2DArray::getLayers(GLint level) const
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000833{
Brandon Jones142ec422014-07-16 10:31:30 -0700834 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getLayerCount(level) : 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000835}
836
837GLenum Texture2DArray::getInternalFormat(GLint level) const
838{
Brandon Jones142ec422014-07-16 10:31:30 -0700839 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 +0000840}
841
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000842bool Texture2DArray::isCompressed(GLint level) const
843{
Geoff Lang5d601382014-07-22 15:14:06 -0400844 return GetInternalFormatInfo(getInternalFormat(level)).compressed;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000845}
846
847bool Texture2DArray::isDepth(GLint level) const
848{
Geoff Lang5d601382014-07-22 15:14:06 -0400849 return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000850}
851
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400852Error 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 +0000853{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400854 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 +0000855}
856
Geoff Langb5348332014-09-02 13:16:34 -0400857Error Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
Jamie Madillc751d1e2014-10-21 17:46:29 -0400858 GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000859{
Jamie Madillc751d1e2014-10-21 17:46:29 -0400860 return mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, unpack, pixels);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000861}
862
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400863Error 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 +0000864{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400865 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 +0000866}
867
Geoff Langb5348332014-09-02 13:16:34 -0400868Error Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
869 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
Jamie Madillc751d1e2014-10-21 17:46:29 -0400870 GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000871{
Jamie Madillc751d1e2014-10-21 17:46:29 -0400872 return mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000873}
874
Geoff Lang1f8532b2014-09-05 09:46:13 -0400875Error Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000876{
Geoff Lang1f8532b2014-09-05 09:46:13 -0400877 Error error = mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth);
878 if (error.isError())
879 {
880 return error;
881 }
882
Jamie Madill6948e302014-10-20 17:04:33 -0400883 mImmutableLevelCount = levels;
Brandon Jones142ec422014-07-16 10:31:30 -0700884
Geoff Lang1f8532b2014-09-05 09:46:13 -0400885 return Error(GL_NO_ERROR);
Jamie Madill2ebab852013-10-24 17:49:42 -0400886}
887
Geoff Langf4134d22014-12-15 10:29:47 -0500888bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
Brandon Jones6053a522014-07-25 16:22:09 -0700889{
890 GLsizei width = getBaseLevelWidth();
891 GLsizei height = getBaseLevelHeight();
892 GLsizei depth = getLayers(0);
893
894 if (width <= 0 || height <= 0 || depth <= 0)
895 {
896 return false;
897 }
898
Geoff Langf4134d22014-12-15 10:29:47 -0500899 if (!data.textureCaps->get(getBaseLevelInternalFormat()).filterable && !IsPointSampled(samplerState))
Brandon Jones6053a522014-07-25 16:22:09 -0700900 {
901 return false;
902 }
903
904 if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
905 {
906 return false;
907 }
908
909 return true;
910}
911
Brandon Jones6053a522014-07-25 16:22:09 -0700912bool Texture2DArray::isMipmapComplete() const
913{
914 int levelCount = mipLevels();
915
916 for (int level = 1; level < levelCount; level++)
917 {
918 if (!isLevelComplete(level))
919 {
920 return false;
921 }
922 }
923
924 return true;
925}
926
927bool Texture2DArray::isLevelComplete(int level) const
928{
929 ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
930
931 if (isImmutable())
932 {
933 return true;
934 }
935
936 GLsizei width = getBaseLevelWidth();
937 GLsizei height = getBaseLevelHeight();
938 GLsizei layers = getLayers(0);
939
940 if (width <= 0 || height <= 0 || layers <= 0)
941 {
942 return false;
943 }
944
945 if (level == 0)
946 {
947 return true;
948 }
949
950 if (getInternalFormat(level) != getInternalFormat(0))
951 {
952 return false;
953 }
954
955 if (getWidth(level) != std::max(1, width >> level))
956 {
957 return false;
958 }
959
960 if (getHeight(level) != std::max(1, height >> level))
961 {
962 return false;
963 }
964
965 if (getLayers(level) != layers)
966 {
967 return false;
968 }
969
970 return true;
971}
972
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000973}