Bug 1874684 - Part 4: Prefer const references instead of copying Instant values....
[gecko.git] / dom / canvas / WebGLTexture.h
blob7d75bf50f6ad3b68eb50f841c58230ba3960f729
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_
9 #include <algorithm>
10 #include <map>
11 #include <set>
12 #include <vector>
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"
24 namespace mozilla {
25 class ErrorResult;
26 class WebGLContext;
27 class WebGLFramebuffer;
28 class WebGLSampler;
29 struct FloatOrInt;
30 struct TexImageSource;
32 namespace dom {
33 class Element;
34 class HTMLVideoElement;
35 class ImageData;
36 class ArrayBufferViewOrSharedArrayBufferView;
37 } // namespace dom
39 namespace layers {
40 class Image;
41 } // namespace layers
43 namespace webgl {
44 struct DriverUnpackInfo;
45 struct FormatUsageInfo;
46 struct PackingInfo;
47 class TexUnpackBlob;
48 } // namespace webgl
50 bool DoesTargetMatchDimensions(WebGLContext* webgl, TexImageTarget target,
51 uint8_t dims);
53 namespace webgl {
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;
72 uint32_t mWidth = 0;
73 uint32_t mHeight = 0;
74 uint32_t mDepth = 0;
75 mutable Maybe<std::vector<bool>> mUninitializedSlices;
76 uint8_t mSamples = 0;
78 // -
80 size_t MemoryUsage() const;
82 bool IsDefined() const {
83 if (!mFormat) {
84 MOZ_ASSERT(!mWidth && !mHeight && !mDepth);
85 return false;
88 return true;
91 Maybe<ImageInfo> NextMip(GLenum target) const;
94 } // namespace webgl
96 class WebGLTexture final : public WebGLContextBoundObject,
97 public CacheInvalidator {
98 // Friends
99 friend class WebGLContext;
100 friend class WebGLFramebuffer;
102 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(WebGLTexture, override)
104 ////////////////////////////////////
105 // Members
106 public:
107 const GLuint mGLName;
109 protected:
110 TexTarget mTarget;
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,
127 MIPMAP_LEVEL_CLEAN,
128 MIPMAP_LEVEL_DIRTY
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'.
138 // -
140 struct CompletenessInfo final {
141 uint8_t levels = 0;
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>
149 mSamplingCache;
151 public:
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;
159 // -
161 const auto& Immutable() const { return mImmutable; }
162 const auto& ImmutableLevelCount() const { return mImmutableLevelCount; }
164 // ES3.0 p150
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"
184 // -
186 const auto& FaceCount() const { return mFaceCount; }
188 // We can just max this out to 31, which is the number of unsigned bits in
189 // GLsizei.
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; }
202 protected:
203 ~WebGLTexture() override;
205 public:
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 ////////////////////////////////////
215 // GL calls
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
224 protected:
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,
231 const uvec3& size,
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;
240 public:
241 void TexStorage(TexTarget target, uint32_t levels, GLenum sizedFormat,
242 const uvec3& size);
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,
258 const uvec2& size2);
260 ////////////////////////////////////
262 protected:
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);
278 default:
279 return 0;
283 public:
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;
316 void Truncate();
318 bool IsCubeMap() const { return (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP); }
321 inline TexImageTarget TexImageTargetForTargetAndFace(TexTarget target,
322 uint8_t face) {
323 switch (target.get()) {
324 case LOCAL_GL_TEXTURE_2D:
325 case LOCAL_GL_TEXTURE_3D:
326 MOZ_ASSERT(face == 0);
327 return target.get();
328 case LOCAL_GL_TEXTURE_CUBE_MAP:
329 MOZ_ASSERT(face < 6);
330 return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
331 default:
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_