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()) {
91 const auto context
= mData
.GetContext();
95 const auto& forwarder
= GetForwarder();
96 RefPtr
<FwdTransactionTracker
> tracker
=
97 context
->UseCompositableForwarder(forwarder
);
98 if (forwarder
&& tracker
) {
99 forwarder
->TrackFwdTransaction(tracker
);
105 const auto context
= mData
.GetContext();
106 if (!context
) return;
107 const auto& provider
= context
->GetBufferProvider();
108 const auto& forwarder
= GetForwarder();
112 auto flags
= TextureFlags::IMMUTABLE
;
114 flags
|= TextureFlags::ORIGIN_BOTTOM_LEFT
;
117 flags
|= TextureFlags::IS_OPAQUE
;
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 RefPtr
<FwdTransactionTracker
> tracker
=
194 context
->UseCompositableForwarder(forwarder
);
196 flags
|= TextureFlags::WAIT_FOR_REMOTE_TEXTURE_OWNER
;
198 forwarder
->UseRemoteTexture(mCanvasClient
, textureDesc
.textureId(),
199 textureDesc
.ownerId(), mData
.mSize
, flags
,
201 FireDidTransactionCallback();
207 // Let's see if we can get a no-copy TextureClient from the canvas.
208 bool lostFrontTexture
= false;
209 auto tc
= fnGetExistingTc(desc
, lostFrontTexture
);
210 if (lostFrontTexture
) {
211 // Device reset could cause this.
215 // Otherwise, snapshot the surface and copy into a TexClient.
216 tc
= fnMakeTcFromSnapshot();
218 if (tc
!= mFrontBufferFromDesc
) {
219 mFrontBufferFromDesc
= nullptr;
223 NS_WARNING("Couldn't make TextureClient for CanvasRenderer.");
227 mCanvasClient
->UseTexture(tc
);
229 FireDidTransactionCallback();
233 } // namespace layers
234 } // namespace mozilla