tor-browser

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

Buffer.h (5952B)


      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 GPU_BUFFER_H_
      7 #define GPU_BUFFER_H_
      8 
      9 #include <memory>
     10 
     11 #include "ObjectModel.h"
     12 #include "js/RootingAPI.h"
     13 #include "mozilla/dom/Nullable.h"
     14 #include "mozilla/ipc/SharedMemoryMapping.h"
     15 #include "mozilla/webgpu/WebGPUTypes.h"
     16 #include "nsTArray.h"
     17 
     18 namespace mozilla {
     19 namespace webgpu {
     20 struct MappedView;
     21 }  // namespace webgpu
     22 }  // namespace mozilla
     23 
     24 // Give `nsTArray` some advice on how to handle `MappedInfo::mViews`.
     25 //
     26 // In the `mozilla::webgpu` namespace, `MappedInfo::mViews` is an
     27 // `nsTArray<MappedView>`, and `MappedView::mArrayBuffer` is a `JS::Heap`
     28 // pointer. This arrangement requires special handling.
     29 //
     30 // Normally, `nsTArray` wants its element type to be movable with simple byte
     31 // copies, so that an `nsTArray` can efficiently resize its element buffer.
     32 // However, `JS::Heap` is marked `MOZ_NON_MEMMOVABLE`, meaning that it cannot be
     33 // safely moved by a simple byte-by-byte copy. Normally, this would cause
     34 // `nsTArray` to reject `JS::Heap` as an element type, but `nsTArray.h`
     35 // specializes `nsTArray_RelocationStrategy` to indicate that `JS::Heap` can be
     36 // moved safely using its move constructor. This causes `nsTArray<JS::Heap<T>>`
     37 // to perform element buffer moves using element-by-element move constructor
     38 // application: slower, but safe for `JS::Heap`.
     39 //
     40 // However, while `MappedView` is automatically marked `MOZ_NON_MEMMOVABLE`
     41 // because of its `mArrayBuffer` member, the `nsTArray_RelocationStrategy`
     42 // specialization is not somehow similarly magically carried over from
     43 // `JS::Heap` to `MappedView`. To use `MappedView` in `nsTArray`, we must spell
     44 // out a relocation strategy for it.
     45 template <>
     46 struct nsTArray_RelocationStrategy<mozilla::webgpu::MappedView> {
     47  // The default move constructors are fine for MappedView.
     48  using Type =
     49      nsTArray_RelocateUsingMoveConstructor<mozilla::webgpu::MappedView>;
     50 };
     51 
     52 namespace mozilla {
     53 class ErrorResult;
     54 
     55 namespace dom {
     56 struct GPUBufferDescriptor;
     57 template <typename T>
     58 class Optional;
     59 enum class GPUBufferMapState : uint8_t;
     60 }  // namespace dom
     61 
     62 namespace webgpu {
     63 
     64 class Device;
     65 
     66 // A portion of the current mapped buffer range that is currently
     67 // visible to JS as an ArrayBuffer.
     68 struct MappedView {
     69  BufferAddress mOffset;
     70  BufferAddress mRangeEnd;
     71  JS::Heap<JSObject*> mArrayBuffer;
     72 
     73  MappedView(BufferAddress aOffset, BufferAddress aRangeEnd,
     74             JSObject* aArrayBuffer)
     75      : mOffset(aOffset), mRangeEnd(aRangeEnd), mArrayBuffer(aArrayBuffer) {}
     76 };
     77 
     78 struct MappedInfo {
     79  // True if mapping is requested for writing.
     80  bool mWritable = false;
     81  // Populated by `GetMappedRange`.
     82  nsTArray<MappedView> mViews;
     83  BufferAddress mOffset;
     84  BufferAddress mSize;
     85  MappedInfo() = default;
     86  MappedInfo(const MappedInfo&) = delete;
     87 };
     88 
     89 class Buffer final : public nsWrapperCache,
     90                     public ObjectBase,
     91                     public ChildOf<Device> {
     92 public:
     93  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(Buffer)
     94  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Buffer)
     95  GPU_DECL_JS_WRAP(Buffer)
     96 
     97  static already_AddRefed<Buffer> Create(Device* aDevice, RawId aDeviceId,
     98                                         const dom::GPUBufferDescriptor& aDesc,
     99                                         ErrorResult& aRv);
    100 
    101  already_AddRefed<dom::Promise> MapAsync(uint32_t aMode, uint64_t aOffset,
    102                                          const dom::Optional<uint64_t>& aSize,
    103                                          ErrorResult& aRv);
    104  void GetMappedRange(JSContext* aCx, uint64_t aOffset,
    105                      const dom::Optional<uint64_t>& aSize,
    106                      JS::Rooted<JSObject*>* aObject, ErrorResult& aRv);
    107  void Unmap(JSContext* aCx, ErrorResult& aRv);
    108  void Destroy(JSContext* aCx, ErrorResult& aRv);
    109 
    110  uint64_t Size() const { return mSize; }
    111  uint32_t Usage() const { return mUsage; }
    112  dom::GPUBufferMapState MapState() const;
    113 
    114  void ResolveMapRequest(dom::Promise* aPromise, BufferAddress aOffset,
    115                         BufferAddress aSize, bool aWritable);
    116  void RejectMapRequest(dom::Promise* aPromise, const nsACString& message);
    117  void RejectMapRequestWithAbortError(dom::Promise* aPromise);
    118 
    119 private:
    120  Buffer(Device* const aParent, RawId aId, BufferAddress aSize, uint32_t aUsage,
    121         ipc::SharedMemoryMapping&& aShmem);
    122  virtual ~Buffer();
    123  void Cleanup();
    124  void UnmapArrayBuffers(JSContext* aCx, ErrorResult& aRv);
    125  void AbortMapRequest();
    126  void SetMapped(BufferAddress aOffset, BufferAddress aSize, bool aWritable);
    127 
    128  bool mValid = true;
    129  // Note: we can't map a buffer with the size that don't fit into `size_t`
    130  // (which may be smaller than `BufferAddress`), but general not all buffers
    131  // are mapped.
    132  const BufferAddress mSize;
    133  const uint32_t mUsage;
    134  nsString mLabel;
    135  // Information about the currently active mapping.
    136  Maybe<MappedInfo> mMapped;
    137  RefPtr<dom::Promise> mMapRequest;
    138 
    139  // A shared memory mapping for the entire buffer, or a zero-length
    140  // mapping.
    141  //
    142  // If `mUsage` contains `MAP_READ` or `MAP_WRITE`, this mapping is
    143  // created at `Buffer` construction, and destroyed at `Buffer`
    144  // destruction.
    145  //
    146  // If `mUsage` contains neither of those flags, but `this` is mapped
    147  // at creation, this mapping is created at `Buffer` construction,
    148  // and destroyed when we first unmap the buffer, by clearing this
    149  // `shared_ptr`.
    150  //
    151  // Otherwise, this points to `SharedMemoryMapping()` (the default
    152  // constructor), a zero-length mapping that doesn't point to any shared
    153  // memory.
    154  std::shared_ptr<ipc::SharedMemoryMapping> mShmem;
    155 };
    156 
    157 }  // namespace webgpu
    158 }  // namespace mozilla
    159 
    160 #endif  // GPU_BUFFER_H_