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