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 "WebGLContext.h"
7 :
8 : #include <algorithm>
9 : #include "angle/ShaderLang.h"
10 : #include "CanvasUtils.h"
11 : #include "gfxPrefs.h"
12 : #include "GLContext.h"
13 : #include "jsfriendapi.h"
14 : #include "mozilla/CheckedInt.h"
15 : #include "mozilla/Preferences.h"
16 : #include "mozilla/Services.h"
17 : #include "nsIObserverService.h"
18 : #include "nsPrintfCString.h"
19 : #include "WebGLActiveInfo.h"
20 : #include "WebGLBuffer.h"
21 : #include "WebGLContextUtils.h"
22 : #include "WebGLFramebuffer.h"
23 : #include "WebGLProgram.h"
24 : #include "WebGLRenderbuffer.h"
25 : #include "WebGLSampler.h"
26 : #include "WebGLShader.h"
27 : #include "WebGLTexture.h"
28 : #include "WebGLUniformLocation.h"
29 : #include "WebGLValidateStrings.h"
30 : #include "WebGLVertexArray.h"
31 : #include "WebGLVertexAttribData.h"
32 :
33 : #if defined(MOZ_WIDGET_COCOA)
34 : #include "nsCocoaFeatures.h"
35 : #endif
36 :
37 : namespace mozilla {
38 :
39 : bool
40 0 : WebGLContext::ValidateBlendEquationEnum(GLenum mode, const char* info)
41 : {
42 0 : switch (mode) {
43 : case LOCAL_GL_FUNC_ADD:
44 : case LOCAL_GL_FUNC_SUBTRACT:
45 : case LOCAL_GL_FUNC_REVERSE_SUBTRACT:
46 0 : return true;
47 :
48 : case LOCAL_GL_MIN:
49 : case LOCAL_GL_MAX:
50 0 : if (IsWebGL2() ||
51 0 : IsExtensionEnabled(WebGLExtensionID::EXT_blend_minmax))
52 : {
53 0 : return true;
54 : }
55 :
56 0 : break;
57 :
58 : default:
59 0 : break;
60 : }
61 :
62 0 : ErrorInvalidEnumInfo(info, mode);
63 0 : return false;
64 : }
65 :
66 : bool
67 0 : WebGLContext::ValidateBlendFuncDstEnum(GLenum factor, const char* info)
68 : {
69 0 : switch (factor) {
70 : case LOCAL_GL_ZERO:
71 : case LOCAL_GL_ONE:
72 : case LOCAL_GL_SRC_COLOR:
73 : case LOCAL_GL_ONE_MINUS_SRC_COLOR:
74 : case LOCAL_GL_DST_COLOR:
75 : case LOCAL_GL_ONE_MINUS_DST_COLOR:
76 : case LOCAL_GL_SRC_ALPHA:
77 : case LOCAL_GL_ONE_MINUS_SRC_ALPHA:
78 : case LOCAL_GL_DST_ALPHA:
79 : case LOCAL_GL_ONE_MINUS_DST_ALPHA:
80 : case LOCAL_GL_CONSTANT_COLOR:
81 : case LOCAL_GL_ONE_MINUS_CONSTANT_COLOR:
82 : case LOCAL_GL_CONSTANT_ALPHA:
83 : case LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA:
84 0 : return true;
85 :
86 : default:
87 0 : ErrorInvalidEnumInfo(info, factor);
88 0 : return false;
89 : }
90 : }
91 :
92 : bool
93 0 : WebGLContext::ValidateBlendFuncSrcEnum(GLenum factor, const char* info)
94 : {
95 0 : if (factor == LOCAL_GL_SRC_ALPHA_SATURATE)
96 0 : return true;
97 :
98 0 : return ValidateBlendFuncDstEnum(factor, info);
99 : }
100 :
101 : bool
102 0 : WebGLContext::ValidateBlendFuncEnumsCompatibility(GLenum sfactor,
103 : GLenum dfactor,
104 : const char* info)
105 : {
106 0 : bool sfactorIsConstantColor = sfactor == LOCAL_GL_CONSTANT_COLOR ||
107 0 : sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
108 0 : bool sfactorIsConstantAlpha = sfactor == LOCAL_GL_CONSTANT_ALPHA ||
109 0 : sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
110 0 : bool dfactorIsConstantColor = dfactor == LOCAL_GL_CONSTANT_COLOR ||
111 0 : dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
112 0 : bool dfactorIsConstantAlpha = dfactor == LOCAL_GL_CONSTANT_ALPHA ||
113 0 : dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
114 0 : if ( (sfactorIsConstantColor && dfactorIsConstantAlpha) ||
115 0 : (dfactorIsConstantColor && sfactorIsConstantAlpha) )
116 : {
117 : ErrorInvalidOperation("%s are mutually incompatible, see section 6.8 in"
118 0 : " the WebGL 1.0 spec", info);
119 0 : return false;
120 : }
121 :
122 0 : return true;
123 : }
124 :
125 : bool
126 0 : WebGLContext::ValidateComparisonEnum(GLenum target, const char* info)
127 : {
128 0 : switch (target) {
129 : case LOCAL_GL_NEVER:
130 : case LOCAL_GL_LESS:
131 : case LOCAL_GL_LEQUAL:
132 : case LOCAL_GL_GREATER:
133 : case LOCAL_GL_GEQUAL:
134 : case LOCAL_GL_EQUAL:
135 : case LOCAL_GL_NOTEQUAL:
136 : case LOCAL_GL_ALWAYS:
137 0 : return true;
138 :
139 : default:
140 0 : ErrorInvalidEnumInfo(info, target);
141 0 : return false;
142 : }
143 : }
144 :
145 : bool
146 0 : WebGLContext::ValidateStencilOpEnum(GLenum action, const char* info)
147 : {
148 0 : switch (action) {
149 : case LOCAL_GL_KEEP:
150 : case LOCAL_GL_ZERO:
151 : case LOCAL_GL_REPLACE:
152 : case LOCAL_GL_INCR:
153 : case LOCAL_GL_INCR_WRAP:
154 : case LOCAL_GL_DECR:
155 : case LOCAL_GL_DECR_WRAP:
156 : case LOCAL_GL_INVERT:
157 0 : return true;
158 :
159 : default:
160 0 : ErrorInvalidEnumInfo(info, action);
161 0 : return false;
162 : }
163 : }
164 :
165 : bool
166 0 : WebGLContext::ValidateFaceEnum(GLenum face, const char* info)
167 : {
168 0 : switch (face) {
169 : case LOCAL_GL_FRONT:
170 : case LOCAL_GL_BACK:
171 : case LOCAL_GL_FRONT_AND_BACK:
172 0 : return true;
173 :
174 : default:
175 0 : ErrorInvalidEnumInfo(info, face);
176 0 : return false;
177 : }
178 : }
179 :
180 : bool
181 0 : WebGLContext::ValidateDrawModeEnum(GLenum mode, const char* info)
182 : {
183 0 : switch (mode) {
184 : case LOCAL_GL_TRIANGLES:
185 : case LOCAL_GL_TRIANGLE_STRIP:
186 : case LOCAL_GL_TRIANGLE_FAN:
187 : case LOCAL_GL_POINTS:
188 : case LOCAL_GL_LINE_STRIP:
189 : case LOCAL_GL_LINE_LOOP:
190 : case LOCAL_GL_LINES:
191 0 : return true;
192 :
193 : default:
194 0 : ErrorInvalidEnumInfo(info, mode);
195 0 : return false;
196 : }
197 : }
198 :
199 : bool
200 0 : WebGLContext::ValidateUniformLocation(WebGLUniformLocation* loc, const char* funcName)
201 : {
202 : /* GLES 2.0.25, p38:
203 : * If the value of location is -1, the Uniform* commands will silently
204 : * ignore the data passed in, and the current uniform values will not be
205 : * changed.
206 : */
207 0 : if (!loc)
208 0 : return false;
209 :
210 0 : if (!ValidateObjectAllowDeleted(funcName, *loc))
211 0 : return false;
212 :
213 0 : if (!mCurrentProgram) {
214 0 : ErrorInvalidOperation("%s: No program is currently bound.", funcName);
215 0 : return false;
216 : }
217 :
218 0 : return loc->ValidateForProgram(mCurrentProgram, funcName);
219 : }
220 :
221 : bool
222 0 : WebGLContext::ValidateAttribArraySetter(const char* name, uint32_t setterElemSize,
223 : uint32_t arrayLength)
224 : {
225 0 : if (IsContextLost())
226 0 : return false;
227 :
228 0 : if (arrayLength < setterElemSize) {
229 : ErrorInvalidValue("%s: Array must have >= %d elements.", name,
230 0 : setterElemSize);
231 0 : return false;
232 : }
233 :
234 0 : return true;
235 : }
236 :
237 : bool
238 0 : WebGLContext::ValidateUniformSetter(WebGLUniformLocation* loc,
239 : uint8_t setterElemSize, GLenum setterType,
240 : const char* funcName)
241 : {
242 0 : if (IsContextLost())
243 0 : return false;
244 :
245 0 : if (!ValidateUniformLocation(loc, funcName))
246 0 : return false;
247 :
248 0 : if (!loc->ValidateSizeAndType(setterElemSize, setterType, funcName))
249 0 : return false;
250 :
251 0 : return true;
252 : }
253 :
254 : bool
255 0 : WebGLContext::ValidateUniformArraySetter(WebGLUniformLocation* loc,
256 : uint8_t setterElemSize,
257 : GLenum setterType,
258 : uint32_t setterArraySize,
259 : const char* funcName,
260 : uint32_t* const out_numElementsToUpload)
261 : {
262 0 : if (IsContextLost())
263 0 : return false;
264 :
265 0 : if (!ValidateUniformLocation(loc, funcName))
266 0 : return false;
267 :
268 0 : if (!loc->ValidateSizeAndType(setterElemSize, setterType, funcName))
269 0 : return false;
270 :
271 0 : if (!loc->ValidateArrayLength(setterElemSize, setterArraySize, funcName))
272 0 : return false;
273 :
274 0 : const auto& elemCount = loc->mInfo->mActiveInfo->mElemCount;
275 0 : MOZ_ASSERT(elemCount > loc->mArrayIndex);
276 0 : const uint32_t uniformElemCount = elemCount - loc->mArrayIndex;
277 :
278 0 : *out_numElementsToUpload = std::min(uniformElemCount,
279 0 : setterArraySize / setterElemSize);
280 0 : return true;
281 : }
282 :
283 : bool
284 0 : WebGLContext::ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc,
285 : uint8_t setterCols,
286 : uint8_t setterRows,
287 : GLenum setterType,
288 : uint32_t setterArraySize,
289 : bool setterTranspose,
290 : const char* funcName,
291 : uint32_t* const out_numElementsToUpload)
292 : {
293 0 : const uint8_t setterElemSize = setterCols * setterRows;
294 :
295 0 : if (IsContextLost())
296 0 : return false;
297 :
298 0 : if (!ValidateUniformLocation(loc, funcName))
299 0 : return false;
300 :
301 0 : if (!loc->ValidateSizeAndType(setterElemSize, setterType, funcName))
302 0 : return false;
303 :
304 0 : if (!loc->ValidateArrayLength(setterElemSize, setterArraySize, funcName))
305 0 : return false;
306 :
307 0 : if (setterTranspose && !IsWebGL2()) {
308 0 : ErrorInvalidValue("%s: `transpose` must be false.", funcName);
309 0 : return false;
310 : }
311 :
312 0 : const auto& elemCount = loc->mInfo->mActiveInfo->mElemCount;
313 0 : MOZ_ASSERT(elemCount > loc->mArrayIndex);
314 0 : const uint32_t uniformElemCount = elemCount - loc->mArrayIndex;
315 :
316 0 : *out_numElementsToUpload = std::min(uniformElemCount,
317 0 : setterArraySize / setterElemSize);
318 0 : return true;
319 : }
320 :
321 : bool
322 0 : WebGLContext::ValidateAttribIndex(GLuint index, const char* info)
323 : {
324 0 : bool valid = (index < MaxVertexAttribs());
325 :
326 0 : if (!valid) {
327 0 : if (index == GLuint(-1)) {
328 : ErrorInvalidValue("%s: -1 is not a valid `index`. This value"
329 : " probably comes from a getAttribLocation()"
330 : " call, where this return value -1 means"
331 : " that the passed name didn't correspond to"
332 : " an active attribute in the specified"
333 0 : " program.", info);
334 : } else {
335 : ErrorInvalidValue("%s: `index` must be less than"
336 0 : " MAX_VERTEX_ATTRIBS.", info);
337 : }
338 : }
339 :
340 0 : return valid;
341 : }
342 :
343 : bool
344 0 : WebGLContext::ValidateStencilParamsForDrawCall()
345 : {
346 : const char msg[] = "%s set different front and back stencil %s. Drawing in"
347 0 : " this configuration is not allowed.";
348 :
349 0 : if (mStencilRefFront != mStencilRefBack) {
350 0 : ErrorInvalidOperation(msg, "stencilFuncSeparate", "reference values");
351 0 : return false;
352 : }
353 :
354 0 : if (mStencilValueMaskFront != mStencilValueMaskBack) {
355 0 : ErrorInvalidOperation(msg, "stencilFuncSeparate", "value masks");
356 0 : return false;
357 : }
358 :
359 0 : if (mStencilWriteMaskFront != mStencilWriteMaskBack) {
360 0 : ErrorInvalidOperation(msg, "stencilMaskSeparate", "write masks");
361 0 : return false;
362 : }
363 :
364 0 : return true;
365 : }
366 :
367 : static inline int32_t
368 : FloorPOT(int32_t x)
369 : {
370 : MOZ_ASSERT(x > 0);
371 : int32_t pot = 1;
372 : while (pot < 0x40000000) {
373 : if (x < pot*2)
374 : break;
375 : pot *= 2;
376 : }
377 : return pot;
378 : }
379 :
380 : bool
381 0 : WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
382 : {
383 0 : MOZ_RELEASE_ASSERT(gl, "GFX: GL not initialized");
384 :
385 : // Unconditionally create a new format usage authority. This is
386 : // important when restoring contexts and extensions need to add
387 : // formats back into the authority.
388 0 : mFormatUsage = CreateFormatUsage(gl);
389 0 : if (!mFormatUsage) {
390 : *out_failReason = { "FEATURE_FAILURE_WEBGL_FORMAT",
391 0 : "Failed to create mFormatUsage." };
392 0 : return false;
393 : }
394 :
395 0 : GLenum error = gl->fGetError();
396 0 : if (error != LOCAL_GL_NO_ERROR) {
397 : const nsPrintfCString reason("GL error 0x%x occurred during OpenGL context"
398 : " initialization, before WebGL initialization!",
399 0 : error);
400 0 : *out_failReason = { "FEATURE_FAILURE_WEBGL_GLERR_1", reason };
401 0 : return false;
402 : }
403 :
404 0 : mMinCapability = gfxPrefs::WebGLMinCapabilityMode();
405 0 : mDisableExtensions = gfxPrefs::WebGLDisableExtensions();
406 0 : mLoseContextOnMemoryPressure = gfxPrefs::WebGLLoseContextOnMemoryPressure();
407 0 : mCanLoseContextInForeground = gfxPrefs::WebGLCanLoseContextInForeground();
408 0 : mRestoreWhenVisible = gfxPrefs::WebGLRestoreWhenVisible();
409 :
410 0 : if (MinCapabilityMode())
411 0 : mDisableFragHighP = true;
412 :
413 : // These are the default values, see 6.2 State tables in the
414 : // OpenGL ES 2.0.25 spec.
415 0 : mColorWriteMask[0] = 1;
416 0 : mColorWriteMask[1] = 1;
417 0 : mColorWriteMask[2] = 1;
418 0 : mColorWriteMask[3] = 1;
419 0 : mDepthWriteMask = 1;
420 0 : mColorClearValue[0] = 0.f;
421 0 : mColorClearValue[1] = 0.f;
422 0 : mColorClearValue[2] = 0.f;
423 0 : mColorClearValue[3] = 0.f;
424 0 : mDepthClearValue = 1.f;
425 0 : mStencilClearValue = 0;
426 0 : mStencilRefFront = 0;
427 0 : mStencilRefBack = 0;
428 :
429 0 : mLineWidth = 1.0;
430 :
431 : /*
432 : // Technically, we should be setting mStencil[...] values to
433 : // `allOnes`, but either ANGLE breaks or the SGX540s on Try break.
434 : GLuint stencilBits = 0;
435 : gl->GetUIntegerv(LOCAL_GL_STENCIL_BITS, &stencilBits);
436 : GLuint allOnes = ~(UINT32_MAX << stencilBits);
437 : mStencilValueMaskFront = allOnes;
438 : mStencilValueMaskBack = allOnes;
439 : mStencilWriteMaskFront = allOnes;
440 : mStencilWriteMaskBack = allOnes;
441 : */
442 :
443 0 : gl->GetUIntegerv(LOCAL_GL_STENCIL_VALUE_MASK, &mStencilValueMaskFront);
444 0 : gl->GetUIntegerv(LOCAL_GL_STENCIL_BACK_VALUE_MASK, &mStencilValueMaskBack);
445 0 : gl->GetUIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &mStencilWriteMaskFront);
446 0 : gl->GetUIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &mStencilWriteMaskBack);
447 :
448 0 : AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_VALUE_MASK, mStencilValueMaskFront);
449 0 : AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_VALUE_MASK, mStencilValueMaskBack);
450 0 : AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_WRITEMASK, mStencilWriteMaskFront);
451 0 : AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_WRITEMASK, mStencilWriteMaskBack);
452 :
453 0 : mDitherEnabled = true;
454 0 : mRasterizerDiscardEnabled = false;
455 0 : mScissorTestEnabled = false;
456 0 : mDepthTestEnabled = 0;
457 0 : mStencilTestEnabled = 0;
458 0 : mGenerateMipmapHint = LOCAL_GL_DONT_CARE;
459 :
460 : // Bindings, etc.
461 0 : mActiveTexture = 0;
462 0 : mDefaultFB_DrawBuffer0 = LOCAL_GL_BACK;
463 :
464 0 : mEmitContextLostErrorOnce = true;
465 0 : mWebGLError = LOCAL_GL_NO_ERROR;
466 0 : mUnderlyingGLError = LOCAL_GL_NO_ERROR;
467 :
468 0 : mBound2DTextures.Clear();
469 0 : mBoundCubeMapTextures.Clear();
470 0 : mBound3DTextures.Clear();
471 0 : mBound2DArrayTextures.Clear();
472 0 : mBoundSamplers.Clear();
473 :
474 0 : mBoundArrayBuffer = nullptr;
475 0 : mCurrentProgram = nullptr;
476 :
477 0 : mBoundDrawFramebuffer = nullptr;
478 0 : mBoundReadFramebuffer = nullptr;
479 0 : mBoundRenderbuffer = nullptr;
480 :
481 0 : MakeContextCurrent();
482 :
483 0 : if (MinCapabilityMode())
484 0 : mGLMaxVertexAttribs = MINVALUE_GL_MAX_VERTEX_ATTRIBS;
485 : else
486 0 : gl->GetUIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs);
487 :
488 0 : if (mGLMaxVertexAttribs < 8) {
489 : const nsPrintfCString reason("GL_MAX_VERTEX_ATTRIBS: %d is < 8!",
490 0 : mGLMaxVertexAttribs);
491 0 : *out_failReason = { "FEATURE_FAILURE_WEBGL_V_ATRB", reason };
492 0 : return false;
493 : }
494 :
495 : // Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
496 : // even though the hardware supports much more. The
497 : // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
498 0 : if (MinCapabilityMode())
499 0 : mGLMaxTextureUnits = MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS;
500 : else
501 0 : gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGLMaxTextureUnits);
502 :
503 0 : if (mGLMaxTextureUnits < 8) {
504 : const nsPrintfCString reason("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!",
505 0 : mGLMaxTextureUnits);
506 0 : *out_failReason = { "FEATURE_FAILURE_WEBGL_T_UNIT", reason };
507 0 : return false;
508 : }
509 :
510 0 : mBound2DTextures.SetLength(mGLMaxTextureUnits);
511 0 : mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
512 0 : mBound3DTextures.SetLength(mGLMaxTextureUnits);
513 0 : mBound2DArrayTextures.SetLength(mGLMaxTextureUnits);
514 0 : mBoundSamplers.SetLength(mGLMaxTextureUnits);
515 :
516 0 : gl->fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS, (GLint*)mImplMaxViewportDims);
517 :
518 : ////////////////
519 :
520 0 : if (MinCapabilityMode()) {
521 0 : mImplMaxTextureSize = MINVALUE_GL_MAX_TEXTURE_SIZE;
522 0 : mImplMaxCubeMapTextureSize = MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE;
523 0 : mImplMaxRenderbufferSize = MINVALUE_GL_MAX_RENDERBUFFER_SIZE;
524 :
525 0 : mImplMax3DTextureSize = MINVALUE_GL_MAX_3D_TEXTURE_SIZE;
526 0 : mImplMaxArrayTextureLayers = MINVALUE_GL_MAX_ARRAY_TEXTURE_LAYERS;
527 :
528 0 : mGLMaxTextureImageUnits = MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS;
529 0 : mGLMaxVertexTextureImageUnits = MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS;
530 : } else {
531 0 : gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, (GLint*)&mImplMaxTextureSize);
532 0 : gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&mImplMaxCubeMapTextureSize);
533 0 : gl->fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, (GLint*)&mImplMaxRenderbufferSize);
534 :
535 0 : if (!gl->GetPotentialInteger(LOCAL_GL_MAX_3D_TEXTURE_SIZE, (GLint*)&mImplMax3DTextureSize))
536 0 : mImplMax3DTextureSize = 0;
537 0 : if (!gl->GetPotentialInteger(LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS, (GLint*)&mImplMaxArrayTextureLayers))
538 0 : mImplMaxArrayTextureLayers = 0;
539 :
540 0 : gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxTextureImageUnits);
541 0 : gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits);
542 : }
543 :
544 : ////////////////
545 :
546 0 : mGLMaxColorAttachments = 1;
547 0 : mGLMaxDrawBuffers = 1;
548 0 : gl->GetPotentialInteger(LOCAL_GL_MAX_COLOR_ATTACHMENTS,
549 0 : (GLint*)&mGLMaxColorAttachments);
550 0 : gl->GetPotentialInteger(LOCAL_GL_MAX_DRAW_BUFFERS, (GLint*)&mGLMaxDrawBuffers);
551 :
552 0 : if (MinCapabilityMode()) {
553 0 : mGLMaxColorAttachments = std::min(mGLMaxColorAttachments,
554 0 : kMinMaxColorAttachments);
555 0 : mGLMaxDrawBuffers = std::min(mGLMaxDrawBuffers, kMinMaxDrawBuffers);
556 : }
557 :
558 0 : if (IsWebGL2()) {
559 0 : mImplMaxColorAttachments = mGLMaxColorAttachments;
560 0 : mImplMaxDrawBuffers = std::min(mGLMaxDrawBuffers, mImplMaxColorAttachments);
561 : } else {
562 0 : mImplMaxColorAttachments = 1;
563 0 : mImplMaxDrawBuffers = 1;
564 : }
565 :
566 : ////////////////
567 :
568 0 : if (MinCapabilityMode()) {
569 0 : mGLMaxFragmentUniformVectors = MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS;
570 0 : mGLMaxVertexUniformVectors = MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS;
571 0 : mGLMaxVaryingVectors = MINVALUE_GL_MAX_VARYING_VECTORS;
572 : } else {
573 0 : if (gl->IsSupported(gl::GLFeature::ES2_compatibility)) {
574 0 : gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGLMaxFragmentUniformVectors);
575 0 : gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS, &mGLMaxVertexUniformVectors);
576 0 : gl->fGetIntegerv(LOCAL_GL_MAX_VARYING_VECTORS, &mGLMaxVaryingVectors);
577 : } else {
578 0 : gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &mGLMaxFragmentUniformVectors);
579 0 : mGLMaxFragmentUniformVectors /= 4;
580 0 : gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS, &mGLMaxVertexUniformVectors);
581 0 : mGLMaxVertexUniformVectors /= 4;
582 :
583 : /* We are now going to try to read GL_MAX_VERTEX_OUTPUT_COMPONENTS
584 : * and GL_MAX_FRAGMENT_INPUT_COMPONENTS, however these constants
585 : * only entered the OpenGL standard at OpenGL 3.2. So we will try
586 : * reading, and check OpenGL error for INVALID_ENUM.
587 : *
588 : * On the public_webgl list, "problematic GetParameter pnames"
589 : * thread, the following formula was given:
590 : * maxVaryingVectors = min(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
591 : * GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4
592 : */
593 0 : GLint maxVertexOutputComponents = 0;
594 0 : GLint maxFragmentInputComponents = 0;
595 :
596 0 : const bool ok = (gl->GetPotentialInteger(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS,
597 0 : &maxVertexOutputComponents) &&
598 0 : gl->GetPotentialInteger(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS,
599 0 : &maxFragmentInputComponents));
600 :
601 0 : if (ok) {
602 0 : mGLMaxVaryingVectors = std::min(maxVertexOutputComponents,
603 0 : maxFragmentInputComponents) / 4;
604 : } else {
605 0 : mGLMaxVaryingVectors = 16;
606 : // 16 = 64/4, and 64 is the min value for
607 : // maxVertexOutputComponents in the OpenGL 3.2 spec.
608 : }
609 : }
610 : }
611 :
612 0 : if (gl->IsCompatibilityProfile()) {
613 0 : gl->fEnable(LOCAL_GL_POINT_SPRITE);
614 : }
615 :
616 0 : if (!gl->IsGLES()) {
617 0 : gl->fEnable(LOCAL_GL_PROGRAM_POINT_SIZE);
618 : }
619 :
620 : #ifdef XP_MACOSX
621 : if (gl->WorkAroundDriverBugs() &&
622 : gl->Vendor() == gl::GLVendor::ATI &&
623 : !nsCocoaFeatures::IsAtLeastVersion(10,9))
624 : {
625 : // The Mac ATI driver, in all known OSX version up to and including
626 : // 10.8, renders points sprites upside-down. (Apple bug 11778921)
627 : gl->fPointParameterf(LOCAL_GL_POINT_SPRITE_COORD_ORIGIN,
628 : LOCAL_GL_LOWER_LEFT);
629 : }
630 : #endif
631 :
632 0 : if (gl->IsSupported(gl::GLFeature::seamless_cube_map_opt_in)) {
633 0 : gl->fEnable(LOCAL_GL_TEXTURE_CUBE_MAP_SEAMLESS);
634 : }
635 :
636 : // Check the shader validator pref
637 0 : mBypassShaderValidation = gfxPrefs::WebGLBypassShaderValidator();
638 :
639 : // initialize shader translator
640 0 : if (!ShInitialize()) {
641 : *out_failReason = { "FEATURE_FAILURE_WEBGL_GLSL",
642 0 : "GLSL translator initialization failed!" };
643 0 : return false;
644 : }
645 :
646 : // Mesa can only be detected with the GL_VERSION string, of the form
647 : // "2.1 Mesa 7.11.0"
648 0 : const char* versionStr = (const char*)(gl->fGetString(LOCAL_GL_VERSION));
649 0 : mIsMesa = strstr(versionStr, "Mesa");
650 :
651 : // Notice that the point of calling fGetError here is not only to check for
652 : // errors, but also to reset the error flags so that a subsequent WebGL
653 : // getError call will give the correct result.
654 0 : error = gl->fGetError();
655 0 : if (error != LOCAL_GL_NO_ERROR) {
656 : const nsPrintfCString reason("GL error 0x%x occurred during WebGL context"
657 : " initialization!",
658 0 : error);
659 0 : *out_failReason = { "FEATURE_FAILURE_WEBGL_GLERR_2", reason };
660 0 : return false;
661 : }
662 :
663 0 : if (IsWebGL2() &&
664 0 : !InitWebGL2(out_failReason))
665 : {
666 : // Todo: Bug 898404: Only allow WebGL2 on GL>=3.0 on desktop GL.
667 0 : return false;
668 : }
669 :
670 0 : mDefaultVertexArray = WebGLVertexArray::Create(this);
671 0 : mDefaultVertexArray->mAttribs.SetLength(mGLMaxVertexAttribs);
672 0 : mBoundVertexArray = mDefaultVertexArray;
673 :
674 : // OpenGL core profiles remove the default VAO object from version
675 : // 4.0.0. We create a default VAO for all core profiles,
676 : // regardless of version.
677 : //
678 : // GL Spec 4.0.0:
679 : // (https://www.opengl.org/registry/doc/glspec40.core.20100311.pdf)
680 : // in Section E.2.2 "Removed Features", pg 397: "[...] The default
681 : // vertex array object (the name zero) is also deprecated. [...]"
682 :
683 0 : if (gl->IsCoreProfile()) {
684 0 : mDefaultVertexArray->GenVertexArray();
685 0 : mDefaultVertexArray->BindVertexArray();
686 : }
687 :
688 0 : mPixelStore_FlipY = false;
689 0 : mPixelStore_PremultiplyAlpha = false;
690 0 : mPixelStore_ColorspaceConversion = BROWSER_DEFAULT_WEBGL;
691 0 : mPixelStore_RequireFastPath = false;
692 :
693 : // GLES 3.0.4, p259:
694 0 : mPixelStore_UnpackImageHeight = 0;
695 0 : mPixelStore_UnpackSkipImages = 0;
696 0 : mPixelStore_UnpackRowLength = 0;
697 0 : mPixelStore_UnpackSkipRows = 0;
698 0 : mPixelStore_UnpackSkipPixels = 0;
699 0 : mPixelStore_UnpackAlignment = 4;
700 0 : mPixelStore_PackRowLength = 0;
701 0 : mPixelStore_PackSkipRows = 0;
702 0 : mPixelStore_PackSkipPixels = 0;
703 0 : mPixelStore_PackAlignment = 4;
704 :
705 0 : mPrimRestartTypeBytes = 0;
706 :
707 0 : mGenericVertexAttribTypes.reset(new GLenum[mGLMaxVertexAttribs]);
708 0 : std::fill_n(mGenericVertexAttribTypes.get(), mGLMaxVertexAttribs, LOCAL_GL_FLOAT);
709 :
710 : static const float kDefaultGenericVertexAttribData[4] = { 0, 0, 0, 1 };
711 0 : memcpy(mGenericVertexAttrib0Data, kDefaultGenericVertexAttribData,
712 0 : sizeof(mGenericVertexAttrib0Data));
713 :
714 0 : mFakeVertexAttrib0BufferObject = 0;
715 :
716 0 : mNeedsIndexValidation = !gl->IsSupported(gl::GLFeature::robust_buffer_access_behavior);
717 0 : if (gfxPrefs::WebGLForceIndexValidation()) {
718 0 : mNeedsIndexValidation = true;
719 : }
720 :
721 0 : return true;
722 : }
723 :
724 : bool
725 0 : WebGLContext::ValidateFramebufferTarget(GLenum target,
726 : const char* const info)
727 : {
728 0 : bool isValid = true;
729 0 : switch (target) {
730 : case LOCAL_GL_FRAMEBUFFER:
731 0 : break;
732 :
733 : case LOCAL_GL_DRAW_FRAMEBUFFER:
734 : case LOCAL_GL_READ_FRAMEBUFFER:
735 0 : isValid = IsWebGL2();
736 0 : break;
737 :
738 : default:
739 0 : isValid = false;
740 0 : break;
741 : }
742 :
743 0 : if (MOZ_LIKELY(isValid)) {
744 0 : return true;
745 : }
746 :
747 0 : ErrorInvalidEnumArg(info, "target", target);
748 0 : return false;
749 : }
750 :
751 : } // namespace mozilla
|