Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/canvas/WebGLContextTextures.cpp
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
#include "WebGLContext.h"
7
#include "WebGLContextUtils.h"
8
#include "WebGLBuffer.h"
9
#include "WebGLVertexAttribData.h"
10
#include "WebGLShader.h"
11
#include "WebGLProgram.h"
12
#include "WebGLUniformLocation.h"
13
#include "WebGLFramebuffer.h"
14
#include "WebGLRenderbuffer.h"
15
#include "WebGLShaderPrecisionFormat.h"
16
#include "WebGLTexture.h"
17
#include "WebGLExtensions.h"
18
#include "WebGLVertexArray.h"
19
20
#include "nsString.h"
21
#include "nsDebug.h"
22
#include "nsReadableUtils.h"
23
24
#include "gfxContext.h"
25
#include "gfxPlatform.h"
26
#include "GLContext.h"
27
28
#include "nsContentUtils.h"
29
#include "nsError.h"
30
#include "nsLayoutUtils.h"
31
32
#include "CanvasUtils.h"
33
#include "gfxUtils.h"
34
35
#include "jsfriendapi.h"
36
37
#include "WebGLTexelConversions.h"
38
#include "WebGLValidateStrings.h"
39
#include <algorithm>
40
41
// needed to check if current OS is lower than 10.7
42
#if defined(MOZ_WIDGET_COCOA)
43
#include "nsCocoaFeatures.h"
44
#endif
45
46
#include "mozilla/DebugOnly.h"
47
#include "mozilla/dom/BindingUtils.h"
48
#include "mozilla/dom/ImageData.h"
49
#include "mozilla/dom/ToJSValue.h"
50
#include "mozilla/EndianUtils.h"
51
52
namespace mozilla {
53
54
static bool
55
IsValidTexTarget(WebGLContext* webgl, uint8_t funcDims, GLenum rawTexTarget,
56
                 TexTarget* const out)
57
0
{
58
0
    uint8_t targetDims;
59
0
60
0
    switch (rawTexTarget) {
61
0
    case LOCAL_GL_TEXTURE_2D:
62
0
    case LOCAL_GL_TEXTURE_CUBE_MAP:
63
0
        targetDims = 2;
64
0
        break;
65
0
66
0
    case LOCAL_GL_TEXTURE_3D:
67
0
    case LOCAL_GL_TEXTURE_2D_ARRAY:
68
0
        if (!webgl->IsWebGL2())
69
0
            return false;
70
0
71
0
        targetDims = 3;
72
0
        break;
73
0
74
0
    default:
75
0
        return false;
76
0
    }
77
0
78
0
    // Some funcs (like GenerateMipmap) doesn't know the dimension, so don't check it.
79
0
    if (funcDims && targetDims != funcDims)
80
0
        return false;
81
0
82
0
    *out = rawTexTarget;
83
0
    return true;
84
0
}
85
86
static bool
87
IsValidTexImageTarget(WebGLContext* webgl, uint8_t funcDims, GLenum rawTexImageTarget,
88
                      TexImageTarget* const out)
89
0
{
90
0
    uint8_t targetDims;
91
0
92
0
    switch (rawTexImageTarget) {
93
0
    case LOCAL_GL_TEXTURE_2D:
94
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
95
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
96
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
97
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
98
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
99
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
100
0
        targetDims = 2;
101
0
        break;
102
0
103
0
    case LOCAL_GL_TEXTURE_3D:
104
0
    case LOCAL_GL_TEXTURE_2D_ARRAY:
105
0
        if (!webgl->IsWebGL2())
106
0
            return false;
107
0
108
0
        targetDims = 3;
109
0
        break;
110
0
111
0
    default:
112
0
        return false;
113
0
    }
114
0
115
0
    if (targetDims != funcDims)
116
0
        return false;
117
0
118
0
    *out = rawTexImageTarget;
119
0
    return true;
120
0
}
121
122
bool
123
ValidateTexTarget(WebGLContext* webgl, uint8_t funcDims,
124
                  GLenum rawTexTarget, TexTarget* const out_texTarget,
125
                  WebGLTexture** const out_tex)
126
0
{
127
0
    if (webgl->IsContextLost())
128
0
        return false;
129
0
130
0
    TexTarget texTarget;
131
0
    if (!IsValidTexTarget(webgl, funcDims, rawTexTarget, &texTarget)) {
132
0
        webgl->ErrorInvalidEnumInfo("texTarget", rawTexTarget);
133
0
        return false;
134
0
    }
135
0
136
0
    WebGLTexture* tex = webgl->ActiveBoundTextureForTarget(texTarget);
137
0
    if (!tex) {
138
0
        webgl->ErrorInvalidOperation("No texture is bound to this target.");
139
0
        return false;
140
0
    }
141
0
142
0
    *out_texTarget = texTarget;
143
0
    *out_tex = tex;
144
0
    return true;
145
0
}
146
147
bool
148
ValidateTexImageTarget(WebGLContext* webgl, uint8_t funcDims,
149
                       GLenum rawTexImageTarget, TexImageTarget* const out_texImageTarget,
150
                       WebGLTexture** const out_tex)
151
0
{
152
0
    if (webgl->IsContextLost())
153
0
        return false;
154
0
155
0
    TexImageTarget texImageTarget;
156
0
    if (!IsValidTexImageTarget(webgl, funcDims, rawTexImageTarget, &texImageTarget)) {
157
0
        webgl->ErrorInvalidEnumInfo("texImageTarget", rawTexImageTarget);
158
0
        return false;
159
0
    }
160
0
161
0
    WebGLTexture* tex = webgl->ActiveBoundTextureForTexImageTarget(texImageTarget);
162
0
    if (!tex) {
163
0
        webgl->ErrorInvalidOperation("No texture is bound to this target.");
164
0
        return false;
165
0
    }
166
0
167
0
    *out_texImageTarget = texImageTarget;
168
0
    *out_tex = tex;
169
0
    return true;
170
0
}
171
172
/*virtual*/ bool
173
WebGLContext::IsTexParamValid(GLenum pname) const
174
0
{
175
0
    switch (pname) {
176
0
    case LOCAL_GL_TEXTURE_MIN_FILTER:
177
0
    case LOCAL_GL_TEXTURE_MAG_FILTER:
178
0
    case LOCAL_GL_TEXTURE_WRAP_S:
179
0
    case LOCAL_GL_TEXTURE_WRAP_T:
180
0
        return true;
181
0
182
0
    case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
183
0
        return IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic);
184
0
185
0
    default:
186
0
        return false;
187
0
    }
188
0
}
189
190
void
191
WebGLContext::InvalidateResolveCacheForTextureWithTexUnit(const GLuint texUnit)
192
0
{
193
0
    if (mBound2DTextures[texUnit])
194
0
        mBound2DTextures[texUnit]->InvalidateResolveCache();
195
0
    if (mBoundCubeMapTextures[texUnit])
196
0
        mBoundCubeMapTextures[texUnit]->InvalidateResolveCache();
197
0
    if (mBound3DTextures[texUnit])
198
0
        mBound3DTextures[texUnit]->InvalidateResolveCache();
199
0
    if (mBound2DArrayTextures[texUnit])
200
0
        mBound2DArrayTextures[texUnit]->InvalidateResolveCache();
201
0
}
202
203
//////////////////////////////////////////////////////////////////////////////////////////
204
// GL calls
205
206
void
207
WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
208
0
{
209
0
    const FuncScope funcScope(*this, "bindTexture");
210
0
    if (IsContextLost())
211
0
        return;
212
0
213
0
     if (newTex && !ValidateObject("tex", *newTex))
214
0
        return;
215
0
216
0
    // Need to check rawTarget first before comparing against newTex->Target() as
217
0
    // newTex->Target() returns a TexTarget, which will assert on invalid value.
218
0
    WebGLRefPtr<WebGLTexture>* currentTexPtr = nullptr;
219
0
    switch (rawTarget) {
220
0
    case LOCAL_GL_TEXTURE_2D:
221
0
        currentTexPtr = &mBound2DTextures[mActiveTexture];
222
0
        break;
223
0
224
0
   case LOCAL_GL_TEXTURE_CUBE_MAP:
225
0
        currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
226
0
        break;
227
0
228
0
   case LOCAL_GL_TEXTURE_3D:
229
0
        if (IsWebGL2())
230
0
            currentTexPtr = &mBound3DTextures[mActiveTexture];
231
0
        break;
232
0
233
0
   case LOCAL_GL_TEXTURE_2D_ARRAY:
234
0
        if (IsWebGL2())
235
0
            currentTexPtr = &mBound2DArrayTextures[mActiveTexture];
236
0
        break;
237
0
    }
238
0
239
0
    if (!currentTexPtr) {
240
0
        ErrorInvalidEnumInfo("target", rawTarget);
241
0
        return;
242
0
    }
243
0
244
0
    const TexTarget texTarget(rawTarget);
245
0
    if (newTex) {
246
0
        if (!newTex->BindTexture(texTarget))
247
0
            return;
248
0
    } else {
249
0
        gl->fBindTexture(texTarget.get(), 0);
250
0
    }
251
0
252
0
    *currentTexPtr = newTex;
253
0
}
254
255
void
256
WebGLContext::GenerateMipmap(GLenum rawTexTarget)
257
0
{
258
0
    const FuncScope funcScope(*this, "generateMipmap");
259
0
    const uint8_t funcDims = 0;
260
0
261
0
    TexTarget texTarget;
262
0
    WebGLTexture* tex;
263
0
    if (!ValidateTexTarget(this, funcDims, rawTexTarget, &texTarget, &tex))
264
0
        return;
265
0
266
0
    tex->GenerateMipmap(texTarget);
267
0
}
268
269
JS::Value
270
WebGLContext::GetTexParameter(GLenum rawTexTarget, GLenum pname)
271
0
{
272
0
    const FuncScope funcScope(*this, "getTexParameter");
273
0
    const uint8_t funcDims = 0;
274
0
275
0
    TexTarget texTarget;
276
0
    WebGLTexture* tex;
277
0
    if (!ValidateTexTarget(this, funcDims, rawTexTarget, &texTarget, &tex))
278
0
        return JS::NullValue();
279
0
280
0
    if (!IsTexParamValid(pname)) {
281
0
        ErrorInvalidEnumInfo("pname", pname);
282
0
        return JS::NullValue();
283
0
    }
284
0
285
0
    return tex->GetTexParameter(texTarget, pname);
286
0
}
287
288
void
289
WebGLContext::TexParameter_base(GLenum rawTexTarget, GLenum pname,
290
                                const FloatOrInt& param)
