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/. */
5
6 #ifndef WEBGL_TEXTURE_H_
7 #define WEBGL_TEXTURE_H_
8
9 #include <algorithm>
10 #include <map>
11 #include <set>
12 #include <vector>
13
14 #include "mozilla/Assertions.h"
15 #include "mozilla/Casting.h"
16 #include "mozilla/CheckedInt.h"
17 #include "mozilla/dom/TypedArray.h"
18
19 #include "CacheInvalidator.h"
20 #include "WebGLObjectModel.h"
21 #include "WebGLStrongTypes.h"
22 #include "WebGLTypes.h"
23
24 namespace mozilla {
25 class ErrorResult;
26 class WebGLContext;
27 class WebGLFramebuffer;
28 class WebGLSampler;
29 struct FloatOrInt;
30 struct TexImageSource;
31
32 namespace dom {
33 class Element;
34 class HTMLVideoElement;
35 class ImageData;
36 class ArrayBufferViewOrSharedArrayBufferView;
37 } // namespace dom
38
39 namespace layers {
40 class Image;
41 } // namespace layers
42
43 namespace webgl {
44 struct DriverUnpackInfo;
45 struct FormatUsageInfo;
46 struct PackingInfo;
47 class TexUnpackBlob;
48 } // namespace webgl
49
50 bool DoesTargetMatchDimensions(WebGLContext* webgl, TexImageTarget target,
51 uint8_t dims);
52
53 namespace webgl {
54
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;
66 };
67
68 struct ImageInfo final {
69 static const ImageInfo kUndefined;
70
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;
77
78 // -
79
80 size_t MemoryUsage() const;
81
IsDefinedfinal82 bool IsDefined() const {
83 if (!mFormat) {
84 MOZ_ASSERT(!mWidth && !mHeight && !mDepth);
85 return false;
86 }
87
88 return true;
89 }
90
91 Maybe<ImageInfo> NextMip(GLenum target) const;
92 };
93
94 } // namespace webgl
95
96 class WebGLTexture final : public WebGLContextBoundObject,
97 public CacheInvalidator {
98 // Friends
99 friend class WebGLContext;
100 friend class WebGLFramebuffer;
101
102 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(WebGLTexture, override)
103
104 ////////////////////////////////////
105 // Members
106 public:
107 const GLuint mGLName;
108
109 protected:
110 TexTarget mTarget;
111
112 static const uint8_t kMaxFaceCount = 6;
113 uint8_t mFaceCount; // 6 for cube maps, 1 otherwise.
114
115 bool mImmutable; // Set by texStorage*
116 uint8_t mImmutableLevelCount;
117
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().
122
123 webgl::SamplingState mSamplingState;
124
125 mutable const GLint* mCurSwizzle =
126 nullptr; // nullptr means 'default swizzle'.
127
128 // -
129
130 struct CompletenessInfo final {
131 uint8_t levels = 0;
132 bool powerOfTwo = false;
133 bool mipmapComplete = false;
134 const webgl::FormatUsageInfo* usage = nullptr;
135 const char* incompleteReason = nullptr;
136 };
137
138 mutable CacheWeakMap<const WebGLSampler*, webgl::SampleableInfo>
139 mSamplingCache;
140
141 public:
142 Maybe<const CompletenessInfo> CalcCompletenessInfo(
143 bool ensureInit, bool skipMips = false) const;
144 Maybe<const webgl::SampleableInfo> CalcSampleableInfo(
145 const WebGLSampler*) const;
146
147 const webgl::SampleableInfo* GetSampleableInfo(const WebGLSampler*) const;
148
149 // -
150
Immutable()151 const auto& Immutable() const { return mImmutable; }
BaseMipmapLevel()152 const auto& BaseMipmapLevel() const { return mBaseMipmapLevel; }
FaceCount()153 const auto& FaceCount() const { return mFaceCount; }
154
155 // We can just max this out to 31, which is the number of unsigned bits in
156 // GLsizei.
157 static const uint8_t kMaxLevelCount = 31;
158
159 // We store information about the various images that are part of this
160 // texture. (cubemap faces, mipmap levels)
161 webgl::ImageInfo mImageInfoArr[kMaxLevelCount * kMaxFaceCount];
162
163 ////////////////////////////////////
164
165 WebGLTexture(WebGLContext* webgl, GLuint tex);
166
Target()167 TexTarget Target() const { return mTarget; }
168
169 protected:
170 ~WebGLTexture() override;
171
172 public:
173 ////////////////////////////////////
174 // GL calls
175 bool BindTexture(TexTarget texTarget);
176 void GenerateMipmap();
177 Maybe<double> GetTexParameter(GLenum pname) const;
178 void TexParameter(TexTarget texTarget, GLenum pname, const FloatOrInt& param);
179
180 ////////////////////////////////////
181 // WebGLTextureUpload.cpp
182
183 protected:
184 void TexOrSubImageBlob(bool isSubImage, TexImageTarget target, GLint level,
185 GLenum internalFormat, GLint xOffset, GLint yOffset,
186 GLint zOffset, const webgl::PackingInfo& pi,
187 const webgl::TexUnpackBlob* blob);
188
189 bool ValidateTexImageSpecification(TexImageTarget target, uint32_t level,
190 const uvec3& size,
191 webgl::ImageInfo** const out_imageInfo);
192 bool ValidateTexImageSelection(TexImageTarget target, uint32_t level,
193 const uvec3& offset, const uvec3& size,
194 webgl::ImageInfo** const out_imageInfo);
195
196 bool ValidateUnpack(const webgl::TexUnpackBlob* blob, bool isFunc3D,
197 const webgl::PackingInfo& srcPI) const;
198
199 public:
200 void TexStorage(TexTarget target, uint32_t levels, GLenum sizedFormat,
201 const uvec3& size);
202
203 // TexSubImage iff `!respecFormat`
204 void TexImage(GLenum imageTarget, uint32_t level, GLenum respecFormat,
205 const uvec3& offset, const uvec3& size,
206 const webgl::PackingInfo& pi, const TexImageSource& src,
207 const dom::HTMLCanvasElement& canvas);
208
209 // CompressedTexSubImage iff `sub`
210 void CompressedTexImage(bool sub, GLenum imageTarget, uint32_t level,
211 GLenum formatEnum, const uvec3& offset,
212 const uvec3& size, const Range<const uint8_t>& src,
213 const uint32_t pboImageSize,
214 const Maybe<uint64_t>& pboOffset);
215
216 // CopyTexSubImage iff `!respecFormat`
217 void CopyTexImage(GLenum imageTarget, uint32_t level, GLenum respecFormat,
218 const uvec3& dstOffset, const ivec2& srcOffset,
219 const uvec2& size2);
220
221 ////////////////////////////////////
222
223 protected:
224 void ClampLevelBaseAndMax();
225 void RefreshSwizzle() const;
226
227 public:
228 uint32_t EffectiveMaxLevel() const; // GLES 3.0.5 p158: `q`
229
230 protected:
FaceForTarget(TexImageTarget texImageTarget)231 static uint8_t FaceForTarget(TexImageTarget texImageTarget) {
232 GLenum rawTexImageTarget = texImageTarget.get();
233 switch (rawTexImageTarget) {
234 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
235 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
236 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
237 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
238 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
239 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
240 return AutoAssertCast(rawTexImageTarget -
241 LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X);
242
243 default:
244 return 0;
245 }
246 }
247
248 public:
ImageInfoAtFace(uint8_t face,uint32_t level)249 auto& ImageInfoAtFace(uint8_t face, uint32_t level) {
250 MOZ_ASSERT(face < mFaceCount);
251 MOZ_ASSERT(level < kMaxLevelCount);
252 size_t pos = (level * mFaceCount) + face;
253 return mImageInfoArr[pos];
254 }
255
ImageInfoAtFace(uint8_t face,uint32_t level)256 const auto& ImageInfoAtFace(uint8_t face, uint32_t level) const {
257 return const_cast<WebGLTexture*>(this)->ImageInfoAtFace(face, level);
258 }
259
ImageInfoAt(TexImageTarget texImageTarget,GLint level)260 auto& ImageInfoAt(TexImageTarget texImageTarget, GLint level) {
261 const auto& face = FaceForTarget(texImageTarget);
262 return ImageInfoAtFace(face, level);
263 }
264
ImageInfoAt(TexImageTarget texImageTarget,GLint level)265 const auto& ImageInfoAt(TexImageTarget texImageTarget, GLint level) const {
266 return const_cast<WebGLTexture*>(this)->ImageInfoAt(texImageTarget, level);
267 }
268
BaseImageInfo()269 const auto& BaseImageInfo() const {
270 if (mBaseMipmapLevel >= kMaxLevelCount) return webgl::ImageInfo::kUndefined;
271
272 return ImageInfoAtFace(0, mBaseMipmapLevel);
273 }
274
275 size_t MemoryUsage() const;
276
277 bool EnsureImageDataInitialized(TexImageTarget target, uint32_t level);
278 void PopulateMipChain(uint32_t maxLevel);
279 bool IsMipAndCubeComplete(uint32_t maxLevel, bool ensureInit,
280 bool* out_initFailed) const;
281 void Truncate();
282
IsCubeMap()283 bool IsCubeMap() const { return (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP); }
284 };
285
TexImageTargetForTargetAndFace(TexTarget target,uint8_t face)286 inline TexImageTarget TexImageTargetForTargetAndFace(TexTarget target,
287 uint8_t face) {
288 switch (target.get()) {
289 case LOCAL_GL_TEXTURE_2D:
290 case LOCAL_GL_TEXTURE_3D:
291 MOZ_ASSERT(face == 0);
292 return target.get();
293 case LOCAL_GL_TEXTURE_CUBE_MAP:
294 MOZ_ASSERT(face < 6);
295 return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
296 default:
297 MOZ_CRASH("GFX: TexImageTargetForTargetAndFace");
298 }
299 }
300
301 already_AddRefed<mozilla::layers::Image> ImageFromVideo(
302 dom::HTMLVideoElement* elem);
303
304 bool IsTarget3D(TexImageTarget target);
305
306 GLenum DoTexImage(gl::GLContext* gl, TexImageTarget target, GLint level,
307 const webgl::DriverUnpackInfo* dui, GLsizei width,
308 GLsizei height, GLsizei depth, const void* data);
309 GLenum DoTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level,
310 GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width,
311 GLsizei height, GLsizei depth,
312 const webgl::PackingInfo& pi, const void* data);
313 GLenum DoCompressedTexSubImage(gl::GLContext* gl, TexImageTarget target,
314 GLint level, GLint xOffset, GLint yOffset,
315 GLint zOffset, GLsizei width, GLsizei height,
316 GLsizei depth, GLenum sizedUnpackFormat,
317 GLsizei dataSize, const void* data);
318
319 } // namespace mozilla
320
321 #endif // WEBGL_TEXTURE_H_
322