Bug 1839315: part 4) Link from `SheetLoadData::mWasAlternate` to spec. r=emilio DONTBUILD
[gecko.git] / gfx / layers / ShareableCanvasRenderer.cpp
blob621d8286a62d5f8f9730516a8b74af3c6151f0eb
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"
16 #include "gfxUtils.h"
17 #include "GLScreenBuffer.h"
18 #include "nsICanvasRenderingContextInternal.h"
19 #include "SharedSurfaceGL.h"
21 using namespace mozilla::gfx;
23 namespace mozilla {
24 namespace layers {
26 ShareableCanvasRenderer::ShareableCanvasRenderer() {
27 MOZ_COUNT_CTOR(ShareableCanvasRenderer);
30 ShareableCanvasRenderer::~ShareableCanvasRenderer() {
31 MOZ_COUNT_DTOR(ShareableCanvasRenderer);
33 mFrontBufferFromDesc = nullptr;
34 DisconnectClient();
37 void ShareableCanvasRenderer::Initialize(const CanvasRendererData& aData) {
38 CanvasRenderer::Initialize(aData);
39 mCanvasClient = nullptr;
42 void ShareableCanvasRenderer::ClearCachedResources() {
43 CanvasRenderer::ClearCachedResources();
45 if (mCanvasClient) {
46 mCanvasClient->Clear();
50 void ShareableCanvasRenderer::DisconnectClient() {
51 if (mCanvasClient) {
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) {
66 return nullptr;
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()) {
87 return;
90 if (!IsDirty()) {
91 return;
93 ResetDirty();
95 const auto context = mData.GetContext();
96 if (!context) return;
97 const auto& provider = context->GetBufferProvider();
98 const auto& forwarder = GetForwarder();
100 // -
102 auto flags = TextureFlags::IMMUTABLE;
103 if (!YIsDown()) {
104 flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
106 if (IsOpaque()) {
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,
115 flags);
116 EnsurePipeline();
117 return;
120 // -
122 const auto fnGetExistingTc =
123 [&](const Maybe<SurfaceDescriptor>& aDesc,
124 bool& aOutLostFrontTexture) -> RefPtr<TextureClient> {
125 if (aDesc) {
126 return GetFrontBufferFromDesc(*aDesc, flags);
128 if (provider) {
129 if (!provider->SetKnowsCompositor(forwarder, aOutLostFrontTexture)) {
130 gfxCriticalNote << "BufferProvider::SetForwarder failed";
131 return nullptr;
133 if (aOutLostFrontTexture) {
134 return nullptr;
137 return provider->GetTextureClient();
139 return nullptr;
142 // -
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);
154 const auto tc =
155 mCanvasClient->CreateTextureClientForCanvas(surfaceFormat, size, flags);
156 if (!tc) {
157 return nullptr;
161 TextureClientAutoLock tcLock(tc, OpenMode::OPEN_WRITE_ONLY);
162 if (!tcLock.Succeeded()) {
163 return nullptr;
166 const RefPtr<DrawTarget> dt = tc->BorrowDrawTarget();
168 const bool requireAlphaPremult = false;
169 auto borrowed = BorrowSnapshot(requireAlphaPremult);
170 if (!borrowed) {
171 return nullptr;
173 dt->CopySurface(borrowed->mSurf, borrowed->mSurf->GetRect(), {0, 0});
176 return tc;
179 // -
182 FirePreTransactionCallback();
184 const auto desc = context->GetFrontBuffer(nullptr);
185 if (desc &&
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;
192 EnsurePipeline();
193 forwarder->UseRemoteTexture(mCanvasClient, textureDesc.textureId(),
194 textureDesc.ownerId(), mData.mSize, flags);
196 FireDidTransactionCallback();
197 return;
200 EnsurePipeline();
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.
207 return;
209 if (!tc) {
210 // Otherwise, snapshot the surface and copy into a TexClient.
211 tc = fnMakeTcFromSnapshot();
213 if (tc != mFrontBufferFromDesc) {
214 mFrontBufferFromDesc = nullptr;
217 if (!tc) {
218 NS_WARNING("Couldn't make TextureClient for CanvasRenderer.");
219 return;
222 mCanvasClient->UseTexture(tc);
224 FireDidTransactionCallback();
228 } // namespace layers
229 } // namespace mozilla