Bug 1732219 - Add API for fetching the preview image. r=geckoview-reviewers,agi,mconley
[gecko.git] / dom / webgpu / CanvasContext.cpp
blob6d73b4b9853fac24e9faec1180aa044018b1127e
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 "mozilla/dom/WebGPUBinding.h"
7 #include "CanvasContext.h"
8 #include "nsDisplayList.h"
9 #include "LayerUserData.h"
10 #include "mozilla/dom/HTMLCanvasElement.h"
11 #include "mozilla/layers/CompositorManagerChild.h"
12 #include "mozilla/layers/ImageDataSerializer.h"
13 #include "mozilla/layers/LayersSurfaces.h"
14 #include "mozilla/layers/RenderRootStateManager.h"
15 #include "mozilla/layers/WebRenderBridgeChild.h"
16 #include "ipc/WebGPUChild.h"
18 namespace mozilla {
19 namespace webgpu {
21 NS_IMPL_CYCLE_COLLECTING_ADDREF(CanvasContext)
22 NS_IMPL_CYCLE_COLLECTING_RELEASE(CanvasContext)
24 GPU_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CanvasContext, mTexture, mBridge,
25 mCanvasElement, mOffscreenCanvas)
27 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CanvasContext)
28 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
29 NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
30 NS_INTERFACE_MAP_ENTRY(nsISupports)
31 NS_INTERFACE_MAP_END
33 CanvasContext::CanvasContext()
34 : mExternalImageId(layers::CompositorManagerChild::GetInstance()
35 ->GetNextExternalImageId()) {}
37 CanvasContext::~CanvasContext() {
38 Cleanup();
39 RemovePostRefreshObserver();
42 void CanvasContext::Cleanup() {
43 Unconfigure();
44 if (mRenderRootStateManager && mImageKey) {
45 mRenderRootStateManager->AddImageKeyForDiscard(mImageKey.value());
46 mRenderRootStateManager = nullptr;
47 mImageKey.reset();
51 JSObject* CanvasContext::WrapObject(JSContext* aCx,
52 JS::Handle<JSObject*> aGivenProto) {
53 return dom::GPUCanvasContext_Binding::Wrap(aCx, this, aGivenProto);
56 bool CanvasContext::UpdateWebRenderCanvasData(
57 nsDisplayListBuilder* aBuilder, WebRenderCanvasData* aCanvasData) {
58 return true;
61 void CanvasContext::Configure(const dom::GPUCanvasConfiguration& aDesc) {
62 Unconfigure();
64 switch (aDesc.mFormat) {
65 case dom::GPUTextureFormat::Rgba8unorm:
66 mGfxFormat = gfx::SurfaceFormat::R8G8B8A8;
67 break;
68 case dom::GPUTextureFormat::Bgra8unorm:
69 mGfxFormat = gfx::SurfaceFormat::B8G8R8A8;
70 break;
71 default:
72 NS_WARNING("Specified swap chain format is not supported");
73 return;
76 gfx::IntSize actualSize(mWidth, mHeight);
77 mTexture = aDesc.mDevice->InitSwapChain(aDesc, mExternalImageId, mGfxFormat,
78 &actualSize);
79 mTexture->mTargetCanvasElement = mCanvasElement;
80 mBridge = aDesc.mDevice->GetBridge();
81 mGfxSize = actualSize;
83 // Force a new frame to be built, which will execute the
84 // `CanvasContextType::WebGPU` switch case in `CreateWebRenderCommands` and
85 // populate the WR user data.
86 mCanvasElement->InvalidateCanvas();
89 Maybe<wr::ImageKey> CanvasContext::GetImageKey() const { return mImageKey; }
91 wr::ImageKey CanvasContext::CreateImageKey(
92 layers::RenderRootStateManager* aManager) {
93 const auto key = aManager->WrBridge()->GetNextImageKey();
94 mRenderRootStateManager = aManager;
95 mImageKey = Some(key);
96 return key;
99 void CanvasContext::Unconfigure() {
100 if (mBridge && mBridge->IsOpen()) {
101 mBridge->SendSwapChainDestroy(mExternalImageId);
103 mBridge = nullptr;
104 mTexture = nullptr;
107 dom::GPUTextureFormat CanvasContext::GetPreferredFormat(Adapter&) const {
108 return dom::GPUTextureFormat::Bgra8unorm;
111 RefPtr<Texture> CanvasContext::GetCurrentTexture() { return mTexture; }
113 bool CanvasContext::UpdateWebRenderLocalCanvasData(
114 layers::WebRenderLocalCanvasData* aCanvasData) {
115 if (!mTexture) {
116 return false;
119 aCanvasData->mGpuBridge = mBridge.get();
120 aCanvasData->mGpuTextureId = mTexture->mId;
121 aCanvasData->mExternalImageId = mExternalImageId;
122 aCanvasData->mFormat = mGfxFormat;
123 return true;
126 wr::ImageDescriptor CanvasContext::MakeImageDescriptor() const {
127 const layers::RGBDescriptor rgbDesc(mGfxSize, mGfxFormat, false);
128 const auto targetStride = layers::ImageDataSerializer::GetRGBStride(rgbDesc);
129 const bool preferCompositorSurface = true;
130 return wr::ImageDescriptor(mGfxSize, targetStride, mGfxFormat,
131 wr::OpacityType::HasAlphaChannel,
132 preferCompositorSurface);
135 } // namespace webgpu
136 } // namespace mozilla