291
0
{
292
0
    const FuncScope funcScope(*this, "texParameter");
293
0
    const uint8_t funcDims = 0;
294
0
295
0
    TexTarget texTarget;
296
0
    WebGLTexture* tex;
297
0
    if (!ValidateTexTarget(this, funcDims, rawTexTarget, &texTarget, &tex))
298
0
        return;
299
0
300
0
    tex->TexParameter(texTarget, pname, param);
301
0
}
302
303
//////////////////////////////////////////////////////////////////////////////////////////
304
// Uploads
305
306
void
307
WebGLContext::CompressedTexImage(uint8_t funcDims, GLenum rawTarget,
308
                                 GLint level, GLenum internalFormat, GLsizei width,
309
                                 GLsizei height, GLsizei depth, GLint border,
310
                                 const TexImageSource& src, const Maybe<GLsizei>& expectedImageSize)
311
0
{
312
0
    TexImageTarget target;
313
0
    WebGLTexture* tex;
314
0
    if (!ValidateTexImageTarget(this, funcDims, rawTarget, &target, &tex))
315
0
        return;
316
0
317
0
    tex->CompressedTexImage(target, level, internalFormat, width, height, depth,
318
0
                            border, src, expectedImageSize);
319
0
}
320
321
void
322
WebGLContext::CompressedTexSubImage(uint8_t funcDims,
323
                                    GLenum rawTarget, GLint level, GLint xOffset,
324
                                    GLint yOffset, GLint zOffset, GLsizei width,
325
                                    GLsizei height, GLsizei depth, GLenum unpackFormat,
326
                                    const TexImageSource& src, const Maybe<GLsizei>& expectedImageSize)
