blob: bee0ef0ecb736dfba3df7b896e8dfcbefaafc70e [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
Jamie Madill10ef2152014-10-20 17:04:34 -0400127unsigned int Texture::getTextureSerial() const
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700128{
Jamie Madill10ef2152014-10-20 17:04:34 -0400129 return mTextureSerial;
130}
131
132unsigned int Texture::issueTextureSerial()
133{
134 return mCurrentTextureSerial++;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700135}
136
137bool Texture::isImmutable() const
138{
Jamie Madill6948e302014-10-20 17:04:33 -0400139 return (mImmutableLevelCount > 0);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700140}
141
142int Texture::immutableLevelCount()
143{
Jamie Madill6948e302014-10-20 17:04:33 -0400144 return mImmutableLevelCount;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700145}
146
147int Texture::mipLevels() const
148{
149 return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
150}
151
Brandon Jonescef06ff2014-08-05 13:27:48 -0700152const rx::Image *Texture::getBaseLevelImage() const
153{
154 return (getImplementation()->getLayerCount(0) > 0 ? getImplementation()->getImage(0, 0) : NULL);
155}
156
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500157Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
158 const PixelUnpackState &unpack, const uint8_t *pixels)
159{
160 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
161
162 Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels);
163 if (error.isError())
164 {
165 return error;
166 }
167
168 return Error(GL_NO_ERROR);
169}
170
171Error Texture::setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type,
172 const PixelUnpackState &unpack, const uint8_t *pixels)
173{
174 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
175
176 return mTexture->setSubImage(target, level, area, format, type, unpack, pixels);
177}
178
179Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size,
180 const PixelUnpackState &unpack, const uint8_t *pixels)
181{
182 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
183
184 Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels);
185 if (error.isError())
186 {
187 return error;
188 }
189
190 return Error(GL_NO_ERROR);
191}
192
193Error Texture::setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format,
194 const PixelUnpackState &unpack, const uint8_t *pixels)
195{
196 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
197
198 return mTexture->setCompressedSubImage(target, level, area, format, unpack, pixels);
199}
200
201Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat,
202 const Framebuffer *source)
203{
204 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
205
206 Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
207 if (error.isError())
208 {
209 return error;
210 }
211
212 return Error(GL_NO_ERROR);
213}
214
215Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea,
216 const Framebuffer *source)
217{
218 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
219
220 return mTexture->copySubImage(target, level, destOffset, sourceArea, source);
221}
222
223Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size)
224{
225 ASSERT(target == mTarget);
226
227 Error error = mTexture->setStorage(target, levels, internalFormat, size);
228 if (error.isError())
229 {
230 return error;
231 }
232
233 mImmutableLevelCount = levels;
234
235 return Error(GL_NO_ERROR);
236}
237
238
239Error Texture::generateMipmaps()
240{
241 Error error = mTexture->generateMipmaps();
242 if (error.isError())
243 {
244 return error;
245 }
246
247 return Error(GL_NO_ERROR);
248}
249
Brandon Jones6053a522014-07-25 16:22:09 -0700250Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id)
251 : Texture(impl, id, GL_TEXTURE_2D)
Jamie Madill22f843a2013-10-24 17:49:36 -0400252{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000253 mSurface = NULL;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000254}
255
256Texture2D::~Texture2D()
257{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000258 if (mSurface)
259 {
Jamie Madillfb0580a2014-11-27 14:03:52 -0500260 mSurface->releaseTexImage(EGL_BACK_BUFFER);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000261 mSurface = NULL;
262 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700263}
daniel@transgaming.comd9ec9022012-12-20 20:52:16 +0000264
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000265GLsizei Texture2D::getWidth(GLint level) const
266{
267 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700268 return mTexture->getImage(level, 0)->getWidth();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000269 else
270 return 0;
271}
272
273GLsizei Texture2D::getHeight(GLint level) const
274{
275 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700276 return mTexture->getImage(level, 0)->getHeight();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000277 else
278 return 0;
279}
280
281GLenum Texture2D::getInternalFormat(GLint level) const
282{
283 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700284 return mTexture->getImage(level, 0)->getInternalFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000285 else
286 return GL_NONE;
287}
288
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500289Error Texture2D::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
290 const PixelUnpackState &unpack, const uint8_t *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000291{
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500292 Error error = Texture::setImage(target, level, internalFormat, size, format, type, unpack, pixels);
293 if (error.isError())
294 {
295 return error;
296 }
297
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000298 releaseTexImage();
shannon.woods@transgaming.com8a406682013-02-28 23:15:26 +0000299
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500300 return Error(GL_NO_ERROR);
301}
302
303Error Texture2D::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size,
304 const PixelUnpackState &unpack, const uint8_t *pixels)
305{
306 Error error = Texture::setCompressedImage(target, level, internalFormat, size, unpack, pixels);
307 if (error.isError())
308 {
309 return error;
310 }
311
312 releaseTexImage();
313
314 return Error(GL_NO_ERROR);
315}
316
317Error Texture2D::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat,
318 const Framebuffer *source)
319{
320 Error error = Texture::copyImage(target, level, sourceArea, internalFormat, source);
321 if (error.isError())
322 {
323 return error;
324 }
325
326 releaseTexImage();
327
328 return Error(GL_NO_ERROR);
329}
330
331Error Texture2D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size)
332{
333 Error error = Texture::setStorage(target, levels, internalFormat, size);
334 if (error.isError())
335 {
336 return error;
337 }
338
339 releaseTexImage();
340
341 return Error(GL_NO_ERROR);
342}
343
344Error Texture2D::generateMipmaps()
345{
346 Error error = Texture::generateMipmaps();
347 if (error.isError())
348 {
349 return error;
350 }
351
352 releaseTexImage();
353
354 return Error(GL_NO_ERROR);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000355}
356
357void Texture2D::bindTexImage(egl::Surface *surface)
358{
359 releaseTexImage();
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700360 mTexture->bindTexImage(surface);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000361 mSurface = surface;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000362}
363
364void Texture2D::releaseTexImage()
365{
366 if (mSurface)
367 {
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000368 mSurface = NULL;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700369 mTexture->releaseTexImage();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000370 }
371}
372
Brandon Jones6053a522014-07-25 16:22:09 -0700373// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
Geoff Langf4134d22014-12-15 10:29:47 -0500374bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
Brandon Jones6053a522014-07-25 16:22:09 -0700375{
376 GLsizei width = getBaseLevelWidth();
377 GLsizei height = getBaseLevelHeight();
378
379 if (width <= 0 || height <= 0)
380 {
381 return false;
382 }
383
Geoff Langf4134d22014-12-15 10:29:47 -0500384 if (!data.textureCaps->get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
Brandon Jones6053a522014-07-25 16:22:09 -0700385 {
386 return false;
387 }
388
Geoff Langf4134d22014-12-15 10:29:47 -0500389 bool npotSupport = data.extensions->textureNPOT;
Brandon Jones6053a522014-07-25 16:22:09 -0700390 if (!npotSupport)
391 {
392 if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
393 (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
394 {
395 return false;
396 }
397 }
398
399 if (IsMipmapFiltered(samplerState))
400 {
401 if (!npotSupport)
402 {
403 if (!gl::isPow2(width) || !gl::isPow2(height))
404 {
405 return false;
406 }
407 }
408
409 if (!isMipmapComplete())
410 {
411 return false;
412 }
413 }
414
415 // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
416 // The internalformat specified for the texture arrays is a sized internal depth or
417 // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
418 // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
419 // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
420 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(0));
Geoff Langf4134d22014-12-15 10:29:47 -0500421 if (formatInfo.depthBits > 0 && data.clientVersion > 2)
Brandon Jones6053a522014-07-25 16:22:09 -0700422 {
423 if (samplerState.compareMode == GL_NONE)
424 {
425 if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
426 samplerState.magFilter != GL_NEAREST)
427 {
428 return false;
429 }
430 }
431 }
432
433 return true;
434}
435
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000436bool Texture2D::isCompressed(GLint level) const
437{
Geoff Lang5d601382014-07-22 15:14:06 -0400438 return GetInternalFormatInfo(getInternalFormat(level)).compressed;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000439}
440
441bool Texture2D::isDepth(GLint level) const
442{
Geoff Lang5d601382014-07-22 15:14:06 -0400443 return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000444}
445
Brandon Jones6053a522014-07-25 16:22:09 -0700446// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
447bool Texture2D::isMipmapComplete() const
448{
449 int levelCount = mipLevels();
450
451 for (int level = 0; level < levelCount; level++)
452 {
453 if (!isLevelComplete(level))
454 {
455 return false;
456 }
457 }
458
459 return true;
460}
461
462bool Texture2D::isLevelComplete(int level) const
463{
464 if (isImmutable())
465 {
466 return true;
467 }
468
469 const rx::Image *baseImage = getBaseLevelImage();
470
471 GLsizei width = baseImage->getWidth();
472 GLsizei height = baseImage->getHeight();
473
474 if (width <= 0 || height <= 0)
475 {
476 return false;
477 }
478
479 // The base image level is complete if the width and height are positive
480 if (level == 0)
481 {
482 return true;
483 }
484
485 ASSERT(level >= 1 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
486 rx::Image *image = mTexture->getImage(level, 0);
487
488 if (image->getInternalFormat() != baseImage->getInternalFormat())
489 {
490 return false;
491 }
492
493 if (image->getWidth() != std::max(1, width >> level))
494 {
495 return false;
496 }
497
498 if (image->getHeight() != std::max(1, height >> level))
499 {
500 return false;
501 }
502
503 return true;
504}
505
506TextureCubeMap::TextureCubeMap(rx::TextureImpl *impl, GLuint id)
507 : Texture(impl, id, GL_TEXTURE_CUBE_MAP)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000508{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000509}
510
511TextureCubeMap::~TextureCubeMap()
512{
Brandon Jones0511e802014-07-14 16:27:26 -0700513}
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000514
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000515GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
516{
517 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700518 return mTexture->getImage(level, targetToLayerIndex(target))->getWidth();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000519 else
520 return 0;
521}
522
523GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
524{
525 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700526 return mTexture->getImage(level, targetToLayerIndex(target))->getHeight();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000527 else
528 return 0;
529}
530
531GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
532{
533 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -0700534 return mTexture->getImage(level, targetToLayerIndex(target))->getInternalFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000535 else
536 return GL_NONE;
537}
538
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000539// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
540bool TextureCubeMap::isCubeComplete() const
541{
Brandon Jones6053a522014-07-25 16:22:09 -0700542 int baseWidth = getBaseLevelWidth();
543 int baseHeight = getBaseLevelHeight();
544 GLenum baseFormat = getBaseLevelInternalFormat();
545
546 if (baseWidth <= 0 || baseWidth != baseHeight)
547 {
548 return false;
549 }
550
551 for (int faceIndex = 1; faceIndex < 6; faceIndex++)
552 {
553 const rx::Image *faceBaseImage = mTexture->getImage(0, faceIndex);
554
555 if (faceBaseImage->getWidth() != baseWidth ||
556 faceBaseImage->getHeight() != baseHeight ||
557 faceBaseImage->getInternalFormat() != baseFormat )
558 {
559 return false;
560 }
561 }
562
563 return true;
Jamie Madill07edd442013-07-19 16:36:58 -0400564}
565
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000566bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
567{
Geoff Lang5d601382014-07-22 15:14:06 -0400568 return GetInternalFormatInfo(getInternalFormat(target, level)).compressed;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000569}
570
Geoff Lang8040f572013-07-25 16:49:54 -0400571bool TextureCubeMap::isDepth(GLenum target, GLint level) const
572{
Geoff Lang5d601382014-07-22 15:14:06 -0400573 return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0;
Geoff Lang8040f572013-07-25 16:49:54 -0400574}
575
Brandon Jones6053a522014-07-25 16:22:09 -0700576// Tests for texture sampling completeness
Geoff Langf4134d22014-12-15 10:29:47 -0500577bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
Brandon Jones6053a522014-07-25 16:22:09 -0700578{
579 int size = getBaseLevelWidth();
580
581 bool mipmapping = IsMipmapFiltered(samplerState);
582
Geoff Langf4134d22014-12-15 10:29:47 -0500583 if (!data.textureCaps->get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable && !IsPointSampled(samplerState))
Brandon Jones6053a522014-07-25 16:22:09 -0700584 {
585 return false;
586 }
587
Geoff Langf4134d22014-12-15 10:29:47 -0500588 if (!gl::isPow2(size) && !data.extensions->textureNPOT)
Brandon Jones6053a522014-07-25 16:22:09 -0700589 {
590 if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
591 {
592 return false;
593 }
594 }
595
596 if (!mipmapping)
597 {
598 if (!isCubeComplete())
599 {
600 return false;
601 }
602 }
603 else
604 {
605 if (!isMipmapComplete()) // Also tests for isCubeComplete()
606 {
607 return false;
608 }
609 }
610
611 return true;
612}
613
Brandon Jonescef06ff2014-08-05 13:27:48 -0700614int TextureCubeMap::targetToLayerIndex(GLenum target)
615{
616 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
617 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
618 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
619 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
620 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
621
622 return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
623}
624
625GLenum TextureCubeMap::layerIndexToTarget(GLint layer)
626{
627 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
628 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
629 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
630 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
631 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
632
633 return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
Geoff Lang8040f572013-07-25 16:49:54 -0400634}
635
Brandon Jones6053a522014-07-25 16:22:09 -0700636bool TextureCubeMap::isMipmapComplete() const
637{
638 if (isImmutable())
639 {
640 return true;
641 }
642
643 if (!isCubeComplete())
644 {
645 return false;
646 }
647
648 int levelCount = mipLevels();
649
650 for (int face = 0; face < 6; face++)
651 {
652 for (int level = 1; level < levelCount; level++)
653 {
654 if (!isFaceLevelComplete(face, level))
655 {
656 return false;
657 }
658 }
659 }
660
661 return true;
662}
663
664bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const
665{
666 ASSERT(level >= 0 && faceIndex < 6 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, faceIndex) != NULL);
667
668 if (isImmutable())
669 {
670 return true;
671 }
672
673 int baseSize = getBaseLevelWidth();
674
675 if (baseSize <= 0)
676 {
677 return false;
678 }
679
680 // "isCubeComplete" checks for base level completeness and we must call that
681 // to determine if any face at level 0 is complete. We omit that check here
682 // to avoid re-checking cube-completeness for every face at level 0.
683 if (level == 0)
684 {
685 return true;
686 }
687
688 // Check that non-zero levels are consistent with the base level.
689 const rx::Image *faceLevelImage = mTexture->getImage(level, faceIndex);
690
691 if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
692 {
693 return false;
694 }
695
696 if (faceLevelImage->getWidth() != std::max(1, baseSize >> level))
697 {
698 return false;
699 }
700
701 return true;
702}
703
704
705Texture3D::Texture3D(rx::TextureImpl *impl, GLuint id)
706 : Texture(impl, id, GL_TEXTURE_3D)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000707{
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000708}
709
710Texture3D::~Texture3D()
711{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700712}
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000713
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000714GLsizei Texture3D::getWidth(GLint level) const
715{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700716 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getWidth() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000717}
718
719GLsizei Texture3D::getHeight(GLint level) const
720{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700721 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getHeight() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000722}
723
724GLsizei Texture3D::getDepth(GLint level) const
725{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700726 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getDepth() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000727}
728
729GLenum Texture3D::getInternalFormat(GLint level) const
730{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700731 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000732}
733
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000734bool Texture3D::isCompressed(GLint level) const
735{
Geoff Lang5d601382014-07-22 15:14:06 -0400736 return GetInternalFormatInfo(getInternalFormat(level)).compressed;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000737}
738
739bool Texture3D::isDepth(GLint level) const
740{
Geoff Lang5d601382014-07-22 15:14:06 -0400741 return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000742}
743
Geoff Langf4134d22014-12-15 10:29:47 -0500744bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
Brandon Jones6053a522014-07-25 16:22:09 -0700745{
746 GLsizei width = getBaseLevelWidth();
747 GLsizei height = getBaseLevelHeight();
748 GLsizei depth = getBaseLevelDepth();
749
750 if (width <= 0 || height <= 0 || depth <= 0)
751 {
752 return false;
753 }
754
Geoff Langf4134d22014-12-15 10:29:47 -0500755 if (!data.textureCaps->get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
Brandon Jones6053a522014-07-25 16:22:09 -0700756 {
757 return false;
758 }
759
760 if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
761 {
762 return false;
763 }
764
765 return true;
766}
767
Brandon Jones6053a522014-07-25 16:22:09 -0700768bool Texture3D::isMipmapComplete() const
769{
770 int levelCount = mipLevels();
771
772 for (int level = 0; level < levelCount; level++)
773 {
774 if (!isLevelComplete(level))
775 {
776 return false;
777 }
778 }
779
780 return true;
781}
782
783bool Texture3D::isLevelComplete(int level) const
784{
785 ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
786
787 if (isImmutable())
788 {
789 return true;
790 }
791
792 GLsizei width = getBaseLevelWidth();
793 GLsizei height = getBaseLevelHeight();
794 GLsizei depth = getBaseLevelDepth();
795
796 if (width <= 0 || height <= 0 || depth <= 0)
797 {
798 return false;
799 }
800
801 if (level == 0)
802 {
803 return true;
804 }
805
806 rx::Image *levelImage = mTexture->getImage(level, 0);
807
808 if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
809 {
810 return false;
811 }
812
813 if (levelImage->getWidth() != std::max(1, width >> level))
814 {
815 return false;
816 }
817
818 if (levelImage->getHeight() != std::max(1, height >> level))
819 {
820 return false;
821 }
822
823 if (levelImage->getDepth() != std::max(1, depth >> level))
824 {
825 return false;
826 }
827
828 return true;
829}
830
831Texture2DArray::Texture2DArray(rx::TextureImpl *impl, GLuint id)
832 : Texture(impl, id, GL_TEXTURE_2D_ARRAY)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000833{
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000834}
835
836Texture2DArray::~Texture2DArray()
837{
Jamie Madill884a4622013-10-24 17:49:41 -0400838}
839
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000840GLsizei Texture2DArray::getWidth(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)->getWidth() : 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000843}
844
845GLsizei Texture2DArray::getHeight(GLint level) const
846{
Brandon Jones142ec422014-07-16 10:31:30 -0700847 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 +0000848}
849
Jamie Madillb8f8b892014-01-07 10:12:50 -0500850GLsizei Texture2DArray::getLayers(GLint level) const
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000851{
Brandon Jones142ec422014-07-16 10:31:30 -0700852 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getLayerCount(level) : 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000853}
854
855GLenum Texture2DArray::getInternalFormat(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)->getInternalFormat() : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000858}
859
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000860bool 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 Langf4134d22014-12-15 10:29:47 -0500870bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
Brandon Jones6053a522014-07-25 16:22:09 -0700871{
872 GLsizei width = getBaseLevelWidth();
873 GLsizei height = getBaseLevelHeight();
874 GLsizei depth = getLayers(0);
875
876 if (width <= 0 || height <= 0 || depth <= 0)
877 {
878 return false;
879 }
880
Geoff Langf4134d22014-12-15 10:29:47 -0500881 if (!data.textureCaps->get(getBaseLevelInternalFormat()).filterable && !IsPointSampled(samplerState))
Brandon Jones6053a522014-07-25 16:22:09 -0700882 {
883 return false;
884 }
885
886 if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
887 {
888 return false;
889 }
890
891 return true;
892}
893
Brandon Jones6053a522014-07-25 16:22:09 -0700894bool Texture2DArray::isMipmapComplete() const
895{
896 int levelCount = mipLevels();
897
898 for (int level = 1; level < levelCount; level++)
899 {
900 if (!isLevelComplete(level))
901 {
902 return false;
903 }
904 }
905
906 return true;
907}
908
909bool Texture2DArray::isLevelComplete(int level) const
910{
911 ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
912
913 if (isImmutable())
914 {
915 return true;
916 }
917
918 GLsizei width = getBaseLevelWidth();
919 GLsizei height = getBaseLevelHeight();
920 GLsizei layers = getLayers(0);
921
922 if (width <= 0 || height <= 0 || layers <= 0)
923 {
924 return false;
925 }
926
927 if (level == 0)
928 {
929 return true;
930 }
931
932 if (getInternalFormat(level) != getInternalFormat(0))
933 {
934 return false;
935 }
936
937 if (getWidth(level) != std::max(1, width >> level))
938 {
939 return false;
940 }
941
942 if (getHeight(level) != std::max(1, height >> level))
943 {
944 return false;
945 }
946
947 if (getLayers(level) != layers)
948 {
949 return false;
950 }
951
952 return true;
953}
954
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000955}