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