/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebGLContext.h" #include #include "GLSLANG/ShaderLang.h" #include "CanvasUtils.h" #include "gfxPrefs.h" #include "GLContext.h" #include "jsfriendapi.h" #include "mozilla/CheckedInt.h" #include "mozilla/Preferences.h" #include "nsIObserverService.h" #include "nsPrintfCString.h" #include "WebGLActiveInfo.h" #include "WebGLBuffer.h" #include "WebGLContextUtils.h" #include "WebGLFramebuffer.h" #include "WebGLProgram.h" #include "WebGLRenderbuffer.h" #include "WebGLSampler.h" #include "WebGLShader.h" #include "WebGLTexture.h" #include "WebGLUniformLocation.h" #include "WebGLValidateStrings.h" #include "WebGLVertexArray.h" #include "WebGLVertexAttribData.h" #if defined(MOZ_WIDGET_COCOA) # include "nsCocoaFeatures.h" #endif //////////////////// // Minimum value constants defined in GLES 2.0.25 $6.2 "State Tables": const uint32_t kMinMaxVertexAttribs = 8; // Page 164 const uint32_t kMinMaxVertexUniformVectors = 128; // Page 164 const uint32_t kMinMaxFragmentUniformVectors = 16; // Page 164 const uint32_t kMinMaxVaryingVectors = 8; // Page 164 const uint32_t kMinMaxVertexTextureImageUnits = 0; // Page 164 const uint32_t kMinMaxFragmentTextureImageUnits = 8; // Page 164 const uint32_t kMinMaxCombinedTextureImageUnits = 8; // Page 164 const uint32_t kMinMaxColorAttachments = 4; const uint32_t kMinMaxDrawBuffers = 4; // These few deviate from the spec: (The minimum values in the spec are // ridiculously low) const uint32_t kMinMaxTextureSize = 1024; // ES2 spec says `64` (p162) const uint32_t kMinMaxCubeMapTextureSize = 512; // ES2 spec says `16` (p162) const uint32_t kMinMaxRenderbufferSize = 1024; // ES2 spec says `1` (p164) // Minimum value constants defined in GLES 3.0.4 $6.2 "State Tables": const uint32_t kMinMax3DTextureSize = 256; const uint32_t kMinMaxArrayTextureLayers = 256; //////////////////// // "Common" but usable values to avoid WebGL fingerprinting: const uint32_t kCommonMaxTextureSize = 2048; const uint32_t kCommonMaxCubeMapTextureSize = 2048; const uint32_t kCommonMaxRenderbufferSize = 2048; const uint32_t kCommonMaxVertexTextureImageUnits = 8; const uint32_t kCommonMaxFragmentTextureImageUnits = 8; const uint32_t kCommonMaxCombinedTextureImageUnits = 16; const uint32_t kCommonMaxVertexAttribs = 16; const uint32_t kCommonMaxVertexUniformVectors = 256; const uint32_t kCommonMaxFragmentUniformVectors = 224; const uint32_t kCommonMaxVaryingVectors = 8; const uint32_t kCommonMaxViewportDims = 4096; // The following ranges came from a 2013 Moto E and an old macbook. const float kCommonAliasedPointSizeRangeMin = 1; const float kCommonAliasedPointSizeRangeMax = 63; const float kCommonAliasedLineWidthRangeMin = 1; const float kCommonAliasedLineWidthRangeMax = 1; template static bool RestrictCap(T* const cap, const T restrictedVal) { if (*cap < restrictedVal) { return false; // already too low! } *cap = restrictedVal; return true; } //////////////////// namespace mozilla { bool WebGLContext::ValidateBlendEquationEnum(GLenum mode, const char* info) { switch (mode) { case LOCAL_GL_FUNC_ADD: case LOCAL_GL_FUNC_SUBTRACT: case LOCAL_GL_FUNC_REVERSE_SUBTRACT: return true; case LOCAL_GL_MIN: case LOCAL_GL_MAX: if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::EXT_blend_minmax)) { return true; } break; default: break; } ErrorInvalidEnumInfo(info, mode); return false; } bool WebGLContext::ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor, const char* info) { bool sfactorIsConstantColor = sfactor == LOCAL_GL_CONSTANT_COLOR || sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR; bool sfactorIsConstantAlpha = sfactor == LOCAL_GL_CONSTANT_ALPHA || sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA; bool dfactorIsConstantColor = dfactor == LOCAL_GL_CONSTANT_COLOR || dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR; bool dfactorIsConstantAlpha = dfactor == LOCAL_GL_CONSTANT_ALPHA || dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA; if ((sfactorIsConstantColor && dfactorIsConstantAlpha) || (dfactorIsConstantColor && sfactorIsConstantAlpha)) { ErrorInvalidOperation( "%s are mutually incompatible, see section 6.8 in" " the WebGL 1.0 spec", info); return false; } return true; } bool WebGLContext::ValidateStencilOpEnum(GLenum action, const char* info) { switch (action) { case LOCAL_GL_KEEP: case LOCAL_GL_ZERO: case LOCAL_GL_REPLACE: case LOCAL_GL_INCR: case LOCAL_GL_INCR_WRAP: case LOCAL_GL_DECR: case LOCAL_GL_DECR_WRAP: case LOCAL_GL_INVERT: return true; default: ErrorInvalidEnumInfo(info, action); return false; } } bool WebGLContext::ValidateFaceEnum(const GLenum face) { switch (face) { case LOCAL_GL_FRONT: case LOCAL_GL_BACK: case LOCAL_GL_FRONT_AND_BACK: return true; default: ErrorInvalidEnumInfo("face", face); return false; } } bool WebGLContext::ValidateUniformLocation( const WebGLUniformLocation* const loc) { /* GLES 2.0.25, p38: * If the value of location is -1, the Uniform* commands will silently * ignore the data passed in, and the current uniform values will not be * changed. */ if (!loc) return false; if (!ValidateObjectAllowDeleted("loc", *loc)) return false; if (!mCurrentProgram) { ErrorInvalidOperation("No program is currently bound."); return false; } return loc->ValidateForProgram(mCurrentProgram); } bool WebGLContext::ValidateAttribArraySetter(uint32_t setterElemSize, uint32_t arrayLength) { if (IsContextLost()) return false; if (arrayLength < setterElemSize) { ErrorInvalidValue("Array must have >= %d elements.", setterElemSize); return false; } return true; } bool WebGLContext::ValidateUniformSetter( const WebGLUniformLocation* const loc, const uint8_t setterElemSize, const webgl::AttribBaseType setterType) { if (IsContextLost()) return false; if (!ValidateUniformLocation(loc)) return false; if (!loc->ValidateSizeAndType(setterElemSize, setterType)) return false; return true; } bool WebGLContext::ValidateUniformArraySetter( const WebGLUniformLocation* const loc, const uint8_t setterElemSize, const webgl::AttribBaseType setterType, const uint32_t setterArraySize, uint32_t* const out_numElementsToUpload) { if (IsContextLost()) return false; if (!ValidateUniformLocation(loc)) return false; if (!loc->ValidateSizeAndType(setterElemSize, setterType)) return false; if (!loc->ValidateArrayLength(setterElemSize, setterArraySize)) return false; const auto& elemCount = loc->mInfo->mActiveInfo->mElemCount; MOZ_ASSERT(elemCount > loc->mArrayIndex); const uint32_t uniformElemCount = elemCount - loc->mArrayIndex; *out_numElementsToUpload = std::min(uniformElemCount, setterArraySize / setterElemSize); return true; } bool WebGLContext::ValidateUniformMatrixArraySetter( const WebGLUniformLocation* const loc, const uint8_t setterCols, const uint8_t setterRows, const webgl::AttribBaseType setterType, const uint32_t setterArraySize, const bool setterTranspose, uint32_t* const out_numElementsToUpload) { const uint8_t setterElemSize = setterCols * setterRows; if (IsContextLost()) return false; if (!ValidateUniformLocation(loc)) return false; if (!loc->ValidateSizeAndType(setterElemSize, setterType)) return false; if (!loc->ValidateArrayLength(setterElemSize, setterArraySize)) return false; if (setterTranspose && !IsWebGL2()) { ErrorInvalidValue("`transpose` must be false."); return false; } const auto& elemCount = loc->mInfo->mActiveInfo->mElemCount; MOZ_ASSERT(elemCount > loc->mArrayIndex); const uint32_t uniformElemCount = elemCount - loc->mArrayIndex; *out_numElementsToUpload = std::min(uniformElemCount, setterArraySize / setterElemSize); return true; } bool WebGLContext::InitAndValidateGL(FailureReason* const out_failReason) { MOZ_RELEASE_ASSERT(gl, "GFX: GL not initialized"); // Unconditionally create a new format usage authority. This is // important when restoring contexts and extensions need to add // formats back into the authority. mFormatUsage = CreateFormatUsage(gl); if (!mFormatUsage) { *out_failReason = {"FEATURE_FAILURE_WEBGL_FORMAT", "Failed to create mFormatUsage."}; return false; } GLenum error = gl->fGetError(); if (error != LOCAL_GL_NO_ERROR) { const nsPrintfCString reason( "GL error 0x%x occurred during OpenGL context" " initialization, before WebGL initialization!", error); *out_failReason = {"FEATURE_FAILURE_WEBGL_GLERR_1", reason}; return false; } mDisableExtensions = gfxPrefs::WebGLDisableExtensions(); mLoseContextOnMemoryPressure = gfxPrefs::WebGLLoseContextOnMemoryPressure(); mCanLoseContextInForeground = gfxPrefs::WebGLCanLoseContextInForeground(); // These are the default values, see 6.2 State tables in the // OpenGL ES 2.0.25 spec. mColorWriteMask = 0x0f; mDriverColorMask = mColorWriteMask; mColorClearValue[0] = 0.f; mColorClearValue[1] = 0.f; mColorClearValue[2] = 0.f; mColorClearValue[3] = 0.f; mDepthWriteMask = true; mDepthClearValue = 1.f; mStencilClearValue = 0; mStencilRefFront = 0; mStencilRefBack = 0; mLineWidth = 1.0; /* // Technically, we should be setting mStencil[...] values to // `allOnes`, but either ANGLE breaks or the SGX540s on Try break. GLuint stencilBits = 0; gl->GetUIntegerv(LOCAL_GL_STENCIL_BITS, &stencilBits); GLuint allOnes = ~(UINT32_MAX << stencilBits); mStencilValueMaskFront = allOnes; mStencilValueMaskBack = allOnes; mStencilWriteMaskFront = allOnes; mStencilWriteMaskBack = allOnes; */ gl->GetUIntegerv(LOCAL_GL_STENCIL_VALUE_MASK, &mStencilValueMaskFront); gl->GetUIntegerv(LOCAL_GL_STENCIL_BACK_VALUE_MASK, &mStencilValueMaskBack); gl->GetUIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &mStencilWriteMaskFront); gl->GetUIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &mStencilWriteMaskBack); AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_VALUE_MASK, mStencilValueMaskFront); AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_VALUE_MASK, mStencilValueMaskBack); AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_WRITEMASK, mStencilWriteMaskFront); AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_WRITEMASK, mStencilWriteMaskBack); mDitherEnabled = true; mRasterizerDiscardEnabled = false; mScissorTestEnabled = false; mDepthTestEnabled = 0; mDriverDepthTest = false; mStencilTestEnabled = 0; mDriverStencilTest = false; mGenerateMipmapHint = LOCAL_GL_DONT_CARE; // Bindings, etc. mActiveTexture = 0; mDefaultFB_DrawBuffer0 = LOCAL_GL_BACK; mDefaultFB_ReadBuffer = LOCAL_GL_BACK; mWebGLError = LOCAL_GL_NO_ERROR; mBound2DTextures.Clear(); mBoundCubeMapTextures.Clear(); mBound3DTextures.Clear(); mBound2DArrayTextures.Clear(); mBoundSamplers.Clear(); mBoundArrayBuffer = nullptr; mCurrentProgram = nullptr; mBoundDrawFramebuffer = nullptr; mBoundReadFramebuffer = nullptr; mBoundRenderbuffer = nullptr; gl->GetUIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs); if (mGLMaxVertexAttribs < 8) { const nsPrintfCString reason("GL_MAX_VERTEX_ATTRIBS: %d is < 8!", mGLMaxVertexAttribs); *out_failReason = {"FEATURE_FAILURE_WEBGL_V_ATRB", reason}; return false; } // Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware, // even though the hardware supports much more. The // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value. mGLMaxCombinedTextureImageUnits = gl->GetIntAs(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS); mGLMaxTextureUnits = mGLMaxCombinedTextureImageUnits; if (mGLMaxCombinedTextureImageUnits < 8) { const nsPrintfCString reason( "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %u is < 8!", mGLMaxTextureUnits); *out_failReason = {"FEATURE_FAILURE_WEBGL_T_UNIT", reason}; return false; } mBound2DTextures.SetLength(mGLMaxTextureUnits); mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits); mBound3DTextures.SetLength(mGLMaxTextureUnits); mBound2DArrayTextures.SetLength(mGLMaxTextureUnits); mBoundSamplers.SetLength(mGLMaxTextureUnits); gl->fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS, (GLint*)mGLMaxViewportDims); //////////////// gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, (GLint*)&mGLMaxTextureSize); gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&mGLMaxCubeMapTextureSize); gl->fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, (GLint*)&mGLMaxRenderbufferSize); if (!gl->GetPotentialInteger(LOCAL_GL_MAX_3D_TEXTURE_SIZE, (GLint*)&mGLMax3DTextureSize)) mGLMax3DTextureSize = 0; if (!gl->GetPotentialInteger(LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS, (GLint*)&mGLMaxArrayTextureLayers)) mGLMaxArrayTextureLayers = 0; gl->GetUIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxFragmentTextureImageUnits); gl->GetUIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits); //////////////// mGLMaxColorAttachments = 1; mGLMaxDrawBuffers = 1; if (IsWebGL2()) { UpdateMaxDrawBuffers(); } //////////////// if (gl->IsGLES()) { mGLMaxFragmentUniformVectors = gl->GetIntAs(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS); mGLMaxVertexUniformVectors = gl->GetIntAs(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS); if (gl->Version() >= 300) { mGLMaxVertexOutputVectors = gl->GetIntAs(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS) / 4; mGLMaxFragmentInputVectors = gl->GetIntAs(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4; } else { mGLMaxFragmentInputVectors = gl->GetIntAs(LOCAL_GL_MAX_VARYING_VECTORS); mGLMaxVertexOutputVectors = mGLMaxFragmentInputVectors; } } else { mGLMaxFragmentUniformVectors = gl->GetIntAs(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS) / 4; mGLMaxVertexUniformVectors = gl->GetIntAs(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS) / 4; if (gl->Version() >= 320) { mGLMaxVertexOutputVectors = gl->GetIntAs(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS) / 4; mGLMaxFragmentInputVectors = gl->GetIntAs(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4; } else { // Same enum val as GL2's GL_MAX_VARYING_FLOATS. mGLMaxFragmentInputVectors = gl->GetIntAs(LOCAL_GL_MAX_VARYING_COMPONENTS) / 4; mGLMaxVertexOutputVectors = mGLMaxFragmentInputVectors; } } //////////////// gl->fGetFloatv(LOCAL_GL_ALIASED_LINE_WIDTH_RANGE, mGLAliasedLineWidthRange); const GLenum driverPName = gl->IsCoreProfile() ? LOCAL_GL_POINT_SIZE_RANGE : LOCAL_GL_ALIASED_POINT_SIZE_RANGE; gl->fGetFloatv(driverPName, mGLAliasedPointSizeRange); //////////////// if (gfxPrefs::WebGLMinCapabilityMode()) { bool ok = true; ok &= RestrictCap(&mGLMaxVertexTextureImageUnits, kMinMaxVertexTextureImageUnits); ok &= RestrictCap(&mGLMaxFragmentTextureImageUnits, kMinMaxFragmentTextureImageUnits); ok &= RestrictCap(&mGLMaxCombinedTextureImageUnits, kMinMaxCombinedTextureImageUnits); ok &= RestrictCap(&mGLMaxVertexAttribs, kMinMaxVertexAttribs); ok &= RestrictCap(&mGLMaxVertexUniformVectors, kMinMaxVertexUniformVectors); ok &= RestrictCap(&mGLMaxFragmentUniformVectors, kMinMaxFragmentUniformVectors); ok &= RestrictCap(&mGLMaxVertexOutputVectors, kMinMaxVaryingVectors); ok &= RestrictCap(&mGLMaxFragmentInputVectors, kMinMaxVaryingVectors); ok &= RestrictCap(&mGLMaxColorAttachments, kMinMaxColorAttachments); ok &= RestrictCap(&mGLMaxDrawBuffers, kMinMaxDrawBuffers); ok &= RestrictCap(&mGLMaxTextureSize, kMinMaxTextureSize); ok &= RestrictCap(&mGLMaxCubeMapTextureSize, kMinMaxCubeMapTextureSize); ok &= RestrictCap(&mGLMax3DTextureSize, kMinMax3DTextureSize); ok &= RestrictCap(&mGLMaxArrayTextureLayers, kMinMaxArrayTextureLayers); ok &= RestrictCap(&mGLMaxRenderbufferSize, kMinMaxRenderbufferSize); if (!ok) { GenerateWarning("Unable to restrict WebGL limits to minimums."); return false; } mDisableFragHighP = true; } else if (nsContentUtils::ShouldResistFingerprinting()) { bool ok = true; ok &= RestrictCap(&mGLMaxTextureSize, kCommonMaxTextureSize); ok &= RestrictCap(&mGLMaxCubeMapTextureSize, kCommonMaxCubeMapTextureSize); ok &= RestrictCap(&mGLMaxRenderbufferSize, kCommonMaxRenderbufferSize); ok &= RestrictCap(&mGLMaxVertexTextureImageUnits, kCommonMaxVertexTextureImageUnits); ok &= RestrictCap(&mGLMaxFragmentTextureImageUnits, kCommonMaxFragmentTextureImageUnits); ok &= RestrictCap(&mGLMaxCombinedTextureImageUnits, kCommonMaxCombinedTextureImageUnits); ok &= RestrictCap(&mGLMaxVertexAttribs, kCommonMaxVertexAttribs); ok &= RestrictCap(&mGLMaxVertexUniformVectors, kCommonMaxVertexUniformVectors); ok &= RestrictCap(&mGLMaxFragmentUniformVectors, kCommonMaxFragmentUniformVectors); ok &= RestrictCap(&mGLMaxVertexOutputVectors, kCommonMaxVaryingVectors); ok &= RestrictCap(&mGLMaxFragmentInputVectors, kCommonMaxVaryingVectors); ok &= RestrictCap(&mGLAliasedLineWidthRange[0], kCommonAliasedLineWidthRangeMin); ok &= RestrictCap(&mGLAliasedLineWidthRange[1], kCommonAliasedLineWidthRangeMax); ok &= RestrictCap(&mGLAliasedPointSizeRange[0], kCommonAliasedPointSizeRangeMin); ok &= RestrictCap(&mGLAliasedPointSizeRange[1], kCommonAliasedPointSizeRangeMax); ok &= RestrictCap(&mGLMaxViewportDims[0], kCommonMaxViewportDims); ok &= RestrictCap(&mGLMaxViewportDims[1], kCommonMaxViewportDims); if (!ok) { GenerateWarning( "Unable to restrict WebGL limits in order to resist fingerprinting"); return false; } } //////////////// if (gl->IsCompatibilityProfile()) { gl->fEnable(LOCAL_GL_POINT_SPRITE); } if (!gl->IsGLES()) { gl->fEnable(LOCAL_GL_PROGRAM_POINT_SIZE); } #ifdef XP_MACOSX if (gl->WorkAroundDriverBugs() && gl->Vendor() == gl::GLVendor::ATI && !nsCocoaFeatures::IsAtLeastVersion(10, 9)) { // The Mac ATI driver, in all known OSX version up to and including // 10.8, renders points sprites upside-down. (Apple bug 11778921) gl->fPointParameterf(LOCAL_GL_POINT_SPRITE_COORD_ORIGIN, LOCAL_GL_LOWER_LEFT); } #endif if (gl->IsSupported(gl::GLFeature::seamless_cube_map_opt_in)) { gl->fEnable(LOCAL_GL_TEXTURE_CUBE_MAP_SEAMLESS); } // Check the shader validator pref mBypassShaderValidation = gfxPrefs::WebGLBypassShaderValidator(); // initialize shader translator if (!sh::Initialize()) { *out_failReason = {"FEATURE_FAILURE_WEBGL_GLSL", "GLSL translator initialization failed!"}; return false; } // Mesa can only be detected with the GL_VERSION string, of the form // "2.1 Mesa 7.11.0" const char* versionStr = (const char*)(gl->fGetString(LOCAL_GL_VERSION)); mIsMesa = strstr(versionStr, "Mesa"); // Notice that the point of calling fGetError here is not only to check for // errors, but also to reset the error flags so that a subsequent WebGL // getError call will give the correct result. error = gl->fGetError(); if (error != LOCAL_GL_NO_ERROR) { const nsPrintfCString reason( "GL error 0x%x occurred during WebGL context" " initialization!", error); *out_failReason = {"FEATURE_FAILURE_WEBGL_GLERR_2", reason}; return false; } if (IsWebGL2() && !InitWebGL2(out_failReason)) { // Todo: Bug 898404: Only allow WebGL2 on GL>=3.0 on desktop GL. return false; } if (!gl->IsSupported(GLFeature::vertex_array_object)) { *out_failReason = {"FEATURE_FAILURE_WEBGL_VAOS", "Requires vertex_array_object."}; return false; } // OpenGL core profiles remove the default VAO object from version // 4.0.0. We create a default VAO for all core profiles, // regardless of version. // // GL Spec 4.0.0: // (https://www.opengl.org/registry/doc/glspec40.core.20100311.pdf) // in Section E.2.2 "Removed Features", pg 397: "[...] The default // vertex array object (the name zero) is also deprecated. [...]" mDefaultVertexArray = WebGLVertexArray::Create(this); mDefaultVertexArray->BindVertexArray(); mDefaultVertexArray->mAttribs.SetLength(mGLMaxVertexAttribs); mPixelStore_FlipY = false; mPixelStore_PremultiplyAlpha = false; mPixelStore_ColorspaceConversion = BROWSER_DEFAULT_WEBGL; mPixelStore_RequireFastPath = false; // GLES 3.0.4, p259: mPixelStore_UnpackImageHeight = 0; mPixelStore_UnpackSkipImages = 0; mPixelStore_UnpackRowLength = 0; mPixelStore_UnpackSkipRows = 0; mPixelStore_UnpackSkipPixels = 0; mPixelStore_UnpackAlignment = 4; mPixelStore_PackRowLength = 0; mPixelStore_PackSkipRows = 0; mPixelStore_PackSkipPixels = 0; mPixelStore_PackAlignment = 4; mPrimRestartTypeBytes = 0; mGenericVertexAttribTypes.assign(mGLMaxVertexAttribs, webgl::AttribBaseType::Float); mGenericVertexAttribTypeInvalidator.InvalidateCaches(); static const float kDefaultGenericVertexAttribData[4] = {0, 0, 0, 1}; memcpy(mGenericVertexAttrib0Data, kDefaultGenericVertexAttribData, sizeof(mGenericVertexAttrib0Data)); mFakeVertexAttrib0BufferObject = 0; mNeedsIndexValidation = !gl->IsSupported(gl::GLFeature::robust_buffer_access_behavior); switch (gfxPrefs::WebGLForceIndexValidation()) { case -1: mNeedsIndexValidation = false; break; case 1: mNeedsIndexValidation = true; break; default: MOZ_ASSERT(gfxPrefs::WebGLForceIndexValidation() == 0); break; } return true; } bool WebGLContext::ValidateFramebufferTarget(GLenum target) { bool isValid = true; switch (target) { case LOCAL_GL_FRAMEBUFFER: break; case LOCAL_GL_DRAW_FRAMEBUFFER: case LOCAL_GL_READ_FRAMEBUFFER: isValid = IsWebGL2(); break; default: isValid = false; break; } if (MOZ_LIKELY(isValid)) { return true; } ErrorInvalidEnumArg("target", target); return false; } } // namespace mozilla