gecko-dev/dom/webgpu/CanvasContext.cpp

125 строки
3.8 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/WebGPUBinding.h"
#include "CanvasContext.h"
#include "SwapChain.h"
#include "nsDisplayList.h"
#include "LayerUserData.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/layers/CompositorManagerChild.h"
#include "mozilla/layers/RenderRootStateManager.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
namespace mozilla {
namespace webgpu {
NS_IMPL_CYCLE_COLLECTING_ADDREF(CanvasContext)
NS_IMPL_CYCLE_COLLECTING_RELEASE(CanvasContext)
GPU_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CanvasContext, mSwapChain,
mCanvasElement, mOffscreenCanvas)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CanvasContext)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
CanvasContext::CanvasContext()
: mExternalImageId(layers::CompositorManagerChild::GetInstance()
->GetNextExternalImageId()) {}
CanvasContext::~CanvasContext() {
Cleanup();
RemovePostRefreshObserver();
}
void CanvasContext::Cleanup() {
if (mSwapChain) {
mSwapChain->Destroy(mExternalImageId);
mSwapChain = nullptr;
}
if (mRenderRootStateManager && mImageKey) {
mRenderRootStateManager->AddImageKeyForDiscard(mImageKey.value());
mRenderRootStateManager = nullptr;
mImageKey.reset();
}
}
JSObject* CanvasContext::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
return dom::GPUCanvasContext_Binding::Wrap(aCx, this, aGivenProto);
}
already_AddRefed<layers::Layer> CanvasContext::GetCanvasLayer(
nsDisplayListBuilder* aBuilder, layers::Layer* aOldLayer,
layers::LayerManager* aManager) {
return nullptr;
}
bool CanvasContext::UpdateWebRenderCanvasData(
nsDisplayListBuilder* aBuilder, WebRenderCanvasData* aCanvasData) {
return true;
}
RefPtr<SwapChain> CanvasContext::ConfigureSwapChain(
const dom::GPUSwapChainDescriptor& aDesc, ErrorResult& aRv) {
Cleanup();
gfx::SurfaceFormat format;
switch (aDesc.mFormat) {
case dom::GPUTextureFormat::Rgba8unorm:
format = gfx::SurfaceFormat::R8G8B8A8;
break;
case dom::GPUTextureFormat::Bgra8unorm:
format = gfx::SurfaceFormat::B8G8R8A8;
break;
default:
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
dom::GPUExtent3DDict extent;
extent.mWidth = mWidth;
extent.mHeight = mHeight;
extent.mDepth = 1;
mSwapChain = new SwapChain(aDesc, extent, mExternalImageId, format);
// Force a new frame to be built, which will execute the
// `CanvasContextType::WebGPU` switch case in `CreateWebRenderCommands` and
// populate the WR user data.
mCanvasElement->InvalidateCanvas();
mSwapChain->GetCurrentTexture()->mTargetCanvasElement = mCanvasElement;
return mSwapChain;
}
Maybe<wr::ImageKey> CanvasContext::GetImageKey() const { return mImageKey; }
wr::ImageKey CanvasContext::CreateImageKey(
layers::RenderRootStateManager* aManager) {
const auto key = aManager->WrBridge()->GetNextImageKey();
mRenderRootStateManager = aManager;
mImageKey = Some(key);
return key;
}
bool CanvasContext::UpdateWebRenderLocalCanvasData(
layers::WebRenderLocalCanvasData* aCanvasData) {
if (!mSwapChain || !mSwapChain->GetGpuBridge()) {
return false;
}
aCanvasData->mGpuBridge = mSwapChain->GetGpuBridge();
aCanvasData->mGpuTextureId = mSwapChain->GetCurrentTexture()->mId;
aCanvasData->mExternalImageId = mExternalImageId;
aCanvasData->mFormat = mSwapChain->mFormat;
return true;
}
} // namespace webgpu
} // namespace mozilla