Coverage Report

Created: 2018-09-25 14:53

/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_