tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

OGLShaderProgram.h (12774B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef GFX_OGLSHADERPROGRAM_H
      8 #define GFX_OGLSHADERPROGRAM_H
      9 
     10 #include <map>
     11 #include <string>
     12 #include <utility>
     13 
     14 #include "GLContext.h"  // for fast inlines of glUniform*
     15 #include "mozilla/UniquePtr.h"
     16 #include "OGLShaderConfig.h"
     17 
     18 namespace mozilla {
     19 namespace layers {
     20 
     21 #if defined(DEBUG)
     22 #  define CHECK_CURRENT_PROGRAM 1
     23 #  define ASSERT_THIS_PROGRAM                                       \
     24    do {                                                            \
     25      GLuint currentProgram;                                        \
     26      mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, &currentProgram); \
     27      MOZ_ASSERT(currentProgram == mProgram,                        \
     28                 "SetUniform with wrong program active!");          \
     29    } while (0)
     30 #else
     31 #  define ASSERT_THIS_PROGRAM \
     32    do {                      \
     33    } while (0)
     34 #endif
     35 
     36 /**
     37 * This struct represents the shaders that make up a program and the uniform
     38 * and attribute parmeters that those shaders take.
     39 * It is used by ShaderProgramOGL.
     40 * Use the factory method GetProfileFor to create instances.
     41 */
     42 struct ProgramProfileOGL {
     43  /**
     44   * Factory method; creates an instance of this class for the given
     45   * ShaderConfigOGL
     46   */
     47  static ProgramProfileOGL GetProfileFor(ShaderConfigOGL aConfig);
     48 
     49  // the source code for the program's shaders
     50  std::string mVertexShaderString;
     51  std::string mFragmentShaderString;
     52 
     53  // the vertex attributes
     54  CopyableTArray<std::pair<nsCString, GLuint>> mAttributes;
     55 
     56  KnownUniform mUniforms[KnownUniform::KnownUniformCount];
     57  CopyableTArray<const char*> mDefines;
     58  size_t mTextureCount;
     59 
     60  ProgramProfileOGL() : mTextureCount(0) {}
     61 
     62 private:
     63  static void BuildMixBlender(const ShaderConfigOGL& aConfig,
     64                              std::ostringstream& fs);
     65 };
     66 
     67 /**
     68 * Represents an OGL shader program. The details of a program are represented
     69 * by a ProgramProfileOGL
     70 */
     71 class ShaderProgramOGL {
     72 public:
     73  typedef mozilla::gl::GLContext GLContext;
     74 
     75  ShaderProgramOGL(GLContext* aGL, const ProgramProfileOGL& aProfile);
     76 
     77  ~ShaderProgramOGL();
     78 
     79  bool HasInitialized() {
     80    NS_ASSERTION(mProgramState != STATE_OK || mProgram > 0,
     81                 "Inconsistent program state");
     82    return mProgramState == STATE_OK;
     83  }
     84 
     85  GLuint GetProgram();
     86 
     87  bool Initialize();
     88 
     89  GLint CreateShader(GLenum aShaderType, const char* aShaderSource);
     90 
     91  /**
     92   * Creates a program and stores its id.
     93   */
     94  bool CreateProgram(const char* aVertexShaderString,
     95                     const char* aFragmentShaderString);
     96 
     97  /**
     98   * The following set of methods set a uniform argument to the shader program.
     99   * Not all uniforms may be set for all programs, and such uses will throw
    100   * an assertion.
    101   */
    102  void SetLayerTransform(const gfx::Matrix4x4& aMatrix) {
    103    SetMatrixUniform(KnownUniform::LayerTransform, aMatrix);
    104  }
    105 
    106  void SetLayerTransformInverse(const gfx::Matrix4x4& aMatrix) {
    107    SetMatrixUniform(KnownUniform::LayerTransformInverse, aMatrix);
    108  }
    109 
    110  void SetRoundedClipRect(const gfx::Rect& aRect) {
    111    float vals[4] = {aRect.x, aRect.y, aRect.width, aRect.height};
    112    SetUniform(KnownUniform::RoundedClipRect, 4, vals);
    113  }
    114 
    115  void SetRoundedClipRadii(const gfx::RectCornerRadii& aRadii) {
    116    float vals[4] = {
    117        aRadii.radii[eCornerTopLeft].width,
    118        aRadii.radii[eCornerBottomLeft].width,
    119        aRadii.radii[eCornerTopRight].width,
    120        aRadii.radii[eCornerBottomRight].width,
    121    };
    122    SetUniform(KnownUniform::RoundedClipRadii, 4, vals);
    123  }
    124 
    125  void SetDEAAEdges(const gfx::Point3D* aEdges) {
    126    SetArrayUniform(KnownUniform::SSEdges, 4, aEdges);
    127  }
    128 
    129  void SetViewportSize(const gfx::IntSize& aSize) {
    130    float vals[2] = {(float)aSize.width, (float)aSize.height};
    131    SetUniform(KnownUniform::ViewportSize, 2, vals);
    132  }
    133 
    134  void SetVisibleCenter(const gfx::Point& aVisibleCenter) {
    135    float vals[2] = {aVisibleCenter.x, aVisibleCenter.y};
    136    SetUniform(KnownUniform::VisibleCenter, 2, vals);
    137  }
    138 
    139  void SetLayerRects(const gfx::Rect* aRects) {
    140    float vals[16] = {
    141        aRects[0].X(), aRects[0].Y(), aRects[0].Width(), aRects[0].Height(),
    142        aRects[1].X(), aRects[1].Y(), aRects[1].Width(), aRects[1].Height(),
    143        aRects[2].X(), aRects[2].Y(), aRects[2].Width(), aRects[2].Height(),
    144        aRects[3].X(), aRects[3].Y(), aRects[3].Width(), aRects[3].Height()};
    145    SetUniform(KnownUniform::LayerRects, 16, vals);
    146  }
    147 
    148  void SetProjectionMatrix(const gfx::Matrix4x4& aMatrix) {
    149    SetMatrixUniform(KnownUniform::MatrixProj, aMatrix);
    150  }
    151 
    152  // sets this program's texture transform, if it uses one
    153  void SetTextureTransform(const gfx::Matrix4x4& aMatrix) {
    154    SetMatrixUniform(KnownUniform::TextureTransform, aMatrix);
    155  }
    156 
    157  void SetTextureRects(const gfx::Rect* aRects) {
    158    float vals[16] = {
    159        aRects[0].X(), aRects[0].Y(), aRects[0].Width(), aRects[0].Height(),
    160        aRects[1].X(), aRects[1].Y(), aRects[1].Width(), aRects[1].Height(),
    161        aRects[2].X(), aRects[2].Y(), aRects[2].Width(), aRects[2].Height(),
    162        aRects[3].X(), aRects[3].Y(), aRects[3].Width(), aRects[3].Height()};
    163    SetUniform(KnownUniform::TextureRects, 16, vals);
    164  }
    165 
    166  void SetRenderOffset(const nsIntPoint& aOffset) {
    167    float vals[4] = {float(aOffset.x), float(aOffset.y)};
    168    SetUniform(KnownUniform::RenderTargetOffset, 2, vals);
    169  }
    170 
    171  void SetRenderOffset(float aX, float aY) {
    172    float vals[2] = {aX, aY};
    173    SetUniform(KnownUniform::RenderTargetOffset, 2, vals);
    174  }
    175 
    176  void SetLayerOpacity(float aOpacity) {
    177    SetUniform(KnownUniform::LayerOpacity, aOpacity);
    178  }
    179 
    180  void SetTextureUnit(GLint aUnit) { SetUniform(KnownUniform::Texture, aUnit); }
    181  void SetYTextureUnit(GLint aUnit) {
    182    SetUniform(KnownUniform::YTexture, aUnit);
    183  }
    184 
    185  void SetCbTextureUnit(GLint aUnit) {
    186    SetUniform(KnownUniform::CbTexture, aUnit);
    187  }
    188 
    189  void SetCrTextureUnit(GLint aUnit) {
    190    SetUniform(KnownUniform::CrTexture, aUnit);
    191  }
    192 
    193  void SetYCbCrTextureUnits(GLint aYUnit, GLint aCbUnit, GLint aCrUnit) {
    194    SetUniform(KnownUniform::YTexture, aYUnit);
    195    SetUniform(KnownUniform::CbTexture, aCbUnit);
    196    SetUniform(KnownUniform::CrTexture, aCrUnit);
    197  }
    198 
    199  void SetNV12TextureUnits(GLint aYUnit, GLint aCbCrUnit) {
    200    SetUniform(KnownUniform::YTexture, aYUnit);
    201    SetUniform(KnownUniform::CbTexture, aCbCrUnit);
    202  }
    203 
    204  void SetTexCoordMultiplier(float aWidth, float aHeight) {
    205    float f[] = {aWidth, aHeight};
    206    SetUniform(KnownUniform::TexCoordMultiplier, 2, f);
    207  }
    208 
    209  void SetCbCrTexCoordMultiplier(float aWidth, float aHeight) {
    210    float f[] = {aWidth, aHeight};
    211    SetUniform(KnownUniform::CbCrTexCoordMultiplier, 2, f);
    212  }
    213 
    214  void SetYUVColorSpace(gfx::YUVColorSpace aYUVColorSpace);
    215 
    216  size_t GetTextureCount() const { return mProfile.mTextureCount; }
    217 
    218 protected:
    219  RefPtr<GLContext> mGL;
    220  // the OpenGL id of the program
    221  GLuint mProgram;
    222  ProgramProfileOGL mProfile;
    223  enum { STATE_NEW, STATE_OK, STATE_ERROR } mProgramState;
    224 
    225 #ifdef CHECK_CURRENT_PROGRAM
    226  static int sCurrentProgramKey;
    227 #endif
    228 
    229  void SetUniform(KnownUniform::KnownUniformName aKnownUniform,
    230                  float aFloatValue) {
    231    ASSERT_THIS_PROGRAM;
    232    NS_ASSERTION(
    233        aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount,
    234        "Invalid known uniform");
    235 
    236    KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
    237    if (ku.UpdateUniform(aFloatValue)) {
    238      mGL->fUniform1f(ku.mLocation, aFloatValue);
    239    }
    240  }
    241 
    242  void SetUniform(KnownUniform::KnownUniformName aKnownUniform,
    243                  const gfx::DeviceColor& aColor) {
    244    ASSERT_THIS_PROGRAM;
    245    NS_ASSERTION(
    246        aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount,
    247        "Invalid known uniform");
    248 
    249    KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
    250    if (ku.UpdateUniform(aColor.r, aColor.g, aColor.b, aColor.a)) {
    251      mGL->fUniform4fv(ku.mLocation, 1, ku.mValue.f16v);
    252    }
    253  }
    254 
    255  void SetUniform(KnownUniform::KnownUniformName aKnownUniform, int aLength,
    256                  const float* aFloatValues) {
    257    ASSERT_THIS_PROGRAM;
    258    NS_ASSERTION(
    259        aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount,
    260        "Invalid known uniform");
    261 
    262    KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
    263    if (ku.UpdateUniform(aLength, aFloatValues)) {
    264      switch (aLength) {
    265        case 1:
    266          mGL->fUniform1fv(ku.mLocation, 1, ku.mValue.f16v);
    267          break;
    268        case 2:
    269          mGL->fUniform2fv(ku.mLocation, 1, ku.mValue.f16v);
    270          break;
    271        case 3:
    272          mGL->fUniform3fv(ku.mLocation, 1, ku.mValue.f16v);
    273          break;
    274        case 4:
    275          mGL->fUniform4fv(ku.mLocation, 1, ku.mValue.f16v);
    276          break;
    277        case 16:
    278          mGL->fUniform4fv(ku.mLocation, 4, ku.mValue.f16v);
    279          break;
    280        default:
    281          MOZ_ASSERT_UNREACHABLE("Bogus aLength param");
    282      }
    283    }
    284  }
    285 
    286  void SetArrayUniform(KnownUniform::KnownUniformName aKnownUniform,
    287                       int aLength, float* aFloatValues) {
    288    ASSERT_THIS_PROGRAM;
    289    NS_ASSERTION(
    290        aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount,
    291        "Invalid known uniform");
    292 
    293    KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
    294    if (ku.UpdateArrayUniform(aLength, aFloatValues)) {
    295      mGL->fUniform1fv(ku.mLocation, aLength, ku.mValue.f16v);
    296    }
    297  }
    298 
    299  void SetArrayUniform(KnownUniform::KnownUniformName aKnownUniform,
    300                       int aLength, const gfx::Point3D* aPointValues) {
    301    ASSERT_THIS_PROGRAM;
    302    NS_ASSERTION(
    303        aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount,
    304        "Invalid known uniform");
    305 
    306    KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
    307    if (ku.UpdateArrayUniform(aLength, aPointValues)) {
    308      mGL->fUniform3fv(ku.mLocation, aLength, ku.mValue.f16v);
    309    }
    310  }
    311 
    312  void SetUniform(KnownUniform::KnownUniformName aKnownUniform,
    313                  GLint aIntValue) {
    314    ASSERT_THIS_PROGRAM;
    315    NS_ASSERTION(
    316        aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount,
    317        "Invalid known uniform");
    318 
    319    KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
    320    if (ku.UpdateUniform(aIntValue)) {
    321      mGL->fUniform1i(ku.mLocation, aIntValue);
    322    }
    323  }
    324 
    325  void SetMatrixUniform(KnownUniform::KnownUniformName aKnownUniform,
    326                        const float* aFloatValues) {
    327    ASSERT_THIS_PROGRAM;
    328    NS_ASSERTION(
    329        aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount,
    330        "Invalid known uniform");
    331 
    332    KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
    333    if (ku.UpdateUniform(16, aFloatValues)) {
    334      mGL->fUniformMatrix4fv(ku.mLocation, 1, false, ku.mValue.f16v);
    335    }
    336  }
    337 
    338  void SetMatrix3fvUniform(KnownUniform::KnownUniformName aKnownUniform,
    339                           const float* aFloatValues) {
    340    ASSERT_THIS_PROGRAM;
    341    NS_ASSERTION(
    342        aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount,
    343        "Invalid known uniform");
    344 
    345    KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
    346    if (ku.UpdateUniform(9, aFloatValues)) {
    347      mGL->fUniformMatrix3fv(ku.mLocation, 1, false, ku.mValue.f16v);
    348    }
    349  }
    350 
    351  void SetVec3fvUniform(KnownUniform::KnownUniformName aKnownUniform,
    352                        const float* aFloatValues) {
    353    ASSERT_THIS_PROGRAM;
    354    NS_ASSERTION(
    355        aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount,
    356        "Invalid known uniform");
    357 
    358    KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
    359    if (ku.UpdateUniform(3, aFloatValues)) {
    360      mGL->fUniform3fv(ku.mLocation, 1, ku.mValue.f16v);
    361    }
    362  }
    363 
    364  void SetMatrixUniform(KnownUniform::KnownUniformName aKnownUniform,
    365                        const gfx::Matrix4x4& aMatrix) {
    366    SetMatrixUniform(aKnownUniform, &aMatrix._11);
    367  }
    368 };
    369 
    370 class ShaderProgramOGLsHolder final {
    371 public:
    372  NS_INLINE_DECL_REFCOUNTING(ShaderProgramOGLsHolder)
    373 
    374  explicit ShaderProgramOGLsHolder(gl::GLContext* aGL);
    375 
    376  ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL& aConfig);
    377  void Clear();
    378  ShaderProgramOGL* ActivateProgram(const ShaderConfigOGL& aConfig);
    379  void ResetCurrentProgram();
    380 
    381 protected:
    382  ~ShaderProgramOGLsHolder();
    383 
    384  const RefPtr<gl::GLContext> mGL;
    385  std::map<ShaderConfigOGL, UniquePtr<ShaderProgramOGL>> mPrograms;
    386  ShaderProgramOGL* mCurrentProgram = nullptr;
    387 };
    388 
    389 }  // namespace layers
    390 }  // namespace mozilla
    391 
    392 #endif  // GFX_OGLSHADERPROGRAM_H