tor-browser

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

WebGLTransformFeedback.cpp (4612B)


      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 "WebGLTransformFeedback.h"
      7 
      8 #include "GLContext.h"
      9 #include "WebGL2Context.h"
     10 #include "WebGLBuffer.h"
     11 #include "WebGLProgram.h"
     12 #include "mozilla/IntegerRange.h"
     13 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
     14 
     15 namespace mozilla {
     16 
     17 WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* webgl, GLuint tf)
     18    : WebGLContextBoundObject(webgl),
     19      mGLName(tf),
     20      mIndexedBindings(webgl::kMaxTransformFeedbackSeparateAttribs),
     21      mIsPaused(false),
     22      mIsActive(false) {}
     23 
     24 WebGLTransformFeedback::~WebGLTransformFeedback() {
     25  if (!mContext) return;
     26  if (mGLName) {
     27    mContext->gl->fDeleteTransformFeedbacks(1, &mGLName);
     28  }
     29 }
     30 
     31 ////////////////////////////////////////
     32 
     33 void WebGLTransformFeedback::BeginTransformFeedback(GLenum primMode) {
     34  if (mIsActive) return mContext->ErrorInvalidOperation("Already active.");
     35 
     36  switch (primMode) {
     37    case LOCAL_GL_POINTS:
     38    case LOCAL_GL_LINES:
     39    case LOCAL_GL_TRIANGLES:
     40      break;
     41    default:
     42      mContext->ErrorInvalidEnum(
     43          "`primitiveMode` must be one of POINTS, LINES, or"
     44          " TRIANGLES.");
     45      return;
     46  }
     47 
     48  const auto& prog = mContext->mCurrentProgram;
     49  if (!prog || !prog->IsLinked() ||
     50      prog->LinkInfo()->componentsPerTFVert.empty()) {
     51    mContext->ErrorInvalidOperation(
     52        "Current program not valid for transform"
     53        " feedback.");
     54    return;
     55  }
     56 
     57  const auto& linkInfo = prog->LinkInfo();
     58  const auto& componentsPerTFVert = linkInfo->componentsPerTFVert;
     59 
     60  size_t minVertCapacity = SIZE_MAX;
     61  for (size_t i = 0; i < componentsPerTFVert.size(); i++) {
     62    const auto& indexedBinding = mIndexedBindings[i];
     63    const auto& componentsPerVert = componentsPerTFVert[i];
     64 
     65    const auto& buffer = indexedBinding.mBufferBinding;
     66    if (!buffer) {
     67      mContext->ErrorInvalidOperation(
     68          "No buffer attached to required transform"
     69          " feedback index %u.",
     70          (uint32_t)i);
     71      return;
     72    }
     73 
     74    for (const auto iBound : IntegerRange(mIndexedBindings.size())) {
     75      const auto& bound = mIndexedBindings[iBound].mBufferBinding.get();
     76      if (iBound != i && buffer == bound) {
     77        mContext->GenErrorIllegalUse(
     78            LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<uint32_t>(i),
     79            LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<uint32_t>(iBound));
     80        return;
     81      }
     82    }
     83 
     84    const size_t vertCapacity = buffer->ByteLength() / 4 / componentsPerVert;
     85    minVertCapacity = std::min(minVertCapacity, vertCapacity);
     86  }
     87 
     88  ////
     89 
     90  const auto& gl = mContext->gl;
     91  gl->fBeginTransformFeedback(primMode);
     92 
     93  ////
     94 
     95  mIsActive = true;
     96  MOZ_ASSERT(!mIsPaused);
     97 
     98  mActive_Program = prog;
     99  mActive_PrimMode = primMode;
    100  mActive_VertPosition = 0;
    101  mActive_VertCapacity = minVertCapacity;
    102 
    103  ////
    104 
    105  mActive_Program->mNumActiveTFOs++;
    106 }
    107 
    108 void WebGLTransformFeedback::EndTransformFeedback() {
    109  if (!mIsActive) return mContext->ErrorInvalidOperation("Not active.");
    110 
    111  ////
    112 
    113  const auto& gl = mContext->gl;
    114  gl->fEndTransformFeedback();
    115 
    116  if (gl->WorkAroundDriverBugs()) {
    117 #ifdef XP_MACOSX
    118    // Multi-threaded GL on mac will generate INVALID_OP in some cases for at
    119    // least BindBufferBase after an EndTransformFeedback if there is not a
    120    // flush between the two. Single-threaded GL does not have this issue. This
    121    // is likely due to not synchronizing client/server state, and erroring in
    122    // BindBufferBase because the client thinks we're still in transform
    123    // feedback.
    124    gl->fFlush();
    125 #endif
    126  }
    127 
    128  ////
    129 
    130  mIsActive = false;
    131  mIsPaused = false;
    132 
    133  ////
    134 
    135  mActive_Program->mNumActiveTFOs--;
    136 }
    137 
    138 void WebGLTransformFeedback::PauseTransformFeedback() {
    139  if (!mIsActive || mIsPaused) {
    140    mContext->ErrorInvalidOperation("Not active or is paused.");
    141    return;
    142  }
    143 
    144  ////
    145 
    146  const auto& gl = mContext->gl;
    147  gl->fPauseTransformFeedback();
    148 
    149  ////
    150 
    151  mIsPaused = true;
    152 }
    153 
    154 void WebGLTransformFeedback::ResumeTransformFeedback() {
    155  if (!mIsPaused) return mContext->ErrorInvalidOperation("Not paused.");
    156 
    157  if (mContext->mCurrentProgram != mActive_Program) {
    158    mContext->ErrorInvalidOperation("Active program differs from original.");
    159    return;
    160  }
    161 
    162  ////
    163 
    164  const auto& gl = mContext->gl;
    165  gl->fResumeTransformFeedback();
    166 
    167  ////
    168 
    169  MOZ_ASSERT(mIsActive);
    170  mIsPaused = false;
    171 }
    172 
    173 }  // namespace mozilla