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/. */
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"
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
);
26 // The above function returns zero if the texture has multiple aspects like
31 return Some((uint8_t)bytes
);
34 Texture::Texture(Device
* const aParent
, RawId aId
,
35 const dom::GPUTextureDescriptor
& aDesc
)
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() {
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.
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.
92 aDesc
.mMipLevelCount
.WasPassed() ? aDesc
.mMipLevelCount
.Value() : 0;
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;
104 RawId id
= ffi::wgpu_client_create_texture_view(bridge
->GetClient(), mId
,
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