tor-browser

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

WebGLContextVertices.cpp (8652B)


      1 /* -*- Mode: C++; tab-width: 4; 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 "GLContext.h"
      7 #include "WebGLBuffer.h"
      8 #include "WebGLContext.h"
      9 #include "WebGLFramebuffer.h"
     10 #include "WebGLProgram.h"
     11 #include "WebGLRenderbuffer.h"
     12 #include "WebGLShader.h"
     13 #include "WebGLTexture.h"
     14 #include "WebGLTypes.h"
     15 #include "WebGLVertexArray.h"
     16 #include "mozilla/ResultVariant.h"
     17 
     18 namespace mozilla {
     19 
     20 static bool ValidateAttribIndex(WebGLContext& webgl, GLuint index) {
     21  bool valid = (index < webgl.MaxVertexAttribs());
     22 
     23  if (!valid) {
     24    if (index == GLuint(-1)) {
     25      webgl.ErrorInvalidValue(
     26          "-1 is not a valid `index`. This value"
     27          " probably comes from a getAttribLocation()"
     28          " call, where this return value -1 means"
     29          " that the passed name didn't correspond to"
     30          " an active attribute in the specified"
     31          " program.");
     32    } else {
     33      webgl.ErrorInvalidValue(
     34          "`index` must be less than"
     35          " MAX_VERTEX_ATTRIBS.");
     36    }
     37  }
     38 
     39  return valid;
     40 }
     41 
     42 ////////////////////////////////////////
     43 
     44 void WebGLContext::VertexAttrib4T(GLuint index, const webgl::TypedQuad& src) {
     45  const FuncScope funcScope(*this, "vertexAttrib[1234]u?[fi]v?");
     46  if (IsContextLost()) return;
     47 
     48  if (!ValidateAttribIndex(*this, index)) return;
     49 
     50  ////
     51 
     52  if (index || !gl->IsCompatibilityProfile()) {
     53    switch (src.type) {
     54      case webgl::AttribBaseType::Boolean:
     55      case webgl::AttribBaseType::Float:
     56        gl->fVertexAttrib4fv(index,
     57                             reinterpret_cast<const float*>(src.data.data()));
     58        break;
     59      case webgl::AttribBaseType::Int:
     60        gl->fVertexAttribI4iv(
     61            index, reinterpret_cast<const int32_t*>(src.data.data()));
     62        break;
     63      case webgl::AttribBaseType::Uint:
     64        gl->fVertexAttribI4uiv(
     65            index, reinterpret_cast<const uint32_t*>(src.data.data()));
     66        break;
     67    }
     68  }
     69 
     70  ////
     71 
     72  mGenericVertexAttribTypes[index] = src.type;
     73  mGenericVertexAttribTypeInvalidator.InvalidateCaches();
     74 
     75  if (!index) {
     76    memcpy(mGenericVertexAttrib0Data, src.data.data(),
     77           sizeof(mGenericVertexAttrib0Data));
     78  }
     79 }
     80 
     81 ////////////////////////////////////////
     82 
     83 void WebGLContext::EnableVertexAttribArray(GLuint index) {
     84  const FuncScope funcScope(*this, "enableVertexAttribArray");
     85  if (IsContextLost()) return;
     86 
     87  if (!ValidateAttribIndex(*this, index)) return;
     88 
     89  gl->fEnableVertexAttribArray(index);
     90 
     91  MOZ_ASSERT(mBoundVertexArray);
     92  mBoundVertexArray->SetAttribIsArray(index, true);
     93 }
     94 
     95 void WebGLContext::DisableVertexAttribArray(GLuint index) {
     96  const FuncScope funcScope(*this, "disableVertexAttribArray");
     97  if (IsContextLost()) return;
     98 
     99  if (!ValidateAttribIndex(*this, index)) return;
    100 
    101  if (index || !gl->IsCompatibilityProfile()) {
    102    gl->fDisableVertexAttribArray(index);
    103  }
    104 
    105  MOZ_ASSERT(mBoundVertexArray);
    106  mBoundVertexArray->SetAttribIsArray(index, false);
    107 }
    108 
    109 Maybe<double> WebGLContext::GetVertexAttrib(GLuint index, GLenum pname) {
    110  const FuncScope funcScope(*this, "getVertexAttrib");
    111  if (IsContextLost()) return Nothing();
    112 
    113  if (!ValidateAttribIndex(*this, index)) return Nothing();
    114 
    115  MOZ_ASSERT(mBoundVertexArray);
    116  auto ret = mBoundVertexArray->GetVertexAttrib(index, pname);
    117 
    118  switch (pname) {
    119    case LOCAL_GL_VERTEX_ATTRIB_ARRAY_INTEGER:
    120      if (!IsWebGL2()) {
    121        ret = Nothing();
    122      }
    123      break;
    124 
    125    case LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
    126      if (!IsWebGL2() &&
    127          !IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays)) {
    128        ret = Nothing();
    129      }
    130      break;
    131  }
    132 
    133  if (!ret) {
    134    ErrorInvalidEnumInfo("pname", pname);
    135  }
    136  return ret;
    137 }
    138 
    139 ////////////////////////////////////////
    140 
    141 Result<webgl::VertAttribPointerCalculated, webgl::ErrorInfo>
    142 CheckVertexAttribPointer(const bool isWebgl2,
    143                         const webgl::VertAttribPointerDesc& desc) {
    144  if (desc.channels < 1 || desc.channels > 4) {
    145    return Err(webgl::ErrorInfo{LOCAL_GL_INVALID_VALUE,
    146                                "Channel count `size` must be within [1,4]."});
    147  }
    148 
    149  ////
    150 
    151  webgl::VertAttribPointerCalculated calc;
    152 
    153  bool isTypeValid = true;
    154  bool isPackedType = false;
    155  uint8_t bytesPerType = 0;
    156  switch (desc.type) {
    157    // WebGL 1:
    158    case LOCAL_GL_BYTE:
    159      bytesPerType = 1;
    160      calc.baseType = webgl::AttribBaseType::Int;
    161      break;
    162    case LOCAL_GL_UNSIGNED_BYTE:
    163      bytesPerType = 1;
    164      calc.baseType = webgl::AttribBaseType::Uint;
    165      break;
    166 
    167    case LOCAL_GL_SHORT:
    168      bytesPerType = 2;
    169      calc.baseType = webgl::AttribBaseType::Int;
    170      break;
    171    case LOCAL_GL_UNSIGNED_SHORT:
    172      bytesPerType = 2;
    173      calc.baseType = webgl::AttribBaseType::Uint;
    174      break;
    175 
    176    case LOCAL_GL_FLOAT:
    177      bytesPerType = 4;
    178      calc.baseType = webgl::AttribBaseType::Float;
    179      break;
    180 
    181    // WebGL 2:
    182    case LOCAL_GL_INT:
    183      isTypeValid = isWebgl2;
    184      bytesPerType = 4;
    185      calc.baseType = webgl::AttribBaseType::Int;
    186      break;
    187    case LOCAL_GL_UNSIGNED_INT:
    188      isTypeValid = isWebgl2;
    189      bytesPerType = 4;
    190      calc.baseType = webgl::AttribBaseType::Uint;
    191      break;
    192 
    193    case LOCAL_GL_HALF_FLOAT:
    194      isTypeValid = isWebgl2;
    195      bytesPerType = 2;
    196      calc.baseType = webgl::AttribBaseType::Float;
    197      break;
    198 
    199    case LOCAL_GL_INT_2_10_10_10_REV:
    200    case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
    201      if (desc.channels != 4) {
    202        return Err(webgl::ErrorInfo{LOCAL_GL_INVALID_OPERATION,
    203                                    "Size must be 4 for this type."});
    204      }
    205      isTypeValid = isWebgl2;
    206      bytesPerType = 4;
    207      calc.baseType =
    208          webgl::AttribBaseType::Float;  // Invalid for intFunc:true.
    209      isPackedType = true;
    210      break;
    211 
    212    default:
    213      isTypeValid = false;
    214      break;
    215  }
    216  if (desc.intFunc) {
    217    isTypeValid = (calc.baseType != webgl::AttribBaseType::Float);
    218  } else {
    219    calc.baseType = webgl::AttribBaseType::Float;
    220  }
    221  if (!isTypeValid) {
    222    const auto info =
    223        nsPrintfCString("Bad `type`: %s", EnumString(desc.type).c_str());
    224    return Err(webgl::ErrorInfo{LOCAL_GL_INVALID_ENUM, info.BeginReading()});
    225  }
    226 
    227  ////
    228 
    229  calc.byteSize = bytesPerType;
    230  if (!isPackedType) {
    231    calc.byteSize *= desc.channels;
    232  }
    233 
    234  calc.byteStride =
    235      desc.byteStrideOrZero ? desc.byteStrideOrZero : calc.byteSize;
    236 
    237  // `alignment` should always be a power of two.
    238  MOZ_ASSERT(IsPowerOfTwo(bytesPerType));
    239  const auto typeAlignmentMask = bytesPerType - 1;
    240 
    241  if (calc.byteStride & typeAlignmentMask ||
    242      desc.byteOffset & typeAlignmentMask) {
    243    return Err(
    244        webgl::ErrorInfo{LOCAL_GL_INVALID_OPERATION,
    245                         "`stride` and `byteOffset` must satisfy the alignment"
    246                         " requirement of `type`."});
    247  }
    248 
    249  return calc;
    250 }
    251 
    252 void DoVertexAttribPointer(gl::GLContext& gl, const uint32_t index,
    253                           const webgl::VertAttribPointerDesc& desc) {
    254  if (desc.intFunc) {
    255    gl.fVertexAttribIPointer(index, desc.channels, desc.type,
    256                             desc.byteStrideOrZero,
    257                             reinterpret_cast<const void*>(desc.byteOffset));
    258  } else {
    259    gl.fVertexAttribPointer(index, desc.channels, desc.type, desc.normalized,
    260                            desc.byteStrideOrZero,
    261                            reinterpret_cast<const void*>(desc.byteOffset));
    262  }
    263 }
    264 
    265 void WebGLContext::VertexAttribPointer(
    266    const uint32_t index, const webgl::VertAttribPointerDesc& desc) {
    267  if (IsContextLost()) return;
    268  if (!ValidateAttribIndex(*this, index)) return;
    269 
    270  const auto res = CheckVertexAttribPointer(IsWebGL2(), desc);
    271  if (res.isErr()) {
    272    const auto& err = res.inspectErr();
    273    GenerateError(err.type, "%s", err.info.c_str());
    274    return;
    275  }
    276  const auto& calc = res.inspect();
    277 
    278  ////
    279 
    280  const auto& buffer = mBoundArrayBuffer;
    281 
    282  mBoundVertexArray->AttribPointer(index, buffer, desc, calc);
    283 
    284  const ScopedLazyBind lazyBind(gl, LOCAL_GL_ARRAY_BUFFER, buffer);
    285  DoVertexAttribPointer(*gl, index, desc);
    286 }
    287 
    288 ////////////////////////////////////////
    289 
    290 void WebGLContext::VertexAttribDivisor(GLuint index, GLuint divisor) {
    291  const FuncScope funcScope(*this, "vertexAttribDivisor");
    292  if (IsContextLost()) return;
    293 
    294  if (!ValidateAttribIndex(*this, index)) return;
    295 
    296  MOZ_ASSERT(mBoundVertexArray);
    297  mBoundVertexArray->AttribDivisor(index, divisor);
    298  gl->fVertexAttribDivisor(index, divisor);
    299 }
    300 
    301 }  // namespace mozilla