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 "GLContext.h" // for GLContext
10 #include "GLScreenBuffer.h" // for GLScreenBuffer
11 #include "SharedSurfaceGL.h" // for SurfaceFactory_GLTexture, etc
13 #include "mozilla/gfx/2D.h"
14 #include "mozilla/layers/AsyncCanvasRenderer.h"
15 #include "mozilla/layers/TextureClientSharedSurface.h"
16 #include "mozilla/layers/CompositableForwarder.h"
18 using namespace mozilla::gfx
;
23 ShareableCanvasRenderer::ShareableCanvasRenderer()
24 : mCanvasClient(nullptr),
26 mFlags(TextureFlags::NO_FLAGS
) {
27 MOZ_COUNT_CTOR(ShareableCanvasRenderer
);
30 ShareableCanvasRenderer::~ShareableCanvasRenderer() {
31 MOZ_COUNT_DTOR(ShareableCanvasRenderer
);
36 void ShareableCanvasRenderer::Initialize(const CanvasInitializeData
& aData
) {
37 CopyableCanvasRenderer::Initialize(aData
);
39 mCanvasClient
= nullptr;
41 if (!mGLContext
) return;
43 gl::GLScreenBuffer
* screen
= mGLContext
->Screen();
45 gl::SurfaceCaps caps
= screen
->mCaps
;
47 auto forwarder
= GetForwarder();
49 mFlags
= TextureFlags::ORIGIN_BOTTOM_LEFT
;
50 if (!aData
.mIsGLAlphaPremult
) {
51 mFlags
|= TextureFlags::NON_PREMULTIPLIED
;
54 UniquePtr
<gl::SurfaceFactory
> factory
=
55 gl::GLScreenBuffer::CreateFactory(mGLContext
, caps
, forwarder
, mFlags
);
57 screen
->Morph(std::move(factory
));
61 void ShareableCanvasRenderer::ClearCachedResources() {
62 CopyableCanvasRenderer::ClearCachedResources();
65 mCanvasClient
->Clear();
69 void ShareableCanvasRenderer::Destroy() {
70 CopyableCanvasRenderer::Destroy();
73 mCanvasClient
->OnDetach();
74 mCanvasClient
= nullptr;
78 bool ShareableCanvasRenderer::UpdateTarget(DrawTarget
* aDestTarget
) {
79 MOZ_ASSERT(!mOOPRenderer
);
81 MOZ_ASSERT(aDestTarget
);
86 RefPtr
<SourceSurface
> surface
;
89 AutoReturnSnapshot autoReturn
;
92 surface
= mAsyncRenderer
->GetSurface();
93 } else if (mBufferProvider
) {
94 surface
= mBufferProvider
->BorrowSnapshot();
95 autoReturn
.mSnapshot
= &surface
;
96 autoReturn
.mBufferProvider
= mBufferProvider
;
104 aDestTarget
->CopySurface(surface
, IntRect(0, 0, mSize
.width
, mSize
.height
),
109 gl::SharedSurface
* frontbuffer
= nullptr;
111 gl::GLScreenBuffer
* screen
= mGLContext
->Screen();
112 const auto& front
= screen
->Front();
114 frontbuffer
= front
->Surf();
118 NS_WARNING("Null frame received.");
122 IntSize
readSize(frontbuffer
->mSize
);
123 SurfaceFormat format
=
124 mOpaque
? SurfaceFormat::B8G8R8X8
: SurfaceFormat::B8G8R8A8
;
125 bool needsPremult
= frontbuffer
->mHasAlpha
&& !mIsAlphaPremultiplied
;
127 // Try to read back directly into aDestTarget's output buffer
131 SurfaceFormat destFormat
;
132 if (aDestTarget
->LockBits(&destData
, &destSize
, &destStride
, &destFormat
)) {
133 if (destSize
== readSize
&& destFormat
== format
) {
134 RefPtr
<DataSourceSurface
> data
= Factory::CreateWrappingDataSourceSurface(
135 destData
, destStride
, destSize
, destFormat
);
136 if (!mGLContext
->Readback(frontbuffer
, data
)) {
137 aDestTarget
->ReleaseBits(destData
);
141 gfxUtils::PremultiplyDataSurface(data
, data
);
143 aDestTarget
->ReleaseBits(destData
);
146 aDestTarget
->ReleaseBits(destData
);
149 RefPtr
<DataSourceSurface
> resultSurf
= GetTempSurface(readSize
, format
);
150 // There will already be a warning from inside of GetTempSurface, but
151 // it doesn't hurt to complain:
152 if (NS_WARN_IF(!resultSurf
)) {
156 // Readback handles Flush/MarkDirty.
157 if (!mGLContext
->Readback(frontbuffer
, resultSurf
)) {
161 gfxUtils::PremultiplyDataSurface(resultSurf
, resultSurf
);
164 aDestTarget
->CopySurface(resultSurf
,
165 IntRect(0, 0, readSize
.width
, readSize
.height
),
171 CanvasClient::CanvasClientType
ShareableCanvasRenderer::GetCanvasClientType() {
172 if (mAsyncRenderer
) {
173 return CanvasClient::CanvasClientAsync
;
177 return CanvasClient::CanvasClientTypeShSurf
;
181 return CanvasClient::CanvasClientTypeOOP
;
184 return CanvasClient::CanvasClientSurface
;
187 void ShareableCanvasRenderer::UpdateCompositableClient(
188 wr::RenderRoot aRenderRoot
) {
189 if (!CreateCompositable()) {
193 if (mCanvasClient
&& mAsyncRenderer
) {
194 mCanvasClient
->UpdateAsync(mAsyncRenderer
);
202 FirePreTransactionCallback();
203 if (mBufferProvider
&& mBufferProvider
->GetTextureClient()) {
204 if (!mBufferProvider
->SetKnowsCompositor(GetForwarder())) {
205 gfxCriticalNote
<< "BufferProvider::SetForwarder failed";
208 mCanvasClient
->UpdateFromTexture(mBufferProvider
->GetTextureClient(),
211 mCanvasClient
->Update(gfx::IntSize(mSize
.width
, mSize
.height
), this,
215 FireDidTransactionCallback();
217 mCanvasClient
->Updated(aRenderRoot
);
220 } // namespace layers
221 } // namespace mozilla