Bug 1632310 [wpt PR 23186] - Add test for computed versus resolved style., a=testonly
[gecko.git] / gfx / layers / ShareableCanvasRenderer.cpp
blob4f452be7c609679aeb36cfa005a0acc9174ed8dc
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
12 #include "gfxUtils.h"
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;
20 namespace mozilla {
21 namespace layers {
23 ShareableCanvasRenderer::ShareableCanvasRenderer()
24 : mCanvasClient(nullptr),
25 mFactory(nullptr),
26 mFlags(TextureFlags::NO_FLAGS) {
27 MOZ_COUNT_CTOR(ShareableCanvasRenderer);
30 ShareableCanvasRenderer::~ShareableCanvasRenderer() {
31 MOZ_COUNT_DTOR(ShareableCanvasRenderer);
33 Destroy();
36 void ShareableCanvasRenderer::Initialize(const CanvasInitializeData& aData) {
37 CopyableCanvasRenderer::Initialize(aData);
39 mCanvasClient = nullptr;
41 if (!mGLContext) return;
43 gl::GLScreenBuffer* screen = mGLContext->Screen();
44 MOZ_ASSERT(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);
56 if (factory) {
57 screen->Morph(std::move(factory));
61 void ShareableCanvasRenderer::ClearCachedResources() {
62 CopyableCanvasRenderer::ClearCachedResources();
64 if (mCanvasClient) {
65 mCanvasClient->Clear();
69 void ShareableCanvasRenderer::Destroy() {
70 CopyableCanvasRenderer::Destroy();
72 if (mCanvasClient) {
73 mCanvasClient->OnDetach();
74 mCanvasClient = nullptr;
78 bool ShareableCanvasRenderer::UpdateTarget(DrawTarget* aDestTarget) {
79 MOZ_ASSERT(!mOOPRenderer);
81 MOZ_ASSERT(aDestTarget);
82 if (!aDestTarget) {
83 return false;
86 RefPtr<SourceSurface> surface;
88 if (!mGLContext) {
89 AutoReturnSnapshot autoReturn;
91 if (mAsyncRenderer) {
92 surface = mAsyncRenderer->GetSurface();
93 } else if (mBufferProvider) {
94 surface = mBufferProvider->BorrowSnapshot();
95 autoReturn.mSnapshot = &surface;
96 autoReturn.mBufferProvider = mBufferProvider;
99 MOZ_ASSERT(surface);
100 if (!surface) {
101 return false;
104 aDestTarget->CopySurface(surface, IntRect(0, 0, mSize.width, mSize.height),
105 IntPoint(0, 0));
106 return true;
109 gl::SharedSurface* frontbuffer = nullptr;
111 gl::GLScreenBuffer* screen = mGLContext->Screen();
112 const auto& front = screen->Front();
113 if (front) {
114 frontbuffer = front->Surf();
117 if (!frontbuffer) {
118 NS_WARNING("Null frame received.");
119 return false;
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
128 uint8_t* destData;
129 IntSize destSize;
130 int32_t destStride;
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);
138 return false;
140 if (needsPremult) {
141 gfxUtils::PremultiplyDataSurface(data, data);
143 aDestTarget->ReleaseBits(destData);
144 return true;
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)) {
153 return false;
156 // Readback handles Flush/MarkDirty.
157 if (!mGLContext->Readback(frontbuffer, resultSurf)) {
158 return false;
160 if (needsPremult) {
161 gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
164 aDestTarget->CopySurface(resultSurf,
165 IntRect(0, 0, readSize.width, readSize.height),
166 IntPoint(0, 0));
168 return true;
171 CanvasClient::CanvasClientType ShareableCanvasRenderer::GetCanvasClientType() {
172 if (mAsyncRenderer) {
173 return CanvasClient::CanvasClientAsync;
176 if (mGLContext) {
177 return CanvasClient::CanvasClientTypeShSurf;
180 if (mOOPRenderer) {
181 return CanvasClient::CanvasClientTypeOOP;
184 return CanvasClient::CanvasClientSurface;
187 void ShareableCanvasRenderer::UpdateCompositableClient(
188 wr::RenderRoot aRenderRoot) {
189 if (!CreateCompositable()) {
190 return;
193 if (mCanvasClient && mAsyncRenderer) {
194 mCanvasClient->UpdateAsync(mAsyncRenderer);
197 if (!IsDirty()) {
198 return;
200 ResetDirty();
202 FirePreTransactionCallback();
203 if (mBufferProvider && mBufferProvider->GetTextureClient()) {
204 if (!mBufferProvider->SetKnowsCompositor(GetForwarder())) {
205 gfxCriticalNote << "BufferProvider::SetForwarder failed";
206 return;
208 mCanvasClient->UpdateFromTexture(mBufferProvider->GetTextureClient(),
209 aRenderRoot);
210 } else {
211 mCanvasClient->Update(gfx::IntSize(mSize.width, mSize.height), this,
212 aRenderRoot);
215 FireDidTransactionCallback();
217 mCanvasClient->Updated(aRenderRoot);
220 } // namespace layers
221 } // namespace mozilla