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 ////////////////////////////////////
208 bool BindTexture(TexTarget texTarget
);
209 void GenerateMipmap();
210 Maybe
<double> GetTexParameter(GLenum pname
) const;
211 void TexParameter(TexTarget texTarget
, GLenum pname
, const FloatOrInt
& param
);
213 ////////////////////////////////////
214 // WebGLTextureUpload.cpp
217 void TexOrSubImageBlob(bool isSubImage
, TexImageTarget target
, GLint level
,
218 GLenum internalFormat
, GLint xOffset
, GLint yOffset
,
219 GLint zOffset
, const webgl::PackingInfo
& pi
,
220 const webgl::TexUnpackBlob
* blob
);
222 bool ValidateTexImageSpecification(TexImageTarget target
, uint32_t level
,
224 webgl::ImageInfo
** const out_imageInfo
);
225 bool ValidateTexImageSelection(TexImageTarget target
, uint32_t level
,
226 const uvec3
& offset
, const uvec3
& size
,
227 webgl::ImageInfo
** const out_imageInfo
);
229 bool ValidateUnpack(const webgl::TexUnpackBlob
* blob
, bool isFunc3D
,
230 const webgl::PackingInfo
& srcPI
) const;
233 void TexStorage(TexTarget target
, uint32_t levels
, GLenum sizedFormat
,
236 // TexSubImage iff `!respecFormat`
237 void TexImage(uint32_t level
, GLenum respecFormat
, const uvec3
& offset
,
238 const webgl::PackingInfo
& pi
, const webgl::TexUnpackBlobDesc
&);
240 // CompressedTexSubImage iff `sub`
241 void CompressedTexImage(bool sub
, GLenum imageTarget
, uint32_t level
,
242 GLenum formatEnum
, const uvec3
& offset
,
243 const uvec3
& size
, const Range
<const uint8_t>& src
,
244 const uint32_t pboImageSize
,
245 const Maybe
<uint64_t>& pboOffset
);
247 // CopyTexSubImage iff `!respecFormat`
248 void CopyTexImage(GLenum imageTarget
, uint32_t level
, GLenum respecFormat
,
249 const uvec3
& dstOffset
, const ivec2
& srcOffset
,
252 ////////////////////////////////////
255 void ClampLevelBaseAndMax();
256 void RefreshSwizzle() const;
258 static uint8_t FaceForTarget(TexImageTarget texImageTarget
) {
259 GLenum rawTexImageTarget
= texImageTarget
.get();
260 switch (rawTexImageTarget
) {
261 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
262 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
263 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
264 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
265 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
266 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
267 return AutoAssertCast(rawTexImageTarget
-
268 LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
276 auto& ImageInfoAtFace(uint8_t face
, uint32_t level
) {
277 MOZ_ASSERT(face
< mFaceCount
);
278 MOZ_ASSERT(level
< kMaxLevelCount
);
279 size_t pos
= (level
* mFaceCount
) + face
;
280 return mImageInfoArr
[pos
];
283 const auto& ImageInfoAtFace(uint8_t face
, uint32_t level
) const {
284 return const_cast<WebGLTexture
*>(this)->ImageInfoAtFace(face
, level
);
287 auto& ImageInfoAt(TexImageTarget texImageTarget
, GLint level
) {
288 const auto& face
= FaceForTarget(texImageTarget
);
289 return ImageInfoAtFace(face
, level
);
292 const auto& ImageInfoAt(TexImageTarget texImageTarget
, GLint level
) const {
293 return const_cast<WebGLTexture
*>(this)->ImageInfoAt(texImageTarget
, level
);
296 const auto& BaseImageInfo() const {
297 if (mBaseMipmapLevel
>= kMaxLevelCount
) return webgl::ImageInfo::kUndefined
;
299 return ImageInfoAtFace(0, mBaseMipmapLevel
);
302 size_t MemoryUsage() const;
304 bool EnsureImageDataInitialized(TexImageTarget target
, uint32_t level
);
305 void PopulateMipChain(uint32_t maxLevel
);
306 bool IsMipAndCubeComplete(uint32_t maxLevel
, bool ensureInit
,
307 bool* out_initFailed
) const;
310 bool IsCubeMap() const { return (mTarget
== LOCAL_GL_TEXTURE_CUBE_MAP
); }
313 inline TexImageTarget
TexImageTargetForTargetAndFace(TexTarget target
,
315 switch (target
.get()) {
316 case LOCAL_GL_TEXTURE_2D
:
317 case LOCAL_GL_TEXTURE_3D
:
318 MOZ_ASSERT(face
== 0);
320 case LOCAL_GL_TEXTURE_CUBE_MAP
:
321 MOZ_ASSERT(face
< 6);
322 return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ face
;
324 MOZ_CRASH("GFX: TexImageTargetForTargetAndFace");
328 already_AddRefed
<mozilla::layers::Image
> ImageFromVideo(
329 dom::HTMLVideoElement
* elem
);
331 bool IsTarget3D(TexImageTarget target
);
333 GLenum
DoTexImage(gl::GLContext
* gl
, TexImageTarget target
, GLint level
,
334 const webgl::DriverUnpackInfo
* dui
, GLsizei width
,
335 GLsizei height
, GLsizei depth
, const void* data
);
336 GLenum
DoTexSubImage(gl::GLContext
* gl
, TexImageTarget target
, GLint level
,
337 GLint xOffset
, GLint yOffset
, GLint zOffset
, GLsizei width
,
338 GLsizei height
, GLsizei depth
,
339 const webgl::PackingInfo
& pi
, const void* data
);
340 GLenum
DoCompressedTexSubImage(gl::GLContext
* gl
, TexImageTarget target
,
341 GLint level
, GLint xOffset
, GLint yOffset
,
342 GLint zOffset
, GLsizei width
, GLsizei height
,
343 GLsizei depth
, GLenum sizedUnpackFormat
,
344 GLsizei dataSize
, const void* data
);
346 } // namespace mozilla
348 #endif // WEBGL_TEXTURE_H_