/* -*- 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 #include #include #include #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 struct Nullable; class OwningUnsignedLongOrUint32ArrayOrBoolean; template class Sequence; } // namespace dom namespace webgl { struct AttribInfo final { const RefPtr mActiveInfo; const GLint mLoc; // -1 for active built-ins const GLenum mBaseType; }; struct UniformInfo final { typedef decltype(WebGLContext::mBound2DTextures) TexListT; const RefPtr mActiveInfo; const TexListT* const mSamplerTexList; 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 LinkedProgramInfo final : public RefCounted , public SupportsWeakPtr { friend class 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; // Needed for draw call validation. std::vector uniformSamplers; mutable std::vector componentsPerTFVert; ////// // The maps for the frag data names to the translated names. std::map 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 , 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< nsTArray >& 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(); } 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_