Bug 1874684 - Part 28: Return DateDuration from DifferenceISODateTime. r=mgaudet
[gecko.git] / gfx / webrender_bindings / RenderCompositorNative.cpp
blob3b5a29948ef81b84e806adc57eacdfd59ef88aaf
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 "RenderCompositorNative.h"
9 #include "GLContext.h"
10 #include "GLContextProvider.h"
11 #include "mozilla/ProfilerLabels.h"
12 #include "mozilla/ProfilerMarkers.h"
13 #include "mozilla/gfx/gfxVars.h"
14 #include "mozilla/gfx/Logging.h"
15 #include "mozilla/layers/CompositionRecorder.h"
16 #include "mozilla/layers/NativeLayer.h"
17 #include "mozilla/layers/SurfacePool.h"
18 #include "mozilla/StaticPrefs_gfx.h"
19 #include "mozilla/webrender/RenderThread.h"
20 #include "mozilla/widget/CompositorWidget.h"
21 #include "RenderCompositorRecordedFrame.h"
23 namespace mozilla::wr {
25 extern LazyLogModule gRenderThreadLog;
26 #define LOG(...) MOZ_LOG(gRenderThreadLog, LogLevel::Debug, (__VA_ARGS__))
28 RenderCompositorNative::RenderCompositorNative(
29 const RefPtr<widget::CompositorWidget>& aWidget, gl::GLContext* aGL)
30 : RenderCompositor(aWidget),
31 mNativeLayerRoot(GetWidget()->GetNativeLayerRoot()) {
32 LOG("RenderCompositorNative::RenderCompositorNative()");
34 #if defined(XP_DARWIN) || defined(MOZ_WAYLAND)
35 auto pool = RenderThread::Get()->SharedSurfacePool();
36 if (pool) {
37 mSurfacePoolHandle = pool->GetHandleForGL(aGL);
39 #endif
40 MOZ_RELEASE_ASSERT(mSurfacePoolHandle);
43 RenderCompositorNative::~RenderCompositorNative() {
44 LOG("RRenderCompositorNative::~RenderCompositorNative()");
46 Pause();
47 mProfilerScreenshotGrabber.Destroy();
48 mNativeLayerRoot->SetLayers({});
49 mNativeLayerForEntireWindow = nullptr;
50 mNativeLayerRootSnapshotter = nullptr;
51 mNativeLayerRoot = nullptr;
54 bool RenderCompositorNative::BeginFrame() {
55 if (!MakeCurrent()) {
56 gfxCriticalNote << "Failed to make render context current, can't draw.";
57 return false;
60 gfx::IntSize bufferSize = GetBufferSize().ToUnknownSize();
61 if (!ShouldUseNativeCompositor()) {
62 if (bufferSize.IsEmpty()) {
63 return false;
65 if (mNativeLayerForEntireWindow &&
66 mNativeLayerForEntireWindow->GetSize() != bufferSize) {
67 mNativeLayerRoot->RemoveLayer(mNativeLayerForEntireWindow);
68 mNativeLayerForEntireWindow = nullptr;
70 if (!mNativeLayerForEntireWindow) {
71 mNativeLayerForEntireWindow =
72 mNativeLayerRoot->CreateLayer(bufferSize, false, mSurfacePoolHandle);
73 mNativeLayerRoot->AppendLayer(mNativeLayerForEntireWindow);
77 gfx::IntRect bounds({}, bufferSize);
78 if (!InitDefaultFramebuffer(bounds)) {
79 return false;
82 return true;
85 RenderedFrameId RenderCompositorNative::EndFrame(
86 const nsTArray<DeviceIntRect>& aDirtyRects) {
87 RenderedFrameId frameId = GetNextRenderFrameId();
89 DoSwap();
91 if (mNativeLayerForEntireWindow) {
92 mNativeLayerForEntireWindow->NotifySurfaceReady();
93 mNativeLayerRoot->CommitToScreen();
96 return frameId;
99 void RenderCompositorNative::Pause() {}
101 bool RenderCompositorNative::Resume() { return true; }
103 inline layers::WebRenderCompositor RenderCompositorNative::CompositorType()
104 const {
105 if (gfx::gfxVars::UseWebRenderCompositor()) {
106 #if defined(XP_DARWIN)
107 return layers::WebRenderCompositor::CORE_ANIMATION;
108 #elif defined(MOZ_WAYLAND)
109 return layers::WebRenderCompositor::WAYLAND;
110 #endif
112 return layers::WebRenderCompositor::DRAW;
115 LayoutDeviceIntSize RenderCompositorNative::GetBufferSize() {
116 return mWidget->GetClientSize();
119 bool RenderCompositorNative::ShouldUseNativeCompositor() {
120 return gfx::gfxVars::UseWebRenderCompositor();
123 void RenderCompositorNative::GetCompositorCapabilities(
124 CompositorCapabilities* aCaps) {
125 RenderCompositor::GetCompositorCapabilities(aCaps);
126 #if defined(XP_DARWIN)
127 aCaps->supports_surface_for_backdrop = !gfx::gfxVars::UseSoftwareWebRender();
128 #endif
131 bool RenderCompositorNative::MaybeReadback(
132 const gfx::IntSize& aReadbackSize, const wr::ImageFormat& aReadbackFormat,
133 const Range<uint8_t>& aReadbackBuffer, bool* aNeedsYFlip) {
134 if (!ShouldUseNativeCompositor()) {
135 return false;
138 MOZ_RELEASE_ASSERT(aReadbackFormat == wr::ImageFormat::BGRA8);
139 if (!mNativeLayerRootSnapshotter) {
140 mNativeLayerRootSnapshotter = mNativeLayerRoot->CreateSnapshotter();
142 if (!mNativeLayerRootSnapshotter) {
143 return false;
146 bool success = mNativeLayerRootSnapshotter->ReadbackPixels(
147 aReadbackSize, gfx::SurfaceFormat::B8G8R8A8, aReadbackBuffer);
149 // ReadbackPixels might have changed the current context. Make sure GL is
150 // current again.
151 MakeCurrent();
153 if (aNeedsYFlip) {
154 *aNeedsYFlip = true;
157 return success;
160 bool RenderCompositorNative::MaybeRecordFrame(
161 layers::CompositionRecorder& aRecorder) {
162 if (!ShouldUseNativeCompositor()) {
163 return false;
166 if (!mNativeLayerRootSnapshotter) {
167 mNativeLayerRootSnapshotter = mNativeLayerRoot->CreateSnapshotter();
170 if (!mNativeLayerRootSnapshotter) {
171 return true;
174 gfx::IntSize size = GetBufferSize().ToUnknownSize();
175 RefPtr<layers::profiler_screenshots::RenderSource> snapshot =
176 mNativeLayerRootSnapshotter->GetWindowContents(size);
177 if (!snapshot) {
178 return true;
181 RefPtr<layers::profiler_screenshots::AsyncReadbackBuffer> buffer =
182 mNativeLayerRootSnapshotter->CreateAsyncReadbackBuffer(size);
183 buffer->CopyFrom(snapshot);
185 RefPtr<layers::RecordedFrame> frame =
186 new RenderCompositorRecordedFrame(TimeStamp::Now(), std::move(buffer));
187 aRecorder.RecordFrame(frame);
189 // GetWindowContents might have changed the current context. Make sure our
190 // context is current again.
191 MakeCurrent();
192 return true;
195 bool RenderCompositorNative::MaybeGrabScreenshot(
196 const gfx::IntSize& aWindowSize) {
197 if (!ShouldUseNativeCompositor()) {
198 return false;
201 if (!mNativeLayerRootSnapshotter) {
202 mNativeLayerRootSnapshotter = mNativeLayerRoot->CreateSnapshotter();
205 if (mNativeLayerRootSnapshotter) {
206 mProfilerScreenshotGrabber.MaybeGrabScreenshot(*mNativeLayerRootSnapshotter,
207 aWindowSize);
209 // MaybeGrabScreenshot might have changed the current context. Make sure our
210 // context is current again.
211 MakeCurrent();
214 return true;
217 bool RenderCompositorNative::MaybeProcessScreenshotQueue() {
218 if (!ShouldUseNativeCompositor()) {
219 return false;
222 mProfilerScreenshotGrabber.MaybeProcessQueue();
224 // MaybeProcessQueue might have changed the current context. Make sure our
225 // context is current again.
226 MakeCurrent();
228 return true;
231 void RenderCompositorNative::CompositorBeginFrame() {
232 mAddedLayers.Clear();
233 mAddedTilePixelCount = 0;
234 mAddedClippedPixelCount = 0;
235 mBeginFrameTimeStamp = TimeStamp::Now();
236 mSurfacePoolHandle->OnBeginFrame();
237 mNativeLayerRoot->PrepareForCommit();
240 void RenderCompositorNative::CompositorEndFrame() {
241 if (profiler_thread_is_being_profiled_for_markers()) {
242 auto bufferSize = GetBufferSize();
243 [[maybe_unused]] uint64_t windowPixelCount =
244 uint64_t(bufferSize.width) * bufferSize.height;
245 int nativeLayerCount = 0;
246 for (const auto& it : mSurfaces) {
247 nativeLayerCount += int(it.second.mNativeLayers.size());
249 PROFILER_MARKER_TEXT(
250 "WR OS Compositor frame", GRAPHICS,
251 MarkerTiming::IntervalUntilNowFrom(mBeginFrameTimeStamp),
252 nsPrintfCString("%d%% painting, %d%% overdraw, %d used "
253 "layers (%d%% memory) + %d unused layers (%d%% memory)",
254 int(mDrawnPixelCount * 100 / windowPixelCount),
255 int(mAddedClippedPixelCount * 100 / windowPixelCount),
256 int(mAddedLayers.Length()),
257 int(mAddedTilePixelCount * 100 / windowPixelCount),
258 int(nativeLayerCount - mAddedLayers.Length()),
259 int((mTotalTilePixelCount - mAddedTilePixelCount) *
260 100 / windowPixelCount)));
262 mDrawnPixelCount = 0;
264 DoFlush();
266 mNativeLayerRoot->SetLayers(mAddedLayers);
267 mNativeLayerRoot->CommitToScreen();
268 mSurfacePoolHandle->OnEndFrame();
271 void RenderCompositorNative::BindNativeLayer(wr::NativeTileId aId,
272 const gfx::IntRect& aDirtyRect) {
273 MOZ_RELEASE_ASSERT(!mCurrentlyBoundNativeLayer);
275 auto surfaceCursor = mSurfaces.find(aId.surface_id);
276 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
277 Surface& surface = surfaceCursor->second;
279 auto layerCursor = surface.mNativeLayers.find(TileKey(aId.x, aId.y));
280 MOZ_RELEASE_ASSERT(layerCursor != surface.mNativeLayers.end());
281 RefPtr<layers::NativeLayer> layer = layerCursor->second;
283 mCurrentlyBoundNativeLayer = layer;
285 mDrawnPixelCount += aDirtyRect.Area();
288 void RenderCompositorNative::UnbindNativeLayer() {
289 MOZ_RELEASE_ASSERT(mCurrentlyBoundNativeLayer);
291 mCurrentlyBoundNativeLayer->NotifySurfaceReady();
292 mCurrentlyBoundNativeLayer = nullptr;
295 void RenderCompositorNative::CreateSurface(wr::NativeSurfaceId aId,
296 wr::DeviceIntPoint aVirtualOffset,
297 wr::DeviceIntSize aTileSize,
298 bool aIsOpaque) {
299 MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
300 mSurfaces.insert({aId, Surface{aTileSize, aIsOpaque}});
303 void RenderCompositorNative::CreateExternalSurface(wr::NativeSurfaceId aId,
304 bool aIsOpaque) {
305 MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
307 RefPtr<layers::NativeLayer> layer =
308 mNativeLayerRoot->CreateLayerForExternalTexture(aIsOpaque);
310 Surface surface{DeviceIntSize{}, aIsOpaque};
311 surface.mIsExternal = true;
312 surface.mNativeLayers.insert({TileKey(0, 0), layer});
314 mSurfaces.insert({aId, std::move(surface)});
317 void RenderCompositorNative::CreateBackdropSurface(wr::NativeSurfaceId aId,
318 wr::ColorF aColor) {
319 MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
321 gfx::DeviceColor color(aColor.r, aColor.g, aColor.b, aColor.a);
322 RefPtr<layers::NativeLayer> layer =
323 mNativeLayerRoot->CreateLayerForColor(color);
325 Surface surface{DeviceIntSize{}, (aColor.a >= 1.0f)};
326 surface.mNativeLayers.insert({TileKey(0, 0), layer});
328 mSurfaces.insert({aId, std::move(surface)});
331 void RenderCompositorNative::AttachExternalImage(
332 wr::NativeSurfaceId aId, wr::ExternalImageId aExternalImage) {
333 RenderTextureHost* image =
334 RenderThread::Get()->GetRenderTexture(aExternalImage);
335 MOZ_RELEASE_ASSERT(image);
337 auto surfaceCursor = mSurfaces.find(aId);
338 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
340 Surface& surface = surfaceCursor->second;
341 MOZ_RELEASE_ASSERT(surface.mNativeLayers.size() == 1);
342 MOZ_RELEASE_ASSERT(surface.mIsExternal);
343 surface.mNativeLayers.begin()->second->AttachExternalImage(image);
346 void RenderCompositorNative::DestroySurface(NativeSurfaceId aId) {
347 auto surfaceCursor = mSurfaces.find(aId);
348 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
350 Surface& surface = surfaceCursor->second;
351 if (!surface.mIsExternal) {
352 for (const auto& iter : surface.mNativeLayers) {
353 mTotalTilePixelCount -= gfx::IntRect({}, iter.second->GetSize()).Area();
357 mSurfaces.erase(surfaceCursor);
360 void RenderCompositorNative::CreateTile(wr::NativeSurfaceId aId, int aX,
361 int aY) {
362 auto surfaceCursor = mSurfaces.find(aId);
363 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
364 Surface& surface = surfaceCursor->second;
365 MOZ_RELEASE_ASSERT(!surface.mIsExternal);
367 RefPtr<layers::NativeLayer> layer = mNativeLayerRoot->CreateLayer(
368 surface.TileSize(), surface.mIsOpaque, mSurfacePoolHandle);
369 surface.mNativeLayers.insert({TileKey(aX, aY), layer});
370 mTotalTilePixelCount += gfx::IntRect({}, layer->GetSize()).Area();
373 void RenderCompositorNative::DestroyTile(wr::NativeSurfaceId aId, int aX,
374 int aY) {
375 auto surfaceCursor = mSurfaces.find(aId);
376 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
377 Surface& surface = surfaceCursor->second;
378 MOZ_RELEASE_ASSERT(!surface.mIsExternal);
380 auto layerCursor = surface.mNativeLayers.find(TileKey(aX, aY));
381 MOZ_RELEASE_ASSERT(layerCursor != surface.mNativeLayers.end());
382 RefPtr<layers::NativeLayer> layer = std::move(layerCursor->second);
383 surface.mNativeLayers.erase(layerCursor);
384 mTotalTilePixelCount -= gfx::IntRect({}, layer->GetSize()).Area();
386 // If the layer is currently present in mNativeLayerRoot, it will be destroyed
387 // once CompositorEndFrame() replaces mNativeLayerRoot's layers and drops that
388 // reference. So until that happens, the layer still needs to hold on to its
389 // front buffer. However, we can tell it to drop its back buffers now, because
390 // we know that we will never draw to it again.
391 // Dropping the back buffers now puts them back in the surface pool, so those
392 // surfaces can be immediately re-used for drawing in other layers in the
393 // current frame.
394 layer->DiscardBackbuffers();
397 gfx::SamplingFilter ToSamplingFilter(wr::ImageRendering aImageRendering) {
398 if (aImageRendering == wr::ImageRendering::Auto) {
399 return gfx::SamplingFilter::LINEAR;
401 return gfx::SamplingFilter::POINT;
404 void RenderCompositorNative::AddSurface(
405 wr::NativeSurfaceId aId, const wr::CompositorSurfaceTransform& aTransform,
406 wr::DeviceIntRect aClipRect, wr::ImageRendering aImageRendering) {
407 MOZ_RELEASE_ASSERT(!mCurrentlyBoundNativeLayer);
409 auto surfaceCursor = mSurfaces.find(aId);
410 MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
411 const Surface& surface = surfaceCursor->second;
413 float sx = aTransform.scale.x;
414 float sy = aTransform.scale.y;
415 float tx = aTransform.offset.x;
416 float ty = aTransform.offset.y;
417 gfx::Matrix4x4 transform(sx, 0.0, 0.0, 0.0, 0.0, sy, 0.0, 0.0, 0.0, 0.0, 1.0,
418 0.0, tx, ty, 0.0, 1.0);
420 for (auto it = surface.mNativeLayers.begin();
421 it != surface.mNativeLayers.end(); ++it) {
422 RefPtr<layers::NativeLayer> layer = it->second;
423 gfx::IntSize layerSize = layer->GetSize();
424 gfx::IntPoint layerPosition(surface.mTileSize.width * it->first.mX,
425 surface.mTileSize.height * it->first.mY);
426 layer->SetPosition(layerPosition);
427 gfx::IntRect clipRect(aClipRect.min.x, aClipRect.min.y, aClipRect.width(),
428 aClipRect.height());
429 layer->SetClipRect(Some(clipRect));
430 layer->SetTransform(transform);
431 layer->SetSamplingFilter(ToSamplingFilter(aImageRendering));
432 mAddedLayers.AppendElement(layer);
434 if (!surface.mIsExternal) {
435 mAddedTilePixelCount += layerSize.width * layerSize.height;
437 gfx::Rect r = transform.TransformBounds(
438 gfx::Rect(layer->CurrentSurfaceDisplayRect()));
439 gfx::IntRect visibleRect =
440 clipRect.Intersect(RoundedToInt(r) + layerPosition);
441 mAddedClippedPixelCount += visibleRect.Area();
445 /* static */
446 UniquePtr<RenderCompositor> RenderCompositorNativeOGL::Create(
447 const RefPtr<widget::CompositorWidget>& aWidget, nsACString& aError) {
448 RefPtr<gl::GLContext> gl = RenderThread::Get()->SingletonGL();
449 if (!gl) {
450 gl = gl::GLContextProvider::CreateForCompositorWidget(
451 aWidget, /* aHardwareWebRender */ true, /* aForceAccelerated */ true);
452 RenderThread::MaybeEnableGLDebugMessage(gl);
454 if (!gl || !gl->MakeCurrent()) {
455 gfxCriticalNote << "Failed GL context creation for WebRender: "
456 << gfx::hexa(gl.get());
457 return nullptr;
459 return MakeUnique<RenderCompositorNativeOGL>(aWidget, std::move(gl));
462 RenderCompositorNativeOGL::RenderCompositorNativeOGL(
463 const RefPtr<widget::CompositorWidget>& aWidget,
464 RefPtr<gl::GLContext>&& aGL)
465 : RenderCompositorNative(aWidget, aGL), mGL(aGL) {
466 MOZ_ASSERT(mGL);
469 RenderCompositorNativeOGL::~RenderCompositorNativeOGL() {
470 if (!mGL->MakeCurrent()) {
471 gfxCriticalNote
472 << "Failed to make render context current during destroying.";
473 // Leak resources!
474 mPreviousFrameDoneSync = nullptr;
475 mThisFrameDoneSync = nullptr;
476 return;
479 if (mPreviousFrameDoneSync) {
480 mGL->fDeleteSync(mPreviousFrameDoneSync);
482 if (mThisFrameDoneSync) {
483 mGL->fDeleteSync(mThisFrameDoneSync);
487 bool RenderCompositorNativeOGL::InitDefaultFramebuffer(
488 const gfx::IntRect& aBounds) {
489 if (mNativeLayerForEntireWindow) {
490 Maybe<GLuint> fbo = mNativeLayerForEntireWindow->NextSurfaceAsFramebuffer(
491 aBounds, aBounds, true);
492 if (!fbo) {
493 return false;
495 mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, *fbo);
496 } else {
497 mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mGL->GetDefaultFramebuffer());
499 return true;
502 void RenderCompositorNativeOGL::DoSwap() {
503 InsertFrameDoneSync();
504 if (mNativeLayerForEntireWindow) {
505 mGL->fFlush();
509 void RenderCompositorNativeOGL::DoFlush() { mGL->fFlush(); }
511 void RenderCompositorNativeOGL::InsertFrameDoneSync() {
512 #ifdef XP_DARWIN
513 // Only do this on macOS.
514 // On other platforms, SwapBuffers automatically applies back-pressure.
515 if (mThisFrameDoneSync) {
516 mGL->fDeleteSync(mThisFrameDoneSync);
518 mThisFrameDoneSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
519 #endif
522 bool RenderCompositorNativeOGL::WaitForGPU() {
523 if (mPreviousFrameDoneSync) {
524 AUTO_PROFILER_LABEL("Waiting for GPU to finish previous frame", GRAPHICS);
525 mGL->fClientWaitSync(mPreviousFrameDoneSync,
526 LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT,
527 LOCAL_GL_TIMEOUT_IGNORED);
528 mGL->fDeleteSync(mPreviousFrameDoneSync);
530 mPreviousFrameDoneSync = mThisFrameDoneSync;
531 mThisFrameDoneSync = nullptr;
533 return true;
536 void RenderCompositorNativeOGL::Bind(wr::NativeTileId aId,
537 wr::DeviceIntPoint* aOffset,
538 uint32_t* aFboId,
539 wr::DeviceIntRect aDirtyRect,
540 wr::DeviceIntRect aValidRect) {
541 gfx::IntRect validRect(aValidRect.min.x, aValidRect.min.y, aValidRect.width(),
542 aValidRect.height());
543 gfx::IntRect dirtyRect(aDirtyRect.min.x, aDirtyRect.min.y, aDirtyRect.width(),
544 aDirtyRect.height());
546 BindNativeLayer(aId, dirtyRect);
548 Maybe<GLuint> fbo = mCurrentlyBoundNativeLayer->NextSurfaceAsFramebuffer(
549 validRect, dirtyRect, true);
551 *aFboId = *fbo;
552 *aOffset = wr::DeviceIntPoint{0, 0};
555 void RenderCompositorNativeOGL::Unbind() {
556 mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
558 UnbindNativeLayer();
561 /* static */
562 UniquePtr<RenderCompositor> RenderCompositorNativeSWGL::Create(
563 const RefPtr<widget::CompositorWidget>& aWidget, nsACString& aError) {
564 void* ctx = wr_swgl_create_context();
565 if (!ctx) {
566 gfxCriticalNote << "Failed SWGL context creation for WebRender";
567 return nullptr;
569 return MakeUnique<RenderCompositorNativeSWGL>(aWidget, ctx);
572 RenderCompositorNativeSWGL::RenderCompositorNativeSWGL(
573 const RefPtr<widget::CompositorWidget>& aWidget, void* aContext)
574 : RenderCompositorNative(aWidget), mContext(aContext) {
575 MOZ_ASSERT(mContext);
578 RenderCompositorNativeSWGL::~RenderCompositorNativeSWGL() {
579 wr_swgl_destroy_context(mContext);
582 bool RenderCompositorNativeSWGL::MakeCurrent() {
583 wr_swgl_make_current(mContext);
584 return true;
587 bool RenderCompositorNativeSWGL::InitDefaultFramebuffer(
588 const gfx::IntRect& aBounds) {
589 if (mNativeLayerForEntireWindow) {
590 if (!MapNativeLayer(mNativeLayerForEntireWindow, aBounds, aBounds)) {
591 return false;
593 wr_swgl_init_default_framebuffer(mContext, aBounds.x, aBounds.y,
594 aBounds.width, aBounds.height,
595 mLayerStride, mLayerValidRectData);
597 return true;
600 void RenderCompositorNativeSWGL::CancelFrame() {
601 if (mNativeLayerForEntireWindow && mLayerTarget) {
602 wr_swgl_init_default_framebuffer(mContext, 0, 0, 0, 0, 0, nullptr);
603 UnmapNativeLayer();
607 void RenderCompositorNativeSWGL::DoSwap() {
608 if (mNativeLayerForEntireWindow && mLayerTarget) {
609 wr_swgl_init_default_framebuffer(mContext, 0, 0, 0, 0, 0, nullptr);
610 UnmapNativeLayer();
614 bool RenderCompositorNativeSWGL::MapNativeLayer(
615 layers::NativeLayer* aLayer, const gfx::IntRect& aDirtyRect,
616 const gfx::IntRect& aValidRect) {
617 uint8_t* data = nullptr;
618 gfx::IntSize size;
619 int32_t stride = 0;
620 gfx::SurfaceFormat format = gfx::SurfaceFormat::UNKNOWN;
621 RefPtr<gfx::DrawTarget> dt = aLayer->NextSurfaceAsDrawTarget(
622 aValidRect, gfx::IntRegion(aDirtyRect), gfx::BackendType::SKIA);
623 if (!dt || !dt->LockBits(&data, &size, &stride, &format)) {
624 return false;
626 MOZ_ASSERT(format == gfx::SurfaceFormat::B8G8R8A8 ||
627 format == gfx::SurfaceFormat::B8G8R8X8);
628 mLayerTarget = std::move(dt);
629 mLayerData = data;
630 mLayerValidRectData = data + aValidRect.y * stride + aValidRect.x * 4;
631 mLayerStride = stride;
632 return true;
635 void RenderCompositorNativeSWGL::UnmapNativeLayer() {
636 MOZ_ASSERT(mLayerTarget && mLayerData);
637 mLayerTarget->ReleaseBits(mLayerData);
638 mLayerTarget = nullptr;
639 mLayerData = nullptr;
640 mLayerValidRectData = nullptr;
641 mLayerStride = 0;
644 bool RenderCompositorNativeSWGL::MapTile(wr::NativeTileId aId,
645 wr::DeviceIntRect aDirtyRect,
646 wr::DeviceIntRect aValidRect,
647 void** aData, int32_t* aStride) {
648 if (mNativeLayerForEntireWindow) {
649 return false;
651 gfx::IntRect dirtyRect(aDirtyRect.min.x, aDirtyRect.min.y, aDirtyRect.width(),
652 aDirtyRect.height());
653 gfx::IntRect validRect(aValidRect.min.x, aValidRect.min.y, aValidRect.width(),
654 aValidRect.height());
655 BindNativeLayer(aId, dirtyRect);
656 if (!MapNativeLayer(mCurrentlyBoundNativeLayer, dirtyRect, validRect)) {
657 UnbindNativeLayer();
658 return false;
660 *aData = mLayerValidRectData;
661 *aStride = mLayerStride;
662 return true;
665 void RenderCompositorNativeSWGL::UnmapTile() {
666 if (!mNativeLayerForEntireWindow && mCurrentlyBoundNativeLayer) {
667 UnmapNativeLayer();
668 UnbindNativeLayer();
672 } // namespace mozilla::wr