tor-browser

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

WebGLContextFramebufferOperations.cpp (6355B)


      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 "GLScreenBuffer.h"
      8 #include "WebGLContext.h"
      9 #include "WebGLFormats.h"
     10 #include "WebGLFramebuffer.h"
     11 #include "WebGLRenderbuffer.h"
     12 #include "WebGLTexture.h"
     13 
     14 namespace mozilla {
     15 
     16 void WebGLContext::Clear(GLbitfield mask) {
     17  const FuncScope funcScope(*this, "clear");
     18  if (IsContextLost()) return;
     19 
     20  uint32_t m = mask & (LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT |
     21                       LOCAL_GL_STENCIL_BUFFER_BIT);
     22  if (mask != m) return ErrorInvalidValue("Invalid mask bits.");
     23 
     24  if (mask == 0) {
     25    GenerateWarning("Calling gl.clear(0) has no effect.");
     26  } else if (mRasterizerDiscardEnabled) {
     27    GenerateWarning(
     28        "Calling gl.clear() with RASTERIZER_DISCARD enabled has no effects.");
     29  }
     30 
     31  if (mask & LOCAL_GL_COLOR_BUFFER_BIT && mBoundDrawFramebuffer) {
     32    for (const auto& cur : mBoundDrawFramebuffer->ColorDrawBuffers()) {
     33      const auto imageInfo = cur->GetImageInfo();
     34      if (!imageInfo || !imageInfo->mFormat) continue;
     35 
     36      if (imageInfo->mFormat->format->baseType !=
     37          webgl::TextureBaseType::Float) {
     38        ErrorInvalidOperation(
     39            "Color draw buffers must be floating-point"
     40            " or fixed-point. (normalized (u)ints)");
     41        return;
     42      }
     43    }
     44  }
     45 
     46  if (!BindCurFBForDraw()) return;
     47 
     48  auto driverMask = mask;
     49  if (!mBoundDrawFramebuffer) {
     50    if (mNeedsFakeNoDepth) {
     51      driverMask &= ~LOCAL_GL_DEPTH_BUFFER_BIT;
     52    }
     53    if (mNeedsFakeNoStencil) {
     54      driverMask &= ~LOCAL_GL_STENCIL_BUFFER_BIT;
     55    }
     56  }
     57 
     58  const ScopedDrawCallWrapper wrapper(*this);
     59  gl->fClear(driverMask);
     60 }
     61 
     62 static GLfloat GLClampFloat(GLfloat val) {
     63  if (val < 0.0) return 0.0;
     64 
     65  if (val > 1.0) return 1.0;
     66 
     67  return val;
     68 }
     69 
     70 void WebGLContext::ClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
     71  const FuncScope funcScope(*this, "clearColor");
     72  if (IsContextLost()) return;
     73 
     74  if (IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_float)) {
     75    MOZ_ASSERT(IsExtensionExplicit(WebGLExtensionID::EXT_color_buffer_float));
     76 
     77  } else if (IsExtensionEnabled(
     78                 WebGLExtensionID::EXT_color_buffer_half_float) ||
     79             IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float)) {
     80    const bool explict =
     81        (IsExtensionExplicit(WebGLExtensionID::EXT_color_buffer_half_float) ||
     82         IsExtensionExplicit(WebGLExtensionID::WEBGL_color_buffer_float));
     83    const bool wouldHaveClamped =
     84        (r != GLClampFloat(r) || g != GLClampFloat(g) || b != GLClampFloat(b) ||
     85         a != GLClampFloat(a));
     86    if (!explict && wouldHaveClamped) {
     87      if (IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float)) {
     88        WarnIfImplicit(WebGLExtensionID::EXT_color_buffer_half_float);
     89      } else if (IsExtensionEnabled(
     90                     WebGLExtensionID::WEBGL_color_buffer_float)) {
     91        WarnIfImplicit(WebGLExtensionID::WEBGL_color_buffer_float);
     92      }
     93    }
     94  } else {
     95    r = GLClampFloat(r);
     96    g = GLClampFloat(g);
     97    b = GLClampFloat(b);
     98    a = GLClampFloat(a);
     99  }
    100 
    101  gl->fClearColor(r, g, b, a);
    102 
    103  mColorClearValue[0] = r;
    104  mColorClearValue[1] = g;
    105  mColorClearValue[2] = b;
    106  mColorClearValue[3] = a;
    107 }
    108 
    109 void WebGLContext::ClearDepth(GLclampf v) {
    110  const FuncScope funcScope(*this, "clearDepth");
    111  if (IsContextLost()) return;
    112 
    113  mDepthClearValue = GLClampFloat(v);
    114  gl->fClearDepth(mDepthClearValue);
    115 }
    116 
    117 void WebGLContext::ClearStencil(GLint v) {
    118  const FuncScope funcScope(*this, "clearStencil");
    119  if (IsContextLost()) return;
    120 
    121  mStencilClearValue = v;
    122  gl->fClearStencil(v);
    123 }
    124 
    125 void WebGLContext::ColorMask(const Maybe<GLuint> i, const uint8_t mask) {
    126  const FuncScope funcScope(*this, "colorMask");
    127  if (IsContextLost()) return;
    128 
    129  if (i) {
    130    MOZ_RELEASE_ASSERT(
    131        IsExtensionEnabled(WebGLExtensionID::OES_draw_buffers_indexed));
    132    const auto limit = MaxValidDrawBuffers();
    133    if (*i >= limit) {
    134      ErrorInvalidValue("`index` (%u) must be < %s (%u)", *i,
    135                        "MAX_DRAW_BUFFERS", limit);
    136      return;
    137    }
    138    if (*i == 0) {
    139      mColorWriteMask0 = mask;
    140    }
    141    mColorWriteMaskNonzero[*i] = bool(mask);
    142  } else {
    143    mColorWriteMask0 = mask;
    144    if (mask) {
    145      mColorWriteMaskNonzero.set();
    146    } else {
    147      mColorWriteMaskNonzero.reset();
    148    }
    149  }
    150 
    151  DoColorMask(i, mask);
    152 }
    153 
    154 void WebGLContext::DepthMask(WebGLboolean b) {
    155  const FuncScope funcScope(*this, "depthMask");
    156  if (IsContextLost()) return;
    157 
    158  mDepthWriteMask = b;
    159  gl->fDepthMask(b);
    160 }
    161 
    162 void WebGLContext::DrawBuffers(const std::vector<GLenum>& buffers) {
    163  const FuncScope funcScope(*this, "drawBuffers");
    164  if (IsContextLost()) return;
    165 
    166  if (mBoundDrawFramebuffer) {
    167    mBoundDrawFramebuffer->DrawBuffers(buffers);
    168    return;
    169  }
    170 
    171  // GLES 3.0.4 p186:
    172  // "If the GL is bound to the default framebuffer, then `n` must be 1 and the
    173  //  constant must be BACK or NONE. [...] If DrawBuffers is supplied with a
    174  //  constant other than BACK and NONE, or with a value of `n` other than 1,
    175  //  the error INVALID_OPERATION is generated."
    176  if (buffers.size() != 1) {
    177    ErrorInvalidOperation(
    178        "For the default framebuffer, `buffers` must have a"
    179        " length of 1.");
    180    return;
    181  }
    182 
    183  switch (buffers[0]) {
    184    case LOCAL_GL_NONE:
    185    case LOCAL_GL_BACK:
    186      break;
    187 
    188    default:
    189      ErrorInvalidOperation(
    190          "For the default framebuffer, `buffers[0]` must be"
    191          " BACK or NONE.");
    192      return;
    193  }
    194 
    195  mDefaultFB_DrawBuffer0 = buffers[0];
    196  // Don't actually set it.
    197 }
    198 
    199 void WebGLContext::StencilMaskSeparate(GLenum face, GLuint mask) {
    200  const FuncScope funcScope(*this, "stencilMaskSeparate");
    201  if (IsContextLost()) return;
    202 
    203  if (!ValidateFaceEnum(face)) return;
    204 
    205  switch (face) {
    206    case LOCAL_GL_FRONT_AND_BACK:
    207      mStencilWriteMaskFront = mask;
    208      mStencilWriteMaskBack = mask;
    209      break;
    210    case LOCAL_GL_FRONT:
    211      mStencilWriteMaskFront = mask;
    212      break;
    213    case LOCAL_GL_BACK:
    214      mStencilWriteMaskBack = mask;
    215      break;
    216  }
    217 
    218  gl->fStencilMaskSeparate(face, mask);
    219 }
    220 
    221 }  // namespace mozilla