Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / dom / canvas / WebGLTexture.h
blob8a451a92776545da2125c51f214ab8db3bde46d8
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 ////////////////////////////////////
207 // GL calls
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
216 protected:
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,
223 const uvec3& size,
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;
232 public:
233 void TexStorage(TexTarget target, uint32_t levels, GLenum sizedFormat,
234 const uvec3& size);
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,
250 const uvec2& size2);
252 ////////////////////////////////////
254 protected:
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);
270 default:
271 return 0;
275 public:
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;
308 void Truncate();
310 bool IsCubeMap() const { return (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP); }
313 inline TexImageTarget TexImageTargetForTargetAndFace(TexTarget target,
314 uint8_t face) {
315 switch (target.get()) {
316 case LOCAL_GL_TEXTURE_2D:
317 case LOCAL_GL_TEXTURE_3D:
318 MOZ_ASSERT(face == 0);
319 return target.get();
320 case LOCAL_GL_TEXTURE_CUBE_MAP:
321 MOZ_ASSERT(face < 6);
322 return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
323 default:
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_