Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/canvas/WebGLContextUtils.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 20; 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 "WebGLContextUtils.h"
7
#include "WebGLContext.h"
8
9
#include "GLContext.h"
10
#include "jsapi.h"
11
#include "mozilla/dom/ScriptSettings.h"
12
#include "mozilla/gfx/Logging.h"
13
#include "mozilla/Preferences.h"
14
#include "mozilla/Sprintf.h"
15
#include "nsIScriptSecurityManager.h"
16
#include "nsIVariant.h"
17
#include "nsPrintfCString.h"
18
#include "nsServiceManagerUtils.h"
19
#include <stdarg.h>
20
#include "WebGLBuffer.h"
21
#include "WebGLExtensions.h"
22
#include "WebGLFramebuffer.h"
23
#include "WebGLProgram.h"
24
#include "WebGLTexture.h"
25
#include "WebGLVertexArray.h"
26
27
namespace mozilla {
28
29
TexTarget
30
TexImageTargetToTexTarget(TexImageTarget texImageTarget)
31
0
{
32
0
    switch (texImageTarget.get()) {
33
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
34
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
35
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
36
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
37
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
38
0
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
39
0
        return LOCAL_GL_TEXTURE_CUBE_MAP;
40
0
41
0
    default:
42
0
        return texImageTarget.get();
43
0
    }
44
0
}
45
46
JS::Value
47
StringValue(JSContext* cx, const char* chars, ErrorResult& rv)
48
0
{
49
0
    JSString* str = JS_NewStringCopyZ(cx, chars);
50
0
    if (!str) {
51
0
        rv.Throw(NS_ERROR_OUT_OF_MEMORY);
52
0
        return JS::NullValue();
53
0
    }
54
0
55
0
    return JS::StringValue(str);
56
0
}
57
58
void
59
WebGLContext::GenerateWarning(const char* fmt, ...) const
60
0
{
61
0
    va_list ap;
62
0
    va_start(ap, fmt);
63
0
64
0
    GenerateWarning(fmt, ap);
65
0
66
0
    va_end(ap);
67
0
}
68
69
void
70
WebGLContext::GenerateWarning(const char* fmt, va_list ap) const
71
0
{
72
0
    if (!ShouldGenerateWarnings())
73
0
        return;
74
0
75
0
    mAlreadyGeneratedWarnings++;
76
0
77
0
    char buf[1024];
78
0
    VsprintfLiteral(buf, fmt, ap);
79
0
80
0
    // no need to print to stderr, as JS_ReportWarning takes care of this for us.
81
0
82
0
    if (!mCanvasElement) {
83
0
        return;
84
0
    }
85
0
86
0
    dom::AutoJSAPI api;
87
0
    if (!api.Init(mCanvasElement->OwnerDoc()->GetScopeObject())) {
88
0
        return;
89
0
    }
90
0
91
0
    JSContext* cx = api.cx();
92
0
    const auto funcName = FuncName();
93
0
    JS_ReportWarningASCII(cx, "WebGL warning: %s: %s", funcName, buf);
94
0
    if (!ShouldGenerateWarnings()) {
95
0
        JS_ReportWarningASCII(cx,
96
0
                              "WebGL: No further warnings will be reported for"
97
0
                              " this WebGL context."
98
0
                              " (already reported %d warnings)",
99
0
                              mAlreadyGeneratedWarnings);
100
0
    }
101
0
}
102
103
bool
104
WebGLContext::ShouldGenerateWarnings() const
105
0
{
106
0
    if (mMaxWarnings == -1)
107
0
        return true;
108
0
109
0
    return mAlreadyGeneratedWarnings < mMaxWarnings;
110
0
}
111
112
void
113
WebGLContext::GeneratePerfWarning(const char* fmt, ...) const
114
0
{
115
0
    if (!ShouldGeneratePerfWarnings())
116
0
        return;
117
0
118
0
    if (!mCanvasElement)
119
0
        return;
120
0
121
0
    dom::AutoJSAPI api;
122
0
    if (!api.Init(mCanvasElement->OwnerDoc()->GetScopeObject()))
123
0
        return;
124
0
    JSContext* cx = api.cx();
125
0
126
0
    ////
127
0
128
0
    va_list ap;
129
0
    va_start(ap, fmt);
130
0
131
0
    char buf[1024];
132
0
    VsprintfLiteral(buf, fmt, ap);
133
0
134
0
    va_end(ap);
135
0
136
0
    ////
137
0
138
0
    const auto funcName = FuncName();
139
0
    JS_ReportWarningASCII(cx, "WebGL perf warning: %s: %s", funcName, buf);
140
0
    mNumPerfWarnings++;
141
0
142
0
    if (!ShouldGeneratePerfWarnings()) {
143
0
        JS_ReportWarningASCII(cx,
144
0
                              "WebGL: After reporting %u, no further perf warnings will"
145
0
                              " be reported for this WebGL context.",
146
0
                              uint32_t(mNumPerfWarnings));
147
0
    }
148
0
}
149
150
void
151
WebGLContext::SynthesizeGLError(GLenum err) const
152
0
{
153
0
    /* ES2 section 2.5 "GL Errors" states that implementations can have
154
0
     * multiple 'flags', as errors might be caught in different parts of
155
0
     * a distributed implementation.
156
0
     * We're signing up as a distributed implementation here, with
157
0
     * separate flags for WebGL and the underlying GLContext.
158
0
     */
159
0
    if (!mWebGLError)
160
0
        mWebGLError = err;
161
0
}
162
163
void
164
WebGLContext::SynthesizeGLError(GLenum err, const char* fmt, ...) const
165
0
{
166
0
    va_list va;
167
0
    va_start(va, fmt);
168
0
    GenerateWarning(fmt, va);
169
0
    va_end(va);
170
0
171
0
    return SynthesizeGLError(err);
172
0
}
173
174
void
175
WebGLContext::ErrorInvalidEnum(const char* fmt, ...) const
176
0
{
177
0
    va_list va;
178
0
    va_start(va, fmt);
179
0
    GenerateWarning(fmt, va);
180
0
    va_end(va);
181
0
182
0
    return SynthesizeGLError(LOCAL_GL_INVALID_ENUM);
183
0
}
184
185
void
186
WebGLContext::ErrorInvalidEnumInfo(const char* info, GLenum enumValue) const
187
0
{
188
0
    nsCString name;
189
0
    EnumName(enumValue, &name);
190
0
191
0
    return ErrorInvalidEnum("%s: invalid enum value %s", info, name.BeginReading());
192
0
}
193
194
void
195
WebGLContext::ErrorInvalidOperation(const char* fmt, ...) const
196
0
{
197
0
    va_list va;
198
0
    va_start(va, fmt);
199
0
    GenerateWarning(fmt, va);
200
0
    va_end(va);
201
0
202
0
    return SynthesizeGLError(LOCAL_GL_INVALID_OPERATION);
203
0
}
204
205
void
206
WebGLContext::ErrorInvalidValue(const char* fmt, ...) const
207
0
{
208
0
    va_list va;
209
0
    va_start(va, fmt);
210
0
    GenerateWarning(fmt, va);
211
0
    va_end(va);
212
0
213
0
    return SynthesizeGLError(LOCAL_GL_INVALID_VALUE);
214
0
}
215
216
void
217
WebGLContext::ErrorInvalidFramebufferOperation(const char* fmt, ...) const
218
0
{
219
0
    va_list va;
220
0
    va_start(va, fmt);
221
0
    GenerateWarning(fmt, va);
222
0
    va_end(va);
223
0
224
0
    return SynthesizeGLError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
225
0
}
226
227
void
228
WebGLContext::ErrorOutOfMemory(const char* fmt, ...) const
229
0
{
230
0
    va_list va;
231
0
    va_start(va, fmt);
232
0
    GenerateWarning(fmt, va);
233
0
    va_end(va);
234
0
235
0
    return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
236
0
}
237
238
void
239
WebGLContext::ErrorImplementationBug(const char* fmt, ...) const
240
0
{
241
0
    const nsPrintfCString warning("Implementation bug, please file at %s! %s",
242
0
                                  "https://bugzilla.mozilla.org/", fmt);
243
0
244
0
    va_list va;
245
0
    va_start(va, fmt);
246
0
    GenerateWarning(warning.BeginReading(), va);
247
0
    va_end(va);
248
0
249
0
    MOZ_ASSERT(false, "WebGLContext::ErrorImplementationBug");
250
0
    NS_ERROR("WebGLContext::ErrorImplementationBug");
251
0
    return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
252
0
}
253
254
/*static*/ const char*
255
WebGLContext::ErrorName(GLenum error)
256
0
{
257
0
    switch(error) {
258
0
    case LOCAL_GL_INVALID_ENUM:
259
0
        return "INVALID_ENUM";
260
0
    case LOCAL_GL_INVALID_OPERATION:
261
0
        return "INVALID_OPERATION";
262
0
    case LOCAL_GL_INVALID_VALUE:
263
0
        return "INVALID_VALUE";
264
0
    case LOCAL_GL_OUT_OF_MEMORY:
265
0
        return "OUT_OF_MEMORY";
266
0
    case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
267
0
        return "INVALID_FRAMEBUFFER_OPERATION";
268
0
    case LOCAL_GL_NO_ERROR:
269
0
        return "NO_ERROR";
270
0
    default:
271
0
        MOZ_ASSERT(false);
272
0
        return "[unknown WebGL error]";
273
0
    }
274
0
}
275
276
// This version is fallible and will return nullptr if unrecognized.
277
const char*
278
GetEnumName(const GLenum val, const char* const defaultRet)
279
0
{
280
0
    switch (val) {
281
0
#define XX(x) case LOCAL_GL_##x: return #x
282
0
        XX(NONE);
283
0
        XX(ALPHA);
284
0
        XX(ATC_RGB);
285
0
        XX(ATC_RGBA_EXPLICIT_ALPHA);
286
0
        XX(ATC_RGBA_INTERPOLATED_ALPHA);
287
0
        XX(COMPRESSED_RGBA_PVRTC_2BPPV1);
288
0
        XX(COMPRESSED_RGBA_PVRTC_4BPPV1);
289
0
        XX(COMPRESSED_RGBA_S3TC_DXT1_EXT);
290
0
        XX(COMPRESSED_RGBA_S3TC_DXT3_EXT);
291
0
        XX(COMPRESSED_RGBA_S3TC_DXT5_EXT);
292
0
        XX(COMPRESSED_RGB_PVRTC_2BPPV1);
293
0
        XX(COMPRESSED_RGB_PVRTC_4BPPV1);
294
0
        XX(COMPRESSED_RGB_S3TC_DXT1_EXT);
295
0
        XX(DEPTH_ATTACHMENT);
296
0
        XX(DEPTH_COMPONENT);
297
0
        XX(DEPTH_COMPONENT16);
298
0
        XX(DEPTH_COMPONENT32);
299
0
        XX(DEPTH_STENCIL);
300
0
        XX(DEPTH24_STENCIL8);
301
0
        XX(DRAW_FRAMEBUFFER);
302
0
        XX(ETC1_RGB8_OES);
303
0
        XX(FLOAT);
304
0
        XX(INT);
305
0
        XX(FRAMEBUFFER);
306
0
        XX(HALF_FLOAT);
307
0
        XX(LUMINANCE);
308
0
        XX(LUMINANCE_ALPHA);
309
0
        XX(READ_FRAMEBUFFER);
310
0
        XX(RGB);
311
0
        XX(RGB16F);
312
0
        XX(RGB32F);
313
0
        XX(RGBA);
314
0
        XX(RGBA16F);
315
0
        XX(RGBA32F);
316
0
        XX(SRGB);
317
0
        XX(SRGB_ALPHA);
318
0
        XX(TEXTURE_2D);
319
0
        XX(TEXTURE_3D);
320
0
        XX(TEXTURE_CUBE_MAP);
321
0
        XX(TEXTURE_CUBE_MAP_NEGATIVE_X);
322
0
        XX(TEXTURE_CUBE_MAP_NEGATIVE_Y);
323
0
        XX(TEXTURE_CUBE_MAP_NEGATIVE_Z);
324
0
        XX(TEXTURE_CUBE_MAP_POSITIVE_X);
325
0
        XX(TEXTURE_CUBE_MAP_POSITIVE_Y);
326
0
        XX(TEXTURE_CUBE_MAP_POSITIVE_Z);
327
0
        XX(UNSIGNED_BYTE);
328
0
        XX(UNSIGNED_INT);
329
0
        XX(UNSIGNED_INT_24_8);
330
0
        XX(UNSIGNED_SHORT);
331
0
        XX(UNSIGNED_SHORT_4_4_4_4);
332
0
        XX(UNSIGNED_SHORT_5_5_5_1);
333
0
        XX(UNSIGNED_SHORT_5_6_5);
334
0
        XX(READ_BUFFER);
335
0
        XX(UNPACK_ROW_LENGTH);
336
0
        XX(UNPACK_SKIP_ROWS);
337
0
        XX(UNPACK_SKIP_PIXELS);
338
0
        XX(PACK_ROW_LENGTH);
339
0
        XX(PACK_SKIP_ROWS);
340
0
        XX(PACK_SKIP_PIXELS);
341
0
        XX(COLOR);
342
0
        XX(DEPTH);
343
0
        XX(STENCIL);
344
0
        XX(RED);
345
0
        XX(RGB8);
346
0
        XX(RGBA8);
347
0
        XX(RGB10_A2);
348
0
        XX(TEXTURE_BINDING_3D);
349
0
        XX(UNPACK_SKIP_IMAGES);
350
0
        XX(UNPACK_IMAGE_HEIGHT);
351
0
        XX(TEXTURE_WRAP_R);
352
0
        XX(MAX_3D_TEXTURE_SIZE);
353
0
        XX(UNSIGNED_INT_2_10_10_10_REV);
354
0
        XX(MAX_ELEMENTS_VERTICES);
355
0
        XX(MAX_ELEMENTS_INDICES);
356
0
        XX(TEXTURE_MIN_LOD);
357
0
        XX(TEXTURE_MAX_LOD);
358
0
        XX(TEXTURE_BASE_LEVEL);
359
0
        XX(TEXTURE_MAX_LEVEL);
360
0
        XX(MIN);
361
0
        XX(MAX);
362
0
        XX(DEPTH_COMPONENT24);
363
0
        XX(MAX_TEXTURE_LOD_BIAS);
364
0
        XX(TEXTURE_COMPARE_MODE);
365
0
        XX(TEXTURE_COMPARE_FUNC);
366
0
        XX(CURRENT_QUERY);
367
0
        XX(QUERY_RESULT);
368
0
        XX(QUERY_RESULT_AVAILABLE);
369
0
        XX(STREAM_READ);
370
0
        XX(STREAM_COPY);
371
0
        XX(STATIC_READ);
372
0
        XX(STATIC_COPY);
373
0
        XX(DYNAMIC_READ);
374
0
        XX(DYNAMIC_COPY);
375
0
        XX(MAX_DRAW_BUFFERS);
376
0
        XX(DRAW_BUFFER0);
377
0
        XX(DRAW_BUFFER1);
378
0
        XX(DRAW_BUFFER2);
379
0
        XX(DRAW_BUFFER3);
380
0
        XX(DRAW_BUFFER4);
381
0
        XX(DRAW_BUFFER5);
382
0
        XX(DRAW_BUFFER6);
383
0
        XX(DRAW_BUFFER7);
384
0
        XX(DRAW_BUFFER8);
385
0
        XX(DRAW_BUFFER9);
386
0
        XX(DRAW_BUFFER10);
387
0
        XX(DRAW_BUFFER11);
388
0
        XX(DRAW_BUFFER12);
389
0
        XX(DRAW_BUFFER13);
390
0
        XX(DRAW_BUFFER14);
391
0
        XX(DRAW_BUFFER15);
392
0
        XX(MAX_FRAGMENT_UNIFORM_COMPONENTS);
393
0
        XX(MAX_VERTEX_UNIFORM_COMPONENTS);
394
0
        XX(SAMPLER_3D);
395
0
        XX(SAMPLER_2D_SHADOW);
396
0
        XX(FRAGMENT_SHADER_DERIVATIVE_HINT);
397
0
        XX(PIXEL_PACK_BUFFER);
398
0
        XX(PIXEL_UNPACK_BUFFER);
399
0
        XX(PIXEL_PACK_BUFFER_BINDING);
400
0
        XX(PIXEL_UNPACK_BUFFER_BINDING);
401
0
        XX(FLOAT_MAT2x3);
402
0
        XX(FLOAT_MAT2x4);
403
0
        XX(FLOAT_MAT3x2);
404
0
        XX(FLOAT_MAT3x4);
405
0
        XX(FLOAT_MAT4x2);
406
0
        XX(FLOAT_MAT4x3);
407
0
        XX(SRGB8);
408
0
        XX(SRGB8_ALPHA8);
409
0
        XX(COMPARE_REF_TO_TEXTURE);
410
0
        XX(VERTEX_ATTRIB_ARRAY_INTEGER);
411
0
        XX(MAX_ARRAY_TEXTURE_LAYERS);
412
0
        XX(MIN_PROGRAM_TEXEL_OFFSET);
413
0
        XX(MAX_PROGRAM_TEXEL_OFFSET);
414
0
        XX(MAX_VARYING_COMPONENTS);
415
0
        XX(TEXTURE_2D_ARRAY);
416
0
        XX(TEXTURE_BINDING_2D_ARRAY);
417
0
        XX(R11F_G11F_B10F);
418
0
        XX(UNSIGNED_INT_10F_11F_11F_REV);
419
0
        XX(RGB9_E5);
420
0
        XX(UNSIGNED_INT_5_9_9_9_REV);
421
0
        XX(TRANSFORM_FEEDBACK_BUFFER_MODE);
422
0
        XX(MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS);
423
0
        XX(TRANSFORM_FEEDBACK_VARYINGS);
424
0
        XX(TRANSFORM_FEEDBACK_BUFFER_START);
425
0
        XX(TRANSFORM_FEEDBACK_BUFFER_SIZE);
426
0
        XX(TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
427
0
        XX(RASTERIZER_DISCARD);
428
0
        XX(MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
429
0
        XX(MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
430
0
        XX(INTERLEAVED_ATTRIBS);
431
0
        XX(SEPARATE_ATTRIBS);
432
0
        XX(TRANSFORM_FEEDBACK_BUFFER);
433
0
        XX(TRANSFORM_FEEDBACK_BUFFER_BINDING);
434
0
        XX(RGBA32UI);
435
0
        XX(RGB32UI);
436
0
        XX(RGBA16UI);
437
0
        XX(RGB16UI);
438
0
        XX(RGBA8UI);
439
0
        XX(RGB8UI);
440
0
        XX(RGBA32I);
441
0
        XX(RGB32I);
442
0
        XX(RGBA16I);
443
0
        XX(RGB16I);
444
0
        XX(RGBA8I);
445
0
        XX(RGB8I);
446
0
        XX(RED_INTEGER);
447
0
        XX(RGB_INTEGER);
448
0
        XX(RGBA_INTEGER);
449
0
        XX(SAMPLER_2D_ARRAY);
450
0
        XX(SAMPLER_2D_ARRAY_SHADOW);
451
0
        XX(SAMPLER_CUBE_SHADOW);
452
0
        XX(UNSIGNED_INT_VEC2);
453
0
        XX(UNSIGNED_INT_VEC3);
454
0
        XX(UNSIGNED_INT_VEC4);
455
0
        XX(INT_SAMPLER_2D);
456
0
        XX(INT_SAMPLER_3D);
457
0
        XX(INT_SAMPLER_CUBE);
458
0
        XX(INT_SAMPLER_2D_ARRAY);
459
0
        XX(UNSIGNED_INT_SAMPLER_2D);
460
0
        XX(UNSIGNED_INT_SAMPLER_3D);
461
0
        XX(UNSIGNED_INT_SAMPLER_CUBE);
462
0
        XX(UNSIGNED_INT_SAMPLER_2D_ARRAY);
463
0
        XX(DEPTH_COMPONENT32F);
464
0
        XX(DEPTH32F_STENCIL8);
465
0
        XX(FLOAT_32_UNSIGNED_INT_24_8_REV);
466
0
        XX(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
467
0
        XX(FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE);
468
0
        XX(FRAMEBUFFER_ATTACHMENT_RED_SIZE);
469
0
        XX(FRAMEBUFFER_ATTACHMENT_GREEN_SIZE);
470
0
        XX(FRAMEBUFFER_ATTACHMENT_BLUE_SIZE);
471
0
        XX(FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE);
472
0
        XX(FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE);
473
0
        XX(FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE);
474
0
        XX(FRAMEBUFFER_DEFAULT);
475
0
        XX(DEPTH_STENCIL_ATTACHMENT);
476
0
        XX(UNSIGNED_NORMALIZED);
477
0
        XX(DRAW_FRAMEBUFFER_BINDING);
478
0
        XX(READ_FRAMEBUFFER_BINDING);
479
0
        XX(RENDERBUFFER_SAMPLES);
480
0
        XX(FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
481
0
        XX(MAX_COLOR_ATTACHMENTS);
482
0
        XX(COLOR_ATTACHMENT0);
483
0
        XX(COLOR_ATTACHMENT1);
484
0
        XX(COLOR_ATTACHMENT2);
485
0
        XX(COLOR_ATTACHMENT3);
486
0
        XX(COLOR_ATTACHMENT4);
487
0
        XX(COLOR_ATTACHMENT5);
488
0
        XX(COLOR_ATTACHMENT6);
489
0
        XX(COLOR_ATTACHMENT7);
490
0
        XX(COLOR_ATTACHMENT8);
491
0
        XX(COLOR_ATTACHMENT9);
492
0
        XX(COLOR_ATTACHMENT10);
493
0
        XX(COLOR_ATTACHMENT11);
494
0
        XX(COLOR_ATTACHMENT12);
495
0
        XX(COLOR_ATTACHMENT13);
496
0
        XX(COLOR_ATTACHMENT14);
497
0
        XX(COLOR_ATTACHMENT15);
498
0
        XX(FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
499
0
        XX(MAX_SAMPLES);
500
0
        XX(RG);
501
0
        XX(RG_INTEGER);
502
0
        XX(R8);
503
0
        XX(RG8);
504
0
        XX(R16F);
505
0
        XX(R32F);
506
0
        XX(RG16F);
507
0
        XX(RG32F);
508
0
        XX(R8I);
509
0
        XX(R8UI);
510
0
        XX(R16I);
511
0
        XX(R16UI);
512
0
        XX(R32I);
513
0
        XX(R32UI);
514
0
        XX(RG8I);
515
0
        XX(RG8UI);
516
0
        XX(RG16I);
517
0
        XX(RG16UI);
518
0
        XX(RG32I);
519
0
        XX(RG32UI);
520
0
        XX(VERTEX_ARRAY_BINDING);
521
0
        XX(R8_SNORM);
522
0
        XX(RG8_SNORM);
523
0
        XX(RGB8_SNORM);
524
0
        XX(RGBA8_SNORM);
525
0
        XX(SIGNED_NORMALIZED);
526
0
        XX(PRIMITIVE_RESTART_FIXED_INDEX);
527
0
        XX(COPY_READ_BUFFER);
528
0
        XX(COPY_WRITE_BUFFER);
529
0
        XX(UNIFORM_BUFFER);
530
0
        XX(UNIFORM_BUFFER_BINDING);
531
0
        XX(UNIFORM_BUFFER_START);
532
0
        XX(UNIFORM_BUFFER_SIZE);
533
0
        XX(MAX_VERTEX_UNIFORM_BLOCKS);
534
0
        XX(MAX_FRAGMENT_UNIFORM_BLOCKS);
535
0
        XX(MAX_COMBINED_UNIFORM_BLOCKS);
536
0
        XX(MAX_UNIFORM_BUFFER_BINDINGS);
537
0
        XX(MAX_UNIFORM_BLOCK_SIZE);
538
0
        XX(MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS);
539
0
        XX(MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS);
540
0
        XX(UNIFORM_BUFFER_OFFSET_ALIGNMENT);
541
0
        XX(ACTIVE_UNIFORM_BLOCKS);
542
0
        XX(UNIFORM_TYPE);
543
0
        XX(UNIFORM_SIZE);
544
0
        XX(UNIFORM_BLOCK_INDEX);
545
0
        XX(UNIFORM_OFFSET);
546
0
        XX(UNIFORM_ARRAY_STRIDE);
547
0
        XX(UNIFORM_MATRIX_STRIDE);
548
0
        XX(UNIFORM_IS_ROW_MAJOR);
549
0
        XX(UNIFORM_BLOCK_BINDING);
550
0
        XX(UNIFORM_BLOCK_DATA_SIZE);
551
0
        XX(UNIFORM_BLOCK_ACTIVE_UNIFORMS);
552
0
        XX(UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES);
553
0
        XX(UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER);
554
0
        XX(UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER);
555
0
        XX(MAX_VERTEX_OUTPUT_COMPONENTS);
556
0
        XX(MAX_FRAGMENT_INPUT_COMPONENTS);
557
0
        XX(MAX_SERVER_WAIT_TIMEOUT);
558
0
        XX(OBJECT_TYPE);
559
0
        XX(SYNC_CONDITION);
560
0
        XX(SYNC_STATUS);
561
0
        XX(SYNC_FLAGS);
562
0
        XX(SYNC_FENCE);
563
0
        XX(SYNC_GPU_COMMANDS_COMPLETE);
564
0
        XX(UNSIGNALED);
565
0
        XX(SIGNALED);
566
0
        XX(ALREADY_SIGNALED);
567
0
        XX(TIMEOUT_EXPIRED);
568
0
        XX(CONDITION_SATISFIED);
569
0
        XX(WAIT_FAILED);
570
0
        XX(VERTEX_ATTRIB_ARRAY_DIVISOR);
571
0
        XX(ANY_SAMPLES_PASSED);
572
0
        XX(ANY_SAMPLES_PASSED_CONSERVATIVE);
573
0
        XX(SAMPLER_BINDING);
574
0
        XX(RGB10_A2UI);
575
0
        XX(TEXTURE_SWIZZLE_R);
576
0
        XX(TEXTURE_SWIZZLE_G);
577
0
        XX(TEXTURE_SWIZZLE_B);
578
0
        XX(TEXTURE_SWIZZLE_A);
579
0
        XX(GREEN);
580
0
        XX(BLUE);
581
0
        XX(INT_2_10_10_10_REV);
582
0
        XX(TRANSFORM_FEEDBACK);
583
0
        XX(TRANSFORM_FEEDBACK_PAUSED);
584
0
        XX(TRANSFORM_FEEDBACK_ACTIVE);
585
0
        XX(TRANSFORM_FEEDBACK_BINDING);
586
0
        XX(COMPRESSED_R11_EAC);
587
0
        XX(COMPRESSED_SIGNED_R11_EAC);
588
0
        XX(COMPRESSED_RG11_EAC);
589
0
        XX(COMPRESSED_SIGNED_RG11_EAC);
590
0
        XX(COMPRESSED_RGB8_ETC2);
591
0
        XX(COMPRESSED_SRGB8_ETC2);
592
0
        XX(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
593
0
        XX(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
594
0
        XX(COMPRESSED_RGBA8_ETC2_EAC);
595
0
        XX(COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
596
0
        XX(TEXTURE_IMMUTABLE_FORMAT);
597
0
        XX(MAX_ELEMENT_INDEX);
598
0
        XX(NUM_SAMPLE_COUNTS);
599
0
        XX(TEXTURE_IMMUTABLE_LEVELS);
600
0
#undef XX
601
0
    }
602
0
603
0
    return defaultRet;
604
0
}
605
606
/*static*/ void
607
WebGLContext::EnumName(GLenum val, nsCString* out_name)
608
0
{
609
0
    const char* name = GetEnumName(val, nullptr);
610
0
    if (name) {
611
0
        *out_name = name;
612
0
        return;
613
0
    }
614
0
615
0
    *out_name = nsPrintfCString("<enum 0x%04x>", val);
616
0
}
617
618
std::string
619
EnumString(const GLenum val)
620
0
{
621
0
    const char* name = GetEnumName(val, nullptr);
622
0
    if (name) {
623
0
        return name;
624
0
    }
625
0
626
0
    const nsPrintfCString hex("<enum 0x%04x>", val);
627
0
    return hex.BeginReading();
628
0
}
629
630
void
631
WebGLContext::ErrorInvalidEnumArg(const char* argName, GLenum val) const
632
0
{
633
0
    nsCString enumName;
634
0
    EnumName(val, &enumName);
635
0
    ErrorInvalidEnum("Bad `%s`: %s", argName, enumName.BeginReading());
636
0
}
637
638
bool
639
IsCompressedTextureFormat(GLenum format)
640
0
{
641
0
    switch (format) {
642
0
    case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
643
0
    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
644
0
    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
645
0
    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
646
0
    case LOCAL_GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
647
0
    case LOCAL_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
648
0
    case LOCAL_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
649
0
    case LOCAL_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
650
0
    case LOCAL_GL_ATC_RGB:
651
0
    case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
652
0
    case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
653
0
    case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
654
0
    case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
655
0
    case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
656
0
    case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
657
0
    case LOCAL_GL_ETC1_RGB8_OES:
658
0
    case LOCAL_GL_COMPRESSED_R11_EAC:
659
0
    case LOCAL_GL_COMPRESSED_SIGNED_R11_EAC:
660
0
    case LOCAL_GL_COMPRESSED_RG11_EAC:
661
0
    case LOCAL_GL_COMPRESSED_SIGNED_RG11_EAC:
662
0
    case LOCAL_GL_COMPRESSED_RGB8_ETC2:
663
0
    case LOCAL_GL_COMPRESSED_SRGB8_ETC2:
664
0
    case LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
665
0
    case LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
666
0
    case LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC:
667
0
    case LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
668
0
        return true;
669
0
    default:
670
0
        return false;
671
0
    }
672
0
}
673
674
675
bool
676
IsTextureFormatCompressed(TexInternalFormat format)
677
0
{
678
0
    return IsCompressedTextureFormat(format.get());
679
0
}
680
681
GLenum
682
WebGLContext::GetAndFlushUnderlyingGLErrors() const
683
0
{
684
0
    // Get and clear GL error in ALL cases.
685
0
    GLenum error = gl->fGetError();
686
0
687
0
    // Only store in mUnderlyingGLError if is hasn't already recorded an
688
0
    // error.
689
0
    if (!mUnderlyingGLError)
690
0
        mUnderlyingGLError = error;
691
0
692
0
    return error;
693
0
}
694
695
#ifdef DEBUG
696
// For NaNs, etc.
697
static bool
698
IsCacheCorrect(float cached, float actual)
699
{
700
    if (IsNaN(cached)) {
701
        // GL is allowed to do anything it wants for NaNs, so if we're shadowing
702
        // a NaN, then whatever `actual` is might be correct.
703
        return true;
704
    }
705
706
    return cached == actual;
707
}
708
709
void
710
AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow)
711
{
712
    GLuint val = 0;
713
    gl->GetUIntegerv(pname, &val);
714
    if (val != shadow) {
715
      printf_stderr("Failed 0x%04x shadow: Cached 0x%x/%u, should be 0x%x/%u.\n",
716
                    pname, shadow, shadow, val, val);
717
      MOZ_ASSERT(false, "Bad cached value.");
718
    }
719
}
720
721
void
722
AssertMaskedUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint mask,
723
                             GLuint shadow)
724
{
725
    GLuint val = 0;
726
    gl->GetUIntegerv(pname, &val);
727
728
    const GLuint valMasked = val & mask;
729
    const GLuint shadowMasked = shadow & mask;
730
731
    if (valMasked != shadowMasked) {
732
      printf_stderr("Failed 0x%04x shadow: Cached 0x%x/%u, should be 0x%x/%u.\n",
733
                    pname, shadowMasked, shadowMasked, valMasked, valMasked);
734
      MOZ_ASSERT(false, "Bad cached value.");
735
    }
736
}
737
#else
738
void
739
AssertUintParamCorrect(gl::GLContext*, GLenum, GLuint)
740
0
{
741
0
}
742
#endif
743
744
void
745
WebGLContext::AssertCachedBindings() const
746
0
{
747
#ifdef DEBUG
748
    GetAndFlushUnderlyingGLErrors();
749
750
    if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
751
        GLuint bound = mBoundVertexArray ? mBoundVertexArray->GLName() : 0;
752
        AssertUintParamCorrect(gl, LOCAL_GL_VERTEX_ARRAY_BINDING, bound);
753
    }
754
755
    GLint stencilBits = 0;
756
    if (GetStencilBits(&stencilBits)) { // Depends on current draw framebuffer.
757
        const GLuint stencilRefMask = (1 << stencilBits) - 1;
758
759
        AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_REF,      stencilRefMask, mStencilRefFront);
760
        AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_REF, stencilRefMask, mStencilRefBack);
761
    }
762
763
    // Program
764
    GLuint bound = mCurrentProgram ? mCurrentProgram->mGLName : 0;
765
    AssertUintParamCorrect(gl, LOCAL_GL_CURRENT_PROGRAM, bound);
766
767
    // Textures
768
    GLenum activeTexture = mActiveTexture + LOCAL_GL_TEXTURE0;
769
    AssertUintParamCorrect(gl, LOCAL_GL_ACTIVE_TEXTURE, activeTexture);
770
771
    WebGLTexture* curTex = ActiveBoundTextureForTarget(LOCAL_GL_TEXTURE_2D);
772
    bound = curTex ? curTex->mGLName : 0;
773
    AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_2D, bound);
774
775
    curTex = ActiveBoundTextureForTarget(LOCAL_GL_TEXTURE_CUBE_MAP);
776
    bound = curTex ? curTex->mGLName : 0;
777
    AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_CUBE_MAP, bound);
778
779
    // Buffers
780
    bound = mBoundArrayBuffer ? mBoundArrayBuffer->mGLName : 0;
781
    AssertUintParamCorrect(gl, LOCAL_GL_ARRAY_BUFFER_BINDING, bound);
782
783
    MOZ_ASSERT(mBoundVertexArray);
784
    WebGLBuffer* curBuff = mBoundVertexArray->mElementArrayBuffer;
785
    bound = curBuff ? curBuff->mGLName : 0;
786
    AssertUintParamCorrect(gl, LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING, bound);
787
788
    MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
789
#endif
790
791
0
    // We do not check the renderbuffer binding, because we never rely on it matching.
792
0
}
793
794
void
795
WebGLContext::AssertCachedGlobalState() const
796
0
{
797
#ifdef DEBUG
798
    GetAndFlushUnderlyingGLErrors();
799
800
    ////////////////
801
802
    // Draw state
803
    MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_DITHER) == mDitherEnabled);
804
    MOZ_ASSERT_IF(IsWebGL2(),
805
                  gl->fIsEnabled(LOCAL_GL_RASTERIZER_DISCARD) == mRasterizerDiscardEnabled);
806
    MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST) == mScissorTestEnabled);
