DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (03b97487f359)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
/* -*- 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 <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 "CacheInvalidator.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 {

enum class TextureBaseType : uint8_t;

struct AttribInfo final {
  const RefPtr<WebGLActiveInfo> mActiveInfo;
  const GLint mLoc;  // -1 for active built-ins
};

struct UniformInfo final {
  typedef decltype(WebGLContext::mBound2DTextures) TexListT;

  const RefPtr<WebGLActiveInfo> mActiveInfo;
  const TexListT* const mSamplerTexList;
  const webgl::TextureBaseType mTexBaseType;
  const bool mIsShadowSampler;

  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 FragOutputInfo final {
  const uint8_t loc;
  const nsCString userName;
  const nsCString mappedName;
  const TextureBaseType baseType;
};

struct CachedDrawFetchLimits final {
  uint64_t maxVerts = 0;
  uint64_t maxInstances = 0;
  std::vector<BufferAndIndex> usedBuffers;
};

struct LinkedProgramInfo final : public RefCounted<LinkedProgramInfo>,
                                 public SupportsWeakPtr<LinkedProgramInfo>,
                                 public CacheInvalidator {
  friend class mozilla::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;
  std::unordered_map<uint8_t, const FragOutputInfo> fragOutputs;
  uint8_t zLayerCount = 1;

  // Needed for draw call validation.
  std::vector<UniformInfo*> uniformSamplers;

  mutable std::vector<size_t> componentsPerTFVert;

  bool attrib0Active;

  //////

  mutable CacheWeakMap<const WebGLVertexArray*, CachedDrawFetchLimits>
      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<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();
  }

  const auto& VertShader() const { return mVertShader; }
  const auto& FragShader() const { return mFragShader; }

  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<std::string, GLuint> mNextLink_BoundAttribLocs;

  std::vector<nsString> mNextLink_TransformFeedbackVaryings;
  GLenum mNextLink_TransformFeedbackBufferMode;

  nsCString mLinkLog;
  RefPtr<const webgl::LinkedProgramInfo> mMostRecentLinkInfo;
};

}  // namespace mozilla

#endif  // WEBGL_PROGRAM_H_