mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
cf3c8fedea
* Majorly simplity CanvasRenderer * Replace GLScreenBuffer with trivial GLSwapChain * Use descriptor structs so that future SharedSurface changes aren't so painful to propagate * Mortgage/strip out more OffscreenCanvas code for now Differential Revision: https://phabricator.services.mozilla.com/D75055
193 lines
4.9 KiB
C++
193 lines
4.9 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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 "ShareableCanvasRenderer.h"
|
|
|
|
#include "mozilla/dom/WebGLTypes.h"
|
|
#include "mozilla/gfx/2D.h"
|
|
#include "mozilla/layers/TextureClientSharedSurface.h"
|
|
#include "mozilla/layers/CompositableForwarder.h"
|
|
|
|
#include "gfxUtils.h"
|
|
#include "GLScreenBuffer.h"
|
|
#include "nsICanvasRenderingContextInternal.h"
|
|
#include "SharedSurfaceGL.h"
|
|
|
|
using namespace mozilla::gfx;
|
|
|
|
namespace mozilla {
|
|
namespace layers {
|
|
|
|
ShareableCanvasRenderer::ShareableCanvasRenderer() {
|
|
MOZ_COUNT_CTOR(ShareableCanvasRenderer);
|
|
}
|
|
|
|
ShareableCanvasRenderer::~ShareableCanvasRenderer() {
|
|
MOZ_COUNT_DTOR(ShareableCanvasRenderer);
|
|
|
|
mFrontBufferFromDesc = nullptr;
|
|
DisconnectClient();
|
|
}
|
|
|
|
void ShareableCanvasRenderer::Initialize(const CanvasRendererData& aData) {
|
|
CanvasRenderer::Initialize(aData);
|
|
mCanvasClient = nullptr;
|
|
}
|
|
|
|
void ShareableCanvasRenderer::ClearCachedResources() {
|
|
CanvasRenderer::ClearCachedResources();
|
|
|
|
if (mCanvasClient) {
|
|
mCanvasClient->Clear();
|
|
}
|
|
}
|
|
|
|
void ShareableCanvasRenderer::DisconnectClient() {
|
|
if (mCanvasClient) {
|
|
mCanvasClient->OnDetach();
|
|
mCanvasClient = nullptr;
|
|
}
|
|
}
|
|
|
|
RefPtr<layers::TextureClient> ShareableCanvasRenderer::GetFrontBufferFromDesc(
|
|
const layers::SurfaceDescriptor& desc, TextureFlags flags) {
|
|
if (mFrontBufferFromDesc && mFrontBufferDesc == desc)
|
|
return mFrontBufferFromDesc;
|
|
mFrontBufferFromDesc = nullptr;
|
|
|
|
// Test the validity of aAllocator
|
|
const auto& compositableForwarder = GetForwarder();
|
|
if (!compositableForwarder) {
|
|
return nullptr;
|
|
}
|
|
const auto& textureForwarder = compositableForwarder->GetTextureForwarder();
|
|
|
|
auto format = gfx::SurfaceFormat::R8G8B8X8;
|
|
if (!mData.mIsOpaque) {
|
|
format = gfx::SurfaceFormat::R8G8B8A8;
|
|
|
|
if (!mData.mIsAlphaPremult) {
|
|
flags |= TextureFlags::NON_PREMULTIPLIED;
|
|
}
|
|
}
|
|
|
|
auto data = MakeUnique<SharedSurfaceTextureData>(desc, format, mData.mSize);
|
|
mFrontBufferDesc = desc;
|
|
mFrontBufferFromDesc =
|
|
TextureClient::CreateWithData(data.release(), flags, textureForwarder);
|
|
return mFrontBufferFromDesc;
|
|
}
|
|
|
|
void ShareableCanvasRenderer::UpdateCompositableClient() {
|
|
if (!CreateCompositable()) {
|
|
return;
|
|
}
|
|
|
|
if (!IsDirty()) {
|
|
return;
|
|
}
|
|
ResetDirty();
|
|
|
|
const auto context = mData.GetContext();
|
|
if (!context) return;
|
|
const auto& provider = context->GetBufferProvider();
|
|
const auto webgl = context->AsWebgl();
|
|
|
|
const auto& forwarder = GetForwarder();
|
|
|
|
// -
|
|
|
|
auto flags = TextureFlags::IMMUTABLE;
|
|
if (!YIsDown()) {
|
|
flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
|
|
}
|
|
|
|
// -
|
|
|
|
const auto fnGetExistingTc = [&]() -> RefPtr<TextureClient> {
|
|
if (provider) {
|
|
auto tc = provider->GetTextureClient();
|
|
if (!tc) return nullptr;
|
|
|
|
if (!provider->SetKnowsCompositor(forwarder)) {
|
|
gfxCriticalNote << "BufferProvider::SetForwarder failed";
|
|
return nullptr;
|
|
}
|
|
tc = provider->GetTextureClient(); // Ask again after SetKnowsCompositor
|
|
return tc;
|
|
}
|
|
|
|
if (!webgl) return nullptr;
|
|
if (!forwarder) return nullptr;
|
|
const auto desc = webgl::GetFrontBuffer(*webgl, forwarder);
|
|
if (!desc) return nullptr;
|
|
return GetFrontBufferFromDesc(*desc, flags);
|
|
};
|
|
|
|
// -
|
|
|
|
const auto fnMakeTcFromSnapshot = [&]() -> RefPtr<TextureClient> {
|
|
const auto& size = mData.mSize;
|
|
|
|
auto contentType = gfxContentType::COLOR;
|
|
if (!mData.mIsOpaque) {
|
|
contentType = gfxContentType::COLOR_ALPHA;
|
|
}
|
|
const auto surfaceFormat =
|
|
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType);
|
|
|
|
const auto tc =
|
|
mCanvasClient->CreateTextureClientForCanvas(surfaceFormat, size, flags);
|
|
if (!tc) {
|
|
return nullptr;
|
|
}
|
|
|
|
{
|
|
TextureClientAutoLock tcLock(tc, OpenMode::OPEN_WRITE_ONLY);
|
|
if (!tcLock.Succeeded()) {
|
|
return nullptr;
|
|
}
|
|
|
|
const RefPtr<DrawTarget> dt = tc->BorrowDrawTarget();
|
|
|
|
const auto borrowed = BorrowSnapshot();
|
|
if (!borrowed) return nullptr;
|
|
|
|
dt->CopySurface(borrowed->mSurf, {{0, 0}, size}, {0, 0});
|
|
}
|
|
|
|
return tc;
|
|
};
|
|
|
|
// -
|
|
|
|
{
|
|
FirePreTransactionCallback();
|
|
|
|
// First, let's see if we can get a no-copy TextureClient from the canvas.
|
|
auto tc = fnGetExistingTc();
|
|
if (!tc) {
|
|
// Otherwise, snapshot the surface and copy into a TexClient.
|
|
tc = fnMakeTcFromSnapshot();
|
|
}
|
|
if (tc != mFrontBufferFromDesc) {
|
|
mFrontBufferFromDesc = nullptr;
|
|
}
|
|
|
|
if (!tc) {
|
|
NS_WARNING("Couldn't make TextureClient for CanvasRenderer.");
|
|
return;
|
|
}
|
|
|
|
mCanvasClient->UseTexture(tc);
|
|
|
|
FireDidTransactionCallback();
|
|
}
|
|
}
|
|
|
|
} // namespace layers
|
|
} // namespace mozilla
|