blob: b268fd89cdd729c4b70d91a4aea7c9c6a2e3e5f0 [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
Jamie Madill10ef2152014-10-20 17:04:34 -040044unsigned int Texture::mCurrentTextureSerial = 1;
45
Brandon Jones6053a522014-07-25 16:22:09 -070046Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
Brandon Jonesf47bebc2014-07-09 14:28:42 -070047 : RefCountObject(id),
Brandon Jones6053a522014-07-25 16:22:09 -070048 mTexture(impl),
Jamie Madill10ef2152014-10-20 17:04:34 -040049 mTextureSerial(issueTextureSerial()),
Brandon Jonesf47bebc2014-07-09 14:28:42 -070050 mUsage(GL_NONE),
Jamie Madill6948e302014-10-20 17:04:33 -040051 mImmutableLevelCount(0),
Geoff Lang7c973ea2014-12-19 15:58:28 -050052 mTarget(target),
53 mBoundSurface(NULL)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000054{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000055}
56
57Texture::~Texture()
58{
Geoff Lang7c973ea2014-12-19 15:58:28 -050059 if (mBoundSurface)
60 {
61 mBoundSurface->releaseTexImage(EGL_BACK_BUFFER);
62 mBoundSurface = NULL;
63 }
Brandon Jones6053a522014-07-25 16:22:09 -070064 SafeDelete(mTexture);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000065}
66
Geoff Lang4907f2c2013-07-25 12:53:57 -040067GLenum Texture::getTarget() const
68{
69 return mTarget;
70}
71
Geoff Lang63b5f1f2013-09-23 14:52:14 -040072void Texture::setUsage(GLenum usage)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000073{
Geoff Lang63b5f1f2013-09-23 14:52:14 -040074 mUsage = usage;
Brandon Jonescef06ff2014-08-05 13:27:48 -070075 getImplementation()->setUsage(usage);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000076}
77
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000078GLenum Texture::getUsage() const
79{
80 return mUsage;
81}
82
Geoff Langa9be0dc2014-12-17 12:34:40 -050083size_t Texture::getWidth(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -040084{
Geoff Lang691e58c2014-12-19 17:03:25 -050085 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang909b90c2015-01-12 14:07:26 -050086 return getImageDesc(ImageIndex::MakeGeneric(target, level)).size.width;
Jamie Madilld3d2a342013-10-07 10:46:35 -040087}
88
Geoff Langa9be0dc2014-12-17 12:34:40 -050089size_t Texture::getHeight(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 Lang909b90c2015-01-12 14:07:26 -050092 return getImageDesc(ImageIndex::MakeGeneric(target, level)).size.height;
Jamie Madilld3d2a342013-10-07 10:46:35 -040093}
94
Geoff Langa9be0dc2014-12-17 12:34:40 -050095size_t Texture::getDepth(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 Lang909b90c2015-01-12 14:07:26 -050098 return getImageDesc(ImageIndex::MakeGeneric(target, level)).size.depth;
Jamie Madilld3d2a342013-10-07 10:46:35 -040099}
100
Geoff Langa9be0dc2014-12-17 12:34:40 -0500101GLenum Texture::getInternalFormat(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 Lang909b90c2015-01-12 14:07:26 -0500104 return getImageDesc(ImageIndex::MakeGeneric(target, level)).internalFormat;
Jamie Madill945f7322014-09-03 15:07:14 -0400105}
106
Geoff Lang691e58c2014-12-19 17:03:25 -0500107bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
108{
109 GLenum baseTarget = getBaseImageTarget();
Jamie Madill19d438d2015-01-19 13:42:12 -0500110 size_t width = getWidth(baseTarget, samplerState.baseLevel);
111 size_t height = getHeight(baseTarget, samplerState.baseLevel);
112 size_t depth = getDepth(baseTarget, samplerState.baseLevel);
Geoff Lang691e58c2014-12-19 17:03:25 -0500113 if (width == 0 || height == 0 || depth == 0)
114 {
115 return false;
116 }
117
118 if (mTarget == GL_TEXTURE_CUBE_MAP && width != height)
119 {
120 return false;
121 }
122
Jamie Madill19d438d2015-01-19 13:42:12 -0500123 GLenum internalFormat = getInternalFormat(baseTarget, samplerState.baseLevel);
Geoff Lang691e58c2014-12-19 17:03:25 -0500124 const TextureCaps &textureCaps = data.textureCaps->get(internalFormat);
125 if (!textureCaps.filterable && !IsPointSampled(samplerState))
126 {
127 return false;
128 }
129
130 bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3;
131 if (!npotSupport)
132 {
133 if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
134 (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
135 {
136 return false;
137 }
138 }
139
140 if (IsMipmapFiltered(samplerState))
141 {
142 if (!npotSupport)
143 {
144 if (!gl::isPow2(width) || !gl::isPow2(height))
145 {
146 return false;
147 }
148 }
149
Jamie Madill19d438d2015-01-19 13:42:12 -0500150 if (!isMipmapComplete(samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500151 {
152 return false;
153 }
154 }
155 else
156 {
157 if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
158 {
159 return false;
160 }
161 }
162
163 // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
164 // The internalformat specified for the texture arrays is a sized internal depth or
165 // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
166 // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
167 // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
168 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
169 if (formatInfo.depthBits > 0 && data.clientVersion > 2)
170 {
171 if (samplerState.compareMode == GL_NONE)
172 {
173 if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
174 samplerState.magFilter != GL_NEAREST)
175 {
176 return false;
177 }
178 }
179 }
180
181 return true;
182}
183
184// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
185bool Texture::isCubeComplete() const
186{
187 ASSERT(mTarget == GL_TEXTURE_CUBE_MAP);
188
189 GLenum baseTarget = FirstCubeMapTextureTarget;
190 size_t width = getWidth(baseTarget, 0);
191 size_t height = getWidth(baseTarget, 0);
192 if (width == 0 || width != height)
193 {
194 return false;
195 }
196
197 GLenum internalFormat = getInternalFormat(baseTarget, 0);
198 for (GLenum face = baseTarget + 1; face <= LastCubeMapTextureTarget; face++)
199 {
200 if (getWidth(face, 0) != width ||
201 getHeight(face, 0) != height ||
202 getInternalFormat(face, 0) != internalFormat)
203 {
204 return false;
205 }
206 }
207
208 return true;
209}
210
Jamie Madill10ef2152014-10-20 17:04:34 -0400211unsigned int Texture::getTextureSerial() const
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700212{
Jamie Madill10ef2152014-10-20 17:04:34 -0400213 return mTextureSerial;
214}
215
216unsigned int Texture::issueTextureSerial()
217{
218 return mCurrentTextureSerial++;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700219}
220
221bool Texture::isImmutable() const
222{
Jamie Madill6948e302014-10-20 17:04:33 -0400223 return (mImmutableLevelCount > 0);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700224}
225
226int Texture::immutableLevelCount()
227{
Jamie Madill6948e302014-10-20 17:04:33 -0400228 return mImmutableLevelCount;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700229}
230
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500231Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
232 const PixelUnpackState &unpack, const uint8_t *pixels)
233{
Geoff Lang691e58c2014-12-19 17:03:25 -0500234 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500235
236 Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels);
237 if (error.isError())
238 {
239 return error;
240 }
241
Geoff Lang7c973ea2014-12-19 15:58:28 -0500242 releaseTexImage();
243
Geoff Lang909b90c2015-01-12 14:07:26 -0500244 setImageDesc(ImageIndex::MakeGeneric(target, level), ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500245
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500246 return Error(GL_NO_ERROR);
247}
248
249Error Texture::setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type,
250 const PixelUnpackState &unpack, const uint8_t *pixels)
251{
Geoff Lang691e58c2014-12-19 17:03:25 -0500252 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500253
254 return mTexture->setSubImage(target, level, area, format, type, unpack, pixels);
255}
256
257Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size,
258 const PixelUnpackState &unpack, const uint8_t *pixels)
259{
Geoff Lang691e58c2014-12-19 17:03:25 -0500260 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500261
262 Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels);
263 if (error.isError())
264 {
265 return error;
266 }
267
Geoff Lang7c973ea2014-12-19 15:58:28 -0500268 releaseTexImage();
269
Geoff Lang909b90c2015-01-12 14:07:26 -0500270 setImageDesc(ImageIndex::MakeGeneric(target, level), ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500271
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500272 return Error(GL_NO_ERROR);
273}
274
275Error Texture::setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format,
276 const PixelUnpackState &unpack, const uint8_t *pixels)
277{
Geoff Lang691e58c2014-12-19 17:03:25 -0500278 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500279
280 return mTexture->setCompressedSubImage(target, level, area, format, unpack, pixels);
281}
282
283Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat,
284 const Framebuffer *source)
285{
Geoff Lang691e58c2014-12-19 17:03:25 -0500286 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500287
288 Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
289 if (error.isError())
290 {
291 return error;
292 }
293
Geoff Lang7c973ea2014-12-19 15:58:28 -0500294 releaseTexImage();
295
Geoff Lang909b90c2015-01-12 14:07:26 -0500296 setImageDesc(ImageIndex::MakeGeneric(target, level), ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
Geoff Langa9be0dc2014-12-17 12:34:40 -0500297 GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
298
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500299 return Error(GL_NO_ERROR);
300}
301
302Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea,
303 const Framebuffer *source)
304{
Geoff Lang691e58c2014-12-19 17:03:25 -0500305 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500306
307 return mTexture->copySubImage(target, level, destOffset, sourceArea, source);
308}
309
310Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size)
311{
312 ASSERT(target == mTarget);
313
314 Error error = mTexture->setStorage(target, levels, internalFormat, size);
315 if (error.isError())
316 {
317 return error;
318 }
319
Geoff Lang7c973ea2014-12-19 15:58:28 -0500320 releaseTexImage();
321
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500322 mImmutableLevelCount = levels;
Geoff Langa9be0dc2014-12-17 12:34:40 -0500323 clearImageDescs();
324 setImageDescChain(levels, size, internalFormat);
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500325
326 return Error(GL_NO_ERROR);
327}
328
329
330Error Texture::generateMipmaps()
331{
332 Error error = mTexture->generateMipmaps();
333 if (error.isError())
334 {
335 return error;
336 }
337
Geoff Lang7c973ea2014-12-19 15:58:28 -0500338 releaseTexImage();
339
Geoff Lang909b90c2015-01-12 14:07:26 -0500340 ImageIndex baseLevel = ImageIndex::MakeGeneric(getBaseImageTarget(), 0);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500341 const ImageDesc &baseImageInfo = getImageDesc(baseLevel);
342 size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1;
343 setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat);
344
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500345 return Error(GL_NO_ERROR);
346}
347
Geoff Langa9be0dc2014-12-17 12:34:40 -0500348void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat)
349{
350 for (size_t level = 0; level < levels; level++)
351 {
352 Extents levelSize(std::max<size_t>(baseSize.width >> level, 1),
353 std::max<size_t>(baseSize.height >> level, 1),
354 (mTarget == GL_TEXTURE_2D_ARRAY) ? baseSize.depth : std::max<size_t>(baseSize.depth >> level, 1));
355 ImageDesc levelInfo(levelSize, sizedInternalFormat);
356
357 if (mTarget == GL_TEXTURE_CUBE_MAP)
358 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500359 for (size_t face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500360 {
Geoff Lang909b90c2015-01-12 14:07:26 -0500361 setImageDesc(ImageIndex::MakeGeneric(face, level), levelInfo);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500362 }
363 }
364 else
365 {
Geoff Lang909b90c2015-01-12 14:07:26 -0500366 setImageDesc(ImageIndex::MakeGeneric(mTarget, level), levelInfo);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500367 }
368 }
369}
370
Geoff Langa9be0dc2014-12-17 12:34:40 -0500371Texture::ImageDesc::ImageDesc()
372 : ImageDesc(Extents(0, 0, 0), GL_NONE)
373{
374}
375
376Texture::ImageDesc::ImageDesc(const Extents &size, GLenum internalFormat)
377 : size(size),
378 internalFormat(internalFormat)
379{
380}
381
Geoff Lang909b90c2015-01-12 14:07:26 -0500382const Texture::ImageDesc &Texture::getImageDesc(const ImageIndex &index) const
Geoff Langa9be0dc2014-12-17 12:34:40 -0500383{
384 static const Texture::ImageDesc defaultDesc;
385 ImageDescMap::const_iterator iter = mImageDescs.find(index);
386 return (iter != mImageDescs.end()) ? iter->second : defaultDesc;
387}
388
Geoff Lang909b90c2015-01-12 14:07:26 -0500389void Texture::setImageDesc(const ImageIndex &index, const ImageDesc &desc)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500390{
391 mImageDescs[index] = desc;
392}
393
Geoff Langb9266272015-01-29 13:25:14 +0000394void Texture::clearImageDesc(const ImageIndex &index)
395{
396 ImageDescMap::iterator iter = mImageDescs.find(index);
397 if (iter != mImageDescs.end())
398 {
399 mImageDescs.erase(iter);
400 }
401}
402
Geoff Langa9be0dc2014-12-17 12:34:40 -0500403void Texture::clearImageDescs()
404{
405 mImageDescs.clear();
406}
407
Geoff Lang7c973ea2014-12-19 15:58:28 -0500408void Texture::bindTexImage(egl::Surface *surface)
409{
Geoff Langb9266272015-01-29 13:25:14 +0000410 ASSERT(surface);
411
Geoff Lang7c973ea2014-12-19 15:58:28 -0500412 releaseTexImage();
413 mTexture->bindTexImage(surface);
414 mBoundSurface = surface;
Geoff Langb9266272015-01-29 13:25:14 +0000415
416 // Set the image info to the size and format of the surface
417 ASSERT(mTarget == GL_TEXTURE_2D);
418 Extents size(surface->getWidth(), surface->getHeight(), 1);
419 ImageDesc desc(size, surface->getConfig()->mRenderTargetFormat);
420 setImageDesc(ImageIndex::MakeGeneric(mTarget, 0), desc);
Geoff Lang7c973ea2014-12-19 15:58:28 -0500421}
422
423void Texture::releaseTexImage()
424{
425 if (mBoundSurface)
426 {
427 mBoundSurface = NULL;
428 mTexture->releaseTexImage();
Geoff Langb9266272015-01-29 13:25:14 +0000429
430 // Erase the image info for level 0
431 ASSERT(mTarget == GL_TEXTURE_2D);
432 clearImageDesc(ImageIndex::MakeGeneric(mTarget, 0));
Geoff Lang7c973ea2014-12-19 15:58:28 -0500433 }
434}
435
Geoff Lang691e58c2014-12-19 17:03:25 -0500436GLenum Texture::getBaseImageTarget() const
Jamie Madill22f843a2013-10-24 17:49:36 -0400437{
Geoff Lang691e58c2014-12-19 17:03:25 -0500438 return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000439}
440
Geoff Lang691e58c2014-12-19 17:03:25 -0500441size_t Texture::getExpectedMipLevels() const
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000442{
Geoff Lang691e58c2014-12-19 17:03:25 -0500443 GLenum baseTarget = getBaseImageTarget();
444 size_t width = getWidth(baseTarget, 0);
445 size_t height = getHeight(baseTarget, 0);
446 if (mTarget == GL_TEXTURE_3D)
447 {
448 size_t depth = getDepth(baseTarget, 0);
449 return log2(std::max(std::max(width, height), depth)) + 1;
450 }
451 else
452 {
453 return log2(std::max(width, height)) + 1;
454 }
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000455}
456
Jamie Madill19d438d2015-01-19 13:42:12 -0500457bool Texture::isMipmapComplete(const gl::SamplerState &samplerState) const
Brandon Jones6053a522014-07-25 16:22:09 -0700458{
Geoff Lang691e58c2014-12-19 17:03:25 -0500459 size_t expectedMipLevels = getExpectedMipLevels();
Jamie Madill19d438d2015-01-19 13:42:12 -0500460
461 size_t maxLevel = std::min<size_t>(expectedMipLevels, samplerState.maxLevel + 1);
462
463 for (size_t level = samplerState.baseLevel; level < maxLevel; level++)
Brandon Jones6053a522014-07-25 16:22:09 -0700464 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500465 if (mTarget == GL_TEXTURE_CUBE_MAP)
Brandon Jones6053a522014-07-25 16:22:09 -0700466 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500467 for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
468 {
Jamie Madill19d438d2015-01-19 13:42:12 -0500469 if (!isLevelComplete(face, level, samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500470 {
471 return false;
472 }
473 }
474 }
475 else
476 {
Jamie Madill19d438d2015-01-19 13:42:12 -0500477 if (!isLevelComplete(mTarget, level, samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500478 {
479 return false;
480 }
Brandon Jones6053a522014-07-25 16:22:09 -0700481 }
482 }
483
484 return true;
485}
486
Geoff Lang691e58c2014-12-19 17:03:25 -0500487
Jamie Madill19d438d2015-01-19 13:42:12 -0500488bool Texture::isLevelComplete(GLenum target, size_t level,
489 const gl::SamplerState &samplerState) const
Brandon Jones6053a522014-07-25 16:22:09 -0700490{
Geoff Langa9be0dc2014-12-17 12:34:40 -0500491 ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
492
Brandon Jones6053a522014-07-25 16:22:09 -0700493 if (isImmutable())
494 {
495 return true;
496 }
497
Jamie Madill19d438d2015-01-19 13:42:12 -0500498 size_t width = getWidth(target, samplerState.baseLevel);
499 size_t height = getHeight(target, samplerState.baseLevel);
Jamie Madill448d3db2015-01-28 16:51:10 -0500500 size_t depth = getDepth(target, samplerState.baseLevel);
Geoff Lang691e58c2014-12-19 17:03:25 -0500501 if (width == 0 || height == 0 || depth == 0)
Brandon Jones6053a522014-07-25 16:22:09 -0700502 {
503 return false;
504 }
505
506 // The base image level is complete if the width and height are positive
507 if (level == 0)
508 {
509 return true;
510 }
511
Jamie Madill19d438d2015-01-19 13:42:12 -0500512 if (getInternalFormat(target, level) != getInternalFormat(target, samplerState.baseLevel))
Brandon Jones6053a522014-07-25 16:22:09 -0700513 {
514 return false;
515 }
516
Geoff Lang691e58c2014-12-19 17:03:25 -0500517 if (getWidth(target, level) != std::max<size_t>(1, width >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700518 {
519 return false;
520 }
521
Geoff Lang691e58c2014-12-19 17:03:25 -0500522 if (getHeight(target, level) != std::max<size_t>(1, height >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700523 {
524 return false;
525 }
526
Geoff Lang691e58c2014-12-19 17:03:25 -0500527 if (mTarget == GL_TEXTURE_3D)
Brandon Jones6053a522014-07-25 16:22:09 -0700528 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500529 if (getDepth(target, level) != std::max<size_t>(1, depth >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700530 {
531 return false;
532 }
533 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500534 else if (mTarget == GL_TEXTURE_2D_ARRAY)
Brandon Jones6053a522014-07-25 16:22:09 -0700535 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500536 if (getDepth(target, level) != depth)
Brandon Jones6053a522014-07-25 16:22:09 -0700537 {
538 return false;
539 }
540 }
541
542 return true;
543}
544
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000545}