807
808
    // Cannot trivially check COLOR_CLEAR_VALUE, since in old GL versions glGet may clamp
809
    // based on whether the current framebuffer is floating-point or not.
810
    // This also means COLOR_CLEAR_VALUE save+restore is dangerous!
811
812
    realGLboolean depthWriteMask = 0;
813
    gl->fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
814
    MOZ_ASSERT(depthWriteMask == mDepthWriteMask);
815
816
    GLfloat depthClearValue = 0.0f;
817
    gl->fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
818
    MOZ_ASSERT(IsCacheCorrect(mDepthClearValue, depthClearValue));
819
820
    const int maxStencilBits = 8;
821
    const GLuint maxStencilBitsMask = (1 << maxStencilBits) - 1;
822
    AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_CLEAR_VALUE, maxStencilBitsMask, mStencilClearValue);
823
824
    // GLES 3.0.4, $4.1.4, p177:
825
    //   [...] the front and back stencil mask are both set to the value `2^s - 1`, where
826
    //   `s` is greater than or equal to the number of bits in the deepest stencil buffer
827
    //   supported by the GL implementation.
828
    AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_VALUE_MASK,      maxStencilBitsMask, mStencilValueMaskFront);
829
    AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_VALUE_MASK, maxStencilBitsMask, mStencilValueMaskBack);
