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"
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/GpuFence.h"
17 #include "mozilla/layers/NativeLayer.h"
18 #include "mozilla/layers/SurfacePool.h"
19 #include "mozilla/StaticPrefs_gfx.h"
20 #include "mozilla/webrender/RenderThread.h"
21 #include "mozilla/widget/CompositorWidget.h"
22 #include "RenderCompositorRecordedFrame.h"
24 namespace mozilla::wr
{
26 extern LazyLogModule gRenderThreadLog
;
27 #define LOG(...) MOZ_LOG(gRenderThreadLog, LogLevel::Debug, (__VA_ARGS__))
29 RenderCompositorNative::RenderCompositorNative(
30 const RefPtr
<widget::CompositorWidget
>& aWidget
, gl::GLContext
* aGL
)
31 : RenderCompositor(aWidget
),
32 mNativeLayerRoot(GetWidget()->GetNativeLayerRoot()) {
33 LOG("RenderCompositorNative::RenderCompositorNative()");
35 #if defined(XP_DARWIN) || defined(MOZ_WAYLAND)
36 auto pool
= RenderThread::Get()->SharedSurfacePool();
38 mSurfacePoolHandle
= pool
->GetHandleForGL(aGL
);
41 MOZ_RELEASE_ASSERT(mSurfacePoolHandle
);
44 RenderCompositorNative::~RenderCompositorNative() {
45 LOG("RRenderCompositorNative::~RenderCompositorNative()");
48 mProfilerScreenshotGrabber
.Destroy();
49 mNativeLayerRoot
->SetLayers({});
50 mNativeLayerForEntireWindow
= nullptr;
51 mNativeLayerRootSnapshotter
= nullptr;
52 mNativeLayerRoot
= nullptr;
55 bool RenderCompositorNative::BeginFrame() {
57 gfxCriticalNote
<< "Failed to make render context current, can't draw.";
61 gfx::IntSize bufferSize
= GetBufferSize().ToUnknownSize();
62 if (!ShouldUseNativeCompositor()) {
63 if (bufferSize
.IsEmpty()) {
66 if (mNativeLayerForEntireWindow
&&
67 mNativeLayerForEntireWindow
->GetSize() != bufferSize
) {
68 mNativeLayerRoot
->RemoveLayer(mNativeLayerForEntireWindow
);
69 mNativeLayerForEntireWindow
= nullptr;
71 if (!mNativeLayerForEntireWindow
) {
72 mNativeLayerForEntireWindow
=
73 mNativeLayerRoot
->CreateLayer(bufferSize
, false, mSurfacePoolHandle
);
74 mNativeLayerRoot
->AppendLayer(mNativeLayerForEntireWindow
);
78 gfx::IntRect
bounds({}, bufferSize
);
79 if (!InitDefaultFramebuffer(bounds
)) {
86 RenderedFrameId
RenderCompositorNative::EndFrame(
87 const nsTArray
<DeviceIntRect
>& aDirtyRects
) {
88 RenderedFrameId frameId
= GetNextRenderFrameId();
92 MOZ_ASSERT(mPendingGpuFeces
.empty());
94 if (mNativeLayerForEntireWindow
) {
95 mNativeLayerForEntireWindow
->NotifySurfaceReady();
96 mNativeLayerRoot
->CommitToScreen();
102 void RenderCompositorNative::Pause() {}
104 bool RenderCompositorNative::Resume() { return true; }
106 inline layers::WebRenderCompositor
RenderCompositorNative::CompositorType()
108 if (gfx::gfxVars::UseWebRenderCompositor()) {
109 #if defined(XP_DARWIN)
110 return layers::WebRenderCompositor::CORE_ANIMATION
;
111 #elif defined(MOZ_WAYLAND)
112 return layers::WebRenderCompositor::WAYLAND
;
115 return layers::WebRenderCompositor::DRAW
;
118 LayoutDeviceIntSize
RenderCompositorNative::GetBufferSize() {
119 return mWidget
->GetClientSize();
122 bool RenderCompositorNative::ShouldUseNativeCompositor() {
123 return gfx::gfxVars::UseWebRenderCompositor();
126 void RenderCompositorNative::GetCompositorCapabilities(
127 CompositorCapabilities
* aCaps
) {
128 RenderCompositor::GetCompositorCapabilities(aCaps
);
129 #if defined(XP_DARWIN)
130 aCaps
->supports_surface_for_backdrop
= !gfx::gfxVars::UseSoftwareWebRender();
134 bool RenderCompositorNative::MaybeReadback(
135 const gfx::IntSize
& aReadbackSize
, const wr::ImageFormat
& aReadbackFormat
,
136 const Range
<uint8_t>& aReadbackBuffer
, bool* aNeedsYFlip
) {
137 if (!ShouldUseNativeCompositor()) {
141 MOZ_RELEASE_ASSERT(aReadbackFormat
== wr::ImageFormat::BGRA8
);
142 if (!mNativeLayerRootSnapshotter
) {
143 mNativeLayerRootSnapshotter
= mNativeLayerRoot
->CreateSnapshotter();
145 if (!mNativeLayerRootSnapshotter
) {
149 bool success
= mNativeLayerRootSnapshotter
->ReadbackPixels(
150 aReadbackSize
, gfx::SurfaceFormat::B8G8R8A8
, aReadbackBuffer
);
152 // ReadbackPixels might have changed the current context. Make sure GL is
163 bool RenderCompositorNative::MaybeRecordFrame(
164 layers::CompositionRecorder
& aRecorder
) {
165 if (!ShouldUseNativeCompositor()) {
169 if (!mNativeLayerRootSnapshotter
) {
170 mNativeLayerRootSnapshotter
= mNativeLayerRoot
->CreateSnapshotter();
173 if (!mNativeLayerRootSnapshotter
) {
177 gfx::IntSize size
= GetBufferSize().ToUnknownSize();
178 RefPtr
<layers::profiler_screenshots::RenderSource
> snapshot
=
179 mNativeLayerRootSnapshotter
->GetWindowContents(size
);
184 RefPtr
<layers::profiler_screenshots::AsyncReadbackBuffer
> buffer
=
185 mNativeLayerRootSnapshotter
->CreateAsyncReadbackBuffer(size
);
186 buffer
->CopyFrom(snapshot
);
188 RefPtr
<layers::RecordedFrame
> frame
=
189 new RenderCompositorRecordedFrame(TimeStamp::Now(), std::move(buffer
));
190 aRecorder
.RecordFrame(frame
);
192 // GetWindowContents might have changed the current context. Make sure our
193 // context is current again.
198 bool RenderCompositorNative::MaybeGrabScreenshot(
199 const gfx::IntSize
& aWindowSize
) {
200 if (!ShouldUseNativeCompositor()) {
204 if (!mNativeLayerRootSnapshotter
) {
205 mNativeLayerRootSnapshotter
= mNativeLayerRoot
->CreateSnapshotter();
208 if (mNativeLayerRootSnapshotter
) {
209 mProfilerScreenshotGrabber
.MaybeGrabScreenshot(*mNativeLayerRootSnapshotter
,
212 // MaybeGrabScreenshot might have changed the current context. Make sure our
213 // context is current again.
220 bool RenderCompositorNative::MaybeProcessScreenshotQueue() {
221 if (!ShouldUseNativeCompositor()) {
225 mProfilerScreenshotGrabber
.MaybeProcessQueue();
227 // MaybeProcessQueue might have changed the current context. Make sure our
228 // context is current again.
234 void RenderCompositorNative::CompositorBeginFrame() {
235 mAddedLayers
.Clear();
236 mAddedTilePixelCount
= 0;
237 mAddedClippedPixelCount
= 0;
238 mBeginFrameTimeStamp
= TimeStamp::Now();
239 mSurfacePoolHandle
->OnBeginFrame();
240 mNativeLayerRoot
->PrepareForCommit();
243 void RenderCompositorNative::CompositorEndFrame() {
244 if (profiler_thread_is_being_profiled_for_markers()) {
245 auto bufferSize
= GetBufferSize();
246 [[maybe_unused
]] uint64_t windowPixelCount
=
247 uint64_t(bufferSize
.width
) * bufferSize
.height
;
248 int nativeLayerCount
= 0;
249 for (const auto& it
: mSurfaces
) {
250 nativeLayerCount
+= int(it
.second
.mNativeLayers
.size());
252 PROFILER_MARKER_TEXT(
253 "WR OS Compositor frame", GRAPHICS
,
254 MarkerTiming::IntervalUntilNowFrom(mBeginFrameTimeStamp
),
255 nsPrintfCString("%d%% painting, %d%% overdraw, %d used "
256 "layers (%d%% memory) + %d unused layers (%d%% memory)",
257 int(mDrawnPixelCount
* 100 / windowPixelCount
),
258 int(mAddedClippedPixelCount
* 100 / windowPixelCount
),
259 int(mAddedLayers
.Length()),
260 int(mAddedTilePixelCount
* 100 / windowPixelCount
),
261 int(nativeLayerCount
- mAddedLayers
.Length()),
262 int((mTotalTilePixelCount
- mAddedTilePixelCount
) *
263 100 / windowPixelCount
)));
265 mDrawnPixelCount
= 0;
269 mNativeLayerRoot
->SetLayers(mAddedLayers
);
270 mNativeLayerRoot
->CommitToScreen();
271 mSurfacePoolHandle
->OnEndFrame();
274 void RenderCompositorNative::BindNativeLayer(wr::NativeTileId aId
,
275 const gfx::IntRect
& aDirtyRect
) {
276 MOZ_RELEASE_ASSERT(!mCurrentlyBoundNativeLayer
);
278 auto surfaceCursor
= mSurfaces
.find(aId
.surface_id
);
279 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
280 Surface
& surface
= surfaceCursor
->second
;
282 auto layerCursor
= surface
.mNativeLayers
.find(TileKey(aId
.x
, aId
.y
));
283 MOZ_RELEASE_ASSERT(layerCursor
!= surface
.mNativeLayers
.end());
284 RefPtr
<layers::NativeLayer
> layer
= layerCursor
->second
;
286 mCurrentlyBoundNativeLayer
= layer
;
288 mDrawnPixelCount
+= aDirtyRect
.Area();
291 void RenderCompositorNative::UnbindNativeLayer() {
292 MOZ_RELEASE_ASSERT(mCurrentlyBoundNativeLayer
);
294 mCurrentlyBoundNativeLayer
->NotifySurfaceReady();
295 mCurrentlyBoundNativeLayer
= nullptr;
298 void RenderCompositorNative::CreateSurface(wr::NativeSurfaceId aId
,
299 wr::DeviceIntPoint aVirtualOffset
,
300 wr::DeviceIntSize aTileSize
,
302 MOZ_RELEASE_ASSERT(mSurfaces
.find(aId
) == mSurfaces
.end());
303 mSurfaces
.insert({aId
, Surface
{aTileSize
, aIsOpaque
}});
306 void RenderCompositorNative::CreateExternalSurface(wr::NativeSurfaceId aId
,
308 MOZ_RELEASE_ASSERT(mSurfaces
.find(aId
) == mSurfaces
.end());
310 RefPtr
<layers::NativeLayer
> layer
=
311 mNativeLayerRoot
->CreateLayerForExternalTexture(aIsOpaque
);
313 Surface surface
{DeviceIntSize
{}, aIsOpaque
};
314 surface
.mIsExternal
= true;
315 surface
.mNativeLayers
.insert({TileKey(0, 0), layer
});
317 mSurfaces
.insert({aId
, std::move(surface
)});
320 void RenderCompositorNative::CreateBackdropSurface(wr::NativeSurfaceId aId
,
322 MOZ_RELEASE_ASSERT(mSurfaces
.find(aId
) == mSurfaces
.end());
324 gfx::DeviceColor
color(aColor
.r
, aColor
.g
, aColor
.b
, aColor
.a
);
325 RefPtr
<layers::NativeLayer
> layer
=
326 mNativeLayerRoot
->CreateLayerForColor(color
);
328 Surface surface
{DeviceIntSize
{}, (aColor
.a
>= 1.0f
)};
329 surface
.mNativeLayers
.insert({TileKey(0, 0), layer
});
331 mSurfaces
.insert({aId
, std::move(surface
)});
334 void RenderCompositorNative::AttachExternalImage(
335 wr::NativeSurfaceId aId
, wr::ExternalImageId aExternalImage
) {
336 RenderTextureHost
* image
=
337 RenderThread::Get()->GetRenderTexture(aExternalImage
);
338 MOZ_RELEASE_ASSERT(image
);
340 auto surfaceCursor
= mSurfaces
.find(aId
);
341 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
343 Surface
& surface
= surfaceCursor
->second
;
344 MOZ_RELEASE_ASSERT(surface
.mNativeLayers
.size() == 1);
345 MOZ_RELEASE_ASSERT(surface
.mIsExternal
);
346 surface
.mNativeLayers
.begin()->second
->AttachExternalImage(image
);
349 void RenderCompositorNative::DestroySurface(NativeSurfaceId aId
) {
350 auto surfaceCursor
= mSurfaces
.find(aId
);
351 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
353 Surface
& surface
= surfaceCursor
->second
;
354 if (!surface
.mIsExternal
) {
355 for (const auto& iter
: surface
.mNativeLayers
) {
356 mTotalTilePixelCount
-= gfx::IntRect({}, iter
.second
->GetSize()).Area();
360 mSurfaces
.erase(surfaceCursor
);
363 void RenderCompositorNative::CreateTile(wr::NativeSurfaceId aId
, int aX
,
365 auto surfaceCursor
= mSurfaces
.find(aId
);
366 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
367 Surface
& surface
= surfaceCursor
->second
;
368 MOZ_RELEASE_ASSERT(!surface
.mIsExternal
);
370 RefPtr
<layers::NativeLayer
> layer
= mNativeLayerRoot
->CreateLayer(
371 surface
.TileSize(), surface
.mIsOpaque
, mSurfacePoolHandle
);
372 surface
.mNativeLayers
.insert({TileKey(aX
, aY
), layer
});
373 mTotalTilePixelCount
+= gfx::IntRect({}, layer
->GetSize()).Area();
376 void RenderCompositorNative::DestroyTile(wr::NativeSurfaceId aId
, int aX
,
378 auto surfaceCursor
= mSurfaces
.find(aId
);
379 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
380 Surface
& surface
= surfaceCursor
->second
;
381 MOZ_RELEASE_ASSERT(!surface
.mIsExternal
);
383 auto layerCursor
= surface
.mNativeLayers
.find(TileKey(aX
, aY
));
384 MOZ_RELEASE_ASSERT(layerCursor
!= surface
.mNativeLayers
.end());
385 RefPtr
<layers::NativeLayer
> layer
= std::move(layerCursor
->second
);
386 surface
.mNativeLayers
.erase(layerCursor
);
387 mTotalTilePixelCount
-= gfx::IntRect({}, layer
->GetSize()).Area();
389 // If the layer is currently present in mNativeLayerRoot, it will be destroyed
390 // once CompositorEndFrame() replaces mNativeLayerRoot's layers and drops that
391 // reference. So until that happens, the layer still needs to hold on to its
392 // front buffer. However, we can tell it to drop its back buffers now, because
393 // we know that we will never draw to it again.
394 // Dropping the back buffers now puts them back in the surface pool, so those
395 // surfaces can be immediately re-used for drawing in other layers in the
397 layer
->DiscardBackbuffers();
400 gfx::SamplingFilter
ToSamplingFilter(wr::ImageRendering aImageRendering
) {
401 if (aImageRendering
== wr::ImageRendering::Auto
) {
402 return gfx::SamplingFilter::LINEAR
;
404 return gfx::SamplingFilter::POINT
;
407 void RenderCompositorNative::AddSurface(
408 wr::NativeSurfaceId aId
, const wr::CompositorSurfaceTransform
& aTransform
,
409 wr::DeviceIntRect aClipRect
, wr::ImageRendering aImageRendering
) {
410 MOZ_RELEASE_ASSERT(!mCurrentlyBoundNativeLayer
);
412 auto surfaceCursor
= mSurfaces
.find(aId
);
413 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
414 const Surface
& surface
= surfaceCursor
->second
;
416 float sx
= aTransform
.scale
.x
;
417 float sy
= aTransform
.scale
.y
;
418 float tx
= aTransform
.offset
.x
;
419 float ty
= aTransform
.offset
.y
;
420 gfx::Matrix4x4
transform(sx
, 0.0, 0.0, 0.0, 0.0, sy
, 0.0, 0.0, 0.0, 0.0, 1.0,
421 0.0, tx
, ty
, 0.0, 1.0);
423 for (auto it
= surface
.mNativeLayers
.begin();
424 it
!= surface
.mNativeLayers
.end(); ++it
) {
425 RefPtr
<layers::NativeLayer
> layer
= it
->second
;
426 gfx::IntSize layerSize
= layer
->GetSize();
427 gfx::IntPoint
layerPosition(surface
.mTileSize
.width
* it
->first
.mX
,
428 surface
.mTileSize
.height
* it
->first
.mY
);
429 layer
->SetPosition(layerPosition
);
430 gfx::IntRect
clipRect(aClipRect
.min
.x
, aClipRect
.min
.y
, aClipRect
.width(),
432 layer
->SetClipRect(Some(clipRect
));
433 layer
->SetTransform(transform
);
434 layer
->SetSamplingFilter(ToSamplingFilter(aImageRendering
));
435 mAddedLayers
.AppendElement(layer
);
437 if (surface
.mIsExternal
) {
438 RefPtr
<layers::GpuFence
> fence
= layer
->GetGpuFence();
439 if (fence
&& BackendType() == layers::WebRenderBackend::HARDWARE
) {
440 mPendingGpuFeces
.emplace_back(fence
);
444 if (!surface
.mIsExternal
) {
445 mAddedTilePixelCount
+= layerSize
.width
* layerSize
.height
;
447 gfx::Rect r
= transform
.TransformBounds(
448 gfx::Rect(layer
->CurrentSurfaceDisplayRect()));
449 gfx::IntRect visibleRect
=
450 clipRect
.Intersect(RoundedToInt(r
) + layerPosition
);
451 mAddedClippedPixelCount
+= visibleRect
.Area();
456 UniquePtr
<RenderCompositor
> RenderCompositorNativeOGL::Create(
457 const RefPtr
<widget::CompositorWidget
>& aWidget
, nsACString
& aError
) {
458 RefPtr
<gl::GLContext
> gl
= RenderThread::Get()->SingletonGL();
460 gl
= gl::GLContextProvider::CreateForCompositorWidget(
461 aWidget
, /* aHardwareWebRender */ true, /* aForceAccelerated */ true);
462 RenderThread::MaybeEnableGLDebugMessage(gl
);
464 if (!gl
|| !gl
->MakeCurrent()) {
465 gfxCriticalNote
<< "Failed GL context creation for WebRender: "
466 << gfx::hexa(gl
.get());
469 return MakeUnique
<RenderCompositorNativeOGL
>(aWidget
, std::move(gl
));
472 RenderCompositorNativeOGL::RenderCompositorNativeOGL(
473 const RefPtr
<widget::CompositorWidget
>& aWidget
,
474 RefPtr
<gl::GLContext
>&& aGL
)
475 : RenderCompositorNative(aWidget
, aGL
), mGL(aGL
) {
479 RenderCompositorNativeOGL::~RenderCompositorNativeOGL() {
480 if (!mGL
->MakeCurrent()) {
482 << "Failed to make render context current during destroying.";
484 mPreviousFrameDoneFences
= nullptr;
485 mThisFrameDoneFences
= nullptr;
489 if (mPreviousFrameDoneFences
&& mPreviousFrameDoneFences
->mSync
) {
490 mGL
->fDeleteSync(mPreviousFrameDoneFences
->mSync
);
492 if (mThisFrameDoneFences
&& mThisFrameDoneFences
->mSync
) {
493 mGL
->fDeleteSync(mThisFrameDoneFences
->mSync
);
497 bool RenderCompositorNativeOGL::InitDefaultFramebuffer(
498 const gfx::IntRect
& aBounds
) {
499 if (mNativeLayerForEntireWindow
) {
500 Maybe
<GLuint
> fbo
= mNativeLayerForEntireWindow
->NextSurfaceAsFramebuffer(
501 aBounds
, aBounds
, true);
505 mGL
->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER
, *fbo
);
507 mGL
->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER
, mGL
->GetDefaultFramebuffer());
512 void RenderCompositorNativeOGL::DoSwap() {
513 InsertFrameDoneSync();
514 if (mNativeLayerForEntireWindow
) {
519 void RenderCompositorNativeOGL::DoFlush() { mGL
->fFlush(); }
521 void RenderCompositorNativeOGL::InsertFrameDoneSync() {
523 // Only do this on macOS.
524 // On other platforms, SwapBuffers automatically applies back-pressure.
525 if (mThisFrameDoneFences
&& mThisFrameDoneFences
->mSync
) {
526 mGL
->fDeleteSync(mThisFrameDoneFences
->mSync
);
528 mThisFrameDoneFences
=
529 MakeUnique
<BackPressureFences
>(std::move(mPendingGpuFeces
));
530 mThisFrameDoneFences
->mSync
=
531 mGL
->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE
, 0);
535 bool RenderCompositorNativeOGL::WaitForGPU() {
536 if (mPreviousFrameDoneFences
) {
537 bool complete
= false;
540 for (const auto& fence
: mPreviousFrameDoneFences
->mGpuFeces
) {
541 if (!fence
->HasCompleted()) {
548 PR_Sleep(PR_MillisecondsToInterval(1));
552 if (mPreviousFrameDoneFences
->mSync
) {
553 AUTO_PROFILER_LABEL("Waiting for GPU to finish previous frame", GRAPHICS
);
554 mGL
->fClientWaitSync(mPreviousFrameDoneFences
->mSync
,
555 LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT
,
556 LOCAL_GL_TIMEOUT_IGNORED
);
557 mGL
->fDeleteSync(mPreviousFrameDoneFences
->mSync
);
560 mPreviousFrameDoneFences
= std::move(mThisFrameDoneFences
);
561 MOZ_ASSERT(!mThisFrameDoneFences
);
566 void RenderCompositorNativeOGL::Bind(wr::NativeTileId aId
,
567 wr::DeviceIntPoint
* aOffset
,
569 wr::DeviceIntRect aDirtyRect
,
570 wr::DeviceIntRect aValidRect
) {
571 gfx::IntRect
validRect(aValidRect
.min
.x
, aValidRect
.min
.y
, aValidRect
.width(),
572 aValidRect
.height());
573 gfx::IntRect
dirtyRect(aDirtyRect
.min
.x
, aDirtyRect
.min
.y
, aDirtyRect
.width(),
574 aDirtyRect
.height());
576 BindNativeLayer(aId
, dirtyRect
);
578 Maybe
<GLuint
> fbo
= mCurrentlyBoundNativeLayer
->NextSurfaceAsFramebuffer(
579 validRect
, dirtyRect
, true);
582 *aOffset
= wr::DeviceIntPoint
{0, 0};
585 void RenderCompositorNativeOGL::Unbind() {
586 mGL
->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER
, 0);
592 UniquePtr
<RenderCompositor
> RenderCompositorNativeSWGL::Create(
593 const RefPtr
<widget::CompositorWidget
>& aWidget
, nsACString
& aError
) {
594 void* ctx
= wr_swgl_create_context();
596 gfxCriticalNote
<< "Failed SWGL context creation for WebRender";
599 return MakeUnique
<RenderCompositorNativeSWGL
>(aWidget
, ctx
);
602 RenderCompositorNativeSWGL::RenderCompositorNativeSWGL(
603 const RefPtr
<widget::CompositorWidget
>& aWidget
, void* aContext
)
604 : RenderCompositorNative(aWidget
), mContext(aContext
) {
605 MOZ_ASSERT(mContext
);
608 RenderCompositorNativeSWGL::~RenderCompositorNativeSWGL() {
609 wr_swgl_destroy_context(mContext
);
612 bool RenderCompositorNativeSWGL::MakeCurrent() {
613 wr_swgl_make_current(mContext
);
617 bool RenderCompositorNativeSWGL::InitDefaultFramebuffer(
618 const gfx::IntRect
& aBounds
) {
619 if (mNativeLayerForEntireWindow
) {
620 if (!MapNativeLayer(mNativeLayerForEntireWindow
, aBounds
, aBounds
)) {
623 wr_swgl_init_default_framebuffer(mContext
, aBounds
.x
, aBounds
.y
,
624 aBounds
.width
, aBounds
.height
,
625 mLayerStride
, mLayerValidRectData
);
630 void RenderCompositorNativeSWGL::CancelFrame() {
631 if (mNativeLayerForEntireWindow
&& mLayerTarget
) {
632 wr_swgl_init_default_framebuffer(mContext
, 0, 0, 0, 0, 0, nullptr);
637 void RenderCompositorNativeSWGL::DoSwap() {
638 if (mNativeLayerForEntireWindow
&& mLayerTarget
) {
639 wr_swgl_init_default_framebuffer(mContext
, 0, 0, 0, 0, 0, nullptr);
644 bool RenderCompositorNativeSWGL::MapNativeLayer(
645 layers::NativeLayer
* aLayer
, const gfx::IntRect
& aDirtyRect
,
646 const gfx::IntRect
& aValidRect
) {
647 uint8_t* data
= nullptr;
650 gfx::SurfaceFormat format
= gfx::SurfaceFormat::UNKNOWN
;
651 RefPtr
<gfx::DrawTarget
> dt
= aLayer
->NextSurfaceAsDrawTarget(
652 aValidRect
, gfx::IntRegion(aDirtyRect
), gfx::BackendType::SKIA
);
653 if (!dt
|| !dt
->LockBits(&data
, &size
, &stride
, &format
)) {
656 MOZ_ASSERT(format
== gfx::SurfaceFormat::B8G8R8A8
||
657 format
== gfx::SurfaceFormat::B8G8R8X8
);
658 mLayerTarget
= std::move(dt
);
660 mLayerValidRectData
= data
+ aValidRect
.y
* stride
+ aValidRect
.x
* 4;
661 mLayerStride
= stride
;
665 void RenderCompositorNativeSWGL::UnmapNativeLayer() {
666 MOZ_ASSERT(mLayerTarget
&& mLayerData
);
667 mLayerTarget
->ReleaseBits(mLayerData
);
668 mLayerTarget
= nullptr;
669 mLayerData
= nullptr;
670 mLayerValidRectData
= nullptr;
674 bool RenderCompositorNativeSWGL::MapTile(wr::NativeTileId aId
,
675 wr::DeviceIntRect aDirtyRect
,
676 wr::DeviceIntRect aValidRect
,
677 void** aData
, int32_t* aStride
) {
678 if (mNativeLayerForEntireWindow
) {
681 gfx::IntRect
dirtyRect(aDirtyRect
.min
.x
, aDirtyRect
.min
.y
, aDirtyRect
.width(),
682 aDirtyRect
.height());
683 gfx::IntRect
validRect(aValidRect
.min
.x
, aValidRect
.min
.y
, aValidRect
.width(),
684 aValidRect
.height());
685 BindNativeLayer(aId
, dirtyRect
);
686 if (!MapNativeLayer(mCurrentlyBoundNativeLayer
, dirtyRect
, validRect
)) {
690 *aData
= mLayerValidRectData
;
691 *aStride
= mLayerStride
;
695 void RenderCompositorNativeSWGL::UnmapTile() {
696 if (!mNativeLayerForEntireWindow
&& mCurrentlyBoundNativeLayer
) {
702 } // namespace mozilla::wr