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