blob: d0c3d84a27c697c25c55401467230df519987751 [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{
Geoff Langb0eecdf2015-02-10 11:09:12 -0500115 const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel);
116 if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0)
Geoff Lang691e58c2014-12-19 17:03:25 -0500117 {
118 return false;
119 }
120
Geoff Langb0eecdf2015-02-10 11:09:12 -0500121 if (mTarget == GL_TEXTURE_CUBE_MAP && baseImageDesc.size.width != baseImageDesc.size.height)
Geoff Lang691e58c2014-12-19 17:03:25 -0500122 {
123 return false;
124 }
125
Geoff Langb0eecdf2015-02-10 11:09:12 -0500126 const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat);
Geoff Lang691e58c2014-12-19 17:03:25 -0500127 if (!textureCaps.filterable && !IsPointSampled(samplerState))
128 {
129 return false;
130 }
131
132 bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3;
133 if (!npotSupport)
134 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500135 if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.width)) ||
136 (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.height)))
Geoff Lang691e58c2014-12-19 17:03:25 -0500137 {
138 return false;
139 }
140 }
141
142 if (IsMipmapFiltered(samplerState))
143 {
144 if (!npotSupport)
145 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500146 if (!gl::isPow2(baseImageDesc.size.width) || !gl::isPow2(baseImageDesc.size.height))
Geoff Lang691e58c2014-12-19 17:03:25 -0500147 {
148 return false;
149 }
150 }
151
Jamie Madill19d438d2015-01-19 13:42:12 -0500152 if (!isMipmapComplete(samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500153 {
154 return false;
155 }
156 }
157 else
158 {
159 if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
160 {
161 return false;
162 }
163 }
164
165 // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
166 // The internalformat specified for the texture arrays is a sized internal depth or
167 // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
168 // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
169 // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
Geoff Langb0eecdf2015-02-10 11:09:12 -0500170 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(baseImageDesc.internalFormat);
Geoff Lang691e58c2014-12-19 17:03:25 -0500171 if (formatInfo.depthBits > 0 && data.clientVersion > 2)
172 {
173 if (samplerState.compareMode == GL_NONE)
174 {
175 if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
176 samplerState.magFilter != GL_NEAREST)
177 {
178 return false;
179 }
180 }
181 }
182
183 return true;
184}
185
186// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
187bool Texture::isCubeComplete() const
188{
189 ASSERT(mTarget == GL_TEXTURE_CUBE_MAP);
190
Geoff Langb0eecdf2015-02-10 11:09:12 -0500191 const ImageDesc &baseImageDesc = getImageDesc(FirstCubeMapTextureTarget, 0);
192 if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height)
Geoff Lang691e58c2014-12-19 17:03:25 -0500193 {
194 return false;
195 }
196
Geoff Langb0eecdf2015-02-10 11:09:12 -0500197 for (GLenum face = FirstCubeMapTextureTarget + 1; face <= LastCubeMapTextureTarget; face++)
Geoff Lang691e58c2014-12-19 17:03:25 -0500198 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500199 const ImageDesc &faceImageDesc = getImageDesc(face, 0);
200 if (faceImageDesc.size.width != baseImageDesc.size.width ||
201 faceImageDesc.size.height != baseImageDesc.size.height ||
202 faceImageDesc.internalFormat != baseImageDesc.internalFormat)
Geoff Lang691e58c2014-12-19 17:03:25 -0500203 {
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 Lang866dd2d2015-02-10 11:08:32 -0500244 setImageDesc(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 Lang866dd2d2015-02-10 11:08:32 -0500270 setImageDesc(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 Lang866dd2d2015-02-10 11:08:32 -0500296 setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
297 GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500298
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 Lang866dd2d2015-02-10 11:08:32 -0500340 const ImageDesc &baseImageInfo = getImageDesc(getBaseImageTarget(), 0);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500341 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 Lang866dd2d2015-02-10 11:08:32 -0500360 setImageDesc(face, level, levelInfo);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500361 }
362 }
363 else
364 {
Geoff Lang866dd2d2015-02-10 11:08:32 -0500365 setImageDesc(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 Lang866dd2d2015-02-10 11:08:32 -0500381const Texture::ImageDesc &Texture::getImageDesc(GLenum target, size_t level) const
Geoff Langa9be0dc2014-12-17 12:34:40 -0500382{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500383 size_t descIndex = GetImageDescIndex(target, level);
384 ASSERT(descIndex < mImageDescs.size());
385 return mImageDescs[descIndex];
Geoff Langa9be0dc2014-12-17 12:34:40 -0500386}
387
Geoff Lang866dd2d2015-02-10 11:08:32 -0500388void Texture::setImageDesc(GLenum target, size_t level, const ImageDesc &desc)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500389{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500390 size_t descIndex = GetImageDescIndex(target, level);
391 ASSERT(descIndex < mImageDescs.size());
392 mImageDescs[descIndex] = desc;
Geoff Langa9be0dc2014-12-17 12:34:40 -0500393}
394
Geoff Lang866dd2d2015-02-10 11:08:32 -0500395void Texture::clearImageDesc(GLenum target, size_t level)
Geoff Langb9266272015-01-29 13:25:14 +0000396{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500397 setImageDesc(target, level, ImageDesc());
Geoff Langb9266272015-01-29 13:25:14 +0000398}
399
Geoff Langa9be0dc2014-12-17 12:34:40 -0500400void Texture::clearImageDescs()
401{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500402 for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
403 {
404 mImageDescs[descIndex] = ImageDesc();
405 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500406}
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);
Geoff Langc223dc62015-01-09 13:10:01 -0500419 ImageDesc desc(size, surface->getConfig()->renderTargetFormat);
Geoff Lang866dd2d2015-02-10 11:08:32 -0500420 setImageDesc(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);
Geoff Lang866dd2d2015-02-10 11:08:32 -0500432 clearImageDesc(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 Langb0eecdf2015-02-10 11:09:12 -0500443 const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), 0);
Geoff Lang691e58c2014-12-19 17:03:25 -0500444 if (mTarget == GL_TEXTURE_3D)
445 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500446 return log2(std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height), baseImageDesc.size.depth)) + 1;
Geoff Lang691e58c2014-12-19 17:03:25 -0500447 }
448 else
449 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500450 return log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)) + 1;
Geoff Lang691e58c2014-12-19 17:03:25 -0500451 }
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000452}
453
Jamie Madill19d438d2015-01-19 13:42:12 -0500454bool Texture::isMipmapComplete(const gl::SamplerState &samplerState) const
Brandon Jones6053a522014-07-25 16:22:09 -0700455{
Geoff Lang691e58c2014-12-19 17:03:25 -0500456 size_t expectedMipLevels = getExpectedMipLevels();
Jamie Madill19d438d2015-01-19 13:42:12 -0500457
458 size_t maxLevel = std::min<size_t>(expectedMipLevels, samplerState.maxLevel + 1);
459
460 for (size_t level = samplerState.baseLevel; level < maxLevel; level++)
Brandon Jones6053a522014-07-25 16:22:09 -0700461 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500462 if (mTarget == GL_TEXTURE_CUBE_MAP)
Brandon Jones6053a522014-07-25 16:22:09 -0700463 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500464 for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
465 {
Jamie Madill19d438d2015-01-19 13:42:12 -0500466 if (!isLevelComplete(face, level, samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500467 {
468 return false;
469 }
470 }
471 }
472 else
473 {
Jamie Madill19d438d2015-01-19 13:42:12 -0500474 if (!isLevelComplete(mTarget, level, samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500475 {
476 return false;
477 }
Brandon Jones6053a522014-07-25 16:22:09 -0700478 }
479 }
480
481 return true;
482}
483
Geoff Lang691e58c2014-12-19 17:03:25 -0500484
Jamie Madill19d438d2015-01-19 13:42:12 -0500485bool Texture::isLevelComplete(GLenum target, size_t level,
486 const gl::SamplerState &samplerState) const
Brandon Jones6053a522014-07-25 16:22:09 -0700487{
Geoff Langa9be0dc2014-12-17 12:34:40 -0500488 ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
489
Brandon Jones6053a522014-07-25 16:22:09 -0700490 if (isImmutable())
491 {
492 return true;
493 }
494
Geoff Langb0eecdf2015-02-10 11:09:12 -0500495 const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel);
496 if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0)
Brandon Jones6053a522014-07-25 16:22:09 -0700497 {
498 return false;
499 }
500
501 // The base image level is complete if the width and height are positive
502 if (level == 0)
503 {
504 return true;
505 }
506
Geoff Langb0eecdf2015-02-10 11:09:12 -0500507 const ImageDesc &levelImageDesc = getImageDesc(target, level);
508 if (levelImageDesc.internalFormat != baseImageDesc.internalFormat)
Brandon Jones6053a522014-07-25 16:22:09 -0700509 {
510 return false;
511 }
512
Geoff Langb0eecdf2015-02-10 11:09:12 -0500513 if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700514 {
515 return false;
516 }
517
Geoff Langb0eecdf2015-02-10 11:09:12 -0500518 if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700519 {
520 return false;
521 }
522
Geoff Lang691e58c2014-12-19 17:03:25 -0500523 if (mTarget == GL_TEXTURE_3D)
Brandon Jones6053a522014-07-25 16:22:09 -0700524 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500525 if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700526 {
527 return false;
528 }
529 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500530 else if (mTarget == GL_TEXTURE_2D_ARRAY)
Brandon Jones6053a522014-07-25 16:22:09 -0700531 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500532 if (levelImageDesc.size.depth != baseImageDesc.size.depth)
Brandon Jones6053a522014-07-25 16:22:09 -0700533 {
534 return false;
535 }
536 }
537
538 return true;
539}
540
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000541}