Bug 1742440 - Add debug capability to check window visibility state by overlay r=gfx-reviewers,nical

It is helpful if window visibility state could be checked by debug overlay.
For now, it works only on Windows with compositor.

Differential Revision: https://phabricator.services.mozilla.com/D131807
This commit is contained in:
sotaro 2021-11-25 11:33:46 +00:00
parent 6110156f18
commit 5477d7dc1d
21 changed files with 227 additions and 4 deletions

View File

@ -575,6 +575,8 @@ static void WebRenderDebugPrefChangeCallback(const char* aPrefName, void*) {
GFX_WEBRENDER_DEBUG(".obscure-images", wr::DebugFlags::OBSCURE_IMAGES)
GFX_WEBRENDER_DEBUG(".glyph-flashing", wr::DebugFlags::GLYPH_FLASHING)
GFX_WEBRENDER_DEBUG(".capture-profiler", wr::DebugFlags::PROFILER_CAPTURE)
GFX_WEBRENDER_DEBUG(".window-visibility",
wr::DebugFlags::WINDOW_VISIBILITY_DBG)
#undef GFX_WEBRENDER_DEBUG
gfx::gfxVars::SetWebRenderDebugFlags(flags.bits);

View File

@ -20,6 +20,7 @@
#ifdef XP_WIN
# include "mozilla/webrender/RenderCompositorANGLE.h"
# include "mozilla/widget/WinCompositorWidget.h"
#endif
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WAYLAND) || defined(MOZ_X11)
@ -121,6 +122,12 @@ void wr_compositor_get_capabilities(void* aCompositor,
compositor->GetCompositorCapabilities(aCaps);
}
void wr_compositor_get_window_visibility(void* aCompositor,
WindowVisibility* aVisibility) {
RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor);
compositor->GetWindowVisibility(aVisibility);
}
void wr_compositor_unbind(void* aCompositor) {
RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor);
compositor->Unbind();
@ -227,6 +234,17 @@ void RenderCompositor::GetCompositorCapabilities(
}
}
void RenderCompositor::GetWindowVisibility(WindowVisibility* aVisibility) {
#ifdef XP_WIN
auto* widget = mWidget->AsWindows();
if (!widget) {
return;
}
aVisibility->size_mode = ToWrWindowSizeMode(widget->GetWindowSizeMode());
aVisibility->is_fully_occluded = widget->GetWindowIsFullyOccluded();
#endif
}
GLenum RenderCompositor::IsContextLost(bool aForce) {
auto* glc = gl();
// GetGraphicsResetStatus may trigger an implicit MakeCurrent if robustness

View File

@ -153,6 +153,8 @@ class RenderCompositor {
// compositor might require.
virtual void GetCompositorCapabilities(CompositorCapabilities* aCaps);
virtual void GetWindowVisibility(WindowVisibility* aVisibility);
// Interface for partial present
virtual bool UsePartialPresent() { return false; }
virtual bool RequestFullRender() { return false; }

View File

@ -20,6 +20,7 @@
#include "mozilla/Range.h"
#include "mozilla/TypeTraits.h"
#include "Units.h"
#include "nsIWidgetListener.h"
namespace mozilla {
@ -872,6 +873,22 @@ static inline wr::SyntheticItalics DegreesToSyntheticItalics(float aDegrees) {
return synthetic_italics;
}
static inline wr::WindowSizeMode ToWrWindowSizeMode(nsSizeMode aSizeMode) {
switch (aSizeMode) {
case nsSizeMode_Normal:
return wr::WindowSizeMode::Normal;
case nsSizeMode_Minimized:
return wr::WindowSizeMode::Minimized;
case nsSizeMode_Maximized:
return wr::WindowSizeMode::Maximized;
case nsSizeMode_Fullscreen:
return wr::WindowSizeMode::Fullscreen;
default:
MOZ_ASSERT_UNREACHABLE("Tried to convert invalid size mode.");
return wr::WindowSizeMode::Invalid;
}
}
} // namespace wr
} // namespace mozilla

View File

@ -42,7 +42,7 @@ use webrender::{
MappedTileInfo, NativeSurfaceId, NativeSurfaceInfo, NativeTileId, PartialPresentCompositor, PipelineInfo,
ProfilerHooks, RecordedFrameHandle, Renderer, RendererOptions, RendererStats, SWGLCompositeSurfaceInfo,
SceneBuilderHooks, ShaderPrecacheFlags, Shaders, SharedShaders, TextureCacheConfig, UploadMethod,
ONE_TIME_USAGE_HINT,
ONE_TIME_USAGE_HINT, WindowVisibility,
};
use wr_malloc_size_of::MallocSizeOfOps;
@ -1258,6 +1258,7 @@ extern "C" {
fn wr_compositor_enable_native_compositor(compositor: *mut c_void, enable: bool);
fn wr_compositor_deinit(compositor: *mut c_void);
fn wr_compositor_get_capabilities(compositor: *mut c_void, caps: *mut CompositorCapabilities);
fn wr_compositor_get_window_visibility(compositor: *mut c_void, caps: *mut WindowVisibility);
fn wr_compositor_map_tile(
compositor: *mut c_void,
id: NativeTileId,
@ -1407,6 +1408,14 @@ impl Compositor for WrCompositor {
caps
}
}
fn get_window_visibility(&self) -> WindowVisibility {
unsafe {
let mut visibility: WindowVisibility = Default::default();
wr_compositor_get_window_visibility(self.0, &mut visibility);
visibility
}
}
}
extern "C" {

View File

@ -973,6 +973,32 @@ impl Default for CompositorCapabilities {
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub enum WindowSizeMode {
Normal,
Minimized,
Maximized,
Fullscreen,
Invalid,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct WindowVisibility {
pub size_mode: WindowSizeMode,
pub is_fully_occluded: bool,
}
impl Default for WindowVisibility {
fn default() -> Self {
WindowVisibility {
size_mode: WindowSizeMode::Normal,
is_fully_occluded: false,
}
}
}
/// The transform type to apply to Compositor surfaces.
// TODO: Should transform from CompositorSurfacePixel instead, but this requires a cleanup of the
// Compositor API to use CompositorSurface-space geometry instead of Device-space where necessary
@ -1120,6 +1146,8 @@ pub trait Compositor {
/// specify what features a compositor supports, depending on the
/// underlying platform
fn get_capabilities(&self) -> CompositorCapabilities;
fn get_window_visibility(&self) -> WindowVisibility;
}
/// Information about the underlying data buffer of a mapped tile.

View File

@ -13,7 +13,7 @@ use std::thread;
use crate::{
api::units::*, api::ColorDepth, api::ColorF, api::ExternalImageId, api::ImageRendering, api::YuvRangedColorSpace,
Compositor, CompositorCapabilities, CompositorSurfaceTransform, NativeSurfaceId, NativeSurfaceInfo, NativeTileId,
profiler, MappableCompositor, SWGLCompositeSurfaceInfo,
profiler, MappableCompositor, SWGLCompositeSurfaceInfo, WindowVisibility,
};
pub struct SwTile {
@ -1500,4 +1500,8 @@ impl Compositor for SwCompositor {
fn get_capabilities(&self) -> CompositorCapabilities {
self.compositor.get_capabilities()
}
fn get_window_visibility(&self) -> WindowVisibility {
self.compositor.get_window_visibility()
}
}

View File

@ -203,7 +203,7 @@ extern crate webrender_build;
#[doc(hidden)]
pub use crate::composite::{CompositorConfig, Compositor, CompositorCapabilities, CompositorSurfaceTransform};
pub use crate::composite::{NativeSurfaceId, NativeTileId, NativeSurfaceInfo, PartialPresentCompositor};
pub use crate::composite::{MappableCompositor, MappedTileInfo, SWGLCompositeSurfaceInfo};
pub use crate::composite::{MappableCompositor, MappedTileInfo, SWGLCompositeSurfaceInfo, WindowVisibility};
pub use crate::device::{UploadMethod, VertexUsageHint, get_gl_target, get_unoptimized_shader_source};
pub use crate::device::{ProgramBinary, ProgramCache, ProgramCacheObserver, FormatDesc};
pub use crate::device::Device;

View File

@ -1789,7 +1789,8 @@ impl Renderer {
DebugFlags::GPU_CACHE_DBG |
DebugFlags::PICTURE_CACHING_DBG |
DebugFlags::PRIMITIVE_DBG |
DebugFlags::ZOOM_DBG
DebugFlags::ZOOM_DBG |
DebugFlags::WINDOW_VISIBILITY_DBG
);
// Update the debug overlay surface, if we are running in native compositor mode.
@ -2039,6 +2040,7 @@ impl Renderer {
self.draw_gpu_cache_debug(device_size);
self.draw_zoom_debug(device_size);
self.draw_epoch_debug();
self.draw_window_visibility_debug();
draw_target
})
});
@ -5247,6 +5249,39 @@ impl Renderer {
);
}
fn draw_window_visibility_debug(&mut self) {
if !self.debug_flags.contains(DebugFlags::WINDOW_VISIBILITY_DBG) {
return;
}
let debug_renderer = match self.debug.get_mut(&mut self.device) {
Some(render) => render,
None => return,
};
let x: f32 = 30.0;
let y: f32 = 40.0;
if let CompositorConfig::Native { ref mut compositor, .. } = self.compositor_config {
let visibility = compositor.get_window_visibility();
let color = if visibility.is_fully_occluded {
ColorU::new(255, 0, 0, 255)
} else {
ColorU::new(0, 0, 255, 255)
};
debug_renderer.add_text(
x, y,
&format!("{:?}", visibility),
color,
None,
);
}
}
fn draw_gpu_cache_debug(&mut self, device_size: DeviceIntSize) {
if !self.debug_flags.contains(DebugFlags::GPU_CACHE_DBG) {
return;

View File

@ -632,6 +632,8 @@ bitflags! {
const PROFILER_CAPTURE = (1 as u32) << 25; // need "as u32" until we have cbindgen#556
/// Invalidate picture tiles every frames (useful when inspecting GPU work in external tools).
const FORCE_PICTURE_INVALIDATION = (1 as u32) << 26;
/// Display window visibility on screen.
const WINDOW_VISIBILITY_DBG = 1 << 27;
}
}

View File

@ -660,6 +660,7 @@ pref("gfx.webrender.debug.obscure-images", false);
pref("gfx.webrender.debug.glyph-flashing", false);
pref("gfx.webrender.debug.capture-profiler", false);
pref("gfx.webrender.debug.profiler-ui", "Default");
pref("gfx.webrender.debug.window-visibility", false);
pref("gfx.webrender.multithreading", true);
#ifdef XP_WIN

View File

@ -74,6 +74,11 @@ void CompositorWidgetChild::UpdateTransparency(nsTransparencyMode aMode) {
Unused << SendUpdateTransparency(aMode);
}
void CompositorWidgetChild::NotifyVisibilityUpdated(nsSizeMode aSizeMode,
bool aIsFullyOccluded) {
Unused << SendNotifyVisibilityUpdated(aSizeMode, aIsFullyOccluded);
};
void CompositorWidgetChild::ClearTransparentWindow() {
Unused << SendClearTransparentWindow();
}

View File

@ -35,6 +35,8 @@ class CompositorWidgetChild final : public PCompositorWidgetChild,
bool OnWindowResize(const LayoutDeviceIntSize& aSize) override;
void OnWindowModeChange(nsSizeMode aSizeMode) override;
void UpdateTransparency(nsTransparencyMode aMode) override;
void NotifyVisibilityUpdated(nsSizeMode aSizeMode,
bool aIsFullyOccluded) override;
void ClearTransparentWindow() override;
mozilla::ipc::IPCResult RecvObserveVsync() override;

View File

@ -36,6 +36,8 @@ CompositorWidgetParent::CompositorWidgetParent(
aInitData.get_WinCompositorWidgetInitData().hWnd())),
mTransparencyMode(
aInitData.get_WinCompositorWidgetInitData().transparencyMode()),
mSizeMode(nsSizeMode_Normal),
mIsFullyOccluded(false),
mRemoteBackbufferClient() {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
MOZ_ASSERT(mWnd && ::IsWindow(mWnd));
@ -150,6 +152,25 @@ mozilla::ipc::IPCResult CompositorWidgetParent::RecvUpdateTransparency(
return IPC_OK();
}
mozilla::ipc::IPCResult CompositorWidgetParent::RecvNotifyVisibilityUpdated(
const nsSizeMode& aSizeMode, const bool& aIsFullyOccluded) {
mSizeMode = aSizeMode;
mIsFullyOccluded = aIsFullyOccluded;
return IPC_OK();
}
nsSizeMode CompositorWidgetParent::CompositorWidgetParent::GetWindowSizeMode()
const {
nsSizeMode sizeMode = mSizeMode;
return sizeMode;
}
bool CompositorWidgetParent::CompositorWidgetParent::GetWindowIsFullyOccluded()
const {
bool isFullyOccluded = mIsFullyOccluded;
return isFullyOccluded;
}
mozilla::ipc::IPCResult CompositorWidgetParent::RecvClearTransparentWindow() {
gfx::CriticalSectionAutoEnter lock(&mPresentLock);

View File

@ -45,12 +45,17 @@ class CompositorWidgetParent final : public PCompositorWidgetParent,
bool HasGlass() const override;
nsSizeMode GetWindowSizeMode() const override;
bool GetWindowIsFullyOccluded() const override;
mozilla::ipc::IPCResult RecvInitialize(
const RemoteBackbufferHandles& aRemoteHandles) override;
mozilla::ipc::IPCResult RecvEnterPresentLock() override;
mozilla::ipc::IPCResult RecvLeavePresentLock() override;
mozilla::ipc::IPCResult RecvUpdateTransparency(
const nsTransparencyMode& aMode) override;
mozilla::ipc::IPCResult RecvNotifyVisibilityUpdated(
const nsSizeMode& aSizeMode, const bool& aIsFullyOccluded) override;
mozilla::ipc::IPCResult RecvClearTransparentWindow() override;
void ActorDestroy(ActorDestroyReason aWhy) override;
@ -75,6 +80,10 @@ class CompositorWidgetParent final : public PCompositorWidgetParent,
mozilla::Atomic<nsTransparencyMode, MemoryOrdering::Relaxed>
mTransparencyMode;
// Visibility handling.
mozilla::Atomic<nsSizeMode, MemoryOrdering::Relaxed> mSizeMode;
mozilla::Atomic<bool, MemoryOrdering::Relaxed> mIsFullyOccluded;
std::unique_ptr<remote_backbuffer::Client> mRemoteBackbufferClient;
};

View File

@ -277,6 +277,22 @@ void InProcessWinCompositorWidget::UpdateTransparency(
}
}
void InProcessWinCompositorWidget::NotifyVisibilityUpdated(
nsSizeMode aSizeMode, bool aIsFullyOccluded) {
mSizeMode = aSizeMode;
mIsFullyOccluded = aIsFullyOccluded;
}
nsSizeMode InProcessWinCompositorWidget::GetWindowSizeMode() const {
nsSizeMode sizeMode = mSizeMode;
return sizeMode;
}
bool InProcessWinCompositorWidget::GetWindowIsFullyOccluded() const {
bool isFullyOccluded = mIsFullyOccluded;
return isFullyOccluded;
}
bool InProcessWinCompositorWidget::HasGlass() const {
MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread() ||
wr::RenderThread::IsInRenderThread());

View File

@ -48,6 +48,8 @@ class InProcessWinCompositorWidget final
bool OnWindowResize(const LayoutDeviceIntSize& aSize) override;
void OnWindowModeChange(nsSizeMode aSizeMode) override;
void UpdateTransparency(nsTransparencyMode aMode) override;
void NotifyVisibilityUpdated(nsSizeMode aSizeMode,
bool aIsFullyOccluded) override;
void ClearTransparentWindow() override;
bool RedrawTransparentWindow();
@ -63,6 +65,9 @@ class InProcessWinCompositorWidget final
bool HasGlass() const override;
nsSizeMode GetWindowSizeMode() const override;
bool GetWindowIsFullyOccluded() const override;
void ObserveVsync(VsyncObserver* aObserver) override;
nsIWidget* RealWidget() override;
@ -86,6 +91,11 @@ class InProcessWinCompositorWidget final
mozilla::Mutex mTransparentSurfaceLock;
mozilla::Atomic<nsTransparencyMode, MemoryOrdering::Relaxed>
mTransparencyMode;
// Visibility handling.
mozilla::Atomic<nsSizeMode, MemoryOrdering::Relaxed> mSizeMode;
mozilla::Atomic<bool, MemoryOrdering::Relaxed> mIsFullyOccluded;
RefPtr<gfxASurface> mTransparentSurface;
HDC mMemoryDC;
HDC mCompositeDC;

View File

@ -6,11 +6,13 @@
include protocol PCompositorBridge;
include "mozilla/dom/TabMessageUtils.h";
include "mozilla/widget/WidgetMessageUtils.h";
using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
using mozilla::WindowsHandle from "mozilla/ipc/IPCTypes.h";
using nsTransparencyMode from "nsIWidget.h";
using nsSizeMode from "nsIWidget.h";
namespace mozilla {
namespace widget {
@ -31,6 +33,7 @@ parent:
sync EnterPresentLock();
sync LeavePresentLock();
async UpdateTransparency(nsTransparencyMode aMode);
async NotifyVisibilityUpdated(nsSizeMode aSizeMode, bool aIsFullyOccluded);
sync ClearTransparentWindow();
async __delete__();

View File

@ -34,6 +34,10 @@ class PlatformCompositorWidgetDelegate : public CompositorWidgetDelegate {
virtual void UpdateTransparency(nsTransparencyMode aMode) = 0;
virtual void ClearTransparentWindow() = 0;
// Deliver visibility info
virtual void NotifyVisibilityUpdated(nsSizeMode aSizeMode,
bool aIsFullyOccluded) = 0;
// CompositorWidgetDelegate Overrides
PlatformCompositorWidgetDelegate* AsPlatformSpecificDelegate() override {
@ -75,6 +79,9 @@ class WinCompositorWidget : public CompositorWidget {
virtual bool HasGlass() const = 0;
virtual nsSizeMode GetWindowSizeMode() const = 0;
virtual bool GetWindowIsFullyOccluded() const = 0;
virtual void UpdateCompositorWnd(const HWND aCompositorWnd,
const HWND aParentWnd) = 0;
virtual void SetRootLayerTreeID(const layers::LayersId& aRootLayerTreeId) = 0;

View File

@ -7342,6 +7342,14 @@ void nsWindow::OnSizeModeChange(nsSizeMode aSizeMode) {
if (NeedsToTrackWindowOcclusionState()) {
WinWindowOcclusionTracker::Get()->OnWindowVisibilityChanged(
this, aSizeMode != nsSizeMode_Minimized);
wr::DebugFlags flags{0};
flags.bits = gfx::gfxVars::WebRenderDebugFlags();
bool debugEnabled = bool(flags & wr::DebugFlags::WINDOW_VISIBILITY_DBG);
if (debugEnabled && mCompositorWidgetDelegate) {
mCompositorWidgetDelegate->NotifyVisibilityUpdated(aSizeMode,
mIsFullyOccluded);
}
}
if (mCompositorWidgetDelegate) {

View File

@ -430,6 +430,14 @@ void nsWindow::NotifyOcclusionState(mozilla::widget::OcclusionState aState) {
("nsWindow::NotifyOcclusionState() mIsFullyOccluded %d mSizeMode %d",
mIsFullyOccluded, mSizeMode));
wr::DebugFlags flags{0};
flags.bits = gfx::gfxVars::WebRenderDebugFlags();
bool debugEnabled = bool(flags & wr::DebugFlags::WINDOW_VISIBILITY_DBG);
if (debugEnabled && mCompositorWidgetDelegate) {
mCompositorWidgetDelegate->NotifyVisibilityUpdated(mSizeMode,
mIsFullyOccluded);
}
if (mWidgetListener) {
mWidgetListener->OcclusionStateChanged(mIsFullyOccluded);
}
@ -442,6 +450,14 @@ void nsWindow::MaybeEnableWindowOcclusion(bool aEnable) {
// Enable window occlusion.
if (enabled && NeedsToTrackWindowOcclusionState()) {
WinWindowOcclusionTracker::Get()->Enable(this, mWnd);
wr::DebugFlags flags{0};
flags.bits = gfx::gfxVars::WebRenderDebugFlags();
bool debugEnabled = bool(flags & wr::DebugFlags::WINDOW_VISIBILITY_DBG);
if (debugEnabled && mCompositorWidgetDelegate) {
mCompositorWidgetDelegate->NotifyVisibilityUpdated(mSizeMode,
mIsFullyOccluded);
}
}
return;
}
@ -455,6 +471,14 @@ void nsWindow::MaybeEnableWindowOcclusion(bool aEnable) {
WinWindowOcclusionTracker::Get()->Disable(this, mWnd);
NotifyOcclusionState(OcclusionState::VISIBLE);
wr::DebugFlags flags{0};
flags.bits = gfx::gfxVars::WebRenderDebugFlags();
bool debugEnabled = bool(flags & wr::DebugFlags::WINDOW_VISIBILITY_DBG);
if (debugEnabled && mCompositorWidgetDelegate) {
mCompositorWidgetDelegate->NotifyVisibilityUpdated(mSizeMode,
mIsFullyOccluded);
}
}
// This override of CreateCompositor is to add support for sending the IPC