void WebGLProgram::GetActiveUniformBlockParam(GLuint uniformBlockIndex, GLenum pname, dom::Nullable<dom::OwningUnsignedLongOrUint32ArrayOrBoolean>& retval) const { retval.SetNull(); if (!IsLinked()) { mContext->ErrorInvalidOperation("getActiveUniformBlockParameter: `program` must be linked."); return; } const webgl::LinkedProgramInfo* linkInfo = LinkInfo(); GLuint uniformBlockCount = (GLuint)linkInfo->uniformBlocks.size(); if (uniformBlockIndex >= uniformBlockCount) { mContext->ErrorInvalidValue("getActiveUniformBlockParameter: index %u invalid.", uniformBlockIndex); return; } gl::GLContext* gl = mContext->GL(); GLint param = 0; switch (pname) { case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: gl->fGetActiveUniformBlockiv(mGLName, uniformBlockIndex, pname, ¶m); retval.SetValue().SetAsBoolean() = (param != 0); return; case LOCAL_GL_UNIFORM_BLOCK_BINDING: case LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE: case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: gl->fGetActiveUniformBlockiv(mGLName, uniformBlockIndex, pname, ¶m); retval.SetValue().SetAsUnsignedLong() = param; return; } }
void WebGLContext::GetSupportedExtensions(JSContext* cx, dom::Nullable< nsTArray<nsString> >& retval) { retval.SetNull(); if (IsContextLost()) return; nsTArray<nsString>& arr = retval.SetValue(); for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++) { WebGLExtensionID extension = WebGLExtensionID(i); if (IsExtensionSupported(cx, extension)) { const char* extStr = GetExtensionString(extension); arr.AppendElement(NS_ConvertUTF8toUTF16(extStr)); } } /** * We keep backward compatibility for these deprecated vendor-prefixed * alias. Do not add new ones anymore. Hide it behind the * webgl.enable-draft-extensions flag instead. */ if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_lose_context)) arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context")); if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_s3tc)) arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc")); if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_atc)) arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc")); if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_pvrtc)) arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc")); if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_depth_texture)) arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture")); }
void WebGL2Context::GetActiveUniforms(WebGLProgram* program, const dom::Sequence<GLuint>& uniformIndices, GLenum pname, dom::Nullable< nsTArray<GLint> >& retval) { retval.SetNull(); if (IsContextLost()) return; if (pname == LOCAL_GL_UNIFORM_NAME_LENGTH) { ErrorInvalidEnumInfo("getActiveUniforms: pname", pname); return; } if (!ValidateObject("getActiveUniforms: program", program)) return; size_t count = uniformIndices.Length(); if (!count) return; GLuint progname = program->mGLName; nsTArray<GLint>& arr = retval.SetValue(); arr.SetLength(count); MakeContextCurrent(); gl->fGetActiveUniformsiv(progname, count, uniformIndices.Elements(), pname, arr.Elements()); }
void WebGL2Context::GetUniformIndices(WebGLProgram* program, const dom::Sequence<nsString>& uniformNames, dom::Nullable< nsTArray<GLuint> >& retval) { retval.SetNull(); if (IsContextLost()) return; if (!ValidateObject("getUniformIndices: program", program)) return; if (!uniformNames.Length()) return; GLuint progname = program->mGLName; size_t count = uniformNames.Length(); nsTArray<GLuint>& arr = retval.SetValue(); MakeContextCurrent(); for (size_t n = 0; n < count; n++) { NS_LossyConvertUTF16toASCII name(uniformNames[n]); // const GLchar* glname = name.get(); const GLchar* glname = nullptr; name.BeginReading(glname); GLuint index = 0; gl->fGetUniformIndices(progname, 1, &glname, &index); arr.AppendElement(index); } }
/* This doesn't belong here. It's part of state querying */ void WebGL2Context::GetIndexedParameter(GLenum target, GLuint index, dom::Nullable<dom::OwningWebGLBufferOrLongLong>& retval) { retval.SetNull(); if (IsContextLost()) return; GLint64 data = 0; MakeContextCurrent(); switch (target) { case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: if (index >= mGLMaxTransformFeedbackSeparateAttribs) return ErrorInvalidValue("getIndexedParameter: index should be less than " "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS"); retval.SetValue().SetAsWebGLBuffer() = mBoundTransformFeedbackBuffers[index].get(); return; case LOCAL_GL_UNIFORM_BUFFER_BINDING: if (index >= mGLMaxUniformBufferBindings) return ErrorInvalidValue("getIndexedParameter: index should be than " "MAX_UNIFORM_BUFFER_BINDINGS"); retval.SetValue().SetAsWebGLBuffer() = mBoundUniformBuffers[index].get(); return; case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_START: case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: case LOCAL_GL_UNIFORM_BUFFER_START: case LOCAL_GL_UNIFORM_BUFFER_SIZE: gl->fGetInteger64i_v(target, index, &data); retval.SetValue().SetAsLongLong() = data; return; } ErrorInvalidEnumInfo("getIndexedParameter: target", target); }
void WebGLProgram::GetUniformIndices(const dom::Sequence<nsString>& uniformNames, dom::Nullable< nsTArray<GLuint> >& retval) const { const char funcName[] = "getUniformIndices"; if (!IsLinked()) { mContext->ErrorInvalidOperation("%s: `program` must be linked.", funcName); return; } size_t count = uniformNames.Length(); nsTArray<GLuint>& arr = retval.SetValue(); gl::GLContext* gl = mContext->GL(); gl->MakeCurrent(); for (size_t i = 0; i < count; i++) { const NS_LossyConvertUTF16toASCII userName(uniformNames[i]); nsDependentCString baseUserName; bool isArray; size_t arrayIndex; if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex)) { arr.AppendElement(LOCAL_GL_INVALID_INDEX); continue; } webgl::UniformInfo* info; if (!LinkInfo()->FindUniform(baseUserName, &info)) { arr.AppendElement(LOCAL_GL_INVALID_INDEX); continue; } nsAutoCString mappedName(info->mActiveInfo->mBaseMappedName); if (isArray) { mappedName.AppendLiteral("["); mappedName.AppendInt(uint32_t(arrayIndex)); mappedName.AppendLiteral("]"); } const GLchar* mappedNameBytes = mappedName.BeginReading(); GLuint index = 0; gl->fGetUniformIndices(mGLName, 1, &mappedNameBytes, &index); arr.AppendElement(index); } }
void DominatorTree::GetImmediatelyDominated(uint64_t aNodeId, dom::Nullable<nsTArray<uint64_t>>& aOutResult, ErrorResult& aRv) { MOZ_ASSERT(aOutResult.IsNull()); JS::ubi::Node::Id id(aNodeId); Maybe<JS::ubi::Node> node = mHeapSnapshot->getNodeById(id); if (node.isNothing()) return; // Get all immediately dominated nodes and their retained sizes. MallocSizeOf mallocSizeOf = getCurrentThreadDebuggerMallocSizeOf(); Maybe<JS::ubi::DominatorTree::DominatedSetRange> range = mDominatorTree.getDominatedSet(*node); MOZ_ASSERT(range.isSome(), "The node should be known, since we got it from the heap snapshot."); size_t length = range->length(); nsTArray<NodeAndRetainedSize> dominatedNodes(length); for (const JS::ubi::Node& dominatedNode : *range) { JS::ubi::Node::Size retainedSize = 0; if (NS_WARN_IF(!mDominatorTree.getRetainedSize(dominatedNode, mallocSizeOf, retainedSize))) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } MOZ_ASSERT(retainedSize != 0, "retainedSize should not be zero since we know the node is in the dominator tree."); dominatedNodes.AppendElement(NodeAndRetainedSize(dominatedNode, retainedSize)); } // Sort them by retained size. NodeAndRetainedSize::Comparator comparator; dominatedNodes.Sort(comparator); // Fill the result with the nodes' ids. JS::ubi::Node root = mDominatorTree.root(); aOutResult.SetValue(nsTArray<uint64_t>(length)); for (const NodeAndRetainedSize& entry : dominatedNodes) { // The root dominates itself, but we don't want to expose that to JS. if (entry.mNode == root) continue; aOutResult.Value().AppendElement(entry.mNode.identifier()); } }
void WebGLContext::GetSupportedExtensions(dom::Nullable< nsTArray<nsString> >& retval, dom::CallerType callerType) { retval.SetNull(); if (IsContextLost()) return; nsTArray<nsString>& arr = retval.SetValue(); for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++) { const auto extension = WebGLExtensionID(i); if (extension == WebGLExtensionID::MOZ_debug) continue; // Hide MOZ_debug from this list. if (IsExtensionSupported(callerType, extension)) { const char* extStr = GetExtensionString(extension); arr.AppendElement(NS_ConvertUTF8toUTF16(extStr)); } } }
void WebGLProgram::GetActiveUniformBlockActiveUniforms(JSContext* cx, GLuint uniformBlockIndex, dom::Nullable<dom::OwningUnsignedLongOrUint32ArrayOrBoolean>& retval, ErrorResult& rv) const { if (!IsLinked()) { mContext->ErrorInvalidOperation("getActiveUniformBlockParameter: `program` must be linked."); return; } const webgl::LinkedProgramInfo* linkInfo = LinkInfo(); GLuint uniformBlockCount = (GLuint)linkInfo->uniformBlocks.size(); if (uniformBlockIndex >= uniformBlockCount) { mContext->ErrorInvalidValue("getActiveUniformBlockParameter: index %u invalid.", uniformBlockIndex); return; } gl::GLContext* gl = mContext->GL(); GLint activeUniformCount = 0; gl->fGetActiveUniformBlockiv(mGLName, uniformBlockIndex, LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &activeUniformCount); JS::RootedObject obj(cx, dom::Uint32Array::Create(cx, mContext, activeUniformCount, nullptr)); if (!obj) { rv = NS_ERROR_OUT_OF_MEMORY; return; } dom::Uint32Array result; DebugOnly<bool> inited = result.Init(obj); MOZ_ASSERT(inited); result.ComputeLengthAndData(); gl->fGetActiveUniformBlockiv(mGLName, uniformBlockIndex, LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, (GLint*)result.Data()); inited = retval.SetValue().SetAsUint32Array().Init(obj); MOZ_ASSERT(inited); }