Bumping manifests a=b2g-bump
[gecko.git] / dom / canvas / WebGLTexture.h
blobc8b99867d21b86c17c50b3deffc0d70aed9337aa
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef WEBGL_TEXTURE_H_
7 #define WEBGL_TEXTURE_H_
9 #include <algorithm>
10 #include "mozilla/Assertions.h"
11 #include "mozilla/CheckedInt.h"
12 #include "mozilla/LinkedList.h"
13 #include "nsAlgorithm.h"
14 #include "nsWrapperCache.h"
15 #include "WebGLBindableName.h"
16 #include "WebGLFramebufferAttachable.h"
17 #include "WebGLObjectModel.h"
18 #include "WebGLStrongTypes.h"
20 namespace mozilla {
22 // Zero is not an integer power of two.
23 inline bool
24 IsPOTAssumingNonnegative(GLsizei x)
26 MOZ_ASSERT(x >= 0);
27 return x && (x & (x-1)) == 0;
30 // NOTE: When this class is switched to new DOM bindings, update the (then-slow)
31 // WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
32 class WebGLTexture MOZ_FINAL
33 : public nsWrapperCache
34 , public WebGLBindableName<TexTarget>
35 , public WebGLRefCountedObject<WebGLTexture>
36 , public LinkedListElement<WebGLTexture>
37 , public WebGLContextBoundObject
38 , public WebGLFramebufferAttachable
40 public:
41 explicit WebGLTexture(WebGLContext* webgl, GLuint tex);
43 void Delete();
45 WebGLContext* GetParentObject() const {
46 return Context();
49 virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE;
51 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture)
52 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture)
54 protected:
55 ~WebGLTexture() {
56 DeleteOnce();
59 friend class WebGLContext;
60 friend class WebGLFramebuffer;
62 // We store information about the various images that are part of this
63 // texture. (cubemap faces, mipmap levels)
65 public:
66 class ImageInfo
67 : public WebGLRectangleObject
69 public:
70 ImageInfo()
71 : mEffectiveInternalFormat(LOCAL_GL_NONE)
72 , mDepth(0)
73 , mImageDataStatus(WebGLImageDataStatus::NoImageData)
76 ImageInfo(GLsizei width, GLsizei height, GLsizei depth,
77 TexInternalFormat effectiveInternalFormat,
78 WebGLImageDataStatus status)
79 : WebGLRectangleObject(width, height)
80 , mEffectiveInternalFormat(effectiveInternalFormat)
81 , mDepth(depth)
82 , mImageDataStatus(status)
84 // shouldn't use this constructor to construct a null ImageInfo
85 MOZ_ASSERT(status != WebGLImageDataStatus::NoImageData);
88 bool operator==(const ImageInfo& a) const {
89 return mImageDataStatus == a.mImageDataStatus &&
90 mWidth == a.mWidth &&
91 mHeight == a.mHeight &&
92 mDepth == a.mDepth &&
93 mEffectiveInternalFormat == a.mEffectiveInternalFormat;
95 bool operator!=(const ImageInfo& a) const {
96 return !(*this == a);
98 bool IsSquare() const {
99 return mWidth == mHeight;
101 bool IsPositive() const {
102 return mWidth > 0 && mHeight > 0 && mDepth > 0;
104 bool IsPowerOfTwo() const {
105 MOZ_ASSERT(mWidth >= 0);
106 MOZ_ASSERT(mHeight >= 0);
107 return IsPOTAssumingNonnegative(mWidth) &&
108 IsPOTAssumingNonnegative(mHeight);
110 bool HasUninitializedImageData() const {
111 return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
113 size_t MemoryUsage() const;
115 TexInternalFormat EffectiveInternalFormat() const {
116 return mEffectiveInternalFormat;
118 GLsizei Depth() const { return mDepth; }
120 protected:
121 // This is the "effective internal format" of the texture, an official
122 // OpenGL spec concept, see OpenGL ES 3.0.3 spec, section 3.8.3, page
123 // 126 and below.
124 TexInternalFormat mEffectiveInternalFormat;
126 /* Used only for 3D textures.
127 * Note that mWidth and mHeight are inherited from WebGLRectangleObject.
128 * It's a pity to store a useless mDepth on non-3D texture images, but
129 * the size of GLsizei is negligible compared to the typical size of a texture image.
131 GLsizei mDepth;
133 WebGLImageDataStatus mImageDataStatus;
135 friend class WebGLTexture;
138 private:
139 static size_t FaceForTarget(TexImageTarget texImageTarget) {
140 if (texImageTarget == LOCAL_GL_TEXTURE_2D ||
141 texImageTarget == LOCAL_GL_TEXTURE_3D)
143 return 0;
145 return texImageTarget.get() - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
148 ImageInfo& ImageInfoAtFace(size_t face, GLint level) {
149 MOZ_ASSERT(face < mFacesCount,
150 "Wrong face index, must be 0 for TEXTURE_2D or TEXTURE_3D,"
151 " and at most 5 for cube maps.");
153 // No need to check level as a wrong value would be caught by
154 // ElementAt().
155 return mImageInfos.ElementAt(level * mFacesCount + face);
158 const ImageInfo& ImageInfoAtFace(size_t face, GLint level) const {
159 return const_cast<const ImageInfo&>(
160 const_cast<WebGLTexture*>(this)->ImageInfoAtFace(face, level)
164 public:
165 ImageInfo& ImageInfoAt(TexImageTarget imageTarget, GLint level) {
166 size_t face = FaceForTarget(imageTarget);
167 return ImageInfoAtFace(face, level);
170 const ImageInfo& ImageInfoAt(TexImageTarget imageTarget, GLint level) const
172 return const_cast<WebGLTexture*>(this)->ImageInfoAt(imageTarget, level);
175 bool HasImageInfoAt(TexImageTarget imageTarget, GLint level) const {
176 size_t face = FaceForTarget(imageTarget);
177 CheckedUint32 checked_index = CheckedUint32(level) * mFacesCount + face;
178 return checked_index.isValid() &&
179 checked_index.value() < mImageInfos.Length() &&
180 ImageInfoAt(imageTarget, level).mImageDataStatus != WebGLImageDataStatus::NoImageData;
183 ImageInfo& ImageInfoBase() {
184 return ImageInfoAtFace(0, 0);
187 const ImageInfo& ImageInfoBase() const {
188 return ImageInfoAtFace(0, 0);
191 size_t MemoryUsage() const;
193 void SetImageDataStatus(TexImageTarget imageTarget, GLint level,
194 WebGLImageDataStatus newStatus)
196 MOZ_ASSERT(HasImageInfoAt(imageTarget, level));
197 ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
198 // There is no way to go from having image data to not having any.
199 MOZ_ASSERT(newStatus != WebGLImageDataStatus::NoImageData ||
200 imageInfo.mImageDataStatus == WebGLImageDataStatus::NoImageData);
202 if (imageInfo.mImageDataStatus != newStatus)
203 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
205 imageInfo.mImageDataStatus = newStatus;
208 void EnsureNoUninitializedImageData(TexImageTarget imageTarget, GLint level);
210 protected:
211 TexMinFilter mMinFilter;
212 TexMagFilter mMagFilter;
213 TexWrap mWrapS, mWrapT;
215 size_t mFacesCount, mMaxLevelWithCustomImages;
216 nsTArray<ImageInfo> mImageInfos;
218 bool mHaveGeneratedMipmap; // Set by generateMipmap
219 bool mImmutable; // Set by texStorage*
221 size_t mBaseMipmapLevel; // Set by texParameter (defaults to 0)
222 size_t mMaxMipmapLevel; // Set by texParameter (defaults to 1000)
224 WebGLTextureFakeBlackStatus mFakeBlackStatus;
226 void EnsureMaxLevelWithCustomImagesAtLeast(size_t maxLevelWithCustomImages) {
227 mMaxLevelWithCustomImages = std::max(mMaxLevelWithCustomImages,
228 maxLevelWithCustomImages);
229 mImageInfos.EnsureLengthAtLeast((mMaxLevelWithCustomImages + 1) * mFacesCount);
232 bool CheckFloatTextureFilterParams() const {
233 // Without OES_texture_float_linear, only NEAREST and
234 // NEAREST_MIMPAMP_NEAREST are supported.
235 return mMagFilter == LOCAL_GL_NEAREST &&
236 (mMinFilter == LOCAL_GL_NEAREST ||
237 mMinFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST);
240 bool AreBothWrapModesClampToEdge() const {
241 return mWrapS == LOCAL_GL_CLAMP_TO_EDGE &&
242 mWrapT == LOCAL_GL_CLAMP_TO_EDGE;
245 bool DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const;
247 public:
248 void Bind(TexTarget texTarget);
250 void SetImageInfo(TexImageTarget target, GLint level, GLsizei width,
251 GLsizei height, GLsizei depth, TexInternalFormat format,
252 WebGLImageDataStatus status);
254 void SetMinFilter(TexMinFilter minFilter) {
255 mMinFilter = minFilter;
256 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
258 void SetMagFilter(TexMagFilter magFilter) {
259 mMagFilter = magFilter;
260 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
262 void SetWrapS(TexWrap wrapS) {
263 mWrapS = wrapS;
264 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
266 void SetWrapT(TexWrap wrapT) {
267 mWrapT = wrapT;
268 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
270 TexMinFilter MinFilter() const { return mMinFilter; }
272 bool DoesMinFilterRequireMipmap() const {
273 return !(mMinFilter == LOCAL_GL_NEAREST ||
274 mMinFilter == LOCAL_GL_LINEAR);
277 void SetGeneratedMipmap();
279 void SetCustomMipmap();
281 bool IsFirstImagePowerOfTwo() const {
282 return ImageInfoBase().IsPowerOfTwo();
285 bool AreAllLevel0ImageInfosEqual() const;
287 bool IsMipmapComplete() const;
289 bool IsCubeComplete() const;
291 bool IsMipmapCubeComplete() const;
293 void SetFakeBlackStatus(WebGLTextureFakeBlackStatus x);
295 bool IsImmutable() const { return mImmutable; }
296 void SetImmutable() { mImmutable = true; }
298 void SetBaseMipmapLevel(size_t level) { mBaseMipmapLevel = level; }
299 void SetMaxMipmapLevel(size_t level) { mMaxMipmapLevel = level; }
301 // Clamping (from ES 3.0.4, section 3.8 - Texturing). When not immutable,
302 // the ranges must be guarded.
303 size_t EffectiveBaseMipmapLevel() const {
304 if (IsImmutable())
305 return std::min(mBaseMipmapLevel, mMaxLevelWithCustomImages);
306 return mBaseMipmapLevel;
308 size_t EffectiveMaxMipmapLevel() const {
309 if (IsImmutable()) {
310 return mozilla::clamped(mMaxMipmapLevel, EffectiveBaseMipmapLevel(),
311 mMaxLevelWithCustomImages);
313 return std::min(mMaxMipmapLevel, mMaxLevelWithCustomImages);
315 bool IsMipmapRangeValid() const;
317 size_t MaxLevelWithCustomImages() const { return mMaxLevelWithCustomImages; }
319 // Returns the current fake-black-status, except if it was Unknown,
320 // in which case this function resolves it first, so it never returns Unknown.
321 WebGLTextureFakeBlackStatus ResolvedFakeBlackStatus();
324 inline TexImageTarget
325 TexImageTargetForTargetAndFace(TexTarget target, size_t face)
327 switch (target.get()) {
328 case LOCAL_GL_TEXTURE_2D:
329 case LOCAL_GL_TEXTURE_3D:
330 MOZ_ASSERT(face == 0);
331 return target.get();
332 case LOCAL_GL_TEXTURE_CUBE_MAP:
333 MOZ_ASSERT(face < 6);
334 return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
335 default:
336 MOZ_CRASH();
340 } // namespace mozilla
342 #endif // WEBGL_TEXTURE_H_