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