blob: 90b8c41f5d645cd2f6365933570e2fe9255b9fdf [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 Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/Surface.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040014
15#include "common/mathutil.h"
16#include "common/utilities.h"
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000017
18namespace gl
19{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000020
Brandon Jones6053a522014-07-25 16:22:09 -070021bool IsMipmapFiltered(const gl::SamplerState &samplerState)
22{
23 switch (samplerState.minFilter)
24 {
25 case GL_NEAREST:
26 case GL_LINEAR:
27 return false;
28 case GL_NEAREST_MIPMAP_NEAREST:
29 case GL_LINEAR_MIPMAP_NEAREST:
30 case GL_NEAREST_MIPMAP_LINEAR:
31 case GL_LINEAR_MIPMAP_LINEAR:
32 return true;
33 default: UNREACHABLE();
34 return false;
35 }
36}
37
38bool IsPointSampled(const gl::SamplerState &samplerState)
39{
40 return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
41}
42
Jamie Madill10ef2152014-10-20 17:04:34 -040043unsigned int Texture::mCurrentTextureSerial = 1;
44
Brandon Jones6053a522014-07-25 16:22:09 -070045Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
Brandon Jonesf47bebc2014-07-09 14:28:42 -070046 : RefCountObject(id),
Brandon Jones6053a522014-07-25 16:22:09 -070047 mTexture(impl),
Jamie Madill10ef2152014-10-20 17:04:34 -040048 mTextureSerial(issueTextureSerial()),
Brandon Jonesf47bebc2014-07-09 14:28:42 -070049 mUsage(GL_NONE),
Jamie Madill6948e302014-10-20 17:04:33 -040050 mImmutableLevelCount(0),
Geoff Lang7c973ea2014-12-19 15:58:28 -050051 mTarget(target),
52 mBoundSurface(NULL)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000053{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000054}
55
56Texture::~Texture()
57{
Geoff Lang7c973ea2014-12-19 15:58:28 -050058 if (mBoundSurface)
59 {
60 mBoundSurface->releaseTexImage(EGL_BACK_BUFFER);
61 mBoundSurface = NULL;
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
Geoff Langa9be0dc2014-12-17 12:34:40 -050082size_t Texture::getWidth(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -040083{
Geoff Lang691e58c2014-12-19 17:03:25 -050084 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang909b90c2015-01-12 14:07:26 -050085 return getImageDesc(ImageIndex::MakeGeneric(target, level)).size.width;
Jamie Madilld3d2a342013-10-07 10:46:35 -040086}
87
Geoff Langa9be0dc2014-12-17 12:34:40 -050088size_t Texture::getHeight(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -040089{
Geoff Lang691e58c2014-12-19 17:03:25 -050090 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang909b90c2015-01-12 14:07:26 -050091 return getImageDesc(ImageIndex::MakeGeneric(target, level)).size.height;
Jamie Madilld3d2a342013-10-07 10:46:35 -040092}
93
Geoff Langa9be0dc2014-12-17 12:34:40 -050094size_t Texture::getDepth(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -040095{
Geoff Lang691e58c2014-12-19 17:03:25 -050096 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang909b90c2015-01-12 14:07:26 -050097 return getImageDesc(ImageIndex::MakeGeneric(target, level)).size.depth;
Jamie Madilld3d2a342013-10-07 10:46:35 -040098}
99
Geoff Langa9be0dc2014-12-17 12:34:40 -0500100GLenum Texture::getInternalFormat(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -0400101{
Geoff Lang691e58c2014-12-19 17:03:25 -0500102 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang909b90c2015-01-12 14:07:26 -0500103 return getImageDesc(ImageIndex::MakeGeneric(target, level)).internalFormat;
Jamie Madill945f7322014-09-03 15:07:14 -0400104}
105
Geoff Lang691e58c2014-12-19 17:03:25 -0500106bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
107{
108 GLenum baseTarget = getBaseImageTarget();
Jamie Madill19d438d2015-01-19 13:42:12 -0500109 size_t width = getWidth(baseTarget, samplerState.baseLevel);
110 size_t height = getHeight(baseTarget, samplerState.baseLevel);
111 size_t depth = getDepth(baseTarget, samplerState.baseLevel);
Geoff Lang691e58c2014-12-19 17:03:25 -0500112 if (width == 0 || height == 0 || depth == 0)
113 {
114 return false;
115 }
116
117 if (mTarget == GL_TEXTURE_CUBE_MAP && width != height)
118 {
119 return false;
120 }
121
Jamie Madill19d438d2015-01-19 13:42:12 -0500122 GLenum internalFormat = getInternalFormat(baseTarget, samplerState.baseLevel);
Geoff Lang691e58c2014-12-19 17:03:25 -0500123 const TextureCaps &textureCaps = data.textureCaps->get(internalFormat);
124 if (!textureCaps.filterable && !IsPointSampled(samplerState))
125 {
126 return false;
127 }
128
129 bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3;
130 if (!npotSupport)
131 {
132 if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
133 (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
134 {
135 return false;
136 }
137 }
138
139 if (IsMipmapFiltered(samplerState))
140 {
141 if (!npotSupport)
142 {
143 if (!gl::isPow2(width) || !gl::isPow2(height))
144 {
145 return false;
146 }
147 }
148
Jamie Madill19d438d2015-01-19 13:42:12 -0500149 if (!isMipmapComplete(samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500150 {
151 return false;
152 }
153 }
154 else
155 {
156 if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
157 {
158 return false;
159 }
160 }
161
162 // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
163 // The internalformat specified for the texture arrays is a sized internal depth or
164 // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
165 // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
166 // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
167 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
168 if (formatInfo.depthBits > 0 && data.clientVersion > 2)
169 {
170 if (samplerState.compareMode == GL_NONE)
171 {
172 if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
173 samplerState.magFilter != GL_NEAREST)
174 {
175 return false;
176 }
177 }
178 }
179
180 return true;
181}
182
183// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
184bool Texture::isCubeComplete() const
185{
186 ASSERT(mTarget == GL_TEXTURE_CUBE_MAP);
187
188 GLenum baseTarget = FirstCubeMapTextureTarget;
189 size_t width = getWidth(baseTarget, 0);
190 size_t height = getWidth(baseTarget, 0);
191 if (width == 0 || width != height)
192 {
193 return false;
194 }
195
196 GLenum internalFormat = getInternalFormat(baseTarget, 0);
197 for (GLenum face = baseTarget + 1; face <= LastCubeMapTextureTarget; face++)
198 {
199 if (getWidth(face, 0) != width ||
200 getHeight(face, 0) != height ||
201 getInternalFormat(face, 0) != internalFormat)
202 {
203 return false;
204 }
205 }
206
207 return true;
208}
209
Jamie Madill10ef2152014-10-20 17:04:34 -0400210unsigned int Texture::getTextureSerial() const
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700211{
Jamie Madill10ef2152014-10-20 17:04:34 -0400212 return mTextureSerial;
213}
214
215unsigned int Texture::issueTextureSerial()
216{
217 return mCurrentTextureSerial++;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700218}
219
220bool Texture::isImmutable() const
221{
Jamie Madill6948e302014-10-20 17:04:33 -0400222 return (mImmutableLevelCount > 0);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700223}
224
225int Texture::immutableLevelCount()
226{
Jamie Madill6948e302014-10-20 17:04:33 -0400227 return mImmutableLevelCount;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700228}
229
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500230Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
231 const PixelUnpackState &unpack, const uint8_t *pixels)
232{
Geoff Lang691e58c2014-12-19 17:03:25 -0500233 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500234
235 Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels);
236 if (error.isError())
237 {
238 return error;
239 }
240
Geoff Lang7c973ea2014-12-19 15:58:28 -0500241 releaseTexImage();
242
Geoff Lang909b90c2015-01-12 14:07:26 -0500243 setImageDesc(ImageIndex::MakeGeneric(target, level), ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500244
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500245 return Error(GL_NO_ERROR);
246}
247
248Error Texture::setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type,
249 const PixelUnpackState &unpack, const uint8_t *pixels)
250{
Geoff Lang691e58c2014-12-19 17:03:25 -0500251 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500252
253 return mTexture->setSubImage(target, level, area, format, type, unpack, pixels);
254}
255
256Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size,
257 const PixelUnpackState &unpack, const uint8_t *pixels)
258{
Geoff Lang691e58c2014-12-19 17:03:25 -0500259 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500260
261 Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels);
262 if (error.isError())
263 {
264 return error;
265 }
266
Geoff Lang7c973ea2014-12-19 15:58:28 -0500267 releaseTexImage();
268
Geoff Lang909b90c2015-01-12 14:07:26 -0500269 setImageDesc(ImageIndex::MakeGeneric(target, level), ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500270
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500271 return Error(GL_NO_ERROR);
272}
273
274Error Texture::setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format,
275 const PixelUnpackState &unpack, const uint8_t *pixels)
276{
Geoff Lang691e58c2014-12-19 17:03:25 -0500277 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500278
279 return mTexture->setCompressedSubImage(target, level, area, format, unpack, pixels);
280}
281
282Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat,
283 const Framebuffer *source)
284{
Geoff Lang691e58c2014-12-19 17:03:25 -0500285 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500286
287 Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
288 if (error.isError())
289 {
290 return error;
291 }
292
Geoff Lang7c973ea2014-12-19 15:58:28 -0500293 releaseTexImage();
294
Geoff Lang909b90c2015-01-12 14:07:26 -0500295 setImageDesc(ImageIndex::MakeGeneric(target, level), ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
Geoff Langa9be0dc2014-12-17 12:34:40 -0500296 GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
297
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500298 return Error(GL_NO_ERROR);
299}
300
301Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea,
302 const Framebuffer *source)
303{
Geoff Lang691e58c2014-12-19 17:03:25 -0500304 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500305
306 return mTexture->copySubImage(target, level, destOffset, sourceArea, source);
307}
308
309Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size)
310{
311 ASSERT(target == mTarget);
312
313 Error error = mTexture->setStorage(target, levels, internalFormat, size);
314 if (error.isError())
315 {
316 return error;
317 }
318
Geoff Lang7c973ea2014-12-19 15:58:28 -0500319 releaseTexImage();
320
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500321 mImmutableLevelCount = levels;
Geoff Langa9be0dc2014-12-17 12:34:40 -0500322 clearImageDescs();
323 setImageDescChain(levels, size, internalFormat);
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500324
325 return Error(GL_NO_ERROR);
326}
327
328
329Error Texture::generateMipmaps()
330{
331 Error error = mTexture->generateMipmaps();
332 if (error.isError())
333 {
334 return error;
335 }
336
Geoff Lang7c973ea2014-12-19 15:58:28 -0500337 releaseTexImage();
338
Geoff Lang909b90c2015-01-12 14:07:26 -0500339 ImageIndex baseLevel = ImageIndex::MakeGeneric(getBaseImageTarget(), 0);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500340 const ImageDesc &baseImageInfo = getImageDesc(baseLevel);
341 size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1;
342 setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat);
343
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500344 return Error(GL_NO_ERROR);
345}
346
Geoff Langa9be0dc2014-12-17 12:34:40 -0500347void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat)
348{
349 for (size_t level = 0; level < levels; level++)
350 {
351 Extents levelSize(std::max<size_t>(baseSize.width >> level, 1),
352 std::max<size_t>(baseSize.height >> level, 1),
353 (mTarget == GL_TEXTURE_2D_ARRAY) ? baseSize.depth : std::max<size_t>(baseSize.depth >> level, 1));
354 ImageDesc levelInfo(levelSize, sizedInternalFormat);
355
356 if (mTarget == GL_TEXTURE_CUBE_MAP)
357 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500358 for (size_t face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500359 {
Geoff Lang909b90c2015-01-12 14:07:26 -0500360 setImageDesc(ImageIndex::MakeGeneric(face, level), levelInfo);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500361 }
362 }
363 else
364 {
Geoff Lang909b90c2015-01-12 14:07:26 -0500365 setImageDesc(ImageIndex::MakeGeneric(mTarget, level), levelInfo);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500366 }
367 }
368}
369
Geoff Langa9be0dc2014-12-17 12:34:40 -0500370Texture::ImageDesc::ImageDesc()
371 : ImageDesc(Extents(0, 0, 0), GL_NONE)
372{
373}
374
375Texture::ImageDesc::ImageDesc(const Extents &size, GLenum internalFormat)
376 : size(size),
377 internalFormat(internalFormat)
378{
379}
380
Geoff Lang909b90c2015-01-12 14:07:26 -0500381const Texture::ImageDesc &Texture::getImageDesc(const ImageIndex &index) const
Geoff Langa9be0dc2014-12-17 12:34:40 -0500382{
383 static const Texture::ImageDesc defaultDesc;
384 ImageDescMap::const_iterator iter = mImageDescs.find(index);
385 return (iter != mImageDescs.end()) ? iter->second : defaultDesc;
386}
387
Geoff Lang909b90c2015-01-12 14:07:26 -0500388void Texture::setImageDesc(const ImageIndex &index, const ImageDesc &desc)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500389{
390 mImageDescs[index] = desc;
391}
392
393void Texture::clearImageDescs()
394{
395 mImageDescs.clear();
396}
397
Geoff Lang7c973ea2014-12-19 15:58:28 -0500398void Texture::bindTexImage(egl::Surface *surface)
399{
400 releaseTexImage();
401 mTexture->bindTexImage(surface);
402 mBoundSurface = surface;
403}
404
405void Texture::releaseTexImage()
406{
407 if (mBoundSurface)
408 {
409 mBoundSurface = NULL;
410 mTexture->releaseTexImage();
411 }
412}
413
Geoff Lang691e58c2014-12-19 17:03:25 -0500414GLenum Texture::getBaseImageTarget() const
Jamie Madill22f843a2013-10-24 17:49:36 -0400415{
Geoff Lang691e58c2014-12-19 17:03:25 -0500416 return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000417}
418
Geoff Lang691e58c2014-12-19 17:03:25 -0500419size_t Texture::getExpectedMipLevels() const
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000420{
Geoff Lang691e58c2014-12-19 17:03:25 -0500421 GLenum baseTarget = getBaseImageTarget();
422 size_t width = getWidth(baseTarget, 0);
423 size_t height = getHeight(baseTarget, 0);
424 if (mTarget == GL_TEXTURE_3D)
425 {
426 size_t depth = getDepth(baseTarget, 0);
427 return log2(std::max(std::max(width, height), depth)) + 1;
428 }
429 else
430 {
431 return log2(std::max(width, height)) + 1;
432 }
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000433}
434
Jamie Madill19d438d2015-01-19 13:42:12 -0500435bool Texture::isMipmapComplete(const gl::SamplerState &samplerState) const
Brandon Jones6053a522014-07-25 16:22:09 -0700436{
Geoff Lang691e58c2014-12-19 17:03:25 -0500437 size_t expectedMipLevels = getExpectedMipLevels();
Jamie Madill19d438d2015-01-19 13:42:12 -0500438
439 size_t maxLevel = std::min<size_t>(expectedMipLevels, samplerState.maxLevel + 1);
440
441 for (size_t level = samplerState.baseLevel; level < maxLevel; level++)
Brandon Jones6053a522014-07-25 16:22:09 -0700442 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500443 if (mTarget == GL_TEXTURE_CUBE_MAP)
Brandon Jones6053a522014-07-25 16:22:09 -0700444 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500445 for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
446 {
Jamie Madill19d438d2015-01-19 13:42:12 -0500447 if (!isLevelComplete(face, level, samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500448 {
449 return false;
450 }
451 }
452 }
453 else
454 {
Jamie Madill19d438d2015-01-19 13:42:12 -0500455 if (!isLevelComplete(mTarget, level, samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500456 {
457 return false;
458 }
Brandon Jones6053a522014-07-25 16:22:09 -0700459 }
460 }
461
462 return true;
463}
464
Geoff Lang691e58c2014-12-19 17:03:25 -0500465
Jamie Madill19d438d2015-01-19 13:42:12 -0500466bool Texture::isLevelComplete(GLenum target, size_t level,
467 const gl::SamplerState &samplerState) const
Brandon Jones6053a522014-07-25 16:22:09 -0700468{
Geoff Langa9be0dc2014-12-17 12:34:40 -0500469 ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
470
Brandon Jones6053a522014-07-25 16:22:09 -0700471 if (isImmutable())
472 {
473 return true;
474 }
475
Jamie Madill19d438d2015-01-19 13:42:12 -0500476 size_t width = getWidth(target, samplerState.baseLevel);
477 size_t height = getHeight(target, samplerState.baseLevel);
478 size_t depth = getHeight(target, samplerState.baseLevel);
Geoff Lang691e58c2014-12-19 17:03:25 -0500479 if (width == 0 || height == 0 || depth == 0)
Brandon Jones6053a522014-07-25 16:22:09 -0700480 {
481 return false;
482 }
483
484 // The base image level is complete if the width and height are positive
485 if (level == 0)
486 {
487 return true;
488 }
489
Jamie Madill19d438d2015-01-19 13:42:12 -0500490 if (getInternalFormat(target, level) != getInternalFormat(target, samplerState.baseLevel))
Brandon Jones6053a522014-07-25 16:22:09 -0700491 {
492 return false;
493 }
494
Geoff Lang691e58c2014-12-19 17:03:25 -0500495 if (getWidth(target, level) != std::max<size_t>(1, width >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700496 {
497 return false;
498 }
499
Geoff Lang691e58c2014-12-19 17:03:25 -0500500 if (getHeight(target, level) != std::max<size_t>(1, height >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700501 {
502 return false;
503 }
504
Geoff Lang691e58c2014-12-19 17:03:25 -0500505 if (mTarget == GL_TEXTURE_3D)
Brandon Jones6053a522014-07-25 16:22:09 -0700506 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500507 if (getDepth(target, level) != std::max<size_t>(1, depth >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700508 {
509 return false;
510 }
511 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500512 else if (mTarget == GL_TEXTURE_2D_ARRAY)
Brandon Jones6053a522014-07-25 16:22:09 -0700513 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500514 if (getDepth(target, level) != depth)
Brandon Jones6053a522014-07-25 16:22:09 -0700515 {
516 return false;
517 }
518 }
519
520 return true;
521}
522
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000523}