tor-browser

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

WebGLTexture.h (11309B)


      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 #ifndef WEBGL_TEXTURE_H_
      7 #define WEBGL_TEXTURE_H_
      8 
      9 #include <algorithm>
     10 #include <vector>
     11 
     12 #include "CacheInvalidator.h"
     13 #include "WebGLObjectModel.h"
     14 #include "WebGLStrongTypes.h"
     15 #include "WebGLTypes.h"
     16 #include "mozilla/Assertions.h"
     17 #include "mozilla/dom/TypedArray.h"
     18 
     19 namespace mozilla {
     20 class ErrorResult;
     21 class WebGLContext;
     22 class WebGLFramebuffer;
     23 class WebGLSampler;
     24 struct FloatOrInt;
     25 struct TexImageSource;
     26 
     27 namespace dom {
     28 class Element;
     29 class HTMLVideoElement;
     30 class ImageData;
     31 class ArrayBufferViewOrSharedArrayBufferView;
     32 }  // namespace dom
     33 
     34 namespace layers {
     35 class Image;
     36 }  // namespace layers
     37 
     38 namespace webgl {
     39 struct DriverUnpackInfo;
     40 struct FormatUsageInfo;
     41 struct PackingInfo;
     42 class TexUnpackBlob;
     43 }  // namespace webgl
     44 
     45 bool DoesTargetMatchDimensions(WebGLContext* webgl, TexImageTarget target,
     46                               uint8_t dims);
     47 
     48 namespace webgl {
     49 
     50 struct SamplingState final {
     51  // Only store that which changes validation.
     52  TexMinFilter minFilter = LOCAL_GL_NEAREST_MIPMAP_LINEAR;
     53  TexMagFilter magFilter = LOCAL_GL_LINEAR;
     54  TexWrap wrapS = LOCAL_GL_REPEAT;
     55  TexWrap wrapT = LOCAL_GL_REPEAT;
     56  // TexWrap wrapR = LOCAL_GL_REPEAT;
     57  // GLfloat minLod = -1000;
     58  // GLfloat maxLod = 1000;
     59  TexCompareMode compareMode = LOCAL_GL_NONE;
     60  // TexCompareFunc compareFunc = LOCAL_GL_LEQUAL;
     61 };
     62 
     63 struct ImageInfo final {
     64  static const ImageInfo kUndefined;
     65 
     66  const webgl::FormatUsageInfo* mFormat = nullptr;
     67  uint32_t mWidth = 0;
     68  uint32_t mHeight = 0;
     69  uint32_t mDepth = 0;
     70  mutable std::optional<std::vector<bool>> mUninitializedSlices;
     71  uint8_t mSamples = 0;
     72 
     73  // -
     74 
     75  size_t MemoryUsage() const;
     76 
     77  bool IsDefined() const {
     78    if (!mFormat) {
     79      MOZ_ASSERT(!mWidth && !mHeight && !mDepth);
     80      return false;
     81    }
     82 
     83    return true;
     84  }
     85 
     86  Maybe<ImageInfo> NextMip(GLenum target) const;
     87 };
     88 
     89 }  // namespace webgl
     90 
     91 class WebGLTexture final : public WebGLContextBoundObject,
     92                           public CacheInvalidator {
     93  // Friends
     94  friend class WebGLContext;
     95  friend class WebGLFramebuffer;
     96 
     97  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(WebGLTexture, override)
     98 
     99  ////////////////////////////////////
    100  // Members
    101 public:
    102  const GLuint mGLName;
    103 
    104 protected:
    105  TexTarget mTarget;
    106 
    107  static const uint8_t kMaxFaceCount = 6;
    108  uint8_t mFaceCount;  // 6 for cube maps, 1 otherwise.
    109 
    110  bool mImmutable;  // Set by texStorage*
    111  uint8_t mImmutableLevelCount;
    112 
    113  uint32_t mBaseMipmapLevel;  // Set by texParameter (defaults to 0)
    114  uint32_t mMaxMipmapLevel;   // Set by texParameter (defaults to 1000)
    115  // You almost certainly don't want to query mMaxMipmapLevel.
    116  // You almost certainly want MaxEffectiveMipmapLevel().
    117 
    118  // These "dirty" flags are set when the level is updated (eg indirectly by
    119  // clamping) and cleared when we tell the driver.
    120  enum MipmapLevelState : uint8_t {
    121    MIPMAP_LEVEL_DEFAULT,
    122    MIPMAP_LEVEL_CLEAN,
    123    MIPMAP_LEVEL_DIRTY
    124  };
    125  MipmapLevelState mBaseMipmapLevelState = MIPMAP_LEVEL_DEFAULT;
    126  MipmapLevelState mMaxMipmapLevelState = MIPMAP_LEVEL_DEFAULT;
    127 
    128  webgl::SamplingState mSamplingState;
    129 
    130  mutable const GLint* mCurSwizzle =
    131      nullptr;  // nullptr means 'default swizzle'.
    132 
    133  // -
    134 
    135  struct CompletenessInfo final {
    136    uint8_t levels = 0;
    137    bool powerOfTwo = false;
    138    bool mipmapComplete = false;
    139    const webgl::FormatUsageInfo* usage = nullptr;
    140    const char* incompleteReason = nullptr;
    141  };
    142 
    143  mutable CacheWeakMap<const WebGLSampler*, webgl::SampleableInfo>
    144      mSamplingCache;
    145 
    146 public:
    147  Maybe<const CompletenessInfo> CalcCompletenessInfo(
    148      bool ensureInit, bool skipMips = false) const;
    149  Maybe<const webgl::SampleableInfo> CalcSampleableInfo(
    150      const WebGLSampler*) const;
    151 
    152  const webgl::SampleableInfo* GetSampleableInfo(const WebGLSampler*) const;
    153 
    154  // -
    155 
    156  const auto& Immutable() const { return mImmutable; }
    157  const auto& ImmutableLevelCount() const { return mImmutableLevelCount; }
    158 
    159  // ES3.0 p150
    160  uint32_t Es3_level_base() const {
    161    const auto level_prime_base = mBaseMipmapLevel;
    162    const auto level_immut = mImmutableLevelCount;
    163 
    164    if (!mImmutable) return level_prime_base;
    165    return std::min(level_prime_base, level_immut - 1u);
    166  }
    167  uint32_t Es3_level_max() const {
    168    const auto level_base = Es3_level_base();
    169    const auto level_prime_max = mMaxMipmapLevel;
    170    const auto level_immut = mImmutableLevelCount;
    171 
    172    if (!mImmutable) return level_prime_max;
    173    return std::clamp(level_base, level_prime_max, level_immut - 1u);
    174  }
    175 
    176  // GLES 3.0.5 p158: `q`
    177  uint32_t Es3_q() const;  // "effective max mip level"
    178 
    179  // -
    180 
    181  const auto& FaceCount() const { return mFaceCount; }
    182 
    183  // We can just max this out to 31, which is the number of unsigned bits in
    184  // GLsizei.
    185  static const uint8_t kMaxLevelCount = 31;
    186 
    187  // We store information about the various images that are part of this
    188  // texture. (cubemap faces, mipmap levels)
    189  webgl::ImageInfo mImageInfoArr[kMaxLevelCount * kMaxFaceCount];
    190 
    191  ////////////////////////////////////
    192 
    193  WebGLTexture(WebGLContext* webgl, GLuint tex);
    194 
    195  TexTarget Target() const { return mTarget; }
    196 
    197 protected:
    198  ~WebGLTexture() override;
    199 
    200 public:
    201  size_t SizeOfExcludingThis(mozilla::MallocSizeOf mso) const {
    202    return CacheInvalidator::SizeOfExcludingThis(mso) +
    203           mSamplingCache.SizeOfExcludingThis(mso);
    204  }
    205  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mso) const {
    206    return mso(this) + SizeOfExcludingThis(mso);
    207  }
    208 
    209  ////////////////////////////////////
    210  // GL calls
    211  bool BindTexture(TexTarget texTarget);
    212  void GenerateMipmap();
    213  Maybe<double> GetTexParameter(GLenum pname) const;
    214  void TexParameter(TexTarget texTarget, GLenum pname, const FloatOrInt& param);
    215 
    216  ////////////////////////////////////
    217  // WebGLTextureUpload.cpp
    218 
    219 protected:
    220  void TexOrSubImageBlob(bool isSubImage, TexImageTarget target, GLint level,
    221                         GLenum internalFormat, GLint xOffset, GLint yOffset,
    222                         GLint zOffset, const webgl::PackingInfo& pi,
    223                         const webgl::TexUnpackBlob* blob);
    224 
    225  bool ValidateTexImageSpecification(TexImageTarget target, uint32_t level,
    226                                     const uvec3& size,
    227                                     webgl::ImageInfo** const out_imageInfo);
    228  bool ValidateTexImageSelection(TexImageTarget target, uint32_t level,
    229                                 const uvec3& offset, const uvec3& size,
    230                                 webgl::ImageInfo** const out_imageInfo);
    231 
    232  bool ValidateUnpack(const webgl::TexUnpackBlob* blob, bool isFunc3D,
    233                      const webgl::PackingInfo& srcPI) const;
    234 
    235 public:
    236  void TexStorage(TexTarget target, uint32_t levels, GLenum sizedFormat,
    237                  const uvec3& size);
    238 
    239  // TexSubImage iff `!respecFormat`
    240  void TexImage(uint32_t level, GLenum respecFormat, const uvec3& offset,
    241                const webgl::PackingInfo& pi, const webgl::TexUnpackBlobDesc&);
    242 
    243  // CompressedTexSubImage iff `sub`
    244  void CompressedTexImage(bool sub, GLenum imageTarget, uint32_t level,
    245                          GLenum formatEnum, const uvec3& offset,
    246                          const uvec3& size, const Range<const uint8_t>& src,
    247                          const uint32_t pboImageSize,
    248                          const Maybe<uint64_t>& pboOffset);
    249 
    250  // CopyTexSubImage iff `!respecFormat`
    251  void CopyTexImage(GLenum imageTarget, uint32_t level, GLenum respecFormat,
    252                    const uvec3& dstOffset, const ivec2& srcOffset,
    253                    const uvec2& size2);
    254 
    255  ////////////////////////////////////
    256 
    257 protected:
    258  void ClampLevelBaseAndMax();
    259  void RefreshSwizzle() const;
    260 
    261  static uint8_t FaceForTarget(TexImageTarget texImageTarget) {
    262    GLenum rawTexImageTarget = texImageTarget.get();
    263    switch (rawTexImageTarget) {
    264      case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
    265      case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    266      case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
    267      case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    268      case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
    269      case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
    270        return AutoAssertCast(rawTexImageTarget -
    271                              LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X);
    272 
    273      default:
    274        return 0;
    275    }
    276  }
    277 
    278 public:
    279  auto& ImageInfoAtFace(uint8_t face, uint32_t level) {
    280    MOZ_ASSERT(face < mFaceCount);
    281    MOZ_ASSERT(level < kMaxLevelCount);
    282    size_t pos = (level * mFaceCount) + face;
    283    return mImageInfoArr[pos];
    284  }
    285 
    286  const auto& ImageInfoAtFace(uint8_t face, uint32_t level) const {
    287    return const_cast<WebGLTexture*>(this)->ImageInfoAtFace(face, level);
    288  }
    289 
    290  auto& ImageInfoAt(TexImageTarget texImageTarget, GLint level) {
    291    const auto& face = FaceForTarget(texImageTarget);
    292    return ImageInfoAtFace(face, level);
    293  }
    294 
    295  const auto& ImageInfoAt(TexImageTarget texImageTarget, GLint level) const {
    296    return const_cast<WebGLTexture*>(this)->ImageInfoAt(texImageTarget, level);
    297  }
    298 
    299  const auto& BaseImageInfo() const {
    300    if (mBaseMipmapLevel >= kMaxLevelCount) return webgl::ImageInfo::kUndefined;
    301 
    302    return ImageInfoAtFace(0, mBaseMipmapLevel);
    303  }
    304 
    305  size_t MemoryUsage() const;
    306 
    307  bool EnsureImageDataInitialized(TexImageTarget target, uint32_t level);
    308  void PopulateMipChain(uint32_t maxLevel);
    309  bool IsMipAndCubeComplete(uint32_t maxLevel, bool ensureInit,
    310                            bool* out_initFailed) const;
    311  void Truncate();
    312 
    313  bool IsCubeMap() const { return (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP); }
    314 };
    315 
    316 inline TexImageTarget TexImageTargetForTargetAndFace(TexTarget target,
    317                                                     uint8_t face) {
    318  switch (target.get()) {
    319    case LOCAL_GL_TEXTURE_2D:
    320    case LOCAL_GL_TEXTURE_3D:
    321      MOZ_ASSERT(face == 0);
    322      return target.get();
    323    case LOCAL_GL_TEXTURE_CUBE_MAP:
    324      MOZ_ASSERT(face < 6);
    325      return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
    326    default:
    327      MOZ_CRASH("GFX: TexImageTargetForTargetAndFace");
    328  }
    329 }
    330 
    331 already_AddRefed<mozilla::layers::Image> ImageFromVideo(
    332    dom::HTMLVideoElement* elem);
    333 
    334 bool IsTarget3D(TexImageTarget target);
    335 
    336 GLenum DoTexImage(gl::GLContext* gl, TexImageTarget target, GLint level,
    337                  const webgl::DriverUnpackInfo* dui, GLsizei width,
    338                  GLsizei height, GLsizei depth, const void* data);
    339 GLenum DoTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level,
    340                     GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width,
    341                     GLsizei height, GLsizei depth,
    342                     const webgl::PackingInfo& pi, const void* data);
    343 GLenum DoCompressedTexSubImage(gl::GLContext* gl, TexImageTarget target,
    344                               GLint level, GLint xOffset, GLint yOffset,
    345                               GLint zOffset, GLsizei width, GLsizei height,
    346                               GLsizei depth, GLenum sizedUnpackFormat,
    347                               GLsizei dataSize, const void* data);
    348 
    349 }  // namespace mozilla
    350 
    351 #endif  // WEBGL_TEXTURE_H_