tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RenderCompositorNative.cpp (25219B)


      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/. */
      6 
      7 #include "RenderCompositorNative.h"
      8 
      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/ProfilerScreenshots.h"
     19 #include "mozilla/layers/SurfacePool.h"
     20 #include "mozilla/StaticPrefs_gfx.h"
     21 #include "mozilla/webrender/RenderTextureHost.h"
     22 #include "mozilla/webrender/RenderThread.h"
     23 #include "mozilla/widget/CompositorWidget.h"
     24 #include "RenderCompositorRecordedFrame.h"
     25 
     26 namespace mozilla::wr {
     27 
     28 extern LazyLogModule gRenderThreadLog;
     29 #define LOG(...) MOZ_LOG(gRenderThreadLog, LogLevel::Debug, (__VA_ARGS__))
     30 
     31 RenderCompositorNative::RenderCompositorNative(
     32    const RefPtr<widget::CompositorWidget>& aWidget, gl::GLContext* aGL)
     33    : RenderCompositor(aWidget),
     34      mNativeLayerRoot(GetWidget()->GetNativeLayerRoot()) {
     35  LOG("RenderCompositorNative::RenderCompositorNative()");
     36 
     37  MOZ_ASSERT(mNativeLayerRoot);
     38 
     39 #if defined(XP_DARWIN) || defined(MOZ_WAYLAND)
     40  auto pool = RenderThread::Get()->SharedSurfacePool();
     41  if (pool) {
     42    mSurfacePoolHandle = pool->GetHandleForGL(aGL);
     43  }
     44 #endif
     45  MOZ_RELEASE_ASSERT(mSurfacePoolHandle);
     46 }
     47 
     48 RenderCompositorNative::~RenderCompositorNative() {
     49  LOG("RRenderCompositorNative::~RenderCompositorNative()");
     50 
     51  Pause();
     52  mProfilerScreenshotGrabber.Destroy();
     53  mNativeLayerRoot->SetLayers({});
     54  mNativeLayerForEntireWindow = nullptr;
     55  mNativeLayerRootSnapshotter = nullptr;
     56  mNativeLayerRoot = nullptr;
     57 }
     58 
     59 bool RenderCompositorNative::BeginFrame() {
     60  if (!MakeCurrent()) {
     61    gfxCriticalNote << "Failed to make render context current, can't draw.";
     62    return false;
     63  }
     64 
     65  gfx::IntSize bufferSize = GetBufferSize().ToUnknownSize();
     66  if (!ShouldUseNativeCompositor()) {
     67    if (bufferSize.IsEmpty()) {
     68      return false;
     69    }
     70    if (mNativeLayerForEntireWindow &&
     71        mNativeLayerForEntireWindow->GetSize() != bufferSize) {
     72      mNativeLayerRoot->RemoveLayer(mNativeLayerForEntireWindow);
     73      mNativeLayerForEntireWindow = nullptr;
     74    }
     75    if (!mNativeLayerForEntireWindow) {
     76      mNativeLayerForEntireWindow =
     77          mNativeLayerRoot->CreateLayer(bufferSize, false, mSurfacePoolHandle);
     78      mNativeLayerRoot->AppendLayer(mNativeLayerForEntireWindow);
     79    }
     80  }
     81 
     82  gfx::IntRect bounds({}, bufferSize);
     83  if (!InitDefaultFramebuffer(bounds)) {
     84    return false;
     85  }
     86 
     87  return true;
     88 }
     89 
     90 RenderedFrameId RenderCompositorNative::EndFrame(
     91    const nsTArray<DeviceIntRect>& aDirtyRects) {
     92  RenderedFrameId frameId = GetNextRenderFrameId();
     93 
     94  DoSwap();
     95 
     96  MOZ_ASSERT(mPendingGpuFeces.empty());
     97 
     98  if (mNativeLayerForEntireWindow) {
     99    mNativeLayerForEntireWindow->NotifySurfaceReady();
    100    mNativeLayerRoot->CommitToScreen();
    101  }
    102 
    103  return frameId;
    104 }
    105 
    106 void RenderCompositorNative::Pause() {}
    107 
    108 bool RenderCompositorNative::Resume() { return true; }
    109 
    110 inline layers::WebRenderCompositor RenderCompositorNative::CompositorType()
    111    const {
    112  if (gfx::gfxVars::UseWebRenderCompositor()) {
    113 #if defined(XP_DARWIN)
    114    return layers::WebRenderCompositor::CORE_ANIMATION;
    115 #elif defined(MOZ_WAYLAND)
    116    return layers::WebRenderCompositor::WAYLAND;
    117 #endif
    118  }
    119  return layers::WebRenderCompositor::DRAW;
    120 }
    121 
    122 LayoutDeviceIntSize RenderCompositorNative::GetBufferSize() {
    123  return mWidget->GetClientSize();
    124 }
    125 
    126 bool RenderCompositorNative::ShouldUseNativeCompositor() {
    127  return gfx::gfxVars::UseWebRenderCompositor();
    128 }
    129 
    130 void RenderCompositorNative::GetCompositorCapabilities(
    131    CompositorCapabilities* aCaps) {
    132  RenderCompositor::GetCompositorCapabilities(aCaps);
    133 #if defined(XP_DARWIN)
    134  aCaps->supports_surface_for_backdrop = !gfx::gfxVars::UseSoftwareWebRender();
    135 #endif
    136 }
    137 
    138 RenderCompositorNative::Surface::~Surface() = default;
    139 
    140 RenderCompositorNative::Surface::Surface(wr::DeviceIntSize aTileSize,
    141                                         bool aIsOpaque)
    142    : mTileSize(aTileSize), mIsOpaque(aIsOpaque) {}
    143 
    144 bool RenderCompositorNative::MaybeReadback(
    145    const gfx::IntSize& aReadbackSize, const wr::ImageFormat& aReadbackFormat,
    146    const Range<uint8_t>& aReadbackBuffer, bool* aNeedsYFlip) {
    147  if (!ShouldUseNativeCompositor()) {
    148    return false;
    149  }
    150 
    151  MOZ_RELEASE_ASSERT(aReadbackFormat == wr::ImageFormat::BGRA8);
    152  if (!mNativeLayerRootSnapshotter) {
    153    mNativeLayerRootSnapshotter = mNativeLayerRoot->CreateSnapshotter();
    154 
    155    if (!mNativeLayerRootSnapshotter) {
    156      return false;
    157    }
    158  }
    159  bool success = mNativeLayerRootSnapshotter->ReadbackPixels(
    160      aReadbackSize, gfx::SurfaceFormat::B8G8R8A8, aReadbackBuffer);
    161 
    162  // ReadbackPixels might have changed the current context. Make sure GL is
    163  // current again.
    164  MakeCurrent();
    165 
    166  if (aNeedsYFlip) {
    167    *aNeedsYFlip = true;
    168  }
    169 
    170  return success;
    171 }
    172 
    173 bool RenderCompositorNative::MaybeRecordFrame(
    174    layers::CompositionRecorder& aRecorder) {
    175  if (!ShouldUseNativeCompositor()) {
    176    return false;
    177  }
    178 
    179  if (!mNativeLayerRootSnapshotter) {
    180    mNativeLayerRootSnapshotter = mNativeLayerRoot->CreateSnapshotter();
    181  }
    182 
    183  if (!mNativeLayerRootSnapshotter) {
    184    return true;
    185  }
    186 
    187  gfx::IntSize size = GetBufferSize().ToUnknownSize();
    188  RefPtr<layers::profiler_screenshots::RenderSource> snapshot =
    189      mNativeLayerRootSnapshotter->GetWindowContents(size);
    190  if (!snapshot) {
    191    return true;
    192  }
    193 
    194  RefPtr<layers::profiler_screenshots::AsyncReadbackBuffer> buffer =
    195      mNativeLayerRootSnapshotter->CreateAsyncReadbackBuffer(size);
    196  buffer->CopyFrom(snapshot);
    197 
    198  RefPtr<layers::RecordedFrame> frame =
    199      new RenderCompositorRecordedFrame(TimeStamp::Now(), std::move(buffer));
    200  aRecorder.RecordFrame(frame);
    201 
    202  // GetWindowContents might have changed the current context. Make sure our
    203  // context is current again.
    204  MakeCurrent();
    205  return true;
    206 }
    207 
    208 bool RenderCompositorNative::MaybeGrabScreenshot(
    209    const gfx::IntSize& aWindowSize) {
    210  if (!ShouldUseNativeCompositor() ||
    211      !mozilla::layers::ProfilerScreenshots::IsEnabled()) {
    212    return false;
    213  }
    214 
    215  if (!mNativeLayerRootSnapshotter) {
    216    mNativeLayerRootSnapshotter = mNativeLayerRoot->CreateSnapshotter();
    217  }
    218 
    219  if (mNativeLayerRootSnapshotter) {
    220    mProfilerScreenshotGrabber.MaybeGrabScreenshot(*mNativeLayerRootSnapshotter,
    221                                                   aWindowSize);
    222 
    223    // MaybeGrabScreenshot might have changed the current context. Make sure our
    224    // context is current again.
    225    MakeCurrent();
    226  }
    227 
    228  return true;
    229 }
    230 
    231 bool RenderCompositorNative::MaybeProcessScreenshotQueue() {
    232  if (!ShouldUseNativeCompositor()) {
    233    return false;
    234  }
    235 
    236  mProfilerScreenshotGrabber.MaybeProcessQueue();
    237 
    238  // MaybeProcessQueue might have changed the current context. Make sure our
    239  // context is current again.
    240  MakeCurrent();
    241 
    242  return true;
    243 }
    244 
    245 void RenderCompositorNative::WaitUntilPresentationFlushed() {
    246  mNativeLayerRoot->WaitUntilCommitToScreenHasBeenProcessed();
    247 }
    248 
    249 void RenderCompositorNative::CompositorBeginFrame() {
    250  mAddedLayers.Clear();
    251  mAddedTilePixelCount = 0;
    252  mAddedClippedPixelCount = 0;
    253  mBeginFrameTimeStamp = TimeStamp::Now();
    254  mSurfacePoolHandle->OnBeginFrame();
    255  mNativeLayerRoot->PrepareForCommit();
    256 }
    257 
    258 void RenderCompositorNative::CompositorEndFrame() {
    259  if (profiler_thread_is_being_profiled_for_markers()) {
    260    auto bufferSize = GetBufferSize();
    261    uint64_t windowPixelCount = uint64_t(bufferSize.width) * bufferSize.height;
    262    if (windowPixelCount) {
    263      int nativeLayerCount = 0;
    264      for (const auto& it : mSurfaces) {
    265        nativeLayerCount += int(it.second.mNativeLayers.size());
    266      }
    267      PROFILER_MARKER_TEXT(
    268          "WR OS Compositor frame", GRAPHICS,
    269          MarkerTiming::IntervalUntilNowFrom(mBeginFrameTimeStamp),
    270          nsPrintfCString(
    271              "%d%% painting, %d%% overdraw, %d used "
    272              "layers (%d%% memory) + %d unused layers (%d%% memory)",
    273              int(mDrawnPixelCount * 100 / windowPixelCount),
    274              int(mAddedClippedPixelCount * 100 / windowPixelCount),
    275              int(mAddedLayers.Length()),
    276              int(mAddedTilePixelCount * 100 / windowPixelCount),
    277              int(nativeLayerCount - mAddedLayers.Length()),
    278              int((mTotalTilePixelCount - mAddedTilePixelCount) * 100 /
    279                  windowPixelCount)));
    280    }
    281  }
    282  mDrawnPixelCount = 0;
    283 
    284 #if defined(XP_DARWIN)
    285  // MacOS fails rendering without the flush here.
    286  DoFlush();
    287 #endif
    288 
    289  mNativeLayerRoot->SetLayers(mAddedLayers);
    290  mNativeLayerRoot->CommitToScreen();
    291  mSurfacePoolHandle->OnEndFrame();
    292 }
    293 
    294 void RenderCompositorNative::BindNativeLayer(wr::NativeTileId aId,
    295                                             const gfx::IntRect& aDirtyRect) {
    296  MOZ_RELEASE_ASSERT(!mCurrentlyBoundNativeLayer);
    297 
    298  auto surfaceCursor = mSurfaces.find(aId.surface_id);
    299  MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    300  Surface& surface = surfaceCursor->second;
    301 
    302  auto layerCursor = surface.mNativeLayers.find(TileKey(aId.x, aId.y));
    303  MOZ_RELEASE_ASSERT(layerCursor != surface.mNativeLayers.end());
    304  RefPtr<layers::NativeLayer> layer = layerCursor->second;
    305 
    306  mCurrentlyBoundNativeLayer = layer;
    307 
    308  mDrawnPixelCount += aDirtyRect.Area();
    309 }
    310 
    311 void RenderCompositorNative::UnbindNativeLayer() {
    312  MOZ_RELEASE_ASSERT(mCurrentlyBoundNativeLayer);
    313 
    314  mCurrentlyBoundNativeLayer->NotifySurfaceReady();
    315  mCurrentlyBoundNativeLayer = nullptr;
    316 }
    317 
    318 void RenderCompositorNative::CreateSurface(wr::NativeSurfaceId aId,
    319                                           wr::DeviceIntPoint aVirtualOffset,
    320                                           wr::DeviceIntSize aTileSize,
    321                                           bool aIsOpaque) {
    322  MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
    323  mSurfaces.insert({aId, Surface{aTileSize, aIsOpaque}});
    324 }
    325 
    326 void RenderCompositorNative::CreateExternalSurface(wr::NativeSurfaceId aId,
    327                                                   bool aIsOpaque) {
    328  MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
    329 
    330  RefPtr<layers::NativeLayer> layer =
    331      mNativeLayerRoot->CreateLayerForExternalTexture(aIsOpaque);
    332 
    333  Surface surface{DeviceIntSize{}, aIsOpaque};
    334  surface.mIsExternal = true;
    335  surface.mNativeLayers.insert({TileKey(0, 0), layer});
    336 
    337  mSurfaces.insert({aId, std::move(surface)});
    338 }
    339 
    340 void RenderCompositorNative::CreateBackdropSurface(wr::NativeSurfaceId aId,
    341                                                   wr::ColorF aColor) {
    342  MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
    343 
    344  gfx::DeviceColor color(aColor.r, aColor.g, aColor.b, aColor.a);
    345  RefPtr<layers::NativeLayer> layer =
    346      mNativeLayerRoot->CreateLayerForColor(color);
    347 
    348  Surface surface{DeviceIntSize{}, (aColor.a >= 1.0f)};
    349  surface.mNativeLayers.insert({TileKey(0, 0), layer});
    350 
    351  mSurfaces.insert({aId, std::move(surface)});
    352 }
    353 
    354 void RenderCompositorNative::AttachExternalImage(
    355    wr::NativeSurfaceId aId, wr::ExternalImageId aExternalImage) {
    356  RenderTextureHost* image =
    357      RenderThread::Get()->GetRenderTexture(aExternalImage);
    358  MOZ_RELEASE_ASSERT(image);
    359 
    360  auto surfaceCursor = mSurfaces.find(aId);
    361  MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    362 
    363  Surface& surface = surfaceCursor->second;
    364  MOZ_RELEASE_ASSERT(surface.mNativeLayers.size() == 1);
    365  MOZ_RELEASE_ASSERT(surface.mIsExternal);
    366  surface.mNativeLayers.begin()->second->AttachExternalImage(image);
    367 }
    368 
    369 void RenderCompositorNativeOGL::AttachExternalImage(
    370    wr::NativeSurfaceId aId, wr::ExternalImageId aExternalImage) {
    371  RenderTextureHost* image =
    372      RenderThread::Get()->GetRenderTexture(aExternalImage);
    373 
    374  // image->Lock only uses the channel index to populate the returned
    375  // `WrExternalImage`. Since we don't use that, it doesn't matter
    376  // what channel index we pass.
    377  image->Lock(0, mGL);
    378 
    379  RenderCompositorNative::AttachExternalImage(aId, aExternalImage);
    380 }
    381 
    382 void RenderCompositorNative::DestroySurface(NativeSurfaceId aId) {
    383  auto surfaceCursor = mSurfaces.find(aId);
    384  MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    385 
    386  Surface& surface = surfaceCursor->second;
    387  if (!surface.mIsExternal) {
    388    for (const auto& iter : surface.mNativeLayers) {
    389      mTotalTilePixelCount -= gfx::IntRect({}, iter.second->GetSize()).Area();
    390    }
    391  }
    392 
    393  mSurfaces.erase(surfaceCursor);
    394 }
    395 
    396 void RenderCompositorNative::CreateTile(wr::NativeSurfaceId aId, int aX,
    397                                        int aY) {
    398  auto surfaceCursor = mSurfaces.find(aId);
    399  MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    400  Surface& surface = surfaceCursor->second;
    401  MOZ_RELEASE_ASSERT(!surface.mIsExternal);
    402 
    403  RefPtr<layers::NativeLayer> layer = mNativeLayerRoot->CreateLayer(
    404      surface.TileSize(), surface.mIsOpaque, mSurfacePoolHandle);
    405  surface.mNativeLayers.insert({TileKey(aX, aY), layer});
    406  mTotalTilePixelCount += gfx::IntRect({}, layer->GetSize()).Area();
    407 }
    408 
    409 void RenderCompositorNative::DestroyTile(wr::NativeSurfaceId aId, int aX,
    410                                         int aY) {
    411  auto surfaceCursor = mSurfaces.find(aId);
    412  MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    413  Surface& surface = surfaceCursor->second;
    414  MOZ_RELEASE_ASSERT(!surface.mIsExternal);
    415 
    416  auto layerCursor = surface.mNativeLayers.find(TileKey(aX, aY));
    417  MOZ_RELEASE_ASSERT(layerCursor != surface.mNativeLayers.end());
    418  RefPtr<layers::NativeLayer> layer = std::move(layerCursor->second);
    419  surface.mNativeLayers.erase(layerCursor);
    420  mTotalTilePixelCount -= gfx::IntRect({}, layer->GetSize()).Area();
    421 
    422  // If the layer is currently present in mNativeLayerRoot, it will be destroyed
    423  // once CompositorEndFrame() replaces mNativeLayerRoot's layers and drops that
    424  // reference. So until that happens, the layer still needs to hold on to its
    425  // front buffer. However, we can tell it to drop its back buffers now, because
    426  // we know that we will never draw to it again.
    427  // Dropping the back buffers now puts them back in the surface pool, so those
    428  // surfaces can be immediately re-used for drawing in other layers in the
    429  // current frame.
    430  layer->DiscardBackbuffers();
    431 }
    432 
    433 gfx::SamplingFilter ToSamplingFilter(wr::ImageRendering aImageRendering) {
    434  if (aImageRendering == wr::ImageRendering::Auto) {
    435    return gfx::SamplingFilter::LINEAR;
    436  }
    437  return gfx::SamplingFilter::POINT;
    438 }
    439 
    440 void RenderCompositorNative::AddSurface(
    441    wr::NativeSurfaceId aId, const wr::CompositorSurfaceTransform& aTransform,
    442    wr::DeviceIntRect aClipRect, wr::ImageRendering aImageRendering,
    443    wr::DeviceIntRect aRoundedClipRect, wr::ClipRadius aClipRadius) {
    444  MOZ_RELEASE_ASSERT(!mCurrentlyBoundNativeLayer);
    445 
    446  auto surfaceCursor = mSurfaces.find(aId);
    447  MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    448  const Surface& surface = surfaceCursor->second;
    449 
    450  float sx = aTransform.scale.x;
    451  float sy = aTransform.scale.y;
    452  float tx = aTransform.offset.x;
    453  float ty = aTransform.offset.y;
    454  gfx::Matrix4x4 transform(sx, 0.0, 0.0, 0.0, 0.0, sy, 0.0, 0.0, 0.0, 0.0, 1.0,
    455                           0.0, tx, ty, 0.0, 1.0);
    456 
    457  for (auto it = surface.mNativeLayers.begin();
    458       it != surface.mNativeLayers.end(); ++it) {
    459    RefPtr<layers::NativeLayer> layer = it->second;
    460    gfx::IntSize layerSize = layer->GetSize();
    461    gfx::IntPoint layerPosition(surface.mTileSize.width * it->first.mX,
    462                                surface.mTileSize.height * it->first.mY);
    463    layer->SetPosition(layerPosition);
    464    gfx::IntRect clipRect(aClipRect.min.x, aClipRect.min.y, aClipRect.width(),
    465                          aClipRect.height());
    466    layer->SetClipRect(Some(clipRect));
    467    gfx::Rect roundedClipRect(aRoundedClipRect.min.x, aRoundedClipRect.min.y,
    468                              aRoundedClipRect.width(),
    469                              aRoundedClipRect.height());
    470    gfx::RectCornerRadii clipRadius(aClipRadius.top_left, aClipRadius.top_right,
    471                                    aClipRadius.bottom_right,
    472                                    aClipRadius.bottom_left);
    473    gfx::RoundedRect roundedClip(roundedClipRect, clipRadius);
    474    layer->SetRoundedClipRect(Some(roundedClip));
    475    layer->SetTransform(transform);
    476    layer->SetSamplingFilter(ToSamplingFilter(aImageRendering));
    477    mAddedLayers.AppendElement(layer);
    478 
    479    if (surface.mIsExternal) {
    480      RefPtr<layers::GpuFence> fence = layer->GetGpuFence();
    481      if (fence && BackendType() == layers::WebRenderBackend::HARDWARE) {
    482        mPendingGpuFeces.emplace_back(fence);
    483      }
    484    }
    485 
    486    if (!surface.mIsExternal) {
    487      mAddedTilePixelCount += layerSize.width * layerSize.height;
    488    }
    489    gfx::Rect r = transform.TransformBounds(
    490        gfx::Rect(layer->CurrentSurfaceDisplayRect()));
    491    gfx::IntRect visibleRect =
    492        clipRect.Intersect(RoundedToInt(r) + layerPosition);
    493    mAddedClippedPixelCount += visibleRect.Area();
    494  }
    495 }
    496 
    497 /* static */
    498 UniquePtr<RenderCompositor> RenderCompositorNativeOGL::Create(
    499    const RefPtr<widget::CompositorWidget>& aWidget, nsACString& aError) {
    500  RefPtr<gl::GLContext> gl = RenderThread::Get()->SingletonGL();
    501  if (!gl) {
    502    gl = gl::GLContextProvider::CreateForCompositorWidget(
    503        aWidget, /* aHardwareWebRender */ true, /* aForceAccelerated */ true);
    504    RenderThread::MaybeEnableGLDebugMessage(gl);
    505  }
    506  if (!gl || !gl->MakeCurrent()) {
    507    gfxCriticalNote << "Failed GL context creation for WebRender: "
    508                    << gfx::hexa(gl.get());
    509    return nullptr;
    510  }
    511  return MakeUnique<RenderCompositorNativeOGL>(aWidget, std::move(gl));
    512 }
    513 
    514 RenderCompositorNativeOGL::RenderCompositorNativeOGL(
    515    const RefPtr<widget::CompositorWidget>& aWidget,
    516    RefPtr<gl::GLContext>&& aGL)
    517    : RenderCompositorNative(aWidget, aGL), mGL(aGL) {
    518  MOZ_ASSERT(mGL);
    519 }
    520 
    521 RenderCompositorNativeOGL::~RenderCompositorNativeOGL() {
    522  if (!mGL->MakeCurrent()) {
    523    gfxCriticalNote
    524        << "Failed to make render context current during destroying.";
    525    // Leak resources!
    526    mPreviousFrameDoneFences = nullptr;
    527    mThisFrameDoneFences = nullptr;
    528    return;
    529  }
    530 
    531  if (mPreviousFrameDoneFences && mPreviousFrameDoneFences->mSync) {
    532    mGL->fDeleteSync(mPreviousFrameDoneFences->mSync);
    533  }
    534  if (mThisFrameDoneFences && mThisFrameDoneFences->mSync) {
    535    mGL->fDeleteSync(mThisFrameDoneFences->mSync);
    536  }
    537 }
    538 
    539 bool RenderCompositorNativeOGL::InitDefaultFramebuffer(
    540    const gfx::IntRect& aBounds) {
    541  if (mNativeLayerForEntireWindow) {
    542    Maybe<GLuint> fbo = mNativeLayerForEntireWindow->NextSurfaceAsFramebuffer(
    543        aBounds, aBounds, true);
    544    if (!fbo) {
    545      return false;
    546    }
    547    mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, *fbo);
    548  } else {
    549    mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mGL->GetDefaultFramebuffer());
    550  }
    551  return true;
    552 }
    553 
    554 void RenderCompositorNativeOGL::DoSwap() {
    555  InsertFrameDoneSync();
    556  if (mNativeLayerForEntireWindow) {
    557    mGL->fFlush();
    558  }
    559 }
    560 
    561 void RenderCompositorNativeOGL::DoFlush() { mGL->fFlush(); }
    562 
    563 void RenderCompositorNativeOGL::InsertFrameDoneSync() {
    564 #ifdef XP_DARWIN
    565  // Only do this on macOS.
    566  // On other platforms, SwapBuffers automatically applies back-pressure.
    567  if (mThisFrameDoneFences && mThisFrameDoneFences->mSync) {
    568    mGL->fDeleteSync(mThisFrameDoneFences->mSync);
    569  }
    570  mThisFrameDoneFences =
    571      MakeUnique<BackPressureFences>(std::move(mPendingGpuFeces));
    572  mThisFrameDoneFences->mSync =
    573      mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
    574 #endif
    575 }
    576 
    577 bool RenderCompositorNativeOGL::WaitForGPU() {
    578  if (mPreviousFrameDoneFences) {
    579    bool complete = false;
    580    while (!complete) {
    581      complete = true;
    582      for (const auto& fence : mPreviousFrameDoneFences->mGpuFeces) {
    583        if (!fence->HasCompleted()) {
    584          complete = false;
    585          break;
    586        }
    587      }
    588 
    589      if (!complete) {
    590        PR_Sleep(PR_MillisecondsToInterval(1));
    591      }
    592    }
    593 
    594    if (mPreviousFrameDoneFences->mSync) {
    595      AUTO_PROFILER_LABEL("Waiting for GPU to finish previous frame", GRAPHICS);
    596      mGL->fClientWaitSync(mPreviousFrameDoneFences->mSync,
    597                           LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT,
    598                           LOCAL_GL_TIMEOUT_IGNORED);
    599      mGL->fDeleteSync(mPreviousFrameDoneFences->mSync);
    600    }
    601  }
    602  mPreviousFrameDoneFences = std::move(mThisFrameDoneFences);
    603  MOZ_ASSERT(!mThisFrameDoneFences);
    604 
    605  return true;
    606 }
    607 
    608 void RenderCompositorNativeOGL::Bind(wr::NativeTileId aId,
    609                                     wr::DeviceIntPoint* aOffset,
    610                                     uint32_t* aFboId,
    611                                     wr::DeviceIntRect aDirtyRect,
    612                                     wr::DeviceIntRect aValidRect) {
    613  gfx::IntRect validRect(aValidRect.min.x, aValidRect.min.y, aValidRect.width(),
    614                         aValidRect.height());
    615  gfx::IntRect dirtyRect(aDirtyRect.min.x, aDirtyRect.min.y, aDirtyRect.width(),
    616                         aDirtyRect.height());
    617 
    618  BindNativeLayer(aId, dirtyRect);
    619 
    620  Maybe<GLuint> fbo = mCurrentlyBoundNativeLayer->NextSurfaceAsFramebuffer(
    621      validRect, dirtyRect, true);
    622 
    623  *aFboId = *fbo;
    624  *aOffset = wr::DeviceIntPoint{0, 0};
    625 }
    626 
    627 void RenderCompositorNativeOGL::Unbind() {
    628  mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
    629 
    630  UnbindNativeLayer();
    631 }
    632 
    633 /* static */
    634 UniquePtr<RenderCompositor> RenderCompositorNativeSWGL::Create(
    635    const RefPtr<widget::CompositorWidget>& aWidget, nsACString& aError) {
    636  void* ctx = wr_swgl_create_context();
    637  if (!ctx) {
    638    gfxCriticalNote << "Failed SWGL context creation for WebRender";
    639    return nullptr;
    640  }
    641  return MakeUnique<RenderCompositorNativeSWGL>(aWidget, ctx);
    642 }
    643 
    644 RenderCompositorNativeSWGL::RenderCompositorNativeSWGL(
    645    const RefPtr<widget::CompositorWidget>& aWidget, void* aContext)
    646    : RenderCompositorNative(aWidget), mContext(aContext) {
    647  MOZ_ASSERT(mContext);
    648 }
    649 
    650 RenderCompositorNativeSWGL::~RenderCompositorNativeSWGL() {
    651  wr_swgl_destroy_context(mContext);
    652 }
    653 
    654 bool RenderCompositorNativeSWGL::MakeCurrent() {
    655  wr_swgl_make_current(mContext);
    656  return true;
    657 }
    658 
    659 bool RenderCompositorNativeSWGL::InitDefaultFramebuffer(
    660    const gfx::IntRect& aBounds) {
    661  if (mNativeLayerForEntireWindow) {
    662    if (!MapNativeLayer(mNativeLayerForEntireWindow, aBounds, aBounds)) {
    663      return false;
    664    }
    665    wr_swgl_init_default_framebuffer(mContext, aBounds.x, aBounds.y,
    666                                     aBounds.width, aBounds.height,
    667                                     mLayerStride, mLayerValidRectData);
    668  }
    669  return true;
    670 }
    671 
    672 void RenderCompositorNativeSWGL::CancelFrame() {
    673  if (mNativeLayerForEntireWindow && mLayerTarget) {
    674    wr_swgl_init_default_framebuffer(mContext, 0, 0, 0, 0, 0, nullptr);
    675    UnmapNativeLayer();
    676  }
    677 }
    678 
    679 void RenderCompositorNativeSWGL::DoSwap() {
    680  if (mNativeLayerForEntireWindow && mLayerTarget) {
    681    wr_swgl_init_default_framebuffer(mContext, 0, 0, 0, 0, 0, nullptr);
    682    UnmapNativeLayer();
    683  }
    684 }
    685 
    686 bool RenderCompositorNativeSWGL::MapNativeLayer(
    687    layers::NativeLayer* aLayer, const gfx::IntRect& aDirtyRect,
    688    const gfx::IntRect& aValidRect) {
    689  uint8_t* data = nullptr;
    690  gfx::IntSize size;
    691  int32_t stride = 0;
    692  gfx::SurfaceFormat format = gfx::SurfaceFormat::UNKNOWN;
    693  RefPtr<gfx::DrawTarget> dt = aLayer->NextSurfaceAsDrawTarget(
    694      aValidRect, gfx::IntRegion(aDirtyRect), gfx::BackendType::SKIA);
    695  if (!dt || !dt->LockBits(&data, &size, &stride, &format)) {
    696    return false;
    697  }
    698  MOZ_ASSERT(format == gfx::SurfaceFormat::B8G8R8A8 ||
    699             format == gfx::SurfaceFormat::B8G8R8X8);
    700  mLayerTarget = std::move(dt);
    701  mLayerData = data;
    702  mLayerValidRectData = data + aValidRect.y * stride + aValidRect.x * 4;
    703  mLayerStride = stride;
    704  return true;
    705 }
    706 
    707 void RenderCompositorNativeSWGL::UnmapNativeLayer() {
    708  MOZ_ASSERT(mLayerTarget && mLayerData);
    709  mLayerTarget->ReleaseBits(mLayerData);
    710  mLayerTarget = nullptr;
    711  mLayerData = nullptr;
    712  mLayerValidRectData = nullptr;
    713  mLayerStride = 0;
    714 }
    715 
    716 bool RenderCompositorNativeSWGL::MapTile(wr::NativeTileId aId,
    717                                         wr::DeviceIntRect aDirtyRect,
    718                                         wr::DeviceIntRect aValidRect,
    719                                         void** aData, int32_t* aStride) {
    720  if (mNativeLayerForEntireWindow) {
    721    return false;
    722  }
    723  gfx::IntRect dirtyRect(aDirtyRect.min.x, aDirtyRect.min.y, aDirtyRect.width(),
    724                         aDirtyRect.height());
    725  gfx::IntRect validRect(aValidRect.min.x, aValidRect.min.y, aValidRect.width(),
    726                         aValidRect.height());
    727  BindNativeLayer(aId, dirtyRect);
    728  if (!MapNativeLayer(mCurrentlyBoundNativeLayer, dirtyRect, validRect)) {
    729    UnbindNativeLayer();
    730    return false;
    731  }
    732  *aData = mLayerValidRectData;
    733  *aStride = mLayerStride;
    734  return true;
    735 }
    736 
    737 void RenderCompositorNativeSWGL::UnmapTile() {
    738  if (!mNativeLayerForEntireWindow && mCurrentlyBoundNativeLayer) {
    739    UnmapNativeLayer();
    740    UnbindNativeLayer();
    741  }
    742 }
    743 
    744 }  // namespace mozilla::wr