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 "WebGLBindableName.h"
10 #include "WebGLFramebufferAttachable.h"
11 #include "WebGLObjectModel.h"
13 #include "nsWrapperCache.h"
15 #include "mozilla/CheckedInt.h"
16 #include "mozilla/LinkedList.h"
21 // Zero is not an integer power of two.
22 inline bool is_pot_assuming_nonnegative(GLsizei x
)
24 return x
&& (x
& (x
-1)) == 0;
27 // NOTE: When this class is switched to new DOM bindings, update the (then-slow)
28 // WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
29 class WebGLTexture MOZ_FINAL
30 : public nsWrapperCache
31 , public WebGLBindableName
32 , public WebGLRefCountedObject
<WebGLTexture
>
33 , public LinkedListElement
<WebGLTexture
>
34 , public WebGLContextBoundObject
35 , public WebGLFramebufferAttachable
38 WebGLTexture(WebGLContext
*context
);
42 WebGLContext
*GetParentObject() const {
46 virtual JSObject
* WrapObject(JSContext
*cx
) MOZ_OVERRIDE
;
48 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture
)
49 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture
)
56 friend class WebGLContext
;
57 friend class WebGLFramebuffer
;
59 // we store information about the various images that are part of
60 // this texture (cubemap faces, mipmap levels)
65 : public WebGLRectangleObject
69 : mWebGLFormat(LOCAL_GL_NONE
)
70 , mWebGLType(LOCAL_GL_NONE
)
71 , mImageDataStatus(WebGLImageDataStatus::NoImageData
)
74 ImageInfo(GLsizei width
,
78 WebGLImageDataStatus status
)
79 : WebGLRectangleObject(width
, height
)
80 , mWebGLFormat(webGLFormat
)
81 , mWebGLType(webGLType
)
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
&&
91 mHeight
== a
.mHeight
&&
92 mWebGLFormat
== a
.mWebGLFormat
&&
93 mWebGLType
== a
.mWebGLType
;
95 bool operator!=(const ImageInfo
& a
) const {
98 bool IsSquare() const {
99 return mWidth
== mHeight
;
101 bool IsPositive() const {
102 return mWidth
> 0 && mHeight
> 0;
104 bool IsPowerOfTwo() const {
105 return is_pot_assuming_nonnegative(mWidth
) &&
106 is_pot_assuming_nonnegative(mHeight
); // negative sizes should never happen (caught in texImage2D...)
108 bool HasUninitializedImageData() const {
109 return mImageDataStatus
== WebGLImageDataStatus::UninitializedImageData
;
111 int64_t MemoryUsage() const;
112 /*! This is the format passed from JS to WebGL.
113 * It can be converted to a value to be passed to driver with
114 * DriverFormatsFromFormatAndType().
116 GLenum
WebGLFormat() const { return mWebGLFormat
; }
117 /*! This is the type passed from JS to WebGL.
118 * It can be converted to a value to be passed to driver with
119 * DriverTypeFromType().
121 GLenum
WebGLType() const { return mWebGLType
; }
124 GLenum mWebGLFormat
; //!< This is the WebGL/GLES format
125 GLenum mWebGLType
; //!< This is the WebGL/GLES type
126 WebGLImageDataStatus mImageDataStatus
;
128 friend class WebGLTexture
;
132 static size_t FaceForTarget(GLenum target
) {
133 // Call this out explicitly:
134 MOZ_ASSERT(target
!= LOCAL_GL_TEXTURE_CUBE_MAP
);
135 MOZ_ASSERT(target
== LOCAL_GL_TEXTURE_2D
||
136 (target
>= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
137 target
<= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
));
138 return target
== LOCAL_GL_TEXTURE_2D
? 0 : target
- LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
141 ImageInfo
& ImageInfoAtFace(size_t face
, GLint level
) {
142 MOZ_ASSERT(face
< mFacesCount
, "wrong face index, must be 0 for TEXTURE_2D and at most 5 for cube maps");
144 // no need to check level as a wrong value would be caught by ElementAt().
145 return mImageInfos
.ElementAt(level
* mFacesCount
+ face
);
148 const ImageInfo
& ImageInfoAtFace(size_t face
, GLint level
) const {
149 return const_cast<const ImageInfo
&>(
150 const_cast<WebGLTexture
*>(this)->ImageInfoAtFace(face
, level
)
155 ImageInfo
& ImageInfoAt(GLenum imageTarget
, GLint level
) {
156 MOZ_ASSERT(imageTarget
);
158 size_t face
= FaceForTarget(imageTarget
);
159 return ImageInfoAtFace(face
, level
);
162 const ImageInfo
& ImageInfoAt(GLenum imageTarget
, GLint level
) const {
163 return const_cast<WebGLTexture
*>(this)->ImageInfoAt(imageTarget
, level
);
166 bool HasImageInfoAt(GLenum imageTarget
, GLint level
) const {
167 MOZ_ASSERT(imageTarget
);
169 size_t face
= FaceForTarget(imageTarget
);
170 CheckedUint32 checked_index
= CheckedUint32(level
) * mFacesCount
+ face
;
171 return checked_index
.isValid() &&
172 checked_index
.value() < mImageInfos
.Length() &&
173 ImageInfoAt(imageTarget
, level
).mImageDataStatus
!= WebGLImageDataStatus::NoImageData
;
176 ImageInfo
& ImageInfoBase() {
177 return ImageInfoAtFace(0, 0);
180 const ImageInfo
& ImageInfoBase() const {
181 return ImageInfoAtFace(0, 0);
184 int64_t MemoryUsage() const;
186 void SetImageDataStatus(GLenum imageTarget
, GLint level
, WebGLImageDataStatus newStatus
) {
187 MOZ_ASSERT(HasImageInfoAt(imageTarget
, level
));
188 ImageInfo
& imageInfo
= ImageInfoAt(imageTarget
, level
);
189 // there is no way to go from having image data to not having any
190 MOZ_ASSERT(newStatus
!= WebGLImageDataStatus::NoImageData
||
191 imageInfo
.mImageDataStatus
== WebGLImageDataStatus::NoImageData
);
192 if (imageInfo
.mImageDataStatus
!= newStatus
) {
193 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown
);
195 imageInfo
.mImageDataStatus
= newStatus
;
198 void DoDeferredImageInitialization(GLenum imageTarget
, GLint level
);
202 GLenum mMinFilter
, mMagFilter
, mWrapS
, mWrapT
;
204 size_t mFacesCount
, mMaxLevelWithCustomImages
;
205 nsTArray
<ImageInfo
> mImageInfos
;
207 bool mHaveGeneratedMipmap
;
208 WebGLTextureFakeBlackStatus mFakeBlackStatus
;
210 void EnsureMaxLevelWithCustomImagesAtLeast(size_t aMaxLevelWithCustomImages
) {
211 mMaxLevelWithCustomImages
= std::max(mMaxLevelWithCustomImages
, aMaxLevelWithCustomImages
);
212 mImageInfos
.EnsureLengthAtLeast((mMaxLevelWithCustomImages
+ 1) * mFacesCount
);
215 bool CheckFloatTextureFilterParams() const {
216 // Without OES_texture_float_linear, only NEAREST and NEAREST_MIMPAMP_NEAREST are supported
217 return (mMagFilter
== LOCAL_GL_NEAREST
) &&
218 (mMinFilter
== LOCAL_GL_NEAREST
|| mMinFilter
== LOCAL_GL_NEAREST_MIPMAP_NEAREST
);
221 bool AreBothWrapModesClampToEdge() const {
222 return mWrapS
== LOCAL_GL_CLAMP_TO_EDGE
&& mWrapT
== LOCAL_GL_CLAMP_TO_EDGE
;
225 bool DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(GLenum texImageTarget
) const;
229 void Bind(GLenum aTarget
);
231 void SetImageInfo(GLenum aTarget
, GLint aLevel
,
232 GLsizei aWidth
, GLsizei aHeight
,
233 GLenum aFormat
, GLenum aType
, WebGLImageDataStatus aStatus
);
235 void SetMinFilter(GLenum aMinFilter
) {
236 mMinFilter
= aMinFilter
;
237 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown
);
239 void SetMagFilter(GLenum aMagFilter
) {
240 mMagFilter
= aMagFilter
;
241 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown
);
243 void SetWrapS(GLenum aWrapS
) {
245 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown
);
247 void SetWrapT(GLenum aWrapT
) {
249 SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown
);
251 GLenum
MinFilter() const { return mMinFilter
; }
253 bool DoesMinFilterRequireMipmap() const {
254 return !(mMinFilter
== LOCAL_GL_NEAREST
|| mMinFilter
== LOCAL_GL_LINEAR
);
257 void SetGeneratedMipmap();
259 void SetCustomMipmap();
261 bool IsFirstImagePowerOfTwo() const {
262 return ImageInfoBase().IsPowerOfTwo();
265 bool AreAllLevel0ImageInfosEqual() const;
267 bool IsMipmapTexture2DComplete() const;
269 bool IsCubeComplete() const;
271 bool IsMipmapCubeComplete() const;
273 void SetFakeBlackStatus(WebGLTextureFakeBlackStatus x
);
275 // Returns the current fake-black-status, except if it was Unknown,
276 // in which case this function resolves it first, so it never returns Unknown.
277 WebGLTextureFakeBlackStatus
ResolvedFakeBlackStatus();
280 } // namespace mozilla