830
831
    AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_WRITEMASK,       maxStencilBitsMask, mStencilWriteMaskFront);
832
    AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_WRITEMASK,  maxStencilBitsMask, mStencilWriteMaskBack);
833
834
    // Viewport
835
    GLint int4[4] = {0, 0, 0, 0};
836
    gl->fGetIntegerv(LOCAL_GL_VIEWPORT, int4);
837
    MOZ_ASSERT(int4[0] == mViewportX &&
838
               int4[1] == mViewportY &&
839
               int4[2] == mViewportWidth &&
840
               int4[3] == mViewportHeight);
841
842
    AssertUintParamCorrect(gl, LOCAL_GL_PACK_ALIGNMENT, mPixelStore_PackAlignment);
843
    AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ALIGNMENT, mPixelStore_UnpackAlignment);
844
845
    if (IsWebGL2()) {
846
        AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_IMAGE_HEIGHT, mPixelStore_UnpackImageHeight);
847
        AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_IMAGES , mPixelStore_UnpackSkipImages);
848
        AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ROW_LENGTH  , mPixelStore_UnpackRowLength);
849
        AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_ROWS   , mPixelStore_UnpackSkipRows);
850
        AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_PIXELS , mPixelStore_UnpackSkipPixels);
851
        AssertUintParamCorrect(gl, LOCAL_GL_PACK_ROW_LENGTH    , mPixelStore_PackRowLength);
