tor-browser

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

WebGLContextTextures.cpp (7443B)


      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 "CanvasUtils.h"
      7 #include "GLContext.h"
      8 #include "WebGLBuffer.h"
      9 #include "WebGLContext.h"
     10 #include "WebGLContextUtils.h"
     11 #include "WebGLExtensions.h"
     12 #include "WebGLFramebuffer.h"
     13 #include "WebGLProgram.h"
     14 #include "WebGLRenderbuffer.h"
     15 #include "WebGLShader.h"
     16 #include "WebGLTexelConversions.h"
     17 #include "WebGLTexture.h"
     18 #include "WebGLValidateStrings.h"
     19 #include "WebGLVertexArray.h"
     20 #include "gfxContext.h"
     21 #include "gfxPlatform.h"
     22 #include "gfxUtils.h"
     23 #include "jsfriendapi.h"
     24 #include "mozilla/dom/BindingUtils.h"
     25 #include "mozilla/dom/ImageData.h"
     26 #include "nsContentUtils.h"
     27 #include "nsDebug.h"
     28 #include "nsError.h"
     29 #include "nsLayoutUtils.h"
     30 #include "nsReadableUtils.h"
     31 #include "nsString.h"
     32 
     33 namespace mozilla {
     34 
     35 /*virtual*/
     36 bool WebGLContext::IsTexParamValid(GLenum pname) const {
     37  switch (pname) {
     38    case LOCAL_GL_TEXTURE_MIN_FILTER:
     39    case LOCAL_GL_TEXTURE_MAG_FILTER:
     40    case LOCAL_GL_TEXTURE_WRAP_S:
     41    case LOCAL_GL_TEXTURE_WRAP_T:
     42      return true;
     43 
     44    case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
     45      return IsExtensionEnabled(
     46          WebGLExtensionID::EXT_texture_filter_anisotropic);
     47 
     48    default:
     49      return false;
     50  }
     51 }
     52 
     53 //////////////////////////////////////////////////////////////////////////////////////////
     54 // GL calls
     55 
     56 void WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex) {
     57  FuncScope funcScope(*this, "bindTexture");
     58  if (IsContextLost()) return;
     59  funcScope.mBindFailureGuard = true;
     60 
     61  if (newTex && !ValidateObject("tex", *newTex)) return;
     62 
     63  // Need to check rawTarget first before comparing against newTex->Target() as
     64  // newTex->Target() returns a TexTarget, which will assert on invalid value.
     65  RefPtr<WebGLTexture>* currentTexPtr = nullptr;
     66  switch (rawTarget) {
     67    case LOCAL_GL_TEXTURE_2D:
     68      currentTexPtr = &mBound2DTextures[mActiveTexture];
     69      break;
     70 
     71    case LOCAL_GL_TEXTURE_CUBE_MAP:
     72      currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
     73      break;
     74 
     75    case LOCAL_GL_TEXTURE_3D:
     76      if (IsWebGL2()) currentTexPtr = &mBound3DTextures[mActiveTexture];
     77      break;
     78 
     79    case LOCAL_GL_TEXTURE_2D_ARRAY:
     80      if (IsWebGL2()) currentTexPtr = &mBound2DArrayTextures[mActiveTexture];
     81      break;
     82  }
     83 
     84  if (!currentTexPtr) {
     85    ErrorInvalidEnumInfo("target", rawTarget);
     86    return;
     87  }
     88 
     89  const auto texTarget = TexTarget(rawTarget);
     90  if (newTex) {
     91    if (!newTex->BindTexture(texTarget)) return;
     92  } else {
     93    gl->fBindTexture(texTarget.get(), 0);
     94  }
     95 
     96  *currentTexPtr = newTex;
     97 
     98  funcScope.mBindFailureGuard = false;
     99 }
    100 
    101 void WebGLContext::GenerateMipmap(GLenum texTarget) {
    102  const FuncScope funcScope(*this, "generateMipmap");
    103 
    104  const auto& tex = GetActiveTex(texTarget);
    105  if (!tex) return;
    106  tex->GenerateMipmap();
    107 }
    108 
    109 Maybe<double> WebGLContext::GetTexParameter(const WebGLTexture& tex,
    110                                            GLenum pname) const {
    111  const FuncScope funcScope(*this, "getTexParameter");
    112 
    113  if (!IsTexParamValid(pname)) {
    114    ErrorInvalidEnumInfo("pname", pname);
    115    return Nothing();
    116  }
    117 
    118  return tex.GetTexParameter(pname);
    119 }
    120 
    121 void WebGLContext::TexParameter_base(GLenum texTarget, GLenum pname,
    122                                     const FloatOrInt& param) {
    123  const FuncScope funcScope(*this, "texParameter");
    124 
    125  const auto& tex = GetActiveTex(texTarget);
    126  if (!tex) return;
    127  tex->TexParameter(texTarget, pname, param);
    128 }
    129 
    130 //////////////////////////////////////////////////////////////////////////////////////////
    131 // Uploads
    132 
    133 WebGLTexture* WebGLContext::GetActiveTex(const GLenum texTarget) const {
    134  const auto* list = &mBound2DTextures;
    135  switch (texTarget) {
    136    case LOCAL_GL_TEXTURE_2D:
    137      break;
    138    case LOCAL_GL_TEXTURE_CUBE_MAP:
    139      list = &mBoundCubeMapTextures;
    140      break;
    141    case LOCAL_GL_TEXTURE_3D:
    142      list = IsWebGL2() ? &mBound3DTextures : nullptr;
    143      break;
    144    case LOCAL_GL_TEXTURE_2D_ARRAY:
    145      list = IsWebGL2() ? &mBound2DArrayTextures : nullptr;
    146      break;
    147    default:
    148      list = nullptr;
    149  }
    150  if (!list) {
    151    ErrorInvalidEnumArg("target", texTarget);
    152    return nullptr;
    153  }
    154  const auto& tex = (*list)[mActiveTexture];
    155  if (!tex) {
    156    GenerateError(LOCAL_GL_INVALID_OPERATION, "No texture bound to %s[%u].",
    157                  EnumString(texTarget).c_str(), mActiveTexture);
    158    return nullptr;
    159  }
    160  return tex;
    161 }
    162 
    163 void WebGLContext::TexStorage(GLenum texTarget, uint32_t levels,
    164                              GLenum internalFormat, uvec3 size) const {
    165  const FuncScope funcScope(*this, "texStorage(Multisample)?");
    166  if (!IsTexTarget3D(texTarget)) {
    167    size.z = 1;
    168  }
    169  const auto tex = GetActiveTex(texTarget);
    170  if (!tex) return;
    171  tex->TexStorage(texTarget, levels, internalFormat, size);
    172 }
    173 
    174 void WebGLContext::TexImage(uint32_t level, GLenum respecFormat, uvec3 offset,
    175                            const webgl::PackingInfo& pi,
    176                            const webgl::TexUnpackBlobDesc& src) const {
    177  const WebGLContext::FuncScope funcScope(
    178      *this, bool(respecFormat) ? "texImage" : "texSubImage");
    179 
    180  const bool isUploadFromPbo = bool(src.pboOffset);
    181  const bool isPboBound = bool(mBoundPixelUnpackBuffer);
    182  if (isUploadFromPbo != isPboBound) {
    183    GenerateError(LOCAL_GL_INVALID_OPERATION,
    184                  "Tex upload from %s but PIXEL_UNPACK_BUFFER %s bound.",
    185                  isUploadFromPbo ? "PBO" : "non-PBO",
    186                  isPboBound ? "was" : "was not");
    187    return;
    188  }
    189 
    190  if (respecFormat) {
    191    offset = {0, 0, 0};
    192  }
    193  const auto texTarget = ImageToTexTarget(src.imageTarget);
    194  const auto tex = GetActiveTex(texTarget);
    195  if (!tex) return;
    196  tex->TexImage(level, respecFormat, offset, pi, src);
    197 }
    198 
    199 void WebGLContext::CompressedTexImage(bool sub, GLenum imageTarget,
    200                                      uint32_t level, GLenum format,
    201                                      uvec3 offset, uvec3 size,
    202                                      const Range<const uint8_t>& src,
    203                                      const uint32_t pboImageSize,
    204                                      const Maybe<uint64_t>& pboOffset) const {
    205  const WebGLContext::FuncScope funcScope(
    206      *this, !sub ? "compressedTexImage" : "compressedTexSubImage");
    207 
    208  if (!sub) {
    209    offset = {0, 0, 0};
    210  }
    211  const auto texTarget = ImageToTexTarget(imageTarget);
    212  if (!IsTexTarget3D(texTarget)) {
    213    size.z = 1;
    214  }
    215  const auto tex = GetActiveTex(texTarget);
    216  if (!tex) return;
    217  tex->CompressedTexImage(sub, imageTarget, level, format, offset, size, src,
    218                          pboImageSize, pboOffset);
    219 }
    220 
    221 void WebGLContext::CopyTexImage(GLenum imageTarget, uint32_t level,
    222                                GLenum respecFormat, uvec3 dstOffset,
    223                                const ivec2& srcOffset,
    224                                const uvec2& size) const {
    225  const WebGLContext::FuncScope funcScope(
    226      *this, bool(respecFormat) ? "copyTexImage" : "copyTexSubImage");
    227 
    228  if (respecFormat) {
    229    dstOffset = {0, 0, 0};
    230  }
    231  const auto tex = GetActiveTex(ImageToTexTarget(imageTarget));
    232  if (!tex) return;
    233  tex->CopyTexImage(imageTarget, level, respecFormat, dstOffset, srcOffset,
    234                    size);
    235 }
    236 
    237 }  // namespace mozilla