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 "RenderCompositor.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"
22 # include "mozilla/webrender/RenderCompositorANGLE.h"
23 # include "mozilla/widget/WinCompositorWidget.h"
26 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK)
27 # include "mozilla/webrender/RenderCompositorEGL.h"
31 # include "mozilla/webrender/RenderCompositorNative.h"
35 # include "mozilla/webrender/RenderCompositorNative.h"
38 namespace mozilla::wr
{
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 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
45 compositor
->AddSurface(aId
, *aTransform
, aClipRect
, aImageRendering
);
48 void wr_compositor_begin_frame(void* aCompositor
) {
49 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
50 compositor
->CompositorBeginFrame();
53 void wr_compositor_bind(void* aCompositor
, wr::NativeTileId aId
,
54 wr::DeviceIntPoint
* aOffset
, uint32_t* aFboId
,
55 wr::DeviceIntRect aDirtyRect
,
56 wr::DeviceIntRect aValidRect
) {
57 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
58 compositor
->Bind(aId
, aOffset
, aFboId
, aDirtyRect
, aValidRect
);
61 void wr_compositor_create_surface(void* aCompositor
, wr::NativeSurfaceId aId
,
62 wr::DeviceIntPoint aVirtualOffset
,
63 wr::DeviceIntSize aTileSize
, bool aIsOpaque
) {
64 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
65 compositor
->CreateSurface(aId
, aVirtualOffset
, aTileSize
, aIsOpaque
);
68 void wr_compositor_create_external_surface(void* aCompositor
,
69 wr::NativeSurfaceId aId
,
71 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
72 compositor
->CreateExternalSurface(aId
, aIsOpaque
);
75 void wr_compositor_create_backdrop_surface(void* aCompositor
,
76 wr::NativeSurfaceId aId
,
78 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
79 compositor
->CreateBackdropSurface(aId
, aColor
);
82 void wr_compositor_create_tile(void* aCompositor
, wr::NativeSurfaceId aId
,
83 int32_t aX
, int32_t aY
) {
84 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
85 compositor
->CreateTile(aId
, aX
, aY
);
88 void wr_compositor_destroy_tile(void* aCompositor
, wr::NativeSurfaceId aId
,
89 int32_t aX
, int32_t aY
) {
90 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
91 compositor
->DestroyTile(aId
, aX
, aY
);
94 void wr_compositor_destroy_surface(void* aCompositor
, NativeSurfaceId aId
) {
95 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
96 compositor
->DestroySurface(aId
);
99 void wr_compositor_attach_external_image(void* aCompositor
,
100 wr::NativeSurfaceId aId
,
101 wr::ExternalImageId aExternalImage
) {
102 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
103 compositor
->AttachExternalImage(aId
, aExternalImage
);
106 void wr_compositor_start_compositing(void* aCompositor
, wr::ColorF aClearColor
,
107 const wr::DeviceIntRect
* aDirtyRects
,
108 size_t aNumDirtyRects
,
109 const wr::DeviceIntRect
* aOpaqueRects
,
110 size_t aNumOpaqueRects
) {
111 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
112 compositor
->StartCompositing(aClearColor
, aDirtyRects
, aNumDirtyRects
,
113 aOpaqueRects
, aNumOpaqueRects
);
116 void wr_compositor_end_frame(void* aCompositor
) {
117 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
118 compositor
->CompositorEndFrame();
121 void wr_compositor_enable_native_compositor(void* aCompositor
, bool aEnable
) {
122 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
123 compositor
->EnableNativeCompositor(aEnable
);
126 void wr_compositor_get_capabilities(void* aCompositor
,
127 CompositorCapabilities
* aCaps
) {
128 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
129 compositor
->GetCompositorCapabilities(aCaps
);
132 void wr_compositor_get_window_visibility(void* aCompositor
,
133 WindowVisibility
* aVisibility
) {
134 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
135 compositor
->GetWindowVisibility(aVisibility
);
138 void wr_compositor_unbind(void* aCompositor
) {
139 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
140 compositor
->Unbind();
143 void wr_compositor_deinit(void* aCompositor
) {
144 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
145 compositor
->DeInit();
148 void wr_compositor_map_tile(void* aCompositor
, wr::NativeTileId aId
,
149 wr::DeviceIntRect aDirtyRect
,
150 wr::DeviceIntRect aValidRect
, void** aData
,
152 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
153 compositor
->MapTile(aId
, aDirtyRect
, aValidRect
, aData
, aStride
);
156 void wr_compositor_unmap_tile(void* aCompositor
) {
157 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
158 compositor
->UnmapTile();
161 void wr_partial_present_compositor_set_buffer_damage_region(
162 void* aCompositor
, const wr::DeviceIntRect
* aRects
, size_t aNRects
) {
163 RenderCompositor
* compositor
= static_cast<RenderCompositor
*>(aCompositor
);
164 compositor
->SetBufferDamageRegion(aRects
, aNRects
);
168 UniquePtr
<RenderCompositor
> RenderCompositor::Create(
169 const RefPtr
<widget::CompositorWidget
>& aWidget
, nsACString
& aError
) {
170 if (aWidget
->GetCompositorOptions().UseSoftwareWebRender()) {
172 // Mac uses NativeLayerCA
173 if (!gfxPlatform::IsHeadless()) {
174 return RenderCompositorNativeSWGL::Create(aWidget
, aError
);
176 #elif defined(MOZ_WAYLAND)
177 if (gfx::gfxVars::UseWebRenderCompositor()) {
178 return RenderCompositorNativeSWGL::Create(aWidget
, aError
);
181 UniquePtr
<RenderCompositor
> comp
=
182 RenderCompositorLayersSWGL::Create(aWidget
, aError
);
186 #if defined(MOZ_WIDGET_ANDROID)
187 // On Android, we do not want to fallback from RenderCompositorOGLSWGL to
188 // RenderCompositorSWGL.
189 if (aWidget
->GetCompositorOptions().AllowSoftwareWebRenderOGL()) {
193 return RenderCompositorSWGL::Create(aWidget
, aError
);
197 if (gfx::gfxVars::UseWebRenderANGLE()) {
198 return RenderCompositorANGLE::Create(aWidget
, aError
);
202 #if defined(MOZ_WAYLAND)
203 if (gfx::gfxVars::UseWebRenderCompositor()) {
204 return RenderCompositorNativeOGL::Create(aWidget
, aError
);
208 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK)
209 UniquePtr
<RenderCompositor
> eglCompositor
=
210 RenderCompositorEGL::Create(aWidget
, aError
);
212 return eglCompositor
;
216 #if defined(MOZ_WIDGET_ANDROID)
217 // RenderCompositorOGL is not used on android
219 #elif defined(XP_DARWIN)
220 // Mac uses NativeLayerCA
221 return RenderCompositorNativeOGL::Create(aWidget
, aError
);
223 return RenderCompositorOGL::Create(aWidget
, aError
);
227 RenderCompositor::RenderCompositor(
228 const RefPtr
<widget::CompositorWidget
>& aWidget
)
229 : mWidget(aWidget
) {}
231 RenderCompositor::~RenderCompositor() = default;
233 bool RenderCompositor::MakeCurrent() { return gl()->MakeCurrent(); }
235 void RenderCompositor::GetCompositorCapabilities(
236 CompositorCapabilities
* aCaps
) {
237 if (StaticPrefs::gfx_webrender_compositor_max_update_rects_AtStartup() > 0) {
238 aCaps
->max_update_rects
= 1;
240 aCaps
->max_update_rects
= 0;
244 void RenderCompositor::GetWindowVisibility(WindowVisibility
* aVisibility
) {
246 auto* widget
= mWidget
->AsWindows();
250 aVisibility
->size_mode
= ToWrWindowSizeMode(widget
->GetWindowSizeMode());
251 aVisibility
->is_fully_occluded
= widget
->GetWindowIsFullyOccluded();
255 GLenum
RenderCompositor::IsContextLost(bool aForce
) {
257 // GetGraphicsResetStatus may trigger an implicit MakeCurrent if robustness
258 // is not supported, so unless we are forcing, pass on the check.
259 if (!glc
|| (!aForce
&& !glc
->IsSupported(gl::GLFeature::robustness
))) {
260 return LOCAL_GL_NO_ERROR
;
262 auto resetStatus
= glc
->fGetGraphicsResetStatus();
263 switch (resetStatus
) {
264 case LOCAL_GL_NO_ERROR
:
266 case LOCAL_GL_INNOCENT_CONTEXT_RESET_ARB
:
267 NS_WARNING("Device reset due to system / different context");
269 case LOCAL_GL_PURGED_CONTEXT_RESET_NV
:
270 NS_WARNING("Device reset due to NV video memory purged");
272 case LOCAL_GL_GUILTY_CONTEXT_RESET_ARB
:
273 gfxCriticalError() << "Device reset due to WR context";
275 case LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB
:
276 gfxCriticalNote
<< "Device reset may be due to WR context";
279 gfxCriticalError() << "Device reset with WR context unexpected status: "
280 << gfx::hexa(resetStatus
);
286 } // namespace mozilla::wr