1use api::{BlobImageHandler, ColorF, CrashAnnotator, DocumentId, IdNamespace};
6use api::{VoidPtrToSizeFn, FontRenderMode, ImageFormat};
7use api::{RenderNotifier, ImageBufferKind};
8use api::units::*;
9use api::channel::unbounded_channel;
10pub use api::DebugFlags;
11
12use crate::bump_allocator::ChunkPool;
13use crate::render_api::{RenderApiSender, FrameMsg};
14use crate::composite::{CompositorKind, CompositorConfig};
15use crate::device::{
16 UploadMethod, UploadPBOPool, VertexUsageHint, Device, ProgramCache, TextureFilter
17};
18use crate::frame_builder::FrameBuilderConfig;
19use crate::glyph_cache::GlyphCache;
20use glyph_rasterizer::{GlyphRasterThread, GlyphRasterizer, SharedFontResources};
21use crate::gpu_types::PrimitiveInstanceData;
22use crate::internal_types::{FastHashMap, FastHashSet};
23use crate::profiler::{self, Profiler, TransactionProfile};
24use crate::device::query::{GpuProfiler, GpuDebugMethod};
25use crate::render_backend::RenderBackend;
26use crate::resource_cache::ResourceCache;
27use crate::scene_builder_thread::{SceneBuilderThread, SceneBuilderThreadChannels, LowPrioritySceneBuilderThread};
28use crate::texture_cache::{TextureCache, TextureCacheConfig};
29use crate::picture_textures::PictureTextures;
30use crate::renderer::{
31 debug, vertex, gl,
32 Renderer, DebugOverlayState, BufferDamageTracker, PipelineInfo, TextureResolver,
33 RendererError, ShaderPrecacheFlags, VERTEX_DATA_TEXTURE_COUNT,
34 upload::UploadTexturePool,
35 shade::{Shaders, SharedShaders},
36};
37#[cfg(feature = "debugger")]
38use crate::debugger::Debugger;
39
40use std::{
41 mem,
42 thread,
43 cell::RefCell,
44 collections::VecDeque,
45 rc::Rc,
46 sync::{Arc, atomic::{AtomicBool, Ordering}},
47 num::NonZeroUsize,
48 path::PathBuf,
49};
50
51use tracy_rs::register_thread_with_profiler;
52use rayon::{ThreadPool, ThreadPoolBuilder};
53use malloc_size_of::MallocSizeOfOps;
54
55pub const ONE_TIME_USAGE_HINT: VertexUsageHint = VertexUsageHint::Stream;
58
59static HAS_BEEN_INITIALIZED: AtomicBool = AtomicBool::new(false);
61
62pub fn wr_has_been_initialized() -> bool {
64 HAS_BEEN_INITIALIZED.load(Ordering::SeqCst)
65}
66
67pub trait SceneBuilderHooks {
70 fn register(&self);
73 fn pre_scene_build(&self);
75 fn pre_scene_swap(&self);
77 fn post_scene_swap(&self, document_id: &Vec<DocumentId>, info: PipelineInfo, schedule_frame: bool);
81 fn post_resource_update(&self, document_ids: &Vec<DocumentId>);
85 fn post_empty_scene_build(&self);
90 fn poke(&self);
95 fn deregister(&self);
98}
99
100pub trait AsyncPropertySampler {
104 fn register(&self);
107 fn sample(&self, document_id: DocumentId, generated_frame_id: Option<u64>) -> Vec<FrameMsg>;
111 fn deregister(&self);
114}
115
116pub trait RenderBackendHooks {
117 fn init_thread(&self);
118}
119
120pub struct WebRenderOptions {
121 pub resource_override_path: Option<PathBuf>,
122 pub use_optimized_shaders: bool,
124 pub enable_aa: bool,
125 pub enable_dithering: bool,
126 pub max_recorded_profiles: usize,
127 pub precache_flags: ShaderPrecacheFlags,
128 pub enable_subpixel_aa: bool,
130 pub clear_color: ColorF,
131 pub enable_clear_scissor: Option<bool>,
132 pub max_internal_texture_size: Option<i32>,
133 pub image_tiling_threshold: i32,
134 pub upload_method: UploadMethod,
135 pub upload_pbo_default_size: usize,
137 pub batched_upload_threshold: i32,
138 pub workers: Option<Arc<ThreadPool>>,
139 pub chunk_pool: Option<Arc<ChunkPool>>,
143 pub dedicated_glyph_raster_thread: Option<GlyphRasterThread>,
144 pub enable_multithreading: bool,
145 pub blob_image_handler: Option<Box<dyn BlobImageHandler>>,
146 pub crash_annotator: Option<Box<dyn CrashAnnotator>>,
147 pub size_of_op: Option<VoidPtrToSizeFn>,
148 pub enclosing_size_of_op: Option<VoidPtrToSizeFn>,
149 pub cached_programs: Option<Rc<ProgramCache>>,
150 pub debug_flags: DebugFlags,
151 pub renderer_id: Option<u64>,
152 pub scene_builder_hooks: Option<Box<dyn SceneBuilderHooks + Send>>,
153 pub render_backend_hooks: Option<Box<dyn RenderBackendHooks + Send>>,
154 pub sampler: Option<Box<dyn AsyncPropertySampler + Send>>,
155 pub support_low_priority_transactions: bool,
156 pub namespace_alloc_by_client: bool,
157 pub shared_font_namespace: Option<IdNamespace>,
161 pub testing: bool,
162 pub gpu_supports_fast_clears: bool,
167 pub allow_dual_source_blending: bool,
168 pub allow_advanced_blend_equation: bool,
169 pub allow_texture_storage_support: bool,
172 pub allow_texture_swizzling: bool,
176 pub clear_caches_with_quads: bool,
181 pub dump_shader_source: Option<String>,
183 pub surface_origin_is_top_left: bool,
184 pub compositor_config: CompositorConfig,
186 pub enable_gpu_markers: bool,
187 pub panic_on_gl_error: bool,
190 pub picture_tile_size: Option<DeviceIntSize>,
191 pub texture_cache_config: TextureCacheConfig,
192 pub enable_instancing: bool,
196 pub reject_software_rasterizer: bool,
199 pub low_quality_pinch_zoom: bool,
205 pub max_shared_surface_size: i32,
206 pub enable_debugger: bool,
209}
210
211impl WebRenderOptions {
212 const BATCH_LOOKBACK_COUNT: usize = 10;
215
216 const MAX_INSTANCE_BUFFER_SIZE: usize = 0x20000; }
224
225impl Default for WebRenderOptions {
226 fn default() -> Self {
227 WebRenderOptions {
228 resource_override_path: None,
229 use_optimized_shaders: false,
230 enable_aa: true,
231 enable_dithering: false,
232 debug_flags: DebugFlags::empty(),
233 max_recorded_profiles: 0,
234 precache_flags: ShaderPrecacheFlags::empty(),
235 enable_subpixel_aa: false,
236 clear_color: ColorF::new(1.0, 1.0, 1.0, 1.0),
237 enable_clear_scissor: None,
238 max_internal_texture_size: None,
239 image_tiling_threshold: 4096,
240 upload_method: UploadMethod::PixelBuffer(ONE_TIME_USAGE_HINT),
243 upload_pbo_default_size: 512 * 512 * 4,
244 batched_upload_threshold: 512 * 512,
245 workers: None,
246 chunk_pool: None,
247 dedicated_glyph_raster_thread: None,
248 enable_multithreading: true,
249 blob_image_handler: None,
250 crash_annotator: None,
251 size_of_op: None,
252 enclosing_size_of_op: None,
253 renderer_id: None,
254 cached_programs: None,
255 scene_builder_hooks: None,
256 render_backend_hooks: None,
257 sampler: None,
258 support_low_priority_transactions: false,
259 namespace_alloc_by_client: false,
260 shared_font_namespace: None,
261 testing: false,
262 gpu_supports_fast_clears: false,
263 allow_dual_source_blending: true,
264 allow_advanced_blend_equation: false,
265 allow_texture_storage_support: true,
266 allow_texture_swizzling: true,
267 clear_caches_with_quads: true,
268 dump_shader_source: None,
269 surface_origin_is_top_left: false,
270 compositor_config: CompositorConfig::default(),
271 enable_gpu_markers: true,
272 panic_on_gl_error: false,
273 picture_tile_size: None,
274 texture_cache_config: TextureCacheConfig::DEFAULT,
275 enable_instancing: true,
278 reject_software_rasterizer: false,
279 low_quality_pinch_zoom: false,
280 max_shared_surface_size: 2048,
281 enable_debugger: true,
282 }
283 }
284}
285
286pub fn create_webrender_instance(
304 gl: Rc<dyn gl::Gl>,
305 notifier: Box<dyn RenderNotifier>,
306 mut options: WebRenderOptions,
307 shaders: Option<&SharedShaders>,
308) -> Result<(Renderer, RenderApiSender), RendererError> {
309 if !wr_has_been_initialized() {
310 #[cfg(feature = "profiler")]
313 unsafe {
314 if let Ok(ref tracy_path) = std::env::var("WR_TRACY_PATH") {
315 let ok = tracy_rs::load(tracy_path);
316 info!("Load tracy from {} -> {}", tracy_path, ok);
317 }
318 }
319
320 register_thread_with_profiler("Compositor".to_owned());
321 }
322
323 HAS_BEEN_INITIALIZED.store(true, Ordering::SeqCst);
324
325 match options.compositor_config {
328 CompositorConfig::Draw { .. } | CompositorConfig::Native { .. } => {}
329 CompositorConfig::Layer { .. } => {
330 options.surface_origin_is_top_left = true;
331 }
332 }
333
334 let (api_tx, api_rx) = unbounded_channel();
335 let (result_tx, result_rx) = unbounded_channel();
336 let gl_type = gl.get_type();
337
338 let mut device = Device::new(
339 gl,
340 options.crash_annotator.clone(),
341 options.resource_override_path.clone(),
342 options.use_optimized_shaders,
343 options.upload_method.clone(),
344 options.batched_upload_threshold,
345 options.cached_programs.take(),
346 options.allow_texture_storage_support,
347 options.allow_texture_swizzling,
348 options.dump_shader_source.take(),
349 options.surface_origin_is_top_left,
350 options.panic_on_gl_error,
351 );
352
353 let color_cache_formats = device.preferred_color_formats();
354 let swizzle_settings = device.swizzle_settings();
355 let use_dual_source_blending =
356 device.get_capabilities().supports_dual_source_blending &&
357 options.allow_dual_source_blending;
358 let ext_blend_equation_advanced =
359 options.allow_advanced_blend_equation &&
360 device.get_capabilities().supports_advanced_blend_equation;
361 let ext_blend_equation_advanced_coherent =
362 device.supports_extension("GL_KHR_blend_equation_advanced_coherent");
363
364 let enable_clear_scissor = options
365 .enable_clear_scissor
366 .unwrap_or(device.get_capabilities().prefers_clear_scissor);
367
368 const MIN_TEXTURE_SIZE: i32 = 2048;
370 let mut max_internal_texture_size = device.max_texture_size();
371 if max_internal_texture_size < MIN_TEXTURE_SIZE {
372 error!(
375 "Device reporting insufficient max texture size ({})",
376 max_internal_texture_size
377 );
378 return Err(RendererError::MaxTextureSize);
379 }
380 if let Some(internal_limit) = options.max_internal_texture_size {
381 assert!(internal_limit >= MIN_TEXTURE_SIZE);
382 max_internal_texture_size = max_internal_texture_size.min(internal_limit);
383 }
384
385 if options.reject_software_rasterizer {
386 let renderer_name_lc = device.get_capabilities().renderer_name.to_lowercase();
387 if renderer_name_lc.contains("llvmpipe") || renderer_name_lc.contains("softpipe") || renderer_name_lc.contains("software rasterizer") {
388 return Err(RendererError::SoftwareRasterizer);
389 }
390 }
391
392 let image_tiling_threshold = options.image_tiling_threshold
393 .min(max_internal_texture_size);
394
395 device.begin_frame();
396
397 let shaders = match shaders {
398 Some(shaders) => Rc::clone(shaders),
399 None => {
400 let mut shaders = Shaders::new(&mut device, gl_type, &options)?;
401 if options.precache_flags.intersects(ShaderPrecacheFlags::ASYNC_COMPILE | ShaderPrecacheFlags::FULL_COMPILE) {
402 let mut pending_shaders = shaders.precache_all(options.precache_flags);
403 while shaders.resume_precache(&mut device, &mut pending_shaders)? {}
404 }
405 Rc::new(RefCell::new(shaders))
406 }
407 };
408
409 let dither_matrix_texture = if options.enable_dithering {
410 let dither_matrix: [u8; 64] = [
411 0,
412 48,
413 12,
414 60,
415 3,
416 51,
417 15,
418 63,
419 32,
420 16,
421 44,
422 28,
423 35,
424 19,
425 47,
426 31,
427 8,
428 56,
429 4,
430 52,
431 11,
432 59,
433 7,
434 55,
435 40,
436 24,
437 36,
438 20,
439 43,
440 27,
441 39,
442 23,
443 2,
444 50,
445 14,
446 62,
447 1,
448 49,
449 13,
450 61,
451 34,
452 18,
453 46,
454 30,
455 33,
456 17,
457 45,
458 29,
459 10,
460 58,
461 6,
462 54,
463 9,
464 57,
465 5,
466 53,
467 42,
468 26,
469 38,
470 22,
471 41,
472 25,
473 37,
474 21,
475 ];
476
477 let texture = device.create_texture(
478 ImageBufferKind::Texture2D,
479 ImageFormat::R8,
480 8,
481 8,
482 TextureFilter::Nearest,
483 None,
484 );
485 device.upload_texture_immediate(&texture, &dither_matrix);
486
487 Some(texture)
488 } else {
489 None
490 };
491
492 let max_primitive_instance_count =
493 WebRenderOptions::MAX_INSTANCE_BUFFER_SIZE / mem::size_of::<PrimitiveInstanceData>();
494 let vaos = vertex::RendererVAOs::new(
495 &mut device,
496 if options.enable_instancing { None } else { NonZeroUsize::new(max_primitive_instance_count) },
497 );
498
499 let texture_upload_pbo_pool = UploadPBOPool::new(&mut device, options.upload_pbo_default_size);
500 let staging_texture_pool = UploadTexturePool::new();
501 let texture_resolver = TextureResolver::new(&mut device);
502
503 let mut vertex_data_textures = Vec::new();
504 for _ in 0 .. VERTEX_DATA_TEXTURE_COUNT {
505 vertex_data_textures.push(vertex::VertexDataTextures::new());
506 }
507
508 let is_software = device.get_capabilities().renderer_name.starts_with("Software");
509
510 device.end_frame();
511
512 let backend_notifier = notifier.clone();
513
514 let clear_alpha_targets_with_quads = !device.get_capabilities().supports_alpha_target_clears;
515
516 let prefer_subpixel_aa = options.enable_subpixel_aa && use_dual_source_blending;
517 let default_font_render_mode = match (options.enable_aa, prefer_subpixel_aa) {
518 (true, true) => FontRenderMode::Subpixel,
519 (true, false) => FontRenderMode::Alpha,
520 (false, _) => FontRenderMode::Mono,
521 };
522
523 let compositor_kind = match options.compositor_config {
524 CompositorConfig::Draw { max_partial_present_rects, draw_previous_partial_present_regions, .. } => {
525 CompositorKind::Draw { max_partial_present_rects, draw_previous_partial_present_regions }
526 }
527 CompositorConfig::Native { ref compositor } => {
528 let capabilities = compositor.get_capabilities(&mut device);
529
530 CompositorKind::Native {
531 capabilities,
532 }
533 }
534 CompositorConfig::Layer { .. } => {
535 CompositorKind::Layer {
536 }
537 }
538 };
539
540 let config = FrameBuilderConfig {
541 default_font_render_mode,
542 dual_source_blending_is_supported: use_dual_source_blending,
543 testing: options.testing,
544 gpu_supports_fast_clears: options.gpu_supports_fast_clears,
545 gpu_supports_advanced_blend: ext_blend_equation_advanced,
546 advanced_blend_is_coherent: ext_blend_equation_advanced_coherent,
547 gpu_supports_render_target_partial_update: device.get_capabilities().supports_render_target_partial_update,
548 external_images_require_copy: !device.get_capabilities().supports_image_external_essl3,
549 batch_lookback_count: WebRenderOptions::BATCH_LOOKBACK_COUNT,
550 background_color: Some(options.clear_color),
551 compositor_kind,
552 tile_size_override: None,
553 max_surface_override: None,
554 max_depth_ids: device.max_depth_ids(),
555 max_target_size: max_internal_texture_size,
556 force_invalidation: false,
557 is_software,
558 low_quality_pinch_zoom: options.low_quality_pinch_zoom,
559 max_shared_surface_size: options.max_shared_surface_size,
560 enable_dithering: options.enable_dithering,
561 };
562 info!("WR {:?}", config);
563
564 let debug_flags = options.debug_flags;
565 let size_of_op = options.size_of_op;
566 let enclosing_size_of_op = options.enclosing_size_of_op;
567 let make_size_of_ops =
568 move || size_of_op.map(|o| MallocSizeOfOps::new(o, enclosing_size_of_op));
569 let workers = options
570 .workers
571 .take()
572 .unwrap_or_else(|| {
573 let worker = ThreadPoolBuilder::new()
574 .thread_name(|idx|{ format!("WRWorker#{}", idx) })
575 .start_handler(move |idx| {
576 register_thread_with_profiler(format!("WRWorker#{}", idx));
577 profiler::register_thread(&format!("WRWorker#{}", idx));
578 })
579 .exit_handler(move |_idx| {
580 profiler::unregister_thread();
581 })
582 .build();
583 Arc::new(worker.unwrap())
584 });
585 let sampler = options.sampler;
586 let namespace_alloc_by_client = options.namespace_alloc_by_client;
587
588 let font_namespace = if namespace_alloc_by_client {
591 options.shared_font_namespace.expect("Shared font namespace must be allocated by client")
592 } else {
593 RenderBackend::next_namespace_id()
594 };
595 let fonts = SharedFontResources::new(font_namespace);
596
597 let blob_image_handler = options.blob_image_handler.take();
598 let scene_builder_hooks = options.scene_builder_hooks;
599 let rb_thread_name = format!("WRRenderBackend#{}", options.renderer_id.unwrap_or(0));
600 let scene_thread_name = format!("WRSceneBuilder#{}", options.renderer_id.unwrap_or(0));
601 let lp_scene_thread_name = format!("WRSceneBuilderLP#{}", options.renderer_id.unwrap_or(0));
602
603 let glyph_rasterizer = GlyphRasterizer::new(
604 workers,
605 options.dedicated_glyph_raster_thread,
606 device.get_capabilities().supports_r8_texture_upload,
607 );
608
609 let (scene_builder_channels, scene_tx) =
610 SceneBuilderThreadChannels::new(api_tx.clone());
611
612 let sb_fonts = fonts.clone();
613
614 thread::Builder::new().name(scene_thread_name.clone()).spawn(move || {
615 register_thread_with_profiler(scene_thread_name.clone());
616 profiler::register_thread(&scene_thread_name);
617
618 let mut scene_builder = SceneBuilderThread::new(
619 config,
620 sb_fonts,
621 make_size_of_ops(),
622 scene_builder_hooks,
623 scene_builder_channels,
624 );
625 scene_builder.run();
626
627 profiler::unregister_thread();
628 })?;
629
630 let low_priority_scene_tx = if options.support_low_priority_transactions {
631 let (low_priority_scene_tx, low_priority_scene_rx) = unbounded_channel();
632 let lp_builder = LowPrioritySceneBuilderThread {
633 rx: low_priority_scene_rx,
634 tx: scene_tx.clone(),
635 tile_pool: api::BlobTilePool::new(),
636 };
637
638 thread::Builder::new().name(lp_scene_thread_name.clone()).spawn(move || {
639 register_thread_with_profiler(lp_scene_thread_name.clone());
640 profiler::register_thread(&lp_scene_thread_name);
641
642 let mut scene_builder = lp_builder;
643 scene_builder.run();
644
645 profiler::unregister_thread();
646 })?;
647
648 low_priority_scene_tx
649 } else {
650 scene_tx.clone()
651 };
652
653 let rb_blob_handler = blob_image_handler
654 .as_ref()
655 .map(|handler| handler.create_similar());
656
657 let texture_cache_config = options.texture_cache_config.clone();
658 let mut picture_tile_size = options.picture_tile_size.unwrap_or(crate::tile_cache::TILE_SIZE_DEFAULT);
659 picture_tile_size.width = picture_tile_size.width.max(128).min(4096);
661 picture_tile_size.height = picture_tile_size.height.max(128).min(4096);
662
663 let picture_texture_filter = if options.low_quality_pinch_zoom {
664 TextureFilter::Linear
665 } else {
666 TextureFilter::Nearest
667 };
668
669 let render_backend_hooks = options.render_backend_hooks.take();
670
671 let chunk_pool = options.chunk_pool.take().unwrap_or_else(|| {
672 Arc::new(ChunkPool::new())
673 });
674
675 let rb_scene_tx = scene_tx.clone();
676 let rb_fonts = fonts.clone();
677 let enable_multithreading = options.enable_multithreading;
678 thread::Builder::new().name(rb_thread_name.clone()).spawn(move || {
679 if let Some(hooks) = render_backend_hooks {
680 hooks.init_thread();
681 }
682 register_thread_with_profiler(rb_thread_name.clone());
683 profiler::register_thread(&rb_thread_name);
684
685 let texture_cache = TextureCache::new(
686 max_internal_texture_size,
687 image_tiling_threshold,
688 color_cache_formats,
689 swizzle_settings,
690 &texture_cache_config,
691 );
692
693 let picture_textures = PictureTextures::new(
694 picture_tile_size,
695 picture_texture_filter,
696 );
697
698 let glyph_cache = GlyphCache::new();
699
700 let mut resource_cache = ResourceCache::new(
701 texture_cache,
702 picture_textures,
703 glyph_rasterizer,
704 glyph_cache,
705 rb_fonts,
706 rb_blob_handler,
707 );
708
709 resource_cache.enable_multithreading(enable_multithreading);
710
711 let mut backend = RenderBackend::new(
712 api_rx,
713 result_tx,
714 rb_scene_tx,
715 resource_cache,
716 chunk_pool,
717 backend_notifier,
718 config,
719 sampler,
720 make_size_of_ops(),
721 debug_flags,
722 namespace_alloc_by_client,
723 );
724 backend.run();
725 profiler::unregister_thread();
726 })?;
727
728 let debug_method = if !options.enable_gpu_markers {
729 GpuDebugMethod::None
731 } else if device.get_capabilities().supports_khr_debug {
732 GpuDebugMethod::KHR
733 } else if device.supports_extension("GL_EXT_debug_marker") {
734 GpuDebugMethod::MarkerEXT
735 } else {
736 warn!("asking to enable_gpu_markers but no supporting extension was found");
737 GpuDebugMethod::None
738 };
739
740 info!("using {:?}", debug_method);
741
742 let gpu_profiler = GpuProfiler::new(Rc::clone(device.rc_gl()), debug_method);
743 #[cfg(feature = "capture")]
744 let read_fbo = device.create_fbo();
745
746 let mut renderer = Renderer {
747 result_rx,
748 api_tx: api_tx.clone(),
749 device,
750 active_documents: FastHashMap::default(),
751 pending_texture_updates: Vec::new(),
752 pending_texture_cache_updates: false,
753 pending_native_surface_updates: Vec::new(),
754 pending_shader_updates: Vec::new(),
755 shaders,
756 debug: debug::LazyInitializedDebugRenderer::new(),
757 debug_flags: DebugFlags::empty(),
758 profile: TransactionProfile::new(),
759 frame_counter: 0,
760 resource_upload_time: 0.0,
761 profiler: Profiler::new(),
762 max_recorded_profiles: options.max_recorded_profiles,
763 clear_color: options.clear_color,
764 enable_clear_scissor,
765 enable_advanced_blend_barriers: !ext_blend_equation_advanced_coherent,
766 clear_caches_with_quads: options.clear_caches_with_quads,
767 clear_alpha_targets_with_quads,
768 last_time: 0,
769 gpu_profiler,
770 vaos,
771 gpu_buffer_texture_f: None,
772 gpu_buffer_texture_f_too_large: 0,
773 gpu_buffer_texture_i: None,
774 gpu_buffer_texture_i_too_large: 0,
775 vertex_data_textures,
776 current_vertex_data_textures: 0,
777 pipeline_info: PipelineInfo::default(),
778 dither_matrix_texture,
779 external_image_handler: None,
780 size_of_ops: make_size_of_ops(),
781 cpu_profiles: VecDeque::new(),
782 gpu_profiles: VecDeque::new(),
783 texture_upload_pbo_pool,
784 staging_texture_pool,
785 texture_resolver,
786 renderer_errors: Vec::new(),
787 async_frame_recorder: None,
788 async_screenshots: None,
789 #[cfg(feature = "capture")]
790 read_fbo,
791 #[cfg(feature = "replay")]
792 owned_external_images: FastHashMap::default(),
793 notifications: Vec::new(),
794 device_size: None,
795 zoom_debug_texture: None,
796 cursor_position: DeviceIntPoint::zero(),
797 shared_texture_cache_cleared: false,
798 documents_seen: FastHashSet::default(),
799 force_redraw: true,
800 compositor_config: options.compositor_config,
801 current_compositor_kind: compositor_kind,
802 allocated_native_surfaces: FastHashSet::default(),
803 debug_overlay_state: DebugOverlayState::new(),
804 buffer_damage_tracker: BufferDamageTracker::default(),
805 max_primitive_instance_count,
806 enable_instancing: options.enable_instancing,
807 consecutive_oom_frames: 0,
808 target_frame_publish_id: None,
809 pending_result_msg: None,
810 layer_compositor_frame_state_in_prev_frame: None,
811 external_composite_debug_items: Vec::new(),
812 command_log: None,
813 #[cfg(feature = "debugger")]
814 debugger: Debugger::new(),
815 };
816
817 renderer.set_debug_flags(debug_flags);
820 renderer.profiler.set_ui("Default");
821
822 let sender = RenderApiSender::new(
823 api_tx,
824 scene_tx,
825 low_priority_scene_tx,
826 blob_image_handler,
827 fonts,
828 );
829
830 #[cfg(feature = "debugger")]
831 if options.enable_debugger {
832 let api = if namespace_alloc_by_client {
833 sender.create_api_by_client(IdNamespace::DEBUGGER)
834 } else {
835 sender.create_api()
836 };
837 crate::debugger::start(api);
838 }
839
840 Ok((renderer, sender))
841}