/* -*- Mode: C++; tab-width: 4; 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/. */ #ifndef WEBGL_PROGRAM_H_ #define WEBGL_PROGRAM_H_ #include #include #include #include #include "mozilla/LinkedList.h" #include "mozilla/RefPtr.h" #include "mozilla/WeakPtr.h" #include "nsString.h" #include "nsWrapperCache.h" #include "CacheInvalidator.h" #include "WebGLContext.h" #include "WebGLObjectModel.h" namespace mozilla { class ErrorResult; class WebGLActiveInfo; class WebGLProgram; class WebGLShader; class WebGLUniformLocation; namespace dom { template struct Nullable; class OwningUnsignedLongOrUint32ArrayOrBoolean; template class Sequence; } // namespace dom namespace webgl { enum class TextureBaseType : uint8_t; struct AttribInfo final { const RefPtr mActiveInfo; const GLint mLoc; // -1 for active built-ins }; struct UniformInfo final { typedef decltype(WebGLContext::mBound2DTextures) TexListT; const RefPtr mActiveInfo; const TexListT* const mSamplerTexList; const webgl::TextureBaseType mTexBaseType; const bool mIsShadowSampler; std::vector mSamplerValues; protected: static const TexListT* GetTexList(WebGLActiveInfo* activeInfo); public: explicit UniformInfo(WebGLActiveInfo* activeInfo); }; struct UniformBlockInfo final { const nsCString mUserName; const nsCString mMappedName; const uint32_t mDataSize; const IndexedBufferBinding* mBinding; UniformBlockInfo(WebGLContext* webgl, const nsACString& userName, const nsACString& mappedName, uint32_t dataSize) : mUserName(userName), mMappedName(mappedName), mDataSize(dataSize), mBinding(&webgl->mIndexedUniformBufferBindings[0]) {} }; struct FragOutputInfo final { const uint8_t loc; const nsCString userName; const nsCString mappedName; const TextureBaseType baseType; }; struct CachedDrawFetchLimits final { uint64_t maxVerts; uint64_t maxInstances; }; struct LinkedProgramInfo final : public RefCounted, public SupportsWeakPtr, public CacheInvalidator { friend class mozilla::WebGLProgram; MOZ_DECLARE_REFCOUNTED_TYPENAME(LinkedProgramInfo) MOZ_DECLARE_WEAKREFERENCE_TYPENAME(LinkedProgramInfo) ////// WebGLProgram* const prog; const GLenum transformFeedbackBufferMode; std::vector attribs; std::vector uniforms; // Owns its contents. std::vector uniformBlocks; // Owns its contents. std::vector> transformFeedbackVaryings; std::unordered_map fragOutputs; // Needed for draw call validation. std::vector uniformSamplers; mutable std::vector componentsPerTFVert; bool attrib0Active; ////// mutable CacheWeakMap mDrawFetchCache; const CachedDrawFetchLimits* GetDrawFetchLimits() const; ////// explicit LinkedProgramInfo(WebGLProgram* prog); ~LinkedProgramInfo(); bool FindAttrib(const nsCString& userName, const AttribInfo** const out_info) const; bool FindUniform(const nsCString& userName, nsCString* const out_mappedName, size_t* const out_arrayIndex, UniformInfo** const out_info) const; }; } // namespace webgl class WebGLProgram final : public nsWrapperCache, public WebGLRefCountedObject, public LinkedListElement { friend class WebGLTransformFeedback; friend struct webgl::LinkedProgramInfo; public: NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLProgram) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLProgram) explicit WebGLProgram(WebGLContext* webgl); void Delete(); // GL funcs void AttachShader(WebGLShader* shader); void BindAttribLocation(GLuint index, const nsAString& name); void DetachShader(const WebGLShader* shader); already_AddRefed GetActiveAttrib(GLuint index) const; already_AddRefed GetActiveUniform(GLuint index) const; void GetAttachedShaders(nsTArray>* const out) const; GLint GetAttribLocation(const nsAString& name) const; GLint GetFragDataLocation(const nsAString& name) const; void GetProgramInfoLog(nsAString* const out) const; JS::Value GetProgramParameter(GLenum pname) const; GLuint GetUniformBlockIndex(const nsAString& name) const; void GetActiveUniformBlockName(GLuint uniformBlockIndex, nsAString& name) const; JS::Value GetActiveUniformBlockParam(GLuint uniformBlockIndex, GLenum pname) const; JS::Value GetActiveUniformBlockActiveUniforms( JSContext* cx, GLuint uniformBlockIndex, ErrorResult* const out_error) const; already_AddRefed GetUniformLocation( const nsAString& name) const; void GetUniformIndices(const dom::Sequence& uniformNames, dom::Nullable>& retval) const; void UniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) const; void LinkProgram(); bool UseProgram() const; void ValidateProgram() const; //////////////// bool FindAttribUserNameByMappedName(const nsACString& mappedName, nsCString* const out_userName) const; bool FindVaryingByMappedName(const nsACString& mappedName, nsCString* const out_userName, bool* const out_isArray) const; bool FindUniformByMappedName(const nsACString& mappedName, nsCString* const out_userName, bool* const out_isArray) const; bool UnmapUniformBlockName(const nsCString& mappedName, nsCString* const out_userName) const; void TransformFeedbackVaryings(const dom::Sequence& varyings, GLenum bufferMode); already_AddRefed GetTransformFeedbackVarying( GLuint index) const; void EnumerateFragOutputs( std::map& out_FragOutputs) const; bool IsLinked() const { return mMostRecentLinkInfo; } const webgl::LinkedProgramInfo* LinkInfo() const { return mMostRecentLinkInfo.get(); } const auto& FragShader() const { return mFragShader; } WebGLContext* GetParentObject() const { return mContext; } virtual JSObject* WrapObject(JSContext* js, JS::Handle givenProto) override; private: ~WebGLProgram(); void LinkAndUpdate(); bool ValidateForLink(); bool ValidateAfterTentativeLink(nsCString* const out_linkLog) const; public: const GLuint mGLName; private: WebGLRefPtr mVertShader; WebGLRefPtr mFragShader; size_t mNumActiveTFOs; std::map mNextLink_BoundAttribLocs; std::vector mNextLink_TransformFeedbackVaryings; GLenum mNextLink_TransformFeedbackBufferMode; nsCString mLinkLog; RefPtr mMostRecentLinkInfo; }; } // namespace mozilla #endif // WEBGL_PROGRAM_H_