1use api::{ClipMode, ColorF, ColorU, MixBlendMode};
38use api::{DocumentId, Epoch, ExternalImageHandler, RenderReasons};
39#[cfg(feature = "replay")]
40use api::ExternalImageId;
41use api::{ExternalImageSource, ExternalImageType, ImageFormat, PremultipliedColorF};
42use api::{PipelineId, ImageRendering, Checkpoint, NotificationRequest, ImageBufferKind};
43#[cfg(feature = "replay")]
44use api::ExternalImage;
45use api::FramePublishId;
46use api::units::*;
47use api::channel::{Sender, Receiver};
48pub use api::DebugFlags;
49use core::time::Duration;
50
51use crate::pattern::PatternKind;
52use crate::render_api::{DebugCommand, ApiMsg, MemoryReport};
53use crate::batch::{AlphaBatchContainer, BatchKind, BatchFeatures, BatchTextures, BrushBatchKind, ClipBatchList};
54use crate::batch::ClipMaskInstanceList;
55#[cfg(any(feature = "capture", feature = "replay"))]
56use crate::capture::{CaptureConfig, ExternalCaptureImage, PlainExternalImage};
57use crate::composite::{CompositeState, CompositeTileSurface, CompositorInputLayer, CompositorSurfaceTransform, ResolvedExternalSurface};
58use crate::composite::{CompositorKind, Compositor, NativeTileId, CompositeFeatures, CompositeSurfaceFormat, ResolvedExternalSurfaceColorData};
59use crate::composite::{CompositorConfig, NativeSurfaceOperationDetails, NativeSurfaceId, NativeSurfaceOperation, ClipRadius};
60use crate::composite::TileKind;
61#[cfg(feature = "debugger")]
62use api::debugger::CompositorDebugInfo;
63use crate::segment::SegmentBuilder;
64use crate::{debug_colors, CompositorInputConfig, CompositorSurfaceUsage};
65use crate::device::{DepthFunction, Device, DrawTarget, ExternalTexture, GpuFrameId, UploadPBOPool};
66use crate::device::{ReadTarget, ShaderError, Texture, TextureFilter, TextureFlags, TextureSlot, Texel};
67use crate::device::query::{GpuSampler, GpuTimer};
68#[cfg(feature = "capture")]
69use crate::device::FBOId;
70use crate::debug_item::DebugItem;
71use crate::frame_builder::Frame;
72use glyph_rasterizer::GlyphFormat;
73use crate::gpu_cache::{GpuCacheUpdate, GpuCacheUpdateList};
74use crate::gpu_cache::{GpuCacheDebugChunk, GpuCacheDebugCmd};
75use crate::gpu_types::{ScalingInstance, SvgFilterInstance, SVGFEFilterInstance, CopyInstance, PrimitiveInstanceData};
76use crate::gpu_types::{BlurInstance, ClearInstance, CompositeInstance, ZBufferId};
77use crate::internal_types::{TextureSource, TextureSourceExternal, TextureCacheCategory, FrameId, FrameVec};
78#[cfg(any(feature = "capture", feature = "replay"))]
79use crate::internal_types::DebugOutput;
80use crate::internal_types::{CacheTextureId, FastHashMap, FastHashSet, RenderedDocument, ResultMsg};
81use crate::internal_types::{TextureCacheAllocInfo, TextureCacheAllocationKind, TextureUpdateList};
82use crate::internal_types::{RenderTargetInfo, Swizzle, DeferredResolveIndex};
83use crate::picture::{ResolvedSurfaceTexture, TileId};
84use crate::prim_store::DeferredResolve;
85use crate::profiler::{self, GpuProfileTag, TransactionProfile};
86use crate::profiler::{Profiler, add_event_marker, add_text_marker, thread_is_being_profiled};
87use crate::device::query::GpuProfiler;
88use crate::render_target::ResolveOp;
89use crate::render_task_graph::RenderTaskGraph;
90use crate::render_task::{RenderTask, RenderTaskKind, ReadbackTask};
91use crate::screen_capture::AsyncScreenshotGrabber;
92use crate::render_target::{RenderTarget, PictureCacheTarget, PictureCacheTargetKind};
93use crate::render_target::{RenderTargetKind, BlitJob};
94use crate::telemetry::Telemetry;
95use crate::tile_cache::PictureCacheDebugInfo;
96use crate::util::drain_filter;
97use crate::rectangle_occlusion as occlusion;
98#[cfg(feature = "debugger")]
99use crate::debugger::{Debugger, DebugQueryKind};
100use upload::{upload_to_texture_cache, UploadTexturePool};
101use init::*;
102
103use euclid::{rect, Transform3D, Scale, default};
104use gleam::gl;
105use malloc_size_of::MallocSizeOfOps;
106
107#[cfg(feature = "replay")]
108use std::sync::Arc;
109
110use std::{
111    cell::RefCell,
112    collections::VecDeque,
113    f32,
114    ffi::c_void,
115    mem,
116    num::NonZeroUsize,
117    path::PathBuf,
118    rc::Rc,
119};
120#[cfg(any(feature = "capture", feature = "replay"))]
121use std::collections::hash_map::Entry;
122
123mod debug;
124mod gpu_buffer;
125mod gpu_cache;
126mod shade;
127mod vertex;
128mod upload;
129pub(crate) mod init;
130
131pub use debug::DebugRenderer;
132pub use shade::{PendingShadersToPrecache, Shaders, SharedShaders};
133pub use vertex::{desc, VertexArrayKind, MAX_VERTEX_TEXTURE_WIDTH};
134pub use gpu_buffer::{GpuBuffer, GpuBufferF, GpuBufferBuilderF, GpuBufferI, GpuBufferBuilderI};
135pub use gpu_buffer::{GpuBufferAddress, GpuBufferBuilder, GpuBufferWriterF};
136
137pub const VERTEX_DATA_TEXTURE_COUNT: usize = 3;
148
149pub const BLOCKS_PER_UV_RECT: usize = 2;
151
152const GPU_TAG_BRUSH_OPACITY: GpuProfileTag = GpuProfileTag {
153    label: "B_Opacity",
154    color: debug_colors::DARKMAGENTA,
155};
156const GPU_TAG_BRUSH_LINEAR_GRADIENT: GpuProfileTag = GpuProfileTag {
157    label: "B_LinearGradient",
158    color: debug_colors::POWDERBLUE,
159};
160const GPU_TAG_BRUSH_YUV_IMAGE: GpuProfileTag = GpuProfileTag {
161    label: "B_YuvImage",
162    color: debug_colors::DARKGREEN,
163};
164const GPU_TAG_BRUSH_MIXBLEND: GpuProfileTag = GpuProfileTag {
165    label: "B_MixBlend",
166    color: debug_colors::MAGENTA,
167};
168const GPU_TAG_BRUSH_BLEND: GpuProfileTag = GpuProfileTag {
169    label: "B_Blend",
170    color: debug_colors::ORANGE,
171};
172const GPU_TAG_BRUSH_IMAGE: GpuProfileTag = GpuProfileTag {
173    label: "B_Image",
174    color: debug_colors::SPRINGGREEN,
175};
176const GPU_TAG_BRUSH_SOLID: GpuProfileTag = GpuProfileTag {
177    label: "B_Solid",
178    color: debug_colors::RED,
179};
180const GPU_TAG_CACHE_CLIP: GpuProfileTag = GpuProfileTag {
181    label: "C_Clip",
182    color: debug_colors::PURPLE,
183};
184const GPU_TAG_CACHE_BORDER: GpuProfileTag = GpuProfileTag {
185    label: "C_Border",
186    color: debug_colors::CORNSILK,
187};
188const GPU_TAG_CACHE_LINE_DECORATION: GpuProfileTag = GpuProfileTag {
189    label: "C_LineDecoration",
190    color: debug_colors::YELLOWGREEN,
191};
192const GPU_TAG_CACHE_FAST_LINEAR_GRADIENT: GpuProfileTag = GpuProfileTag {
193    label: "C_FastLinearGradient",
194    color: debug_colors::BROWN,
195};
196const GPU_TAG_CACHE_LINEAR_GRADIENT: GpuProfileTag = GpuProfileTag {
197    label: "C_LinearGradient",
198    color: debug_colors::BROWN,
199};
200const GPU_TAG_GRADIENT: GpuProfileTag = GpuProfileTag {
201    label: "C_Gradient",
202    color: debug_colors::BROWN,
203};
204const GPU_TAG_RADIAL_GRADIENT: GpuProfileTag = GpuProfileTag {
205    label: "C_RadialGradient",
206    color: debug_colors::BROWN,
207};
208const GPU_TAG_CONIC_GRADIENT: GpuProfileTag = GpuProfileTag {
209    label: "C_ConicGradient",
210    color: debug_colors::BROWN,
211};
212const GPU_TAG_SETUP_TARGET: GpuProfileTag = GpuProfileTag {
213    label: "target init",
214    color: debug_colors::SLATEGREY,
215};
216const GPU_TAG_SETUP_DATA: GpuProfileTag = GpuProfileTag {
217    label: "data init",
218    color: debug_colors::LIGHTGREY,
219};
220const GPU_TAG_PRIM_SPLIT_COMPOSITE: GpuProfileTag = GpuProfileTag {
221    label: "SplitComposite",
222    color: debug_colors::DARKBLUE,
223};
224const GPU_TAG_PRIM_TEXT_RUN: GpuProfileTag = GpuProfileTag {
225    label: "TextRun",
226    color: debug_colors::BLUE,
227};
228const GPU_TAG_PRIMITIVE: GpuProfileTag = GpuProfileTag {
229    label: "Primitive",
230    color: debug_colors::RED,
231};
232const GPU_TAG_INDIRECT_PRIM: GpuProfileTag = GpuProfileTag {
233    label: "Primitive (indirect)",
234    color: debug_colors::YELLOWGREEN,
235};
236const GPU_TAG_INDIRECT_MASK: GpuProfileTag = GpuProfileTag {
237    label: "Mask (indirect)",
238    color: debug_colors::IVORY,
239};
240const GPU_TAG_BLUR: GpuProfileTag = GpuProfileTag {
241    label: "Blur",
242    color: debug_colors::VIOLET,
243};
244const GPU_TAG_BLIT: GpuProfileTag = GpuProfileTag {
245    label: "Blit",
246    color: debug_colors::LIME,
247};
248const GPU_TAG_SCALE: GpuProfileTag = GpuProfileTag {
249    label: "Scale",
250    color: debug_colors::GHOSTWHITE,
251};
252const GPU_SAMPLER_TAG_ALPHA: GpuProfileTag = GpuProfileTag {
253    label: "Alpha targets",
254    color: debug_colors::BLACK,
255};
256const GPU_SAMPLER_TAG_OPAQUE: GpuProfileTag = GpuProfileTag {
257    label: "Opaque pass",
258    color: debug_colors::BLACK,
259};
260const GPU_SAMPLER_TAG_TRANSPARENT: GpuProfileTag = GpuProfileTag {
261    label: "Transparent pass",
262    color: debug_colors::BLACK,
263};
264const GPU_TAG_SVG_FILTER: GpuProfileTag = GpuProfileTag {
265    label: "SvgFilter",
266    color: debug_colors::LEMONCHIFFON,
267};
268const GPU_TAG_SVG_FILTER_NODES: GpuProfileTag = GpuProfileTag {
269    label: "SvgFilterNodes",
270    color: debug_colors::LEMONCHIFFON,
271};
272const GPU_TAG_COMPOSITE: GpuProfileTag = GpuProfileTag {
273    label: "Composite",
274    color: debug_colors::TOMATO,
275};
276
277#[derive(Debug, Copy, Clone)]
282struct OcclusionItemKey {
283    tile_index: usize,
284    needs_mask: bool,
285}
286
287struct SwapChainLayer {
290    occlusion: occlusion::FrontToBackBuilder<OcclusionItemKey>,
291    clear_tiles: Vec<occlusion::Item<OcclusionItemKey>>,
292}
293
294struct CompositeTileState {
296    pub local_rect: PictureRect,
297    pub local_valid_rect: PictureRect,
298    pub device_clip_rect: DeviceRect,
299    pub z_id: ZBufferId,
300    pub device_tile_box: DeviceRect,
301    pub visible_rects: Vec<DeviceRect>,
302}
303
304impl CompositeTileState {
305    pub fn same_state(&self, other: &CompositeTileState) -> bool {
306        self.local_rect == other.local_rect &&
307        self.local_valid_rect == other.local_valid_rect &&
308        self.device_clip_rect == other.device_clip_rect &&
309        self.z_id == other.z_id &&
310        self.device_tile_box == other.device_tile_box
311    }
312}
313
314struct LayerCompositorFrameState {
316    tile_states: FastHashMap<TileId, CompositeTileState>,
317    pub rects_without_id: Vec<DeviceRect>,
318}
319
320pub const TEXTURE_CACHE_DBG_CLEAR_COLOR: [f32; 4] = [0.0, 0.0, 0.8, 1.0];
324
325impl BatchKind {
326    fn sampler_tag(&self) -> GpuProfileTag {
327        match *self {
328            BatchKind::SplitComposite => GPU_TAG_PRIM_SPLIT_COMPOSITE,
329            BatchKind::Brush(kind) => {
330                match kind {
331                    BrushBatchKind::Solid => GPU_TAG_BRUSH_SOLID,
332                    BrushBatchKind::Image(..) => GPU_TAG_BRUSH_IMAGE,
333                    BrushBatchKind::Blend => GPU_TAG_BRUSH_BLEND,
334                    BrushBatchKind::MixBlend { .. } => GPU_TAG_BRUSH_MIXBLEND,
335                    BrushBatchKind::YuvImage(..) => GPU_TAG_BRUSH_YUV_IMAGE,
336                    BrushBatchKind::LinearGradient => GPU_TAG_BRUSH_LINEAR_GRADIENT,
337                    BrushBatchKind::Opacity => GPU_TAG_BRUSH_OPACITY,
338                }
339            }
340            BatchKind::TextRun(_) => GPU_TAG_PRIM_TEXT_RUN,
341            BatchKind::Quad(PatternKind::ColorOrTexture) => GPU_TAG_PRIMITIVE,
342            BatchKind::Quad(PatternKind::Gradient) => GPU_TAG_GRADIENT,
343            BatchKind::Quad(PatternKind::RadialGradient) => GPU_TAG_RADIAL_GRADIENT,
344            BatchKind::Quad(PatternKind::ConicGradient) => GPU_TAG_CONIC_GRADIENT,
345            BatchKind::Quad(PatternKind::Mask) => GPU_TAG_INDIRECT_MASK,
346        }
347    }
348}
349
350fn flag_changed(before: DebugFlags, after: DebugFlags, select: DebugFlags) -> Option<bool> {
351    if before & select != after & select {
352        Some(after.contains(select))
353    } else {
354        None
355    }
356}
357
358#[repr(C)]
359#[derive(Copy, Clone, Debug)]
360pub enum ShaderColorMode {
361    Alpha = 0,
362    SubpixelDualSource = 1,
363    BitmapShadow = 2,
364    ColorBitmap = 3,
365    Image = 4,
366    MultiplyDualSource = 5,
367}
368
369impl From<GlyphFormat> for ShaderColorMode {
370    fn from(format: GlyphFormat) -> ShaderColorMode {
371        match format {
372            GlyphFormat::Alpha |
373            GlyphFormat::TransformedAlpha |
374            GlyphFormat::Bitmap => ShaderColorMode::Alpha,
375            GlyphFormat::Subpixel | GlyphFormat::TransformedSubpixel => {
376                panic!("Subpixel glyph formats must be handled separately.");
377            }
378            GlyphFormat::ColorBitmap => ShaderColorMode::ColorBitmap,
379        }
380    }
381}
382
383#[derive(Debug, Copy, Clone, PartialEq, Eq)]
389pub(crate) enum TextureSampler {
390    Color0,
391    Color1,
392    Color2,
393    GpuCache,
394    TransformPalette,
395    RenderTasks,
396    Dither,
397    PrimitiveHeadersF,
398    PrimitiveHeadersI,
399    ClipMask,
400    GpuBufferF,
401    GpuBufferI,
402}
403
404impl TextureSampler {
405    pub(crate) fn color(n: usize) -> TextureSampler {
406        match n {
407            0 => TextureSampler::Color0,
408            1 => TextureSampler::Color1,
409            2 => TextureSampler::Color2,
410            _ => {
411                panic!("There are only 3 color samplers.");
412            }
413        }
414    }
415}
416
417impl Into<TextureSlot> for TextureSampler {
418    fn into(self) -> TextureSlot {
419        match self {
420            TextureSampler::Color0 => TextureSlot(0),
421            TextureSampler::Color1 => TextureSlot(1),
422            TextureSampler::Color2 => TextureSlot(2),
423            TextureSampler::GpuCache => TextureSlot(3),
424            TextureSampler::TransformPalette => TextureSlot(4),
425            TextureSampler::RenderTasks => TextureSlot(5),
426            TextureSampler::Dither => TextureSlot(6),
427            TextureSampler::PrimitiveHeadersF => TextureSlot(7),
428            TextureSampler::PrimitiveHeadersI => TextureSlot(8),
429            TextureSampler::ClipMask => TextureSlot(9),
430            TextureSampler::GpuBufferF => TextureSlot(10),
431            TextureSampler::GpuBufferI => TextureSlot(11),
432        }
433    }
434}
435
436#[derive(Clone, Debug, PartialEq)]
437pub enum GraphicsApi {
438    OpenGL,
439}
440
441#[derive(Clone, Debug)]
442pub struct GraphicsApiInfo {
443    pub kind: GraphicsApi,
444    pub renderer: String,
445    pub version: String,
446}
447
448#[derive(Debug)]
449pub struct GpuProfile {
450    pub frame_id: GpuFrameId,
451    pub paint_time_ns: u64,
452}
453
454impl GpuProfile {
455    fn new(frame_id: GpuFrameId, timers: &[GpuTimer]) -> GpuProfile {
456        let mut paint_time_ns = 0;
457        for timer in timers {
458            paint_time_ns += timer.time_ns;
459        }
460        GpuProfile {
461            frame_id,
462            paint_time_ns,
463        }
464    }
465}
466
467#[derive(Debug)]
468pub struct CpuProfile {
469    pub frame_id: GpuFrameId,
470    pub backend_time_ns: u64,
471    pub composite_time_ns: u64,
472    pub draw_calls: usize,
473}
474
475impl CpuProfile {
476    fn new(
477        frame_id: GpuFrameId,
478        backend_time_ns: u64,
479        composite_time_ns: u64,
480        draw_calls: usize,
481    ) -> CpuProfile {
482        CpuProfile {
483            frame_id,
484            backend_time_ns,
485            composite_time_ns,
486            draw_calls,
487        }
488    }
489}
490
491#[derive(Debug, Copy, Clone)]
493enum PartialPresentMode {
494    Single {
498        dirty_rect: DeviceRect,
499    },
500}
501
502struct CacheTexture {
503    texture: Texture,
504    category: TextureCacheCategory,
505}
506
507struct TextureResolver {
513    texture_cache_map: FastHashMap<CacheTextureId, CacheTexture>,
515
516    external_images: FastHashMap<DeferredResolveIndex, ExternalTexture>,
518
519    dummy_cache_texture: Texture,
523}
524
525impl TextureResolver {
526    fn new(device: &mut Device) -> TextureResolver {
527        let dummy_cache_texture = device
528            .create_texture(
529                ImageBufferKind::Texture2D,
530                ImageFormat::RGBA8,
531                1,
532                1,
533                TextureFilter::Linear,
534                None,
535            );
536        device.upload_texture_immediate(
537            &dummy_cache_texture,
538            &[0xff, 0xff, 0xff, 0xff],
539        );
540
541        TextureResolver {
542            texture_cache_map: FastHashMap::default(),
543            external_images: FastHashMap::default(),
544            dummy_cache_texture,
545        }
546    }
547
548    fn deinit(self, device: &mut Device) {
549        device.delete_texture(self.dummy_cache_texture);
550
551        for (_id, item) in self.texture_cache_map {
552            device.delete_texture(item.texture);
553        }
554    }
555
556    fn begin_frame(&mut self) {
557    }
558
559    fn end_pass(
560        &mut self,
561        device: &mut Device,
562        textures_to_invalidate: &[CacheTextureId],
563    ) {
564        for texture_id in textures_to_invalidate {
568            let render_target = &self.texture_cache_map[texture_id].texture;
569            device.invalidate_render_target(render_target);
570        }
571    }
572
573    fn bind(&self, texture_id: &TextureSource, sampler: TextureSampler, device: &mut Device) -> Swizzle {
575        match *texture_id {
576            TextureSource::Invalid => {
577                Swizzle::default()
578            }
579            TextureSource::Dummy => {
580                let swizzle = Swizzle::default();
581                device.bind_texture(sampler, &self.dummy_cache_texture, swizzle);
582                swizzle
583            }
584            TextureSource::External(TextureSourceExternal { ref index, .. }) => {
585                let texture = self.external_images
586                    .get(index)
587                    .expect("BUG: External image should be resolved by now");
588                device.bind_external_texture(sampler, texture);
589                Swizzle::default()
590            }
591            TextureSource::TextureCache(index, swizzle) => {
592                let texture = &self.texture_cache_map[&index].texture;
593                device.bind_texture(sampler, texture, swizzle);
594                swizzle
595            }
596        }
597    }
598
599    fn resolve(&self, texture_id: &TextureSource) -> Option<(&Texture, Swizzle)> {
603        match *texture_id {
604            TextureSource::Invalid => None,
605            TextureSource::Dummy => {
606                Some((&self.dummy_cache_texture, Swizzle::default()))
607            }
608            TextureSource::External(..) => {
609                panic!("BUG: External textures cannot be resolved, they can only be bound.");
610            }
611            TextureSource::TextureCache(index, swizzle) => {
612                Some((&self.texture_cache_map[&index].texture, swizzle))
613            }
614        }
615    }
616
617    fn get_uv_rect(
620        &self,
621        source: &TextureSource,
622        default_value: TexelRect,
623    ) -> TexelRect {
624        match source {
625            TextureSource::External(TextureSourceExternal { ref index, .. }) => {
626                let texture = self.external_images
627                    .get(index)
628                    .expect("BUG: External image should be resolved by now");
629                texture.get_uv_rect()
630            }
631            _ => {
632                default_value
633            }
634        }
635    }
636
637    fn get_texture_size(&self, texture: &TextureSource) -> DeviceIntSize {
639        match *texture {
640            TextureSource::Invalid => DeviceIntSize::zero(),
641            TextureSource::TextureCache(id, _) => {
642                self.texture_cache_map[&id].texture.get_dimensions()
643            },
644            TextureSource::External(TextureSourceExternal { index, .. }) => {
645                let uv_rect = self.external_images[&index].get_uv_rect();
650                (uv_rect.uv1 - uv_rect.uv0).abs().to_size().to_i32()
651            },
652            TextureSource::Dummy => DeviceIntSize::new(1, 1),
653        }
654    }
655
656    fn report_memory(&self) -> MemoryReport {
657        let mut report = MemoryReport::default();
658
659        for item in self.texture_cache_map.values() {
662            let counter = match item.category {
663                TextureCacheCategory::Atlas => &mut report.atlas_textures,
664                TextureCacheCategory::Standalone => &mut report.standalone_textures,
665                TextureCacheCategory::PictureTile => &mut report.picture_tile_textures,
666                TextureCacheCategory::RenderTarget => &mut report.render_target_textures,
667            };
668            *counter += item.texture.size_in_bytes();
669        }
670
671        report
672    }
673
674    fn update_profile(&self, profile: &mut TransactionProfile) {
675        let mut external_image_bytes = 0;
676        for img in self.external_images.values() {
677            let uv_rect = img.get_uv_rect();
678            let size = (uv_rect.uv1 - uv_rect.uv0).abs().to_size().to_i32();
681
682            let bpp = 4;
685            external_image_bytes += size.area() as usize * bpp;
686        }
687
688        profile.set(profiler::EXTERNAL_IMAGE_BYTES, profiler::bytes_to_mb(external_image_bytes));
689    }
690
691    fn get_cache_texture_mut(&mut self, id: &CacheTextureId) -> &mut Texture {
692        &mut self.texture_cache_map
693            .get_mut(id)
694            .expect("bug: texture not allocated")
695            .texture
696    }
697}
698
699#[derive(Debug, Copy, Clone, PartialEq)]
700#[cfg_attr(feature = "capture", derive(Serialize))]
701#[cfg_attr(feature = "replay", derive(Deserialize))]
702pub enum BlendMode {
703    None,
704    Alpha,
705    PremultipliedAlpha,
706    PremultipliedDestOut,
707    SubpixelDualSource,
708    Advanced(MixBlendMode),
709    MultiplyDualSource,
710    Screen,
711    Exclusion,
712    PlusLighter,
713}
714
715impl BlendMode {
716    pub fn from_mix_blend_mode(
720        mode: MixBlendMode,
721        advanced_blend: bool,
722        coherent: bool,
723        dual_source: bool,
724    ) -> Option<BlendMode> {
725        Some(match mode {
729            _ if advanced_blend && coherent => BlendMode::Advanced(mode),
731            MixBlendMode::Screen => BlendMode::Screen,
733            MixBlendMode::Exclusion => BlendMode::Exclusion,
735            MixBlendMode::PlusLighter => BlendMode::PlusLighter,
737            MixBlendMode::Multiply if dual_source => BlendMode::MultiplyDualSource,
739            _ if advanced_blend => BlendMode::Advanced(mode),
741            _ => return None,
743        })
744    }
745}
746
747struct DebugOverlayState {
749    is_enabled: bool,
751
752    current_size: Option<DeviceIntSize>,
755
756    layer_index: usize,
757}
758
759impl DebugOverlayState {
760    fn new() -> Self {
761        DebugOverlayState {
762            is_enabled: false,
763            current_size: None,
764            layer_index: 0,
765        }
766    }
767}
768
769#[derive(Debug, Default)]
771pub(crate) struct BufferDamageTracker {
772    damage_rects: [DeviceRect; 4],
773    current_offset: usize,
774}
775
776impl BufferDamageTracker {
777    fn push_dirty_rect(&mut self, rect: &DeviceRect) {
780        self.damage_rects[self.current_offset] = rect.clone();
781        self.current_offset = match self.current_offset {
782            0 => self.damage_rects.len() - 1,
783            n => n - 1,
784        }
785    }
786
787    fn get_damage_rect(&self, buffer_age: usize) -> Option<DeviceRect> {
791        match buffer_age {
792            0 => None,
794            1 => Some(DeviceRect::zero()),
797            n if n <= self.damage_rects.len() + 1 => {
800                Some(
801                    self.damage_rects.iter()
802                        .cycle()
803                        .skip(self.current_offset + 1)
804                        .take(n - 1)
805                        .fold(DeviceRect::zero(), |acc, r| acc.union(r))
806                )
807            }
808            _ => None,
811        }
812    }
813}
814
815pub struct Renderer {
821    result_rx: Receiver<ResultMsg>,
822    api_tx: Sender<ApiMsg>,
823    pub device: Device,
824    pending_texture_updates: Vec<TextureUpdateList>,
825    pending_texture_cache_updates: bool,
827    pending_native_surface_updates: Vec<NativeSurfaceOperation>,
828    pending_gpu_cache_updates: Vec<GpuCacheUpdateList>,
829    pending_gpu_cache_clear: bool,
830    pending_shader_updates: Vec<PathBuf>,
831    active_documents: FastHashMap<DocumentId, RenderedDocument>,
832
833    shaders: Rc<RefCell<Shaders>>,
834
835    max_recorded_profiles: usize,
836
837    clear_color: ColorF,
838    enable_clear_scissor: bool,
839    enable_advanced_blend_barriers: bool,
840    clear_caches_with_quads: bool,
841    clear_alpha_targets_with_quads: bool,
842
843    debug: debug::LazyInitializedDebugRenderer,
844    debug_flags: DebugFlags,
845    profile: TransactionProfile,
846    frame_counter: u64,
847    resource_upload_time: f64,
848    gpu_cache_upload_time: f64,
849    profiler: Profiler,
850    #[cfg(feature = "debugger")]
851    debugger: Debugger,
852
853    last_time: u64,
854
855    pub gpu_profiler: GpuProfiler,
856    vaos: vertex::RendererVAOs,
857
858    gpu_cache_texture: gpu_cache::GpuCacheTexture,
859    vertex_data_textures: Vec<vertex::VertexDataTextures>,
860    current_vertex_data_textures: usize,
861
862    gpu_cache_debug_chunks: Vec<Vec<GpuCacheDebugChunk>>,
866
867    gpu_cache_frame_id: FrameId,
868    gpu_cache_overflow: bool,
869
870    pipeline_info: PipelineInfo,
871
872    texture_resolver: TextureResolver,
874
875    texture_upload_pbo_pool: UploadPBOPool,
876    staging_texture_pool: UploadTexturePool,
877
878    dither_matrix_texture: Option<Texture>,
879
880    external_image_handler: Option<Box<dyn ExternalImageHandler>>,
883
884    size_of_ops: Option<MallocSizeOfOps>,
887
888    pub renderer_errors: Vec<RendererError>,
889
890    pub(in crate) async_frame_recorder: Option<AsyncScreenshotGrabber>,
891    pub(in crate) async_screenshots: Option<AsyncScreenshotGrabber>,
892
893    cpu_profiles: VecDeque<CpuProfile>,
896    gpu_profiles: VecDeque<GpuProfile>,
897
898    notifications: Vec<NotificationRequest>,
900
901    device_size: Option<DeviceIntSize>,
902
903    zoom_debug_texture: Option<Texture>,
905
906    cursor_position: DeviceIntPoint,
909
910    shared_texture_cache_cleared: bool,
913
914    documents_seen: FastHashSet<DocumentId>,
916
917    #[cfg(feature = "capture")]
918    read_fbo: FBOId,
919    #[cfg(feature = "replay")]
920    owned_external_images: FastHashMap<(ExternalImageId, u8), ExternalTexture>,
921
922    compositor_config: CompositorConfig,
924    current_compositor_kind: CompositorKind,
925
926    allocated_native_surfaces: FastHashSet<NativeSurfaceId>,
931
932    force_redraw: bool,
935
936    debug_overlay_state: DebugOverlayState,
938
939    buffer_damage_tracker: BufferDamageTracker,
943
944    max_primitive_instance_count: usize,
945    enable_instancing: bool,
946
947    consecutive_oom_frames: u32,
950
951    target_frame_publish_id: Option<FramePublishId>,
954
955    pending_result_msg: Option<ResultMsg>,
957
958    layer_compositor_frame_state_in_prev_frame: Option<LayerCompositorFrameState>,
960}
961
962#[derive(Debug)]
963pub enum RendererError {
964    Shader(ShaderError),
965    Thread(std::io::Error),
966    MaxTextureSize,
967    SoftwareRasterizer,
968    OutOfMemory,
969}
970
971impl From<ShaderError> for RendererError {
972    fn from(err: ShaderError) -> Self {
973        RendererError::Shader(err)
974    }
975}
976
977impl From<std::io::Error> for RendererError {
978    fn from(err: std::io::Error) -> Self {
979        RendererError::Thread(err)
980    }
981}
982
983impl Renderer {
984    pub fn device_size(&self) -> Option<DeviceIntSize> {
985        self.device_size
986    }
987
988    pub fn set_cursor_position(
990        &mut self,
991        position: DeviceIntPoint,
992    ) {
993        self.cursor_position = position;
994    }
995
996    pub fn get_max_texture_size(&self) -> i32 {
997        self.device.max_texture_size()
998    }
999
1000    pub fn get_graphics_api_info(&self) -> GraphicsApiInfo {
1001        GraphicsApiInfo {
1002            kind: GraphicsApi::OpenGL,
1003            version: self.device.gl().get_string(gl::VERSION),
1004            renderer: self.device.gl().get_string(gl::RENDERER),
1005        }
1006    }
1007
1008    pub fn preferred_color_format(&self) -> ImageFormat {
1009        self.device.preferred_color_formats().external
1010    }
1011
1012    pub fn required_texture_stride_alignment(&self, format: ImageFormat) -> usize {
1013        self.device.required_pbo_stride().num_bytes(format).get()
1014    }
1015
1016    pub fn set_clear_color(&mut self, color: ColorF) {
1017        self.clear_color = color;
1018    }
1019
1020    pub fn flush_pipeline_info(&mut self) -> PipelineInfo {
1021        mem::replace(&mut self.pipeline_info, PipelineInfo::default())
1022    }
1023
1024    pub fn current_epoch(&self, document_id: DocumentId, pipeline_id: PipelineId) -> Option<Epoch> {
1026        self.pipeline_info.epochs.get(&(pipeline_id, document_id)).cloned()
1027    }
1028
1029    fn get_next_result_msg(&mut self) -> Option<ResultMsg> {
1030        if self.pending_result_msg.is_none() {
1031            if let Ok(msg) = self.result_rx.try_recv() {
1032                self.pending_result_msg = Some(msg);
1033            }
1034        }
1035
1036        match (&self.pending_result_msg, &self.target_frame_publish_id) {
1037          (Some(ResultMsg::PublishDocument(frame_publish_id, _, _, _)), Some(target_id)) => {
1038            if frame_publish_id > target_id {
1039              return None;
1040            }
1041          }
1042          _ => {}
1043        }
1044
1045        self.pending_result_msg.take()
1046    }
1047
1048    pub fn update(&mut self) {
1052        profile_scope!("update");
1053
1054        while let Some(msg) = self.get_next_result_msg() {
1056            match msg {
1057                ResultMsg::PublishPipelineInfo(mut pipeline_info) => {
1058                    for ((pipeline_id, document_id), epoch) in pipeline_info.epochs {
1059                        self.pipeline_info.epochs.insert((pipeline_id, document_id), epoch);
1060                    }
1061                    self.pipeline_info.removed_pipelines.extend(pipeline_info.removed_pipelines.drain(..));
1062                }
1063                ResultMsg::PublishDocument(
1064                    _,
1065                    document_id,
1066                    mut doc,
1067                    resource_update_list,
1068                ) => {
1069                    let prev_frame_memory = if let Some(mut prev_doc) = self.active_documents.remove(&document_id) {
1078                        doc.profile.merge(&mut prev_doc.profile);
1079
1080                        if prev_doc.frame.must_be_drawn() {
1081                            prev_doc.render_reasons |= RenderReasons::TEXTURE_CACHE_FLUSH;
1082                            self.render_impl(
1083                                document_id,
1084                                &mut prev_doc,
1085                                None,
1086                                0,
1087                            ).ok();
1088                        }
1089
1090                        Some(prev_doc.frame.allocator_memory)
1091                    } else {
1092                        None
1093                    };
1094
1095                    if let Some(memory) = prev_frame_memory {
1096                        memory.assert_memory_reusable();
1099                    }
1100
1101                    self.active_documents.insert(document_id, doc);
1102
1103                    self.pending_texture_cache_updates |= !resource_update_list.texture_updates.updates.is_empty();
1115                    self.pending_texture_updates.push(resource_update_list.texture_updates);
1116                    self.pending_native_surface_updates.extend(resource_update_list.native_surface_updates);
1117                    self.documents_seen.insert(document_id);
1118                }
1119                ResultMsg::UpdateGpuCache(mut list) => {
1120                    if list.clear {
1121                        self.pending_gpu_cache_clear = true;
1122                    }
1123                    if list.clear {
1124                        self.gpu_cache_debug_chunks = Vec::new();
1125                    }
1126                    for cmd in mem::replace(&mut list.debug_commands, Vec::new()) {
1127                        match cmd {
1128                            GpuCacheDebugCmd::Alloc(chunk) => {
1129                                let row = chunk.address.v as usize;
1130                                if row >= self.gpu_cache_debug_chunks.len() {
1131                                    self.gpu_cache_debug_chunks.resize(row + 1, Vec::new());
1132                                }
1133                                self.gpu_cache_debug_chunks[row].push(chunk);
1134                            },
1135                            GpuCacheDebugCmd::Free(address) => {
1136                                let chunks = &mut self.gpu_cache_debug_chunks[address.v as usize];
1137                                let pos = chunks.iter()
1138                                    .position(|x| x.address == address).unwrap();
1139                                chunks.remove(pos);
1140                            },
1141                        }
1142                    }
1143                    self.pending_gpu_cache_updates.push(list);
1144                }
1145                ResultMsg::UpdateResources {
1146                    resource_updates,
1147                    memory_pressure,
1148                } => {
1149                    if memory_pressure {
1150                        let active_documents = mem::replace(
1160                            &mut self.active_documents,
1161                            FastHashMap::default(),
1162                        );
1163                        for (doc_id, mut doc) in active_documents {
1164                            if doc.frame.must_be_drawn() {
1165                                self.render_impl(
1169                                    doc_id,
1170                                    &mut doc,
1171                                    None,
1172                                    0,
1173                                ).ok();
1174                            }
1175                        }
1176                    }
1177
1178                    self.pending_texture_cache_updates |= !resource_updates.texture_updates.updates.is_empty();
1179                    self.pending_texture_updates.push(resource_updates.texture_updates);
1180                    self.pending_native_surface_updates.extend(resource_updates.native_surface_updates);
1181                    self.device.begin_frame();
1182
1183                    self.update_texture_cache();
1184                    self.update_native_surfaces();
1185
1186                    if memory_pressure {
1192                        self.texture_upload_pbo_pool.on_memory_pressure(&mut self.device);
1193                        self.staging_texture_pool.delete_textures(&mut self.device);
1194                    }
1195
1196                    self.device.end_frame();
1197                }
1198                ResultMsg::RenderDocumentOffscreen(document_id, mut offscreen_doc, resources) => {
1199                    let prev_doc = self.active_documents.remove(&document_id);
1204                    if let Some(mut prev_doc) = prev_doc {
1205                        if prev_doc.frame.must_be_drawn() {
1206                            prev_doc.render_reasons |= RenderReasons::TEXTURE_CACHE_FLUSH;
1207                            self.render_impl(
1208                                document_id,
1209                                &mut prev_doc,
1210                                None,
1211                                0,
1212                            ).ok();
1213                        }
1214
1215                        self.active_documents.insert(document_id, prev_doc);
1216                    }
1217
1218                    self.pending_texture_cache_updates |= !resources.texture_updates.updates.is_empty();
1221                    self.pending_texture_updates.push(resources.texture_updates);
1222                    self.pending_native_surface_updates.extend(resources.native_surface_updates);
1223
1224                    self.render_impl(
1225                        document_id,
1226                        &mut offscreen_doc,
1227                        None,
1228                        0,
1229                    ).unwrap();
1230                }
1231                ResultMsg::AppendNotificationRequests(mut notifications) => {
1232                    if !self.pending_texture_cache_updates {
1238                        drain_filter(
1239                            &mut notifications,
1240                            |n| { n.when() == Checkpoint::FrameTexturesUpdated },
1241                            |n| { n.notify(); },
1242                        );
1243                    }
1244                    self.notifications.append(&mut notifications);
1245                }
1246                ResultMsg::ForceRedraw => {
1247                    self.force_redraw = true;
1248                }
1249                ResultMsg::RefreshShader(path) => {
1250                    self.pending_shader_updates.push(path);
1251                }
1252                ResultMsg::SetParameter(ref param) => {
1253                    self.device.set_parameter(param);
1254                    self.profiler.set_parameter(param);
1255                }
1256                ResultMsg::DebugOutput(output) => match output {
1257                    #[cfg(feature = "capture")]
1258                    DebugOutput::SaveCapture(config, deferred) => {
1259                        self.save_capture(config, deferred);
1260                    }
1261                    #[cfg(feature = "replay")]
1262                    DebugOutput::LoadCapture(config, plain_externals) => {
1263                        self.active_documents.clear();
1264                        self.load_capture(config, plain_externals);
1265                    }
1266                },
1267                ResultMsg::DebugCommand(command) => {
1268                    self.handle_debug_command(command);
1269                }
1270            }
1271        }
1272    }
1273
1274    pub fn set_target_frame_publish_id(&mut self, publish_id: FramePublishId) {
1277        self.target_frame_publish_id = Some(publish_id);
1278    }
1279
1280    fn handle_debug_command(&mut self, command: DebugCommand) {
1281        match command {
1282            DebugCommand::SetPictureTileSize(_) |
1283            DebugCommand::SetMaximumSurfaceSize(_) |
1284            DebugCommand::GenerateFrame => {
1285                panic!("Should be handled by render backend");
1286            }
1287            #[cfg(feature = "debugger")]
1288            DebugCommand::Query(ref query) => {
1289                match query.kind {
1290                    DebugQueryKind::SpatialTree { .. } => {
1291                        panic!("Should be handled by render backend");
1292                    }
1293                    DebugQueryKind::CompositorConfig { .. } => {
1294                        let result = match self.active_documents.iter().last() {
1295                            Some((_, doc)) => {
1296                                doc.frame.composite_state.print_to_string()
1297                            }
1298                            None => {
1299                                "No active documents".into()
1300                            }
1301                        };
1302                        query.result.send(result).ok();
1303                    }
1304                    DebugQueryKind::CompositorView { .. } => {
1305                        let result = match self.active_documents.iter().last() {
1306                            Some((_, doc)) => {
1307                                let info = CompositorDebugInfo::from(&doc.frame.composite_state);
1308                                serde_json::to_string(&info).unwrap()
1309                            }
1310                            None => {
1311                                "No active documents".into()
1312                            }
1313                        };
1314                        query.result.send(result).ok();
1315                    }
1316                }
1317            }
1318            DebugCommand::SaveCapture(..) |
1319            DebugCommand::LoadCapture(..) |
1320            DebugCommand::StartCaptureSequence(..) |
1321            DebugCommand::StopCaptureSequence => {
1322                panic!("Capture commands are not welcome here! Did you build with 'capture' feature?")
1323            }
1324            DebugCommand::ClearCaches(_)
1325            | DebugCommand::SimulateLongSceneBuild(_)
1326            | DebugCommand::EnableNativeCompositor(_)
1327            | DebugCommand::SetBatchingLookback(_) => {}
1328            DebugCommand::InvalidateGpuCache => {
1329                self.gpu_cache_texture.invalidate();
1330            }
1331            DebugCommand::SetFlags(flags) => {
1332                self.set_debug_flags(flags);
1333            }
1334            DebugCommand::GetDebugFlags(tx) => {
1335                tx.send(self.debug_flags).unwrap();
1336            }
1337            #[cfg(feature = "debugger")]
1338            DebugCommand::AddDebugClient(client) => {
1339                self.debugger.add_client(
1340                    client,
1341                    self.debug_flags,
1342                    &self.profiler,
1343                );
1344            }
1345        }
1346    }
1347
1348    pub fn set_external_image_handler(&mut self, handler: Box<dyn ExternalImageHandler>) {
1350        self.external_image_handler = Some(handler);
1351    }
1352
1353    pub fn get_frame_profiles(&mut self) -> (Vec<CpuProfile>, Vec<GpuProfile>) {
1355        let cpu_profiles = self.cpu_profiles.drain(..).collect();
1356        let gpu_profiles = self.gpu_profiles.drain(..).collect();
1357        (cpu_profiles, gpu_profiles)
1358    }
1359
1360    pub fn force_redraw(&mut self) {
1363        self.force_redraw = true;
1364    }
1365
1366    pub fn render(
1372        &mut self,
1373        device_size: DeviceIntSize,
1374        buffer_age: usize,
1375    ) -> Result<RenderResults, Vec<RendererError>> {
1376        self.device_size = Some(device_size);
1377
1378        let doc_id = self.active_documents.keys().last().cloned();
1385
1386        let result = match doc_id {
1387            Some(doc_id) => {
1388                let mut doc = self.active_documents
1390                    .remove(&doc_id)
1391                    .unwrap();
1392
1393                let size = if !device_size.is_empty() {
1394                    Some(device_size)
1395                } else {
1396                    None
1397                };
1398
1399                let result = self.render_impl(
1400                    doc_id,
1401                    &mut doc,
1402                    size,
1403                    buffer_age,
1404                );
1405
1406                self.active_documents.insert(doc_id, doc);
1407
1408                result
1409            }
1410            None => {
1411                self.last_time = zeitstempel::now();
1412                Ok(RenderResults::default())
1413            }
1414        };
1415
1416        drain_filter(
1417            &mut self.notifications,
1418            |n| { n.when() == Checkpoint::FrameRendered },
1419            |n| { n.notify(); },
1420        );
1421
1422        let mut oom = false;
1423        if let Err(ref errors) = result {
1424            for error in errors {
1425                if matches!(error, &RendererError::OutOfMemory) {
1426                    oom = true;
1427                    break;
1428                }
1429            }
1430        }
1431
1432        if oom {
1433            let _ = self.api_tx.send(ApiMsg::MemoryPressure);
1434            self.consecutive_oom_frames += 1;
1436            assert!(self.consecutive_oom_frames < 5, "Renderer out of memory");
1437        } else {
1438            self.consecutive_oom_frames = 0;
1439        }
1440
1441        self.notifications.clear();
1445
1446        tracy_frame_marker!();
1447
1448        result
1449    }
1450
1451    fn update_debug_overlay(
1454        &mut self,
1455        framebuffer_size: DeviceIntSize,
1456        has_debug_items: bool,
1457    ) {
1458        self.debug_overlay_state.is_enabled = has_debug_items || self.debug_flags.intersects(
1460            DebugFlags::PROFILER_DBG |
1461            DebugFlags::RENDER_TARGET_DBG |
1462            DebugFlags::TEXTURE_CACHE_DBG |
1463            DebugFlags::EPOCHS |
1464            DebugFlags::GPU_CACHE_DBG |
1465            DebugFlags::PICTURE_CACHING_DBG |
1466            DebugFlags::PRIMITIVE_DBG |
1467            DebugFlags::ZOOM_DBG |
1468            DebugFlags::WINDOW_VISIBILITY_DBG
1469        );
1470
1471        if let CompositorKind::Native { .. } = self.current_compositor_kind {
1473            let compositor = self.compositor_config.compositor().unwrap();
1474
1475            if let Some(current_size) = self.debug_overlay_state.current_size {
1478                if !self.debug_overlay_state.is_enabled || current_size != framebuffer_size {
1479                    compositor.destroy_surface(&mut self.device, NativeSurfaceId::DEBUG_OVERLAY);
1480                    self.debug_overlay_state.current_size = None;
1481                }
1482            }
1483
1484            if self.debug_overlay_state.is_enabled && self.debug_overlay_state.current_size.is_none() {
1486                compositor.create_surface(
1487                    &mut self.device,
1488                    NativeSurfaceId::DEBUG_OVERLAY,
1489                    DeviceIntPoint::zero(),
1490                    framebuffer_size,
1491                    false,
1492                );
1493                compositor.create_tile(
1494                    &mut self.device,
1495                    NativeTileId::DEBUG_OVERLAY,
1496                );
1497                self.debug_overlay_state.current_size = Some(framebuffer_size);
1498            }
1499        }
1500    }
1501
1502    fn bind_debug_overlay(&mut self, device_size: DeviceIntSize) -> Option<DrawTarget> {
1504        if self.debug_overlay_state.is_enabled {
1506            match self.current_compositor_kind {
1507                CompositorKind::Native { .. } => {
1508                    let compositor = self.compositor_config.compositor().unwrap();
1509                    let surface_size = self.debug_overlay_state.current_size.unwrap();
1510
1511                    compositor.invalidate_tile(
1513                        &mut self.device,
1514                        NativeTileId::DEBUG_OVERLAY,
1515                        DeviceIntRect::from_size(surface_size),
1516                    );
1517                    let surface_info = compositor.bind(
1519                        &mut self.device,
1520                        NativeTileId::DEBUG_OVERLAY,
1521                        DeviceIntRect::from_size(surface_size),
1522                        DeviceIntRect::from_size(surface_size),
1523                    );
1524
1525                    let draw_target = DrawTarget::NativeSurface {
1527                        offset: surface_info.origin,
1528                        external_fbo_id: surface_info.fbo_id,
1529                        dimensions: surface_size,
1530                    };
1531                    self.device.bind_draw_target(draw_target);
1532
1533                    self.device.clear_target(
1535                        Some([0.0, 0.0, 0.0, 0.0]),
1536                        None, None,
1538                    );
1539
1540                    Some(draw_target)
1541                }
1542                CompositorKind::Layer { .. } => {
1543                    let compositor = self.compositor_config.layer_compositor().unwrap();
1544                    compositor.bind_layer(self.debug_overlay_state.layer_index, &[]);
1545
1546                    self.device.clear_target(
1547                        Some([0.0, 0.0, 0.0, 0.0]),
1548                        None, None,
1550                    );
1551
1552                    Some(DrawTarget::new_default(device_size, self.device.surface_origin_is_top_left()))
1553                }
1554                CompositorKind::Draw { .. } => {
1555                    Some(DrawTarget::new_default(device_size, self.device.surface_origin_is_top_left()))
1559                }
1560            }
1561        } else {
1562            None
1563        }
1564    }
1565
1566    fn unbind_debug_overlay(&mut self) {
1568        if self.debug_overlay_state.is_enabled {
1570            match self.current_compositor_kind {
1571                CompositorKind::Native { .. } => {
1572                    let compositor = self.compositor_config.compositor().unwrap();
1573                    compositor.unbind(&mut self.device);
1575
1576                    let clip_rect = DeviceIntRect::from_size(
1577                        self.debug_overlay_state.current_size.unwrap(),
1578                    );
1579
1580                    compositor.add_surface(
1581                        &mut self.device,
1582                        NativeSurfaceId::DEBUG_OVERLAY,
1583                        CompositorSurfaceTransform::identity(),
1584                        clip_rect,
1585                        ImageRendering::Auto,
1586                        clip_rect,
1587                        ClipRadius::EMPTY,
1588                    );
1589                }
1590                CompositorKind::Draw { .. } => {}
1591                CompositorKind::Layer { .. } => {
1592                    let compositor = self.compositor_config.layer_compositor().unwrap();
1593                    compositor.present_layer(self.debug_overlay_state.layer_index, &[]);
1594                }
1595            }
1596        }
1597    }
1598
1599    fn render_impl(
1604        &mut self,
1605        doc_id: DocumentId,
1606        active_doc: &mut RenderedDocument,
1607        mut device_size: Option<DeviceIntSize>,
1608        buffer_age: usize,
1609    ) -> Result<RenderResults, Vec<RendererError>> {
1610        profile_scope!("render");
1611        let mut results = RenderResults::default();
1612        self.profile.end_time_if_started(profiler::FRAME_SEND_TIME);
1613        self.profile.start_time(profiler::RENDERER_TIME);
1614
1615        self.staging_texture_pool.begin_frame();
1616
1617        let compositor_kind = active_doc.frame.composite_state.compositor_kind;
1618        if self.current_compositor_kind != compositor_kind {
1620            let enable = match (self.current_compositor_kind, compositor_kind) {
1621                (CompositorKind::Native { .. }, CompositorKind::Draw { .. }) => {
1622                    if self.debug_overlay_state.current_size.is_some() {
1623                        self.compositor_config
1624                            .compositor()
1625                            .unwrap()
1626                            .destroy_surface(&mut self.device, NativeSurfaceId::DEBUG_OVERLAY);
1627                        self.debug_overlay_state.current_size = None;
1628                    }
1629                    false
1630                }
1631                (CompositorKind::Draw { .. }, CompositorKind::Native { .. }) => {
1632                    true
1633                }
1634                (current_compositor_kind, active_doc_compositor_kind) => {
1635                    warn!("Compositor mismatch, assuming this is Wrench running. Current {:?}, active {:?}",
1636                        current_compositor_kind, active_doc_compositor_kind);
1637                    false
1638                }
1639            };
1640
1641            if let Some(config) = self.compositor_config.compositor() {
1642                config.enable_native_compositor(&mut self.device, enable);
1643            }
1644            self.current_compositor_kind = compositor_kind;
1645        }
1646
1647        self.texture_resolver.begin_frame();
1654
1655        if let Some(device_size) = device_size {
1656            self.update_gpu_profile(device_size);
1657        }
1658
1659        let cpu_frame_id = {
1660            let _gm = self.gpu_profiler.start_marker("begin frame");
1661            let frame_id = self.device.begin_frame();
1662            self.gpu_profiler.begin_frame(frame_id);
1663
1664            self.device.disable_scissor();
1665            self.device.disable_depth();
1666            self.set_blend(false, FramebufferKind::Main);
1667            self.update_texture_cache();
1670            self.update_native_surfaces();
1671
1672            frame_id
1673        };
1674
1675        if !active_doc.frame.present {
1676            device_size = None;
1679        }
1680
1681        if let Some(device_size) = device_size {
1682            if let CompositorKind::Native { .. } = self.current_compositor_kind {
1686                let compositor = self.compositor_config.compositor().unwrap();
1687                compositor.begin_frame(&mut self.device);
1688            }
1689
1690            self.update_debug_overlay(device_size, !active_doc.frame.debug_items.is_empty());
1693        }
1694
1695        let frame = &mut active_doc.frame;
1696        let profile = &mut active_doc.profile;
1697        assert!(self.current_compositor_kind == frame.composite_state.compositor_kind);
1698
1699        if self.shared_texture_cache_cleared {
1700            assert!(self.documents_seen.contains(&doc_id),
1701                    "Cleared texture cache without sending new document frame.");
1702        }
1703
1704        match self.prepare_gpu_cache(&frame.deferred_resolves) {
1705            Ok(..) => {
1706                assert!(frame.gpu_cache_frame_id <= self.gpu_cache_frame_id,
1707                    "Received frame depends on a later GPU cache epoch ({:?}) than one we received last via `UpdateGpuCache` ({:?})",
1708                    frame.gpu_cache_frame_id, self.gpu_cache_frame_id);
1709
1710                self.draw_frame(
1711                    frame,
1712                    device_size,
1713                    buffer_age,
1714                    &mut results,
1715                );
1716
1717                if thread_is_being_profiled() {
1720                    let duration = Duration::new(0,0);
1721                    if let Some(n) = self.profile.get(profiler::RENDERED_PICTURE_TILES) {
1722                        let message = (n as usize).to_string();
1723                        add_text_marker("NumPictureCacheInvalidated", &message, duration);
1724                    }
1725                }
1726
1727                if device_size.is_some() {
1728                    self.draw_frame_debug_items(&frame.debug_items);
1729                }
1730
1731                self.profile.merge(profile);
1732            }
1733            Err(e) => {
1734                self.renderer_errors.push(e);
1735            }
1736        }
1737
1738        self.unlock_external_images(&frame.deferred_resolves);
1739
1740        let _gm = self.gpu_profiler.start_marker("end frame");
1741        self.gpu_profiler.end_frame();
1742
1743        let t = self.profile.end_time(profiler::RENDERER_TIME);
1744        self.profile.end_time_if_started(profiler::TOTAL_FRAME_CPU_TIME);
1745
1746        let current_time = zeitstempel::now();
1747        if device_size.is_some() {
1748            let time = profiler::ns_to_ms(current_time - self.last_time);
1749            self.profile.set(profiler::FRAME_TIME, time);
1750        }
1751
1752        let debug_overlay = device_size.and_then(|device_size| {
1753            self.bind_debug_overlay(device_size).map(|draw_target| {
1755                self.draw_render_target_debug(&draw_target);
1756                self.draw_texture_cache_debug(&draw_target);
1757                self.draw_gpu_cache_debug(device_size);
1758                self.draw_zoom_debug(device_size);
1759                self.draw_epoch_debug();
1760                self.draw_window_visibility_debug();
1761                draw_target
1762            })
1763        });
1764
1765        Telemetry::record_renderer_time(Duration::from_micros((t * 1000.00) as u64));
1766        if self.profile.get(profiler::SHADER_BUILD_TIME).is_none() {
1767          Telemetry::record_renderer_time_no_sc(Duration::from_micros((t * 1000.00) as u64));
1768        }
1769
1770        if self.max_recorded_profiles > 0 {
1771            while self.cpu_profiles.len() >= self.max_recorded_profiles {
1772                self.cpu_profiles.pop_front();
1773            }
1774            let cpu_profile = CpuProfile::new(
1775                cpu_frame_id,
1776                (self.profile.get_or(profiler::FRAME_BUILDING_TIME, 0.0) * 1000000.0) as u64,
1777                (self.profile.get_or(profiler::RENDERER_TIME, 0.0) * 1000000.0) as u64,
1778                self.profile.get_or(profiler::DRAW_CALLS, 0.0) as usize,
1779            );
1780            self.cpu_profiles.push_back(cpu_profile);
1781        }
1782
1783        if thread_is_being_profiled() {
1784            let duration = Duration::new(0,0);
1785            let message = (self.profile.get_or(profiler::DRAW_CALLS, 0.0) as usize).to_string();
1786            add_text_marker("NumDrawCalls", &message, duration);
1787        }
1788
1789        let report = self.texture_resolver.report_memory();
1790        self.profile.set(profiler::RENDER_TARGET_MEM, profiler::bytes_to_mb(report.render_target_textures));
1791        self.profile.set(profiler::PICTURE_TILES_MEM, profiler::bytes_to_mb(report.picture_tile_textures));
1792        self.profile.set(profiler::ATLAS_TEXTURES_MEM, profiler::bytes_to_mb(report.atlas_textures));
1793        self.profile.set(profiler::STANDALONE_TEXTURES_MEM, profiler::bytes_to_mb(report.standalone_textures));
1794
1795        self.profile.set(profiler::DEPTH_TARGETS_MEM, profiler::bytes_to_mb(self.device.depth_targets_memory()));
1796
1797        self.profile.set(profiler::TEXTURES_CREATED, self.device.textures_created);
1798        self.profile.set(profiler::TEXTURES_DELETED, self.device.textures_deleted);
1799
1800        results.stats.texture_upload_mb = self.profile.get_or(profiler::TEXTURE_UPLOADS_MEM, 0.0);
1801        self.frame_counter += 1;
1802        results.stats.resource_upload_time = self.resource_upload_time;
1803        self.resource_upload_time = 0.0;
1804        results.stats.gpu_cache_upload_time = self.gpu_cache_upload_time;
1805        self.gpu_cache_upload_time = 0.0;
1806
1807        if let Some(stats) = active_doc.frame_stats.take() {
1808          results.stats.merge(&stats);
1810
1811          self.profiler.update_frame_stats(stats);
1812        }
1813
1814        let add_markers = thread_is_being_profiled();
1821        for i in 0..RenderReasons::NUM_BITS {
1822            let counter = profiler::RENDER_REASON_FIRST + i as usize;
1823            let mut val = 0.0;
1824            let reason_bit = RenderReasons::from_bits_truncate(1 << i);
1825            if active_doc.render_reasons.contains(reason_bit) {
1826                val = 1.0;
1827                if add_markers {
1828                    let event_str = format!("Render reason {:?}", reason_bit);
1829                    add_event_marker(&event_str);
1830                }
1831            }
1832            self.profile.set(counter, val);
1833        }
1834        active_doc.render_reasons = RenderReasons::empty();
1835
1836
1837        self.texture_resolver.update_profile(&mut self.profile);
1838
1839        self.profiler.set_counters(&mut self.profile);
1841
1842        #[cfg(feature = "debugger")]
1845        self.debugger.update(
1846            self.debug_flags,
1847            &self.profiler,
1848        );
1849
1850        self.profiler.update();
1852
1853        if self.debug_flags.intersects(DebugFlags::PROFILER_DBG | DebugFlags::PROFILER_CAPTURE) {
1854            if let Some(device_size) = device_size {
1855                if let Some(debug_renderer) = self.debug.get_mut(&mut self.device) {
1857                    self.profiler.draw_profile(
1858                        self.frame_counter,
1859                        debug_renderer,
1860                        device_size,
1861                    );
1862                }
1863            }
1864        }
1865
1866        if self.debug_flags.contains(DebugFlags::ECHO_DRIVER_MESSAGES) {
1867            self.device.echo_driver_messages();
1868        }
1869
1870        if let Some(debug_renderer) = self.debug.try_get_mut() {
1871            let small_screen = self.debug_flags.contains(DebugFlags::SMALL_SCREEN);
1872            let scale = if small_screen { 1.6 } else { 1.0 };
1873            let surface_origin_is_top_left = match self.current_compositor_kind {
1876                CompositorKind::Native { .. } => true,
1877                CompositorKind::Draw { .. } | CompositorKind::Layer { .. } => self.device.surface_origin_is_top_left(),
1878            };
1879            debug_renderer.render(
1882                &mut self.device,
1883                debug_overlay.and(device_size),
1884                scale,
1885                surface_origin_is_top_left,
1886            );
1887        }
1888
1889        self.staging_texture_pool.end_frame(&mut self.device);
1890        self.texture_upload_pbo_pool.end_frame(&mut self.device);
1891        self.device.end_frame();
1892
1893        if debug_overlay.is_some() {
1894            self.last_time = current_time;
1895
1896            self.unbind_debug_overlay();
1899        }
1900
1901        if device_size.is_some() {
1902            match self.current_compositor_kind {
1906                CompositorKind::Layer { .. } => {
1907                    let compositor = self.compositor_config.layer_compositor().unwrap();
1908                    compositor.end_frame();
1909                }
1910                CompositorKind::Native { .. } => {
1911                    profile_scope!("compositor.end_frame");
1912                    let compositor = self.compositor_config.compositor().unwrap();
1913                    compositor.end_frame(&mut self.device);
1914                }
1915                CompositorKind::Draw { .. } => {}
1916            }
1917        }
1918
1919        self.documents_seen.clear();
1920        self.shared_texture_cache_cleared = false;
1921
1922        self.check_gl_errors();
1923
1924        if self.renderer_errors.is_empty() {
1925            Ok(results)
1926        } else {
1927            Err(mem::replace(&mut self.renderer_errors, Vec::new()))
1928        }
1929    }
1930
1931    fn update_gpu_profile(&mut self, device_size: DeviceIntSize) {
1932        let _gm = self.gpu_profiler.start_marker("build samples");
1933        let (gpu_frame_id, timers, samplers) = self.gpu_profiler.build_samples();
1936
1937        if self.max_recorded_profiles > 0 {
1938            while self.gpu_profiles.len() >= self.max_recorded_profiles {
1939                self.gpu_profiles.pop_front();
1940            }
1941
1942            self.gpu_profiles.push_back(GpuProfile::new(gpu_frame_id, &timers));
1943        }
1944
1945        self.profiler.set_gpu_time_queries(timers);
1946
1947        if !samplers.is_empty() {
1948            let screen_fraction = 1.0 / device_size.to_f32().area();
1949
1950            fn accumulate_sampler_value(description: &str, samplers: &[GpuSampler]) -> f32 {
1951                let mut accum = 0.0;
1952                for sampler in samplers {
1953                    if sampler.tag.label != description {
1954                        continue;
1955                    }
1956
1957                    accum += sampler.count as f32;
1958                }
1959
1960                accum
1961            }
1962
1963            let alpha_targets = accumulate_sampler_value(&"Alpha targets", &samplers) * screen_fraction;
1964            let transparent_pass = accumulate_sampler_value(&"Transparent pass", &samplers) * screen_fraction;
1965            let opaque_pass = accumulate_sampler_value(&"Opaque pass", &samplers) * screen_fraction;
1966            self.profile.set(profiler::ALPHA_TARGETS_SAMPLERS, alpha_targets);
1967            self.profile.set(profiler::TRANSPARENT_PASS_SAMPLERS, transparent_pass);
1968            self.profile.set(profiler::OPAQUE_PASS_SAMPLERS, opaque_pass);
1969            self.profile.set(profiler::TOTAL_SAMPLERS, alpha_targets + transparent_pass + opaque_pass);
1970        }
1971    }
1972
1973    fn update_texture_cache(&mut self) {
1974        profile_scope!("update_texture_cache");
1975
1976        let _gm = self.gpu_profiler.start_marker("texture cache update");
1977        let mut pending_texture_updates = mem::replace(&mut self.pending_texture_updates, vec![]);
1978        self.pending_texture_cache_updates = false;
1979
1980        self.profile.start_time(profiler::TEXTURE_CACHE_UPDATE_TIME);
1981
1982        let mut create_cache_texture_time = 0;
1983        let mut delete_cache_texture_time = 0;
1984
1985        for update_list in pending_texture_updates.drain(..) {
1986            for ((src_tex, dst_tex), copies) in &update_list.copies {
1988
1989                let dest_texture = &self.texture_resolver.texture_cache_map[&dst_tex].texture;
1990                let dst_texture_size = dest_texture.get_dimensions().to_f32();
1991
1992                let mut copy_instances = Vec::new();
1993                for copy in copies {
1994                    copy_instances.push(CopyInstance {
1995                        src_rect: copy.src_rect.to_f32(),
1996                        dst_rect: copy.dst_rect.to_f32(),
1997                        dst_texture_size,
1998                    });
1999                }
2000
2001                let draw_target = DrawTarget::from_texture(dest_texture, false);
2002                self.device.bind_draw_target(draw_target);
2003
2004                self.shaders
2005                    .borrow_mut()
2006                    .ps_copy()
2007                    .bind(
2008                        &mut self.device,
2009                        &Transform3D::identity(),
2010                        None,
2011                        &mut self.renderer_errors,
2012                        &mut self.profile,
2013                    );
2014
2015                self.draw_instanced_batch(
2016                    ©_instances,
2017                    VertexArrayKind::Copy,
2018                    &BatchTextures::composite_rgb(
2019                        TextureSource::TextureCache(*src_tex, Swizzle::default())
2020                    ),
2021                    &mut RendererStats::default(),
2022                );
2023            }
2024
2025            let mut pending_deletes = Vec::new();
2027            for allocation in &update_list.allocations {
2028                let old = self.texture_resolver.texture_cache_map.remove(&allocation.id);
2029                match allocation.kind {
2030                    TextureCacheAllocationKind::Alloc(_) => {
2031                        assert!(old.is_none(), "Renderer and backend disagree!");
2032                    }
2033                    TextureCacheAllocationKind::Reset(_) |
2034                    TextureCacheAllocationKind::Free => {
2035                        assert!(old.is_some(), "Renderer and backend disagree!");
2036                    }
2037                }
2038                if let Some(old) = old {
2039
2040                    let size = old.texture.get_dimensions();
2042                    let info = TextureCacheAllocInfo {
2043                        width: size.width,
2044                        height: size.height,
2045                        format: old.texture.get_format(),
2046                        filter: old.texture.get_filter(),
2047                        target: old.texture.get_target(),
2048                        is_shared_cache: old.texture.flags().contains(TextureFlags::IS_SHARED_TEXTURE_CACHE),
2049                        has_depth: old.texture.supports_depth(),
2050                        category: old.category,
2051                    };
2052                    pending_deletes.push((old.texture, info));
2053                }
2054            }
2055            let mut reused_textures = VecDeque::with_capacity(pending_deletes.len());
2057            for allocation in &update_list.allocations {
2058                match allocation.kind {
2059                    TextureCacheAllocationKind::Alloc(ref info) |
2060                    TextureCacheAllocationKind::Reset(ref info) => {
2061                        reused_textures.push_back(
2062                            pending_deletes.iter()
2063                                .position(|(_, old_info)| *old_info == *info)
2064                                .map(|index| pending_deletes.swap_remove(index).0)
2065                        );
2066                    }
2067                    TextureCacheAllocationKind::Free => {}
2068                }
2069            }
2070
2071            if !pending_deletes.is_empty() {
2073                let delete_texture_start = zeitstempel::now();
2074                for (texture, _) in pending_deletes {
2075                    add_event_marker("TextureCacheFree");
2076                    self.device.delete_texture(texture);
2077                }
2078                delete_cache_texture_time += zeitstempel::now() - delete_texture_start;
2079            }
2080
2081            for allocation in update_list.allocations {
2082                match allocation.kind {
2083                    TextureCacheAllocationKind::Alloc(_) => add_event_marker("TextureCacheAlloc"),
2084                    TextureCacheAllocationKind::Reset(_) => add_event_marker("TextureCacheReset"),
2085                    TextureCacheAllocationKind::Free => {}
2086                };
2087                match allocation.kind {
2088                    TextureCacheAllocationKind::Alloc(ref info) |
2089                    TextureCacheAllocationKind::Reset(ref info) => {
2090                        let create_cache_texture_start = zeitstempel::now();
2091                        let mut texture = reused_textures.pop_front().unwrap_or(None).unwrap_or_else(|| {
2097                            self.device.create_texture(
2098                                info.target,
2099                                info.format,
2100                                info.width,
2101                                info.height,
2102                                info.filter,
2103                                Some(RenderTargetInfo { has_depth: info.has_depth }),
2106                            )
2107                        });
2108
2109                        if info.is_shared_cache {
2110                            texture.flags_mut()
2111                                .insert(TextureFlags::IS_SHARED_TEXTURE_CACHE);
2112
2113                            if self.device.use_batched_texture_uploads() &&
2117                                !self.device.get_capabilities().supports_render_target_partial_update
2118                            {
2119                                self.clear_texture(&texture, [0.0; 4]);
2120                            }
2121
2122                            if self.debug_flags.contains(DebugFlags::TEXTURE_CACHE_DBG) {
2126                                self.clear_texture(&texture, TEXTURE_CACHE_DBG_CLEAR_COLOR);
2127                            }
2128                        }
2129
2130                        create_cache_texture_time += zeitstempel::now() - create_cache_texture_start;
2131
2132                        self.texture_resolver.texture_cache_map.insert(allocation.id, CacheTexture {
2133                            texture,
2134                            category: info.category,
2135                        });
2136                    }
2137                    TextureCacheAllocationKind::Free => {}
2138                };
2139            }
2140
2141            upload_to_texture_cache(self, update_list.updates);
2142
2143            self.check_gl_errors();
2144        }
2145
2146        if create_cache_texture_time > 0 {
2147            self.profile.set(
2148                profiler::CREATE_CACHE_TEXTURE_TIME,
2149                profiler::ns_to_ms(create_cache_texture_time)
2150            );
2151        }
2152        if delete_cache_texture_time > 0 {
2153            self.profile.set(
2154                profiler::DELETE_CACHE_TEXTURE_TIME,
2155                profiler::ns_to_ms(delete_cache_texture_time)
2156            )
2157        }
2158
2159        let t = self.profile.end_time(profiler::TEXTURE_CACHE_UPDATE_TIME);
2160        self.resource_upload_time += t;
2161        Telemetry::record_texture_cache_update_time(Duration::from_micros((t * 1000.00) as u64));
2162
2163        drain_filter(
2164            &mut self.notifications,
2165            |n| { n.when() == Checkpoint::FrameTexturesUpdated },
2166            |n| { n.notify(); },
2167        );
2168    }
2169
2170    fn check_gl_errors(&mut self) {
2171        let err = self.device.gl().get_error();
2172        if err == gl::OUT_OF_MEMORY {
2173            self.renderer_errors.push(RendererError::OutOfMemory);
2174        }
2175
2176        }
2178
2179    fn bind_textures(&mut self, textures: &BatchTextures) {
2180        for i in 0 .. 3 {
2181            self.texture_resolver.bind(
2182                &textures.input.colors[i],
2183                TextureSampler::color(i),
2184                &mut self.device,
2185            );
2186        }
2187
2188        self.texture_resolver.bind(
2189            &textures.clip_mask,
2190            TextureSampler::ClipMask,
2191            &mut self.device,
2192        );
2193
2194        if let Some(ref texture) = self.dither_matrix_texture {
2196            self.device.bind_texture(TextureSampler::Dither, texture, Swizzle::default());
2197        }
2198    }
2199
2200    fn draw_instanced_batch<T: Clone>(
2201        &mut self,
2202        data: &[T],
2203        vertex_array_kind: VertexArrayKind,
2204        textures: &BatchTextures,
2205        stats: &mut RendererStats,
2206    ) {
2207        self.bind_textures(textures);
2208
2209        debug_assert!(!data.is_empty());
2214
2215        let vao = &self.vaos[vertex_array_kind];
2216        self.device.bind_vao(vao);
2217
2218        let chunk_size = if self.debug_flags.contains(DebugFlags::DISABLE_BATCHING) {
2219            1
2220        } else if vertex_array_kind == VertexArrayKind::Primitive {
2221            self.max_primitive_instance_count
2222        } else {
2223            data.len()
2224        };
2225
2226        for chunk in data.chunks(chunk_size) {
2227            if self.enable_instancing {
2228                self.device
2229                    .update_vao_instances(vao, chunk, ONE_TIME_USAGE_HINT, None);
2230                self.device
2231                    .draw_indexed_triangles_instanced_u16(6, chunk.len() as i32);
2232            } else {
2233                self.device
2234                    .update_vao_instances(vao, chunk, ONE_TIME_USAGE_HINT, NonZeroUsize::new(4));
2235                self.device
2236                    .draw_indexed_triangles(6 * chunk.len() as i32);
2237            }
2238            self.profile.inc(profiler::DRAW_CALLS);
2239            stats.total_draw_calls += 1;
2240        }
2241
2242        self.profile.add(profiler::VERTICES, 6 * data.len());
2243    }
2244
2245    fn handle_readback_composite(
2246        &mut self,
2247        draw_target: DrawTarget,
2248        uses_scissor: bool,
2249        backdrop: &RenderTask,
2250        readback: &RenderTask,
2251    ) {
2252        let readback_origin = match readback.kind {
2255            RenderTaskKind::Readback(ReadbackTask { readback_origin: Some(o), .. }) => o,
2256            RenderTaskKind::Readback(ReadbackTask { readback_origin: None, .. }) => {
2257                return;
2261            }
2262            _ => unreachable!(),
2263        };
2264
2265        if uses_scissor {
2266            self.device.disable_scissor();
2267        }
2268
2269        let texture_source = TextureSource::TextureCache(
2270            readback.get_target_texture(),
2271            Swizzle::default(),
2272        );
2273        let (cache_texture, _) = self.texture_resolver
2274            .resolve(&texture_source).expect("bug: no source texture");
2275
2276        let readback_rect = readback.get_target_rect();
2280        let backdrop_rect = backdrop.get_target_rect();
2281        let (backdrop_screen_origin, _) = match backdrop.kind {
2282            RenderTaskKind::Picture(ref task_info) => (task_info.content_origin, task_info.device_pixel_scale),
2283            _ => panic!("bug: composite on non-picture?"),
2284        };
2285
2286        let cache_draw_target = DrawTarget::from_texture(
2290            cache_texture,
2291            false,
2292        );
2293
2294        let wanted_rect = DeviceRect::from_origin_and_size(
2296            readback_origin,
2297            readback_rect.size().to_f32(),
2298        );
2299
2300        let avail_rect = DeviceRect::from_origin_and_size(
2304            backdrop_screen_origin,
2305            backdrop_rect.size().to_f32(),
2306        );
2307
2308        if let Some(int_rect) = wanted_rect.intersection(&avail_rect) {
2309            let copy_size = int_rect.size().to_i32();
2312
2313            let src_origin = backdrop_rect.min.to_f32() +
2314                int_rect.min.to_vector() -
2315                backdrop_screen_origin.to_vector();
2316
2317            let src = DeviceIntRect::from_origin_and_size(
2318                src_origin.to_i32(),
2319                copy_size,
2320            );
2321
2322            let dest_origin = readback_rect.min.to_f32() +
2323                int_rect.min.to_vector() -
2324                readback_origin.to_vector();
2325
2326            let dest = DeviceIntRect::from_origin_and_size(
2327                dest_origin.to_i32(),
2328                copy_size,
2329            );
2330
2331            debug_assert!(!draw_target.is_default());
2333            let device_to_framebuffer = Scale::new(1i32);
2334
2335            self.device.blit_render_target(
2336                draw_target.into(),
2337                src * device_to_framebuffer,
2338                cache_draw_target,
2339                dest * device_to_framebuffer,
2340                TextureFilter::Linear,
2341            );
2342        }
2343
2344        self.device.bind_draw_target(draw_target);
2347        self.device.reset_read_target();
2348
2349        if uses_scissor {
2350            self.device.enable_scissor();
2351        }
2352    }
2353
2354    fn handle_resolves(
2355        &mut self,
2356        resolve_ops: &[ResolveOp],
2357        render_tasks: &RenderTaskGraph,
2358        draw_target: DrawTarget,
2359    ) {
2360        if resolve_ops.is_empty() {
2361            return;
2362        }
2363
2364        let _timer = self.gpu_profiler.start_timer(GPU_TAG_BLIT);
2365
2366        for resolve_op in resolve_ops {
2367            self.handle_resolve(
2368                resolve_op,
2369                render_tasks,
2370                draw_target,
2371            );
2372        }
2373
2374        self.device.reset_read_target();
2375    }
2376
2377    fn handle_prims(
2378        &mut self,
2379        draw_target: &DrawTarget,
2380        prim_instances: &[FastHashMap<TextureSource, FrameVec<PrimitiveInstanceData>>],
2381        prim_instances_with_scissor: &FastHashMap<(DeviceIntRect, PatternKind), FastHashMap<TextureSource, FrameVec<PrimitiveInstanceData>>>,
2382        projection: &default::Transform3D<f32>,
2383        stats: &mut RendererStats,
2384    ) {
2385        self.device.disable_depth_write();
2386
2387        let has_prim_instances = prim_instances.iter().any(|map| !map.is_empty());
2388        if has_prim_instances || !prim_instances_with_scissor.is_empty() {
2389            let _timer = self.gpu_profiler.start_timer(GPU_TAG_INDIRECT_PRIM);
2390
2391            self.set_blend(false, FramebufferKind::Other);
2392
2393            for (pattern_idx, prim_instances_map) in prim_instances.iter().enumerate() {
2394                if prim_instances_map.is_empty() {
2395                    continue;
2396                }
2397                let pattern = PatternKind::from_u32(pattern_idx as u32);
2398
2399                self.shaders.borrow_mut().get_quad_shader(pattern).bind(
2400                    &mut self.device,
2401                    projection,
2402                    None,
2403                    &mut self.renderer_errors,
2404                    &mut self.profile,
2405                );
2406
2407                for (texture_source, prim_instances) in prim_instances_map {
2408                    let texture_bindings = BatchTextures::composite_rgb(*texture_source);
2409
2410                    self.draw_instanced_batch(
2411                        prim_instances,
2412                        VertexArrayKind::Primitive,
2413                        &texture_bindings,
2414                        stats,
2415                    );
2416                }
2417            }
2418
2419            if !prim_instances_with_scissor.is_empty() {
2420                self.set_blend(true, FramebufferKind::Other);
2421                self.device.set_blend_mode_premultiplied_alpha();
2422                self.device.enable_scissor();
2423
2424                let mut prev_pattern = None;
2425
2426                for ((scissor_rect, pattern), prim_instances_map) in prim_instances_with_scissor {
2427                    if prev_pattern != Some(*pattern) {
2428                        prev_pattern = Some(*pattern);
2429                        self.shaders.borrow_mut().get_quad_shader(*pattern).bind(
2430                            &mut self.device,
2431                            projection,
2432                            None,
2433                            &mut self.renderer_errors,
2434                            &mut self.profile,
2435                        );
2436                    }
2437
2438                    self.device.set_scissor_rect(draw_target.to_framebuffer_rect(*scissor_rect));
2439
2440                    for (texture_source, prim_instances) in prim_instances_map {
2441                        let texture_bindings = BatchTextures::composite_rgb(*texture_source);
2442
2443                        self.draw_instanced_batch(
2444                            prim_instances,
2445                            VertexArrayKind::Primitive,
2446                            &texture_bindings,
2447                            stats,
2448                        );
2449                    }
2450                }
2451
2452                self.device.disable_scissor();
2453            }
2454        }
2455    }
2456
2457    fn handle_clips(
2458        &mut self,
2459        draw_target: &DrawTarget,
2460        masks: &ClipMaskInstanceList,
2461        projection: &default::Transform3D<f32>,
2462        stats: &mut RendererStats,
2463    ) {
2464        self.device.disable_depth_write();
2465
2466        {
2467            let _timer = self.gpu_profiler.start_timer(GPU_TAG_INDIRECT_MASK);
2468
2469            self.set_blend(true, FramebufferKind::Other);
2470            self.set_blend_mode_multiply(FramebufferKind::Other);
2471
2472            if !masks.mask_instances_fast.is_empty() {
2473                self.shaders.borrow_mut().ps_mask_fast().bind(
2474                    &mut self.device,
2475                    projection,
2476                    None,
2477                    &mut self.renderer_errors,
2478                    &mut self.profile,
2479                );
2480
2481                self.draw_instanced_batch(
2482                    &masks.mask_instances_fast,
2483                    VertexArrayKind::Mask,
2484                    &BatchTextures::empty(),
2485                    stats,
2486                );
2487            }
2488
2489            if !masks.mask_instances_fast_with_scissor.is_empty() {
2490                self.shaders.borrow_mut().ps_mask_fast().bind(
2491                    &mut self.device,
2492                    projection,
2493                    None,
2494                    &mut self.renderer_errors,
2495                    &mut self.profile,
2496                );
2497
2498                self.device.enable_scissor();
2499
2500                for (scissor_rect, instances) in &masks.mask_instances_fast_with_scissor {
2501                    self.device.set_scissor_rect(draw_target.to_framebuffer_rect(*scissor_rect));
2502
2503                    self.draw_instanced_batch(
2504                        instances,
2505                        VertexArrayKind::Mask,
2506                        &BatchTextures::empty(),
2507                        stats,
2508                    );
2509                }
2510
2511                self.device.disable_scissor();
2512            }
2513
2514            if !masks.image_mask_instances.is_empty() {
2515                self.shaders.borrow_mut().ps_quad_textured().bind(
2516                    &mut self.device,
2517                    projection,
2518                    None,
2519                    &mut self.renderer_errors,
2520                    &mut self.profile,
2521                );
2522
2523                for (texture, prim_instances) in &masks.image_mask_instances {
2524                    self.draw_instanced_batch(
2525                        prim_instances,
2526                        VertexArrayKind::Primitive,
2527                        &BatchTextures::composite_rgb(*texture),
2528                        stats,
2529                    );
2530                }
2531            }
2532
2533            if !masks.image_mask_instances_with_scissor.is_empty() {
2534                self.device.enable_scissor();
2535
2536                self.shaders.borrow_mut().ps_quad_textured().bind(
2537                    &mut self.device,
2538                    projection,
2539                    None,
2540                    &mut self.renderer_errors,
2541                    &mut self.profile,
2542                );
2543
2544                for ((scissor_rect, texture), prim_instances) in &masks.image_mask_instances_with_scissor {
2545                    self.device.set_scissor_rect(draw_target.to_framebuffer_rect(*scissor_rect));
2546
2547                    self.draw_instanced_batch(
2548                        prim_instances,
2549                        VertexArrayKind::Primitive,
2550                        &BatchTextures::composite_rgb(*texture),
2551                        stats,
2552                    );
2553                }
2554
2555                self.device.disable_scissor();
2556            }
2557
2558            if !masks.mask_instances_slow.is_empty() {
2559                self.shaders.borrow_mut().ps_mask().bind(
2560                    &mut self.device,
2561                    projection,
2562                    None,
2563                    &mut self.renderer_errors,
2564                    &mut self.profile,
2565                );
2566
2567                self.draw_instanced_batch(
2568                    &masks.mask_instances_slow,
2569                    VertexArrayKind::Mask,
2570                    &BatchTextures::empty(),
2571                    stats,
2572                );
2573            }
2574
2575            if !masks.mask_instances_slow_with_scissor.is_empty() {
2576                self.shaders.borrow_mut().ps_mask().bind(
2577                    &mut self.device,
2578                    projection,
2579                    None,
2580                    &mut self.renderer_errors,
2581                    &mut self.profile,
2582                );
2583
2584                self.device.enable_scissor();
2585
2586                for (scissor_rect, instances) in &masks.mask_instances_slow_with_scissor {
2587                    self.device.set_scissor_rect(draw_target.to_framebuffer_rect(*scissor_rect));
2588
2589                    self.draw_instanced_batch(
2590                        instances,
2591                        VertexArrayKind::Mask,
2592                        &BatchTextures::empty(),
2593                        stats,
2594                    );
2595                }
2596
2597                self.device.disable_scissor();
2598            }
2599        }
2600    }
2601
2602    fn handle_blits(
2603        &mut self,
2604        blits: &[BlitJob],
2605        render_tasks: &RenderTaskGraph,
2606        draw_target: DrawTarget,
2607    ) {
2608        if blits.is_empty() {
2609            return;
2610        }
2611
2612        let _timer = self.gpu_profiler.start_timer(GPU_TAG_BLIT);
2613
2614        for blit in blits {
2617            let (source, source_rect) = {
2618                let task = &render_tasks[blit.source];
2622                let source_rect = blit.source_rect.translate(task.get_target_rect().min.to_vector());
2623                let source_texture = task.get_texture_source();
2624
2625                (source_texture, source_rect)
2626            };
2627
2628            let (texture, swizzle) = self.texture_resolver
2629                .resolve(&source)
2630                .expect("BUG: invalid source texture");
2631
2632            if swizzle != Swizzle::default() {
2633                error!("Swizzle {:?} can't be handled by a blit", swizzle);
2634            }
2635
2636            let read_target = DrawTarget::from_texture(
2637                texture,
2638                false,
2639            );
2640
2641            self.device.blit_render_target(
2642                read_target.into(),
2643                read_target.to_framebuffer_rect(source_rect),
2644                draw_target,
2645                draw_target.to_framebuffer_rect(blit.target_rect),
2646                TextureFilter::Linear,
2647            );
2648        }
2649    }
2650
2651    fn handle_scaling(
2652        &mut self,
2653        scalings: &FastHashMap<TextureSource, FrameVec<ScalingInstance>>,
2654        projection: &default::Transform3D<f32>,
2655        stats: &mut RendererStats,
2656    ) {
2657        if scalings.is_empty() {
2658            return
2659        }
2660
2661        let _timer = self.gpu_profiler.start_timer(GPU_TAG_SCALE);
2662        for (source, instances) in scalings {
2663            let buffer_kind = source.image_buffer_kind();
2664
2665            let uv_override_instances;
2670            let instances = match source {
2671                TextureSource::External(..) => {
2672                    uv_override_instances = instances.iter().map(|instance| {
2673                        let mut new_instance = instance.clone();
2674                        let texel_rect: TexelRect = self.texture_resolver.get_uv_rect(
2675                            &source,
2676                            instance.source_rect.cast().into()
2677                        ).into();
2678                        new_instance.source_rect = DeviceRect::new(texel_rect.uv0, texel_rect.uv1);
2679                        new_instance
2680                    }).collect::<Vec<_>>();
2681                    uv_override_instances.as_slice()
2682                }
2683                _ => instances.as_slice()
2684            };
2685
2686            self.shaders
2687                .borrow_mut()
2688                .get_scale_shader(buffer_kind)
2689                .bind(
2690                    &mut self.device,
2691                    &projection,
2692                    Some(self.texture_resolver.get_texture_size(source).to_f32()),
2693                    &mut self.renderer_errors,
2694                    &mut self.profile,
2695                );
2696
2697            self.draw_instanced_batch(
2698                instances,
2699                VertexArrayKind::Scale,
2700                &BatchTextures::composite_rgb(*source),
2701                stats,
2702            );
2703        }
2704    }
2705
2706    fn handle_svg_filters(
2707        &mut self,
2708        textures: &BatchTextures,
2709        svg_filters: &[SvgFilterInstance],
2710        projection: &default::Transform3D<f32>,
2711        stats: &mut RendererStats,
2712    ) {
2713        if svg_filters.is_empty() {
2714            return;
2715        }
2716
2717        let _timer = self.gpu_profiler.start_timer(GPU_TAG_SVG_FILTER);
2718
2719        self.shaders.borrow_mut().cs_svg_filter().bind(
2720            &mut self.device,
2721            &projection,
2722            None,
2723            &mut self.renderer_errors,
2724            &mut self.profile,
2725        );
2726
2727        self.draw_instanced_batch(
2728            &svg_filters,
2729            VertexArrayKind::SvgFilter,
2730            textures,
2731            stats,
2732        );
2733    }
2734
2735    fn handle_svg_nodes(
2736        &mut self,
2737        textures: &BatchTextures,
2738        svg_filters: &[SVGFEFilterInstance],
2739        projection: &default::Transform3D<f32>,
2740        stats: &mut RendererStats,
2741    ) {
2742        if svg_filters.is_empty() {
2743            return;
2744        }
2745
2746        let _timer = self.gpu_profiler.start_timer(GPU_TAG_SVG_FILTER_NODES);
2747
2748        self.shaders.borrow_mut().cs_svg_filter_node().bind(
2749            &mut self.device,
2750            &projection,
2751            None,
2752            &mut self.renderer_errors,
2753            &mut self.profile,
2754        );
2755
2756        self.draw_instanced_batch(
2757            &svg_filters,
2758            VertexArrayKind::SvgFilterNode,
2759            textures,
2760            stats,
2761        );
2762    }
2763
2764    fn handle_resolve(
2765        &mut self,
2766        resolve_op: &ResolveOp,
2767        render_tasks: &RenderTaskGraph,
2768        draw_target: DrawTarget,
2769    ) {
2770        for src_task_id in &resolve_op.src_task_ids {
2771            let src_task = &render_tasks[*src_task_id];
2772            let src_info = match src_task.kind {
2773                RenderTaskKind::Picture(ref info) => info,
2774                _ => panic!("bug: not a picture"),
2775            };
2776            let src_task_rect = src_task.get_target_rect().to_f32();
2777
2778            let dest_task = &render_tasks[resolve_op.dest_task_id];
2779            let dest_info = match dest_task.kind {
2780                RenderTaskKind::Picture(ref info) => info,
2781                _ => panic!("bug: not a picture"),
2782            };
2783            let dest_task_rect = dest_task.get_target_rect().to_f32();
2784
2785            let dest_task_rect = DeviceRect::from_origin_and_size(
2791                dest_task_rect.min,
2792                dest_info.content_size.to_f32(),
2793            );
2794
2795            let wanted_rect = DeviceRect::from_origin_and_size(
2797                dest_info.content_origin,
2798                dest_task_rect.size().to_f32(),
2799            ).cast_unit() * dest_info.device_pixel_scale.inverse();
2800
2801            let avail_rect = DeviceRect::from_origin_and_size(
2805                src_info.content_origin,
2806                src_task_rect.size().to_f32(),
2807            ).cast_unit() * src_info.device_pixel_scale.inverse();
2808
2809            if let Some(device_int_rect) = wanted_rect.intersection(&avail_rect) {
2810                let src_int_rect = (device_int_rect * src_info.device_pixel_scale).cast_unit();
2811                let dest_int_rect = (device_int_rect * dest_info.device_pixel_scale).cast_unit();
2812
2813                let src_origin = src_task_rect.min.to_f32() +
2817                    src_int_rect.min.to_vector() -
2818                    src_info.content_origin.to_vector();
2819
2820                let src = DeviceIntRect::from_origin_and_size(
2821                    src_origin.to_i32(),
2822                    src_int_rect.size().round().to_i32(),
2823                );
2824
2825                let dest_origin = dest_task_rect.min.to_f32() +
2826                    dest_int_rect.min.to_vector() -
2827                    dest_info.content_origin.to_vector();
2828
2829                let dest = DeviceIntRect::from_origin_and_size(
2830                    dest_origin.to_i32(),
2831                    dest_int_rect.size().round().to_i32(),
2832                );
2833
2834                let texture_source = TextureSource::TextureCache(
2835                    src_task.get_target_texture(),
2836                    Swizzle::default(),
2837                );
2838                let (cache_texture, _) = self.texture_resolver
2839                    .resolve(&texture_source).expect("bug: no source texture");
2840
2841                let read_target = ReadTarget::from_texture(cache_texture);
2842
2843                debug_assert!(!draw_target.is_default());
2845                let device_to_framebuffer = Scale::new(1i32);
2846
2847                self.device.blit_render_target(
2848                    read_target,
2849                    src * device_to_framebuffer,
2850                    draw_target,
2851                    dest * device_to_framebuffer,
2852                    TextureFilter::Linear,
2853                );
2854            }
2855        }
2856    }
2857
2858    fn draw_picture_cache_target(
2859        &mut self,
2860        target: &PictureCacheTarget,
2861        draw_target: DrawTarget,
2862        projection: &default::Transform3D<f32>,
2863        render_tasks: &RenderTaskGraph,
2864        stats: &mut RendererStats,
2865    ) {
2866        profile_scope!("draw_picture_cache_target");
2867
2868        self.profile.inc(profiler::RENDERED_PICTURE_TILES);
2869        let _gm = self.gpu_profiler.start_marker("picture cache target");
2870        let framebuffer_kind = FramebufferKind::Other;
2871
2872        {
2873            let _timer = self.gpu_profiler.start_timer(GPU_TAG_SETUP_TARGET);
2874            self.device.bind_draw_target(draw_target);
2875
2876            if self.device.get_capabilities().supports_qcom_tiled_rendering {
2877                self.device.gl().start_tiling_qcom(
2878                    target.dirty_rect.min.x.max(0) as _,
2879                    target.dirty_rect.min.y.max(0) as _,
2880                    target.dirty_rect.width() as _,
2881                    target.dirty_rect.height() as _,
2882                    0,
2883                );
2884            }
2885
2886            self.device.enable_depth_write();
2887            self.set_blend(false, framebuffer_kind);
2888
2889            let clear_color = target.clear_color.map(|c| c.to_array());
2890            let scissor_rect = if self.device.get_capabilities().supports_render_target_partial_update
2891                && (target.dirty_rect != target.valid_rect
2892                    || self.device.get_capabilities().prefers_clear_scissor)
2893            {
2894                Some(target.dirty_rect)
2895            } else {
2896                None
2897            };
2898            match scissor_rect {
2899                Some(r) if self.clear_caches_with_quads => {
2902                    self.device.enable_depth(DepthFunction::Always);
2903                    let old_draw_call_count = stats.total_draw_calls;
2905                    if clear_color.is_none() {
2906                        self.device.disable_color_write();
2907                    }
2908                    let instance = ClearInstance {
2909                        rect: [
2910                            r.min.x as f32, r.min.y as f32,
2911                            r.max.x as f32, r.max.y as f32,
2912                        ],
2913                        color: clear_color.unwrap_or([0.0; 4]),
2914                    };
2915                    self.shaders.borrow_mut().ps_clear().bind(
2916                        &mut self.device,
2917                        &projection,
2918                        None,
2919                        &mut self.renderer_errors,
2920                        &mut self.profile,
2921                    );
2922                    self.draw_instanced_batch(
2923                        &[instance],
2924                        VertexArrayKind::Clear,
2925                        &BatchTextures::empty(),
2926                        stats,
2927                    );
2928                    if clear_color.is_none() {
2929                        self.device.enable_color_write();
2930                    }
2931                    stats.total_draw_calls = old_draw_call_count;
2932                    self.device.disable_depth();
2933                }
2934                other => {
2935                    let scissor_rect = other.map(|rect| {
2936                        draw_target.build_scissor_rect(Some(rect))
2937                    });
2938                    self.device.clear_target(clear_color, Some(1.0), scissor_rect);
2939                }
2940            };
2941            self.device.disable_depth_write();
2942        }
2943
2944        match target.kind {
2945            PictureCacheTargetKind::Draw { ref alpha_batch_container } => {
2946                self.draw_alpha_batch_container(
2947                    alpha_batch_container,
2948                    draw_target,
2949                    framebuffer_kind,
2950                    projection,
2951                    render_tasks,
2952                    stats,
2953                );
2954            }
2955            PictureCacheTargetKind::Blit { task_id, sub_rect_offset } => {
2956                let src_task = &render_tasks[task_id];
2957                let (texture, _swizzle) = self.texture_resolver
2958                    .resolve(&src_task.get_texture_source())
2959                    .expect("BUG: invalid source texture");
2960
2961                let src_task_rect = src_task.get_target_rect();
2962
2963                let p0 = src_task_rect.min + sub_rect_offset;
2964                let p1 = p0 + target.dirty_rect.size();
2965                let src_rect = DeviceIntRect::new(p0, p1);
2966
2967                let target_rect = target
2971                    .dirty_rect
2972                    .translate(draw_target.offset().to_vector())
2973                    .cast_unit();
2974
2975                self.device.blit_render_target(
2976                    ReadTarget::from_texture(texture),
2977                    src_rect.cast_unit(),
2978                    draw_target,
2979                    target_rect,
2980                    TextureFilter::Nearest,
2981                );
2982            }
2983        }
2984
2985        self.device.invalidate_depth_target();
2986        if self.device.get_capabilities().supports_qcom_tiled_rendering {
2987            self.device.gl().end_tiling_qcom(gl::COLOR_BUFFER_BIT0_QCOM);
2988        }
2989    }
2990
2991    fn draw_alpha_batch_container(
2994        &mut self,
2995        alpha_batch_container: &AlphaBatchContainer,
2996        draw_target: DrawTarget,
2997        framebuffer_kind: FramebufferKind,
2998        projection: &default::Transform3D<f32>,
2999        render_tasks: &RenderTaskGraph,
3000        stats: &mut RendererStats,
3001    ) {
3002        let uses_scissor = alpha_batch_container.task_scissor_rect.is_some();
3003
3004        if uses_scissor {
3005            self.device.enable_scissor();
3006            let scissor_rect = draw_target.build_scissor_rect(
3007                alpha_batch_container.task_scissor_rect,
3008            );
3009            self.device.set_scissor_rect(scissor_rect)
3010        }
3011
3012        if !alpha_batch_container.opaque_batches.is_empty()
3013            && !self.debug_flags.contains(DebugFlags::DISABLE_OPAQUE_PASS) {
3014            let _gl = self.gpu_profiler.start_marker("opaque batches");
3015            let opaque_sampler = self.gpu_profiler.start_sampler(GPU_SAMPLER_TAG_OPAQUE);
3016            self.set_blend(false, framebuffer_kind);
3017            self.device.enable_depth(DepthFunction::LessEqual);
3019            self.device.enable_depth_write();
3020
3021            for batch in alpha_batch_container
3024                .opaque_batches
3025                .iter()
3026                .rev()
3027                {
3028                    if should_skip_batch(&batch.key.kind, self.debug_flags) {
3029                        continue;
3030                    }
3031
3032                    self.shaders.borrow_mut()
3033                        .get(&batch.key, batch.features, self.debug_flags, &self.device)
3034                        .bind(
3035                            &mut self.device, projection, None,
3036                            &mut self.renderer_errors,
3037                            &mut self.profile,
3038                        );
3039
3040                    let _timer = self.gpu_profiler.start_timer(batch.key.kind.sampler_tag());
3041                    self.draw_instanced_batch(
3042                        &batch.instances,
3043                        VertexArrayKind::Primitive,
3044                        &batch.key.textures,
3045                        stats
3046                    );
3047                }
3048
3049            self.device.disable_depth_write();
3050            self.gpu_profiler.finish_sampler(opaque_sampler);
3051        } else {
3052            self.device.disable_depth();
3053        }
3054
3055        if !alpha_batch_container.alpha_batches.is_empty()
3056            && !self.debug_flags.contains(DebugFlags::DISABLE_ALPHA_PASS) {
3057            let _gl = self.gpu_profiler.start_marker("alpha batches");
3058            let transparent_sampler = self.gpu_profiler.start_sampler(GPU_SAMPLER_TAG_TRANSPARENT);
3059            self.set_blend(true, framebuffer_kind);
3060
3061            let mut prev_blend_mode = BlendMode::None;
3062            let shaders_rc = self.shaders.clone();
3063
3064            for batch in &alpha_batch_container.alpha_batches {
3065                if should_skip_batch(&batch.key.kind, self.debug_flags) {
3066                    continue;
3067                }
3068
3069                let mut shaders = shaders_rc.borrow_mut();
3070                let shader = shaders.get(
3071                    &batch.key,
3072                    batch.features | BatchFeatures::ALPHA_PASS,
3073                    self.debug_flags,
3074                    &self.device,
3075                );
3076
3077                if batch.key.blend_mode != prev_blend_mode {
3078                    match batch.key.blend_mode {
3079                        _ if self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) &&
3080                            framebuffer_kind == FramebufferKind::Main => {
3081                            self.device.set_blend_mode_show_overdraw();
3082                        }
3083                        BlendMode::None => {
3084                            unreachable!("bug: opaque blend in alpha pass");
3085                        }
3086                        BlendMode::Alpha => {
3087                            self.device.set_blend_mode_alpha();
3088                        }
3089                        BlendMode::PremultipliedAlpha => {
3090                            self.device.set_blend_mode_premultiplied_alpha();
3091                        }
3092                        BlendMode::PremultipliedDestOut => {
3093                            self.device.set_blend_mode_premultiplied_dest_out();
3094                        }
3095                        BlendMode::SubpixelDualSource => {
3096                            self.device.set_blend_mode_subpixel_dual_source();
3097                        }
3098                        BlendMode::Advanced(mode) => {
3099                            if self.enable_advanced_blend_barriers {
3100                                self.device.gl().blend_barrier_khr();
3101                            }
3102                            self.device.set_blend_mode_advanced(mode);
3103                        }
3104                        BlendMode::MultiplyDualSource => {
3105                            self.device.set_blend_mode_multiply_dual_source();
3106                        }
3107                        BlendMode::Screen => {
3108                            self.device.set_blend_mode_screen();
3109                        }
3110                        BlendMode::Exclusion => {
3111                            self.device.set_blend_mode_exclusion();
3112                        }
3113                        BlendMode::PlusLighter => {
3114                            self.device.set_blend_mode_plus_lighter();
3115                        }
3116                    }
3117                    prev_blend_mode = batch.key.blend_mode;
3118                }
3119
3120                if let BatchKind::Brush(BrushBatchKind::MixBlend { task_id, backdrop_id }) = batch.key.kind {
3122                    debug_assert_eq!(batch.instances.len(), 1);
3125                    self.handle_readback_composite(
3126                        draw_target,
3127                        uses_scissor,
3128                        &render_tasks[task_id],
3129                        &render_tasks[backdrop_id],
3130                    );
3131                }
3132
3133                let _timer = self.gpu_profiler.start_timer(batch.key.kind.sampler_tag());
3134                shader.bind(
3135                    &mut self.device,
3136                    projection,
3137                    None,
3138                    &mut self.renderer_errors,
3139                    &mut self.profile,
3140                );
3141
3142                self.draw_instanced_batch(
3143                    &batch.instances,
3144                    VertexArrayKind::Primitive,
3145                    &batch.key.textures,
3146                    stats
3147                );
3148            }
3149
3150            self.set_blend(false, framebuffer_kind);
3151            self.gpu_profiler.finish_sampler(transparent_sampler);
3152        }
3153
3154        self.device.disable_depth();
3155        if uses_scissor {
3156            self.device.disable_scissor();
3157        }
3158    }
3159
3160    fn update_external_native_surfaces(
3162        &mut self,
3163        external_surfaces: &[ResolvedExternalSurface],
3164        results: &mut RenderResults,
3165    ) {
3166        if external_surfaces.is_empty() {
3167            return;
3168        }
3169
3170        let opaque_sampler = self.gpu_profiler.start_sampler(GPU_SAMPLER_TAG_OPAQUE);
3171
3172        self.device.disable_depth();
3173        self.set_blend(false, FramebufferKind::Main);
3174
3175        for surface in external_surfaces {
3176            let (native_surface_id, surface_size) = match surface.update_params {
3178                Some(params) => params,
3179                None => continue,
3180            };
3181
3182            let surface_rect = surface_size.into();
3185
3186            let surface_info = self.compositor_config
3188                .compositor()
3189                .unwrap()
3190                .bind(
3191                    &mut self.device,
3192                    NativeTileId {
3193                        surface_id: native_surface_id,
3194                        x: 0,
3195                        y: 0,
3196                    },
3197                    surface_rect,
3198                    surface_rect,
3199                );
3200
3201            let draw_target = DrawTarget::NativeSurface {
3203                offset: surface_info.origin,
3204                external_fbo_id: surface_info.fbo_id,
3205                dimensions: surface_size,
3206            };
3207            self.device.bind_draw_target(draw_target);
3208
3209            let projection = Transform3D::ortho(
3210                0.0,
3211                surface_size.width as f32,
3212                0.0,
3213                surface_size.height as f32,
3214                self.device.ortho_near_plane(),
3215                self.device.ortho_far_plane(),
3216            );
3217
3218            let ( textures, instance ) = match surface.color_data {
3219                ResolvedExternalSurfaceColorData::Yuv{
3220                        ref planes, color_space, format, channel_bit_depth, .. } => {
3221
3222                    let textures = BatchTextures::composite_yuv(
3223                        planes[0].texture,
3224                        planes[1].texture,
3225                        planes[2].texture,
3226                    );
3227
3228                    let uv_rects = [
3234                        self.texture_resolver.get_uv_rect(&textures.input.colors[0], planes[0].uv_rect),
3235                        self.texture_resolver.get_uv_rect(&textures.input.colors[1], planes[1].uv_rect),
3236                        self.texture_resolver.get_uv_rect(&textures.input.colors[2], planes[2].uv_rect),
3237                    ];
3238
3239                    let instance = CompositeInstance::new_yuv(
3240                        surface_rect.to_f32(),
3241                        surface_rect.to_f32(),
3242                        color_space,
3245                        format,
3246                        channel_bit_depth,
3247                        uv_rects,
3248                        (false, false),
3249                        None,
3250                    );
3251
3252                    self.shaders
3254                        .borrow_mut()
3255                        .get_composite_shader(
3256                            CompositeSurfaceFormat::Yuv,
3257                            surface.image_buffer_kind,
3258                            instance.get_yuv_features(),
3259                        ).bind(
3260                            &mut self.device,
3261                            &projection,
3262                            None,
3263                            &mut self.renderer_errors,
3264                            &mut self.profile,
3265                        );
3266
3267                    ( textures, instance )
3268                },
3269                ResolvedExternalSurfaceColorData::Rgb{ ref plane, .. } => {
3270                    let textures = BatchTextures::composite_rgb(plane.texture);
3271                    let uv_rect = self.texture_resolver.get_uv_rect(&textures.input.colors[0], plane.uv_rect);
3272                    let instance = CompositeInstance::new_rgb(
3273                        surface_rect.to_f32(),
3274                        surface_rect.to_f32(),
3275                        PremultipliedColorF::WHITE,
3276                        uv_rect,
3277                        plane.texture.uses_normalized_uvs(),
3278                        (false, false),
3279                        None,
3280                    );
3281                    let features = instance.get_rgb_features();
3282
3283                    self.shaders
3284                        .borrow_mut()
3285                        .get_composite_shader(
3286                            CompositeSurfaceFormat::Rgba,
3287                            surface.image_buffer_kind,
3288                            features,
3289                        ).bind(
3290                            &mut self.device,
3291                            &projection,
3292                            None,
3293                            &mut self.renderer_errors,
3294                            &mut self.profile,
3295                        );
3296
3297                    ( textures, instance )
3298                },
3299            };
3300
3301            self.draw_instanced_batch(
3302                &[instance],
3303                VertexArrayKind::Composite,
3304                &textures,
3305                &mut results.stats,
3306            );
3307
3308            self.compositor_config
3309                .compositor()
3310                .unwrap()
3311                .unbind(&mut self.device);
3312        }
3313
3314        self.gpu_profiler.finish_sampler(opaque_sampler);
3315    }
3316
3317    fn draw_tile_list<'a, I: Iterator<Item = &'a occlusion::Item<OcclusionItemKey>>>(
3319        &mut self,
3320        tiles_iter: I,
3321        composite_state: &CompositeState,
3322        external_surfaces: &[ResolvedExternalSurface],
3323        projection: &default::Transform3D<f32>,
3324        stats: &mut RendererStats,
3325    ) {
3326        let mut current_shader_params = (
3327            CompositeSurfaceFormat::Rgba,
3328            ImageBufferKind::Texture2D,
3329            CompositeFeatures::empty(),
3330            None,
3331        );
3332        let mut current_textures = BatchTextures::empty();
3333        let mut instances = Vec::new();
3334
3335        self.shaders
3336            .borrow_mut()
3337            .get_composite_shader(
3338                current_shader_params.0,
3339                current_shader_params.1,
3340                current_shader_params.2,
3341            ).bind(
3342                &mut self.device,
3343                projection,
3344                None,
3345                &mut self.renderer_errors,
3346                &mut self.profile,
3347            );
3348
3349        for item in tiles_iter {
3350            let tile = &composite_state.tiles[item.key.tile_index];
3351
3352            let clip_rect = item.rectangle;
3353            let tile_rect = composite_state.get_device_rect(&tile.local_rect, tile.transform_index);
3354            let transform = composite_state.get_device_transform(tile.transform_index);
3355            let flip = (transform.scale.x < 0.0, transform.scale.y < 0.0);
3356
3357            let clip = if item.key.needs_mask {
3358                tile.clip_index.map(|index| {
3359                    composite_state.get_compositor_clip(index)
3360                })
3361            } else {
3362                None
3363            };
3364
3365            let (instance, textures, shader_params) = match tile.surface {
3367                CompositeTileSurface::Color { color } => {
3368                    let dummy = TextureSource::Dummy;
3369                    let image_buffer_kind = dummy.image_buffer_kind();
3370                    let instance = CompositeInstance::new(
3371                        tile_rect,
3372                        clip_rect,
3373                        color.premultiplied(),
3374                        flip,
3375                        clip,
3376                    );
3377                    let features = instance.get_rgb_features();
3378                    (
3379                        instance,
3380                        BatchTextures::composite_rgb(dummy),
3381                        (CompositeSurfaceFormat::Rgba, image_buffer_kind, features, None),
3382                    )
3383                }
3384                CompositeTileSurface::Texture { surface: ResolvedSurfaceTexture::TextureCache { texture } } => {
3385                    let instance = CompositeInstance::new(
3386                        tile_rect,
3387                        clip_rect,
3388                        PremultipliedColorF::WHITE,
3389                        flip,
3390                        clip,
3391                    );
3392                    let features = instance.get_rgb_features();
3393                    (
3394                        instance,
3395                        BatchTextures::composite_rgb(texture),
3396                        (
3397                            CompositeSurfaceFormat::Rgba,
3398                            ImageBufferKind::Texture2D,
3399                            features,
3400                            None,
3401                        ),
3402                    )
3403                }
3404                CompositeTileSurface::ExternalSurface { external_surface_index } => {
3405                    let surface = &external_surfaces[external_surface_index.0];
3406
3407                    match surface.color_data {
3408                        ResolvedExternalSurfaceColorData::Yuv{ ref planes, color_space, format, channel_bit_depth, .. } => {
3409                            let textures = BatchTextures::composite_yuv(
3410                                planes[0].texture,
3411                                planes[1].texture,
3412                                planes[2].texture,
3413                            );
3414
3415                            let uv_rects = [
3421                                self.texture_resolver.get_uv_rect(&textures.input.colors[0], planes[0].uv_rect),
3422                                self.texture_resolver.get_uv_rect(&textures.input.colors[1], planes[1].uv_rect),
3423                                self.texture_resolver.get_uv_rect(&textures.input.colors[2], planes[2].uv_rect),
3424                            ];
3425
3426                            let instance = CompositeInstance::new_yuv(
3427                                tile_rect,
3428                                clip_rect,
3429                                color_space,
3430                                format,
3431                                channel_bit_depth,
3432                                uv_rects,
3433                                flip,
3434                                clip,
3435                            );
3436                            let features = instance.get_yuv_features();
3437
3438                            (
3439                                instance,
3440                                textures,
3441                                (
3442                                    CompositeSurfaceFormat::Yuv,
3443                                    surface.image_buffer_kind,
3444                                    features,
3445                                    None
3446                                ),
3447                            )
3448                        },
3449                        ResolvedExternalSurfaceColorData::Rgb { ref plane, .. } => {
3450                            let uv_rect = self.texture_resolver.get_uv_rect(&plane.texture, plane.uv_rect);
3451                            let instance = CompositeInstance::new_rgb(
3452                                tile_rect,
3453                                clip_rect,
3454                                PremultipliedColorF::WHITE,
3455                                uv_rect,
3456                                plane.texture.uses_normalized_uvs(),
3457                                flip,
3458                                clip,
3459                            );
3460                            let features = instance.get_rgb_features();
3461                            (
3462                                instance,
3463                                BatchTextures::composite_rgb(plane.texture),
3464                                (
3465                                    CompositeSurfaceFormat::Rgba,
3466                                    surface.image_buffer_kind,
3467                                    features,
3468                                    Some(self.texture_resolver.get_texture_size(&plane.texture).to_f32()),
3469                                ),
3470                            )
3471                        },
3472                    }
3473                }
3474                CompositeTileSurface::Clear => {
3475                    let dummy = TextureSource::Dummy;
3476                    let image_buffer_kind = dummy.image_buffer_kind();
3477                    let instance = CompositeInstance::new(
3478                        tile_rect,
3479                        clip_rect,
3480                        PremultipliedColorF::BLACK,
3481                        flip,
3482                        clip,
3483                    );
3484                    let features = instance.get_rgb_features();
3485                    (
3486                        instance,
3487                        BatchTextures::composite_rgb(dummy),
3488                        (CompositeSurfaceFormat::Rgba, image_buffer_kind, features, None),
3489                    )
3490                }
3491                CompositeTileSurface::Texture { surface: ResolvedSurfaceTexture::Native { .. } } => {
3492                    unreachable!("bug: found native surface in simple composite path");
3493                }
3494            };
3495
3496            let flush_batch = !current_textures.is_compatible_with(&textures) ||
3498                shader_params != current_shader_params;
3499
3500            if flush_batch {
3501                if !instances.is_empty() {
3502                    self.draw_instanced_batch(
3503                        &instances,
3504                        VertexArrayKind::Composite,
3505                        ¤t_textures,
3506                        stats,
3507                    );
3508                    instances.clear();
3509                }
3510            }
3511
3512            if shader_params != current_shader_params {
3513                self.shaders
3514                    .borrow_mut()
3515                    .get_composite_shader(shader_params.0, shader_params.1, shader_params.2)
3516                    .bind(
3517                        &mut self.device,
3518                        projection,
3519                        shader_params.3,
3520                        &mut self.renderer_errors,
3521                        &mut self.profile,
3522                    );
3523
3524                current_shader_params = shader_params;
3525            }
3526
3527            current_textures = textures;
3528
3529            instances.push(instance);
3531        }
3532
3533        if !instances.is_empty() {
3535            self.draw_instanced_batch(
3536                &instances,
3537                VertexArrayKind::Composite,
3538                ¤t_textures,
3539                stats,
3540            );
3541        }
3542    }
3543
3544    fn composite_pass(
3547        &mut self,
3548        composite_state: &CompositeState,
3549        draw_target: DrawTarget,
3550        clear_color: ColorF,
3551        projection: &default::Transform3D<f32>,
3552        results: &mut RenderResults,
3553        partial_present_mode: Option<PartialPresentMode>,
3554        layer: &SwapChainLayer,
3555    ) {
3556        self.device.bind_draw_target(draw_target);
3557        self.device.disable_depth_write();
3558        self.device.disable_depth();
3559
3560        if let Some(partial_present) = self.compositor_config.partial_present() {
3566            if let Some(PartialPresentMode::Single { dirty_rect }) = partial_present_mode {
3567                partial_present.set_buffer_damage_region(&[dirty_rect.to_i32()]);
3568            }
3569        }
3570
3571        let clear_color = Some(clear_color.to_array());
3573
3574        match partial_present_mode {
3575            Some(PartialPresentMode::Single { dirty_rect }) => {
3576                if !dirty_rect.is_empty() && layer.occlusion.test(&dirty_rect) {
3581                    self.device.clear_target(clear_color,
3583                                             None,
3584                                             Some(draw_target.to_framebuffer_rect(dirty_rect.to_i32())));
3585                }
3586            }
3587            None => {
3588                self.device.clear_target(clear_color,
3590                                         None,
3591                                         None);
3592            }
3593        }
3594
3595        let opaque_items = layer.occlusion.opaque_items();
3597        if !opaque_items.is_empty() {
3598            let opaque_sampler = self.gpu_profiler.start_sampler(GPU_SAMPLER_TAG_OPAQUE);
3599            self.set_blend(false, FramebufferKind::Main);
3600            self.draw_tile_list(
3601                opaque_items.iter(),
3602                &composite_state,
3603                &composite_state.external_surfaces,
3604                projection,
3605                &mut results.stats,
3606            );
3607            self.gpu_profiler.finish_sampler(opaque_sampler);
3608        }
3609
3610        if !layer.clear_tiles.is_empty() {
3612            let transparent_sampler = self.gpu_profiler.start_sampler(GPU_SAMPLER_TAG_TRANSPARENT);
3613            self.set_blend(true, FramebufferKind::Main);
3614            self.device.set_blend_mode_premultiplied_dest_out();
3615            self.draw_tile_list(
3616                layer.clear_tiles.iter(),
3617                &composite_state,
3618                &composite_state.external_surfaces,
3619                projection,
3620                &mut results.stats,
3621            );
3622            self.gpu_profiler.finish_sampler(transparent_sampler);
3623        }
3624
3625        let alpha_items = layer.occlusion.alpha_items();
3627        if !alpha_items.is_empty() {
3628            let transparent_sampler = self.gpu_profiler.start_sampler(GPU_SAMPLER_TAG_TRANSPARENT);
3629            self.set_blend(true, FramebufferKind::Main);
3630            self.set_blend_mode_premultiplied_alpha(FramebufferKind::Main);
3631            self.draw_tile_list(
3632                alpha_items.iter().rev(),
3633                &composite_state,
3634                &composite_state.external_surfaces,
3635                projection,
3636                &mut results.stats,
3637            );
3638            self.gpu_profiler.finish_sampler(transparent_sampler);
3639        }
3640    }
3641
3642    fn composite_simple(
3647        &mut self,
3648        composite_state: &CompositeState,
3649        frame_device_size: DeviceIntSize,
3650        fb_draw_target: DrawTarget,
3651        projection: &default::Transform3D<f32>,
3652        results: &mut RenderResults,
3653        partial_present_mode: Option<PartialPresentMode>,
3654        device_size: DeviceIntSize,
3655    ) {
3656        let _gm = self.gpu_profiler.start_marker("framebuffer");
3657        let _timer = self.gpu_profiler.start_timer(GPU_TAG_COMPOSITE);
3658
3659        let num_tiles = composite_state.tiles
3662            .iter()
3663            .filter(|tile| tile.kind != TileKind::Clear).count();
3664        self.profile.set(profiler::PICTURE_TILES, num_tiles);
3665
3666        let (window_is_opaque, enable_screenshot)  = match self.compositor_config.layer_compositor() {
3667            Some(ref compositor) => {
3668                let props = compositor.get_window_properties();
3669                (props.is_opaque, props.enable_screenshot)
3670            }
3671            None => (true, true)
3672        };
3673
3674        let mut input_layers: Vec<CompositorInputLayer> = Vec::new();
3675        let mut swapchain_layers = Vec::new();
3676        let cap = composite_state.tiles.len();
3677        let mut segment_builder = SegmentBuilder::new();
3678        let mut tile_index_to_layer_index = vec![None; composite_state.tiles.len()];
3679        let mut full_render_occlusion = occlusion::FrontToBackBuilder::with_capacity(cap, cap);
3680        let mut layer_compositor_frame_state = LayerCompositorFrameState{
3681            tile_states: FastHashMap::default(),
3682            rects_without_id: Vec::new(),
3683        };
3684
3685        if self.debug_overlay_state.is_enabled {
3689            self.debug_overlay_state.layer_index = input_layers.len();
3690
3691            input_layers.push(CompositorInputLayer {
3692                usage: CompositorSurfaceUsage::DebugOverlay,
3693                is_opaque: false,
3694                offset: DeviceIntPoint::zero(),
3695                clip_rect: device_size.into(),
3696            });
3697
3698            swapchain_layers.push(SwapChainLayer {
3699                clear_tiles: Vec::new(),
3700                occlusion: occlusion::FrontToBackBuilder::with_capacity(cap, cap),
3701            });
3702        }
3703
3704        for (idx, tile) in composite_state.tiles.iter().enumerate() {
3707            let device_tile_box = composite_state.get_device_rect(
3708                &tile.local_rect,
3709                tile.transform_index
3710            );
3711
3712            if let Some(ref _compositor) = self.compositor_config.layer_compositor() {
3713                match tile.tile_id {
3714                    Some(tile_id) => {
3715                        layer_compositor_frame_state.
3716                            tile_states
3717                            .insert(
3718                            tile_id,
3719                            CompositeTileState {
3720                                local_rect: tile.local_rect,
3721                                local_valid_rect: tile.local_valid_rect,
3722                                device_clip_rect: tile.device_clip_rect,
3723                                z_id: tile.z_id,
3724                                device_tile_box: device_tile_box,
3725                                visible_rects: Vec::new(),
3726                            },
3727                        );
3728                    }
3729                    None => {}
3730                }
3731            }
3732
3733            let device_valid_rect = composite_state
3735                .get_device_rect(&tile.local_valid_rect, tile.transform_index);
3736
3737            let rect = device_tile_box
3738                .intersection_unchecked(&tile.device_clip_rect)
3739                .intersection_unchecked(&device_valid_rect);
3740
3741            if rect.is_empty() {
3742                continue;
3743            }
3744
3745            let usage = match tile.surface {
3747                CompositeTileSurface::Texture { .. } |
3748                CompositeTileSurface::Color { .. } |
3749                CompositeTileSurface::Clear => {
3750                    CompositorSurfaceUsage::Content
3751                }
3752                CompositeTileSurface::ExternalSurface { external_surface_index } => {
3753                    match (self.current_compositor_kind, enable_screenshot) {
3754                        (CompositorKind::Native { .. }, _) | (CompositorKind::Draw { .. }, _) => {
3755                            CompositorSurfaceUsage::Content
3756                        }
3757                        (CompositorKind::Layer { .. }, true) => {
3758                            CompositorSurfaceUsage::Content
3759                        }
3760                        (CompositorKind::Layer { .. }, false) => {
3761                            let surface = &composite_state.external_surfaces[external_surface_index.0];
3762
3763                            match surface.external_image_id {
3767                                Some(external_image_id) => {
3768                                    let image_key = match surface.color_data {
3769                                        ResolvedExternalSurfaceColorData::Rgb { image_dependency, .. } => image_dependency.key,
3770                                        ResolvedExternalSurfaceColorData::Yuv { image_dependencies, .. } => image_dependencies[0].key,
3771                                    };
3772
3773                                    CompositorSurfaceUsage::External {
3774                                        image_key,
3775                                        external_image_id,
3776                                        transform_index: tile.transform_index,
3777                                    }
3778                                }
3779                                None => {
3780                                    CompositorSurfaceUsage::Content
3781                                }
3782                            }
3783                        }
3784                    }
3785                }
3786            };
3787
3788            if let Some(ref _compositor) = self.compositor_config.layer_compositor() {
3789                if let CompositeTileSurface::ExternalSurface { .. } = tile.surface {
3790                    assert!(tile.tile_id.is_none());
3791                    if let CompositorSurfaceUsage::Content = usage {
3793                        layer_compositor_frame_state.rects_without_id.push(rect);
3794                    }
3795                } else {
3796                    assert!(tile.tile_id.is_some());
3797                }
3798            }
3799
3800            let new_layer_kind = match input_layers.last() {
3802                Some(curr_layer) => {
3803                    match (curr_layer.usage, usage) {
3804                        (CompositorSurfaceUsage::Content, CompositorSurfaceUsage::Content) => None,
3806                        (CompositorSurfaceUsage::External { .. }, CompositorSurfaceUsage::Content) => Some(usage),
3807
3808                        (CompositorSurfaceUsage::Content, CompositorSurfaceUsage::External { .. }) |
3810                        (CompositorSurfaceUsage::External { .. }, CompositorSurfaceUsage::External { .. }) => {
3811                            match self.compositor_config {
3813                                CompositorConfig::Draw { .. } | CompositorConfig::Native { .. } => None,
3814                                CompositorConfig::Layer { .. } => {
3815                                    Some(usage)
3816                                }
3817                            }
3818                        }
3819                        (CompositorSurfaceUsage::DebugOverlay, _) => {
3820                            Some(usage)
3821                        }
3822                        (_, CompositorSurfaceUsage::DebugOverlay) => {
3824                            unreachable!();
3825                        }
3826                    }
3827                }
3828                None => {
3829                    Some(usage)
3831                }
3832            };
3833
3834            if let Some(new_layer_kind) = new_layer_kind {
3835                let (offset, clip_rect, is_opaque) = match usage {
3836                    CompositorSurfaceUsage::Content => {
3837                        (
3838                            DeviceIntPoint::zero(),
3839                            device_size.into(),
3840                            false,      )
3842                    }
3843                    CompositorSurfaceUsage::External { .. } => {
3844                        let rect = composite_state.get_device_rect(
3845                            &tile.local_rect,
3846                            tile.transform_index
3847                        );
3848
3849                        let clip_rect = tile.device_clip_rect.to_i32();
3850                        let is_opaque = tile.kind != TileKind::Alpha;
3851
3852                        (rect.min.to_i32(), clip_rect, is_opaque)
3853                    }
3854                    CompositorSurfaceUsage::DebugOverlay => unreachable!(),
3855                };
3856
3857                input_layers.push(CompositorInputLayer {
3858                    usage: new_layer_kind,
3859                    is_opaque,
3860                    offset,
3861                    clip_rect,
3862                });
3863
3864                swapchain_layers.push(SwapChainLayer {
3865                    clear_tiles: Vec::new(),
3866                    occlusion: occlusion::FrontToBackBuilder::with_capacity(cap, cap),
3867                })
3868            }
3869            tile_index_to_layer_index[idx] = Some(input_layers.len() - 1);
3870
3871            match tile.kind {
3874                TileKind::Opaque | TileKind::Alpha => {
3875                    let is_opaque = tile.kind != TileKind::Alpha;
3876
3877                    match tile.clip_index {
3878                        Some(clip_index) => {
3879                            let clip = composite_state.get_compositor_clip(clip_index);
3880
3881                            segment_builder.initialize(
3883                                rect.cast_unit(),
3884                                None,
3885                                rect.cast_unit(),
3886                            );
3887                            segment_builder.push_clip_rect(
3888                                clip.rect.cast_unit(),
3889                                Some(clip.radius),
3890                                ClipMode::Clip,
3891                            );
3892                            segment_builder.build(|segment| {
3893                                let key = OcclusionItemKey { tile_index: idx, needs_mask: segment.has_mask };
3894
3895                                full_render_occlusion.add(
3896                                    &segment.rect.cast_unit(),
3897                                    is_opaque && !segment.has_mask,
3898                                    key,
3899                                );
3900                            });
3901                        }
3902                        None => {
3903                            full_render_occlusion.add(&rect, is_opaque, OcclusionItemKey {
3904                                tile_index: idx,
3905                                needs_mask: false,
3906                            });
3907                        }
3908                    }
3909                }
3910                TileKind::Clear => {}
3911            }
3912        }
3913
3914        assert_eq!(swapchain_layers.len(), input_layers.len());
3915
3916        if window_is_opaque {
3917            match input_layers.last_mut() {
3918                Some(_layer) => {
3919                    }
3926                None => {
3927                    input_layers.push(CompositorInputLayer {
3931                        usage: CompositorSurfaceUsage::Content,
3932                        is_opaque: true,
3933                        offset: DeviceIntPoint::zero(),
3934                        clip_rect: device_size.into(),
3935                    });
3936
3937                    swapchain_layers.push(SwapChainLayer {
3938                        clear_tiles: Vec::new(),
3939                        occlusion: occlusion::FrontToBackBuilder::with_capacity(cap, cap),
3940                    });
3941                }
3942            }
3943        }
3944
3945        let mut full_render = false;
3946
3947        if let Some(ref mut compositor) = self.compositor_config.layer_compositor() {
3949            let input = CompositorInputConfig {
3950                enable_screenshot,
3951                layers: &input_layers,
3952            };
3953            full_render = compositor.begin_frame(&input);
3954        }
3955
3956        let mut partial_present_mode = if full_render {
3958            None
3959        } else {
3960            partial_present_mode
3961        };
3962
3963        assert_eq!(swapchain_layers.len(), input_layers.len());
3964
3965        if let Some(ref _compositor) = self.compositor_config.layer_compositor() {
3967            for item in full_render_occlusion
3969            .opaque_items()
3970            .iter()
3971            .chain(full_render_occlusion.alpha_items().iter()) {
3972                let tile = &composite_state.tiles[item.key.tile_index];
3973                match tile.tile_id {
3974                    Some(tile_id) => {
3975                        if let Some(tile_state) = layer_compositor_frame_state.tile_states.get_mut(&tile_id) {
3976                            tile_state.visible_rects.push(item.rectangle);
3977                        } else {
3978                            unreachable!();
3979                        }
3980                    }
3981                    None => {}
3982                }
3983            }
3984
3985            let can_use_partial_present =
3986                !self.force_redraw && !full_render &&
3987                self.layer_compositor_frame_state_in_prev_frame.is_some();
3988
3989            if can_use_partial_present {
3990                let mut combined_dirty_rect = DeviceRect::zero();
3991
3992                for tile in composite_state.tiles.iter() {
3993                    if tile.kind == TileKind::Clear {
3994                        continue;
3995                    }
3996
3997                    if tile.tile_id.is_none() {
3998                        match tile.surface {
3999                            CompositeTileSurface::ExternalSurface { .. } => {}
4000                            CompositeTileSurface::Texture { .. }  |
4001                            CompositeTileSurface::Color { .. } |
4002                            CompositeTileSurface::Clear => {
4003                                unreachable!();
4004                            },
4005                        }
4006                        continue;
4007                    }
4008
4009                    assert!(tile.tile_id.is_some());
4010
4011                    let tiles_exists_in_prev_frame =
4012                        self.layer_compositor_frame_state_in_prev_frame
4013                        .as_ref()
4014                        .unwrap()
4015                        .tile_states
4016                        .contains_key(&tile.tile_id.unwrap());
4017                    let tile_id = tile.tile_id.unwrap();
4018                    let tile_state = layer_compositor_frame_state.tile_states.get(&tile_id).unwrap();
4019
4020                    if tiles_exists_in_prev_frame {
4021                        let prev_tile_state = self.layer_compositor_frame_state_in_prev_frame
4022                            .as_ref()
4023                            .unwrap()
4024                            .tile_states
4025                            .get(&tile_id)
4026                            .unwrap();
4027
4028                        if tile_state.same_state(prev_tile_state) {
4029                            let dirty_rect = composite_state.get_device_rect(
4032                                &tile.local_dirty_rect,
4033                                tile.transform_index,
4034                            );
4035                            for rect in tile_state.visible_rects.iter()  {
4036                                let visible_dirty_rect = rect.intersection(&dirty_rect);
4037                                if visible_dirty_rect.is_some() {
4038                                    combined_dirty_rect = combined_dirty_rect.union(&visible_dirty_rect.unwrap());
4039                                }
4040                            }
4041                        } else {
4042                            for rect in tile_state.visible_rects
4045                                .iter()
4046                                .chain(prev_tile_state.visible_rects.iter())  {
4047                                combined_dirty_rect = combined_dirty_rect.union(&rect);
4048                            }
4049                        }
4050                    } else {
4051                        for rect in &tile_state.visible_rects {
4053                            combined_dirty_rect = combined_dirty_rect.union(&rect);
4054                        }
4055                    }
4056                }
4057
4058                for (tile_id, tile_state) in self.layer_compositor_frame_state_in_prev_frame
4060                    .as_ref()
4061                    .unwrap()
4062                    .tile_states
4063                    .iter() {
4064                    if !layer_compositor_frame_state.tile_states.contains_key(&tile_id) {
4065                        for rect in tile_state.visible_rects.iter()  {
4066                            combined_dirty_rect = combined_dirty_rect.union(&rect);
4067                        }
4068                    }
4069                }
4070
4071                for rect in layer_compositor_frame_state
4073                    .rects_without_id
4074                    .iter()
4075                    .chain(self.layer_compositor_frame_state_in_prev_frame.as_ref().unwrap().rects_without_id.iter())  {
4076                    combined_dirty_rect = combined_dirty_rect.union(&rect);
4077                }
4078
4079                partial_present_mode = Some(PartialPresentMode::Single {
4080                    dirty_rect: combined_dirty_rect,
4081                });
4082            } else {
4083                partial_present_mode = None;
4084            }
4085
4086            self.layer_compositor_frame_state_in_prev_frame = Some(layer_compositor_frame_state);
4087        }
4088
4089        for (idx, tile) in composite_state.tiles.iter().enumerate() {
4094            let device_tile_box = composite_state.get_device_rect(
4095                &tile.local_rect,
4096                tile.transform_index
4097            );
4098
4099            let partial_clip_rect = match partial_present_mode {
4102                Some(PartialPresentMode::Single { dirty_rect }) => dirty_rect,
4103                None => device_tile_box,
4104            };
4105
4106            let device_valid_rect = composite_state
4108                .get_device_rect(&tile.local_valid_rect, tile.transform_index);
4109
4110            let rect = device_tile_box
4111                .intersection_unchecked(&tile.device_clip_rect)
4112                .intersection_unchecked(&partial_clip_rect)
4113                .intersection_unchecked(&device_valid_rect);
4114
4115            if rect.is_empty() {
4116                continue;
4117            }
4118
4119            let layer_index = match tile_index_to_layer_index[idx] {
4120                None => {
4121                    error!("rect {:?} should have valid layer index", rect);
4123                    continue;
4124                }
4125                Some(layer_index) => layer_index,
4126            };
4127
4128            let layer = &mut swapchain_layers[layer_index];
4131
4132            match tile.kind {
4134                TileKind::Opaque | TileKind::Alpha => {
4135                    let is_opaque = tile.kind != TileKind::Alpha;
4136
4137                    match tile.clip_index {
4138                        Some(clip_index) => {
4139                            let clip = composite_state.get_compositor_clip(clip_index);
4140
4141                                segment_builder.initialize(
4143                                rect.cast_unit(),
4144                                None,
4145                                rect.cast_unit(),
4146                            );
4147                            segment_builder.push_clip_rect(
4148                                clip.rect.cast_unit(),
4149                                Some(clip.radius),
4150                                ClipMode::Clip,
4151                            );
4152                            segment_builder.build(|segment| {
4153                                let key = OcclusionItemKey { tile_index: idx, needs_mask: segment.has_mask };
4154
4155                                layer.occlusion.add(
4156                                    &segment.rect.cast_unit(),
4157                                    is_opaque && !segment.has_mask,
4158                                    key,
4159                                );
4160                            });
4161                        }
4162                        None => {
4163                            layer.occlusion.add(&rect, is_opaque, OcclusionItemKey {
4164                                tile_index: idx,
4165                                needs_mask: false,
4166                            });
4167                        }
4168                    }
4169                }
4170                TileKind::Clear => {
4171                    layer.clear_tiles.push(occlusion::Item { rectangle: rect, key: OcclusionItemKey { tile_index: idx, needs_mask: false } });
4176                }
4177            }
4178        }
4179
4180        assert_eq!(swapchain_layers.len(), input_layers.len());
4181        let mut content_clear_color = Some(self.clear_color);
4182
4183        for (layer_index, (layer, swapchain_layer)) in input_layers.iter().zip(swapchain_layers.iter()).enumerate() {
4184            self.device.reset_state();
4185
4186            match layer.usage {
4188                CompositorSurfaceUsage::Content => {}
4189                CompositorSurfaceUsage::External { .. } | CompositorSurfaceUsage::DebugOverlay => {
4190                    continue;
4191                }
4192            }
4193
4194            let clear_color = content_clear_color.take().unwrap_or(ColorF::TRANSPARENT);
4196
4197            if let Some(ref mut _compositor) = self.compositor_config.layer_compositor() {
4198                if let Some(PartialPresentMode::Single { dirty_rect }) = partial_present_mode {
4199                    if dirty_rect.is_empty() {
4200                        continue;
4201                    }
4202                }
4203            }
4204
4205            let draw_target = match self.compositor_config {
4206                CompositorConfig::Layer { ref mut compositor } => {
4207                    match partial_present_mode {
4208                        Some(PartialPresentMode::Single { dirty_rect }) => {
4209                            compositor.bind_layer(layer_index, &[dirty_rect.to_i32()]);
4210                        }
4211                        None => {
4212                            compositor.bind_layer(layer_index, &[]);
4213                        }
4214                    };
4215
4216                    DrawTarget::NativeSurface {
4217                        offset: -layer.offset,
4218                        external_fbo_id: 0,
4219                        dimensions: frame_device_size,
4220                    }
4221                }
4222                CompositorConfig::Draw { .. } | CompositorConfig::Native { .. } => {
4224                    fb_draw_target
4225                }
4226            };
4227
4228            self.composite_pass(
4232                composite_state,
4233                draw_target,
4234                clear_color,
4235                projection,
4236                results,
4237                partial_present_mode,
4238                swapchain_layer,
4239            );
4240
4241            if let Some(ref mut compositor) = self.compositor_config.layer_compositor() {
4242                match partial_present_mode {
4243                    Some(PartialPresentMode::Single { dirty_rect }) => {
4244                        compositor.present_layer(layer_index, &[dirty_rect.to_i32()]);
4245                    }
4246                    None => {
4247                        compositor.present_layer(layer_index, &[]);
4248                    }
4249                };
4250            }
4251        }
4252
4253        if let Some(ref mut compositor) = self.compositor_config.layer_compositor() {
4255            for (layer_index, layer) in input_layers.iter().enumerate() {
4256                let transform = match layer.usage {
4259                    CompositorSurfaceUsage::Content => CompositorSurfaceTransform::identity(),
4260                    CompositorSurfaceUsage::External { transform_index, .. } => composite_state.get_compositor_transform(transform_index),
4261                    CompositorSurfaceUsage::DebugOverlay => CompositorSurfaceTransform::identity(),
4262                };
4263
4264                compositor.add_surface(
4265                    layer_index,
4266                    transform,
4267                    layer.clip_rect,
4268                    ImageRendering::Auto,
4269                );
4270            }
4271        }
4272    }
4273
4274    fn clear_render_target(
4275        &mut self,
4276        target: &RenderTarget,
4277        draw_target: DrawTarget,
4278        framebuffer_kind: FramebufferKind,
4279        projection: &default::Transform3D<f32>,
4280        stats: &mut RendererStats,
4281    ) {
4282        let needs_depth = target.needs_depth();
4283
4284        let clear_depth = if needs_depth {
4285            Some(1.0)
4286        } else {
4287            None
4288        };
4289
4290        let _timer = self.gpu_profiler.start_timer(GPU_TAG_SETUP_TARGET);
4291
4292        self.device.disable_depth();
4293        self.set_blend(false, framebuffer_kind);
4294
4295        let is_alpha = target.target_kind == RenderTargetKind::Alpha;
4296        let require_precise_clear = target.cached;
4297
4298        let clear_with_quads = (target.cached && self.clear_caches_with_quads)
4302            || (is_alpha && self.clear_alpha_targets_with_quads);
4303
4304        let favor_partial_updates = self.device.get_capabilities().supports_render_target_partial_update
4305            && self.enable_clear_scissor;
4306
4307        let full_clears_on_adreno = is_alpha && self.device.get_capabilities().requires_alpha_target_full_clear;
4310        let require_full_clear = !require_precise_clear
4311            && (full_clears_on_adreno || !favor_partial_updates);
4312
4313        let clear_color = target
4314            .clear_color
4315            .map(|color| color.to_array());
4316
4317        let mut cleared_depth = false;
4318        if clear_with_quads {
4319            } else if require_precise_clear {
4321            for (rect, color) in &target.clears {
4323                self.device.clear_target(
4324                    Some(color.to_array()),
4325                    None,
4326                    Some(draw_target.to_framebuffer_rect(*rect)),
4327                );
4328            }
4329        } else {
4330            let clear_rect = if require_full_clear {
4334                None
4335            } else {
4336                match draw_target {
4337                    DrawTarget::Default { rect, total_size, .. } => {
4338                        if rect.min == FramebufferIntPoint::zero() && rect.size() == total_size {
4339                            None
4341                        } else {
4342                            Some(rect)
4343                        }
4344                    }
4345                    DrawTarget::Texture { .. } => {
4346                        target.used_rect.map(|rect| draw_target.to_framebuffer_rect(rect))
4357                    }
4358                    _ => None,
4360                }
4361            };
4362
4363            self.device.clear_target(
4364                clear_color,
4365                clear_depth,
4366                clear_rect,
4367            );
4368            cleared_depth = true;
4369        }
4370
4371        if needs_depth && !cleared_depth {
4373            self.device.clear_target(None, clear_depth, None);
4376        }
4377
4378        let mut clear_instances = Vec::with_capacity(target.clears.len());
4383        for (rect, color) in &target.clears {
4384            if clear_with_quads || (!require_precise_clear && target.clear_color != Some(*color)) {
4385                let rect = rect.to_f32();
4386                clear_instances.push(ClearInstance {
4387                    rect: [
4388                        rect.min.x, rect.min.y,
4389                        rect.max.x, rect.max.y,
4390                    ],
4391                    color: color.to_array(),
4392                })
4393            }
4394        }
4395
4396        if !clear_instances.is_empty() {
4397            self.shaders.borrow_mut().ps_clear().bind(
4398                &mut self.device,
4399                &projection,
4400                None,
4401                &mut self.renderer_errors,
4402                &mut self.profile,
4403            );
4404            self.draw_instanced_batch(
4405                &clear_instances,
4406                VertexArrayKind::Clear,
4407                &BatchTextures::empty(),
4408                stats,
4409            );
4410        }
4411    }
4412
4413    fn draw_render_target(
4414        &mut self,
4415        texture_id: CacheTextureId,
4416        target: &RenderTarget,
4417        render_tasks: &RenderTaskGraph,
4418        stats: &mut RendererStats,
4419    ) {
4420        let needs_depth = target.needs_depth();
4421
4422        let texture = self.texture_resolver.get_cache_texture_mut(&texture_id);
4423        if needs_depth {
4424            self.device.reuse_render_target::<u8>(
4425                texture,
4426                RenderTargetInfo { has_depth: needs_depth },
4427            );
4428        }
4429
4430        let draw_target = DrawTarget::from_texture(
4431            texture,
4432            needs_depth,
4433        );
4434
4435        let projection = Transform3D::ortho(
4436            0.0,
4437            draw_target.dimensions().width as f32,
4438            0.0,
4439            draw_target.dimensions().height as f32,
4440            self.device.ortho_near_plane(),
4441            self.device.ortho_far_plane(),
4442        );
4443
4444        profile_scope!("draw_render_target");
4445        let _gm = self.gpu_profiler.start_marker("render target");
4446
4447        let counter = match target.target_kind {
4448            RenderTargetKind::Color => profiler::COLOR_PASSES,
4449            RenderTargetKind::Alpha => profiler::ALPHA_PASSES,
4450        };
4451        self.profile.inc(counter);
4452
4453        let sampler_query = match target.target_kind {
4454            RenderTargetKind::Color => None,
4455            RenderTargetKind::Alpha => Some(self.gpu_profiler.start_sampler(GPU_SAMPLER_TAG_ALPHA)),
4456        };
4457
4458        if let DrawTarget::Texture { with_depth, .. } = draw_target {
4460            assert!(with_depth >= target.needs_depth());
4461        }
4462
4463        let framebuffer_kind = if draw_target.is_default() {
4464            FramebufferKind::Main
4465        } else {
4466            FramebufferKind::Other
4467        };
4468
4469        self.device.bind_draw_target(draw_target);
4470
4471        if self.device.get_capabilities().supports_qcom_tiled_rendering {
4472            let preserve_mask = match target.clear_color {
4473                Some(_) => 0,
4474                None => gl::COLOR_BUFFER_BIT0_QCOM,
4475            };
4476            if let Some(used_rect) = target.used_rect {
4477                self.device.gl().start_tiling_qcom(
4478                    used_rect.min.x.max(0) as _,
4479                    used_rect.min.y.max(0) as _,
4480                    used_rect.width() as _,
4481                    used_rect.height() as _,
4482                    preserve_mask,
4483                );
4484            }
4485        }
4486
4487        if needs_depth {
4488            self.device.enable_depth_write();
4489        } else {
4490            self.device.disable_depth_write();
4491        }
4492
4493        self.clear_render_target(
4494            target,
4495            draw_target,
4496            framebuffer_kind,
4497            &projection,
4498            stats,
4499        );
4500
4501        if needs_depth {
4502            self.device.disable_depth_write();
4503        }
4504
4505        self.handle_resolves(
4507            &target.resolve_ops,
4508            render_tasks,
4509            draw_target,
4510        );
4511
4512        self.handle_blits(
4514            &target.blits,
4515            render_tasks,
4516            draw_target,
4517        );
4518
4519        if !target.border_segments_solid.is_empty() ||
4521           !target.border_segments_complex.is_empty()
4522        {
4523            let _timer = self.gpu_profiler.start_timer(GPU_TAG_CACHE_BORDER);
4524
4525            self.set_blend(true, FramebufferKind::Other);
4526            self.set_blend_mode_premultiplied_alpha(FramebufferKind::Other);
4527
4528            if !target.border_segments_solid.is_empty() {
4529                self.shaders.borrow_mut().cs_border_solid().bind(
4530                    &mut self.device,
4531                    &projection,
4532                    None,
4533                    &mut self.renderer_errors,
4534                    &mut self.profile,
4535                );
4536
4537                self.draw_instanced_batch(
4538                    &target.border_segments_solid,
4539                    VertexArrayKind::Border,
4540                    &BatchTextures::empty(),
4541                    stats,
4542                );
4543            }
4544
4545            if !target.border_segments_complex.is_empty() {
4546                self.shaders.borrow_mut().cs_border_segment().bind(
4547                    &mut self.device,
4548                    &projection,
4549                    None,
4550                    &mut self.renderer_errors,
4551                    &mut self.profile,
4552                );
4553
4554                self.draw_instanced_batch(
4555                    &target.border_segments_complex,
4556                    VertexArrayKind::Border,
4557                    &BatchTextures::empty(),
4558                    stats,
4559                );
4560            }
4561
4562            self.set_blend(false, FramebufferKind::Other);
4563        }
4564
4565        if !target.line_decorations.is_empty() {
4567            let _timer = self.gpu_profiler.start_timer(GPU_TAG_CACHE_LINE_DECORATION);
4568
4569            self.set_blend(true, FramebufferKind::Other);
4570            self.set_blend_mode_premultiplied_alpha(FramebufferKind::Other);
4571
4572            self.shaders.borrow_mut().cs_line_decoration().bind(
4573                &mut self.device,
4574                &projection,
4575                None,
4576                &mut self.renderer_errors,
4577                &mut self.profile,
4578            );
4579
4580            self.draw_instanced_batch(
4581                &target.line_decorations,
4582                VertexArrayKind::LineDecoration,
4583                &BatchTextures::empty(),
4584                stats,
4585            );
4586
4587            self.set_blend(false, FramebufferKind::Other);
4588        }
4589
4590        if !target.fast_linear_gradients.is_empty() {
4592            let _timer = self.gpu_profiler.start_timer(GPU_TAG_CACHE_FAST_LINEAR_GRADIENT);
4593
4594            self.set_blend(false, FramebufferKind::Other);
4595
4596            self.shaders.borrow_mut().cs_fast_linear_gradient().bind(
4597                &mut self.device,
4598                &projection,
4599                None,
4600                &mut self.renderer_errors,
4601                &mut self.profile,
4602            );
4603
4604            self.draw_instanced_batch(
4605                &target.fast_linear_gradients,
4606                VertexArrayKind::FastLinearGradient,
4607                &BatchTextures::empty(),
4608                stats,
4609            );
4610        }
4611
4612        if !target.linear_gradients.is_empty() {
4614            let _timer = self.gpu_profiler.start_timer(GPU_TAG_CACHE_LINEAR_GRADIENT);
4615
4616            self.set_blend(false, FramebufferKind::Other);
4617
4618            self.shaders.borrow_mut().cs_linear_gradient().bind(
4619                &mut self.device,
4620                &projection,
4621                None,
4622                &mut self.renderer_errors,
4623                &mut self.profile,
4624            );
4625
4626            if let Some(ref texture) = self.dither_matrix_texture {
4627                self.device.bind_texture(TextureSampler::Dither, texture, Swizzle::default());
4628            }
4629
4630            self.draw_instanced_batch(
4631                &target.linear_gradients,
4632                VertexArrayKind::LinearGradient,
4633                &BatchTextures::empty(),
4634                stats,
4635            );
4636        }
4637
4638        if !target.radial_gradients.is_empty() {
4640            let _timer = self.gpu_profiler.start_timer(GPU_TAG_RADIAL_GRADIENT);
4641
4642            self.set_blend(false, FramebufferKind::Other);
4643
4644            self.shaders.borrow_mut().cs_radial_gradient().bind(
4645                &mut self.device,
4646                &projection,
4647                None,
4648                &mut self.renderer_errors,
4649                &mut self.profile,
4650            );
4651
4652            if let Some(ref texture) = self.dither_matrix_texture {
4653                self.device.bind_texture(TextureSampler::Dither, texture, Swizzle::default());
4654            }
4655
4656            self.draw_instanced_batch(
4657                &target.radial_gradients,
4658                VertexArrayKind::RadialGradient,
4659                &BatchTextures::empty(),
4660                stats,
4661            );
4662        }
4663
4664        if !target.conic_gradients.is_empty() {
4666            let _timer = self.gpu_profiler.start_timer(GPU_TAG_CONIC_GRADIENT);
4667
4668            self.set_blend(false, FramebufferKind::Other);
4669
4670            self.shaders.borrow_mut().cs_conic_gradient().bind(
4671                &mut self.device,
4672                &projection,
4673                None,
4674                &mut self.renderer_errors,
4675                &mut self.profile,
4676            );
4677
4678            if let Some(ref texture) = self.dither_matrix_texture {
4679                self.device.bind_texture(TextureSampler::Dither, texture, Swizzle::default());
4680            }
4681
4682            self.draw_instanced_batch(
4683                &target.conic_gradients,
4684                VertexArrayKind::ConicGradient,
4685                &BatchTextures::empty(),
4686                stats,
4687            );
4688        }
4689
4690        if !target.vertical_blurs.is_empty() || !target.horizontal_blurs.is_empty() {
4697            let _timer = self.gpu_profiler.start_timer(GPU_TAG_BLUR);
4698
4699            self.set_blend(false, framebuffer_kind);
4700            self.shaders.borrow_mut().cs_blur_rgba8()
4701                .bind(&mut self.device, &projection, None, &mut self.renderer_errors, &mut self.profile);
4702
4703            if !target.vertical_blurs.is_empty() {
4704                self.draw_blurs(
4705                    &target.vertical_blurs,
4706                    stats,
4707                );
4708            }
4709
4710            if !target.horizontal_blurs.is_empty() {
4711                self.draw_blurs(
4712                    &target.horizontal_blurs,
4713                    stats,
4714                );
4715            }
4716        }
4717
4718        self.handle_scaling(
4719            &target.scalings,
4720            &projection,
4721            stats,
4722        );
4723
4724        for (ref textures, ref filters) in &target.svg_filters {
4725            self.handle_svg_filters(
4726                textures,
4727                filters,
4728                &projection,
4729                stats,
4730            );
4731        }
4732
4733        for (ref textures, ref filters) in &target.svg_nodes {
4734            self.handle_svg_nodes(textures, filters, &projection, stats);
4735        }
4736
4737        for alpha_batch_container in &target.alpha_batch_containers {
4738            self.draw_alpha_batch_container(
4739                alpha_batch_container,
4740                draw_target,
4741                framebuffer_kind,
4742                &projection,
4743                render_tasks,
4744                stats,
4745            );
4746        }
4747
4748        self.handle_prims(
4749            &draw_target,
4750            &target.prim_instances,
4751            &target.prim_instances_with_scissor,
4752            &projection,
4753            stats,
4754        );
4755
4756        let has_primary_clips = !target.clip_batcher.primary_clips.is_empty();
4758        let has_secondary_clips = !target.clip_batcher.secondary_clips.is_empty();
4759        let has_clip_masks = !target.clip_masks.is_empty();
4760        if has_primary_clips | has_secondary_clips | has_clip_masks {
4761            let _timer = self.gpu_profiler.start_timer(GPU_TAG_CACHE_CLIP);
4762
4763            if has_primary_clips {
4767                self.set_blend(false, FramebufferKind::Other);
4771                self.draw_clip_batch_list(
4772                    &target.clip_batcher.primary_clips,
4773                    &projection,
4774                    stats,
4775                );
4776            }
4777
4778            if has_secondary_clips {
4779                self.set_blend(true, FramebufferKind::Other);
4782                self.set_blend_mode_multiply(FramebufferKind::Other);
4783                self.draw_clip_batch_list(
4784                    &target.clip_batcher.secondary_clips,
4785                    &projection,
4786                    stats,
4787                );
4788            }
4789
4790            if has_clip_masks {
4791                self.handle_clips(
4792                    &draw_target,
4793                    &target.clip_masks,
4794                    &projection,
4795                    stats,
4796                );
4797            }
4798        }
4799
4800        if needs_depth {
4801            self.device.invalidate_depth_target();
4802        }
4803        if self.device.get_capabilities().supports_qcom_tiled_rendering {
4804            self.device.gl().end_tiling_qcom(gl::COLOR_BUFFER_BIT0_QCOM);
4805        }
4806
4807        if let Some(sampler) = sampler_query {
4808            self.gpu_profiler.finish_sampler(sampler);
4809        }
4810    }
4811
4812    fn draw_blurs(
4813        &mut self,
4814        blurs: &FastHashMap<TextureSource, FrameVec<BlurInstance>>,
4815        stats: &mut RendererStats,
4816    ) {
4817        for (texture, blurs) in blurs {
4818            let textures = BatchTextures::composite_rgb(
4819                *texture,
4820            );
4821
4822            self.draw_instanced_batch(
4823                blurs,
4824                VertexArrayKind::Blur,
4825                &textures,
4826                stats,
4827            );
4828        }
4829    }
4830
4831    fn draw_clip_batch_list(
4833        &mut self,
4834        list: &ClipBatchList,
4835        projection: &default::Transform3D<f32>,
4836        stats: &mut RendererStats,
4837    ) {
4838        if self.debug_flags.contains(DebugFlags::DISABLE_CLIP_MASKS) {
4839            return;
4840        }
4841
4842        if !list.slow_rectangles.is_empty() {
4844            let _gm2 = self.gpu_profiler.start_marker("slow clip rectangles");
4845            self.shaders.borrow_mut().cs_clip_rectangle_slow().bind(
4846                &mut self.device,
4847                projection,
4848                None,
4849                &mut self.renderer_errors,
4850                &mut self.profile,
4851            );
4852            self.draw_instanced_batch(
4853                &list.slow_rectangles,
4854                VertexArrayKind::ClipRect,
4855                &BatchTextures::empty(),
4856                stats,
4857            );
4858        }
4859        if !list.fast_rectangles.is_empty() {
4860            let _gm2 = self.gpu_profiler.start_marker("fast clip rectangles");
4861            self.shaders.borrow_mut().cs_clip_rectangle_fast().bind(
4862                &mut self.device,
4863                projection,
4864                None,
4865                &mut self.renderer_errors,
4866                &mut self.profile,
4867            );
4868            self.draw_instanced_batch(
4869                &list.fast_rectangles,
4870                VertexArrayKind::ClipRect,
4871                &BatchTextures::empty(),
4872                stats,
4873            );
4874        }
4875
4876        for (mask_texture_id, items) in list.box_shadows.iter() {
4878            let _gm2 = self.gpu_profiler.start_marker("box-shadows");
4879            let textures = BatchTextures::composite_rgb(*mask_texture_id);
4880            self.shaders.borrow_mut().cs_clip_box_shadow()
4881                .bind(&mut self.device, projection, None, &mut self.renderer_errors, &mut self.profile);
4882            self.draw_instanced_batch(
4883                items,
4884                VertexArrayKind::ClipBoxShadow,
4885                &textures,
4886                stats,
4887            );
4888        }
4889    }
4890
4891    fn update_deferred_resolves(&mut self, deferred_resolves: &[DeferredResolve]) -> Option<GpuCacheUpdateList> {
4892        if deferred_resolves.is_empty() {
4897            return None;
4898        }
4899
4900        let handler = self.external_image_handler
4901            .as_mut()
4902            .expect("Found external image, but no handler set!");
4903
4904        let mut list = GpuCacheUpdateList {
4905            frame_id: FrameId::INVALID,
4906            clear: false,
4907            height: self.gpu_cache_texture.get_height(),
4908            blocks: Vec::new(),
4909            updates: Vec::new(),
4910            debug_commands: Vec::new(),
4911        };
4912
4913        for (i, deferred_resolve) in deferred_resolves.iter().enumerate() {
4914            self.gpu_profiler.place_marker("deferred resolve");
4915            let props = &deferred_resolve.image_properties;
4916            let ext_image = props
4917                .external_image
4918                .expect("BUG: Deferred resolves must be external images!");
4919            let image = handler.lock(ext_image.id, ext_image.channel_index, deferred_resolve.is_composited);
4921            let texture_target = match ext_image.image_type {
4922                ExternalImageType::TextureHandle(target) => target,
4923                ExternalImageType::Buffer => {
4924                    panic!("not a suitable image type in update_deferred_resolves()");
4925                }
4926            };
4927
4928            self.device.reset_state();
4931
4932            let texture = match image.source {
4933                ExternalImageSource::NativeTexture(texture_id) => {
4934                    ExternalTexture::new(
4935                        texture_id,
4936                        texture_target,
4937                        image.uv,
4938                        deferred_resolve.rendering,
4939                    )
4940                }
4941                ExternalImageSource::Invalid => {
4942                    warn!("Invalid ext-image");
4943                    debug!(
4944                        "For ext_id:{:?}, channel:{}.",
4945                        ext_image.id,
4946                        ext_image.channel_index
4947                    );
4948                    ExternalTexture::new(
4950                        0,
4951                        texture_target,
4952                        image.uv,
4953                        deferred_resolve.rendering,
4954                    )
4955                }
4956                ExternalImageSource::RawData(_) => {
4957                    panic!("Raw external data is not expected for deferred resolves!");
4958                }
4959            };
4960
4961            self.texture_resolver
4962                .external_images
4963                .insert(DeferredResolveIndex(i as u32), texture);
4964
4965            list.updates.push(GpuCacheUpdate::Copy {
4966                block_index: list.blocks.len(),
4967                block_count: BLOCKS_PER_UV_RECT,
4968                address: deferred_resolve.address,
4969            });
4970            list.blocks.push(image.uv.into());
4971            list.blocks.push([0f32; 4].into());
4972        }
4973
4974        Some(list)
4975    }
4976
4977    fn unlock_external_images(
4978        &mut self,
4979        deferred_resolves: &[DeferredResolve],
4980    ) {
4981        if !self.texture_resolver.external_images.is_empty() {
4982            let handler = self.external_image_handler
4983                .as_mut()
4984                .expect("Found external image, but no handler set!");
4985
4986            for (index, _) in self.texture_resolver.external_images.drain() {
4987                let props = &deferred_resolves[index.0 as usize].image_properties;
4988                let ext_image = props
4989                    .external_image
4990                    .expect("BUG: Deferred resolves must be external images!");
4991                handler.unlock(ext_image.id, ext_image.channel_index);
4992            }
4993        }
4994    }
4995
4996    fn calculate_dirty_rects(
5000        &mut self,
5001        buffer_age: usize,
5002        composite_state: &CompositeState,
5003        draw_target_dimensions: DeviceIntSize,
5004        results: &mut RenderResults,
5005    ) -> Option<PartialPresentMode> {
5006
5007        if let Some(ref _compositor) = self.compositor_config.layer_compositor() {
5008            return None;
5010        }
5011
5012        let mut partial_present_mode = None;
5013
5014        let (max_partial_present_rects, draw_previous_partial_present_regions) = match self.current_compositor_kind {
5015            CompositorKind::Native { .. } => {
5016                (1, false)
5021            }
5022            CompositorKind::Draw { draw_previous_partial_present_regions, max_partial_present_rects } => {
5023                (max_partial_present_rects, draw_previous_partial_present_regions)
5024            }
5025            CompositorKind::Layer { .. } => {
5026                unreachable!();
5027            }
5028        };
5029
5030        if max_partial_present_rects > 0 {
5031            let prev_frames_damage_rect = if let Some(..) = self.compositor_config.partial_present() {
5032                self.buffer_damage_tracker
5033                    .get_damage_rect(buffer_age)
5034                    .or_else(|| Some(DeviceRect::from_size(draw_target_dimensions.to_f32())))
5035            } else {
5036                None
5037            };
5038
5039            let can_use_partial_present =
5040                composite_state.dirty_rects_are_valid &&
5041                !self.force_redraw &&
5042                !(prev_frames_damage_rect.is_none() && draw_previous_partial_present_regions) &&
5043                !self.debug_overlay_state.is_enabled;
5044
5045            if can_use_partial_present {
5046                let mut combined_dirty_rect = DeviceRect::zero();
5047                let fb_rect = DeviceRect::from_size(draw_target_dimensions.to_f32());
5048
5049                for tile in &composite_state.tiles {
5052                    if tile.kind == TileKind::Clear {
5053                        continue;
5054                    }
5055                    let dirty_rect = composite_state.get_device_rect(
5056                        &tile.local_dirty_rect,
5057                        tile.transform_index,
5058                    );
5059
5060                    if let Some(dirty_rect) = dirty_rect.intersection(&fb_rect) {
5065                        combined_dirty_rect = combined_dirty_rect.union(&dirty_rect);
5066                    }
5067                }
5068
5069                let combined_dirty_rect = combined_dirty_rect.round();
5070                let combined_dirty_rect_i32 = combined_dirty_rect.to_i32();
5071                if !combined_dirty_rect.is_empty() {
5074                    results.dirty_rects.push(combined_dirty_rect_i32);
5075                }
5076
5077                if draw_previous_partial_present_regions {
5079                    self.buffer_damage_tracker.push_dirty_rect(&combined_dirty_rect);
5080                }
5081
5082                let total_dirty_rect = if draw_previous_partial_present_regions {
5088                    combined_dirty_rect.union(&prev_frames_damage_rect.unwrap())
5089                } else {
5090                    combined_dirty_rect
5091                };
5092
5093                partial_present_mode = Some(PartialPresentMode::Single {
5094                    dirty_rect: total_dirty_rect,
5095                });
5096            } else {
5097                let fb_rect = DeviceIntRect::from_size(
5100                    draw_target_dimensions,
5101                );
5102                results.dirty_rects.push(fb_rect);
5103
5104                if draw_previous_partial_present_regions {
5105                    self.buffer_damage_tracker.push_dirty_rect(&fb_rect.to_f32());
5106                }
5107            }
5108        }
5109
5110        partial_present_mode
5111    }
5112
5113    fn bind_frame_data(&mut self, frame: &mut Frame) {
5114        profile_scope!("bind_frame_data");
5115
5116        let _timer = self.gpu_profiler.start_timer(GPU_TAG_SETUP_DATA);
5117
5118        self.vertex_data_textures[self.current_vertex_data_textures].update(
5119            &mut self.device,
5120            &mut self.texture_upload_pbo_pool,
5121            frame,
5122        );
5123        self.current_vertex_data_textures =
5124            (self.current_vertex_data_textures + 1) % VERTEX_DATA_TEXTURE_COUNT;
5125    }
5126
5127    fn update_native_surfaces(&mut self) {
5128        profile_scope!("update_native_surfaces");
5129
5130        match self.compositor_config {
5131            CompositorConfig::Native { ref mut compositor, .. } => {
5132                for op in self.pending_native_surface_updates.drain(..) {
5133                    match op.details {
5134                        NativeSurfaceOperationDetails::CreateSurface { id, virtual_offset, tile_size, is_opaque } => {
5135                            let _inserted = self.allocated_native_surfaces.insert(id);
5136                            debug_assert!(_inserted, "bug: creating existing surface");
5137                            compositor.create_surface(
5138                                    &mut self.device,
5139                                    id,
5140                                    virtual_offset,
5141                                    tile_size,
5142                                    is_opaque,
5143                            );
5144                        }
5145                        NativeSurfaceOperationDetails::CreateExternalSurface { id, is_opaque } => {
5146                            let _inserted = self.allocated_native_surfaces.insert(id);
5147                            debug_assert!(_inserted, "bug: creating existing surface");
5148                            compositor.create_external_surface(
5149                                &mut self.device,
5150                                id,
5151                                is_opaque,
5152                            );
5153                        }
5154                        NativeSurfaceOperationDetails::CreateBackdropSurface { id, color } => {
5155                            let _inserted = self.allocated_native_surfaces.insert(id);
5156                            debug_assert!(_inserted, "bug: creating existing surface");
5157                            compositor.create_backdrop_surface(
5158                                &mut self.device,
5159                                id,
5160                                color,
5161                            );
5162                        }
5163                        NativeSurfaceOperationDetails::DestroySurface { id } => {
5164                            let _existed = self.allocated_native_surfaces.remove(&id);
5165                            debug_assert!(_existed, "bug: removing unknown surface");
5166                            compositor.destroy_surface(&mut self.device, id);
5167                        }
5168                        NativeSurfaceOperationDetails::CreateTile { id } => {
5169                            compositor.create_tile(&mut self.device, id);
5170                        }
5171                        NativeSurfaceOperationDetails::DestroyTile { id } => {
5172                            compositor.destroy_tile(&mut self.device, id);
5173                        }
5174                        NativeSurfaceOperationDetails::AttachExternalImage { id, external_image } => {
5175                            compositor.attach_external_image(&mut self.device, id, external_image);
5176                        }
5177                    }
5178                }
5179            }
5180            CompositorConfig::Draw { .. } | CompositorConfig::Layer { .. } => {
5181                debug_assert!(self.pending_native_surface_updates.is_empty());
5184            }
5185        }
5186    }
5187
5188    fn create_gpu_buffer_texture<T: Texel>(
5189        &mut self,
5190        buffer: &GpuBuffer<T>,
5191        sampler: TextureSampler,
5192    ) -> Option<Texture> {
5193        if buffer.is_empty() {
5194            None
5195        } else {
5196            let gpu_buffer_texture = self.device.create_texture(
5197                ImageBufferKind::Texture2D,
5198                buffer.format,
5199                buffer.size.width,
5200                buffer.size.height,
5201                TextureFilter::Nearest,
5202                None,
5203            );
5204
5205            self.device.bind_texture(
5206                sampler,
5207                &gpu_buffer_texture,
5208                Swizzle::default(),
5209            );
5210
5211            self.device.upload_texture_immediate(
5212                &gpu_buffer_texture,
5213                &buffer.data,
5214            );
5215
5216            Some(gpu_buffer_texture)
5217        }
5218    }
5219
5220    fn draw_frame(
5221        &mut self,
5222        frame: &mut Frame,
5223        device_size: Option<DeviceIntSize>,
5224        buffer_age: usize,
5225        results: &mut RenderResults,
5226    ) {
5227        profile_scope!("draw_frame");
5228
5229        #[cfg(not(target_os = "android"))]
5231        let _gm = self.gpu_profiler.start_marker("draw frame");
5232
5233        if frame.passes.is_empty() {
5234            frame.has_been_rendered = true;
5235            return;
5236        }
5237
5238        self.device.disable_depth_write();
5239        self.set_blend(false, FramebufferKind::Other);
5240        self.device.disable_stencil();
5241
5242        self.bind_frame_data(frame);
5243
5244        let gpu_buffer_texture_f = self.create_gpu_buffer_texture(
5247            &frame.gpu_buffer_f,
5248            TextureSampler::GpuBufferF,
5249        );
5250        let gpu_buffer_texture_i = self.create_gpu_buffer_texture(
5251            &frame.gpu_buffer_i,
5252            TextureSampler::GpuBufferI,
5253        );
5254
5255        let bytes_to_mb = 1.0 / 1000000.0;
5256        let gpu_buffer_bytes_f = gpu_buffer_texture_f
5257            .as_ref()
5258            .map(|tex| tex.size_in_bytes())
5259            .unwrap_or(0);
5260        let gpu_buffer_bytes_i = gpu_buffer_texture_i
5261            .as_ref()
5262            .map(|tex| tex.size_in_bytes())
5263            .unwrap_or(0);
5264        let gpu_buffer_mb = (gpu_buffer_bytes_f + gpu_buffer_bytes_i) as f32 * bytes_to_mb;
5265        self.profile.set(profiler::GPU_BUFFER_MEM, gpu_buffer_mb);
5266
5267        let gpu_cache_bytes = self.gpu_cache_texture.gpu_size_in_bytes();
5268        let gpu_cache_mb = gpu_cache_bytes as f32 * bytes_to_mb;
5269        self.profile.set(profiler::GPU_CACHE_MEM, gpu_cache_mb);
5270
5271        let present_mode = device_size.and_then(|device_size| {
5277            self.calculate_dirty_rects(
5278                buffer_age,
5279                &frame.composite_state,
5280                device_size,
5281                results,
5282            )
5283        });
5284
5285        if let CompositorKind::Native { .. } = self.current_compositor_kind {
5294            let compositor = self.compositor_config.compositor().unwrap();
5295            if !frame.has_been_rendered {
5297                for tile in &frame.composite_state.tiles {
5298                    if tile.kind == TileKind::Clear {
5299                        continue;
5300                    }
5301                    if !tile.local_dirty_rect.is_empty() {
5302                        if let CompositeTileSurface::Texture { surface: ResolvedSurfaceTexture::Native { id, .. } } = tile.surface {
5303                            let valid_rect = frame.composite_state.get_surface_rect(
5304                                &tile.local_valid_rect,
5305                                &tile.local_rect,
5306                                tile.transform_index,
5307                            ).to_i32();
5308
5309                            compositor.invalidate_tile(&mut self.device, id, valid_rect);
5310                        }
5311                    }
5312                }
5313            }
5314            for surface in &frame.composite_state.external_surfaces {
5319                if let Some((native_surface_id, size)) = surface.update_params {
5320                    let surface_rect = size.into();
5321                    compositor.invalidate_tile(&mut self.device, NativeTileId { surface_id: native_surface_id, x: 0, y: 0 }, surface_rect);
5322                }
5323            }
5324            if device_size.is_some() {
5329                frame.composite_state.composite_native(
5330                    self.clear_color,
5331                    &results.dirty_rects,
5332                    &mut self.device,
5333                    &mut **compositor,
5334                );
5335            }
5336        }
5337
5338        for (_pass_index, pass) in frame.passes.iter_mut().enumerate() {
5339            #[cfg(not(target_os = "android"))]
5340            let _gm = self.gpu_profiler.start_marker(&format!("pass {}", _pass_index));
5341
5342            profile_scope!("offscreen target");
5343
5344            if !frame.has_been_rendered {
5348                for (&texture_id, target) in &pass.texture_cache {
5349                    self.draw_render_target(
5350                        texture_id,
5351                        target,
5352                        &frame.render_tasks,
5353                        &mut results.stats,
5354                    );
5355                }
5356
5357                if !pass.picture_cache.is_empty() {
5358                    self.profile.inc(profiler::COLOR_PASSES);
5359                }
5360
5361                for picture_target in &pass.picture_cache {
5363                    results.stats.color_target_count += 1;
5364
5365                    let draw_target = match picture_target.surface {
5366                        ResolvedSurfaceTexture::TextureCache { ref texture } => {
5367                            let (texture, _) = self.texture_resolver
5368                                .resolve(texture)
5369                                .expect("bug");
5370
5371                            DrawTarget::from_texture(
5372                                texture,
5373                                true,
5374                            )
5375                        }
5376                        ResolvedSurfaceTexture::Native { id, size } => {
5377                            let surface_info = match self.current_compositor_kind {
5378                                CompositorKind::Native { .. } => {
5379                                    let compositor = self.compositor_config.compositor().unwrap();
5380                                    compositor.bind(
5381                                        &mut self.device,
5382                                        id,
5383                                        picture_target.dirty_rect,
5384                                        picture_target.valid_rect,
5385                                    )
5386                                }
5387                                CompositorKind::Draw { .. } | CompositorKind::Layer { .. } => {
5388                                    unreachable!();
5389                                }
5390                            };
5391
5392                            DrawTarget::NativeSurface {
5393                                offset: surface_info.origin,
5394                                external_fbo_id: surface_info.fbo_id,
5395                                dimensions: size,
5396                            }
5397                        }
5398                    };
5399
5400                    let projection = Transform3D::ortho(
5401                        0.0,
5402                        draw_target.dimensions().width as f32,
5403                        0.0,
5404                        draw_target.dimensions().height as f32,
5405                        self.device.ortho_near_plane(),
5406                        self.device.ortho_far_plane(),
5407                    );
5408
5409                    self.draw_picture_cache_target(
5410                        picture_target,
5411                        draw_target,
5412                        &projection,
5413                        &frame.render_tasks,
5414                        &mut results.stats,
5415                    );
5416
5417                    if let ResolvedSurfaceTexture::Native { .. } = picture_target.surface {
5419                        match self.current_compositor_kind {
5420                            CompositorKind::Native { .. } => {
5421                                let compositor = self.compositor_config.compositor().unwrap();
5422                                compositor.unbind(&mut self.device);
5423                            }
5424                            CompositorKind::Draw { .. } | CompositorKind::Layer { .. } => {
5425                                unreachable!();
5426                            }
5427                        }
5428                    }
5429                }
5430            }
5431
5432            for target in &pass.alpha.targets {
5433                results.stats.alpha_target_count += 1;
5434                self.draw_render_target(
5435                    target.texture_id(),
5436                    target,
5437                    &frame.render_tasks,
5438                    &mut results.stats,
5439                );
5440            }
5441
5442            for target in &pass.color.targets {
5443                results.stats.color_target_count += 1;
5444                self.draw_render_target(
5445                    target.texture_id(),
5446                    target,
5447                    &frame.render_tasks,
5448                    &mut results.stats,
5449                );
5450            }
5451
5452            self.texture_resolver.end_pass(
5458                &mut self.device,
5459                &pass.textures_to_invalidate,
5460            );
5461        }
5462
5463        self.composite_frame(
5464            frame,
5465            device_size,
5466            results,
5467            present_mode,
5468        );
5469
5470        if let Some(gpu_buffer_texture_f) = gpu_buffer_texture_f {
5471            self.device.delete_texture(gpu_buffer_texture_f);
5472        }
5473        if let Some(gpu_buffer_texture_i) = gpu_buffer_texture_i {
5474            self.device.delete_texture(gpu_buffer_texture_i);
5475        }
5476
5477        frame.has_been_rendered = true;
5478    }
5479
5480    fn composite_frame(
5481        &mut self,
5482        frame: &mut Frame,
5483        device_size: Option<DeviceIntSize>,
5484        results: &mut RenderResults,
5485        present_mode: Option<PartialPresentMode>,
5486    ) {
5487        profile_scope!("main target");
5488
5489        if let Some(device_size) = device_size {
5490            results.stats.color_target_count += 1;
5491            results.picture_cache_debug = mem::replace(
5492                &mut frame.composite_state.picture_cache_debug,
5493                PictureCacheDebugInfo::new(),
5494            );
5495
5496            let size = frame.device_rect.size().to_f32();
5497            let surface_origin_is_top_left = self.device.surface_origin_is_top_left();
5498            let (bottom, top) = if surface_origin_is_top_left {
5499              (0.0, size.height)
5500            } else {
5501              (size.height, 0.0)
5502            };
5503
5504            let projection = Transform3D::ortho(
5505                0.0,
5506                size.width,
5507                bottom,
5508                top,
5509                self.device.ortho_near_plane(),
5510                self.device.ortho_far_plane(),
5511            );
5512
5513            let fb_scale = Scale::<_, _, FramebufferPixel>::new(1i32);
5514            let mut fb_rect = frame.device_rect * fb_scale;
5515
5516            if !surface_origin_is_top_left {
5517                let h = fb_rect.height();
5518                fb_rect.min.y = device_size.height - fb_rect.max.y;
5519                fb_rect.max.y = fb_rect.min.y + h;
5520            }
5521
5522            let draw_target = DrawTarget::Default {
5523                rect: fb_rect,
5524                total_size: device_size * fb_scale,
5525                surface_origin_is_top_left,
5526            };
5527
5528            match self.current_compositor_kind {
5531                CompositorKind::Native { .. } => {
5532                    self.update_external_native_surfaces(
5536                        &frame.composite_state.external_surfaces,
5537                        results,
5538                    );
5539                }
5540                CompositorKind::Draw { .. } | CompositorKind::Layer { .. } => {
5541                    self.composite_simple(
5542                        &frame.composite_state,
5543                        frame.device_rect.size(),
5544                        draw_target,
5545                        &projection,
5546                        results,
5547                        present_mode,
5548                        device_size,
5549                    );
5550                }
5551            }
5552            self.force_redraw = false;
5554        } else {
5555            self.force_redraw = true;
5558        }
5559    }
5560
5561    pub fn debug_renderer(&mut self) -> Option<&mut DebugRenderer> {
5562        self.debug.get_mut(&mut self.device)
5563    }
5564
5565    pub fn get_debug_flags(&self) -> DebugFlags {
5566        self.debug_flags
5567    }
5568
5569    pub fn set_debug_flags(&mut self, flags: DebugFlags) {
5570        if let Some(enabled) = flag_changed(self.debug_flags, flags, DebugFlags::GPU_TIME_QUERIES) {
5571            if enabled {
5572                self.gpu_profiler.enable_timers();
5573            } else {
5574                self.gpu_profiler.disable_timers();
5575            }
5576        }
5577        if let Some(enabled) = flag_changed(self.debug_flags, flags, DebugFlags::GPU_SAMPLE_QUERIES) {
5578            if enabled {
5579                self.gpu_profiler.enable_samplers();
5580            } else {
5581                self.gpu_profiler.disable_samplers();
5582            }
5583        }
5584
5585        self.debug_flags = flags;
5586    }
5587
5588    pub fn set_profiler_ui(&mut self, ui_str: &str) {
5589        self.profiler.set_ui(ui_str);
5590    }
5591
5592    fn draw_frame_debug_items(&mut self, items: &[DebugItem]) {
5593        if items.is_empty() {
5594            return;
5595        }
5596
5597        let debug_renderer = match self.debug.get_mut(&mut self.device) {
5598            Some(render) => render,
5599            None => return,
5600        };
5601
5602        for item in items {
5603            match item {
5604                DebugItem::Rect { rect, outer_color, inner_color, thickness } => {
5605                    if inner_color.a > 0.001 {
5606                        let rect = rect.inflate(-thickness as f32, -thickness as f32);
5607                        debug_renderer.add_quad(
5608                            rect.min.x,
5609                            rect.min.y,
5610                            rect.max.x,
5611                            rect.max.y,
5612                            (*inner_color).into(),
5613                            (*inner_color).into(),
5614                        );
5615                    }
5616
5617                    if outer_color.a > 0.001 {
5618                        debug_renderer.add_rect(
5619                            &rect.to_i32(),
5620                            *thickness,
5621                            (*outer_color).into(),
5622                        );
5623                    }
5624                }
5625                DebugItem::Text { ref msg, position, color } => {
5626                    debug_renderer.add_text(
5627                        position.x,
5628                        position.y,
5629                        msg,
5630                        (*color).into(),
5631                        None,
5632                    );
5633                }
5634            }
5635        }
5636    }
5637
5638    fn draw_render_target_debug(&mut self, draw_target: &DrawTarget) {
5639        if !self.debug_flags.contains(DebugFlags::RENDER_TARGET_DBG) {
5640            return;
5641        }
5642
5643        let debug_renderer = match self.debug.get_mut(&mut self.device) {
5644            Some(render) => render,
5645            None => return,
5646        };
5647
5648        let textures = self.texture_resolver
5649            .texture_cache_map
5650            .values()
5651            .filter(|item| item.category == TextureCacheCategory::RenderTarget)
5652            .map(|item| &item.texture)
5653            .collect::<Vec<&Texture>>();
5654
5655        Self::do_debug_blit(
5656            &mut self.device,
5657            debug_renderer,
5658            textures,
5659            draw_target,
5660            0,
5661            &|_| [0.0, 1.0, 0.0, 1.0], );
5663    }
5664
5665    fn draw_zoom_debug(
5666        &mut self,
5667        device_size: DeviceIntSize,
5668    ) {
5669        if !self.debug_flags.contains(DebugFlags::ZOOM_DBG) {
5670            return;
5671        }
5672
5673        let debug_renderer = match self.debug.get_mut(&mut self.device) {
5674            Some(render) => render,
5675            None => return,
5676        };
5677
5678        let source_size = DeviceIntSize::new(64, 64);
5679        let target_size = DeviceIntSize::new(1024, 1024);
5680
5681        let source_origin = DeviceIntPoint::new(
5682            (self.cursor_position.x - source_size.width / 2)
5683                .min(device_size.width - source_size.width)
5684                .max(0),
5685            (self.cursor_position.y - source_size.height / 2)
5686                .min(device_size.height - source_size.height)
5687                .max(0),
5688        );
5689
5690        let source_rect = DeviceIntRect::from_origin_and_size(
5691            source_origin,
5692            source_size,
5693        );
5694
5695        let target_rect = DeviceIntRect::from_origin_and_size(
5696            DeviceIntPoint::new(
5697                device_size.width - target_size.width - 64,
5698                device_size.height - target_size.height - 64,
5699            ),
5700            target_size,
5701        );
5702
5703        let texture_rect = FramebufferIntRect::from_size(
5704            source_rect.size().cast_unit(),
5705        );
5706
5707        debug_renderer.add_rect(
5708            &target_rect.inflate(1, 1),
5709            1,
5710            debug_colors::RED.into(),
5711        );
5712
5713        if self.zoom_debug_texture.is_none() {
5714            let texture = self.device.create_texture(
5715                ImageBufferKind::Texture2D,
5716                ImageFormat::BGRA8,
5717                source_rect.width(),
5718                source_rect.height(),
5719                TextureFilter::Nearest,
5720                Some(RenderTargetInfo { has_depth: false }),
5721            );
5722
5723            self.zoom_debug_texture = Some(texture);
5724        }
5725
5726        let read_target = DrawTarget::new_default(device_size, self.device.surface_origin_is_top_left());
5728        self.device.blit_render_target(
5729            read_target.into(),
5730            read_target.to_framebuffer_rect(source_rect),
5731            DrawTarget::from_texture(
5732                self.zoom_debug_texture.as_ref().unwrap(),
5733                false,
5734            ),
5735            texture_rect,
5736            TextureFilter::Nearest,
5737        );
5738
5739        self.device.blit_render_target(
5741            ReadTarget::from_texture(
5742                self.zoom_debug_texture.as_ref().unwrap(),
5743            ),
5744            texture_rect,
5745            read_target,
5746            read_target.to_framebuffer_rect(target_rect),
5747            TextureFilter::Nearest,
5748        );
5749    }
5750
5751    fn draw_texture_cache_debug(&mut self, draw_target: &DrawTarget) {
5752        if !self.debug_flags.contains(DebugFlags::TEXTURE_CACHE_DBG) {
5753            return;
5754        }
5755
5756        let debug_renderer = match self.debug.get_mut(&mut self.device) {
5757            Some(render) => render,
5758            None => return,
5759        };
5760
5761        let textures = self.texture_resolver
5762            .texture_cache_map
5763            .values()
5764            .filter(|item| item.category == TextureCacheCategory::Atlas)
5765            .map(|item| &item.texture)
5766            .collect::<Vec<&Texture>>();
5767
5768        fn select_color(texture: &Texture) -> [f32; 4] {
5769            if texture.flags().contains(TextureFlags::IS_SHARED_TEXTURE_CACHE) {
5770                [1.0, 0.5, 0.0, 1.0] } else {
5772                [1.0, 0.0, 1.0, 1.0] }
5774        }
5775
5776        Self::do_debug_blit(
5777            &mut self.device,
5778            debug_renderer,
5779            textures,
5780            draw_target,
5781            if self.debug_flags.contains(DebugFlags::RENDER_TARGET_DBG) { 544 } else { 0 },
5782            &select_color,
5783        );
5784    }
5785
5786    fn do_debug_blit(
5787        device: &mut Device,
5788        debug_renderer: &mut DebugRenderer,
5789        mut textures: Vec<&Texture>,
5790        draw_target: &DrawTarget,
5791        bottom: i32,
5792        select_color: &dyn Fn(&Texture) -> [f32; 4],
5793    ) {
5794        let mut spacing = 16;
5795        let mut size = 512;
5796
5797        let device_size = draw_target.dimensions();
5798        let fb_width = device_size.width;
5799        let fb_height = device_size.height;
5800        let surface_origin_is_top_left = draw_target.surface_origin_is_top_left();
5801
5802        let num_textures = textures.len() as i32;
5803
5804        if num_textures * (size + spacing) > fb_width {
5805            let factor = fb_width as f32 / (num_textures * (size + spacing)) as f32;
5806            size = (size as f32 * factor) as i32;
5807            spacing = (spacing as f32 * factor) as i32;
5808        }
5809
5810        let text_height = 14; let text_margin = 1;
5812        let tag_height = text_height + text_margin * 2;
5813        let tag_y = fb_height - (bottom + spacing + tag_height);
5814        let image_y = tag_y - size;
5815
5816        textures.sort_by_key(|t| t.size_in_bytes());
5822
5823        let mut i = 0;
5824        for texture in textures.iter() {
5825            let dimensions = texture.get_dimensions();
5826            let src_rect = FramebufferIntRect::from_size(
5827                FramebufferIntSize::new(dimensions.width as i32, dimensions.height as i32),
5828            );
5829
5830            let x = fb_width - (spacing + size) * (i as i32 + 1);
5831
5832            if x > fb_width {
5834                return;
5835            }
5836
5837            let tag_rect = rect(x, tag_y, size, tag_height).to_box2d();
5839            let tag_color = select_color(texture);
5840            device.clear_target(
5841                Some(tag_color),
5842                None,
5843                Some(draw_target.to_framebuffer_rect(tag_rect)),
5844            );
5845
5846            let dim = texture.get_dimensions();
5848            let text_rect = tag_rect.inflate(-text_margin, -text_margin);
5849            debug_renderer.add_text(
5850                text_rect.min.x as f32,
5851                text_rect.max.y as f32, &format!("{}x{}", dim.width, dim.height),
5853                ColorU::new(0, 0, 0, 255),
5854                Some(tag_rect.to_f32())
5855            );
5856
5857            let dest_rect = draw_target.to_framebuffer_rect(rect(x, image_y, size, size).to_box2d());
5859            let read_target = ReadTarget::from_texture(texture);
5860
5861            if surface_origin_is_top_left {
5862                device.blit_render_target(
5863                    read_target,
5864                    src_rect,
5865                    *draw_target,
5866                    dest_rect,
5867                    TextureFilter::Linear,
5868                );
5869            } else {
5870                 device.blit_render_target_invert_y(
5872                    read_target,
5873                    src_rect,
5874                    *draw_target,
5875                    dest_rect,
5876                );
5877            }
5878            i += 1;
5879        }
5880    }
5881
5882    fn draw_epoch_debug(&mut self) {
5883        if !self.debug_flags.contains(DebugFlags::EPOCHS) {
5884            return;
5885        }
5886
5887        let debug_renderer = match self.debug.get_mut(&mut self.device) {
5888            Some(render) => render,
5889            None => return,
5890        };
5891
5892        let dy = debug_renderer.line_height();
5893        let x0: f32 = 30.0;
5894        let y0: f32 = 30.0;
5895        let mut y = y0;
5896        let mut text_width = 0.0;
5897        for ((pipeline, document_id), epoch) in  &self.pipeline_info.epochs {
5898            y += dy;
5899            let w = debug_renderer.add_text(
5900                x0, y,
5901                &format!("({:?}, {:?}): {:?}", pipeline, document_id, epoch),
5902                ColorU::new(255, 255, 0, 255),
5903                None,
5904            ).size.width;
5905            text_width = f32::max(text_width, w);
5906        }
5907
5908        let margin = 10.0;
5909        debug_renderer.add_quad(
5910            x0 - margin,
5911            y0 - margin,
5912            x0 + text_width + margin,
5913            y + margin,
5914            ColorU::new(25, 25, 25, 200),
5915            ColorU::new(51, 51, 51, 200),
5916        );
5917    }
5918
5919    fn draw_window_visibility_debug(&mut self) {
5920        if !self.debug_flags.contains(DebugFlags::WINDOW_VISIBILITY_DBG) {
5921            return;
5922        }
5923
5924        let debug_renderer = match self.debug.get_mut(&mut self.device) {
5925            Some(render) => render,
5926            None => return,
5927        };
5928
5929        let x: f32 = 30.0;
5930        let y: f32 = 40.0;
5931
5932        if let CompositorConfig::Native { ref mut compositor, .. } = self.compositor_config {
5933            let visibility = compositor.get_window_visibility(&mut self.device);
5934            let color = if visibility.is_fully_occluded {
5935                ColorU::new(255, 0, 0, 255)
5936
5937            } else {
5938                ColorU::new(0, 0, 255, 255)
5939            };
5940
5941            debug_renderer.add_text(
5942                x, y,
5943                &format!("{:?}", visibility),
5944                color,
5945                None,
5946            );
5947        }
5948
5949
5950    }
5951
5952    fn draw_gpu_cache_debug(&mut self, device_size: DeviceIntSize) {
5953        if !self.debug_flags.contains(DebugFlags::GPU_CACHE_DBG) {
5954            return;
5955        }
5956
5957        let debug_renderer = match self.debug.get_mut(&mut self.device) {
5958            Some(render) => render,
5959            None => return,
5960        };
5961
5962        let (x_off, y_off) = (30f32, 30f32);
5963        let height = self.gpu_cache_texture.get_height()
5964            .min(device_size.height - (y_off as i32) * 2) as usize;
5965        debug_renderer.add_quad(
5966            x_off,
5967            y_off,
5968            x_off + MAX_VERTEX_TEXTURE_WIDTH as f32,
5969            y_off + height as f32,
5970            ColorU::new(80, 80, 80, 80),
5971            ColorU::new(80, 80, 80, 80),
5972        );
5973
5974        let upper = self.gpu_cache_debug_chunks.len().min(height);
5975        for chunk in self.gpu_cache_debug_chunks[0..upper].iter().flatten() {
5976            let color = ColorU::new(250, 0, 0, 200);
5977            debug_renderer.add_quad(
5978                x_off + chunk.address.u as f32,
5979                y_off + chunk.address.v as f32,
5980                x_off + chunk.address.u as f32 + chunk.size as f32,
5981                y_off + chunk.address.v as f32 + 1.0,
5982                color,
5983                color,
5984            );
5985        }
5986    }
5987
5988    pub fn read_pixels_into(&mut self, rect: FramebufferIntRect, format: ImageFormat, output: &mut [u8]) {
5990        self.device.read_pixels_into(rect, format, output);
5991    }
5992
5993    pub fn read_pixels_rgba8(&mut self, rect: FramebufferIntRect) -> Vec<u8> {
5994        let mut pixels = vec![0; (rect.area() * 4) as usize];
5995        self.device.read_pixels_into(rect, ImageFormat::RGBA8, &mut pixels);
5996        pixels
5997    }
5998
5999    pub fn deinit(mut self) {
6001        self.device.begin_frame();
6003        if let CompositorConfig::Native { mut compositor, .. } = self.compositor_config {
6006            for id in self.allocated_native_surfaces.drain() {
6007                compositor.destroy_surface(&mut self.device, id);
6008            }
6009            if self.debug_overlay_state.current_size.is_some() {
6011                compositor.destroy_surface(&mut self.device, NativeSurfaceId::DEBUG_OVERLAY);
6012            }
6013            compositor.deinit(&mut self.device);
6014        }
6015        self.gpu_cache_texture.deinit(&mut self.device);
6016        if let Some(dither_matrix_texture) = self.dither_matrix_texture {
6017            self.device.delete_texture(dither_matrix_texture);
6018        }
6019        if let Some(zoom_debug_texture) = self.zoom_debug_texture {
6020            self.device.delete_texture(zoom_debug_texture);
6021        }
6022        for textures in self.vertex_data_textures.drain(..) {
6023            textures.deinit(&mut self.device);
6024        }
6025        self.texture_upload_pbo_pool.deinit(&mut self.device);
6026        self.staging_texture_pool.delete_textures(&mut self.device);
6027        self.texture_resolver.deinit(&mut self.device);
6028        self.vaos.deinit(&mut self.device);
6029        self.debug.deinit(&mut self.device);
6030
6031        if let Ok(shaders) = Rc::try_unwrap(self.shaders) {
6032            shaders.into_inner().deinit(&mut self.device);
6033        }
6034
6035        if let Some(async_screenshots) = self.async_screenshots.take() {
6036            async_screenshots.deinit(&mut self.device);
6037        }
6038
6039        if let Some(async_frame_recorder) = self.async_frame_recorder.take() {
6040            async_frame_recorder.deinit(&mut self.device);
6041        }
6042
6043        #[cfg(feature = "capture")]
6044        self.device.delete_fbo(self.read_fbo);
6045        #[cfg(feature = "replay")]
6046        for (_, ext) in self.owned_external_images {
6047            self.device.delete_external_texture(ext);
6048        }
6049        self.device.end_frame();
6050    }
6051
6052    pub fn report_memory(&self, swgl: *mut c_void) -> MemoryReport {
6054        let mut report = MemoryReport::default();
6055
6056        self.gpu_cache_texture.report_memory_to(&mut report, self.size_of_ops.as_ref().unwrap());
6058
6059        self.staging_texture_pool.report_memory_to(&mut report, self.size_of_ops.as_ref().unwrap());
6060
6061        for (_id, doc) in &self.active_documents {
6063            let frame_alloc_stats = doc.frame.allocator_memory.get_stats();
6064            report.frame_allocator += frame_alloc_stats.reserved_bytes;
6065            report.render_tasks += doc.frame.render_tasks.report_memory();
6066        }
6067
6068        for textures in &self.vertex_data_textures {
6070            report.vertex_data_textures += textures.size_in_bytes();
6071        }
6072
6073        report += self.texture_resolver.report_memory();
6075
6076        report += self.texture_upload_pbo_pool.report_memory();
6078
6079        report += self.device.report_memory(self.size_of_ops.as_ref().unwrap(), swgl);
6081
6082        report
6083    }
6084
6085    fn set_blend(&mut self, mut blend: bool, framebuffer_kind: FramebufferKind) {
6088        if framebuffer_kind == FramebufferKind::Main &&
6089                self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) {
6090            blend = true
6091        }
6092        self.device.set_blend(blend)
6093    }
6094
6095    fn set_blend_mode_multiply(&mut self, framebuffer_kind: FramebufferKind) {
6096        if framebuffer_kind == FramebufferKind::Main &&
6097                self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) {
6098            self.device.set_blend_mode_show_overdraw();
6099        } else {
6100            self.device.set_blend_mode_multiply();
6101        }
6102    }
6103
6104    fn set_blend_mode_premultiplied_alpha(&mut self, framebuffer_kind: FramebufferKind) {
6105        if framebuffer_kind == FramebufferKind::Main &&
6106                self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) {
6107            self.device.set_blend_mode_show_overdraw();
6108        } else {
6109            self.device.set_blend_mode_premultiplied_alpha();
6110        }
6111    }
6112
6113    fn clear_texture(&mut self, texture: &Texture, color: [f32; 4]) {
6115        self.device.bind_draw_target(DrawTarget::from_texture(
6116            &texture,
6117            false,
6118        ));
6119        self.device.clear_target(Some(color), None, None);
6120    }
6121}
6122
6123bitflags! {
6124    #[derive(Default, Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
6126    pub struct ShaderPrecacheFlags: u32 {
6127        const EMPTY                 = 0;
6129
6130        const ASYNC_COMPILE         = 1 << 2;
6132
6133        const FULL_COMPILE          = 1 << 3;
6135    }
6136}
6137
6138#[derive(Debug, Default)]
6140pub struct FullFrameStats {
6141    pub full_display_list: bool,
6142    pub gecko_display_list_time: f64,
6143    pub wr_display_list_time: f64,
6144    pub scene_build_time: f64,
6145    pub frame_build_time: f64,
6146}
6147
6148impl FullFrameStats {
6149    pub fn merge(&self, other: &FullFrameStats) -> Self {
6150        Self {
6151            full_display_list: self.full_display_list || other.full_display_list,
6152            gecko_display_list_time: self.gecko_display_list_time + other.gecko_display_list_time,
6153            wr_display_list_time: self.wr_display_list_time + other.wr_display_list_time,
6154            scene_build_time: self.scene_build_time + other.scene_build_time,
6155            frame_build_time: self.frame_build_time + other.frame_build_time
6156        }
6157    }
6158
6159    pub fn total(&self) -> f64 {
6160      self.gecko_display_list_time + self.wr_display_list_time + self.scene_build_time + self.frame_build_time
6161    }
6162}
6163
6164#[repr(C)]
6168#[derive(Debug, Default)]
6169pub struct RendererStats {
6170    pub total_draw_calls: usize,
6171    pub alpha_target_count: usize,
6172    pub color_target_count: usize,
6173    pub texture_upload_mb: f64,
6174    pub resource_upload_time: f64,
6175    pub gpu_cache_upload_time: f64,
6176    pub gecko_display_list_time: f64,
6177    pub wr_display_list_time: f64,
6178    pub scene_build_time: f64,
6179    pub frame_build_time: f64,
6180    pub full_display_list: bool,
6181    pub full_paint: bool,
6182}
6183
6184impl RendererStats {
6185    pub fn merge(&mut self, stats: &FullFrameStats) {
6186        self.gecko_display_list_time = stats.gecko_display_list_time;
6187        self.wr_display_list_time = stats.wr_display_list_time;
6188        self.scene_build_time = stats.scene_build_time;
6189        self.frame_build_time = stats.frame_build_time;
6190        self.full_display_list = stats.full_display_list;
6191        self.full_paint = true;
6192    }
6193}
6194
6195#[derive(Debug, Default)]
6198pub struct RenderResults {
6199    pub stats: RendererStats,
6201
6202    pub dirty_rects: Vec<DeviceIntRect>,
6211
6212    pub picture_cache_debug: PictureCacheDebugInfo,
6215}
6216
6217#[cfg(any(feature = "capture", feature = "replay"))]
6218#[cfg_attr(feature = "capture", derive(Serialize))]
6219#[cfg_attr(feature = "replay", derive(Deserialize))]
6220struct PlainTexture {
6221    data: String,
6222    size: DeviceIntSize,
6223    format: ImageFormat,
6224    filter: TextureFilter,
6225    has_depth: bool,
6226    category: Option<TextureCacheCategory>,
6227}
6228
6229
6230#[cfg(any(feature = "capture", feature = "replay"))]
6231#[cfg_attr(feature = "capture", derive(Serialize))]
6232#[cfg_attr(feature = "replay", derive(Deserialize))]
6233struct PlainRenderer {
6234    device_size: Option<DeviceIntSize>,
6235    gpu_cache: PlainTexture,
6236    gpu_cache_frame_id: FrameId,
6237    textures: FastHashMap<CacheTextureId, PlainTexture>,
6238}
6239
6240#[cfg(any(feature = "capture", feature = "replay"))]
6241#[cfg_attr(feature = "capture", derive(Serialize))]
6242#[cfg_attr(feature = "replay", derive(Deserialize))]
6243struct PlainExternalResources {
6244    images: Vec<ExternalCaptureImage>
6245}
6246
6247#[cfg(feature = "replay")]
6248enum CapturedExternalImageData {
6249    NativeTexture(gl::GLuint),
6250    Buffer(Arc<Vec<u8>>),
6251}
6252
6253#[cfg(feature = "replay")]
6254struct DummyExternalImageHandler {
6255    data: FastHashMap<(ExternalImageId, u8), (CapturedExternalImageData, TexelRect)>,
6256}
6257
6258#[cfg(feature = "replay")]
6259impl ExternalImageHandler for DummyExternalImageHandler {
6260    fn lock(&mut self, key: ExternalImageId, channel_index: u8, _is_composited: bool) -> ExternalImage {
6261        let (ref captured_data, ref uv) = self.data[&(key, channel_index)];
6262        ExternalImage {
6263            uv: *uv,
6264            source: match *captured_data {
6265                CapturedExternalImageData::NativeTexture(tid) => ExternalImageSource::NativeTexture(tid),
6266                CapturedExternalImageData::Buffer(ref arc) => ExternalImageSource::RawData(&*arc),
6267            }
6268        }
6269    }
6270    fn unlock(&mut self, _key: ExternalImageId, _channel_index: u8) {}
6271}
6272
6273#[derive(Default)]
6274pub struct PipelineInfo {
6275    pub epochs: FastHashMap<(PipelineId, DocumentId), Epoch>,
6276    pub removed_pipelines: Vec<(PipelineId, DocumentId)>,
6277}
6278
6279impl Renderer {
6280    #[cfg(feature = "capture")]
6281    fn save_texture(
6282        texture: &Texture, category: Option<TextureCacheCategory>, name: &str, root: &PathBuf, device: &mut Device
6283    ) -> PlainTexture {
6284        use std::fs;
6285        use std::io::Write;
6286
6287        let short_path = format!("textures/{}.raw", name);
6288
6289        let bytes_per_pixel = texture.get_format().bytes_per_pixel();
6290        let read_format = texture.get_format();
6291        let rect_size = texture.get_dimensions();
6292
6293        let mut file = fs::File::create(root.join(&short_path))
6294            .expect(&format!("Unable to create {}", short_path));
6295        let bytes_per_texture = (rect_size.width * rect_size.height * bytes_per_pixel) as usize;
6296        let mut data = vec![0; bytes_per_texture];
6297
6298        let rect = device_size_as_framebuffer_size(rect_size).into();
6302
6303        device.attach_read_texture(texture);
6304        #[cfg(feature = "png")]
6305        {
6306            let mut png_data;
6307            let (data_ref, format) = match texture.get_format() {
6308                ImageFormat::RGBAF32 => {
6309                    png_data = vec![0; (rect_size.width * rect_size.height * 4) as usize];
6310                    device.read_pixels_into(rect, ImageFormat::RGBA8, &mut png_data);
6311                    (&png_data, ImageFormat::RGBA8)
6312                }
6313                fm => (&data, fm),
6314            };
6315            CaptureConfig::save_png(
6316                root.join(format!("textures/{}-{}.png", name, 0)),
6317                rect_size, format,
6318                None,
6319                data_ref,
6320            );
6321        }
6322        device.read_pixels_into(rect, read_format, &mut data);
6323        file.write_all(&data)
6324            .unwrap();
6325
6326        PlainTexture {
6327            data: short_path,
6328            size: rect_size,
6329            format: texture.get_format(),
6330            filter: texture.get_filter(),
6331            has_depth: texture.supports_depth(),
6332            category,
6333        }
6334    }
6335
6336    #[cfg(feature = "replay")]
6337    fn load_texture(
6338        target: ImageBufferKind,
6339        plain: &PlainTexture,
6340        rt_info: Option<RenderTargetInfo>,
6341        root: &PathBuf,
6342        device: &mut Device
6343    ) -> (Texture, Vec<u8>)
6344    {
6345        use std::fs::File;
6346        use std::io::Read;
6347
6348        let mut texels = Vec::new();
6349        File::open(root.join(&plain.data))
6350            .expect(&format!("Unable to open texture at {}", plain.data))
6351            .read_to_end(&mut texels)
6352            .unwrap();
6353
6354        let texture = device.create_texture(
6355            target,
6356            plain.format,
6357            plain.size.width,
6358            plain.size.height,
6359            plain.filter,
6360            rt_info,
6361        );
6362        device.upload_texture_immediate(&texture, &texels);
6363
6364        (texture, texels)
6365    }
6366
6367    #[cfg(feature = "capture")]
6368    fn save_capture(
6369        &mut self,
6370        config: CaptureConfig,
6371        deferred_images: Vec<ExternalCaptureImage>,
6372    ) {
6373        use std::fs;
6374        use std::io::Write;
6375        use api::ExternalImageData;
6376        use crate::render_api::CaptureBits;
6377
6378        let root = config.resource_root();
6379
6380        self.device.begin_frame();
6381        let _gm = self.gpu_profiler.start_marker("read GPU data");
6382        self.device.bind_read_target_impl(self.read_fbo, DeviceIntPoint::zero());
6383
6384        if config.bits.contains(CaptureBits::EXTERNAL_RESOURCES) && !deferred_images.is_empty() {
6385            info!("saving external images");
6386            let mut arc_map = FastHashMap::<*const u8, String>::default();
6387            let mut tex_map = FastHashMap::<u32, String>::default();
6388            let handler = self.external_image_handler
6389                .as_mut()
6390                .expect("Unable to lock the external image handler!");
6391            for def in &deferred_images {
6392                info!("\t{}", def.short_path);
6393                let ExternalImageData { id, channel_index, image_type, .. } = def.external;
6394                let ext_image = handler.lock(id, channel_index, false);
6396                let (data, short_path) = match ext_image.source {
6397                    ExternalImageSource::RawData(data) => {
6398                        let arc_id = arc_map.len() + 1;
6399                        match arc_map.entry(data.as_ptr()) {
6400                            Entry::Occupied(e) => {
6401                                (None, e.get().clone())
6402                            }
6403                            Entry::Vacant(e) => {
6404                                let short_path = format!("externals/d{}.raw", arc_id);
6405                                (Some(data.to_vec()), e.insert(short_path).clone())
6406                            }
6407                        }
6408                    }
6409                    ExternalImageSource::NativeTexture(gl_id) => {
6410                        let tex_id = tex_map.len() + 1;
6411                        match tex_map.entry(gl_id) {
6412                            Entry::Occupied(e) => {
6413                                (None, e.get().clone())
6414                            }
6415                            Entry::Vacant(e) => {
6416                                let target = match image_type {
6417                                    ExternalImageType::TextureHandle(target) => target,
6418                                    ExternalImageType::Buffer => unreachable!(),
6419                                };
6420                                info!("\t\tnative texture of target {:?}", target);
6421                                self.device.attach_read_texture_external(gl_id, target);
6422                                let data = self.device.read_pixels(&def.descriptor);
6423                                let short_path = format!("externals/t{}.raw", tex_id);
6424                                (Some(data), e.insert(short_path).clone())
6425                            }
6426                        }
6427                    }
6428                    ExternalImageSource::Invalid => {
6429                        info!("\t\tinvalid source!");
6430                        (None, String::new())
6431                    }
6432                };
6433                if let Some(bytes) = data {
6434                    fs::File::create(root.join(&short_path))
6435                        .expect(&format!("Unable to create {}", short_path))
6436                        .write_all(&bytes)
6437                        .unwrap();
6438                    #[cfg(feature = "png")]
6439                    CaptureConfig::save_png(
6440                        root.join(&short_path).with_extension("png"),
6441                        def.descriptor.size,
6442                        def.descriptor.format,
6443                        def.descriptor.stride,
6444                        &bytes,
6445                    );
6446                }
6447                let plain = PlainExternalImage {
6448                    data: short_path,
6449                    external: def.external,
6450                    uv: ext_image.uv,
6451                };
6452                config.serialize_for_resource(&plain, &def.short_path);
6453            }
6454            for def in &deferred_images {
6455                handler.unlock(def.external.id, def.external.channel_index);
6456            }
6457            let plain_external = PlainExternalResources {
6458                images: deferred_images,
6459            };
6460            config.serialize_for_resource(&plain_external, "external_resources");
6461        }
6462
6463        if config.bits.contains(CaptureBits::FRAME) {
6464            let path_textures = root.join("textures");
6465            if !path_textures.is_dir() {
6466                fs::create_dir(&path_textures).unwrap();
6467            }
6468
6469            info!("saving GPU cache");
6470            self.update_gpu_cache(); let mut plain_self = PlainRenderer {
6472                device_size: self.device_size,
6473                gpu_cache: Self::save_texture(
6474                    self.gpu_cache_texture.get_texture(),
6475                    None, "gpu", &root, &mut self.device,
6476                ),
6477                gpu_cache_frame_id: self.gpu_cache_frame_id,
6478                textures: FastHashMap::default(),
6479            };
6480
6481            info!("saving cached textures");
6482            for (id, item) in &self.texture_resolver.texture_cache_map {
6483                let file_name = format!("cache-{}", plain_self.textures.len() + 1);
6484                info!("\t{}", file_name);
6485                let plain = Self::save_texture(&item.texture, Some(item.category), &file_name, &root, &mut self.device);
6486                plain_self.textures.insert(*id, plain);
6487            }
6488
6489            config.serialize_for_resource(&plain_self, "renderer");
6490        }
6491
6492        self.device.reset_read_target();
6493        self.device.end_frame();
6494
6495        let mut stats_file = fs::File::create(config.root.join("profiler-stats.txt"))
6496            .expect(&format!("Unable to create profiler-stats.txt"));
6497        if self.debug_flags.intersects(DebugFlags::PROFILER_DBG | DebugFlags::PROFILER_CAPTURE) {
6498            self.profiler.dump_stats(&mut stats_file).unwrap();
6499        } else {
6500            writeln!(stats_file, "Turn on PROFILER_DBG or PROFILER_CAPTURE to get stats here!").unwrap();
6501        }
6502
6503        info!("done.");
6504    }
6505
6506    #[cfg(feature = "replay")]
6507    fn load_capture(
6508        &mut self,
6509        config: CaptureConfig,
6510        plain_externals: Vec<PlainExternalImage>,
6511    ) {
6512        use std::{fs::File, io::Read};
6513
6514        info!("loading external buffer-backed images");
6515        assert!(self.texture_resolver.external_images.is_empty());
6516        let mut raw_map = FastHashMap::<String, Arc<Vec<u8>>>::default();
6517        let mut image_handler = DummyExternalImageHandler {
6518            data: FastHashMap::default(),
6519        };
6520
6521        let root = config.resource_root();
6522
6523        for plain_ext in plain_externals {
6528            let data = match raw_map.entry(plain_ext.data) {
6529                Entry::Occupied(e) => e.get().clone(),
6530                Entry::Vacant(e) => {
6531                    let mut buffer = Vec::new();
6532                    File::open(root.join(e.key()))
6533                        .expect(&format!("Unable to open {}", e.key()))
6534                        .read_to_end(&mut buffer)
6535                        .unwrap();
6536                    e.insert(Arc::new(buffer)).clone()
6537                }
6538            };
6539            let ext = plain_ext.external;
6540            let value = (CapturedExternalImageData::Buffer(data), plain_ext.uv);
6541            image_handler.data.insert((ext.id, ext.channel_index), value);
6542        }
6543
6544        if let Some(external_resources) = config.deserialize_for_resource::<PlainExternalResources, _>("external_resources") {
6545            info!("loading external texture-backed images");
6546            let mut native_map = FastHashMap::<String, gl::GLuint>::default();
6547            for ExternalCaptureImage { short_path, external, descriptor } in external_resources.images {
6548                let target = match external.image_type {
6549                    ExternalImageType::TextureHandle(target) => target,
6550                    ExternalImageType::Buffer => continue,
6551                };
6552                let plain_ext = config.deserialize_for_resource::<PlainExternalImage, _>(&short_path)
6553                    .expect(&format!("Unable to read {}.ron", short_path));
6554                let key = (external.id, external.channel_index);
6555
6556                let tid = match native_map.entry(plain_ext.data) {
6557                    Entry::Occupied(e) => e.get().clone(),
6558                    Entry::Vacant(e) => {
6559                        let plain_tex = PlainTexture {
6560                            data: e.key().clone(),
6561                            size: descriptor.size,
6562                            format: descriptor.format,
6563                            filter: TextureFilter::Linear,
6564                            has_depth: false,
6565                            category: None,
6566                        };
6567                        let t = Self::load_texture(
6568                            target,
6569                            &plain_tex,
6570                            None,
6571                            &root,
6572                            &mut self.device
6573                        );
6574                        let extex = t.0.into_external();
6575                        self.owned_external_images.insert(key, extex.clone());
6576                        e.insert(extex.internal_id()).clone()
6577                    }
6578                };
6579
6580                let value = (CapturedExternalImageData::NativeTexture(tid), plain_ext.uv);
6581                image_handler.data.insert(key, value);
6582            }
6583        }
6584
6585        self.device.begin_frame();
6586        self.gpu_cache_texture.remove_texture(&mut self.device);
6587
6588        if let Some(renderer) = config.deserialize_for_resource::<PlainRenderer, _>("renderer") {
6589            info!("loading cached textures");
6590            self.device_size = renderer.device_size;
6591
6592            for (_id, item) in self.texture_resolver.texture_cache_map.drain() {
6593                self.device.delete_texture(item.texture);
6594            }
6595            for (id, texture) in renderer.textures {
6596                info!("\t{}", texture.data);
6597                let target = ImageBufferKind::Texture2D;
6598                let t = Self::load_texture(
6599                    target,
6600                    &texture,
6601                    Some(RenderTargetInfo { has_depth: texture.has_depth }),
6602                    &root,
6603                    &mut self.device
6604                );
6605                self.texture_resolver.texture_cache_map.insert(id, CacheTexture {
6606                    texture: t.0,
6607                    category: texture.category.unwrap_or(TextureCacheCategory::Standalone),
6608                });
6609            }
6610
6611            info!("loading gpu cache");
6612            let (t, gpu_cache_data) = Self::load_texture(
6613                ImageBufferKind::Texture2D,
6614                &renderer.gpu_cache,
6615                Some(RenderTargetInfo { has_depth: false }),
6616                &root,
6617                &mut self.device,
6618            );
6619            self.gpu_cache_texture.load_from_data(t, gpu_cache_data);
6620            self.gpu_cache_frame_id = renderer.gpu_cache_frame_id;
6621        } else {
6622            info!("loading cached textures");
6623            self.device.begin_frame();
6624            for (_id, item) in self.texture_resolver.texture_cache_map.drain() {
6625                self.device.delete_texture(item.texture);
6626            }
6627        }
6628        self.device.end_frame();
6629
6630        self.external_image_handler = Some(Box::new(image_handler) as Box<_>);
6631        info!("done.");
6632    }
6633}
6634
6635#[derive(Clone, Copy, PartialEq)]
6636enum FramebufferKind {
6637    Main,
6638    Other,
6639}
6640
6641fn should_skip_batch(kind: &BatchKind, flags: DebugFlags) -> bool {
6642    match kind {
6643        BatchKind::TextRun(_) => {
6644            flags.contains(DebugFlags::DISABLE_TEXT_PRIMS)
6645        }
6646        BatchKind::Brush(BrushBatchKind::LinearGradient) => {
6647            flags.contains(DebugFlags::DISABLE_GRADIENT_PRIMS)
6648        }
6649        _ => false,
6650    }
6651}
6652
6653impl CompositeState {
6654    fn composite_native(
6657        &self,
6658        clear_color: ColorF,
6659        dirty_rects: &[DeviceIntRect],
6660        device: &mut Device,
6661        compositor: &mut dyn Compositor,
6662    ) {
6663        for surface in &self.descriptor.surfaces {
6667            compositor.add_surface(
6668                device,
6669                surface.surface_id.expect("bug: no native surface allocated"),
6670                surface.transform,
6671                surface.clip_rect.to_i32(),
6672                surface.image_rendering,
6673                surface.rounded_clip_rect.to_i32(),
6674                surface.rounded_clip_radii,
6675            );
6676        }
6677        compositor.start_compositing(device, clear_color, dirty_rects, &[]);
6678    }
6679}
6680
6681mod tests {
6682    #[test]
6683    fn test_buffer_damage_tracker() {
6684        use super::BufferDamageTracker;
6685        use api::units::{DevicePoint, DeviceRect, DeviceSize};
6686
6687        let mut tracker = BufferDamageTracker::default();
6688        assert_eq!(tracker.get_damage_rect(0), None);
6689        assert_eq!(tracker.get_damage_rect(1), Some(DeviceRect::zero()));
6690        assert_eq!(tracker.get_damage_rect(2), Some(DeviceRect::zero()));
6691        assert_eq!(tracker.get_damage_rect(3), Some(DeviceRect::zero()));
6692
6693        let damage1 = DeviceRect::from_origin_and_size(DevicePoint::new(10.0, 10.0), DeviceSize::new(10.0, 10.0));
6694        let damage2 = DeviceRect::from_origin_and_size(DevicePoint::new(20.0, 20.0), DeviceSize::new(10.0, 10.0));
6695        let combined = damage1.union(&damage2);
6696
6697        tracker.push_dirty_rect(&damage1);
6698        assert_eq!(tracker.get_damage_rect(0), None);
6699        assert_eq!(tracker.get_damage_rect(1), Some(DeviceRect::zero()));
6700        assert_eq!(tracker.get_damage_rect(2), Some(damage1));
6701        assert_eq!(tracker.get_damage_rect(3), Some(damage1));
6702
6703        tracker.push_dirty_rect(&damage2);
6704        assert_eq!(tracker.get_damage_rect(0), None);
6705        assert_eq!(tracker.get_damage_rect(1), Some(DeviceRect::zero()));
6706        assert_eq!(tracker.get_damage_rect(2), Some(damage2));
6707        assert_eq!(tracker.get_damage_rect(3), Some(combined));
6708    }
6709}