852
        AssertUintParamCorrect(gl, LOCAL_GL_PACK_SKIP_ROWS     , mPixelStore_PackSkipRows);
853
        AssertUintParamCorrect(gl, LOCAL_GL_PACK_SKIP_PIXELS   , mPixelStore_PackSkipPixels);
854
    }
855
856
    MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
857
#endif
858
}
859
860
const char*
861
InfoFrom(WebGLTexImageFunc func, WebGLTexDimensions dims)
862
0
{
863
0
    switch (dims) {
864
0
    case WebGLTexDimensions::Tex2D:
865
0
        switch (func) {
866
0
        case WebGLTexImageFunc::TexImage:        return "texImage2D";
867
0
        case WebGLTexImageFunc::TexSubImage:     return "texSubImage2D";
868
0
        case WebGLTexImageFunc::CopyTexImage:    return "copyTexImage2D";
869
0
        case WebGLTexImageFunc::CopyTexSubImage: return "copyTexSubImage2D";
870
0
        case WebGLTexImageFunc::CompTexImage:    return "compressedTexImage2D";
871
0
        case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage2D";
872
0
        default:
873
0
            MOZ_CRASH("GFX: invalid 2D TexDimensions");
874
0
        }
875
0
    case WebGLTexDimensions::Tex3D:
876
0
        switch (func) {
877
0
        case WebGLTexImageFunc::TexImage:        return "texImage3D";
878
0
        case WebGLTexImageFunc::TexSubImage:     return "texSubImage3D";
879
0
        case WebGLTexImageFunc::CopyTexSubImage: return "copyTexSubImage3D";
880
0
        case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage3D";
881
0
        default:
882
0
            MOZ_CRASH("GFX: invalid 3D TexDimensions");
883
0
        }
884
0
    default:
885
0
        MOZ_CRASH("GFX: invalid TexDimensions");
886
0
    }
887
0
}
888
889
////
890
891
JS::Value
892
StringValue(JSContext* cx, const nsAString& str, ErrorResult& er)
893
0
{
894
0
    JSString* jsStr = JS_NewUCStringCopyN(cx, str.BeginReading(), str.Length());
895
0
    if (!jsStr) {
896
0
        er.Throw(NS_ERROR_OUT_OF_MEMORY);
897
0
        return JS::NullValue();
898
0
    }
899
0
900
0
    return JS::StringValue(jsStr);
901
0
}
902
903
} // namespace mozilla