327
0
{
328
0
    TexImageTarget target;
329
0
    WebGLTexture* tex;
330
0
    if (!ValidateTexImageTarget(this, funcDims, rawTarget, &target, &tex))
331
0
        return;
332
0
333
0
    tex->CompressedTexSubImage(target, level, xOffset, yOffset, zOffset, width,
334
0
                               height, depth, unpackFormat, src, expectedImageSize);
335
0
}
336
337
////
338
339
void
340
WebGLContext::CopyTexImage2D(GLenum rawTarget, GLint level, GLenum internalFormat,
341
                             GLint x, GLint y, GLsizei width, GLsizei height,
342
                             GLint border)
343
0
{
344
0
    const FuncScope funcScope(*this, "copyTexImage2D");
345
0
    const uint8_t funcDims = 2;
346
0
347
0
    TexImageTarget target;
348
0
    WebGLTexture* tex;
349
0
    if (!ValidateTexImageTarget(this, funcDims, rawTarget, &target, &tex))
350
0
        return;
351
0
352
0
    tex->CopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
353
0
}
354
355
void
356
WebGLContext::CopyTexSubImage(uint8_t funcDims, GLenum rawTarget,
357
                              GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
358
                              GLint x, GLint y, GLsizei width, GLsizei height)
359
0
{
360
0
    TexImageTarget target;
361
0
    WebGLTexture* tex;
362
0
    if (!ValidateTexImageTarget(this, funcDims, rawTarget, &target, &tex))
363
0
        return;
364
0
365
0
    tex->CopyTexSubImage(target, level, xOffset, yOffset, zOffset, x, y, width,
366
0
                         height);
367
0
}
368
369
////
370
371
void
372
WebGLContext::TexImage(uint8_t funcDims, GLenum rawTarget,
373
                       GLint level, GLenum internalFormat, GLsizei width, GLsizei height,
374
                       GLsizei depth, GLint border, GLenum unpackFormat,
375
                       GLenum unpackType, const TexImageSource& src)
376
0
{
377
0
    TexImageTarget target;
378
0
    WebGLTexture* tex;
379
0
    if (!ValidateTexImageTarget(this, funcDims, rawTarget, &target, &tex))
380
0
        return;
381
0
382
0
    const webgl::PackingInfo pi = {unpackFormat, unpackType};
383
0
    tex->TexImage(target, level, internalFormat, width, height, depth, border,
384
0
                  pi, src);
385
0
}
386
387
void
388
WebGLContext::TexSubImage(uint8_t funcDims, GLenum rawTarget,
389
                          GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
390
                          GLsizei width, GLsizei height, GLsizei depth,
391
                          GLenum unpackFormat, GLenum unpackType,
392
                          const TexImageSource& src)
393
0
{
394
0
    TexImageTarget target;
395
0
    WebGLTexture* tex;
396
0
    if (!ValidateTexImageTarget(this, funcDims, rawTarget, &target, &tex))
397
0
        return;
398
0
399
0
    const webgl::PackingInfo pi = {unpackFormat, unpackType};
400
0
    tex->TexSubImage(target, level, xOffset, yOffset, zOffset, width, height,
401
0
                     depth, pi, src);
402
0
}
403
404
} // namespace mozilla