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 // These "dirty" flags are set when the level is updated (eg indirectly by
124 // clamping) and cleared when we tell the driver.
125 enum MipmapLevelState
: uint8_t {
126 MIPMAP_LEVEL_DEFAULT
,
130 MipmapLevelState mBaseMipmapLevelState
= MIPMAP_LEVEL_DEFAULT
;
131 MipmapLevelState mMaxMipmapLevelState
= MIPMAP_LEVEL_DEFAULT
;
133 webgl::SamplingState mSamplingState
;
135 mutable const GLint
* mCurSwizzle
=
136 nullptr; // nullptr means 'default swizzle'.
140 struct CompletenessInfo final
{
142 bool powerOfTwo
= false;
143 bool mipmapComplete
= false;
144 const webgl::FormatUsageInfo
* usage
= nullptr;
145 const char* incompleteReason
= nullptr;
148 mutable CacheWeakMap
<const WebGLSampler
*, webgl::SampleableInfo
>
152 Maybe
<const CompletenessInfo
> CalcCompletenessInfo(
153 bool ensureInit
, bool skipMips
= false) const;
154 Maybe
<const webgl::SampleableInfo
> CalcSampleableInfo(
155 const WebGLSampler
*) const;
157 const webgl::SampleableInfo
* GetSampleableInfo(const WebGLSampler
*) const;
161 const auto& Immutable() const { return mImmutable
; }
162 const auto& ImmutableLevelCount() const { return mImmutableLevelCount
; }
165 uint32_t Es3_level_base() const {
166 const auto level_prime_base
= mBaseMipmapLevel
;
167 const auto level_immut
= mImmutableLevelCount
;
169 if (!mImmutable
) return level_prime_base
;
170 return std::min(level_prime_base
, level_immut
- 1u);
172 uint32_t Es3_level_max() const {
173 const auto level_base
= Es3_level_base();
174 const auto level_prime_max
= mMaxMipmapLevel
;
175 const auto level_immut
= mImmutableLevelCount
;
177 if (!mImmutable
) return level_prime_max
;
178 return std::min(std::max(level_base
, level_prime_max
), level_immut
- 1u);
181 // GLES 3.0.5 p158: `q`
182 uint32_t Es3_q() const; // "effective max mip level"
186 const auto& FaceCount() const { return mFaceCount
; }
188 // We can just max this out to 31, which is the number of unsigned bits in
190 static const uint8_t kMaxLevelCount
= 31;
192 // We store information about the various images that are part of this
193 // texture. (cubemap faces, mipmap levels)
194 webgl::ImageInfo mImageInfoArr
[kMaxLevelCount
* kMaxFaceCount
];
196 ////////////////////////////////////
198 WebGLTexture(WebGLContext
* webgl
, GLuint tex
);
200 TexTarget
Target() const { return mTarget
; }
203 ~WebGLTexture() override
;
206 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mso
) const {
207 return CacheInvalidator::SizeOfExcludingThis(mso
) +
208 mSamplingCache
.SizeOfExcludingThis(mso
);
210 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mso
) const {
211 return mso(this) + SizeOfExcludingThis(mso
);
214 ////////////////////////////////////
216 bool BindTexture(TexTarget texTarget
);
217 void GenerateMipmap();
218 Maybe
<double> GetTexParameter(GLenum pname
) const;
219 void TexParameter(TexTarget texTarget
, GLenum pname
, const FloatOrInt
& param
);
221 ////////////////////////////////////
222 // WebGLTextureUpload.cpp
225 void TexOrSubImageBlob(bool isSubImage
, TexImageTarget target
, GLint level
,
226 GLenum internalFormat
, GLint xOffset
, GLint yOffset
,
227 GLint zOffset
, const webgl::PackingInfo
& pi
,
228 const webgl::TexUnpackBlob
* blob
);
230 bool ValidateTexImageSpecification(TexImageTarget target
, uint32_t level
,
232 webgl::ImageInfo
** const out_imageInfo
);
233 bool ValidateTexImageSelection(TexImageTarget target
, uint32_t level
,
234 const uvec3
& offset
, const uvec3
& size
,
235 webgl::ImageInfo
** const out_imageInfo
);
237 bool ValidateUnpack(const webgl::TexUnpackBlob
* blob
, bool isFunc3D
,
238 const webgl::PackingInfo
& srcPI
) const;
241 void TexStorage(TexTarget target
, uint32_t levels
, GLenum sizedFormat
,
244 // TexSubImage iff `!respecFormat`
245 void TexImage(uint32_t level
, GLenum respecFormat
, const uvec3
& offset
,
246 const webgl::PackingInfo
& pi
, const webgl::TexUnpackBlobDesc
&);
248 // CompressedTexSubImage iff `sub`
249 void CompressedTexImage(bool sub
, GLenum imageTarget
, uint32_t level
,
250 GLenum formatEnum
, const uvec3
& offset
,
251 const uvec3
& size
, const Range
<const uint8_t>& src
,
252 const uint32_t pboImageSize
,
253 const Maybe
<uint64_t>& pboOffset
);
255 // CopyTexSubImage iff `!respecFormat`
256 void CopyTexImage(GLenum imageTarget
, uint32_t level
, GLenum respecFormat
,
257 const uvec3
& dstOffset
, const ivec2
& srcOffset
,
260 ////////////////////////////////////
263 void ClampLevelBaseAndMax();
264 void RefreshSwizzle() const;
266 static uint8_t FaceForTarget(TexImageTarget texImageTarget
) {
267 GLenum rawTexImageTarget
= texImageTarget
.get();
268 switch (rawTexImageTarget
) {
269 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
270 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
271 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
272 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
273 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
274 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
275 return AutoAssertCast(rawTexImageTarget
-
276 LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
284 auto& ImageInfoAtFace(uint8_t face
, uint32_t level
) {
285 MOZ_ASSERT(face
< mFaceCount
);
286 MOZ_ASSERT(level
< kMaxLevelCount
);
287 size_t pos
= (level
* mFaceCount
) + face
;
288 return mImageInfoArr
[pos
];
291 const auto& ImageInfoAtFace(uint8_t face
, uint32_t level
) const {
292 return const_cast<WebGLTexture
*>(this)->ImageInfoAtFace(face
, level
);
295 auto& ImageInfoAt(TexImageTarget texImageTarget
, GLint level
) {
296 const auto& face
= FaceForTarget(texImageTarget
);
297 return ImageInfoAtFace(face
, level
);
300 const auto& ImageInfoAt(TexImageTarget texImageTarget
, GLint level
) const {
301 return const_cast<WebGLTexture
*>(this)->ImageInfoAt(texImageTarget
, level
);
304 const auto& BaseImageInfo() const {
305 if (mBaseMipmapLevel
>= kMaxLevelCount
) return webgl::ImageInfo::kUndefined
;
307 return ImageInfoAtFace(0, mBaseMipmapLevel
);
310 size_t MemoryUsage() const;
312 bool EnsureImageDataInitialized(TexImageTarget target
, uint32_t level
);
313 void PopulateMipChain(uint32_t maxLevel
);
314 bool IsMipAndCubeComplete(uint32_t maxLevel
, bool ensureInit
,
315 bool* out_initFailed
) const;
318 bool IsCubeMap() const { return (mTarget
== LOCAL_GL_TEXTURE_CUBE_MAP
); }
321 inline TexImageTarget
TexImageTargetForTargetAndFace(TexTarget target
,
323 switch (target
.get()) {
324 case LOCAL_GL_TEXTURE_2D
:
325 case LOCAL_GL_TEXTURE_3D
:
326 MOZ_ASSERT(face
== 0);
328 case LOCAL_GL_TEXTURE_CUBE_MAP
:
329 MOZ_ASSERT(face
< 6);
330 return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ face
;
332 MOZ_CRASH("GFX: TexImageTargetForTargetAndFace");
336 already_AddRefed
<mozilla::layers::Image
> ImageFromVideo(
337 dom::HTMLVideoElement
* elem
);
339 bool IsTarget3D(TexImageTarget target
);
341 GLenum
DoTexImage(gl::GLContext
* gl
, TexImageTarget target
, GLint level
,
342 const webgl::DriverUnpackInfo
* dui
, GLsizei width
,
343 GLsizei height
, GLsizei depth
, const void* data
);
344 GLenum
DoTexSubImage(gl::GLContext
* gl
, TexImageTarget target
, GLint level
,
345 GLint xOffset
, GLint yOffset
, GLint zOffset
, GLsizei width
,
346 GLsizei height
, GLsizei depth
,
347 const webgl::PackingInfo
& pi
, const void* data
);
348 GLenum
DoCompressedTexSubImage(gl::GLContext
* gl
, TexImageTarget target
,
349 GLint level
, GLint xOffset
, GLint yOffset
,
350 GLint zOffset
, GLsizei width
, GLsizei height
,
351 GLsizei depth
, GLenum sizedUnpackFormat
,
352 GLsizei dataSize
, const void* data
);
354 } // namespace mozilla
356 #endif // WEBGL_TEXTURE_H_