/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* 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 <map> #include <set> #include <string> #include <vector> #include "mozilla/LinkedList.h" #include "mozilla/RefPtr.h" #include "mozilla/WeakPtr.h" #include "nsString.h" #include "nsWrapperCache.h" #include "WebGLContext.h" #include "WebGLObjectModel.h" namespace mozilla { class ErrorResult; class WebGLActiveInfo; class WebGLProgram; class WebGLShader; class WebGLUniformLocation; namespace dom { template<typename> struct Nullable; class OwningUnsignedLongOrUint32ArrayOrBoolean; template<typename> class Sequence; } // namespace dom namespace webgl { struct AttribInfo final { const RefPtr<WebGLActiveInfo> mActiveInfo; const GLint mLoc; // -1 for active built-ins const GLenum mBaseType; }; struct UniformInfo final { typedef decltype(WebGLContext::mBound2DTextures) TexListT; const RefPtr<WebGLActiveInfo> mActiveInfo; const TexListT* const mSamplerTexList; std::vector<uint32_t> 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 LinkedProgramInfo final : public RefCounted<LinkedProgramInfo> , public SupportsWeakPtr<LinkedProgramInfo> { friend class WebGLProgram; MOZ_DECLARE_REFCOUNTED_TYPENAME(LinkedProgramInfo) MOZ_DECLARE_WEAKREFERENCE_TYPENAME(LinkedProgramInfo) ////// WebGLProgram* const prog; const GLenum transformFeedbackBufferMode; std::vector<AttribInfo> attribs; std::vector<UniformInfo*> uniforms; // Owns its contents. std::vector<UniformBlockInfo*> uniformBlocks; // Owns its contents. std::vector<RefPtr<WebGLActiveInfo>> transformFeedbackVaryings; // Needed for draw call validation. std::vector<UniformInfo*> uniformSamplers; mutable std::vector<size_t> componentsPerTFVert; ////// // The maps for the frag data names to the translated names. std::map<nsCString, const nsCString> fragDataMap; 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; bool MapFragDataName(const nsCString& userName, nsCString* const out_mappedName) const; }; } // namespace webgl class WebGLProgram final : public nsWrapperCache , public WebGLRefCountedObject<WebGLProgram> , public LinkedListElement<WebGLProgram> { 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<WebGLActiveInfo> GetActiveAttrib(GLuint index) const; already_AddRefed<WebGLActiveInfo> GetActiveUniform(GLuint index) const; void GetAttachedShaders(nsTArray<RefPtr<WebGLShader>>* 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<WebGLUniformLocation> GetUniformLocation(const nsAString& name) const; void GetUniformIndices(const dom::Sequence<nsString>& uniformNames, dom::Nullable< nsTArray<GLuint> >& 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<nsString>& varyings, GLenum bufferMode); already_AddRefed<WebGLActiveInfo> GetTransformFeedbackVarying(GLuint index) const; void EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const; bool IsLinked() const { return mMostRecentLinkInfo; } const webgl::LinkedProgramInfo* LinkInfo() const { return mMostRecentLinkInfo.get(); } WebGLContext* GetParentObject() const { return mContext; } virtual JSObject* WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto) override; private: ~WebGLProgram(); void LinkAndUpdate(); bool ValidateForLink(); bool ValidateAfterTentativeLink(nsCString* const out_linkLog) const; public: const GLuint mGLName; private: WebGLRefPtr<WebGLShader> mVertShader; WebGLRefPtr<WebGLShader> mFragShader; size_t mNumActiveTFOs; std::map<nsCString, GLuint> mNextLink_BoundAttribLocs; std::vector<nsString> mNextLink_TransformFeedbackVaryings; GLenum mNextLink_TransformFeedbackBufferMode; nsCString mLinkLog; RefPtr<const webgl::LinkedProgramInfo> mMostRecentLinkInfo; }; } // namespace mozilla #endif // WEBGL_PROGRAM_H_