Bug 1918529 - fix some subpixel misalignment issues with gfx.webrender.svg-filter...
[gecko.git] / gfx / webrender_bindings / RenderCompositorNative.cpp
blob409b2ab86ce5dbbda8db680e5fc6044a83cc51ce
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/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();
37 if (pool) {
38 mSurfacePoolHandle = pool->GetHandleForGL(aGL);
40 #endif
41 MOZ_RELEASE_ASSERT(mSurfacePoolHandle);
44 RenderCompositorNative::~RenderCompositorNative() {
45 LOG("RRenderCompositorNative::~RenderCompositorNative()");
47 Pause();
48 mProfilerScreenshotGrabber.Destroy();
49 mNativeLayerRoot->SetLayers({});
50 mNativeLayerForEntireWindow = nullptr;
51 mNativeLayerRootSnapshotter = nullptr;
52 mNativeLayerRoot = nullptr;
55 bool RenderCompositorNative::BeginFrame() {
56 if (!MakeCurrent()) {
57 gfxCriticalNote << "Failed to make render context current, can't draw.";
58 return false;
61 gfx::IntSize bufferSize = GetBufferSize().ToUnknownSize();
62 if (!ShouldUseNativeCompositor()) {
63 if (bufferSize.IsEmpty()) {
64 return false;
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)) {
80 return false;
83 return true;
86 RenderedFrameId RenderCompositorNative::EndFrame(
87 const nsTArray<DeviceIntRect>& aDirtyRects) {
88 RenderedFrameId frameId = GetNextRenderFrameId();
90 DoSwap();
92 MOZ_ASSERT(mPendingGpuFeces.empty());
94 if (mNativeLayerForEntireWindow) {
95 mNativeLayerForEntireWindow->NotifySurfaceReady();
96 mNativeLayerRoot->CommitToScreen();
99 return frameId;
102 void RenderCompositorNative::Pause() {}
104 bool RenderCompositorNative::Resume() { return true; }
106 inline layers::WebRenderCompositor RenderCompositorNative::CompositorType()
107 const {
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;
113 #endif
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();
131 #endif
134 bool RenderCompositorNative::MaybeReadback(
135 const gfx::IntSize& aReadbackSize, const wr::ImageFormat& aReadbackFormat,
136 const Range<uint8_t>& aReadbackBuffer, bool* aNeedsYFlip) {
137 if (!ShouldUseNativeCompositor()) {
138 return false;
141 MOZ_RELEASE_ASSERT(aReadbackFormat == wr::ImageFormat::BGRA8);
142 if (!mNativeLayerRootSnapshotter) {
143 mNativeLayerRootSnapshotter = mNativeLayerRoot->CreateSnapshotter();
145 if (!mNativeLayerRootSnapshotter) {
146 return false;
149 bool success = mNativeLayerRootSnapshotter->ReadbackPixels(
150 aReadbackSize, gfx::SurfaceFormat::B8G8R8A8, aReadbackBuffer);
152 // ReadbackPixels might have changed the current context. Make sure GL is
153 // current again.
154 MakeCurrent();
156 if (aNeedsYFlip) {
157 *aNeedsYFlip = true;
160 return success;
163 bool RenderCompositorNative::MaybeRecordFrame(
164 layers::CompositionRecorder& aRecorder) {
165 if (!ShouldUseNativeCompositor()) {
166 return false;
169 if (!mNativeLayerRootSnapshotter) {
170 mNativeLayerRootSnapshotter = mNativeLayerRoot->CreateSnapshotter();
173 if (!mNativeLayerRootSnapshotter) {
174 return true;
177 gfx::IntSize size = GetBufferSize().ToUnknownSize();
178 RefPtr<layers::profiler_screenshots::RenderSource> snapshot =
179 mNativeLayerRootSnapshotter->GetWindowContents(size);
180 if (!snapshot) {
181 return true;
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.
194 MakeCurrent();
195 return true;
198 bool RenderCompositorNative::MaybeGrabScreenshot(
199 const gfx::IntSize& aWindowSize) {
200 if (!ShouldUseNativeCompositor()) {
201 return false;
204 if (!mNativeLayerRootSnapshotter) {
205 mNativeLayerRootSnapshotter = mNativeLayerRoot->CreateSnapshotter();
208 if (mNativeLayerRootSnapshotter) {
209 mProfilerScreenshotGrabber.MaybeGrabScreenshot(*mNativeLayerRootSnapshotter,
210 aWindowSize);
212 // MaybeGrabScreenshot might have changed the current context. Make sure our
213 // context is current again.
214 MakeCurrent();
217 return true;
220 bool RenderCompositorNative::MaybeProcessScreenshotQueue() {
221 if (!ShouldUseNativeCompositor()) {
222 return false;
225 mProfilerScreenshotGrabber.MaybeProcessQueue();
227 // MaybeProcessQueue might have changed the current context. Make sure our
228 // context is current again.
229 MakeCurrent();
231 return true;
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;
267 DoFlush();
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,
301 bool aIsOpaque) {
302 MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
303 mSurfaces.insert({aId, Surface{aTileSize, aIsOpaque}});
306 void RenderCompositorNative::CreateExternalSurface(wr::NativeSurfaceId aId,
307 bool aIsOpaque) {
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,
321 wr::ColorF aColor) {
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,
364 int aY) {
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,
377 int aY) {
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
396 // current frame.
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(),
431 aClipRect.height());
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();
455 /* static */
456 UniquePtr<RenderCompositor> RenderCompositorNativeOGL::Create(
457 const RefPtr<widget::CompositorWidget>& aWidget, nsACString& aError) {
458 RefPtr<gl::GLContext> gl = RenderThread::Get()->SingletonGL();
459 if (!gl) {
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());
467 return nullptr;
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) {
476 MOZ_ASSERT(mGL);
479 RenderCompositorNativeOGL::~RenderCompositorNativeOGL() {
480 if (!mGL->MakeCurrent()) {
481 gfxCriticalNote
482 << "Failed to make render context current during destroying.";
483 // Leak resources!
484 mPreviousFrameDoneFences = nullptr;
485 mThisFrameDoneFences = nullptr;
486 return;
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);
502 if (!fbo) {
503 return false;
505 mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, *fbo);
506 } else {
507 mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mGL->GetDefaultFramebuffer());
509 return true;
512 void RenderCompositorNativeOGL::DoSwap() {
513 InsertFrameDoneSync();
514 if (mNativeLayerForEntireWindow) {
515 mGL->fFlush();
519 void RenderCompositorNativeOGL::DoFlush() { mGL->fFlush(); }
521 void RenderCompositorNativeOGL::InsertFrameDoneSync() {
522 #ifdef XP_DARWIN
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);
532 #endif
535 bool RenderCompositorNativeOGL::WaitForGPU() {
536 if (mPreviousFrameDoneFences) {
537 bool complete = false;
538 while (!complete) {
539 complete = true;
540 for (const auto& fence : mPreviousFrameDoneFences->mGpuFeces) {
541 if (!fence->HasCompleted()) {
542 complete = false;
543 break;
547 if (!complete) {
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);
563 return true;
566 void RenderCompositorNativeOGL::Bind(wr::NativeTileId aId,
567 wr::DeviceIntPoint* aOffset,
568 uint32_t* aFboId,
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);
581 *aFboId = *fbo;
582 *aOffset = wr::DeviceIntPoint{0, 0};
585 void RenderCompositorNativeOGL::Unbind() {
586 mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
588 UnbindNativeLayer();
591 /* static */
592 UniquePtr<RenderCompositor> RenderCompositorNativeSWGL::Create(
593 const RefPtr<widget::CompositorWidget>& aWidget, nsACString& aError) {
594 void* ctx = wr_swgl_create_context();
595 if (!ctx) {
596 gfxCriticalNote << "Failed SWGL context creation for WebRender";
597 return nullptr;
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);
614 return true;
617 bool RenderCompositorNativeSWGL::InitDefaultFramebuffer(
618 const gfx::IntRect& aBounds) {
619 if (mNativeLayerForEntireWindow) {
620 if (!MapNativeLayer(mNativeLayerForEntireWindow, aBounds, aBounds)) {
621 return false;
623 wr_swgl_init_default_framebuffer(mContext, aBounds.x, aBounds.y,
624 aBounds.width, aBounds.height,
625 mLayerStride, mLayerValidRectData);
627 return true;
630 void RenderCompositorNativeSWGL::CancelFrame() {
631 if (mNativeLayerForEntireWindow && mLayerTarget) {
632 wr_swgl_init_default_framebuffer(mContext, 0, 0, 0, 0, 0, nullptr);
633 UnmapNativeLayer();
637 void RenderCompositorNativeSWGL::DoSwap() {
638 if (mNativeLayerForEntireWindow && mLayerTarget) {
639 wr_swgl_init_default_framebuffer(mContext, 0, 0, 0, 0, 0, nullptr);
640 UnmapNativeLayer();
644 bool RenderCompositorNativeSWGL::MapNativeLayer(
645 layers::NativeLayer* aLayer, const gfx::IntRect& aDirtyRect,
646 const gfx::IntRect& aValidRect) {
647 uint8_t* data = nullptr;
648 gfx::IntSize size;
649 int32_t stride = 0;
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)) {
654 return false;
656 MOZ_ASSERT(format == gfx::SurfaceFormat::B8G8R8A8 ||
657 format == gfx::SurfaceFormat::B8G8R8X8);
658 mLayerTarget = std::move(dt);
659 mLayerData = data;
660 mLayerValidRectData = data + aValidRect.y * stride + aValidRect.x * 4;
661 mLayerStride = stride;
662 return true;
665 void RenderCompositorNativeSWGL::UnmapNativeLayer() {
666 MOZ_ASSERT(mLayerTarget && mLayerData);
667 mLayerTarget->ReleaseBits(mLayerData);
668 mLayerTarget = nullptr;
669 mLayerData = nullptr;
670 mLayerValidRectData = nullptr;
671 mLayerStride = 0;
674 bool RenderCompositorNativeSWGL::MapTile(wr::NativeTileId aId,
675 wr::DeviceIntRect aDirtyRect,
676 wr::DeviceIntRect aValidRect,
677 void** aData, int32_t* aStride) {
678 if (mNativeLayerForEntireWindow) {
679 return false;
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)) {
687 UnbindNativeLayer();
688 return false;
690 *aData = mLayerValidRectData;
691 *aStride = mLayerStride;
692 return true;
695 void RenderCompositorNativeSWGL::UnmapTile() {
696 if (!mNativeLayerForEntireWindow && mCurrentlyBoundNativeLayer) {
697 UnmapNativeLayer();
698 UnbindNativeLayer();
702 } // namespace mozilla::wr