blob: a311485aec47b280365b30bf35f4c1eaaa1f1737 [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
Geoff Lang691e58c2014-12-19 17:03:25 -05007// Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63.
daniel@transgaming.com95a758f2012-07-12 15:17:06 +00008
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/Texture.h"
Geoff Langb4dedf32015-01-05 14:08:53 -050010#include "libANGLE/Data.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/formatutils.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040012
Geoff Langb9266272015-01-29 13:25:14 +000013#include "libANGLE/Config.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Surface.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040015
16#include "common/mathutil.h"
17#include "common/utilities.h"
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000018
19namespace gl
20{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000021
Brandon Jones6053a522014-07-25 16:22:09 -070022bool IsMipmapFiltered(const gl::SamplerState &samplerState)
23{
24 switch (samplerState.minFilter)
25 {
26 case GL_NEAREST:
27 case GL_LINEAR:
28 return false;
29 case GL_NEAREST_MIPMAP_NEAREST:
30 case GL_LINEAR_MIPMAP_NEAREST:
31 case GL_NEAREST_MIPMAP_LINEAR:
32 case GL_LINEAR_MIPMAP_LINEAR:
33 return true;
34 default: UNREACHABLE();
35 return false;
36 }
37}
38
39bool IsPointSampled(const gl::SamplerState &samplerState)
40{
41 return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
42}
43
Geoff Lang866dd2d2015-02-10 11:08:32 -050044static size_t GetImageDescIndex(GLenum target, size_t level)
45{
46 return IsCubeMapTextureTarget(target) ? ((level * 6) + CubeMapTextureTargetToLayerIndex(target)) : level;
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),
Geoff Lang7c973ea2014-12-19 15:58:28 -050057 mTarget(target),
Geoff Lang866dd2d2015-02-10 11:08:32 -050058 mImageDescs(IMPLEMENTATION_MAX_TEXTURE_LEVELS * (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)),
Geoff Lang7c973ea2014-12-19 15:58:28 -050059 mBoundSurface(NULL)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000060{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000061}
62
63Texture::~Texture()
64{
Geoff Lang7c973ea2014-12-19 15:58:28 -050065 if (mBoundSurface)
66 {
67 mBoundSurface->releaseTexImage(EGL_BACK_BUFFER);
68 mBoundSurface = NULL;
69 }
Brandon Jones6053a522014-07-25 16:22:09 -070070 SafeDelete(mTexture);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000071}
72
Geoff Lang4907f2c2013-07-25 12:53:57 -040073GLenum Texture::getTarget() const
74{
75 return mTarget;
76}
77
Geoff Lang63b5f1f2013-09-23 14:52:14 -040078void Texture::setUsage(GLenum usage)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000079{
Geoff Lang63b5f1f2013-09-23 14:52:14 -040080 mUsage = usage;
Brandon Jonescef06ff2014-08-05 13:27:48 -070081 getImplementation()->setUsage(usage);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000082}
83
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000084GLenum Texture::getUsage() const
85{
86 return mUsage;
87}
88
Geoff Langa9be0dc2014-12-17 12:34:40 -050089size_t Texture::getWidth(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -040090{
Geoff Lang691e58c2014-12-19 17:03:25 -050091 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang866dd2d2015-02-10 11:08:32 -050092 return getImageDesc(target, level).size.width;
Jamie Madilld3d2a342013-10-07 10:46:35 -040093}
94
Geoff Langa9be0dc2014-12-17 12:34:40 -050095size_t Texture::getHeight(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -040096{
Geoff Lang691e58c2014-12-19 17:03:25 -050097 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang866dd2d2015-02-10 11:08:32 -050098 return getImageDesc(target, level).size.height;
Jamie Madilld3d2a342013-10-07 10:46:35 -040099}
100
Geoff Langa9be0dc2014-12-17 12:34:40 -0500101size_t Texture::getDepth(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -0400102{
Geoff Lang691e58c2014-12-19 17:03:25 -0500103 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang866dd2d2015-02-10 11:08:32 -0500104 return getImageDesc(target, level).size.depth;
Jamie Madilld3d2a342013-10-07 10:46:35 -0400105}
106
Geoff Langa9be0dc2014-12-17 12:34:40 -0500107GLenum Texture::getInternalFormat(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -0400108{
Geoff Lang691e58c2014-12-19 17:03:25 -0500109 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang866dd2d2015-02-10 11:08:32 -0500110 return getImageDesc(target, level).internalFormat;
Jamie Madill945f7322014-09-03 15:07:14 -0400111}
112
Geoff Lang691e58c2014-12-19 17:03:25 -0500113bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
114{
115 GLenum baseTarget = getBaseImageTarget();
Jamie Madill19d438d2015-01-19 13:42:12 -0500116 size_t width = getWidth(baseTarget, samplerState.baseLevel);
117 size_t height = getHeight(baseTarget, samplerState.baseLevel);
118 size_t depth = getDepth(baseTarget, samplerState.baseLevel);
Geoff Lang691e58c2014-12-19 17:03:25 -0500119 if (width == 0 || height == 0 || depth == 0)
120 {
121 return false;
122 }
123
124 if (mTarget == GL_TEXTURE_CUBE_MAP && width != height)
125 {
126 return false;
127 }
128
Jamie Madill19d438d2015-01-19 13:42:12 -0500129 GLenum internalFormat = getInternalFormat(baseTarget, samplerState.baseLevel);
Geoff Lang691e58c2014-12-19 17:03:25 -0500130 const TextureCaps &textureCaps = data.textureCaps->get(internalFormat);
131 if (!textureCaps.filterable && !IsPointSampled(samplerState))
132 {
133 return false;
134 }
135
136 bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3;
137 if (!npotSupport)
138 {
139 if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
140 (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
141 {
142 return false;
143 }
144 }
145
146 if (IsMipmapFiltered(samplerState))
147 {
148 if (!npotSupport)
149 {
150 if (!gl::isPow2(width) || !gl::isPow2(height))
151 {
152 return false;
153 }
154 }
155
Jamie Madill19d438d2015-01-19 13:42:12 -0500156 if (!isMipmapComplete(samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500157 {
158 return false;
159 }
160 }
161 else
162 {
163 if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
164 {
165 return false;
166 }
167 }
168
169 // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
170 // The internalformat specified for the texture arrays is a sized internal depth or
171 // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
172 // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
173 // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
174 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
175 if (formatInfo.depthBits > 0 && data.clientVersion > 2)
176 {
177 if (samplerState.compareMode == GL_NONE)
178 {
179 if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
180 samplerState.magFilter != GL_NEAREST)
181 {
182 return false;
183 }
184 }
185 }
186
187 return true;
188}
189
190// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
191bool Texture::isCubeComplete() const
192{
193 ASSERT(mTarget == GL_TEXTURE_CUBE_MAP);
194
195 GLenum baseTarget = FirstCubeMapTextureTarget;
196 size_t width = getWidth(baseTarget, 0);
197 size_t height = getWidth(baseTarget, 0);
198 if (width == 0 || width != height)
199 {
200 return false;
201 }
202
203 GLenum internalFormat = getInternalFormat(baseTarget, 0);
204 for (GLenum face = baseTarget + 1; face <= LastCubeMapTextureTarget; face++)
205 {
206 if (getWidth(face, 0) != width ||
207 getHeight(face, 0) != height ||
208 getInternalFormat(face, 0) != internalFormat)
209 {
210 return false;
211 }
212 }
213
214 return true;
215}
216
Jamie Madill10ef2152014-10-20 17:04:34 -0400217unsigned int Texture::getTextureSerial() const
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700218{
Jamie Madill10ef2152014-10-20 17:04:34 -0400219 return mTextureSerial;
220}
221
222unsigned int Texture::issueTextureSerial()
223{
224 return mCurrentTextureSerial++;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700225}
226
227bool Texture::isImmutable() const
228{
Jamie Madill6948e302014-10-20 17:04:33 -0400229 return (mImmutableLevelCount > 0);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700230}
231
232int Texture::immutableLevelCount()
233{
Jamie Madill6948e302014-10-20 17:04:33 -0400234 return mImmutableLevelCount;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700235}
236
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500237Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
238 const PixelUnpackState &unpack, const uint8_t *pixels)
239{
Geoff Lang691e58c2014-12-19 17:03:25 -0500240 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500241
242 Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels);
243 if (error.isError())
244 {
245 return error;
246 }
247
Geoff Lang7c973ea2014-12-19 15:58:28 -0500248 releaseTexImage();
249
Geoff Lang866dd2d2015-02-10 11:08:32 -0500250 setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500251
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500252 return Error(GL_NO_ERROR);
253}
254
255Error Texture::setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type,
256 const PixelUnpackState &unpack, const uint8_t *pixels)
257{
Geoff Lang691e58c2014-12-19 17:03:25 -0500258 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500259
260 return mTexture->setSubImage(target, level, area, format, type, unpack, pixels);
261}
262
263Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size,
264 const PixelUnpackState &unpack, const uint8_t *pixels)
265{
Geoff Lang691e58c2014-12-19 17:03:25 -0500266 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500267
268 Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels);
269 if (error.isError())
270 {
271 return error;
272 }
273
Geoff Lang7c973ea2014-12-19 15:58:28 -0500274 releaseTexImage();
275
Geoff Lang866dd2d2015-02-10 11:08:32 -0500276 setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500277
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500278 return Error(GL_NO_ERROR);
279}
280
281Error Texture::setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format,
282 const PixelUnpackState &unpack, const uint8_t *pixels)
283{
Geoff Lang691e58c2014-12-19 17:03:25 -0500284 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500285
286 return mTexture->setCompressedSubImage(target, level, area, format, unpack, pixels);
287}
288
289Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat,
290 const Framebuffer *source)
291{
Geoff Lang691e58c2014-12-19 17:03:25 -0500292 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500293
294 Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
295 if (error.isError())
296 {
297 return error;
298 }
299
Geoff Lang7c973ea2014-12-19 15:58:28 -0500300 releaseTexImage();
301
Geoff Lang866dd2d2015-02-10 11:08:32 -0500302 setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
303 GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500304
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500305 return Error(GL_NO_ERROR);
306}
307
308Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea,
309 const Framebuffer *source)
310{
Geoff Lang691e58c2014-12-19 17:03:25 -0500311 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500312
313 return mTexture->copySubImage(target, level, destOffset, sourceArea, source);
314}
315
316Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size)
317{
318 ASSERT(target == mTarget);
319
320 Error error = mTexture->setStorage(target, levels, internalFormat, size);
321 if (error.isError())
322 {
323 return error;
324 }
325
Geoff Lang7c973ea2014-12-19 15:58:28 -0500326 releaseTexImage();
327
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500328 mImmutableLevelCount = levels;
Geoff Langa9be0dc2014-12-17 12:34:40 -0500329 clearImageDescs();
330 setImageDescChain(levels, size, internalFormat);
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500331
332 return Error(GL_NO_ERROR);
333}
334
335
336Error Texture::generateMipmaps()
337{
338 Error error = mTexture->generateMipmaps();
339 if (error.isError())
340 {
341 return error;
342 }
343
Geoff Lang7c973ea2014-12-19 15:58:28 -0500344 releaseTexImage();
345
Geoff Lang866dd2d2015-02-10 11:08:32 -0500346 const ImageDesc &baseImageInfo = getImageDesc(getBaseImageTarget(), 0);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500347 size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1;
348 setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat);
349
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500350 return Error(GL_NO_ERROR);
351}
352
Geoff Langa9be0dc2014-12-17 12:34:40 -0500353void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat)
354{
355 for (size_t level = 0; level < levels; level++)
356 {
357 Extents levelSize(std::max<size_t>(baseSize.width >> level, 1),
358 std::max<size_t>(baseSize.height >> level, 1),
359 (mTarget == GL_TEXTURE_2D_ARRAY) ? baseSize.depth : std::max<size_t>(baseSize.depth >> level, 1));
360 ImageDesc levelInfo(levelSize, sizedInternalFormat);
361
362 if (mTarget == GL_TEXTURE_CUBE_MAP)
363 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500364 for (size_t face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500365 {
Geoff Lang866dd2d2015-02-10 11:08:32 -0500366 setImageDesc(face, level, levelInfo);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500367 }
368 }
369 else
370 {
Geoff Lang866dd2d2015-02-10 11:08:32 -0500371 setImageDesc(mTarget, level, levelInfo);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500372 }
373 }
374}
375
Geoff Langa9be0dc2014-12-17 12:34:40 -0500376Texture::ImageDesc::ImageDesc()
377 : ImageDesc(Extents(0, 0, 0), GL_NONE)
378{
379}
380
381Texture::ImageDesc::ImageDesc(const Extents &size, GLenum internalFormat)
382 : size(size),
383 internalFormat(internalFormat)
384{
385}
386
Geoff Lang866dd2d2015-02-10 11:08:32 -0500387const Texture::ImageDesc &Texture::getImageDesc(GLenum target, size_t level) const
Geoff Langa9be0dc2014-12-17 12:34:40 -0500388{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500389 size_t descIndex = GetImageDescIndex(target, level);
390 ASSERT(descIndex < mImageDescs.size());
391 return mImageDescs[descIndex];
Geoff Langa9be0dc2014-12-17 12:34:40 -0500392}
393
Geoff Lang866dd2d2015-02-10 11:08:32 -0500394void Texture::setImageDesc(GLenum target, size_t level, const ImageDesc &desc)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500395{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500396 size_t descIndex = GetImageDescIndex(target, level);
397 ASSERT(descIndex < mImageDescs.size());
398 mImageDescs[descIndex] = desc;
Geoff Langa9be0dc2014-12-17 12:34:40 -0500399}
400
Geoff Lang866dd2d2015-02-10 11:08:32 -0500401void Texture::clearImageDesc(GLenum target, size_t level)
Geoff Langb9266272015-01-29 13:25:14 +0000402{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500403 setImageDesc(target, level, ImageDesc());
Geoff Langb9266272015-01-29 13:25:14 +0000404}
405
Geoff Langa9be0dc2014-12-17 12:34:40 -0500406void Texture::clearImageDescs()
407{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500408 for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
409 {
410 mImageDescs[descIndex] = ImageDesc();
411 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500412}
413
Geoff Lang7c973ea2014-12-19 15:58:28 -0500414void Texture::bindTexImage(egl::Surface *surface)
415{
Geoff Langb9266272015-01-29 13:25:14 +0000416 ASSERT(surface);
417
Geoff Lang7c973ea2014-12-19 15:58:28 -0500418 releaseTexImage();
419 mTexture->bindTexImage(surface);
420 mBoundSurface = surface;
Geoff Langb9266272015-01-29 13:25:14 +0000421
422 // Set the image info to the size and format of the surface
423 ASSERT(mTarget == GL_TEXTURE_2D);
424 Extents size(surface->getWidth(), surface->getHeight(), 1);
Geoff Langc223dc62015-01-09 13:10:01 -0500425 ImageDesc desc(size, surface->getConfig()->renderTargetFormat);
Geoff Lang866dd2d2015-02-10 11:08:32 -0500426 setImageDesc(mTarget, 0, desc);
Geoff Lang7c973ea2014-12-19 15:58:28 -0500427}
428
429void Texture::releaseTexImage()
430{
431 if (mBoundSurface)
432 {
433 mBoundSurface = NULL;
434 mTexture->releaseTexImage();
Geoff Langb9266272015-01-29 13:25:14 +0000435
436 // Erase the image info for level 0
437 ASSERT(mTarget == GL_TEXTURE_2D);
Geoff Lang866dd2d2015-02-10 11:08:32 -0500438 clearImageDesc(mTarget, 0);
Geoff Lang7c973ea2014-12-19 15:58:28 -0500439 }
440}
441
Geoff Lang691e58c2014-12-19 17:03:25 -0500442GLenum Texture::getBaseImageTarget() const
Jamie Madill22f843a2013-10-24 17:49:36 -0400443{
Geoff Lang691e58c2014-12-19 17:03:25 -0500444 return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000445}
446
Geoff Lang691e58c2014-12-19 17:03:25 -0500447size_t Texture::getExpectedMipLevels() const
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000448{
Geoff Lang691e58c2014-12-19 17:03:25 -0500449 GLenum baseTarget = getBaseImageTarget();
450 size_t width = getWidth(baseTarget, 0);
451 size_t height = getHeight(baseTarget, 0);
452 if (mTarget == GL_TEXTURE_3D)
453 {
454 size_t depth = getDepth(baseTarget, 0);
455 return log2(std::max(std::max(width, height), depth)) + 1;
456 }
457 else
458 {
459 return log2(std::max(width, height)) + 1;
460 }
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000461}
462
Jamie Madill19d438d2015-01-19 13:42:12 -0500463bool Texture::isMipmapComplete(const gl::SamplerState &samplerState) const
Brandon Jones6053a522014-07-25 16:22:09 -0700464{
Geoff Lang691e58c2014-12-19 17:03:25 -0500465 size_t expectedMipLevels = getExpectedMipLevels();
Jamie Madill19d438d2015-01-19 13:42:12 -0500466
467 size_t maxLevel = std::min<size_t>(expectedMipLevels, samplerState.maxLevel + 1);
468
469 for (size_t level = samplerState.baseLevel; level < maxLevel; level++)
Brandon Jones6053a522014-07-25 16:22:09 -0700470 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500471 if (mTarget == GL_TEXTURE_CUBE_MAP)
Brandon Jones6053a522014-07-25 16:22:09 -0700472 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500473 for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
474 {
Jamie Madill19d438d2015-01-19 13:42:12 -0500475 if (!isLevelComplete(face, level, samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500476 {
477 return false;
478 }
479 }
480 }
481 else
482 {
Jamie Madill19d438d2015-01-19 13:42:12 -0500483 if (!isLevelComplete(mTarget, level, samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500484 {
485 return false;
486 }
Brandon Jones6053a522014-07-25 16:22:09 -0700487 }
488 }
489
490 return true;
491}
492
Geoff Lang691e58c2014-12-19 17:03:25 -0500493
Jamie Madill19d438d2015-01-19 13:42:12 -0500494bool Texture::isLevelComplete(GLenum target, size_t level,
495 const gl::SamplerState &samplerState) const
Brandon Jones6053a522014-07-25 16:22:09 -0700496{
Geoff Langa9be0dc2014-12-17 12:34:40 -0500497 ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
498
Brandon Jones6053a522014-07-25 16:22:09 -0700499 if (isImmutable())
500 {
501 return true;
502 }
503
Jamie Madill19d438d2015-01-19 13:42:12 -0500504 size_t width = getWidth(target, samplerState.baseLevel);
505 size_t height = getHeight(target, samplerState.baseLevel);
Jamie Madill448d3db2015-01-28 16:51:10 -0500506 size_t depth = getDepth(target, samplerState.baseLevel);
Geoff Lang691e58c2014-12-19 17:03:25 -0500507 if (width == 0 || height == 0 || depth == 0)
Brandon Jones6053a522014-07-25 16:22:09 -0700508 {
509 return false;
510 }
511
512 // The base image level is complete if the width and height are positive
513 if (level == 0)
514 {
515 return true;
516 }
517
Jamie Madill19d438d2015-01-19 13:42:12 -0500518 if (getInternalFormat(target, level) != getInternalFormat(target, samplerState.baseLevel))
Brandon Jones6053a522014-07-25 16:22:09 -0700519 {
520 return false;
521 }
522
Geoff Lang691e58c2014-12-19 17:03:25 -0500523 if (getWidth(target, level) != std::max<size_t>(1, width >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700524 {
525 return false;
526 }
527
Geoff Lang691e58c2014-12-19 17:03:25 -0500528 if (getHeight(target, level) != std::max<size_t>(1, height >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700529 {
530 return false;
531 }
532
Geoff Lang691e58c2014-12-19 17:03:25 -0500533 if (mTarget == GL_TEXTURE_3D)
Brandon Jones6053a522014-07-25 16:22:09 -0700534 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500535 if (getDepth(target, level) != std::max<size_t>(1, depth >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700536 {
537 return false;
538 }
539 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500540 else if (mTarget == GL_TEXTURE_2D_ARRAY)
Brandon Jones6053a522014-07-25 16:22:09 -0700541 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500542 if (getDepth(target, level) != depth)
Brandon Jones6053a522014-07-25 16:22:09 -0700543 {
544 return false;
545 }
546 }
547
548 return true;
549}
550
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000551}