/src/mozilla-central/dom/canvas/WebGLTexture.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
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/CheckedInt.h" |
16 | | #include "mozilla/dom/TypedArray.h" |
17 | | #include "mozilla/LinkedList.h" |
18 | | #include "nsWrapperCache.h" |
19 | | |
20 | | #include "WebGLFramebufferAttachable.h" |
21 | | #include "WebGLObjectModel.h" |
22 | | #include "WebGLStrongTypes.h" |
23 | | #include "WebGLTypes.h" |
24 | | |
25 | | namespace mozilla { |
26 | | class ErrorResult; |
27 | | class WebGLContext; |
28 | | struct FloatOrInt; |
29 | | struct TexImageSource; |
30 | | |
31 | | namespace dom { |
32 | | class Element; |
33 | | class HTMLVideoElement; |
34 | | class ImageData; |
35 | | class ArrayBufferViewOrSharedArrayBufferView; |
36 | | } // namespace dom |
37 | | |
38 | | namespace layers { |
39 | | class Image; |
40 | | } // namespace layers |
41 | | |
42 | | namespace webgl { |
43 | | struct DriverUnpackInfo; |
44 | | struct FormatUsageInfo; |
45 | | struct PackingInfo; |
46 | | class TexUnpackBlob; |
47 | | } // namespace webgl |
48 | | |
49 | | |
50 | | bool |
51 | | DoesTargetMatchDimensions(WebGLContext* webgl, TexImageTarget target, uint8_t dims); |
52 | | |
53 | | namespace webgl { |
54 | | |
55 | | struct SamplingState final |
56 | | { |
57 | | // Only store that which changes validation. |
58 | | TexMinFilter minFilter = LOCAL_GL_NEAREST_MIPMAP_LINEAR; |
59 | | TexMagFilter magFilter = LOCAL_GL_LINEAR; |
60 | | TexWrap wrapS = LOCAL_GL_REPEAT; |
61 | | TexWrap wrapT = LOCAL_GL_REPEAT; |
62 | | //TexWrap wrapR = LOCAL_GL_REPEAT; |
63 | | //GLfloat minLod = -1000; |
64 | | //GLfloat maxLod = 1000; |
65 | | TexCompareMode compareMode = LOCAL_GL_NONE; |
66 | | //TexCompareFunc compareFunc = LOCAL_GL_LEQUAL; |
67 | | }; |
68 | | |
69 | | } // namespace webgl |
70 | | |
71 | | // NOTE: When this class is switched to new DOM bindings, update the (then-slow) |
72 | | // WrapObject calls in GetParameter and GetFramebufferAttachmentParameter. |
73 | | class WebGLTexture final |
74 | | : public nsWrapperCache |
75 | | , public WebGLRefCountedObject<WebGLTexture> |
76 | | , public LinkedListElement<WebGLTexture> |
77 | | { |
78 | | // Friends |
79 | | friend class WebGLContext; |
80 | | friend class WebGLFramebuffer; |
81 | | |
82 | | //////////////////////////////////// |
83 | | // Members |
84 | | public: |
85 | | const GLuint mGLName; |
86 | | |
87 | | protected: |
88 | | TexTarget mTarget; |
89 | | |
90 | | static const uint8_t kMaxFaceCount = 6; |
91 | | uint8_t mFaceCount; // 6 for cube maps, 1 otherwise. |
92 | | |
93 | | bool mImmutable; // Set by texStorage* |
94 | | uint8_t mImmutableLevelCount; |
95 | | |
96 | | uint32_t mBaseMipmapLevel; // Set by texParameter (defaults to 0) |
97 | | uint32_t mMaxMipmapLevel; // Set by texParameter (defaults to 1000) |
98 | | // You almost certainly don't want to query mMaxMipmapLevel. |
99 | | // You almost certainly want MaxEffectiveMipmapLevel(). |
100 | | |
101 | | webgl::SamplingState mSamplingState; |
102 | | |
103 | | // Resolvable optimizations: |
104 | | bool mIsResolved; |
105 | | FakeBlackType mResolved_FakeBlack; |
106 | | const GLint* mResolved_Swizzle; // nullptr means 'default swizzle'. |
107 | | |
108 | | public: |
109 | | class ImageInfo; |
110 | | |
111 | | // numLevels = log2(size) + 1 |
112 | | // numLevels(16k) = log2(16k) + 1 = 14 + 1 = 15 |
113 | | // numLevels(1M) = log2(1M) + 1 = 19.9 + 1 ~= 21 |
114 | | // Or we can just max this out to 31, which is the number of unsigned bits in GLsizei. |
115 | | static const uint8_t kMaxLevelCount = 31; |
116 | | |
117 | | // And in turn, it needs these forwards: |
118 | | protected: |
119 | | // We need to forward these. |
120 | | void SetImageInfo(ImageInfo* target, const ImageInfo& newInfo); |
121 | | void SetImageInfosAtLevel(uint32_t level, const ImageInfo& newInfo); |
122 | | |
123 | | public: |
124 | | // We store information about the various images that are part of this |
125 | | // texture. (cubemap faces, mipmap levels) |
126 | | class ImageInfo |
127 | | { |
128 | | friend void WebGLTexture::SetImageInfo(ImageInfo* target, |
129 | | const ImageInfo& newInfo); |
130 | | friend void WebGLTexture::SetImageInfosAtLevel(uint32_t level, |
131 | | const ImageInfo& newInfo); |
132 | | |
133 | | public: |
134 | | static const ImageInfo kUndefined; |
135 | | |
136 | | // This is the "effective internal format" of the texture, an official |
137 | | // OpenGL spec concept, see OpenGL ES 3.0.3 spec, section 3.8.3, page |
138 | | // 126 and below. |
139 | | const webgl::FormatUsageInfo* const mFormat; |
140 | | |
141 | | const uint32_t mWidth; |
142 | | const uint32_t mHeight; |
143 | | const uint32_t mDepth; |
144 | | |
145 | | protected: |
146 | | bool mIsDataInitialized; |
147 | | |
148 | | std::set<WebGLFBAttachPoint*> mAttachPoints; |
149 | | |
150 | | public: |
151 | | ImageInfo() |
152 | | : mFormat(LOCAL_GL_NONE) |
153 | | , mWidth(0) |
154 | | , mHeight(0) |
155 | | , mDepth(0) |
156 | | , mIsDataInitialized(false) |
157 | 3 | { } |
158 | | |
159 | | ImageInfo(const webgl::FormatUsageInfo* format, uint32_t width, uint32_t height, |
160 | | uint32_t depth, bool isDataInitialized) |
161 | | : mFormat(format) |
162 | | , mWidth(width) |
163 | | , mHeight(height) |
164 | | , mDepth(depth) |
165 | | , mIsDataInitialized(isDataInitialized) |
166 | 0 | { |
167 | 0 | MOZ_ASSERT(mFormat); |
168 | 0 | } |
169 | | |
170 | | void Clear(); |
171 | | |
172 | 0 | ~ImageInfo() { |
173 | 0 | MOZ_ASSERT(!mAttachPoints.size()); |
174 | 0 | } |
175 | | |
176 | | protected: |
177 | | void Set(const ImageInfo& a); |
178 | | |
179 | | public: |
180 | 0 | uint32_t PossibleMipmapLevels() const { |
181 | 0 | // GLES 3.0.4, 3.8 - Mipmapping: `floor(log2(largest_of_dims)) + 1` |
182 | 0 | const uint32_t largest = std::max(std::max(mWidth, mHeight), mDepth); |
183 | 0 | MOZ_ASSERT(largest != 0); |
184 | 0 | return FloorLog2Size(largest) + 1; |
185 | 0 | } |
186 | | |
187 | | bool IsPowerOfTwo() const; |
188 | | |
189 | | void AddAttachPoint(WebGLFBAttachPoint* attachPoint); |
190 | | void RemoveAttachPoint(WebGLFBAttachPoint* attachPoint); |
191 | | void OnRespecify() const; |
192 | | |
193 | | size_t MemoryUsage() const; |
194 | | |
195 | 0 | bool IsDefined() const { |
196 | 0 | if (mFormat == LOCAL_GL_NONE) { |
197 | 0 | MOZ_ASSERT(!mWidth && !mHeight && !mDepth); |
198 | 0 | return false; |
199 | 0 | } |
200 | 0 |
|
201 | 0 | return true; |
202 | 0 | } |
203 | | |
204 | 0 | bool IsDataInitialized() const { return mIsDataInitialized; } |
205 | | |
206 | | void SetIsDataInitialized(bool isDataInitialized, WebGLTexture* tex); |
207 | | }; |
208 | | |
209 | | ImageInfo mImageInfoArr[kMaxLevelCount * kMaxFaceCount]; |
210 | | |
211 | | //////////////////////////////////// |
212 | | public: |
213 | | NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture) |
214 | | NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture) |
215 | | |
216 | | WebGLTexture(WebGLContext* webgl, GLuint tex); |
217 | | |
218 | | void Delete(); |
219 | | |
220 | 0 | bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; } |
221 | 0 | TexTarget Target() const { return mTarget; } |
222 | | |
223 | 0 | WebGLContext* GetParentObject() const { |
224 | 0 | return mContext; |
225 | 0 | } |
226 | | |
227 | | virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override; |
228 | | |
229 | | protected: |
230 | 0 | ~WebGLTexture() { |
231 | 0 | DeleteOnce(); |
232 | 0 | } |
233 | | |
234 | | public: |
235 | | //////////////////////////////////// |
236 | | // GL calls |
237 | | bool BindTexture(TexTarget texTarget); |
238 | | void GenerateMipmap(TexTarget texTarget); |
239 | | JS::Value GetTexParameter(TexTarget texTarget, GLenum pname); |
240 | | bool IsTexture() const; |
241 | | void TexParameter(TexTarget texTarget, GLenum pname, const FloatOrInt& param); |
242 | | |
243 | | //////////////////////////////////// |
244 | | // WebGLTextureUpload.cpp |
245 | | |
246 | | protected: |
247 | | void TexOrSubImageBlob(bool isSubImage, TexImageTarget target, |
248 | | GLint level, GLenum internalFormat, GLint xOffset, |
249 | | GLint yOffset, GLint zOffset, |
250 | | const webgl::PackingInfo& pi, |
251 | | const webgl::TexUnpackBlob* blob); |
252 | | |
253 | | bool ValidateTexImageSpecification(TexImageTarget target, |
254 | | GLint level, uint32_t width, uint32_t height, |
255 | | uint32_t depth, |
256 | | WebGLTexture::ImageInfo** const out_imageInfo); |
257 | | bool ValidateTexImageSelection(TexImageTarget target, |
258 | | GLint level, GLint xOffset, GLint yOffset, |
259 | | GLint zOffset, uint32_t width, uint32_t height, |
260 | | uint32_t depth, |
261 | | WebGLTexture::ImageInfo** const out_imageInfo); |
262 | | bool ValidateCopyTexImageForFeedback(uint32_t level, GLint layer = 0) const; |
263 | | |
264 | | bool ValidateUnpack(const webgl::TexUnpackBlob* blob, |
265 | | bool isFunc3D, const webgl::PackingInfo& srcPI) const; |
266 | | public: |
267 | | void TexStorage(TexTarget target, GLsizei levels, |
268 | | GLenum sizedFormat, GLsizei width, GLsizei height, GLsizei depth); |
269 | | void TexImage(TexImageTarget target, GLint level, |
270 | | GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, |
271 | | GLint border, const webgl::PackingInfo& pi, const TexImageSource& src); |
272 | | void TexSubImage(TexImageTarget target, GLint level, |
273 | | GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width, |
274 | | GLsizei height, GLsizei depth, const webgl::PackingInfo& pi, |
275 | | const TexImageSource& src); |
276 | | protected: |
277 | | void TexImage(TexImageTarget target, GLint level, |
278 | | GLenum internalFormat, const webgl::PackingInfo& pi, |
279 | | const webgl::TexUnpackBlob* blob); |
280 | | void TexSubImage(TexImageTarget target, GLint level, |
281 | | GLint xOffset, GLint yOffset, GLint zOffset, |
282 | | const webgl::PackingInfo& pi, const webgl::TexUnpackBlob* blob); |
283 | | public: |
284 | | void CompressedTexImage(TexImageTarget target, GLint level, |
285 | | GLenum internalFormat, GLsizei width, GLsizei height, |
286 | | GLsizei depth, GLint border, const TexImageSource& src, |
287 | | const Maybe<GLsizei>& expectedImageSize); |
288 | | void CompressedTexSubImage(TexImageTarget target, GLint level, |
289 | | GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width, |
290 | | GLsizei height, GLsizei depth, GLenum sizedUnpackFormat, |
291 | | const TexImageSource& src, const Maybe<GLsizei>& expectedImageSize); |
292 | | |
293 | | void CopyTexImage2D(TexImageTarget target, GLint level, GLenum internalFormat, |
294 | | GLint x, GLint y, GLsizei width, GLsizei height, GLint border); |
295 | | void CopyTexSubImage(TexImageTarget target, GLint level, |
296 | | GLint xOffset, GLint yOffset, GLint zOffset, GLint x, GLint y, |
297 | | GLsizei width, GLsizei height); |
298 | | |
299 | | //////////////////////////////////// |
300 | | |
301 | | protected: |
302 | | void ClampLevelBaseAndMax(); |
303 | | |
304 | | void PopulateMipChain(uint32_t baseLevel, uint32_t maxLevel); |
305 | | |
306 | | bool MaxEffectiveMipmapLevel(uint32_t texUnit, uint32_t* const out) const; |
307 | | |
308 | 0 | static uint8_t FaceForTarget(TexImageTarget texImageTarget) { |
309 | 0 | GLenum rawTexImageTarget = texImageTarget.get(); |
310 | 0 | switch (rawTexImageTarget) { |
311 | 0 | case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X: |
312 | 0 | case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X: |
313 | 0 | case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y: |
314 | 0 | case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: |
315 | 0 | case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z: |
316 | 0 | case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: |
317 | 0 | return rawTexImageTarget - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X; |
318 | 0 |
|
319 | 0 | default: |
320 | 0 | return 0; |
321 | 0 | } |
322 | 0 | } |
323 | | |
324 | 0 | ImageInfo& ImageInfoAtFace(uint8_t face, uint32_t level) { |
325 | 0 | MOZ_ASSERT(face < mFaceCount); |
326 | 0 | MOZ_ASSERT(level < kMaxLevelCount); |
327 | 0 | size_t pos = (level * mFaceCount) + face; |
328 | 0 | return mImageInfoArr[pos]; |
329 | 0 | } |
330 | | |
331 | 0 | const ImageInfo& ImageInfoAtFace(uint8_t face, uint32_t level) const { |
332 | 0 | return const_cast<WebGLTexture*>(this)->ImageInfoAtFace(face, level); |
333 | 0 | } |
334 | | |
335 | | public: |
336 | 0 | ImageInfo& ImageInfoAt(TexImageTarget texImageTarget, GLint level) { |
337 | 0 | auto face = FaceForTarget(texImageTarget); |
338 | 0 | return ImageInfoAtFace(face, level); |
339 | 0 | } |
340 | | |
341 | 0 | const ImageInfo& ImageInfoAt(TexImageTarget texImageTarget, GLint level) const { |
342 | 0 | return const_cast<WebGLTexture*>(this)->ImageInfoAt(texImageTarget, level); |
343 | 0 | } |
344 | | |
345 | | void SetImageInfoAt(TexImageTarget texImageTarget, GLint level, |
346 | | const ImageInfo& val) |
347 | 0 | { |
348 | 0 | ImageInfo* target = &ImageInfoAt(texImageTarget, level); |
349 | 0 | SetImageInfo(target, val); |
350 | 0 | } |
351 | | |
352 | 0 | const ImageInfo& BaseImageInfo() const { |
353 | 0 | if (mBaseMipmapLevel >= kMaxLevelCount) |
354 | 0 | return ImageInfo::kUndefined; |
355 | 0 | |
356 | 0 | return ImageInfoAtFace(0, mBaseMipmapLevel); |
357 | 0 | } |
358 | | |
359 | | size_t MemoryUsage() const; |
360 | | |
361 | | bool InitializeImageData(TexImageTarget target, uint32_t level); |
362 | | protected: |
363 | | bool EnsureImageDataInitialized(TexImageTarget target, |
364 | | uint32_t level); |
365 | | bool EnsureLevelInitialized(uint32_t level); |
366 | | |
367 | | public: |
368 | | void SetGeneratedMipmap(); |
369 | | |
370 | | void SetCustomMipmap(); |
371 | | |
372 | | bool AreAllLevel0ImageInfosEqual() const; |
373 | | |
374 | | bool IsMipmapComplete(uint32_t texUnit, |
375 | | bool* const out_initFailed); |
376 | | |
377 | | bool IsCubeComplete() const; |
378 | | |
379 | | bool IsComplete(uint32_t texUnit, const char** const out_reason, |
380 | | bool* const out_initFailed); |
381 | | |
382 | | bool IsMipmapCubeComplete() const; |
383 | | |
384 | 0 | bool IsCubeMap() const { return (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP); } |
385 | | |
386 | | // Resolve cache optimizations |
387 | | protected: |
388 | | bool GetFakeBlackType(uint32_t texUnit, |
389 | | FakeBlackType* const out_fakeBlack); |
390 | | public: |
391 | | bool IsFeedback(WebGLContext* webgl, uint32_t texUnit, |
392 | | const std::vector<const WebGLFBAttachPoint*>& fbAttachments) const; |
393 | | |
394 | | bool ResolveForDraw(uint32_t texUnit, |
395 | | FakeBlackType* const out_fakeBlack); |
396 | | |
397 | 0 | void InvalidateResolveCache() { mIsResolved = false; } |
398 | | }; |
399 | | |
400 | | inline TexImageTarget |
401 | | TexImageTargetForTargetAndFace(TexTarget target, uint8_t face) |
402 | 0 | { |
403 | 0 | switch (target.get()) { |
404 | 0 | case LOCAL_GL_TEXTURE_2D: |
405 | 0 | case LOCAL_GL_TEXTURE_3D: |
406 | 0 | MOZ_ASSERT(face == 0); |
407 | 0 | return target.get(); |
408 | 0 | case LOCAL_GL_TEXTURE_CUBE_MAP: |
409 | 0 | MOZ_ASSERT(face < 6); |
410 | 0 | return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; |
411 | 0 | default: |
412 | 0 | MOZ_CRASH("GFX: TexImageTargetForTargetAndFace"); |
413 | 0 | } |
414 | 0 | } |
415 | | |
416 | | already_AddRefed<mozilla::layers::Image> |
417 | | ImageFromVideo(dom::HTMLVideoElement* elem); |
418 | | |
419 | | bool |
420 | | IsTarget3D(TexImageTarget target); |
421 | | |
422 | | GLenum |
423 | | DoTexImage(gl::GLContext* gl, TexImageTarget target, GLint level, |
424 | | const webgl::DriverUnpackInfo* dui, GLsizei width, GLsizei height, |
425 | | GLsizei depth, const void* data); |
426 | | GLenum |
427 | | DoTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level, GLint xOffset, |
428 | | GLint yOffset, GLint zOffset, GLsizei width, GLsizei height, |
429 | | GLsizei depth, const webgl::PackingInfo& pi, const void* data); |
430 | | GLenum |
431 | | DoCompressedTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level, |
432 | | GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width, |
433 | | GLsizei height, GLsizei depth, GLenum sizedUnpackFormat, |
434 | | GLsizei dataSize, const void* data); |
435 | | |
436 | | } // namespace mozilla |
437 | | |
438 | | #endif // WEBGL_TEXTURE_H_ |