Backed out 3 changesets (bug 1918178) for causing reftest failures. a=backout
[gecko.git] / gfx / webrender_bindings / RenderCompositorLayersSWGL.cpp
blob505e07d59f9433a8270ff37c79c84bdbc4c72373
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
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file,
7 * You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include "RenderCompositorLayersSWGL.h"
11 #include "GLContext.h"
12 #include "GLContextEGL.h"
13 #include "mozilla/layers/BuildConstants.h"
14 #include "mozilla/layers/Effects.h"
15 #include "mozilla/layers/TextureHostOGL.h"
16 #include "mozilla/widget/CompositorWidget.h"
17 #include "RenderCompositorRecordedFrame.h"
19 #if defined(XP_WIN)
20 # include "mozilla/webrender/RenderCompositorD3D11SWGL.h"
21 #else
22 # include "mozilla/webrender/RenderCompositorOGLSWGL.h"
23 #endif
25 namespace mozilla {
26 using namespace layers;
27 using namespace gfx;
29 namespace wr {
31 UniquePtr<RenderCompositor> RenderCompositorLayersSWGL::Create(
32 const RefPtr<widget::CompositorWidget>& aWidget, nsACString& aError) {
33 #ifdef XP_WIN
34 return RenderCompositorD3D11SWGL::Create(aWidget, aError);
35 #else
36 return RenderCompositorOGLSWGL::Create(aWidget, aError);
37 #endif
40 RenderCompositorLayersSWGL::RenderCompositorLayersSWGL(
41 Compositor* aCompositor, const RefPtr<widget::CompositorWidget>& aWidget,
42 void* aContext)
43 : RenderCompositor(aWidget),
44 mCompositor(aCompositor),
45 mContext(aContext),
46 mCurrentTileId(wr::NativeTileId()) {
47 MOZ_ASSERT(mCompositor);
48 MOZ_ASSERT(mContext);
51 RenderCompositorLayersSWGL::~RenderCompositorLayersSWGL() {
52 wr_swgl_destroy_context(mContext);
55 bool RenderCompositorLayersSWGL::MakeCurrent() {
56 wr_swgl_make_current(mContext);
57 return true;
60 bool RenderCompositorLayersSWGL::BeginFrame() {
61 MOZ_ASSERT(!mInFrame);
62 MakeCurrent();
63 mInFrame = true;
64 return true;
67 void RenderCompositorLayersSWGL::CancelFrame() {
68 MOZ_ASSERT(mInFrame);
69 mInFrame = false;
70 if (mCompositingStarted) {
71 mCompositor->CancelFrame();
72 mCompositingStarted = false;
76 void RenderCompositorLayersSWGL::StartCompositing(
77 wr::ColorF aClearColor, const wr::DeviceIntRect* aDirtyRects,
78 size_t aNumDirtyRects, const wr::DeviceIntRect* aOpaqueRects,
79 size_t aNumOpaqueRects) {
80 MOZ_RELEASE_ASSERT(!mCompositingStarted);
82 if (!mInFrame || aNumDirtyRects == 0) {
83 return;
86 gfx::IntRect bounds(gfx::IntPoint(0, 0), GetBufferSize().ToUnknownSize());
87 nsIntRegion dirty;
89 MOZ_RELEASE_ASSERT(aNumDirtyRects > 0);
90 for (size_t i = 0; i < aNumDirtyRects; i++) {
91 const auto& rect = aDirtyRects[i];
92 dirty.OrWith(
93 gfx::IntRect(rect.min.x, rect.min.y, rect.width(), rect.height()));
95 dirty.AndWith(bounds);
97 nsIntRegion opaque(bounds);
98 opaque.SubOut(mWidget->GetTransparentRegion().ToUnknownRegion());
99 for (size_t i = 0; i < aNumOpaqueRects; i++) {
100 const auto& rect = aOpaqueRects[i];
101 opaque.OrWith(
102 gfx::IntRect(rect.min.x, rect.min.y, rect.width(), rect.height()));
105 mCompositor->SetClearColor(gfx::DeviceColor(aClearColor.r, aClearColor.g,
106 aClearColor.b, aClearColor.a));
108 if (!mCompositor->BeginFrameForWindow(dirty, Nothing(), bounds, opaque)) {
109 return;
111 mCompositingStarted = true;
114 void RenderCompositorLayersSWGL::CompositorEndFrame() {
115 nsTArray<FrameSurface> frameSurfaces = std::move(mFrameSurfaces);
117 if (!mCompositingStarted) {
118 return;
121 for (auto& frameSurface : frameSurfaces) {
122 auto surfaceCursor = mSurfaces.find(frameSurface.mId);
123 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
124 Surface* surface = surfaceCursor->second.get();
126 for (auto it = surface->mTiles.begin(); it != surface->mTiles.end(); ++it) {
127 if (!it->second->IsValid()) {
128 continue;
131 gfx::Point tileOffset(it->first.mX * surface->mTileSize.width,
132 it->first.mY * surface->mTileSize.height);
133 gfx::Rect drawRect = it->second->mValidRect + tileOffset;
135 RefPtr<TexturedEffect> texturedEffect =
136 new EffectRGB(it->second->GetTextureSource(),
137 /* aPremultiplied */ true, frameSurface.mFilter);
138 if (surface->mIsOpaque) {
139 texturedEffect->mPremultipliedCopy = true;
142 texturedEffect->mTextureCoords =
143 gfx::Rect(it->second->mValidRect.x / surface->mTileSize.width,
144 it->second->mValidRect.y / surface->mTileSize.height,
145 it->second->mValidRect.width / surface->mTileSize.width,
146 it->second->mValidRect.height / surface->mTileSize.height);
148 EffectChain effect;
149 effect.mPrimaryEffect = texturedEffect;
150 mCompositor->DrawQuad(drawRect, frameSurface.mClipRect, effect, 1.0,
151 frameSurface.mTransform, drawRect);
154 if (surface->mExternalImage) {
155 HandleExternalImage(surface->mExternalImage, frameSurface);
160 RenderedFrameId RenderCompositorLayersSWGL::EndFrame(
161 const nsTArray<DeviceIntRect>& aDirtyRects) {
162 MOZ_ASSERT(mInFrame);
163 mInFrame = false;
164 if (mCompositingStarted) {
165 mCompositor->EndFrame();
166 mCompositingStarted = false;
168 return GetNextRenderFrameId();
171 LayoutDeviceIntSize RenderCompositorLayersSWGL::GetBufferSize() {
172 return mWidget->GetClientSize();
175 void RenderCompositorLayersSWGL::Bind(wr::NativeTileId aId,
176 wr::DeviceIntPoint* aOffset,
177 uint32_t* aFboId,
178 wr::DeviceIntRect aDirtyRect,
179 wr::DeviceIntRect aValidRect) {
180 MOZ_RELEASE_ASSERT(false);
183 void RenderCompositorLayersSWGL::Unbind() { MOZ_RELEASE_ASSERT(false); }
185 bool RenderCompositorLayersSWGL::MapTile(wr::NativeTileId aId,
186 wr::DeviceIntRect aDirtyRect,
187 wr::DeviceIntRect aValidRect,
188 void** aData, int32_t* aStride) {
189 auto surfaceCursor = mSurfaces.find(aId.surface_id);
190 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
191 Surface* surface = surfaceCursor->second.get();
193 auto layerCursor = surface->mTiles.find(TileKey(aId.x, aId.y));
194 MOZ_RELEASE_ASSERT(layerCursor != surface->mTiles.end());
196 mCurrentTile = layerCursor->second.get();
197 mCurrentTileId = aId;
198 mCurrentTileDirty = gfx::IntRect(aDirtyRect.min.x, aDirtyRect.min.y,
199 aDirtyRect.width(), aDirtyRect.height());
201 if (!mCurrentTile->Map(aDirtyRect, aValidRect, aData, aStride)) {
202 gfxCriticalNote << "MapTile failed aValidRect: "
203 << gfx::Rect(aValidRect.min.x, aValidRect.min.y,
204 aValidRect.width(), aValidRect.height());
205 return false;
208 // Store the new valid rect, so that we can composite only those pixels
209 mCurrentTile->mValidRect = gfx::Rect(aValidRect.min.x, aValidRect.min.y,
210 aValidRect.width(), aValidRect.height());
211 return true;
214 void RenderCompositorLayersSWGL::UnmapTile() {
215 mCurrentTile->Unmap(mCurrentTileDirty);
216 mCurrentTile = nullptr;
219 void RenderCompositorLayersSWGL::CreateSurface(
220 wr::NativeSurfaceId aId, wr::DeviceIntPoint aVirtualOffset,
221 wr::DeviceIntSize aTileSize, bool aIsOpaque) {
222 MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
223 auto surface = DoCreateSurface(aTileSize, aIsOpaque);
224 mSurfaces.insert({aId, std::move(surface)});
227 UniquePtr<RenderCompositorLayersSWGL::Surface>
228 RenderCompositorLayersSWGL::DoCreateSurface(wr::DeviceIntSize aTileSize,
229 bool aIsOpaque) {
230 return MakeUnique<Surface>(aTileSize, aIsOpaque);
233 void RenderCompositorLayersSWGL::CreateExternalSurface(wr::NativeSurfaceId aId,
234 bool aIsOpaque) {
235 MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
236 auto surface = MakeUnique<Surface>(wr::DeviceIntSize{}, aIsOpaque);
237 surface->mIsExternal = true;
238 mSurfaces.insert({aId, std::move(surface)});
241 void RenderCompositorLayersSWGL::DestroySurface(NativeSurfaceId aId) {
242 auto surfaceCursor = mSurfaces.find(aId);
243 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
244 mSurfaces.erase(surfaceCursor);
247 void RenderCompositorLayersSWGL::CreateTile(wr::NativeSurfaceId aId, int32_t aX,
248 int32_t aY) {
249 auto surfaceCursor = mSurfaces.find(aId);
250 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
251 Surface* surface = surfaceCursor->second.get();
252 MOZ_RELEASE_ASSERT(!surface->mIsExternal);
254 auto tile = DoCreateTile(surface);
255 surface->mTiles.insert({TileKey(aX, aY), std::move(tile)});
258 void RenderCompositorLayersSWGL::DestroyTile(wr::NativeSurfaceId aId,
259 int32_t aX, int32_t aY) {
260 auto surfaceCursor = mSurfaces.find(aId);
261 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
262 Surface* surface = surfaceCursor->second.get();
263 MOZ_RELEASE_ASSERT(!surface->mIsExternal);
265 auto layerCursor = surface->mTiles.find(TileKey(aX, aY));
266 MOZ_RELEASE_ASSERT(layerCursor != surface->mTiles.end());
267 surface->mTiles.erase(layerCursor);
270 void RenderCompositorLayersSWGL::AttachExternalImage(
271 wr::NativeSurfaceId aId, wr::ExternalImageId aExternalImage) {
272 RenderTextureHost* image =
273 RenderThread::Get()->GetRenderTexture(aExternalImage);
274 MOZ_ASSERT(image);
275 if (!image) {
276 gfxCriticalNoteOnce
277 << "Failed to get RenderTextureHost for D3D11SWGL extId:"
278 << AsUint64(aExternalImage);
279 return;
281 #if defined(XP_WIN)
282 MOZ_RELEASE_ASSERT(image->AsRenderDXGITextureHost() ||
283 image->AsRenderDXGIYCbCrTextureHost());
284 #elif defined(ANDROID)
285 MOZ_RELEASE_ASSERT(image->AsRenderAndroidHardwareBufferTextureHost() ||
286 image->AsRenderAndroidSurfaceTextureHost() ||
287 image->AsRenderEGLImageTextureHost());
288 #endif
290 auto surfaceCursor = mSurfaces.find(aId);
291 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
293 Surface* surface = surfaceCursor->second.get();
294 surface->mExternalImage = image;
295 MOZ_RELEASE_ASSERT(surface->mTiles.empty());
296 MOZ_RELEASE_ASSERT(surface->mIsExternal);
299 // static
300 gfx::SamplingFilter RenderCompositorLayersSWGL::ToSamplingFilter(
301 wr::ImageRendering aImageRendering) {
302 if (aImageRendering == wr::ImageRendering::Auto) {
303 return gfx::SamplingFilter::LINEAR;
305 return gfx::SamplingFilter::POINT;
308 void RenderCompositorLayersSWGL::AddSurface(
309 wr::NativeSurfaceId aId, const wr::CompositorSurfaceTransform& aTransform,
310 wr::DeviceIntRect aClipRect, wr::ImageRendering aImageRendering) {
311 float sx = aTransform.scale.x;
312 float sy = aTransform.scale.y;
313 float tx = aTransform.offset.x;
314 float ty = aTransform.offset.y;
315 gfx::Matrix4x4 transform(sx, 0.0, 0.0, 0.0, 0.0, sy, 0.0, 0.0, 0.0, 0.0, 1.0,
316 0.0, tx, ty, 0.0, 1.0);
317 gfx::IntRect clipRect(aClipRect.min.x, aClipRect.min.y, aClipRect.width(),
318 aClipRect.height());
320 mFrameSurfaces.AppendElement(FrameSurface{aId, transform, clipRect,
321 ToSamplingFilter(aImageRendering)});
324 void RenderCompositorLayersSWGL::MaybeRequestAllowFrameRecording(
325 bool aWillRecord) {
326 mCompositor->RequestAllowFrameRecording(aWillRecord);
329 class WindowLMC : public profiler_screenshots::Window {
330 public:
331 explicit WindowLMC(Compositor* aCompositor) : mCompositor(aCompositor) {}
333 already_AddRefed<profiler_screenshots::RenderSource> GetWindowContents(
334 const gfx::IntSize& aWindowSize) override;
335 already_AddRefed<profiler_screenshots::DownscaleTarget> CreateDownscaleTarget(
336 const gfx::IntSize& aSize) override;
337 already_AddRefed<profiler_screenshots::AsyncReadbackBuffer>
338 CreateAsyncReadbackBuffer(const gfx::IntSize& aSize) override;
340 protected:
341 Compositor* mCompositor;
344 class RenderSourceLMC : public profiler_screenshots::RenderSource {
345 public:
346 explicit RenderSourceLMC(CompositingRenderTarget* aRT)
347 : RenderSource(aRT->GetSize()), mRT(aRT) {}
349 const auto& RenderTarget() { return mRT; }
351 protected:
352 virtual ~RenderSourceLMC() {}
354 RefPtr<CompositingRenderTarget> mRT;
357 class DownscaleTargetLMC : public profiler_screenshots::DownscaleTarget {
358 public:
359 explicit DownscaleTargetLMC(CompositingRenderTarget* aRT,
360 Compositor* aCompositor)
361 : profiler_screenshots::DownscaleTarget(aRT->GetSize()),
362 mRenderSource(new RenderSourceLMC(aRT)),
363 mCompositor(aCompositor) {}
365 already_AddRefed<profiler_screenshots::RenderSource> AsRenderSource()
366 override {
367 return do_AddRef(mRenderSource);
370 bool DownscaleFrom(profiler_screenshots::RenderSource* aSource,
371 const IntRect& aSourceRect,
372 const IntRect& aDestRect) override {
373 MOZ_RELEASE_ASSERT(aSourceRect.TopLeft() == IntPoint());
374 MOZ_RELEASE_ASSERT(aDestRect.TopLeft() == IntPoint());
375 RefPtr<CompositingRenderTarget> previousTarget =
376 mCompositor->GetCurrentRenderTarget();
378 mCompositor->SetRenderTarget(mRenderSource->RenderTarget());
379 bool result = mCompositor->BlitRenderTarget(
380 static_cast<RenderSourceLMC*>(aSource)->RenderTarget(),
381 aSourceRect.Size(), aDestRect.Size());
383 // Restore the old render target.
384 mCompositor->SetRenderTarget(previousTarget);
386 return result;
389 protected:
390 virtual ~DownscaleTargetLMC() {}
392 RefPtr<RenderSourceLMC> mRenderSource;
393 Compositor* mCompositor;
396 class AsyncReadbackBufferLMC
397 : public profiler_screenshots::AsyncReadbackBuffer {
398 public:
399 AsyncReadbackBufferLMC(mozilla::layers::AsyncReadbackBuffer* aARB,
400 Compositor* aCompositor)
401 : profiler_screenshots::AsyncReadbackBuffer(aARB->GetSize()),
402 mARB(aARB),
403 mCompositor(aCompositor) {}
404 void CopyFrom(profiler_screenshots::RenderSource* aSource) override {
405 mCompositor->ReadbackRenderTarget(
406 static_cast<RenderSourceLMC*>(aSource)->RenderTarget(), mARB);
408 bool MapAndCopyInto(DataSourceSurface* aSurface,
409 const IntSize& aReadSize) override {
410 return mARB->MapAndCopyInto(aSurface, aReadSize);
413 protected:
414 virtual ~AsyncReadbackBufferLMC() {}
416 RefPtr<mozilla::layers::AsyncReadbackBuffer> mARB;
417 Compositor* mCompositor;
420 already_AddRefed<profiler_screenshots::RenderSource>
421 WindowLMC::GetWindowContents(const gfx::IntSize& aWindowSize) {
422 RefPtr<CompositingRenderTarget> rt = mCompositor->GetWindowRenderTarget();
423 if (!rt) {
424 return nullptr;
426 return MakeAndAddRef<RenderSourceLMC>(rt);
429 already_AddRefed<profiler_screenshots::DownscaleTarget>
430 WindowLMC::CreateDownscaleTarget(const gfx::IntSize& aSize) {
431 RefPtr<CompositingRenderTarget> rt =
432 mCompositor->CreateRenderTarget(IntRect({}, aSize), INIT_MODE_NONE);
433 return MakeAndAddRef<DownscaleTargetLMC>(rt, mCompositor);
436 already_AddRefed<profiler_screenshots::AsyncReadbackBuffer>
437 WindowLMC::CreateAsyncReadbackBuffer(const gfx::IntSize& aSize) {
438 RefPtr<AsyncReadbackBuffer> carb =
439 mCompositor->CreateAsyncReadbackBuffer(aSize);
440 if (!carb) {
441 return nullptr;
443 return MakeAndAddRef<AsyncReadbackBufferLMC>(carb, mCompositor);
446 bool RenderCompositorLayersSWGL::MaybeRecordFrame(
447 layers::CompositionRecorder& aRecorder) {
448 WindowLMC window(mCompositor);
449 gfx::IntSize size = GetBufferSize().ToUnknownSize();
450 RefPtr<layers::profiler_screenshots::RenderSource> snapshot =
451 window.GetWindowContents(size);
452 if (!snapshot) {
453 return true;
456 RefPtr<layers::profiler_screenshots::AsyncReadbackBuffer> buffer =
457 window.CreateAsyncReadbackBuffer(size);
458 buffer->CopyFrom(snapshot);
460 RefPtr<layers::RecordedFrame> frame =
461 new RenderCompositorRecordedFrame(TimeStamp::Now(), std::move(buffer));
462 aRecorder.RecordFrame(frame);
463 return false;
466 bool RenderCompositorLayersSWGL::MaybeGrabScreenshot(
467 const gfx::IntSize& aWindowSize) {
468 if (!mCompositingStarted) {
469 return true;
471 WindowLMC window(mCompositor);
472 mProfilerScreenshotGrabber.MaybeGrabScreenshot(window, aWindowSize);
473 return true;
476 bool RenderCompositorLayersSWGL::MaybeProcessScreenshotQueue() {
477 mProfilerScreenshotGrabber.MaybeProcessQueue();
478 return true;
481 } // namespace wr
482 } // namespace mozilla