Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
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 WEBGLTEXTURE_H_
7 #define WEBGLTEXTURE_H_
9 #include "WebGLObjectModel.h"
10 #include "WebGLFramebufferAttachable.h"
12 #include "nsWrapperCache.h"
14 #include "mozilla/LinkedList.h"
15 #include <algorithm>
17 namespace mozilla {
19 // Zero is not an integer power of two.
20 inline bool is_pot_assuming_nonnegative(GLsizei x)
21 {
22 return x && (x & (x-1)) == 0;
23 }
25 // NOTE: When this class is switched to new DOM bindings, update the (then-slow)
26 // WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
27 class WebGLTexture MOZ_FINAL
28 : public nsWrapperCache
29 , public WebGLRefCountedObject<WebGLTexture>
30 , public LinkedListElement<WebGLTexture>
31 , public WebGLContextBoundObject
32 , public WebGLFramebufferAttachable
33 {
34 public:
35 WebGLTexture(WebGLContext *context);
37 ~WebGLTexture() {
38 DeleteOnce();
39 }
41 void Delete();
43 bool HasEverBeenBound() const { return mHasEverBeenBound; }
44 void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
45 GLuint GLName() const { return mGLName; }
46 GLenum Target() const { return mTarget; }
48 WebGLContext *GetParentObject() const {
49 return Context();
50 }
52 virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
54 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture)
55 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture)
57 protected:
59 friend class WebGLContext;
60 friend class WebGLFramebuffer;
62 bool mHasEverBeenBound;
63 GLuint mGLName;
65 // we store information about the various images that are part of
66 // this texture (cubemap faces, mipmap levels)
68 public:
70 class ImageInfo
71 : public WebGLRectangleObject
72 {
73 public:
74 ImageInfo()
75 : mWebGLFormat(LOCAL_GL_NONE)
76 , mWebGLType(LOCAL_GL_NONE)
77 , mImageDataStatus(WebGLImageDataStatus::NoImageData)
78 {}
80 ImageInfo(GLsizei width,
81 GLsizei height,
82 GLenum webGLFormat,
83 GLenum webGLType,
84 WebGLImageDataStatus status)
85 : WebGLRectangleObject(width, height)
86 , mWebGLFormat(webGLFormat)
87 , mWebGLType(webGLType)
88 , mImageDataStatus(status)
89 {
90 // shouldn't use this constructor to construct a null ImageInfo
91 MOZ_ASSERT(status != WebGLImageDataStatus::NoImageData);
92 }
94 bool operator==(const ImageInfo& a) const {
95 return mImageDataStatus == a.mImageDataStatus &&
96 mWidth == a.mWidth &&
97 mHeight == a.mHeight &&
98 mWebGLFormat == a.mWebGLFormat &&
99 mWebGLType == a.mWebGLType;
100 }
101 bool operator!=(const ImageInfo& a) const {
102 return !(*this == a);
103 }
104 bool IsSquare() const {
105 return mWidth == mHeight;
106 }
107 bool IsPositive() const {
108 return mWidth > 0 && mHeight > 0;
109 }
110 bool IsPowerOfTwo() const {
111 return is_pot_assuming_nonnegative(mWidth) &&
112 is_pot_assuming_nonnegative(mHeight); // negative sizes should never happen (caught in texImage2D...)
113 }
114 bool HasUninitializedImageData() const {
115 return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
116 }
117 int64_t MemoryUsage() const;
118 /*! This is the format passed from JS to WebGL.
119 * It can be converted to a value to be passed to driver with
120 * DriverFormatsFromFormatAndType().
121 */
122 GLenum WebGLFormat() const { return mWebGLFormat; }
123 /*! This is the type passed from JS to WebGL.
124 * It can be converted to a value to be passed to driver with
125 * DriverTypeFromType().
126 */
127 GLenum WebGLType() const { return mWebGLType; }
129 protected:
130 GLenum mWebGLFormat; //!< This is the WebGL/GLES format
131 GLenum mWebGLType; //!< This is the WebGL/GLES type
132 WebGLImageDataStatus mImageDataStatus;
134 friend class WebGLTexture;
135 };
137 private:
138 static size_t FaceForTarget(GLenum target) {
139 // Call this out explicitly:
140 MOZ_ASSERT(target != LOCAL_GL_TEXTURE_CUBE_MAP);
141 MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
142 (target >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
143 target <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z));
144 return target == LOCAL_GL_TEXTURE_2D ? 0 : target - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
145 }
147 ImageInfo& ImageInfoAtFace(size_t face, GLint level) {
148 MOZ_ASSERT(face < mFacesCount, "wrong face index, must be 0 for TEXTURE_2D and at most 5 for cube maps");
150 // no need to check level as a wrong value would be caught by ElementAt().
151 return mImageInfos.ElementAt(level * mFacesCount + face);
152 }
154 const ImageInfo& ImageInfoAtFace(size_t face, GLint level) const {
155 return const_cast<const ImageInfo&>(
156 const_cast<WebGLTexture*>(this)->ImageInfoAtFace(face, level)
157 );
158 }
160 public:
161 ImageInfo& ImageInfoAt(GLenum imageTarget, GLint level) {
162 MOZ_ASSERT(imageTarget);
164 size_t face = FaceForTarget(imageTarget);
165 return ImageInfoAtFace(face, level);
166 }
168 const ImageInfo& ImageInfoAt(GLenum imageTarget, GLint level) const {
169 return const_cast<WebGLTexture*>(this)->ImageInfoAt(imageTarget, level);
170 }
172 bool HasImageInfoAt(GLenum imageTarget, GLint level) const {
173 MOZ_ASSERT(imageTarget);
175 size_t face = FaceForTarget(imageTarget);
176 CheckedUint32 checked_index = CheckedUint32(level) * mFacesCount + face;
177 return checked_index.isValid() &&
178 checked_index.value() < mImageInfos.Length() &&
179 ImageInfoAt(imageTarget, level).mImageDataStatus != WebGLImageDataStatus::NoImageData;
180 }
182 ImageInfo& ImageInfoBase() {
183 return ImageInfoAtFace(0, 0);
184 }
186 const ImageInfo& ImageInfoBase() const {
187 return ImageInfoAtFace(0, 0);
188 }
190 int64_t MemoryUsage() const;
192 void SetImageDataStatus(GLenum imageTarget, GLint level, WebGLImageDataStatus newStatus) {
193 MOZ_ASSERT(HasImageInfoAt(imageTarget, level));
194 ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
195 // there is no way to go from having image data to not having any
196 MOZ_ASSERT(newStatus != WebGLImageDataStatus::NoImageData ||
197 imageInfo.mImageDataStatus == WebGLImageDataStatus::NoImageData);
198 if (imageInfo.mImageDataStatus != newStatus) {
199 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
200 }
201 imageInfo.mImageDataStatus = newStatus;
202 }
204 void DoDeferredImageInitialization(GLenum imageTarget, GLint level);
206 protected:
208 GLenum mTarget;
209 GLenum mMinFilter, mMagFilter, mWrapS, mWrapT;
211 size_t mFacesCount, mMaxLevelWithCustomImages;
212 nsTArray<ImageInfo> mImageInfos;
214 bool mHaveGeneratedMipmap;
215 WebGLTextureFakeBlackStatus mFakeBlackStatus;
217 void EnsureMaxLevelWithCustomImagesAtLeast(size_t aMaxLevelWithCustomImages) {
218 mMaxLevelWithCustomImages = std::max(mMaxLevelWithCustomImages, aMaxLevelWithCustomImages);
219 mImageInfos.EnsureLengthAtLeast((mMaxLevelWithCustomImages + 1) * mFacesCount);
220 }
222 bool CheckFloatTextureFilterParams() const {
223 // Without OES_texture_float_linear, only NEAREST and NEAREST_MIMPAMP_NEAREST are supported
224 return (mMagFilter == LOCAL_GL_NEAREST) &&
225 (mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST);
226 }
228 bool AreBothWrapModesClampToEdge() const {
229 return mWrapS == LOCAL_GL_CLAMP_TO_EDGE && mWrapT == LOCAL_GL_CLAMP_TO_EDGE;
230 }
232 bool DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(GLenum texImageTarget) const;
234 public:
236 void Bind(GLenum aTarget);
238 void SetImageInfo(GLenum aTarget, GLint aLevel,
239 GLsizei aWidth, GLsizei aHeight,
240 GLenum aFormat, GLenum aType, WebGLImageDataStatus aStatus);
242 void SetMinFilter(GLenum aMinFilter) {
243 mMinFilter = aMinFilter;
244 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
245 }
246 void SetMagFilter(GLenum aMagFilter) {
247 mMagFilter = aMagFilter;
248 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
249 }
250 void SetWrapS(GLenum aWrapS) {
251 mWrapS = aWrapS;
252 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
253 }
254 void SetWrapT(GLenum aWrapT) {
255 mWrapT = aWrapT;
256 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
257 }
258 GLenum MinFilter() const { return mMinFilter; }
260 bool DoesMinFilterRequireMipmap() const {
261 return !(mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_LINEAR);
262 }
264 void SetGeneratedMipmap();
266 void SetCustomMipmap();
268 bool IsFirstImagePowerOfTwo() const {
269 return ImageInfoBase().IsPowerOfTwo();
270 }
272 bool AreAllLevel0ImageInfosEqual() const;
274 bool IsMipmapTexture2DComplete() const;
276 bool IsCubeComplete() const;
278 bool IsMipmapCubeComplete() const;
280 void SetFakeBlackStatus(WebGLTextureFakeBlackStatus x) {
281 mFakeBlackStatus = x;
282 mContext->SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
283 }
284 // Returns the current fake-black-status, except if it was Unknown,
285 // in which case this function resolves it first, so it never returns Unknown.
286 WebGLTextureFakeBlackStatus ResolvedFakeBlackStatus();
287 };
289 } // namespace mozilla
291 #endif