1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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_
14 #include "mozilla/Assertions.h"
15 #include "mozilla/Casting.h"
16 #include "mozilla/CheckedInt.h"
17 #include "mozilla/dom/TypedArray.h"
19 #include "CacheInvalidator.h"
20 #include "WebGLObjectModel.h"
21 #include "WebGLStrongTypes.h"
22 #include "WebGLTypes.h"
27 class WebGLFramebuffer
;
30 struct TexImageSource
;
34 class HTMLVideoElement
;
36 class ArrayBufferViewOrSharedArrayBufferView
;
44 struct DriverUnpackInfo
;
45 struct FormatUsageInfo
;
50 bool DoesTargetMatchDimensions(WebGLContext
* webgl
, TexImageTarget target
,
55 struct SamplingState final
{
56 // Only store that which changes validation.
57 TexMinFilter minFilter
= LOCAL_GL_NEAREST_MIPMAP_LINEAR
;
58 TexMagFilter magFilter
= LOCAL_GL_LINEAR
;
59 TexWrap wrapS
= LOCAL_GL_REPEAT
;
60 TexWrap wrapT
= LOCAL_GL_REPEAT
;
61 // TexWrap wrapR = LOCAL_GL_REPEAT;
62 // GLfloat minLod = -1000;
63 // GLfloat maxLod = 1000;
64 TexCompareMode compareMode
= LOCAL_GL_NONE
;
65 // TexCompareFunc compareFunc = LOCAL_GL_LEQUAL;
68 struct ImageInfo final
{
69 static const ImageInfo kUndefined
;
71 const webgl::FormatUsageInfo
* mFormat
= nullptr;
75 mutable Maybe
<std::vector
<bool>> mUninitializedSlices
;
80 size_t MemoryUsage() const;
82 bool IsDefined() const {
84 MOZ_ASSERT(!mWidth
&& !mHeight
&& !mDepth
);
91 Maybe
<ImageInfo
> NextMip(GLenum target
) const;
96 class WebGLTexture final
: public WebGLContextBoundObject
,
97 public CacheInvalidator
{
99 friend class WebGLContext
;
100 friend class WebGLFramebuffer
;
102 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(WebGLTexture
, override
)
104 ////////////////////////////////////
107 const GLuint mGLName
;
112 static const uint8_t kMaxFaceCount
= 6;
113 uint8_t mFaceCount
; // 6 for cube maps, 1 otherwise.
115 bool mImmutable
; // Set by texStorage*
116 uint8_t mImmutableLevelCount
;
118 uint32_t mBaseMipmapLevel
; // Set by texParameter (defaults to 0)
119 uint32_t mMaxMipmapLevel
; // Set by texParameter (defaults to 1000)
120 // You almost certainly don't want to query mMaxMipmapLevel.
121 // You almost certainly want MaxEffectiveMipmapLevel().
123 webgl::SamplingState mSamplingState
;
125 mutable const GLint
* mCurSwizzle
=
126 nullptr; // nullptr means 'default swizzle'.
130 struct CompletenessInfo final
{
132 bool powerOfTwo
= false;
133 bool mipmapComplete
= false;
134 const webgl::FormatUsageInfo
* usage
= nullptr;
135 const char* incompleteReason
= nullptr;
138 mutable CacheWeakMap
<const WebGLSampler
*, webgl::SampleableInfo
>
142 Maybe
<const CompletenessInfo
> CalcCompletenessInfo(
143 bool ensureInit
, bool skipMips
= false) const;
144 Maybe
<const webgl::SampleableInfo
> CalcSampleableInfo(
145 const WebGLSampler
*) const;
147 const webgl::SampleableInfo
* GetSampleableInfo(const WebGLSampler
*) const;
151 const auto& Immutable() const { return mImmutable
; }
152 const auto& ImmutableLevelCount() const { return mImmutableLevelCount
; }
155 uint32_t Es3_level_base() const {
156 const auto level_prime_base
= mBaseMipmapLevel
;
157 const auto level_immut
= mImmutableLevelCount
;
159 if (!mImmutable
) return level_prime_base
;
160 return std::min(level_prime_base
, level_immut
- 1u);
162 uint32_t Es3_level_max() const {
163 const auto level_base
= Es3_level_base();
164 const auto level_prime_max
= mMaxMipmapLevel
;
165 const auto level_immut
= mImmutableLevelCount
;
167 if (!mImmutable
) return level_prime_max
;
168 return std::min(std::max(level_base
, level_prime_max
), level_immut
- 1u);
171 // GLES 3.0.5 p158: `q`
172 uint32_t Es3_q() const; // "effective max mip level"
176 const auto& FaceCount() const { return mFaceCount
; }
178 // We can just max this out to 31, which is the number of unsigned bits in
180 static const uint8_t kMaxLevelCount
= 31;
182 // We store information about the various images that are part of this
183 // texture. (cubemap faces, mipmap levels)
184 webgl::ImageInfo mImageInfoArr
[kMaxLevelCount
* kMaxFaceCount
];
186 ////////////////////////////////////
188 WebGLTexture(WebGLContext
* webgl
, GLuint tex
);
190 TexTarget
Target() const { return mTarget
; }
193 ~WebGLTexture() override
;
196 ////////////////////////////////////
198 bool BindTexture(TexTarget texTarget
);
199 void GenerateMipmap();
200 Maybe
<double> GetTexParameter(GLenum pname
) const;
201 void TexParameter(TexTarget texTarget
, GLenum pname
, const FloatOrInt
& param
);
203 ////////////////////////////////////
204 // WebGLTextureUpload.cpp
207 void TexOrSubImageBlob(bool isSubImage
, TexImageTarget target
, GLint level
,
208 GLenum internalFormat
, GLint xOffset
, GLint yOffset
,
209 GLint zOffset
, const webgl::PackingInfo
& pi
,
210 const webgl::TexUnpackBlob
* blob
);
212 bool ValidateTexImageSpecification(TexImageTarget target
, uint32_t level
,
214 webgl::ImageInfo
** const out_imageInfo
);
215 bool ValidateTexImageSelection(TexImageTarget target
, uint32_t level
,
216 const uvec3
& offset
, const uvec3
& size
,
217 webgl::ImageInfo
** const out_imageInfo
);
219 bool ValidateUnpack(const webgl::TexUnpackBlob
* blob
, bool isFunc3D
,
220 const webgl::PackingInfo
& srcPI
) const;
223 void TexStorage(TexTarget target
, uint32_t levels
, GLenum sizedFormat
,
226 // TexSubImage iff `!respecFormat`
227 void TexImage(uint32_t level
, GLenum respecFormat
, const uvec3
& offset
,
228 const webgl::PackingInfo
& pi
, const webgl::TexUnpackBlobDesc
&);
230 // CompressedTexSubImage iff `sub`
231 void CompressedTexImage(bool sub
, GLenum imageTarget
, uint32_t level
,
232 GLenum formatEnum
, const uvec3
& offset
,
233 const uvec3
& size
, const Range
<const uint8_t>& src
,
234 const uint32_t pboImageSize
,
235 const Maybe
<uint64_t>& pboOffset
);
237 // CopyTexSubImage iff `!respecFormat`
238 void CopyTexImage(GLenum imageTarget
, uint32_t level
, GLenum respecFormat
,
239 const uvec3
& dstOffset
, const ivec2
& srcOffset
,
242 ////////////////////////////////////
245 void ClampLevelBaseAndMax();
246 void RefreshSwizzle() const;
248 static uint8_t FaceForTarget(TexImageTarget texImageTarget
) {
249 GLenum rawTexImageTarget
= texImageTarget
.get();
250 switch (rawTexImageTarget
) {
251 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
252 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
253 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
254 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
255 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
256 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
257 return AutoAssertCast(rawTexImageTarget
-
258 LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
266 auto& ImageInfoAtFace(uint8_t face
, uint32_t level
) {
267 MOZ_ASSERT(face
< mFaceCount
);
268 MOZ_ASSERT(level
< kMaxLevelCount
);
269 size_t pos
= (level
* mFaceCount
) + face
;
270 return mImageInfoArr
[pos
];
273 const auto& ImageInfoAtFace(uint8_t face
, uint32_t level
) const {
274 return const_cast<WebGLTexture
*>(this)->ImageInfoAtFace(face
, level
);
277 auto& ImageInfoAt(TexImageTarget texImageTarget
, GLint level
) {
278 const auto& face
= FaceForTarget(texImageTarget
);
279 return ImageInfoAtFace(face
, level
);
282 const auto& ImageInfoAt(TexImageTarget texImageTarget
, GLint level
) const {
283 return const_cast<WebGLTexture
*>(this)->ImageInfoAt(texImageTarget
, level
);
286 const auto& BaseImageInfo() const {
287 if (mBaseMipmapLevel
>= kMaxLevelCount
) return webgl::ImageInfo::kUndefined
;
289 return ImageInfoAtFace(0, mBaseMipmapLevel
);
292 size_t MemoryUsage() const;
294 bool EnsureImageDataInitialized(TexImageTarget target
, uint32_t level
);
295 void PopulateMipChain(uint32_t maxLevel
);
296 bool IsMipAndCubeComplete(uint32_t maxLevel
, bool ensureInit
,
297 bool* out_initFailed
) const;
300 bool IsCubeMap() const { return (mTarget
== LOCAL_GL_TEXTURE_CUBE_MAP
); }
303 inline TexImageTarget
TexImageTargetForTargetAndFace(TexTarget target
,
305 switch (target
.get()) {
306 case LOCAL_GL_TEXTURE_2D
:
307 case LOCAL_GL_TEXTURE_3D
:
308 MOZ_ASSERT(face
== 0);
310 case LOCAL_GL_TEXTURE_CUBE_MAP
:
311 MOZ_ASSERT(face
< 6);
312 return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ face
;
314 MOZ_CRASH("GFX: TexImageTargetForTargetAndFace");
318 already_AddRefed
<mozilla::layers::Image
> ImageFromVideo(
319 dom::HTMLVideoElement
* elem
);
321 bool IsTarget3D(TexImageTarget target
);
323 GLenum
DoTexImage(gl::GLContext
* gl
, TexImageTarget target
, GLint level
,
324 const webgl::DriverUnpackInfo
* dui
, GLsizei width
,
325 GLsizei height
, GLsizei depth
, const void* data
);
326 GLenum
DoTexSubImage(gl::GLContext
* gl
, TexImageTarget target
, GLint level
,
327 GLint xOffset
, GLint yOffset
, GLint zOffset
, GLsizei width
,
328 GLsizei height
, GLsizei depth
,
329 const webgl::PackingInfo
& pi
, const void* data
);
330 GLenum
DoCompressedTexSubImage(gl::GLContext
* gl
, TexImageTarget target
,
331 GLint level
, GLint xOffset
, GLint yOffset
,
332 GLint zOffset
, GLsizei width
, GLsizei height
,
333 GLsizei depth
, GLenum sizedUnpackFormat
,
334 GLsizei dataSize
, const void* data
);
336 } // namespace mozilla
338 #endif // WEBGL_TEXTURE_H_