tor-browser

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

WebGLShader.cpp (5947B)


      1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "WebGLShader.h"
      7 
      8 #include "GLContext.h"
      9 #include "GLSLANG/ShaderLang.h"
     10 #include "WebGLContext.h"
     11 #include "WebGLObjectModel.h"
     12 #include "WebGLShaderValidator.h"
     13 #include "WebGLValidateStrings.h"
     14 #include "mozilla/MemoryReporting.h"
     15 #include "mozilla/dom/WebGLRenderingContextBinding.h"
     16 #include "nsPrintfCString.h"
     17 #include "nsString.h"
     18 #include "prenv.h"
     19 
     20 namespace mozilla {
     21 
     22 static void PrintLongString(const char* const begin, const size_t len) {
     23  // Wow - Roll Your Own Foreach-Lines because printf_stderr has a hard-coded
     24  // internal size, so long strings are truncated.
     25 
     26  const size_t chunkSize = 1000;
     27  auto buf = std::vector<char>(chunkSize + 1);  // +1 for null-term
     28  const auto bufBegin = buf.data();
     29 
     30  auto chunkBegin = begin;
     31  const auto end = begin + len;
     32  while (chunkBegin + chunkSize < end) {
     33    memcpy(bufBegin, chunkBegin, chunkSize);
     34    printf_stderr("%s", bufBegin);
     35    chunkBegin += chunkSize;
     36  }
     37  printf_stderr("%s", chunkBegin);
     38 }
     39 
     40 template <size_t N>
     41 static bool SubstringStartsWith(const std::string& testStr, size_t offset,
     42                                const char (&refStr)[N]) {
     43  for (size_t i = 0; i < N - 1; i++) {
     44    if (testStr[offset + i] != refStr[i]) return false;
     45  }
     46  return true;
     47 }
     48 
     49 static void GetCompilationStatusAndLog(gl::GLContext* gl, GLuint shader,
     50                                       bool* const out_success,
     51                                       std::string* const out_log) {
     52  GLint compileStatus = LOCAL_GL_FALSE;
     53  gl->fGetShaderiv(shader, LOCAL_GL_COMPILE_STATUS, &compileStatus);
     54 
     55  // It's simpler if we always get the log.
     56  GLint lenWithNull = 0;
     57  gl->fGetShaderiv(shader, LOCAL_GL_INFO_LOG_LENGTH, &lenWithNull);
     58  if (lenWithNull < 1) {
     59    lenWithNull = 1;
     60  }
     61  std::vector<char> buffer(lenWithNull);
     62  gl->fGetShaderInfoLog(shader, buffer.size(), nullptr, buffer.data());
     63  *out_log = buffer.data();
     64 
     65  *out_success = (compileStatus == LOCAL_GL_TRUE);
     66 }
     67 
     68 ////////////////////////////////////////////////////////////////////////////////
     69 
     70 WebGLShader::WebGLShader(WebGLContext* webgl, GLenum type)
     71    : WebGLContextBoundObject(webgl),
     72      mGLName(webgl->gl->fCreateShader(type)),
     73      mType(type) {
     74  mCompileResults = std::make_unique<webgl::ShaderValidatorResults>();
     75 }
     76 
     77 WebGLShader::~WebGLShader() {
     78  if (!mContext) return;
     79  mContext->gl->fDeleteShader(mGLName);
     80 }
     81 
     82 void WebGLShader::ShaderSource(const std::string& u8) {
     83  mSource = CrushGlslToAscii(u8);
     84 }
     85 
     86 void WebGLShader::CompileShader() {
     87  mCompilationSuccessful = false;
     88 
     89  gl::GLContext* gl = mContext->gl;
     90 
     91  static const bool kDumpShaders = PR_GetEnv("MOZ_WEBGL_DUMP_SHADERS");
     92  if (MOZ_UNLIKELY(kDumpShaders)) {
     93    printf_stderr("==== begin MOZ_WEBGL_DUMP_SHADERS ====\n");
     94    PrintLongString(mSource.c_str(), mSource.size());
     95  }
     96 
     97  {
     98    const auto validator = mContext->CreateShaderValidator(mType);
     99    MOZ_ASSERT(validator);
    100 
    101    mCompileResults = validator->ValidateAndTranslate(mSource.c_str());
    102  }
    103 
    104  mCompilationLog = mCompileResults->mInfoLog.c_str();
    105  const auto& success = mCompileResults->mValid;
    106 
    107  if (MOZ_UNLIKELY(kDumpShaders)) {
    108    printf_stderr("\n==== \\/ \\/ \\/ ====\n");
    109    if (success) {
    110      const auto& translated = mCompileResults->mObjectCode;
    111      PrintLongString(translated.data(), translated.size());
    112    } else {
    113      printf_stderr("Validation failed:\n%s",
    114                    mCompileResults->mInfoLog.c_str());
    115    }
    116    printf_stderr("\n==== end ====\n");
    117  }
    118 
    119  if (!success) return;
    120 
    121  const std::array<const char*, 1> parts = {
    122      mCompileResults->mObjectCode.c_str()};
    123  gl->fShaderSource(mGLName, parts.size(), parts.data(), nullptr);
    124 
    125  gl->fCompileShader(mGLName);
    126 
    127  GetCompilationStatusAndLog(gl, mGLName, &mCompilationSuccessful,
    128                             &mCompilationLog);
    129 }
    130 
    131 ////////////////////////////////////////////////////////////////////////////////
    132 
    133 size_t WebGLShader::CalcNumSamplerUniforms() const {
    134  size_t accum = 0;
    135  for (const auto& cur : mCompileResults->mUniforms) {
    136    const auto& type = cur.type;
    137    if (type == LOCAL_GL_SAMPLER_2D || type == LOCAL_GL_SAMPLER_CUBE) {
    138      accum += cur.getArraySizeProduct();
    139    }
    140  }
    141  return accum;
    142 }
    143 
    144 size_t WebGLShader::NumAttributes() const {
    145  return mCompileResults->mAttributes.size();
    146 }
    147 
    148 void WebGLShader::BindAttribLocation(GLuint prog, const std::string& userName,
    149                                     GLuint index) const {
    150  for (const auto& attrib : mCompileResults->mAttributes) {
    151    if (attrib.name == userName) {
    152      mContext->gl->fBindAttribLocation(prog, index, attrib.mappedName.c_str());
    153      return;
    154    }
    155  }
    156 }
    157 
    158 void WebGLShader::MapTransformFeedbackVaryings(
    159    const std::vector<std::string>& varyings,
    160    std::vector<std::string>* out_mappedVaryings) const {
    161  MOZ_ASSERT(mType == LOCAL_GL_VERTEX_SHADER);
    162  MOZ_ASSERT(out_mappedVaryings);
    163 
    164  out_mappedVaryings->clear();
    165  out_mappedVaryings->reserve(varyings.size());
    166 
    167  const auto& shaderVaryings = mCompileResults->mVaryings;
    168 
    169  for (const auto& userName : varyings) {
    170    const auto* mappedName = &userName;
    171    for (const auto& shaderVarying : shaderVaryings) {
    172      if (shaderVarying.name == userName) {
    173        mappedName = &shaderVarying.mappedName;
    174        break;
    175      }
    176    }
    177    out_mappedVaryings->push_back(*mappedName);
    178  }
    179 }
    180 
    181 ////////////////////////////////////////////////////////////////////////////////
    182 // Boilerplate
    183 
    184 size_t WebGLShader::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
    185  return mallocSizeOf(this) + mSource.size() + 1 +
    186         mCompileResults->SizeOfIncludingThis(mallocSizeOf) +
    187         mCompilationLog.size() + 1;
    188 }
    189 
    190 }  // namespace mozilla