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