1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ShareableCanvasRenderer.h"
9 #include "mozilla/dom/WebGLTypes.h"
10 #include "mozilla/gfx/2D.h"
11 #include "mozilla/layers/TextureClientSharedSurface.h"
12 #include "mozilla/layers/CompositableForwarder.h"
13 #include "mozilla/layers/TextureForwarder.h"
15 #include "ClientWebGLContext.h"
17 #include "GLScreenBuffer.h"
18 #include "nsICanvasRenderingContextInternal.h"
19 #include "SharedSurfaceGL.h"
21 using namespace mozilla::gfx
;
26 ShareableCanvasRenderer::ShareableCanvasRenderer() {
27 MOZ_COUNT_CTOR(ShareableCanvasRenderer
);
30 ShareableCanvasRenderer::~ShareableCanvasRenderer() {
31 MOZ_COUNT_DTOR(ShareableCanvasRenderer
);
33 mFrontBufferFromDesc
= nullptr;
37 void ShareableCanvasRenderer::Initialize(const CanvasRendererData
& aData
) {
38 CanvasRenderer::Initialize(aData
);
39 mCanvasClient
= nullptr;
42 void ShareableCanvasRenderer::ClearCachedResources() {
43 CanvasRenderer::ClearCachedResources();
46 mCanvasClient
->Clear();
50 void ShareableCanvasRenderer::DisconnectClient() {
52 mCanvasClient
->OnDetach();
53 mCanvasClient
= nullptr;
57 RefPtr
<layers::TextureClient
> ShareableCanvasRenderer::GetFrontBufferFromDesc(
58 const layers::SurfaceDescriptor
& desc
, TextureFlags flags
) {
59 if (mFrontBufferFromDesc
&& mFrontBufferDesc
== desc
)
60 return mFrontBufferFromDesc
;
61 mFrontBufferFromDesc
= nullptr;
63 // Test the validity of aAllocator
64 const auto& compositableForwarder
= GetForwarder();
65 if (!compositableForwarder
) {
68 const auto& textureForwarder
= compositableForwarder
->GetTextureForwarder();
70 auto format
= gfx::SurfaceFormat::R8G8B8X8
;
71 if (!mData
.mIsOpaque
) {
72 format
= gfx::SurfaceFormat::R8G8B8A8
;
74 if (!mData
.mIsAlphaPremult
) {
75 flags
|= TextureFlags::NON_PREMULTIPLIED
;
79 mFrontBufferFromDesc
= SharedSurfaceTextureData::CreateTextureClient(
80 desc
, format
, mData
.mSize
, flags
, textureForwarder
);
81 mFrontBufferDesc
= desc
;
82 return mFrontBufferFromDesc
;
85 void ShareableCanvasRenderer::UpdateCompositableClient() {
86 if (!CreateCompositable()) {
95 const auto context
= mData
.GetContext();
97 const auto& provider
= context
->GetBufferProvider();
98 const auto& forwarder
= GetForwarder();
102 auto flags
= TextureFlags::IMMUTABLE
;
104 flags
|= TextureFlags::ORIGIN_BOTTOM_LEFT
;
107 flags
|= TextureFlags::IS_OPAQUE
;
110 // With remote texture push callback, a new pushed remote texture is notifiled
111 // from RemoteTextureMap to WebRenderImageHost.
112 if (mData
.mRemoteTextureOwnerIdOfPushCallback
) {
113 GetForwarder()->EnableRemoteTexturePushCallback(
114 mCanvasClient
, *mData
.mRemoteTextureOwnerIdOfPushCallback
, mData
.mSize
,
122 const auto fnGetExistingTc
=
123 [&](const Maybe
<SurfaceDescriptor
>& aDesc
,
124 bool& aOutLostFrontTexture
) -> RefPtr
<TextureClient
> {
126 return GetFrontBufferFromDesc(*aDesc
, flags
);
129 if (!provider
->SetKnowsCompositor(forwarder
, aOutLostFrontTexture
)) {
130 gfxCriticalNote
<< "BufferProvider::SetForwarder failed";
133 if (aOutLostFrontTexture
) {
137 return provider
->GetTextureClient();
144 const auto fnMakeTcFromSnapshot
= [&]() -> RefPtr
<TextureClient
> {
145 const auto& size
= mData
.mSize
;
147 auto contentType
= gfxContentType::COLOR
;
148 if (!mData
.mIsOpaque
) {
149 contentType
= gfxContentType::COLOR_ALPHA
;
151 const auto surfaceFormat
=
152 gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType
);
155 mCanvasClient
->CreateTextureClientForCanvas(surfaceFormat
, size
, flags
);
161 TextureClientAutoLock
tcLock(tc
, OpenMode::OPEN_WRITE_ONLY
);
162 if (!tcLock
.Succeeded()) {
166 const RefPtr
<DrawTarget
> dt
= tc
->BorrowDrawTarget();
168 const bool requireAlphaPremult
= false;
169 auto borrowed
= BorrowSnapshot(requireAlphaPremult
);
173 dt
->CopySurface(borrowed
->mSurf
, borrowed
->mSurf
->GetRect(), {0, 0});
182 FirePreTransactionCallback();
184 const auto desc
= context
->GetFrontBuffer(nullptr);
186 desc
->type() == SurfaceDescriptor::TSurfaceDescriptorRemoteTexture
) {
187 const auto& forwarder
= GetForwarder();
188 const auto& textureDesc
= desc
->get_SurfaceDescriptorRemoteTexture();
189 if (!mData
.mIsAlphaPremult
) {
190 flags
|= TextureFlags::NON_PREMULTIPLIED
;
193 forwarder
->UseRemoteTexture(mCanvasClient
, textureDesc
.textureId(),
194 textureDesc
.ownerId(), mData
.mSize
, flags
);
196 FireDidTransactionCallback();
202 // Let's see if we can get a no-copy TextureClient from the canvas.
203 bool lostFrontTexture
= false;
204 auto tc
= fnGetExistingTc(desc
, lostFrontTexture
);
205 if (lostFrontTexture
) {
206 // Device reset could cause this.
210 // Otherwise, snapshot the surface and copy into a TexClient.
211 tc
= fnMakeTcFromSnapshot();
213 if (tc
!= mFrontBufferFromDesc
) {
214 mFrontBufferFromDesc
= nullptr;
218 NS_WARNING("Couldn't make TextureClient for CanvasRenderer.");
222 mCanvasClient
->UseTexture(tc
);
224 FireDidTransactionCallback();
228 } // namespace layers
229 } // namespace mozilla