blob: d17dd5d5d0fdd43d8d578ce705ede16a4b08bbf0 [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 Lang0b7eef72014-06-12 14:10:47 -040010
11#include "common/mathutil.h"
12#include "common/utilities.h"
Jamie Madill79481d62015-04-14 08:13:47 -040013#include "libANGLE/Config.h"
14#include "libANGLE/Data.h"
15#include "libANGLE/Surface.h"
16#include "libANGLE/formatutils.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
Geoff Lang866dd2d2015-02-10 11:08:32 -050043static size_t GetImageDescIndex(GLenum target, size_t level)
44{
45 return IsCubeMapTextureTarget(target) ? ((level * 6) + CubeMapTextureTargetToLayerIndex(target)) : level;
46}
47
Brandon Jones6053a522014-07-25 16:22:09 -070048Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
Jamie Madill79481d62015-04-14 08:13:47 -040049 : FramebufferAttachmentObject(id),
Brandon Jones6053a522014-07-25 16:22:09 -070050 mTexture(impl),
Brandon Jonesf47bebc2014-07-09 14:28:42 -070051 mUsage(GL_NONE),
Jamie Madill6948e302014-10-20 17:04:33 -040052 mImmutableLevelCount(0),
Geoff Lang7c973ea2014-12-19 15:58:28 -050053 mTarget(target),
Geoff Lang866dd2d2015-02-10 11:08:32 -050054 mImageDescs(IMPLEMENTATION_MAX_TEXTURE_LEVELS * (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)),
Geoff Lang0fe40532015-02-10 12:01:27 -050055 mCompletenessCache(),
Geoff Lang7c973ea2014-12-19 15:58:28 -050056 mBoundSurface(NULL)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000057{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000058}
59
60Texture::~Texture()
61{
Geoff Lang7c973ea2014-12-19 15:58:28 -050062 if (mBoundSurface)
63 {
64 mBoundSurface->releaseTexImage(EGL_BACK_BUFFER);
65 mBoundSurface = NULL;
66 }
Brandon Jones6053a522014-07-25 16:22:09 -070067 SafeDelete(mTexture);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000068}
69
Geoff Lang4907f2c2013-07-25 12:53:57 -040070GLenum Texture::getTarget() const
71{
72 return mTarget;
73}
74
Geoff Lang63b5f1f2013-09-23 14:52:14 -040075void Texture::setUsage(GLenum usage)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000076{
Geoff Lang63b5f1f2013-09-23 14:52:14 -040077 mUsage = usage;
Brandon Jonescef06ff2014-08-05 13:27:48 -070078 getImplementation()->setUsage(usage);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000079}
80
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000081GLenum Texture::getUsage() const
82{
83 return mUsage;
84}
85
Geoff Langa9be0dc2014-12-17 12:34:40 -050086size_t Texture::getWidth(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -040087{
Geoff Lang691e58c2014-12-19 17:03:25 -050088 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang866dd2d2015-02-10 11:08:32 -050089 return getImageDesc(target, level).size.width;
Jamie Madilld3d2a342013-10-07 10:46:35 -040090}
91
Geoff Langa9be0dc2014-12-17 12:34:40 -050092size_t Texture::getHeight(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -040093{
Geoff Lang691e58c2014-12-19 17:03:25 -050094 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang866dd2d2015-02-10 11:08:32 -050095 return getImageDesc(target, level).size.height;
Jamie Madilld3d2a342013-10-07 10:46:35 -040096}
97
Geoff Langa9be0dc2014-12-17 12:34:40 -050098size_t Texture::getDepth(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -040099{
Geoff Lang691e58c2014-12-19 17:03:25 -0500100 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang866dd2d2015-02-10 11:08:32 -0500101 return getImageDesc(target, level).size.depth;
Jamie Madilld3d2a342013-10-07 10:46:35 -0400102}
103
Geoff Langa9be0dc2014-12-17 12:34:40 -0500104GLenum Texture::getInternalFormat(GLenum target, size_t level) const
Jamie Madilld3d2a342013-10-07 10:46:35 -0400105{
Geoff Lang691e58c2014-12-19 17:03:25 -0500106 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang866dd2d2015-02-10 11:08:32 -0500107 return getImageDesc(target, level).internalFormat;
Jamie Madill945f7322014-09-03 15:07:14 -0400108}
109
Geoff Lang691e58c2014-12-19 17:03:25 -0500110bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
111{
Geoff Langb0eecdf2015-02-10 11:09:12 -0500112 const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel);
Geoff Langb0eecdf2015-02-10 11:09:12 -0500113 const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat);
Geoff Lang0fe40532015-02-10 12:01:27 -0500114 if (!mCompletenessCache.cacheValid ||
115 mCompletenessCache.samplerState != samplerState ||
116 mCompletenessCache.filterable != textureCaps.filterable ||
117 mCompletenessCache.clientVersion != data.clientVersion ||
118 mCompletenessCache.supportsNPOT != data.extensions->textureNPOT)
Geoff Lang691e58c2014-12-19 17:03:25 -0500119 {
Geoff Lang0fe40532015-02-10 12:01:27 -0500120 mCompletenessCache.cacheValid = true;
121 mCompletenessCache.samplerState = samplerState;
122 mCompletenessCache.filterable = textureCaps.filterable;
123 mCompletenessCache.clientVersion = data.clientVersion;
124 mCompletenessCache.supportsNPOT = data.extensions->textureNPOT;
125 mCompletenessCache.samplerComplete = computeSamplerCompleteness(samplerState, data);
Geoff Lang691e58c2014-12-19 17:03:25 -0500126 }
Geoff Lang0fe40532015-02-10 12:01:27 -0500127 return mCompletenessCache.samplerComplete;
Geoff Lang691e58c2014-12-19 17:03:25 -0500128}
129
130// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
131bool Texture::isCubeComplete() const
132{
133 ASSERT(mTarget == GL_TEXTURE_CUBE_MAP);
134
Geoff Langb0eecdf2015-02-10 11:09:12 -0500135 const ImageDesc &baseImageDesc = getImageDesc(FirstCubeMapTextureTarget, 0);
136 if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height)
Geoff Lang691e58c2014-12-19 17:03:25 -0500137 {
138 return false;
139 }
140
Geoff Langb0eecdf2015-02-10 11:09:12 -0500141 for (GLenum face = FirstCubeMapTextureTarget + 1; face <= LastCubeMapTextureTarget; face++)
Geoff Lang691e58c2014-12-19 17:03:25 -0500142 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500143 const ImageDesc &faceImageDesc = getImageDesc(face, 0);
144 if (faceImageDesc.size.width != baseImageDesc.size.width ||
145 faceImageDesc.size.height != baseImageDesc.size.height ||
146 faceImageDesc.internalFormat != baseImageDesc.internalFormat)
Geoff Lang691e58c2014-12-19 17:03:25 -0500147 {
148 return false;
149 }
150 }
151
152 return true;
153}
154
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700155bool Texture::isImmutable() const
156{
Jamie Madill6948e302014-10-20 17:04:33 -0400157 return (mImmutableLevelCount > 0);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700158}
159
160int Texture::immutableLevelCount()
161{
Jamie Madill6948e302014-10-20 17:04:33 -0400162 return mImmutableLevelCount;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700163}
164
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500165Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
166 const PixelUnpackState &unpack, const uint8_t *pixels)
167{
Geoff Lang691e58c2014-12-19 17:03:25 -0500168 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500169
170 Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels);
171 if (error.isError())
172 {
173 return error;
174 }
175
Geoff Lang7c973ea2014-12-19 15:58:28 -0500176 releaseTexImage();
177
Geoff Lang866dd2d2015-02-10 11:08:32 -0500178 setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500179
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500180 return Error(GL_NO_ERROR);
181}
182
183Error Texture::setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type,
184 const PixelUnpackState &unpack, const uint8_t *pixels)
185{
Geoff Lang691e58c2014-12-19 17:03:25 -0500186 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500187
188 return mTexture->setSubImage(target, level, area, format, type, unpack, pixels);
189}
190
191Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size,
192 const PixelUnpackState &unpack, const uint8_t *pixels)
193{
Geoff Lang691e58c2014-12-19 17:03:25 -0500194 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500195
196 Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels);
197 if (error.isError())
198 {
199 return error;
200 }
201
Geoff Lang7c973ea2014-12-19 15:58:28 -0500202 releaseTexImage();
203
Geoff Lang866dd2d2015-02-10 11:08:32 -0500204 setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500205
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500206 return Error(GL_NO_ERROR);
207}
208
209Error Texture::setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format,
210 const PixelUnpackState &unpack, const uint8_t *pixels)
211{
Geoff Lang691e58c2014-12-19 17:03:25 -0500212 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500213
214 return mTexture->setCompressedSubImage(target, level, area, format, unpack, pixels);
215}
216
217Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat,
218 const Framebuffer *source)
219{
Geoff Lang691e58c2014-12-19 17:03:25 -0500220 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500221
222 Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
223 if (error.isError())
224 {
225 return error;
226 }
227
Geoff Lang7c973ea2014-12-19 15:58:28 -0500228 releaseTexImage();
229
Geoff Lang866dd2d2015-02-10 11:08:32 -0500230 setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
231 GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500232
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500233 return Error(GL_NO_ERROR);
234}
235
236Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea,
237 const Framebuffer *source)
238{
Geoff Lang691e58c2014-12-19 17:03:25 -0500239 ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500240
241 return mTexture->copySubImage(target, level, destOffset, sourceArea, source);
242}
243
244Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size)
245{
246 ASSERT(target == mTarget);
247
248 Error error = mTexture->setStorage(target, levels, internalFormat, size);
249 if (error.isError())
250 {
251 return error;
252 }
253
Geoff Lang7c973ea2014-12-19 15:58:28 -0500254 releaseTexImage();
255
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500256 mImmutableLevelCount = levels;
Geoff Langa9be0dc2014-12-17 12:34:40 -0500257 clearImageDescs();
258 setImageDescChain(levels, size, internalFormat);
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500259
260 return Error(GL_NO_ERROR);
261}
262
263
264Error Texture::generateMipmaps()
265{
Gregoire Payen de La Garanderie752ce192015-04-14 11:11:12 +0100266 Error error = mTexture->generateMipmaps(getSamplerState());
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500267 if (error.isError())
268 {
269 return error;
270 }
271
Geoff Lang7c973ea2014-12-19 15:58:28 -0500272 releaseTexImage();
273
Geoff Lang866dd2d2015-02-10 11:08:32 -0500274 const ImageDesc &baseImageInfo = getImageDesc(getBaseImageTarget(), 0);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500275 size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1;
276 setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat);
277
Geoff Lang0a4f1e22014-12-17 12:33:26 -0500278 return Error(GL_NO_ERROR);
279}
280
Geoff Langa9be0dc2014-12-17 12:34:40 -0500281void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat)
282{
283 for (size_t level = 0; level < levels; level++)
284 {
285 Extents levelSize(std::max<size_t>(baseSize.width >> level, 1),
286 std::max<size_t>(baseSize.height >> level, 1),
287 (mTarget == GL_TEXTURE_2D_ARRAY) ? baseSize.depth : std::max<size_t>(baseSize.depth >> level, 1));
288 ImageDesc levelInfo(levelSize, sizedInternalFormat);
289
290 if (mTarget == GL_TEXTURE_CUBE_MAP)
291 {
Geoff Lang691e58c2014-12-19 17:03:25 -0500292 for (size_t face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500293 {
Geoff Lang866dd2d2015-02-10 11:08:32 -0500294 setImageDesc(face, level, levelInfo);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500295 }
296 }
297 else
298 {
Geoff Lang866dd2d2015-02-10 11:08:32 -0500299 setImageDesc(mTarget, level, levelInfo);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500300 }
301 }
302}
303
Geoff Langa9be0dc2014-12-17 12:34:40 -0500304Texture::ImageDesc::ImageDesc()
305 : ImageDesc(Extents(0, 0, 0), GL_NONE)
306{
307}
308
309Texture::ImageDesc::ImageDesc(const Extents &size, GLenum internalFormat)
310 : size(size),
311 internalFormat(internalFormat)
312{
313}
314
Geoff Lang866dd2d2015-02-10 11:08:32 -0500315const Texture::ImageDesc &Texture::getImageDesc(GLenum target, size_t level) const
Geoff Langa9be0dc2014-12-17 12:34:40 -0500316{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500317 size_t descIndex = GetImageDescIndex(target, level);
318 ASSERT(descIndex < mImageDescs.size());
319 return mImageDescs[descIndex];
Geoff Langa9be0dc2014-12-17 12:34:40 -0500320}
321
Geoff Lang866dd2d2015-02-10 11:08:32 -0500322void Texture::setImageDesc(GLenum target, size_t level, const ImageDesc &desc)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500323{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500324 size_t descIndex = GetImageDescIndex(target, level);
325 ASSERT(descIndex < mImageDescs.size());
326 mImageDescs[descIndex] = desc;
Geoff Lang0fe40532015-02-10 12:01:27 -0500327 mCompletenessCache.cacheValid = false;
Geoff Langa9be0dc2014-12-17 12:34:40 -0500328}
329
Geoff Lang866dd2d2015-02-10 11:08:32 -0500330void Texture::clearImageDesc(GLenum target, size_t level)
Geoff Langb9266272015-01-29 13:25:14 +0000331{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500332 setImageDesc(target, level, ImageDesc());
Geoff Langb9266272015-01-29 13:25:14 +0000333}
334
Geoff Langa9be0dc2014-12-17 12:34:40 -0500335void Texture::clearImageDescs()
336{
Geoff Lang866dd2d2015-02-10 11:08:32 -0500337 for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
338 {
339 mImageDescs[descIndex] = ImageDesc();
340 }
Geoff Lang0fe40532015-02-10 12:01:27 -0500341 mCompletenessCache.cacheValid = false;
Geoff Langa9be0dc2014-12-17 12:34:40 -0500342}
343
Geoff Lang7c973ea2014-12-19 15:58:28 -0500344void Texture::bindTexImage(egl::Surface *surface)
345{
Geoff Langb9266272015-01-29 13:25:14 +0000346 ASSERT(surface);
347
Geoff Lang7c973ea2014-12-19 15:58:28 -0500348 releaseTexImage();
349 mTexture->bindTexImage(surface);
350 mBoundSurface = surface;
Geoff Langb9266272015-01-29 13:25:14 +0000351
352 // Set the image info to the size and format of the surface
353 ASSERT(mTarget == GL_TEXTURE_2D);
354 Extents size(surface->getWidth(), surface->getHeight(), 1);
Geoff Langc223dc62015-01-09 13:10:01 -0500355 ImageDesc desc(size, surface->getConfig()->renderTargetFormat);
Geoff Lang866dd2d2015-02-10 11:08:32 -0500356 setImageDesc(mTarget, 0, desc);
Geoff Lang7c973ea2014-12-19 15:58:28 -0500357}
358
359void Texture::releaseTexImage()
360{
361 if (mBoundSurface)
362 {
363 mBoundSurface = NULL;
364 mTexture->releaseTexImage();
Geoff Langb9266272015-01-29 13:25:14 +0000365
366 // Erase the image info for level 0
367 ASSERT(mTarget == GL_TEXTURE_2D);
Geoff Lang866dd2d2015-02-10 11:08:32 -0500368 clearImageDesc(mTarget, 0);
Geoff Lang7c973ea2014-12-19 15:58:28 -0500369 }
370}
371
Geoff Lang691e58c2014-12-19 17:03:25 -0500372GLenum Texture::getBaseImageTarget() const
Jamie Madill22f843a2013-10-24 17:49:36 -0400373{
Geoff Lang691e58c2014-12-19 17:03:25 -0500374 return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000375}
376
Geoff Lang691e58c2014-12-19 17:03:25 -0500377size_t Texture::getExpectedMipLevels() const
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000378{
Geoff Langb0eecdf2015-02-10 11:09:12 -0500379 const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), 0);
Geoff Lang691e58c2014-12-19 17:03:25 -0500380 if (mTarget == GL_TEXTURE_3D)
381 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500382 return log2(std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height), baseImageDesc.size.depth)) + 1;
Geoff Lang691e58c2014-12-19 17:03:25 -0500383 }
384 else
385 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500386 return log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)) + 1;
Geoff Lang691e58c2014-12-19 17:03:25 -0500387 }
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000388}
389
Geoff Lang0fe40532015-02-10 12:01:27 -0500390bool Texture::computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const
391{
392 const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel);
393 if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0)
394 {
395 return false;
396 }
397
398 if (mTarget == GL_TEXTURE_CUBE_MAP && baseImageDesc.size.width != baseImageDesc.size.height)
399 {
400 return false;
401 }
402
403 const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat);
404 if (!textureCaps.filterable && !IsPointSampled(samplerState))
405 {
406 return false;
407 }
408
409 bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3;
410 if (!npotSupport)
411 {
412 if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.width)) ||
413 (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.height)))
414 {
415 return false;
416 }
417 }
418
419 if (IsMipmapFiltered(samplerState))
420 {
421 if (!npotSupport)
422 {
423 if (!gl::isPow2(baseImageDesc.size.width) || !gl::isPow2(baseImageDesc.size.height))
424 {
425 return false;
426 }
427 }
428
429 if (!computeMipmapCompleteness(samplerState))
430 {
431 return false;
432 }
433 }
434 else
435 {
436 if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
437 {
438 return false;
439 }
440 }
441
442 // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
443 // The internalformat specified for the texture arrays is a sized internal depth or
444 // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
445 // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
446 // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
447 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(baseImageDesc.internalFormat);
448 if (formatInfo.depthBits > 0 && data.clientVersion > 2)
449 {
450 if (samplerState.compareMode == GL_NONE)
451 {
452 if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
453 samplerState.magFilter != GL_NEAREST)
454 {
455 return false;
456 }
457 }
458 }
459
460 return true;
461}
462
463bool Texture::computeMipmapCompleteness(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 {
Geoff Lang0fe40532015-02-10 12:01:27 -0500475 if (!computeLevelCompleteness(face, level, samplerState))
Geoff Lang691e58c2014-12-19 17:03:25 -0500476 {
477 return false;
478 }
479 }
480 }
481 else
482 {
Geoff Lang0fe40532015-02-10 12:01:27 -0500483 if (!computeLevelCompleteness(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
Geoff Lang0fe40532015-02-10 12:01:27 -0500494bool Texture::computeLevelCompleteness(GLenum target, size_t level, const gl::SamplerState &samplerState) const
Brandon Jones6053a522014-07-25 16:22:09 -0700495{
Geoff Langa9be0dc2014-12-17 12:34:40 -0500496 ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
497
Brandon Jones6053a522014-07-25 16:22:09 -0700498 if (isImmutable())
499 {
500 return true;
501 }
502
Geoff Langb0eecdf2015-02-10 11:09:12 -0500503 const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel);
504 if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0)
Brandon Jones6053a522014-07-25 16:22:09 -0700505 {
506 return false;
507 }
508
509 // The base image level is complete if the width and height are positive
510 if (level == 0)
511 {
512 return true;
513 }
514
Geoff Langb0eecdf2015-02-10 11:09:12 -0500515 const ImageDesc &levelImageDesc = getImageDesc(target, level);
516 if (levelImageDesc.internalFormat != baseImageDesc.internalFormat)
Brandon Jones6053a522014-07-25 16:22:09 -0700517 {
518 return false;
519 }
520
Geoff Langb0eecdf2015-02-10 11:09:12 -0500521 if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700522 {
523 return false;
524 }
525
Geoff Langb0eecdf2015-02-10 11:09:12 -0500526 if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700527 {
528 return false;
529 }
530
Geoff Lang691e58c2014-12-19 17:03:25 -0500531 if (mTarget == GL_TEXTURE_3D)
Brandon Jones6053a522014-07-25 16:22:09 -0700532 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500533 if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> level))
Brandon Jones6053a522014-07-25 16:22:09 -0700534 {
535 return false;
536 }
537 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500538 else if (mTarget == GL_TEXTURE_2D_ARRAY)
Brandon Jones6053a522014-07-25 16:22:09 -0700539 {
Geoff Langb0eecdf2015-02-10 11:09:12 -0500540 if (levelImageDesc.size.depth != baseImageDesc.size.depth)
Brandon Jones6053a522014-07-25 16:22:09 -0700541 {
542 return false;
543 }
544 }
545
546 return true;
547}
548
Geoff Lang0fe40532015-02-10 12:01:27 -0500549Texture::SamplerCompletenessCache::SamplerCompletenessCache()
550 : cacheValid(false),
551 samplerState(),
552 filterable(false),
553 clientVersion(0),
554 supportsNPOT(false),
555 samplerComplete(false)
556{
557}
558
Jamie Madill79481d62015-04-14 08:13:47 -0400559GLsizei Texture::getAttachmentWidth(const gl::FramebufferAttachment::Target &target) const
560{
561 return getWidth(target.textureIndex().type, target.textureIndex().mipIndex);
562}
563
564GLsizei Texture::getAttachmentHeight(const gl::FramebufferAttachment::Target &target) const
565{
566 return getHeight(target.textureIndex().type, target.textureIndex().mipIndex);
567}
568
569GLenum Texture::getAttachmentInternalFormat(const gl::FramebufferAttachment::Target &target) const
570{
571 return getInternalFormat(target.textureIndex().type, target.textureIndex().mipIndex);
572}
573
574GLsizei Texture::getAttachmentSamples(const gl::FramebufferAttachment::Target &/*target*/) const
575{
576 // Multisample textures not currently supported
577 return 0;
578}
579
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000580}