zng_wgt_webrender_debug/
lib.rs#![doc(html_favicon_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo-icon.png")]
#![doc(html_logo_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo.png")]
#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
pub use webrender_api::DebugFlags;
use zng_app::view_process::{VIEW_PROCESS, VIEW_PROCESS_INITED_EVENT};
use zng_ext_window::WINDOWS;
use zng_wgt::prelude::*;
#[property(CONTEXT, default(RendererDebug::disabled()))]
pub fn renderer_debug(child: impl UiNode, debug: impl IntoVar<RendererDebug>) -> impl UiNode {
let debug = debug.into_var();
let mut send = false;
match_node(child, move |_, op| match op {
UiNodeOp::Init => {
WIDGET.sub_var(&debug).sub_event(&VIEW_PROCESS_INITED_EVENT);
send = debug.with(|d| !d.is_empty());
}
UiNodeOp::Event { update } => {
if VIEW_PROCESS_INITED_EVENT.has(update) {
send = true;
WIDGET.layout();
}
}
UiNodeOp::Update { .. } => {
if debug.is_new() {
send = true;
WIDGET.layout();
}
}
UiNodeOp::Layout { .. } => {
if std::mem::take(&mut send) {
if let Some(ext_id) = VIEW_PROCESS.extension_id("zng-view.webrender_debug").ok().flatten() {
debug.with(|d| match WINDOWS.view_render_extension(WINDOW.id(), ext_id, d) {
Ok(()) => {}
Err(e) => tracing::error!("{e}"),
});
}
}
}
_ => {}
})
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
pub struct RendererDebug {
#[serde(with = "serde_debug_flags")]
pub flags: DebugFlags,
pub profiler_ui: String,
}
impl Default for RendererDebug {
fn default() -> Self {
Self::disabled()
}
}
impl RendererDebug {
pub fn disabled() -> Self {
Self {
flags: DebugFlags::empty(),
profiler_ui: String::new(),
}
}
pub fn profiler(ui: impl Into<String>) -> Self {
Self {
flags: DebugFlags::PROFILER_DBG,
profiler_ui: ui.into(),
}
}
pub fn flags(flags: DebugFlags) -> Self {
Self {
flags,
profiler_ui: String::new(),
}
}
pub fn is_empty(&self) -> bool {
self.flags.is_empty() && self.profiler_ui.is_empty()
}
}
impl_from_and_into_var! {
fn from(profiler_default: bool) -> RendererDebug {
if profiler_default {
Self::profiler("Default")
} else {
Self::disabled()
}
}
fn from(profiler: &str) -> RendererDebug {
Self::profiler(profiler)
}
fn from(profiler: Txt) -> RendererDebug {
Self::profiler(profiler)
}
fn from(flags: DebugFlags) -> RendererDebug {
Self::flags(flags)
}
}
mod serde_debug_flags {
use super::*;
use serde::*;
bitflags::bitflags! {
#[repr(C)]
#[derive(Default, Deserialize, Serialize)]
#[serde(transparent)]
struct DebugFlagsRef: u32 {
const PROFILER_DBG = DebugFlags::PROFILER_DBG.bits();
const RENDER_TARGET_DBG = DebugFlags::RENDER_TARGET_DBG.bits();
const TEXTURE_CACHE_DBG = DebugFlags::TEXTURE_CACHE_DBG.bits();
const GPU_TIME_QUERIES = DebugFlags::GPU_TIME_QUERIES.bits();
const GPU_SAMPLE_QUERIES = DebugFlags::GPU_SAMPLE_QUERIES.bits();
const DISABLE_BATCHING = DebugFlags::DISABLE_BATCHING.bits();
const EPOCHS = DebugFlags::EPOCHS.bits();
const ECHO_DRIVER_MESSAGES = DebugFlags::ECHO_DRIVER_MESSAGES.bits();
const SHOW_OVERDRAW = DebugFlags::SHOW_OVERDRAW.bits();
const GPU_CACHE_DBG = DebugFlags::GPU_CACHE_DBG.bits();
const TEXTURE_CACHE_DBG_CLEAR_EVICTED = DebugFlags::TEXTURE_CACHE_DBG_CLEAR_EVICTED.bits();
const PICTURE_CACHING_DBG = DebugFlags::PICTURE_CACHING_DBG.bits();
const PRIMITIVE_DBG = DebugFlags::PRIMITIVE_DBG.bits();
const ZOOM_DBG = DebugFlags::ZOOM_DBG.bits();
const SMALL_SCREEN = DebugFlags::SMALL_SCREEN.bits();
const DISABLE_OPAQUE_PASS = DebugFlags::DISABLE_OPAQUE_PASS.bits();
const DISABLE_ALPHA_PASS = DebugFlags::DISABLE_ALPHA_PASS.bits();
const DISABLE_CLIP_MASKS = DebugFlags::DISABLE_CLIP_MASKS.bits();
const DISABLE_TEXT_PRIMS = DebugFlags::DISABLE_TEXT_PRIMS.bits();
const DISABLE_GRADIENT_PRIMS = DebugFlags::DISABLE_GRADIENT_PRIMS.bits();
const OBSCURE_IMAGES = DebugFlags::OBSCURE_IMAGES.bits();
const GLYPH_FLASHING = DebugFlags::GLYPH_FLASHING.bits();
const SMART_PROFILER = DebugFlags::SMART_PROFILER.bits();
const INVALIDATION_DBG = DebugFlags::INVALIDATION_DBG.bits();
const PROFILER_CAPTURE = DebugFlags::PROFILER_CAPTURE.bits();
const FORCE_PICTURE_INVALIDATION = DebugFlags::FORCE_PICTURE_INVALIDATION.bits();
const WINDOW_VISIBILITY_DBG = DebugFlags::WINDOW_VISIBILITY_DBG.bits();
const RESTRICT_BLOB_SIZE = DebugFlags::RESTRICT_BLOB_SIZE.bits();
}
}
impl From<DebugFlagsRef> for DebugFlags {
fn from(value: DebugFlagsRef) -> Self {
DebugFlags::from_bits(value.bits()).unwrap()
}
}
impl From<DebugFlags> for DebugFlagsRef {
fn from(value: DebugFlags) -> Self {
DebugFlagsRef::from_bits(value.bits()).unwrap()
}
}
pub fn serialize<S: serde::Serializer>(flags: &DebugFlags, serializer: S) -> Result<S::Ok, S::Error> {
DebugFlagsRef::from(*flags).serialize(serializer)
}
pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<DebugFlags, D::Error> {
DebugFlagsRef::deserialize(deserializer).map(Into::into)
}
}