Bug 1857841 - pt 3. Add a new page kind named "fresh" r=glandium
[gecko.git] / dom / webgpu / Texture.cpp
blobc7bc4061181a1bf1a1ff023b71c07b34f0b214b6
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/. */
6 #include "Texture.h"
8 #include "ipc/WebGPUChild.h"
9 #include "mozilla/webgpu/ffi/wgpu.h"
10 #include "mozilla/webgpu/CanvasContext.h"
11 #include "mozilla/dom/WebGPUBinding.h"
12 #include "mozilla/webgpu/WebGPUTypes.h"
13 #include "TextureView.h"
14 #include "Utility.h"
16 namespace mozilla::webgpu {
18 GPU_IMPL_CYCLE_COLLECTION(Texture, mParent)
19 GPU_IMPL_JS_WRAP(Texture)
21 static Maybe<uint8_t> GetBytesPerBlockSingleAspect(
22 dom::GPUTextureFormat aFormat) {
23 auto format = ConvertTextureFormat(aFormat);
24 uint32_t bytes = ffi::wgpu_texture_format_block_size_single_aspect(format);
25 if (bytes == 0) {
26 // The above function returns zero if the texture has multiple aspects like
27 // depth and stencil.
28 return Nothing();
31 return Some((uint8_t)bytes);
34 Texture::Texture(Device* const aParent, RawId aId,
35 const dom::GPUTextureDescriptor& aDesc)
36 : ChildOf(aParent),
37 mId(aId),
38 mFormat(aDesc.mFormat),
39 mBytesPerBlock(GetBytesPerBlockSingleAspect(aDesc.mFormat)),
40 mSize(ConvertExtent(aDesc.mSize)),
41 mMipLevelCount(aDesc.mMipLevelCount),
42 mSampleCount(aDesc.mSampleCount),
43 mDimension(aDesc.mDimension),
44 mUsage(aDesc.mUsage) {
45 MOZ_RELEASE_ASSERT(aId);
48 void Texture::Cleanup() {
49 if (!mParent) {
50 return;
53 auto bridge = mParent->GetBridge();
54 if (bridge && bridge->IsOpen()) {
55 bridge->SendTextureDrop(mId);
58 // After cleanup is called, no other method should ever be called on the
59 // object so we don't have to null-check mParent in other places.
60 // This serves the purpose of preventing SendTextureDrop from happening
61 // twice. TODO: Does it matter for breaking cycles too? Cleanup is called
62 // by the macros that deal with cycle colleciton.
63 mParent = nullptr;
66 Texture::~Texture() { Cleanup(); }
68 already_AddRefed<TextureView> Texture::CreateView(
69 const dom::GPUTextureViewDescriptor& aDesc) {
70 auto bridge = mParent->GetBridge();
72 ffi::WGPUTextureViewDescriptor desc = {};
74 webgpu::StringHelper label(aDesc.mLabel);
75 desc.label = label.Get();
77 ffi::WGPUTextureFormat format = {ffi::WGPUTextureFormat_Sentinel};
78 if (aDesc.mFormat.WasPassed()) {
79 format = ConvertTextureFormat(aDesc.mFormat.Value());
80 desc.format = &format;
82 ffi::WGPUTextureViewDimension dimension =
83 ffi::WGPUTextureViewDimension_Sentinel;
84 if (aDesc.mDimension.WasPassed()) {
85 dimension = ffi::WGPUTextureViewDimension(aDesc.mDimension.Value());
86 desc.dimension = &dimension;
89 // Ideally we'd just do something like "aDesc.mMipLevelCount.ptrOr(nullptr)"
90 // but dom::Optional does not seem to have very many nice things.
91 uint32_t mipCount =
92 aDesc.mMipLevelCount.WasPassed() ? aDesc.mMipLevelCount.Value() : 0;
93 uint32_t layerCount =
94 aDesc.mArrayLayerCount.WasPassed() ? aDesc.mArrayLayerCount.Value() : 0;
96 desc.aspect = ffi::WGPUTextureAspect(aDesc.mAspect);
97 desc.base_mip_level = aDesc.mBaseMipLevel;
98 desc.mip_level_count = aDesc.mMipLevelCount.WasPassed() ? &mipCount : nullptr;
99 desc.base_array_layer = aDesc.mBaseArrayLayer;
100 desc.array_layer_count =
101 aDesc.mArrayLayerCount.WasPassed() ? &layerCount : nullptr;
103 ipc::ByteBuf bb;
104 RawId id = ffi::wgpu_client_create_texture_view(bridge->GetClient(), mId,
105 &desc, ToFFI(&bb));
106 if (bridge->CanSend()) {
107 bridge->SendTextureAction(mId, mParent->mId, std::move(bb));
110 RefPtr<TextureView> view = new TextureView(this, id);
111 return view.forget();
114 void Texture::Destroy() {
115 auto bridge = mParent->GetBridge();
116 if (bridge && bridge->IsOpen()) {
117 bridge->SendTextureDestroy(mId, mParent->GetId());
121 } // namespace mozilla::webgpu