RenderCompositor.cpp (12808B)
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 "RenderCompositor.h" 8 9 #include "gfxConfig.h" 10 #include "gfxPlatform.h" 11 #include "GLContext.h" 12 #include "mozilla/StaticPrefs_gfx.h" 13 #include "mozilla/gfx/Logging.h" 14 #include "mozilla/gfx/gfxVars.h" 15 #include "mozilla/layers/SyncObject.h" 16 #include "mozilla/webrender/RenderCompositorLayersSWGL.h" 17 #include "mozilla/webrender/RenderCompositorOGL.h" 18 #include "mozilla/webrender/RenderCompositorSWGL.h" 19 #include "mozilla/widget/CompositorWidget.h" 20 21 #ifdef XP_WIN 22 # include "mozilla/webrender/RenderCompositorANGLE.h" 23 # include "mozilla/widget/WinCompositorWidget.h" 24 #endif 25 26 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK) 27 # include "mozilla/webrender/RenderCompositorEGL.h" 28 #endif 29 30 #ifdef MOZ_WAYLAND 31 # include "mozilla/webrender/RenderCompositorNative.h" 32 #endif 33 34 #ifdef XP_DARWIN 35 # include "mozilla/webrender/RenderCompositorNative.h" 36 #endif 37 38 namespace mozilla::wr { 39 40 void wr_compositor_add_surface(void* aCompositor, wr::NativeSurfaceId aId, 41 const wr::CompositorSurfaceTransform* aTransform, 42 wr::DeviceIntRect aClipRect, 43 wr::ImageRendering aImageRendering, 44 wr::DeviceIntRect aRoundedClipRect, 45 wr::ClipRadius aRoundedClipRadius) { 46 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 47 compositor->AddSurface(aId, *aTransform, aClipRect, aImageRendering, 48 aRoundedClipRect, aRoundedClipRadius); 49 } 50 51 void wr_compositor_begin_frame(void* aCompositor) { 52 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 53 compositor->CompositorBeginFrame(); 54 } 55 56 void wr_compositor_bind(void* aCompositor, wr::NativeTileId aId, 57 wr::DeviceIntPoint* aOffset, uint32_t* aFboId, 58 wr::DeviceIntRect aDirtyRect, 59 wr::DeviceIntRect aValidRect) { 60 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 61 compositor->Bind(aId, aOffset, aFboId, aDirtyRect, aValidRect); 62 } 63 64 void wr_compositor_create_surface(void* aCompositor, wr::NativeSurfaceId aId, 65 wr::DeviceIntPoint aVirtualOffset, 66 wr::DeviceIntSize aTileSize, bool aIsOpaque) { 67 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 68 compositor->CreateSurface(aId, aVirtualOffset, aTileSize, aIsOpaque); 69 } 70 71 void wr_compositor_create_external_surface(void* aCompositor, 72 wr::NativeSurfaceId aId, 73 bool aIsOpaque) { 74 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 75 compositor->CreateExternalSurface(aId, aIsOpaque); 76 } 77 78 void wr_compositor_create_swapchain_surface(void* aCompositor, 79 wr::NativeSurfaceId aId, 80 wr::DeviceIntSize aSize, 81 bool aIsOpaque, 82 bool aNeedsSyncDcompCommit) { 83 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 84 compositor->CreateSwapChainSurface(aId, aSize, aIsOpaque, 85 aNeedsSyncDcompCommit); 86 } 87 88 void wr_compositor_resize_swapchain(void* aCompositor, wr::NativeSurfaceId aId, 89 wr::DeviceIntSize aSize) { 90 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 91 compositor->ResizeSwapChainSurface(aId, aSize); 92 } 93 94 void wr_compositor_create_backdrop_surface(void* aCompositor, 95 wr::NativeSurfaceId aId, 96 wr::ColorF aColor) { 97 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 98 compositor->CreateBackdropSurface(aId, aColor); 99 } 100 101 void wr_compositor_create_tile(void* aCompositor, wr::NativeSurfaceId aId, 102 int32_t aX, int32_t aY) { 103 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 104 compositor->CreateTile(aId, aX, aY); 105 } 106 107 void wr_compositor_destroy_tile(void* aCompositor, wr::NativeSurfaceId aId, 108 int32_t aX, int32_t aY) { 109 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 110 compositor->DestroyTile(aId, aX, aY); 111 } 112 113 void wr_compositor_bind_swapchain(void* aCompositor, wr::NativeSurfaceId aId, 114 const wr::DeviceIntRect* aDirtyRects, 115 size_t aNumDirtyRects) { 116 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 117 compositor->BindSwapChain(aId, aDirtyRects, aNumDirtyRects); 118 } 119 120 void wr_compositor_present_swapchain(void* aCompositor, wr::NativeSurfaceId aId, 121 const wr::DeviceIntRect* aDirtyRects, 122 size_t aNumDirtyRects) { 123 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 124 compositor->PresentSwapChain(aId, aDirtyRects, aNumDirtyRects); 125 } 126 127 void wr_compositor_destroy_surface(void* aCompositor, NativeSurfaceId aId) { 128 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 129 compositor->DestroySurface(aId); 130 } 131 132 void wr_compositor_attach_external_image(void* aCompositor, 133 wr::NativeSurfaceId aId, 134 wr::ExternalImageId aExternalImage) { 135 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 136 compositor->AttachExternalImage(aId, aExternalImage); 137 } 138 139 void wr_compositor_start_compositing(void* aCompositor, wr::ColorF aClearColor, 140 const wr::DeviceIntRect* aDirtyRects, 141 size_t aNumDirtyRects, 142 const wr::DeviceIntRect* aOpaqueRects, 143 size_t aNumOpaqueRects) { 144 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 145 compositor->StartCompositing(aClearColor, aDirtyRects, aNumDirtyRects, 146 aOpaqueRects, aNumOpaqueRects); 147 } 148 149 void wr_compositor_end_frame(void* aCompositor) { 150 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 151 compositor->CompositorEndFrame(); 152 } 153 154 void wr_compositor_enable_native_compositor(void* aCompositor, bool aEnable) { 155 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 156 compositor->EnableNativeCompositor(aEnable); 157 } 158 159 void wr_compositor_get_capabilities(void* aCompositor, 160 CompositorCapabilities* aCaps) { 161 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 162 compositor->GetCompositorCapabilities(aCaps); 163 } 164 165 void wr_compositor_get_window_visibility(void* aCompositor, 166 WindowVisibility* aVisibility) { 167 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 168 compositor->GetWindowVisibility(aVisibility); 169 } 170 171 void wr_compositor_get_window_properties(void* aCompositor, 172 WindowProperties* aProperties) { 173 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 174 compositor->GetWindowProperties(aProperties); 175 } 176 177 void wr_compositor_unbind(void* aCompositor) { 178 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 179 compositor->Unbind(); 180 } 181 182 void wr_compositor_deinit(void* aCompositor) { 183 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 184 compositor->DeInit(); 185 } 186 187 void wr_compositor_map_tile(void* aCompositor, wr::NativeTileId aId, 188 wr::DeviceIntRect aDirtyRect, 189 wr::DeviceIntRect aValidRect, void** aData, 190 int32_t* aStride) { 191 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 192 compositor->MapTile(aId, aDirtyRect, aValidRect, aData, aStride); 193 } 194 195 void wr_compositor_unmap_tile(void* aCompositor) { 196 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 197 compositor->UnmapTile(); 198 } 199 200 void wr_partial_present_compositor_set_buffer_damage_region( 201 void* aCompositor, const wr::DeviceIntRect* aRects, size_t aNRects) { 202 RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor); 203 compositor->SetBufferDamageRegion(aRects, aNRects); 204 } 205 206 /* static */ 207 UniquePtr<RenderCompositor> RenderCompositor::Create( 208 const RefPtr<widget::CompositorWidget>& aWidget, nsACString& aError) { 209 if (aWidget->GetCompositorOptions().UseSoftwareWebRender()) { 210 #ifdef XP_DARWIN 211 // Mac uses NativeLayerCA 212 if (!gfxPlatform::IsHeadless()) { 213 return RenderCompositorNativeSWGL::Create(aWidget, aError); 214 } 215 #elif defined(MOZ_WAYLAND) 216 // Some widgets on Wayland (D&D popups for instance) can't use native 217 // compositor due to system limitations. 218 if (gfx::gfxVars::UseWebRenderCompositor() && 219 aWidget->GetCompositorOptions().AllowNativeCompositor()) { 220 return RenderCompositorNativeSWGL::Create(aWidget, aError); 221 } 222 #endif 223 UniquePtr<RenderCompositor> comp = 224 RenderCompositorLayersSWGL::Create(aWidget, aError); 225 if (comp) { 226 return comp; 227 } 228 #if defined(MOZ_WIDGET_ANDROID) 229 // On Android, we do not want to fallback from RenderCompositorOGLSWGL to 230 // RenderCompositorSWGL. 231 if (aWidget->GetCompositorOptions().AllowSoftwareWebRenderOGL()) { 232 return nullptr; 233 } 234 #endif 235 return RenderCompositorSWGL::Create(aWidget, aError); 236 } 237 238 #ifdef XP_WIN 239 if (gfx::gfxVars::UseWebRenderANGLE()) { 240 return RenderCompositorANGLE::Create(aWidget, aError); 241 } 242 #endif 243 244 #if defined(MOZ_WAYLAND) 245 if (gfx::gfxVars::UseWebRenderCompositor() && 246 aWidget->GetCompositorOptions().AllowNativeCompositor()) { 247 return RenderCompositorNativeOGL::Create(aWidget, aError); 248 } 249 #endif 250 251 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK) 252 UniquePtr<RenderCompositor> eglCompositor = 253 RenderCompositorEGL::Create(aWidget, aError); 254 if (eglCompositor) { 255 return eglCompositor; 256 } 257 #endif 258 259 #if defined(MOZ_WIDGET_ANDROID) 260 // RenderCompositorOGL is not used on android 261 return nullptr; 262 #elif defined(XP_DARWIN) 263 // Mac uses NativeLayerCA 264 return RenderCompositorNativeOGL::Create(aWidget, aError); 265 #else 266 return RenderCompositorOGL::Create(aWidget, aError); 267 #endif 268 } 269 270 RenderCompositor::RenderCompositor( 271 const RefPtr<widget::CompositorWidget>& aWidget) 272 : mWidget(aWidget) {} 273 274 RenderCompositor::~RenderCompositor() = default; 275 276 bool RenderCompositor::MakeCurrent() { return gl()->MakeCurrent(); } 277 278 void RenderCompositor::GetCompositorCapabilities( 279 CompositorCapabilities* aCaps) { 280 if (StaticPrefs::gfx_webrender_compositor_max_update_rects_AtStartup() > 0) { 281 aCaps->max_update_rects = 1; 282 } else { 283 aCaps->max_update_rects = 0; 284 } 285 } 286 287 void RenderCompositor::GetWindowVisibility(WindowVisibility* aVisibility) { 288 #ifdef XP_WIN 289 auto* widget = mWidget->AsWindows(); 290 if (!widget) { 291 return; 292 } 293 aVisibility->is_fully_occluded = widget->GetWindowIsFullyOccluded(); 294 #endif 295 } 296 297 void RenderCompositor::GetWindowProperties(WindowProperties* aProperties) { 298 aProperties->is_opaque = true; 299 } 300 301 gfx::DeviceResetReason RenderCompositor::IsContextLost(bool aForce) { 302 auto* glc = gl(); 303 // GetGraphicsResetStatus may trigger an implicit MakeCurrent if robustness 304 // is not supported, so unless we are forcing, pass on the check. 305 if (!glc || (!aForce && !glc->IsSupported(gl::GLFeature::robustness))) { 306 return gfx::DeviceResetReason::OK; 307 } 308 auto resetStatus = glc->fGetGraphicsResetStatus(); 309 switch (resetStatus) { 310 case LOCAL_GL_NO_ERROR: 311 return gfx::DeviceResetReason::OK; 312 case LOCAL_GL_INNOCENT_CONTEXT_RESET_ARB: 313 return gfx::DeviceResetReason::DRIVER_ERROR; 314 case LOCAL_GL_PURGED_CONTEXT_RESET_NV: 315 return gfx::DeviceResetReason::NVIDIA_VIDEO; 316 case LOCAL_GL_GUILTY_CONTEXT_RESET_ARB: 317 return gfx::DeviceResetReason::RESET; 318 case LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB: 319 return gfx::DeviceResetReason::UNKNOWN; 320 default: 321 gfxCriticalError() << "Device reset with WR context unexpected status: " 322 << gfx::hexa(resetStatus); 323 break; 324 } 325 return gfx::DeviceResetReason::OTHER; 326 } 327 328 } // namespace mozilla::wr