1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 //! The high-level module responsible for interfacing with the GPU.
6 //!
7 //! Much of WebRender's design is driven by separating work into different
8 //! threads. To avoid the complexities of multi-threaded GPU access, we restrict
9 //! all communication with the GPU to one thread, the render thread. But since
10 //! issuing GPU commands is often a bottleneck, we move everything else (i.e.
11 //! the computation of what commands to issue) to another thread, the
12 //! RenderBackend thread. The RenderBackend, in turn, may delegate work to other
13 //! thread (like the SceneBuilder threads or Rayon workers), but the
14 //! Render-vs-RenderBackend distinction is the most important.
15 //!
16 //! The consumer is responsible for initializing the render thread before
17 //! calling into WebRender, which means that this module also serves as the
18 //! initial entry point into WebRender, and is responsible for spawning the
19 //! various other threads discussed above. That said, WebRender initialization
20 //! returns both the `Renderer` instance as well as a channel for communicating
21 //! directly with the `RenderBackend`. Aside from a few high-level operations
22 //! like 'render now', most of interesting commands from the consumer go over
23 //! that channel and operate on the `RenderBackend`.
24 
25 use api::{BlobImageHandler, ColorF, ColorU, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
26 use api::{DocumentId, Epoch, ExternalImageId};
27 use api::{ExternalImageType, FontRenderMode, FrameMsg, ImageFormat, PipelineId};
28 use api::{ImageRendering, Checkpoint, NotificationRequest};
29 use api::{MemoryReport, VoidPtrToSizeFn};
30 use api::{RenderApiSender, RenderNotifier, TexelRect, TextureTarget};
31 use api::{channel};
32 use api::DebugCommand;
33 pub use api::DebugFlags;
34 use api::channel::PayloadReceiverHelperMethods;
35 use batch::{BatchKind, BatchTextures, BrushBatchKind};
36 #[cfg(any(feature = "capture", feature = "replay"))]
37 use capture::{CaptureConfig, ExternalCaptureImage, PlainExternalImage};
38 use debug_colors;
39 use debug_render::{DebugItem, DebugRenderer};
40 use device::{DepthFunction, Device, GpuFrameId, Program, UploadMethod, Texture, PBO};
41 use device::{DrawTarget, ExternalTexture, FBOId, ReadTarget, TextureSlot};
42 use device::{ShaderError, TextureFilter, TextureFlags,
43              VertexUsageHint, VAO, VBO, CustomVAO};
44 use device::{ProgramCache, ReadPixelsFormat};
45 use device::query::GpuTimer;
46 use euclid::rect;
47 use euclid::Transform3D;
48 use frame_builder::{ChasePrimitive, FrameBuilderConfig};
49 use gleam::gl;
50 use glyph_rasterizer::{GlyphFormat, GlyphRasterizer};
51 use gpu_cache::{GpuBlockData, GpuCacheUpdate, GpuCacheUpdateList};
52 use gpu_cache::{GpuCacheDebugChunk, GpuCacheDebugCmd};
53 #[cfg(feature = "pathfinder")]
54 use gpu_glyph_renderer::GpuGlyphRenderer;
55 use gpu_types::ScalingInstance;
56 use internal_types::{TextureSource, ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE, ResourceCacheError};
57 use internal_types::{CacheTextureId, DebugOutput, FastHashMap, LayerIndex, RenderedDocument, ResultMsg};
58 use internal_types::{TextureCacheAllocationKind, TextureCacheUpdate, TextureUpdateList, TextureUpdateSource};
59 use internal_types::{RenderTargetInfo, SavedTargetIndex};
60 use malloc_size_of::MallocSizeOfOps;
61 use picture::{RecordedDirtyRegion, TileCache};
62 use prim_store::DeferredResolve;
63 use profiler::{BackendProfileCounters, FrameProfileCounters, TimeProfileCounter,
64                GpuProfileTag, RendererProfileCounters, RendererProfileTimers};
65 use profiler::{Profiler, ChangeIndicator};
66 use device::query::GpuProfiler;
67 use rayon::{ThreadPool, ThreadPoolBuilder};
68 use record::ApiRecordingReceiver;
69 use render_backend::{FrameId, RenderBackend};
70 use scene_builder::{SceneBuilder, LowPrioritySceneBuilder};
71 use shade::{Shaders, WrShaders};
72 use smallvec::SmallVec;
73 use render_task::{RenderTask, RenderTaskKind, RenderTaskTree};
74 use resource_cache::ResourceCache;
75 use util::drain_filter;
76 
77 use std;
78 use std::cmp;
79 use std::collections::VecDeque;
80 use std::collections::hash_map::Entry;
81 use std::f32;
82 use std::mem;
83 use std::os::raw::c_void;
84 use std::path::PathBuf;
85 use std::rc::Rc;
86 use std::sync::Arc;
87 use std::sync::atomic::{AtomicBool, Ordering};
88 use std::sync::mpsc::{channel, Receiver};
89 use std::thread;
90 use std::cell::RefCell;
91 use texture_cache::TextureCache;
92 use thread_profiler::{register_thread_with_profiler, write_profile};
93 use tiling::{AlphaRenderTarget, ColorRenderTarget};
94 use tiling::{BlitJob, BlitJobSource, RenderPass, RenderPassKind, RenderTargetList};
95 use tiling::{Frame, RenderTarget, RenderTargetKind, TextureCacheRenderTarget};
96 #[cfg(not(feature = "pathfinder"))]
97 use tiling::GlyphJob;
98 use time::precise_time_ns;
99 
100 cfg_if! {
101     if #[cfg(feature = "debugger")] {
102         use serde_json;
103         use debug_server::{self, DebugServer};
104     } else {
105         use api::ApiMsg;
106         use api::channel::MsgSender;
107     }
108 }
109 
110 /// Is only false if no WR instances have ever been created.
111 static HAS_BEEN_INITIALIZED: AtomicBool = AtomicBool::new(false);
112 
113 /// Returns true if a WR instance has ever been initialized in this process.
wr_has_been_initialized() -> bool114 pub fn wr_has_been_initialized() -> bool {
115     HAS_BEEN_INITIALIZED.load(Ordering::SeqCst)
116 }
117 
118 pub const MAX_VERTEX_TEXTURE_WIDTH: usize = 1024;
119 /// Enabling this toggle would force the GPU cache scattered texture to
120 /// be resized every frame, which enables GPU debuggers to see if this
121 /// is performed correctly.
122 const GPU_CACHE_RESIZE_TEST: bool = false;
123 
124 /// Number of GPU blocks per UV rectangle provided for an image.
125 pub const BLOCKS_PER_UV_RECT: usize = 2;
126 
127 const GPU_TAG_BRUSH_LINEAR_GRADIENT: GpuProfileTag = GpuProfileTag {
128     label: "B_LinearGradient",
129     color: debug_colors::POWDERBLUE,
130 };
131 const GPU_TAG_BRUSH_RADIAL_GRADIENT: GpuProfileTag = GpuProfileTag {
132     label: "B_RadialGradient",
133     color: debug_colors::LIGHTPINK,
134 };
135 const GPU_TAG_BRUSH_YUV_IMAGE: GpuProfileTag = GpuProfileTag {
136     label: "B_YuvImage",
137     color: debug_colors::DARKGREEN,
138 };
139 const GPU_TAG_BRUSH_MIXBLEND: GpuProfileTag = GpuProfileTag {
140     label: "B_MixBlend",
141     color: debug_colors::MAGENTA,
142 };
143 const GPU_TAG_BRUSH_BLEND: GpuProfileTag = GpuProfileTag {
144     label: "B_Blend",
145     color: debug_colors::ORANGE,
146 };
147 const GPU_TAG_BRUSH_IMAGE: GpuProfileTag = GpuProfileTag {
148     label: "B_Image",
149     color: debug_colors::SPRINGGREEN,
150 };
151 const GPU_TAG_BRUSH_SOLID: GpuProfileTag = GpuProfileTag {
152     label: "B_Solid",
153     color: debug_colors::RED,
154 };
155 const GPU_TAG_CACHE_CLIP: GpuProfileTag = GpuProfileTag {
156     label: "C_Clip",
157     color: debug_colors::PURPLE,
158 };
159 const GPU_TAG_CACHE_BORDER: GpuProfileTag = GpuProfileTag {
160     label: "C_Border",
161     color: debug_colors::CORNSILK,
162 };
163 const GPU_TAG_CACHE_LINE_DECORATION: GpuProfileTag = GpuProfileTag {
164     label: "C_LineDecoration",
165     color: debug_colors::YELLOWGREEN,
166 };
167 const GPU_TAG_SETUP_TARGET: GpuProfileTag = GpuProfileTag {
168     label: "target init",
169     color: debug_colors::SLATEGREY,
170 };
171 const GPU_TAG_SETUP_DATA: GpuProfileTag = GpuProfileTag {
172     label: "data init",
173     color: debug_colors::LIGHTGREY,
174 };
175 const GPU_TAG_PRIM_SPLIT_COMPOSITE: GpuProfileTag = GpuProfileTag {
176     label: "SplitComposite",
177     color: debug_colors::DARKBLUE,
178 };
179 const GPU_TAG_PRIM_TEXT_RUN: GpuProfileTag = GpuProfileTag {
180     label: "TextRun",
181     color: debug_colors::BLUE,
182 };
183 const GPU_TAG_BLUR: GpuProfileTag = GpuProfileTag {
184     label: "Blur",
185     color: debug_colors::VIOLET,
186 };
187 const GPU_TAG_BLIT: GpuProfileTag = GpuProfileTag {
188     label: "Blit",
189     color: debug_colors::LIME,
190 };
191 const GPU_TAG_SCALE: GpuProfileTag = GpuProfileTag {
192     label: "Scale",
193     color: debug_colors::GHOSTWHITE,
194 };
195 
196 const GPU_SAMPLER_TAG_ALPHA: GpuProfileTag = GpuProfileTag {
197     label: "Alpha Targets",
198     color: debug_colors::BLACK,
199 };
200 const GPU_SAMPLER_TAG_OPAQUE: GpuProfileTag = GpuProfileTag {
201     label: "Opaque Pass",
202     color: debug_colors::BLACK,
203 };
204 const GPU_SAMPLER_TAG_TRANSPARENT: GpuProfileTag = GpuProfileTag {
205     label: "Transparent Pass",
206     color: debug_colors::BLACK,
207 };
208 
209 /// The clear color used for the texture cache when the debug display is enabled.
210 /// We use a shade of blue so that we can still identify completely blue items in
211 /// the texture cache.
212 const TEXTURE_CACHE_DBG_CLEAR_COLOR: [f32; 4] = [0.0, 0.0, 0.8, 1.0];
213 
214 impl BatchKind {
215     #[cfg(feature = "debugger")]
debug_name(&self) -> &'static str216     fn debug_name(&self) -> &'static str {
217         match *self {
218             BatchKind::SplitComposite => "SplitComposite",
219             BatchKind::Brush(kind) => {
220                 match kind {
221                     BrushBatchKind::Solid => "Brush (Solid)",
222                     BrushBatchKind::Image(..) => "Brush (Image)",
223                     BrushBatchKind::Blend => "Brush (Blend)",
224                     BrushBatchKind::MixBlend { .. } => "Brush (Composite)",
225                     BrushBatchKind::YuvImage(..) => "Brush (YuvImage)",
226                     BrushBatchKind::RadialGradient => "Brush (RadialGradient)",
227                     BrushBatchKind::LinearGradient => "Brush (LinearGradient)",
228                 }
229             }
230             BatchKind::TextRun(_) => "TextRun",
231         }
232     }
233 
sampler_tag(&self) -> GpuProfileTag234     fn sampler_tag(&self) -> GpuProfileTag {
235         match *self {
236             BatchKind::SplitComposite => GPU_TAG_PRIM_SPLIT_COMPOSITE,
237             BatchKind::Brush(kind) => {
238                 match kind {
239                     BrushBatchKind::Solid => GPU_TAG_BRUSH_SOLID,
240                     BrushBatchKind::Image(..) => GPU_TAG_BRUSH_IMAGE,
241                     BrushBatchKind::Blend => GPU_TAG_BRUSH_BLEND,
242                     BrushBatchKind::MixBlend { .. } => GPU_TAG_BRUSH_MIXBLEND,
243                     BrushBatchKind::YuvImage(..) => GPU_TAG_BRUSH_YUV_IMAGE,
244                     BrushBatchKind::RadialGradient => GPU_TAG_BRUSH_RADIAL_GRADIENT,
245                     BrushBatchKind::LinearGradient => GPU_TAG_BRUSH_LINEAR_GRADIENT,
246                 }
247             }
248             BatchKind::TextRun(_) => GPU_TAG_PRIM_TEXT_RUN,
249         }
250     }
251 }
252 
flag_changed(before: DebugFlags, after: DebugFlags, select: DebugFlags) -> Option<bool>253 fn flag_changed(before: DebugFlags, after: DebugFlags, select: DebugFlags) -> Option<bool> {
254     if before & select != after & select {
255         Some(after.contains(select))
256     } else {
257         None
258     }
259 }
260 
261 #[repr(C)]
262 #[derive(Copy, Clone, Debug)]
263 pub enum ShaderColorMode {
264     FromRenderPassMode = 0,
265     Alpha = 1,
266     SubpixelConstantTextColor = 2,
267     SubpixelWithBgColorPass0 = 3,
268     SubpixelWithBgColorPass1 = 4,
269     SubpixelWithBgColorPass2 = 5,
270     SubpixelDualSource = 6,
271     Bitmap = 7,
272     ColorBitmap = 8,
273     Image = 9,
274 }
275 
276 impl From<GlyphFormat> for ShaderColorMode {
from(format: GlyphFormat) -> ShaderColorMode277     fn from(format: GlyphFormat) -> ShaderColorMode {
278         match format {
279             GlyphFormat::Alpha | GlyphFormat::TransformedAlpha => ShaderColorMode::Alpha,
280             GlyphFormat::Subpixel | GlyphFormat::TransformedSubpixel => {
281                 panic!("Subpixel glyph formats must be handled separately.");
282             }
283             GlyphFormat::Bitmap => ShaderColorMode::Bitmap,
284             GlyphFormat::ColorBitmap => ShaderColorMode::ColorBitmap,
285         }
286     }
287 }
288 
289 /// Enumeration of the texture samplers used across the various WebRender shaders.
290 ///
291 /// Each variant corresponds to a uniform declared in shader source. We only bind
292 /// the variants we need for a given shader, so not every variant is bound for every
293 /// batch.
294 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
295 pub(crate) enum TextureSampler {
296     Color0,
297     Color1,
298     Color2,
299     PrevPassAlpha,
300     PrevPassColor,
301     GpuCache,
302     TransformPalette,
303     RenderTasks,
304     Dither,
305     PrimitiveHeadersF,
306     PrimitiveHeadersI,
307 }
308 
309 impl TextureSampler {
color(n: usize) -> TextureSampler310     pub(crate) fn color(n: usize) -> TextureSampler {
311         match n {
312             0 => TextureSampler::Color0,
313             1 => TextureSampler::Color1,
314             2 => TextureSampler::Color2,
315             _ => {
316                 panic!("There are only 3 color samplers.");
317             }
318         }
319     }
320 }
321 
322 impl Into<TextureSlot> for TextureSampler {
into(self) -> TextureSlot323     fn into(self) -> TextureSlot {
324         match self {
325             TextureSampler::Color0 => TextureSlot(0),
326             TextureSampler::Color1 => TextureSlot(1),
327             TextureSampler::Color2 => TextureSlot(2),
328             TextureSampler::PrevPassAlpha => TextureSlot(3),
329             TextureSampler::PrevPassColor => TextureSlot(4),
330             TextureSampler::GpuCache => TextureSlot(5),
331             TextureSampler::TransformPalette => TextureSlot(6),
332             TextureSampler::RenderTasks => TextureSlot(7),
333             TextureSampler::Dither => TextureSlot(8),
334             TextureSampler::PrimitiveHeadersF => TextureSlot(9),
335             TextureSampler::PrimitiveHeadersI => TextureSlot(10),
336         }
337     }
338 }
339 
340 #[derive(Debug, Clone, Copy)]
341 #[repr(C)]
342 pub struct PackedVertex {
343     pub pos: [f32; 2],
344 }
345 
346 pub(crate) mod desc {
347     use device::{VertexAttribute, VertexAttributeKind, VertexDescriptor};
348 
349     pub const PRIM_INSTANCES: VertexDescriptor = VertexDescriptor {
350         vertex_attributes: &[
351             VertexAttribute {
352                 name: "aPosition",
353                 count: 2,
354                 kind: VertexAttributeKind::F32,
355             },
356         ],
357         instance_attributes: &[
358             VertexAttribute {
359                 name: "aData",
360                 count: 4,
361                 kind: VertexAttributeKind::I32,
362             },
363         ],
364     };
365 
366     pub const BLUR: VertexDescriptor = VertexDescriptor {
367         vertex_attributes: &[
368             VertexAttribute {
369                 name: "aPosition",
370                 count: 2,
371                 kind: VertexAttributeKind::F32,
372             },
373         ],
374         instance_attributes: &[
375             VertexAttribute {
376                 name: "aBlurRenderTaskAddress",
377                 count: 1,
378                 kind: VertexAttributeKind::I32,
379             },
380             VertexAttribute {
381                 name: "aBlurSourceTaskAddress",
382                 count: 1,
383                 kind: VertexAttributeKind::I32,
384             },
385             VertexAttribute {
386                 name: "aBlurDirection",
387                 count: 1,
388                 kind: VertexAttributeKind::I32,
389             },
390         ],
391     };
392 
393     pub const LINE: VertexDescriptor = VertexDescriptor {
394         vertex_attributes: &[
395             VertexAttribute {
396                 name: "aPosition",
397                 count: 2,
398                 kind: VertexAttributeKind::F32,
399             },
400         ],
401         instance_attributes: &[
402             VertexAttribute {
403                 name: "aTaskRect",
404                 count: 4,
405                 kind: VertexAttributeKind::F32,
406             },
407             VertexAttribute {
408                 name: "aLocalSize",
409                 count: 2,
410                 kind: VertexAttributeKind::F32,
411             },
412             VertexAttribute {
413                 name: "aWavyLineThickness",
414                 count: 1,
415                 kind: VertexAttributeKind::F32,
416             },
417             VertexAttribute {
418                 name: "aStyle",
419                 count: 1,
420                 kind: VertexAttributeKind::I32,
421             },
422             VertexAttribute {
423                 name: "aOrientation",
424                 count: 1,
425                 kind: VertexAttributeKind::I32,
426             },
427         ],
428     };
429 
430     pub const BORDER: VertexDescriptor = VertexDescriptor {
431         vertex_attributes: &[
432             VertexAttribute {
433                 name: "aPosition",
434                 count: 2,
435                 kind: VertexAttributeKind::F32,
436             },
437         ],
438         instance_attributes: &[
439             VertexAttribute {
440                 name: "aTaskOrigin",
441                 count: 2,
442                 kind: VertexAttributeKind::F32,
443             },
444             VertexAttribute {
445                 name: "aRect",
446                 count: 4,
447                 kind: VertexAttributeKind::F32,
448             },
449             VertexAttribute {
450                 name: "aColor0",
451                 count: 4,
452                 kind: VertexAttributeKind::F32,
453             },
454             VertexAttribute {
455                 name: "aColor1",
456                 count: 4,
457                 kind: VertexAttributeKind::F32,
458             },
459             VertexAttribute {
460                 name: "aFlags",
461                 count: 1,
462                 kind: VertexAttributeKind::I32,
463             },
464             VertexAttribute {
465                 name: "aWidths",
466                 count: 2,
467                 kind: VertexAttributeKind::F32,
468             },
469             VertexAttribute {
470                 name: "aRadii",
471                 count: 2,
472                 kind: VertexAttributeKind::F32,
473             },
474             VertexAttribute {
475                 name: "aClipParams1",
476                 count: 4,
477                 kind: VertexAttributeKind::F32,
478             },
479             VertexAttribute {
480                 name: "aClipParams2",
481                 count: 4,
482                 kind: VertexAttributeKind::F32,
483             },
484         ],
485     };
486 
487     pub const SCALE: VertexDescriptor = VertexDescriptor {
488         vertex_attributes: &[
489             VertexAttribute {
490                 name: "aPosition",
491                 count: 2,
492                 kind: VertexAttributeKind::F32,
493             },
494         ],
495         instance_attributes: &[
496             VertexAttribute {
497                 name: "aScaleRenderTaskAddress",
498                 count: 1,
499                 kind: VertexAttributeKind::I32,
500             },
501             VertexAttribute {
502                 name: "aScaleSourceTaskAddress",
503                 count: 1,
504                 kind: VertexAttributeKind::I32,
505             },
506         ],
507     };
508 
509     pub const CLIP: VertexDescriptor = VertexDescriptor {
510         vertex_attributes: &[
511             VertexAttribute {
512                 name: "aPosition",
513                 count: 2,
514                 kind: VertexAttributeKind::F32,
515             },
516         ],
517         instance_attributes: &[
518             VertexAttribute {
519                 name: "aClipRenderTaskAddress",
520                 count: 1,
521                 kind: VertexAttributeKind::I32,
522             },
523             VertexAttribute {
524                 name: "aClipTransformId",
525                 count: 1,
526                 kind: VertexAttributeKind::I32,
527             },
528             VertexAttribute {
529                 name: "aPrimTransformId",
530                 count: 1,
531                 kind: VertexAttributeKind::I32,
532             },
533             VertexAttribute {
534                 name: "aClipDataResourceAddress",
535                 count: 4,
536                 kind: VertexAttributeKind::U16,
537             },
538             VertexAttribute {
539                 name: "aClipLocalPos",
540                 count: 2,
541                 kind: VertexAttributeKind::F32,
542             },
543             VertexAttribute {
544                 name: "aClipTileRect",
545                 count: 4,
546                 kind: VertexAttributeKind::F32,
547             },
548             VertexAttribute {
549                 name: "aClipDeviceArea",
550                 count: 4,
551                 kind: VertexAttributeKind::F32,
552             },
553             VertexAttribute {
554                 name: "aClipSnapOffsets",
555                 count: 4,
556                 kind: VertexAttributeKind::F32,
557             }
558         ],
559     };
560 
561     pub const GPU_CACHE_UPDATE: VertexDescriptor = VertexDescriptor {
562         vertex_attributes: &[
563             VertexAttribute {
564                 name: "aPosition",
565                 count: 2,
566                 kind: VertexAttributeKind::U16Norm,
567             },
568             VertexAttribute {
569                 name: "aValue",
570                 count: 4,
571                 kind: VertexAttributeKind::F32,
572             },
573         ],
574         instance_attributes: &[],
575     };
576 
577     pub const VECTOR_STENCIL: VertexDescriptor = VertexDescriptor {
578         vertex_attributes: &[
579             VertexAttribute {
580                 name: "aPosition",
581                 count: 2,
582                 kind: VertexAttributeKind::F32,
583             },
584         ],
585         instance_attributes: &[
586             VertexAttribute {
587                 name: "aFromPosition",
588                 count: 2,
589                 kind: VertexAttributeKind::F32,
590             },
591             VertexAttribute {
592                 name: "aCtrlPosition",
593                 count: 2,
594                 kind: VertexAttributeKind::F32,
595             },
596             VertexAttribute {
597                 name: "aToPosition",
598                 count: 2,
599                 kind: VertexAttributeKind::F32,
600             },
601             VertexAttribute {
602                 name: "aFromNormal",
603                 count: 2,
604                 kind: VertexAttributeKind::F32,
605             },
606             VertexAttribute {
607                 name: "aCtrlNormal",
608                 count: 2,
609                 kind: VertexAttributeKind::F32,
610             },
611             VertexAttribute {
612                 name: "aToNormal",
613                 count: 2,
614                 kind: VertexAttributeKind::F32,
615             },
616             VertexAttribute {
617                 name: "aPathID",
618                 count: 1,
619                 kind: VertexAttributeKind::U16,
620             },
621             VertexAttribute {
622                 name: "aPad",
623                 count: 1,
624                 kind: VertexAttributeKind::U16,
625             },
626         ],
627     };
628 
629     pub const VECTOR_COVER: VertexDescriptor = VertexDescriptor {
630         vertex_attributes: &[
631             VertexAttribute {
632                 name: "aPosition",
633                 count: 2,
634                 kind: VertexAttributeKind::F32,
635             },
636         ],
637         instance_attributes: &[
638             VertexAttribute {
639                 name: "aTargetRect",
640                 count: 4,
641                 kind: VertexAttributeKind::I32,
642             },
643             VertexAttribute {
644                 name: "aStencilOrigin",
645                 count: 2,
646                 kind: VertexAttributeKind::I32,
647             },
648             VertexAttribute {
649                 name: "aSubpixel",
650                 count: 1,
651                 kind: VertexAttributeKind::U16,
652             },
653             VertexAttribute {
654                 name: "aPad",
655                 count: 1,
656                 kind: VertexAttributeKind::U16,
657             },
658         ],
659     };
660 }
661 
662 #[derive(Debug, Copy, Clone)]
663 pub(crate) enum VertexArrayKind {
664     Primitive,
665     Blur,
666     Clip,
667     VectorStencil,
668     VectorCover,
669     Border,
670     Scale,
671     LineDecoration,
672 }
673 
674 #[derive(Clone, Debug, PartialEq)]
675 pub enum GraphicsApi {
676     OpenGL,
677 }
678 
679 #[derive(Clone, Debug)]
680 pub struct GraphicsApiInfo {
681     pub kind: GraphicsApi,
682     pub renderer: String,
683     pub version: String,
684 }
685 
686 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
687 #[cfg_attr(feature = "capture", derive(Serialize))]
688 #[cfg_attr(feature = "replay", derive(Deserialize))]
689 pub enum ImageBufferKind {
690     Texture2D = 0,
691     TextureRect = 1,
692     TextureExternal = 2,
693     Texture2DArray = 3,
694 }
695 
696 //TODO: those types are the same, so let's merge them
697 impl From<TextureTarget> for ImageBufferKind {
from(target: TextureTarget) -> Self698     fn from(target: TextureTarget) -> Self {
699         match target {
700             TextureTarget::Default => ImageBufferKind::Texture2D,
701             TextureTarget::Rect => ImageBufferKind::TextureRect,
702             TextureTarget::Array => ImageBufferKind::Texture2DArray,
703             TextureTarget::External => ImageBufferKind::TextureExternal,
704         }
705     }
706 }
707 
708 #[derive(Debug, Copy, Clone)]
709 pub enum RendererKind {
710     Native,
711     OSMesa,
712 }
713 
714 #[derive(Debug)]
715 pub struct GpuProfile {
716     pub frame_id: GpuFrameId,
717     pub paint_time_ns: u64,
718 }
719 
720 impl GpuProfile {
new<T>(frame_id: GpuFrameId, timers: &[GpuTimer<T>]) -> GpuProfile721     fn new<T>(frame_id: GpuFrameId, timers: &[GpuTimer<T>]) -> GpuProfile {
722         let mut paint_time_ns = 0;
723         for timer in timers {
724             paint_time_ns += timer.time_ns;
725         }
726         GpuProfile {
727             frame_id,
728             paint_time_ns,
729         }
730     }
731 }
732 
733 #[derive(Debug)]
734 pub struct CpuProfile {
735     pub frame_id: GpuFrameId,
736     pub backend_time_ns: u64,
737     pub composite_time_ns: u64,
738     pub draw_calls: usize,
739 }
740 
741 impl CpuProfile {
new( frame_id: GpuFrameId, backend_time_ns: u64, composite_time_ns: u64, draw_calls: usize, ) -> CpuProfile742     fn new(
743         frame_id: GpuFrameId,
744         backend_time_ns: u64,
745         composite_time_ns: u64,
746         draw_calls: usize,
747     ) -> CpuProfile {
748         CpuProfile {
749             frame_id,
750             backend_time_ns,
751             composite_time_ns,
752             draw_calls,
753         }
754     }
755 }
756 
757 #[cfg(not(feature = "pathfinder"))]
758 pub struct GpuGlyphRenderer;
759 
760 #[cfg(not(feature = "pathfinder"))]
761 impl GpuGlyphRenderer {
new(_: &mut Device, _: &VAO, _: ShaderPrecacheFlags) -> Result<GpuGlyphRenderer, RendererError>762     fn new(_: &mut Device, _: &VAO, _: ShaderPrecacheFlags) -> Result<GpuGlyphRenderer, RendererError> {
763         Ok(GpuGlyphRenderer)
764     }
765 }
766 
767 #[cfg(not(feature = "pathfinder"))]
768 struct StenciledGlyphPage;
769 
770 /// A Texture that has been initialized by the `device` module and is ready to
771 /// be used.
772 struct ActiveTexture {
773     texture: Texture,
774     saved_index: Option<SavedTargetIndex>,
775 }
776 
777 /// Helper struct for resolving device Textures for use during rendering passes.
778 ///
779 /// Manages the mapping between the at-a-distance texture handles used by the
780 /// `RenderBackend` (which does not directly interface with the GPU) and actual
781 /// device texture handles.
782 struct TextureResolver {
783     /// A map to resolve texture cache IDs to native textures.
784     texture_cache_map: FastHashMap<CacheTextureId, Texture>,
785 
786     /// Map of external image IDs to native textures.
787     external_images: FastHashMap<(ExternalImageId, u8), ExternalTexture>,
788 
789     /// A special 1x1 dummy texture used for shaders that expect to work with
790     /// the output of the previous pass but are actually running in the first
791     /// pass.
792     dummy_cache_texture: Texture,
793 
794     /// The outputs of the previous pass, if applicable.
795     prev_pass_color: Option<ActiveTexture>,
796     prev_pass_alpha: Option<ActiveTexture>,
797 
798     /// Saved render targets from previous passes. This is used when a pass
799     /// needs access to the result of a pass other than the immediately-preceding
800     /// one. In this case, the `RenderTask` will get a a non-`None` `saved_index`,
801     /// which will cause the resulting render target to be persisted in this list
802     /// (at that index) until the end of the frame.
803     saved_targets: Vec<Texture>,
804 
805     /// Pool of idle render target textures ready for re-use.
806     ///
807     /// Naively, it would seem like we only ever need two pairs of (color,
808     /// alpha) render targets: one for the output of the previous pass (serving
809     /// as input to the current pass), and one for the output of the current
810     /// pass. However, there are cases where the output of one pass is used as
811     /// the input to multiple future passes. For example, drop-shadows draw the
812     /// picture in pass X, then reference it in pass X+1 to create the blurred
813     /// shadow, and pass the results of both X and X+1 to pass X+2 draw the
814     /// actual content.
815     ///
816     /// See the comments in `allocate_target_texture` for more insight on why
817     /// reuse is a win.
818     render_target_pool: Vec<Texture>,
819 }
820 
821 impl TextureResolver {
new(device: &mut Device) -> TextureResolver822     fn new(device: &mut Device) -> TextureResolver {
823         let dummy_cache_texture = device
824             .create_texture(
825                 TextureTarget::Array,
826                 ImageFormat::BGRA8,
827                 1,
828                 1,
829                 TextureFilter::Linear,
830                 None,
831                 1,
832             );
833 
834         TextureResolver {
835             texture_cache_map: FastHashMap::default(),
836             external_images: FastHashMap::default(),
837             dummy_cache_texture,
838             prev_pass_alpha: None,
839             prev_pass_color: None,
840             saved_targets: Vec::default(),
841             render_target_pool: Vec::new(),
842         }
843     }
844 
deinit(self, device: &mut Device)845     fn deinit(self, device: &mut Device) {
846         device.delete_texture(self.dummy_cache_texture);
847 
848         for (_id, texture) in self.texture_cache_map {
849             device.delete_texture(texture);
850         }
851 
852         for texture in self.render_target_pool {
853             device.delete_texture(texture);
854         }
855     }
856 
begin_frame(&mut self)857     fn begin_frame(&mut self) {
858         assert!(self.prev_pass_color.is_none());
859         assert!(self.prev_pass_alpha.is_none());
860         assert!(self.saved_targets.is_empty());
861     }
862 
end_frame(&mut self, device: &mut Device, frame_id: GpuFrameId)863     fn end_frame(&mut self, device: &mut Device, frame_id: GpuFrameId) {
864         // return the cached targets to the pool
865         self.end_pass(device, None, None);
866         // return the saved targets as well
867         while let Some(target) = self.saved_targets.pop() {
868             self.return_to_pool(device, target);
869         }
870 
871         // GC the render target pool.
872         //
873         // We use a simple scheme whereby we drop any texture that hasn't been used
874         // in the last 30 frames. This should generally prevent any sustained build-
875         // up of unused textures, unless we don't generate frames for a long period.
876         // This can happen when the window is minimized, and we probably want to
877         // flush all the WebRender caches in that case [1].
878         //
879         // [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1494099
880         self.retain_targets(device, |texture| texture.used_recently(frame_id, 30));
881     }
882 
883     /// Transfers ownership of a render target back to the pool.
return_to_pool(&mut self, device: &mut Device, target: Texture)884     fn return_to_pool(&mut self, device: &mut Device, target: Texture) {
885         device.invalidate_render_target(&target);
886         self.render_target_pool.push(target);
887     }
888 
889     /// Drops all targets from the render target pool that do not satisfy the predicate.
retain_targets<F: Fn(&Texture) -> bool>(&mut self, device: &mut Device, f: F)890     pub fn retain_targets<F: Fn(&Texture) -> bool>(&mut self, device: &mut Device, f: F) {
891         // We can't just use retain() because `Texture` requires manual cleanup.
892         let mut tmp = SmallVec::<[Texture; 8]>::new();
893         for target in self.render_target_pool.drain(..) {
894             if f(&target) {
895                 tmp.push(target);
896             } else {
897                 device.delete_texture(target);
898             }
899         }
900         self.render_target_pool.extend(tmp);
901     }
902 
end_pass( &mut self, device: &mut Device, a8_texture: Option<ActiveTexture>, rgba8_texture: Option<ActiveTexture>, )903     fn end_pass(
904         &mut self,
905         device: &mut Device,
906         a8_texture: Option<ActiveTexture>,
907         rgba8_texture: Option<ActiveTexture>,
908     ) {
909         // If we have cache textures from previous pass, return them to the pool.
910         // Also assign the pool index of those cache textures to last pass's index because this is
911         // the result of last pass.
912         // Note: the order here is important, needs to match the logic in `RenderPass::build()`.
913         if let Some(at) = self.prev_pass_color.take() {
914             if let Some(index) = at.saved_index {
915                 assert_eq!(self.saved_targets.len(), index.0);
916                 self.saved_targets.push(at.texture);
917             } else {
918                 self.return_to_pool(device, at.texture);
919             }
920         }
921         if let Some(at) = self.prev_pass_alpha.take() {
922             if let Some(index) = at.saved_index {
923                 assert_eq!(self.saved_targets.len(), index.0);
924                 self.saved_targets.push(at.texture);
925             } else {
926                 self.return_to_pool(device, at.texture);
927             }
928         }
929 
930         // We have another pass to process, make these textures available
931         // as inputs to the next pass.
932         self.prev_pass_color = rgba8_texture;
933         self.prev_pass_alpha = a8_texture;
934     }
935 
936     // Bind a source texture to the device.
bind(&self, texture_id: &TextureSource, sampler: TextureSampler, device: &mut Device)937     fn bind(&self, texture_id: &TextureSource, sampler: TextureSampler, device: &mut Device) {
938         match *texture_id {
939             TextureSource::Invalid => {}
940             TextureSource::PrevPassAlpha => {
941                 let texture = match self.prev_pass_alpha {
942                     Some(ref at) => &at.texture,
943                     None => &self.dummy_cache_texture,
944                 };
945                 device.bind_texture(sampler, texture);
946             }
947             TextureSource::PrevPassColor => {
948                 let texture = match self.prev_pass_color {
949                     Some(ref at) => &at.texture,
950                     None => &self.dummy_cache_texture,
951                 };
952                 device.bind_texture(sampler, texture);
953             }
954             TextureSource::External(external_image) => {
955                 let texture = self.external_images
956                     .get(&(external_image.id, external_image.channel_index))
957                     .expect(&format!("BUG: External image should be resolved by now"));
958                 device.bind_external_texture(sampler, texture);
959             }
960             TextureSource::TextureCache(index) => {
961                 let texture = &self.texture_cache_map[&index];
962                 device.bind_texture(sampler, texture);
963             }
964             TextureSource::RenderTaskCache(saved_index) => {
965                 let texture = &self.saved_targets[saved_index.0];
966                 device.bind_texture(sampler, texture)
967             }
968         }
969     }
970 
971     // Get the real (OpenGL) texture ID for a given source texture.
972     // For a texture cache texture, the IDs are stored in a vector
973     // map for fast access.
resolve(&self, texture_id: &TextureSource) -> Option<&Texture>974     fn resolve(&self, texture_id: &TextureSource) -> Option<&Texture> {
975         match *texture_id {
976             TextureSource::Invalid => None,
977             TextureSource::PrevPassAlpha => Some(
978                 match self.prev_pass_alpha {
979                     Some(ref at) => &at.texture,
980                     None => &self.dummy_cache_texture,
981                 }
982             ),
983             TextureSource::PrevPassColor => Some(
984                 match self.prev_pass_color {
985                     Some(ref at) => &at.texture,
986                     None => &self.dummy_cache_texture,
987                 }
988             ),
989             TextureSource::External(..) => {
990                 panic!("BUG: External textures cannot be resolved, they can only be bound.");
991             }
992             TextureSource::TextureCache(index) => {
993                 Some(&self.texture_cache_map[&index])
994             }
995             TextureSource::RenderTaskCache(saved_index) => {
996                 Some(&self.saved_targets[saved_index.0])
997             }
998         }
999     }
1000 
report_memory(&self) -> MemoryReport1001     fn report_memory(&self) -> MemoryReport {
1002         let mut report = MemoryReport::default();
1003 
1004         // We're reporting GPU memory rather than heap-allocations, so we don't
1005         // use size_of_op.
1006         for t in self.texture_cache_map.values() {
1007             report.texture_cache_textures += t.size_in_bytes();
1008         }
1009         for t in self.render_target_pool.iter() {
1010             report.render_target_textures += t.size_in_bytes();
1011         }
1012 
1013         report
1014     }
1015 }
1016 
1017 #[derive(Debug, Copy, Clone, PartialEq)]
1018 #[cfg_attr(feature = "capture", derive(Serialize))]
1019 #[cfg_attr(feature = "replay", derive(Deserialize))]
1020 pub enum BlendMode {
1021     None,
1022     Alpha,
1023     PremultipliedAlpha,
1024     PremultipliedDestOut,
1025     SubpixelDualSource,
1026     SubpixelConstantTextColor(ColorF),
1027     SubpixelWithBgColor,
1028 }
1029 
1030 /// Tracks the state of each row in the GPU cache texture.
1031 struct CacheRow {
1032     /// Mirrored block data on CPU for this row. We store a copy of
1033     /// the data on the CPU side to improve upload batching.
1034     cpu_blocks: Box<[GpuBlockData; MAX_VERTEX_TEXTURE_WIDTH]>,
1035     /// True if this row is dirty.
1036     is_dirty: bool,
1037 }
1038 
1039 impl CacheRow {
new() -> Self1040     fn new() -> Self {
1041         CacheRow {
1042             cpu_blocks: Box::new([GpuBlockData::EMPTY; MAX_VERTEX_TEXTURE_WIDTH]),
1043             is_dirty: false,
1044         }
1045     }
1046 }
1047 
1048 /// The bus over which CPU and GPU versions of the GPU cache
1049 /// get synchronized.
1050 enum GpuCacheBus {
1051     /// PBO-based updates, currently operate on a row granularity.
1052     /// Therefore, are subject to fragmentation issues.
1053     PixelBuffer {
1054         /// PBO used for transfers.
1055         buffer: PBO,
1056         /// Per-row data.
1057         rows: Vec<CacheRow>,
1058     },
1059     /// Shader-based scattering updates. Currently rendered by a set
1060     /// of points into the GPU texture, each carrying a `GpuBlockData`.
1061     Scatter {
1062         /// Special program to run the scattered update.
1063         program: Program,
1064         /// VAO containing the source vertex buffers.
1065         vao: CustomVAO,
1066         /// VBO for positional data, supplied as normalized `u16`.
1067         buf_position: VBO<[u16; 2]>,
1068         /// VBO for gpu block data.
1069         buf_value: VBO<GpuBlockData>,
1070         /// Currently stored block count.
1071         count: usize,
1072     },
1073 }
1074 
1075 /// The device-specific representation of the cache texture in gpu_cache.rs
1076 struct GpuCacheTexture {
1077     texture: Option<Texture>,
1078     bus: GpuCacheBus,
1079 }
1080 
1081 impl GpuCacheTexture {
1082 
1083     /// Ensures that we have an appropriately-sized texture. Returns true if a
1084     /// new texture was created.
ensure_texture(&mut self, device: &mut Device, height: i32)1085     fn ensure_texture(&mut self, device: &mut Device, height: i32) {
1086         // If we already have a texture that works, we're done.
1087         if self.texture.as_ref().map_or(false, |t| t.get_dimensions().height >= height) {
1088             if GPU_CACHE_RESIZE_TEST {
1089                 // Special debug mode - resize the texture even though it's fine.
1090             } else {
1091                 return;
1092             }
1093         }
1094 
1095         // Take the old texture, if any.
1096         let blit_source = self.texture.take();
1097 
1098         // Create the new texture.
1099         assert!(height >= 2, "Height is too small for ANGLE");
1100         let new_size = DeviceIntSize::new(MAX_VERTEX_TEXTURE_WIDTH as _, height);
1101         let rt_info = Some(RenderTargetInfo { has_depth: false });
1102         let mut texture = device.create_texture(
1103             TextureTarget::Default,
1104             ImageFormat::RGBAF32,
1105             new_size.width,
1106             new_size.height,
1107             TextureFilter::Nearest,
1108             rt_info,
1109             1,
1110         );
1111 
1112         // Blit the contents of the previous texture, if applicable.
1113         if let Some(blit_source) = blit_source {
1114             device.blit_renderable_texture(&mut texture, &blit_source);
1115             device.delete_texture(blit_source);
1116         }
1117 
1118         self.texture = Some(texture);
1119     }
1120 
new(device: &mut Device, use_scatter: bool) -> Result<Self, RendererError>1121     fn new(device: &mut Device, use_scatter: bool) -> Result<Self, RendererError> {
1122         let bus = if use_scatter {
1123             let program = device.create_program_linked(
1124                 "gpu_cache_update",
1125                 String::new(),
1126                 &desc::GPU_CACHE_UPDATE,
1127             )?;
1128             let buf_position = device.create_vbo();
1129             let buf_value = device.create_vbo();
1130             //Note: the vertex attributes have to be supplied in the same order
1131             // as for program creation, but each assigned to a different stream.
1132             let vao = device.create_custom_vao(&[
1133                 buf_position.stream_with(&desc::GPU_CACHE_UPDATE.vertex_attributes[0..1]),
1134                 buf_value   .stream_with(&desc::GPU_CACHE_UPDATE.vertex_attributes[1..2]),
1135             ]);
1136             GpuCacheBus::Scatter {
1137                 program,
1138                 vao,
1139                 buf_position,
1140                 buf_value,
1141                 count: 0,
1142             }
1143         } else {
1144             let buffer = device.create_pbo();
1145             GpuCacheBus::PixelBuffer {
1146                 buffer,
1147                 rows: Vec::new(),
1148             }
1149         };
1150 
1151         Ok(GpuCacheTexture {
1152             texture: None,
1153             bus,
1154         })
1155     }
1156 
deinit(mut self, device: &mut Device)1157     fn deinit(mut self, device: &mut Device) {
1158         if let Some(t) = self.texture.take() {
1159             device.delete_texture(t);
1160         }
1161         match self.bus {
1162             GpuCacheBus::PixelBuffer { buffer, ..} => {
1163                 device.delete_pbo(buffer);
1164             }
1165             GpuCacheBus::Scatter { program, vao, buf_position, buf_value, ..} => {
1166                 device.delete_program(program);
1167                 device.delete_custom_vao(vao);
1168                 device.delete_vbo(buf_position);
1169                 device.delete_vbo(buf_value);
1170             }
1171         }
1172     }
1173 
get_height(&self) -> i321174     fn get_height(&self) -> i32 {
1175         self.texture.as_ref().map_or(0, |t| t.get_dimensions().height)
1176     }
1177 
prepare_for_updates( &mut self, device: &mut Device, total_block_count: usize, max_height: i32, )1178     fn prepare_for_updates(
1179         &mut self,
1180         device: &mut Device,
1181         total_block_count: usize,
1182         max_height: i32,
1183     ) {
1184         self.ensure_texture(device, max_height);
1185         match self.bus {
1186             GpuCacheBus::PixelBuffer { .. } => {},
1187             GpuCacheBus::Scatter {
1188                 ref mut buf_position,
1189                 ref mut buf_value,
1190                 ref mut count,
1191                 ..
1192             } => {
1193                 *count = 0;
1194                 if total_block_count > buf_value.allocated_count() {
1195                     device.allocate_vbo(buf_position, total_block_count, VertexUsageHint::Stream);
1196                     device.allocate_vbo(buf_value,    total_block_count, VertexUsageHint::Stream);
1197                 }
1198             }
1199         }
1200     }
1201 
update(&mut self, device: &mut Device, updates: &GpuCacheUpdateList)1202     fn update(&mut self, device: &mut Device, updates: &GpuCacheUpdateList) {
1203         match self.bus {
1204             GpuCacheBus::PixelBuffer { ref mut rows, .. } => {
1205                 for update in &updates.updates {
1206                     match *update {
1207                         GpuCacheUpdate::Copy {
1208                             block_index,
1209                             block_count,
1210                             address,
1211                         } => {
1212                             let row = address.v as usize;
1213 
1214                             // Ensure that the CPU-side shadow copy of the GPU cache data has enough
1215                             // rows to apply this patch.
1216                             while rows.len() <= row {
1217                                 // Add a new row.
1218                                 rows.push(CacheRow::new());
1219                             }
1220 
1221                             // This row is dirty (needs to be updated in GPU texture).
1222                             rows[row].is_dirty = true;
1223 
1224                             // Copy the blocks from the patch array in the shadow CPU copy.
1225                             let block_offset = address.u as usize;
1226                             let data = &mut rows[row].cpu_blocks;
1227                             for i in 0 .. block_count {
1228                                 data[block_offset + i] = updates.blocks[block_index + i];
1229                             }
1230                         }
1231                     }
1232                 }
1233             }
1234             GpuCacheBus::Scatter {
1235                 ref buf_position,
1236                 ref buf_value,
1237                 ref mut count,
1238                 ..
1239             } => {
1240                 //TODO: re-use this heap allocation
1241                 // Unused positions will be left as 0xFFFF, which translates to
1242                 // (1.0, 1.0) in the vertex output position and gets culled out
1243                 let mut position_data = vec![[!0u16; 2]; updates.blocks.len()];
1244                 let size = self.texture.as_ref().unwrap().get_dimensions().to_usize();
1245 
1246                 for update in &updates.updates {
1247                     match *update {
1248                         GpuCacheUpdate::Copy {
1249                             block_index,
1250                             block_count,
1251                             address,
1252                         } => {
1253                             // Convert the absolute texel position into normalized
1254                             let y = ((2*address.v as usize + 1) << 15) / size.height;
1255                             for i in 0 .. block_count {
1256                                 let x = ((2*address.u as usize + 2*i + 1) << 15) / size.width;
1257                                 position_data[block_index + i] = [x as _, y as _];
1258                             }
1259                         }
1260                     }
1261                 }
1262 
1263                 device.fill_vbo(buf_value, &updates.blocks, *count);
1264                 device.fill_vbo(buf_position, &position_data, *count);
1265                 *count += position_data.len();
1266             }
1267         }
1268     }
1269 
flush(&mut self, device: &mut Device) -> usize1270     fn flush(&mut self, device: &mut Device) -> usize {
1271         let texture = self.texture.as_ref().unwrap();
1272         match self.bus {
1273             GpuCacheBus::PixelBuffer { ref buffer, ref mut rows } => {
1274                 let rows_dirty = rows
1275                     .iter()
1276                     .filter(|row| row.is_dirty)
1277                     .count();
1278                 if rows_dirty == 0 {
1279                     return 0
1280                 }
1281 
1282                 let mut uploader = device.upload_texture(
1283                     texture,
1284                     buffer,
1285                     rows_dirty * MAX_VERTEX_TEXTURE_WIDTH,
1286                 );
1287 
1288                 for (row_index, row) in rows.iter_mut().enumerate() {
1289                     if !row.is_dirty {
1290                         continue;
1291                     }
1292 
1293                     let rect = DeviceIntRect::new(
1294                         DeviceIntPoint::new(0, row_index as i32),
1295                         DeviceIntSize::new(MAX_VERTEX_TEXTURE_WIDTH as i32, 1),
1296                     );
1297 
1298                     uploader.upload(rect, 0, None, &*row.cpu_blocks);
1299 
1300                     row.is_dirty = false;
1301                 }
1302 
1303                 rows_dirty
1304             }
1305             GpuCacheBus::Scatter { ref program, ref vao, count, .. } => {
1306                 device.disable_depth();
1307                 device.set_blend(false);
1308                 device.bind_program(program);
1309                 device.bind_custom_vao(vao);
1310                 device.bind_draw_target(
1311                     DrawTarget::Texture {
1312                         texture,
1313                         layer: 0,
1314                         with_depth: false,
1315                     },
1316                 );
1317                 device.draw_nonindexed_points(0, count as _);
1318                 0
1319             }
1320         }
1321     }
1322 }
1323 
1324 struct VertexDataTexture {
1325     texture: Option<Texture>,
1326     format: ImageFormat,
1327     pbo: PBO,
1328 }
1329 
1330 impl VertexDataTexture {
new( device: &mut Device, format: ImageFormat, ) -> VertexDataTexture1331     fn new(
1332         device: &mut Device,
1333         format: ImageFormat,
1334     ) -> VertexDataTexture {
1335         let pbo = device.create_pbo();
1336         VertexDataTexture { texture: None, format, pbo }
1337     }
1338 
1339     /// Returns a borrow of the GPU texture. Panics if it hasn't been initialized.
texture(&self) -> &Texture1340     fn texture(&self) -> &Texture {
1341         self.texture.as_ref().unwrap()
1342     }
1343 
1344     /// Returns an estimate of the GPU memory consumed by this VertexDataTexture.
size_in_bytes(&self) -> usize1345     fn size_in_bytes(&self) -> usize {
1346         self.texture.as_ref().map_or(0, |t| t.size_in_bytes())
1347     }
1348 
update<T>(&mut self, device: &mut Device, data: &mut Vec<T>)1349     fn update<T>(&mut self, device: &mut Device, data: &mut Vec<T>) {
1350         debug_assert!(mem::size_of::<T>() % 16 == 0);
1351         let texels_per_item = mem::size_of::<T>() / 16;
1352         let items_per_row = MAX_VERTEX_TEXTURE_WIDTH / texels_per_item;
1353 
1354         // Ensure we always end up with a texture when leaving this method.
1355         if data.is_empty() {
1356             if self.texture.is_some() {
1357                 return;
1358             }
1359             data.push(unsafe { mem::uninitialized() });
1360         }
1361 
1362         // Extend the data array to be a multiple of the row size.
1363         // This ensures memory safety when the array is passed to
1364         // OpenGL to upload to the GPU.
1365         if items_per_row != 0 {
1366             while data.len() % items_per_row != 0 {
1367                 data.push(unsafe { mem::uninitialized() });
1368             }
1369         }
1370 
1371         let width =
1372             (MAX_VERTEX_TEXTURE_WIDTH - (MAX_VERTEX_TEXTURE_WIDTH % texels_per_item)) as i32;
1373         let needed_height = (data.len() / items_per_row) as i32;
1374         let existing_height = self.texture.as_ref().map_or(0, |t| t.get_dimensions().height);
1375 
1376         // Create a new texture if needed.
1377         //
1378         // These textures are generally very small, which is why we don't bother
1379         // with incremental updates and just re-upload every frame. For most pages
1380         // they're one row each, and on stress tests like css-francine they end up
1381         // in the 6-14 range. So we size the texture tightly to what we need (usually
1382         // 1), and shrink it if the waste would be more than 10 rows. This helps
1383         // with memory overhead, especially because there are several instances of
1384         // these textures per Renderer.
1385         if needed_height > existing_height || needed_height + 10 < existing_height {
1386             // Drop the existing texture, if any.
1387             if let Some(t) = self.texture.take() {
1388                 device.delete_texture(t);
1389             }
1390 
1391             let texture = device.create_texture(
1392                 TextureTarget::Default,
1393                 self.format,
1394                 width,
1395                 // Ensure height is at least two to work around
1396                 // https://bugs.chromium.org/p/angleproject/issues/detail?id=3039
1397                 needed_height.max(2),
1398                 TextureFilter::Nearest,
1399                 None,
1400                 1,
1401             );
1402             self.texture = Some(texture);
1403         }
1404 
1405         let rect = DeviceIntRect::new(
1406             DeviceIntPoint::zero(),
1407             DeviceIntSize::new(width, needed_height),
1408         );
1409         device
1410             .upload_texture(self.texture(), &self.pbo, 0)
1411             .upload(rect, 0, None, data);
1412     }
1413 
deinit(mut self, device: &mut Device)1414     fn deinit(mut self, device: &mut Device) {
1415         device.delete_pbo(self.pbo);
1416         if let Some(t) = self.texture.take() {
1417             device.delete_texture(t);
1418         }
1419     }
1420 }
1421 
1422 struct FrameOutput {
1423     last_access: GpuFrameId,
1424     fbo_id: FBOId,
1425 }
1426 
1427 #[derive(PartialEq)]
1428 struct TargetSelector {
1429     size: DeviceIntSize,
1430     num_layers: usize,
1431     format: ImageFormat,
1432 }
1433 
1434 struct LazyInitializedDebugRenderer {
1435     debug_renderer: Option<DebugRenderer>,
1436     failed: bool,
1437 }
1438 
1439 impl LazyInitializedDebugRenderer {
new() -> Self1440     pub fn new() -> Self {
1441         Self {
1442             debug_renderer: None,
1443             failed: false,
1444         }
1445     }
1446 
get_mut<'a>(&'a mut self, device: &mut Device) -> Option<&'a mut DebugRenderer>1447     pub fn get_mut<'a>(&'a mut self, device: &mut Device) -> Option<&'a mut DebugRenderer> {
1448         if self.failed {
1449             return None;
1450         }
1451         if self.debug_renderer.is_none() {
1452             match DebugRenderer::new(device) {
1453                 Ok(renderer) => { self.debug_renderer = Some(renderer); }
1454                 Err(_) => {
1455                     // The shader compilation code already logs errors.
1456                     self.failed = true;
1457                 }
1458             }
1459         }
1460 
1461         self.debug_renderer.as_mut()
1462     }
1463 
1464     /// Returns mut ref to `DebugRenderer` if one already exists, otherwise returns `None`.
try_get_mut<'a>(&'a mut self) -> Option<&'a mut DebugRenderer>1465     pub fn try_get_mut<'a>(&'a mut self) -> Option<&'a mut DebugRenderer> {
1466         self.debug_renderer.as_mut()
1467     }
1468 
deinit(self, device: &mut Device)1469     pub fn deinit(self, device: &mut Device) {
1470         if let Some(debug_renderer) = self.debug_renderer {
1471             debug_renderer.deinit(device);
1472         }
1473     }
1474 }
1475 
1476 // NB: If you add more VAOs here, be sure to deinitialize them in
1477 // `Renderer::deinit()` below.
1478 pub struct RendererVAOs {
1479     prim_vao: VAO,
1480     blur_vao: VAO,
1481     clip_vao: VAO,
1482     border_vao: VAO,
1483     line_vao: VAO,
1484     scale_vao: VAO,
1485 }
1486 
1487 /// The renderer is responsible for submitting to the GPU the work prepared by the
1488 /// RenderBackend.
1489 ///
1490 /// We have a separate `Renderer` instance for each instance of WebRender (generally
1491 /// one per OS window), and all instances share the same thread.
1492 pub struct Renderer {
1493     result_rx: Receiver<ResultMsg>,
1494     debug_server: DebugServer,
1495     pub device: Device,
1496     pending_texture_updates: Vec<TextureUpdateList>,
1497     pending_gpu_cache_updates: Vec<GpuCacheUpdateList>,
1498     pending_gpu_cache_clear: bool,
1499     pending_shader_updates: Vec<PathBuf>,
1500     active_documents: Vec<(DocumentId, RenderedDocument)>,
1501 
1502     shaders: Rc<RefCell<Shaders>>,
1503 
1504     pub gpu_glyph_renderer: GpuGlyphRenderer,
1505 
1506     max_recorded_profiles: usize,
1507 
1508     clear_color: Option<ColorF>,
1509     enable_clear_scissor: bool,
1510     debug: LazyInitializedDebugRenderer,
1511     debug_flags: DebugFlags,
1512     backend_profile_counters: BackendProfileCounters,
1513     profile_counters: RendererProfileCounters,
1514     resource_upload_time: u64,
1515     gpu_cache_upload_time: u64,
1516     profiler: Profiler,
1517     new_frame_indicator: ChangeIndicator,
1518     new_scene_indicator: ChangeIndicator,
1519     slow_frame_indicator: ChangeIndicator,
1520 
1521     last_time: u64,
1522 
1523     pub gpu_profile: GpuProfiler<GpuProfileTag>,
1524     vaos: RendererVAOs,
1525 
1526     prim_header_f_texture: VertexDataTexture,
1527     prim_header_i_texture: VertexDataTexture,
1528     transforms_texture: VertexDataTexture,
1529     render_task_texture: VertexDataTexture,
1530     gpu_cache_texture: GpuCacheTexture,
1531 
1532     /// When the GPU cache debugger is enabled, we keep track of the live blocks
1533     /// in the GPU cache so that we can use them for the debug display. This
1534     /// member stores those live blocks, indexed by row.
1535     gpu_cache_debug_chunks: Vec<Vec<GpuCacheDebugChunk>>,
1536 
1537     gpu_cache_frame_id: FrameId,
1538     gpu_cache_overflow: bool,
1539 
1540     pipeline_info: PipelineInfo,
1541 
1542     // Manages and resolves source textures IDs to real texture IDs.
1543     texture_resolver: TextureResolver,
1544 
1545     // A PBO used to do asynchronous texture cache uploads.
1546     texture_cache_upload_pbo: PBO,
1547 
1548     dither_matrix_texture: Option<Texture>,
1549 
1550     /// Optional trait object that allows the client
1551     /// application to provide external buffers for image data.
1552     external_image_handler: Option<Box<ExternalImageHandler>>,
1553 
1554     /// Optional trait object that allows the client
1555     /// application to provide a texture handle to
1556     /// copy the WR output to.
1557     output_image_handler: Option<Box<OutputImageHandler>>,
1558 
1559     /// Optional function pointers for measuring memory used by a given
1560     /// heap-allocated pointer.
1561     size_of_ops: Option<MallocSizeOfOps>,
1562 
1563     // Currently allocated FBOs for output frames.
1564     output_targets: FastHashMap<u32, FrameOutput>,
1565 
1566     pub renderer_errors: Vec<RendererError>,
1567 
1568     /// List of profile results from previous frames. Can be retrieved
1569     /// via get_frame_profiles().
1570     cpu_profiles: VecDeque<CpuProfile>,
1571     gpu_profiles: VecDeque<GpuProfile>,
1572 
1573     /// Notification requests to be fulfilled after rendering.
1574     notifications: Vec<NotificationRequest>,
1575 
1576     framebuffer_size: Option<DeviceIntSize>,
1577 
1578     /// A lazily created texture for the zoom debugging widget.
1579     zoom_debug_texture: Option<Texture>,
1580 
1581     /// The current mouse position. This is used for debugging
1582     /// functionality only, such as the debug zoom widget.
1583     cursor_position: DeviceIntPoint,
1584 
1585     #[cfg(feature = "capture")]
1586     read_fbo: FBOId,
1587     #[cfg(feature = "replay")]
1588     owned_external_images: FastHashMap<(ExternalImageId, u8), ExternalTexture>,
1589 }
1590 
1591 #[derive(Debug)]
1592 pub enum RendererError {
1593     Shader(ShaderError),
1594     Thread(std::io::Error),
1595     Resource(ResourceCacheError),
1596     MaxTextureSize,
1597 }
1598 
1599 impl From<ShaderError> for RendererError {
from(err: ShaderError) -> Self1600     fn from(err: ShaderError) -> Self {
1601         RendererError::Shader(err)
1602     }
1603 }
1604 
1605 impl From<std::io::Error> for RendererError {
from(err: std::io::Error) -> Self1606     fn from(err: std::io::Error) -> Self {
1607         RendererError::Thread(err)
1608     }
1609 }
1610 
1611 impl From<ResourceCacheError> for RendererError {
from(err: ResourceCacheError) -> Self1612     fn from(err: ResourceCacheError) -> Self {
1613         RendererError::Resource(err)
1614     }
1615 }
1616 
1617 impl Renderer {
1618     /// Initializes WebRender and creates a `Renderer` and `RenderApiSender`.
1619     ///
1620     /// # Examples
1621     /// Initializes a `Renderer` with some reasonable values. For more information see
1622     /// [`RendererOptions`][rendereroptions].
1623     ///
1624     /// ```rust,ignore
1625     /// # use webrender::renderer::Renderer;
1626     /// # use std::path::PathBuf;
1627     /// let opts = webrender::RendererOptions {
1628     ///    device_pixel_ratio: 1.0,
1629     ///    resource_override_path: None,
1630     ///    enable_aa: false,
1631     /// };
1632     /// let (renderer, sender) = Renderer::new(opts);
1633     /// ```
1634     /// [rendereroptions]: struct.RendererOptions.html
new( gl: Rc<gl::Gl>, notifier: Box<RenderNotifier>, mut options: RendererOptions, shaders: Option<&mut WrShaders> ) -> Result<(Self, RenderApiSender), RendererError>1635     pub fn new(
1636         gl: Rc<gl::Gl>,
1637         notifier: Box<RenderNotifier>,
1638         mut options: RendererOptions,
1639         shaders: Option<&mut WrShaders>
1640     ) -> Result<(Self, RenderApiSender), RendererError> {
1641         HAS_BEEN_INITIALIZED.store(true, Ordering::SeqCst);
1642 
1643         let (api_tx, api_rx) = channel::msg_channel()?;
1644         let (payload_tx, payload_rx) = channel::payload_channel()?;
1645         let (result_tx, result_rx) = channel();
1646         let gl_type = gl.get_type();
1647 
1648         let debug_server = DebugServer::new(api_tx.clone());
1649 
1650         let mut device = Device::new(
1651             gl,
1652             options.resource_override_path.clone(),
1653             options.upload_method.clone(),
1654             options.cached_programs.take(),
1655         );
1656 
1657         let ext_dual_source_blending = !options.disable_dual_source_blending &&
1658             device.supports_extension("GL_ARB_blend_func_extended") &&
1659             device.supports_extension("GL_ARB_explicit_attrib_location");
1660 
1661         // 512 is the minimum that the texture cache can work with.
1662         const MIN_TEXTURE_SIZE: i32 = 512;
1663         if let Some(user_limit) = options.max_texture_size {
1664             assert!(user_limit >= MIN_TEXTURE_SIZE);
1665             device.clamp_max_texture_size(user_limit);
1666         }
1667         if device.max_texture_size() < MIN_TEXTURE_SIZE {
1668             // Broken GL contexts can return a max texture size of zero (See #1260).
1669             // Better to gracefully fail now than panic as soon as a texture is allocated.
1670             error!(
1671                 "Device reporting insufficient max texture size ({})",
1672                 device.max_texture_size()
1673             );
1674             return Err(RendererError::MaxTextureSize);
1675         }
1676         let max_texture_size = device.max_texture_size();
1677         let max_texture_layers = device.max_texture_layers();
1678 
1679         register_thread_with_profiler("Compositor".to_owned());
1680 
1681         device.begin_frame();
1682 
1683         let shaders = match shaders {
1684             Some(shaders) => Rc::clone(&shaders.shaders),
1685             None => Rc::new(RefCell::new(Shaders::new(&mut device, gl_type, &options)?)),
1686         };
1687 
1688         let backend_profile_counters = BackendProfileCounters::new();
1689 
1690         let dither_matrix_texture = if options.enable_dithering {
1691             let dither_matrix: [u8; 64] = [
1692                 00,
1693                 48,
1694                 12,
1695                 60,
1696                 03,
1697                 51,
1698                 15,
1699                 63,
1700                 32,
1701                 16,
1702                 44,
1703                 28,
1704                 35,
1705                 19,
1706                 47,
1707                 31,
1708                 08,
1709                 56,
1710                 04,
1711                 52,
1712                 11,
1713                 59,
1714                 07,
1715                 55,
1716                 40,
1717                 24,
1718                 36,
1719                 20,
1720                 43,
1721                 27,
1722                 39,
1723                 23,
1724                 02,
1725                 50,
1726                 14,
1727                 62,
1728                 01,
1729                 49,
1730                 13,
1731                 61,
1732                 34,
1733                 18,
1734                 46,
1735                 30,
1736                 33,
1737                 17,
1738                 45,
1739                 29,
1740                 10,
1741                 58,
1742                 06,
1743                 54,
1744                 09,
1745                 57,
1746                 05,
1747                 53,
1748                 42,
1749                 26,
1750                 38,
1751                 22,
1752                 41,
1753                 25,
1754                 37,
1755                 21,
1756             ];
1757 
1758             let mut texture = device.create_texture(
1759                 TextureTarget::Default,
1760                 ImageFormat::R8,
1761                 8,
1762                 8,
1763                 TextureFilter::Nearest,
1764                 None,
1765                 1,
1766             );
1767             device.upload_texture_immediate(&texture, &dither_matrix);
1768 
1769             Some(texture)
1770         } else {
1771             None
1772         };
1773 
1774         let x0 = 0.0;
1775         let y0 = 0.0;
1776         let x1 = 1.0;
1777         let y1 = 1.0;
1778 
1779         let quad_indices: [u16; 6] = [0, 1, 2, 2, 1, 3];
1780         let quad_vertices = [
1781             PackedVertex { pos: [x0, y0] },
1782             PackedVertex { pos: [x1, y0] },
1783             PackedVertex { pos: [x0, y1] },
1784             PackedVertex { pos: [x1, y1] },
1785         ];
1786 
1787         let prim_vao = device.create_vao(&desc::PRIM_INSTANCES);
1788         device.bind_vao(&prim_vao);
1789         device.update_vao_indices(&prim_vao, &quad_indices, VertexUsageHint::Static);
1790         device.update_vao_main_vertices(&prim_vao, &quad_vertices, VertexUsageHint::Static);
1791 
1792         let gpu_glyph_renderer = try!(GpuGlyphRenderer::new(&mut device,
1793                                                             &prim_vao,
1794                                                             options.precache_flags));
1795 
1796         let blur_vao = device.create_vao_with_new_instances(&desc::BLUR, &prim_vao);
1797         let clip_vao = device.create_vao_with_new_instances(&desc::CLIP, &prim_vao);
1798         let border_vao = device.create_vao_with_new_instances(&desc::BORDER, &prim_vao);
1799         let scale_vao = device.create_vao_with_new_instances(&desc::SCALE, &prim_vao);
1800         let line_vao = device.create_vao_with_new_instances(&desc::LINE, &prim_vao);
1801         let texture_cache_upload_pbo = device.create_pbo();
1802 
1803         let texture_resolver = TextureResolver::new(&mut device);
1804 
1805         let prim_header_f_texture = VertexDataTexture::new(&mut device, ImageFormat::RGBAF32);
1806         let prim_header_i_texture = VertexDataTexture::new(&mut device, ImageFormat::RGBAI32);
1807         let transforms_texture = VertexDataTexture::new(&mut device, ImageFormat::RGBAF32);
1808         let render_task_texture = VertexDataTexture::new(&mut device, ImageFormat::RGBAF32);
1809 
1810         let gpu_cache_texture = GpuCacheTexture::new(
1811             &mut device,
1812             options.scatter_gpu_cache_updates,
1813         )?;
1814 
1815         device.end_frame();
1816 
1817         let backend_notifier = notifier.clone();
1818 
1819         let default_font_render_mode = match (options.enable_aa, options.enable_subpixel_aa) {
1820             (true, true) => FontRenderMode::Subpixel,
1821             (true, false) => FontRenderMode::Alpha,
1822             (false, _) => FontRenderMode::Mono,
1823         };
1824 
1825         let config = FrameBuilderConfig {
1826             default_font_render_mode,
1827             dual_source_blending_is_enabled: true,
1828             dual_source_blending_is_supported: ext_dual_source_blending,
1829             chase_primitive: options.chase_primitive,
1830             enable_picture_caching: options.enable_picture_caching,
1831             testing: options.testing,
1832         };
1833 
1834         let device_pixel_ratio = options.device_pixel_ratio;
1835         let debug_flags = options.debug_flags;
1836         let payload_rx_for_backend = payload_rx.to_mpsc_receiver();
1837         let size_of_op = options.size_of_op;
1838         let enclosing_size_of_op = options.enclosing_size_of_op;
1839         let make_size_of_ops =
1840             move || size_of_op.map(|o| MallocSizeOfOps::new(o, enclosing_size_of_op));
1841         let recorder = options.recorder;
1842         let thread_listener = Arc::new(options.thread_listener);
1843         let thread_listener_for_rayon_start = thread_listener.clone();
1844         let thread_listener_for_rayon_end = thread_listener.clone();
1845         let workers = options
1846             .workers
1847             .take()
1848             .unwrap_or_else(|| {
1849                 let worker = ThreadPoolBuilder::new()
1850                     .thread_name(|idx|{ format!("WRWorker#{}", idx) })
1851                     .start_handler(move |idx| {
1852                         register_thread_with_profiler(format!("WRWorker#{}", idx));
1853                         if let Some(ref thread_listener) = *thread_listener_for_rayon_start {
1854                             thread_listener.thread_started(&format!("WRWorker#{}", idx));
1855                         }
1856                     })
1857                     .exit_handler(move |idx| {
1858                         if let Some(ref thread_listener) = *thread_listener_for_rayon_end {
1859                             thread_listener.thread_stopped(&format!("WRWorker#{}", idx));
1860                         }
1861                     })
1862                     .build();
1863                 Arc::new(worker.unwrap())
1864             });
1865         let sampler = options.sampler;
1866         let namespace_alloc_by_client = options.namespace_alloc_by_client;
1867 
1868         let blob_image_handler = options.blob_image_handler.take();
1869         let thread_listener_for_render_backend = thread_listener.clone();
1870         let thread_listener_for_scene_builder = thread_listener.clone();
1871         let thread_listener_for_lp_scene_builder = thread_listener.clone();
1872         let scene_builder_hooks = options.scene_builder_hooks;
1873         let rb_thread_name = format!("WRRenderBackend#{}", options.renderer_id.unwrap_or(0));
1874         let scene_thread_name = format!("WRSceneBuilder#{}", options.renderer_id.unwrap_or(0));
1875         let lp_scene_thread_name = format!("WRSceneBuilderLP#{}", options.renderer_id.unwrap_or(0));
1876         let glyph_rasterizer = GlyphRasterizer::new(workers)?;
1877 
1878         let (scene_builder, scene_tx, scene_rx) = SceneBuilder::new(
1879             config,
1880             api_tx.clone(),
1881             scene_builder_hooks,
1882             make_size_of_ops(),
1883         );
1884         thread::Builder::new().name(scene_thread_name.clone()).spawn(move || {
1885             register_thread_with_profiler(scene_thread_name.clone());
1886             if let Some(ref thread_listener) = *thread_listener_for_scene_builder {
1887                 thread_listener.thread_started(&scene_thread_name);
1888             }
1889 
1890             let mut scene_builder = scene_builder;
1891             scene_builder.run();
1892 
1893             if let Some(ref thread_listener) = *thread_listener_for_scene_builder {
1894                 thread_listener.thread_stopped(&scene_thread_name);
1895             }
1896         })?;
1897 
1898         let low_priority_scene_tx = if options.support_low_priority_transactions {
1899             let (low_priority_scene_tx, low_priority_scene_rx) = channel();
1900             let lp_builder = LowPrioritySceneBuilder {
1901                 rx: low_priority_scene_rx,
1902                 tx: scene_tx.clone(),
1903                 simulate_slow_ms: 0,
1904             };
1905 
1906             thread::Builder::new().name(lp_scene_thread_name.clone()).spawn(move || {
1907                 register_thread_with_profiler(lp_scene_thread_name.clone());
1908                 if let Some(ref thread_listener) = *thread_listener_for_lp_scene_builder {
1909                     thread_listener.thread_started(&lp_scene_thread_name);
1910                 }
1911 
1912                 let mut scene_builder = lp_builder;
1913                 scene_builder.run();
1914 
1915                 if let Some(ref thread_listener) = *thread_listener_for_lp_scene_builder {
1916                     thread_listener.thread_stopped(&lp_scene_thread_name);
1917                 }
1918             })?;
1919 
1920             low_priority_scene_tx
1921         } else {
1922             scene_tx.clone()
1923         };
1924 
1925         thread::Builder::new().name(rb_thread_name.clone()).spawn(move || {
1926             register_thread_with_profiler(rb_thread_name.clone());
1927             if let Some(ref thread_listener) = *thread_listener_for_render_backend {
1928                 thread_listener.thread_started(&rb_thread_name);
1929             }
1930 
1931             let texture_cache = TextureCache::new(
1932                 max_texture_size,
1933                 max_texture_layers,
1934                 TileCache::tile_dimensions(config.testing),
1935             );
1936 
1937             let resource_cache = ResourceCache::new(
1938                 texture_cache,
1939                 glyph_rasterizer,
1940                 blob_image_handler,
1941             );
1942 
1943             let mut backend = RenderBackend::new(
1944                 api_rx,
1945                 payload_rx_for_backend,
1946                 result_tx,
1947                 scene_tx,
1948                 low_priority_scene_tx,
1949                 scene_rx,
1950                 device_pixel_ratio,
1951                 resource_cache,
1952                 backend_notifier,
1953                 config,
1954                 recorder,
1955                 sampler,
1956                 make_size_of_ops(),
1957                 debug_flags,
1958                 namespace_alloc_by_client,
1959             );
1960             backend.run(backend_profile_counters);
1961             if let Some(ref thread_listener) = *thread_listener_for_render_backend {
1962                 thread_listener.thread_stopped(&rb_thread_name);
1963             }
1964         })?;
1965 
1966         let ext_debug_marker = device.supports_extension("GL_EXT_debug_marker");
1967         let gpu_profile = GpuProfiler::new(Rc::clone(device.rc_gl()), ext_debug_marker);
1968         #[cfg(feature = "capture")]
1969         let read_fbo = device.create_fbo();
1970 
1971         let mut renderer = Renderer {
1972             result_rx,
1973             debug_server,
1974             device,
1975             active_documents: Vec::new(),
1976             pending_texture_updates: Vec::new(),
1977             pending_gpu_cache_updates: Vec::new(),
1978             pending_gpu_cache_clear: false,
1979             pending_shader_updates: Vec::new(),
1980             shaders,
1981             debug: LazyInitializedDebugRenderer::new(),
1982             debug_flags: DebugFlags::empty(),
1983             backend_profile_counters: BackendProfileCounters::new(),
1984             profile_counters: RendererProfileCounters::new(),
1985             resource_upload_time: 0,
1986             gpu_cache_upload_time: 0,
1987             profiler: Profiler::new(),
1988             new_frame_indicator: ChangeIndicator::new(),
1989             new_scene_indicator: ChangeIndicator::new(),
1990             slow_frame_indicator: ChangeIndicator::new(),
1991             max_recorded_profiles: options.max_recorded_profiles,
1992             clear_color: options.clear_color,
1993             enable_clear_scissor: options.enable_clear_scissor,
1994             last_time: 0,
1995             gpu_profile,
1996             gpu_glyph_renderer,
1997             vaos: RendererVAOs {
1998                 prim_vao,
1999                 blur_vao,
2000                 clip_vao,
2001                 border_vao,
2002                 scale_vao,
2003                 line_vao,
2004             },
2005             transforms_texture,
2006             prim_header_i_texture,
2007             prim_header_f_texture,
2008             render_task_texture,
2009             pipeline_info: PipelineInfo::default(),
2010             dither_matrix_texture,
2011             external_image_handler: None,
2012             output_image_handler: None,
2013             size_of_ops: make_size_of_ops(),
2014             output_targets: FastHashMap::default(),
2015             cpu_profiles: VecDeque::new(),
2016             gpu_profiles: VecDeque::new(),
2017             gpu_cache_texture,
2018             gpu_cache_debug_chunks: Vec::new(),
2019             gpu_cache_frame_id: FrameId::INVALID,
2020             gpu_cache_overflow: false,
2021             texture_cache_upload_pbo,
2022             texture_resolver,
2023             renderer_errors: Vec::new(),
2024             #[cfg(feature = "capture")]
2025             read_fbo,
2026             #[cfg(feature = "replay")]
2027             owned_external_images: FastHashMap::default(),
2028             notifications: Vec::new(),
2029             framebuffer_size: None,
2030             zoom_debug_texture: None,
2031             cursor_position: DeviceIntPoint::zero(),
2032         };
2033 
2034         // We initially set the flags to default and then now call set_debug_flags
2035         // to ensure any potential transition when enabling a flag is run.
2036         renderer.set_debug_flags(debug_flags);
2037 
2038         let sender = RenderApiSender::new(api_tx, payload_tx);
2039         Ok((renderer, sender))
2040     }
2041 
2042     /// Update the current position of the debug cursor.
set_cursor_position( &mut self, position: DeviceIntPoint, )2043     pub fn set_cursor_position(
2044         &mut self,
2045         position: DeviceIntPoint,
2046     ) {
2047         self.cursor_position = position;
2048     }
2049 
get_max_texture_size(&self) -> i322050     pub fn get_max_texture_size(&self) -> i32 {
2051         self.device.max_texture_size()
2052     }
2053 
get_graphics_api_info(&self) -> GraphicsApiInfo2054     pub fn get_graphics_api_info(&self) -> GraphicsApiInfo {
2055         GraphicsApiInfo {
2056             kind: GraphicsApi::OpenGL,
2057             version: self.device.gl().get_string(gl::VERSION),
2058             renderer: self.device.gl().get_string(gl::RENDERER),
2059         }
2060     }
2061 
2062     /// Returns the Epoch of the current frame in a pipeline.
current_epoch(&self, pipeline_id: PipelineId) -> Option<Epoch>2063     pub fn current_epoch(&self, pipeline_id: PipelineId) -> Option<Epoch> {
2064         self.pipeline_info.epochs.get(&pipeline_id).cloned()
2065     }
2066 
flush_pipeline_info(&mut self) -> PipelineInfo2067     pub fn flush_pipeline_info(&mut self) -> PipelineInfo {
2068         mem::replace(&mut self.pipeline_info, PipelineInfo::default())
2069     }
2070 
2071     // update the program cache with new binaries, e.g. when some of the lazy loaded
2072     // shader programs got activated in the mean time
update_program_cache(&mut self, cached_programs: Rc<ProgramCache>)2073     pub fn update_program_cache(&mut self, cached_programs: Rc<ProgramCache>) {
2074         self.device.update_program_cache(cached_programs);
2075     }
2076 
2077     /// Processes the result queue.
2078     ///
2079     /// Should be called before `render()`, as texture cache updates are done here.
update(&mut self)2080     pub fn update(&mut self) {
2081         profile_scope!("update");
2082         // Pull any pending results and return the most recent.
2083         while let Ok(msg) = self.result_rx.try_recv() {
2084             match msg {
2085                 ResultMsg::PublishPipelineInfo(mut pipeline_info) => {
2086                     for (pipeline_id, epoch) in pipeline_info.epochs {
2087                         self.pipeline_info.epochs.insert(pipeline_id, epoch);
2088                     }
2089                     self.pipeline_info.removed_pipelines.extend(pipeline_info.removed_pipelines.drain(..));
2090                 }
2091                 ResultMsg::PublishDocument(
2092                     document_id,
2093                     mut doc,
2094                     texture_update_list,
2095                     profile_counters,
2096                 ) => {
2097                     if doc.is_new_scene {
2098                         self.new_scene_indicator.changed();
2099                     }
2100 
2101                     // Add a new document to the active set, expressed as a `Vec` in order
2102                     // to re-order based on `DocumentLayer` during rendering.
2103                     match self.active_documents.iter().position(|&(id, _)| id == document_id) {
2104                         Some(pos) => {
2105                             // If the document we are replacing must be drawn
2106                             // (in order to update the texture cache), issue
2107                             // a render just to off-screen targets.
2108                             if self.active_documents[pos].1.frame.must_be_drawn() {
2109                                 let framebuffer_size = self.framebuffer_size;
2110                                 self.render_impl(framebuffer_size).ok();
2111                             }
2112                             self.active_documents[pos].1 = doc;
2113                         }
2114                         None => self.active_documents.push((document_id, doc)),
2115                     }
2116 
2117                     // IMPORTANT: The pending texture cache updates must be applied
2118                     //            *after* the previous frame has been rendered above
2119                     //            (if neceessary for a texture cache update). For
2120                     //            an example of why this is required:
2121                     //            1) Previous frame contains a render task that
2122                     //               targets Texture X.
2123                     //            2) New frame contains a texture cache update which
2124                     //               frees Texture X.
2125                     //            3) bad stuff happens.
2126 
2127                     //TODO: associate `document_id` with target window
2128                     self.pending_texture_updates.push(texture_update_list);
2129                     self.backend_profile_counters = profile_counters;
2130                 }
2131                 ResultMsg::UpdateGpuCache(mut list) => {
2132                     if list.clear {
2133                         self.pending_gpu_cache_clear = true;
2134                     }
2135                     if list.clear {
2136                         self.gpu_cache_debug_chunks = Vec::new();
2137                     }
2138                     for cmd in mem::replace(&mut list.debug_commands, Vec::new()) {
2139                         match cmd {
2140                             GpuCacheDebugCmd::Alloc(chunk) => {
2141                                 let row = chunk.address.v as usize;
2142                                 if row >= self.gpu_cache_debug_chunks.len() {
2143                                     self.gpu_cache_debug_chunks.resize(row + 1, Vec::new());
2144                                 }
2145                                 self.gpu_cache_debug_chunks[row].push(chunk);
2146                             },
2147                             GpuCacheDebugCmd::Free(address) => {
2148                                 let chunks = &mut self.gpu_cache_debug_chunks[address.v as usize];
2149                                 let pos = chunks.iter()
2150                                     .position(|x| x.address == address).unwrap();
2151                                 chunks.remove(pos);
2152                             },
2153                         }
2154                     }
2155                     self.pending_gpu_cache_updates.push(list);
2156                 }
2157                 ResultMsg::UpdateResources {
2158                     updates,
2159                     memory_pressure,
2160                 } => {
2161                     self.pending_texture_updates.push(updates);
2162                     self.device.begin_frame();
2163 
2164                     self.update_texture_cache();
2165 
2166                     // Flush the render target pool on memory pressure.
2167                     //
2168                     // This needs to be separate from the block below because
2169                     // the device module asserts if we delete textures while
2170                     // not in a frame.
2171                     if memory_pressure {
2172                         self.texture_resolver.retain_targets(&mut self.device, |_| false);
2173                     }
2174 
2175                     self.device.end_frame();
2176                     // If we receive a `PublishDocument` message followed by this one
2177                     // within the same update we need to cancel the frame because we
2178                     // might have deleted the resources in use in the frame due to a
2179                     // memory pressure event.
2180                     if memory_pressure {
2181                         self.active_documents.clear();
2182                     }
2183                 }
2184                 ResultMsg::AppendNotificationRequests(mut notifications) => {
2185                     if self.pending_texture_updates.is_empty() {
2186                         drain_filter(
2187                             &mut notifications,
2188                             |n| { n.when() == Checkpoint::FrameTexturesUpdated },
2189                             |n| { n.notify(); },
2190                         );
2191                     }
2192                     self.notifications.append(&mut notifications);
2193                 }
2194                 ResultMsg::RefreshShader(path) => {
2195                     self.pending_shader_updates.push(path);
2196                 }
2197                 ResultMsg::DebugOutput(output) => match output {
2198                     DebugOutput::FetchDocuments(string) |
2199                     DebugOutput::FetchClipScrollTree(string) => {
2200                         self.debug_server.send(string);
2201                     }
2202                     #[cfg(feature = "capture")]
2203                     DebugOutput::SaveCapture(config, deferred) => {
2204                         self.save_capture(config, deferred);
2205                     }
2206                     #[cfg(feature = "replay")]
2207                     DebugOutput::LoadCapture(root, plain_externals) => {
2208                         self.active_documents.clear();
2209                         self.load_capture(root, plain_externals);
2210                     }
2211                 },
2212                 ResultMsg::DebugCommand(command) => {
2213                     self.handle_debug_command(command);
2214                 }
2215             }
2216         }
2217     }
2218 
2219     #[cfg(not(feature = "debugger"))]
get_screenshot_for_debugger(&mut self) -> String2220     fn get_screenshot_for_debugger(&mut self) -> String {
2221         // Avoid unused param warning.
2222         let _ = &self.debug_server;
2223         String::new()
2224     }
2225 
2226 
2227     #[cfg(feature = "debugger")]
get_screenshot_for_debugger(&mut self) -> String2228     fn get_screenshot_for_debugger(&mut self) -> String {
2229         use api::ImageDescriptor;
2230 
2231         let desc = ImageDescriptor::new(1024, 768, ImageFormat::BGRA8, true, false);
2232         let data = self.device.read_pixels(&desc);
2233         let screenshot = debug_server::Screenshot::new(desc.size, data);
2234 
2235         serde_json::to_string(&screenshot).unwrap()
2236     }
2237 
2238     #[cfg(not(feature = "debugger"))]
get_passes_for_debugger(&self) -> String2239     fn get_passes_for_debugger(&self) -> String {
2240         // Avoid unused param warning.
2241         let _ = &self.debug_server;
2242         String::new()
2243     }
2244 
2245     #[cfg(feature = "debugger")]
debug_alpha_target(target: &AlphaRenderTarget) -> debug_server::Target2246     fn debug_alpha_target(target: &AlphaRenderTarget) -> debug_server::Target {
2247         let mut debug_target = debug_server::Target::new("A8");
2248 
2249         debug_target.add(
2250             debug_server::BatchKind::Cache,
2251             "Scalings",
2252             target.scalings.len(),
2253         );
2254         debug_target.add(
2255             debug_server::BatchKind::Cache,
2256             "Zero Clears",
2257             target.zero_clears.len(),
2258         );
2259         debug_target.add(
2260             debug_server::BatchKind::Clip,
2261             "BoxShadows",
2262             target.clip_batcher.box_shadows.len(),
2263         );
2264         debug_target.add(
2265             debug_server::BatchKind::Cache,
2266             "Vertical Blur",
2267             target.vertical_blurs.len(),
2268         );
2269         debug_target.add(
2270             debug_server::BatchKind::Cache,
2271             "Horizontal Blur",
2272             target.horizontal_blurs.len(),
2273         );
2274         debug_target.add(
2275             debug_server::BatchKind::Clip,
2276             "Rectangles",
2277             target.clip_batcher.rectangles.len(),
2278         );
2279         for (_, items) in target.clip_batcher.images.iter() {
2280             debug_target.add(debug_server::BatchKind::Clip, "Image mask", items.len());
2281         }
2282 
2283         debug_target
2284     }
2285 
2286     #[cfg(feature = "debugger")]
debug_color_target(target: &ColorRenderTarget) -> debug_server::Target2287     fn debug_color_target(target: &ColorRenderTarget) -> debug_server::Target {
2288         let mut debug_target = debug_server::Target::new("RGBA8");
2289 
2290         debug_target.add(
2291             debug_server::BatchKind::Cache,
2292             "Scalings",
2293             target.scalings.len(),
2294         );
2295         debug_target.add(
2296             debug_server::BatchKind::Cache,
2297             "Readbacks",
2298             target.readbacks.len(),
2299         );
2300         debug_target.add(
2301             debug_server::BatchKind::Cache,
2302             "Vertical Blur",
2303             target.vertical_blurs.len(),
2304         );
2305         debug_target.add(
2306             debug_server::BatchKind::Cache,
2307             "Horizontal Blur",
2308             target.horizontal_blurs.len(),
2309         );
2310 
2311         for alpha_batch_container in &target.alpha_batch_containers {
2312             for batch in alpha_batch_container.opaque_batches.iter().rev() {
2313                 debug_target.add(
2314                     debug_server::BatchKind::Opaque,
2315                     batch.key.kind.debug_name(),
2316                     batch.instances.len(),
2317                 );
2318             }
2319 
2320             for batch in &alpha_batch_container.alpha_batches {
2321                 debug_target.add(
2322                     debug_server::BatchKind::Alpha,
2323                     batch.key.kind.debug_name(),
2324                     batch.instances.len(),
2325                 );
2326             }
2327         }
2328 
2329         debug_target
2330     }
2331 
2332     #[cfg(feature = "debugger")]
debug_texture_cache_target(target: &TextureCacheRenderTarget) -> debug_server::Target2333     fn debug_texture_cache_target(target: &TextureCacheRenderTarget) -> debug_server::Target {
2334         let mut debug_target = debug_server::Target::new("Texture Cache");
2335 
2336         debug_target.add(
2337             debug_server::BatchKind::Cache,
2338             "Horizontal Blur",
2339             target.horizontal_blurs.len(),
2340         );
2341 
2342         debug_target
2343     }
2344 
2345     #[cfg(feature = "debugger")]
get_passes_for_debugger(&self) -> String2346     fn get_passes_for_debugger(&self) -> String {
2347         let mut debug_passes = debug_server::PassList::new();
2348 
2349         for &(_, ref render_doc) in &self.active_documents {
2350             for pass in &render_doc.frame.passes {
2351                 let mut debug_targets = Vec::new();
2352                 match pass.kind {
2353                     RenderPassKind::MainFramebuffer(ref target) => {
2354                         debug_targets.push(Self::debug_color_target(target));
2355                     }
2356                     RenderPassKind::OffScreen { ref alpha, ref color, ref texture_cache } => {
2357                         debug_targets.extend(alpha.targets.iter().map(Self::debug_alpha_target));
2358                         debug_targets.extend(color.targets.iter().map(Self::debug_color_target));
2359                         debug_targets.extend(texture_cache.iter().map(|(_, target)| Self::debug_texture_cache_target(target)))
2360                     }
2361                 }
2362 
2363                 debug_passes.add(debug_server::Pass { targets: debug_targets });
2364             }
2365         }
2366 
2367         serde_json::to_string(&debug_passes).unwrap()
2368     }
2369 
2370     #[cfg(not(feature = "debugger"))]
get_render_tasks_for_debugger(&self) -> String2371     fn get_render_tasks_for_debugger(&self) -> String {
2372         String::new()
2373     }
2374 
2375     #[cfg(feature = "debugger")]
get_render_tasks_for_debugger(&self) -> String2376     fn get_render_tasks_for_debugger(&self) -> String {
2377         let mut debug_root = debug_server::RenderTaskList::new();
2378 
2379         for &(_, ref render_doc) in &self.active_documents {
2380             let debug_node = debug_server::TreeNode::new("document render tasks");
2381             let mut builder = debug_server::TreeNodeBuilder::new(debug_node);
2382 
2383             let render_tasks = &render_doc.frame.render_tasks;
2384             match render_tasks.tasks.last() {
2385                 Some(main_task) => main_task.print_with(&mut builder, render_tasks),
2386                 None => continue,
2387             };
2388 
2389             debug_root.add(builder.build());
2390         }
2391 
2392         serde_json::to_string(&debug_root).unwrap()
2393     }
2394 
handle_debug_command(&mut self, command: DebugCommand)2395     fn handle_debug_command(&mut self, command: DebugCommand) {
2396         match command {
2397             DebugCommand::EnableDualSourceBlending(_) => {
2398                 panic!("Should be handled by render backend");
2399             }
2400             DebugCommand::FetchDocuments |
2401             DebugCommand::FetchClipScrollTree => {}
2402             DebugCommand::FetchRenderTasks => {
2403                 let json = self.get_render_tasks_for_debugger();
2404                 self.debug_server.send(json);
2405             }
2406             DebugCommand::FetchPasses => {
2407                 let json = self.get_passes_for_debugger();
2408                 self.debug_server.send(json);
2409             }
2410             DebugCommand::FetchScreenshot => {
2411                 let json = self.get_screenshot_for_debugger();
2412                 self.debug_server.send(json);
2413             }
2414             DebugCommand::SaveCapture(..) |
2415             DebugCommand::LoadCapture(..) => {
2416                 panic!("Capture commands are not welcome here! Did you build with 'capture' feature?")
2417             }
2418             DebugCommand::ClearCaches(_)
2419             | DebugCommand::SimulateLongSceneBuild(_)
2420             | DebugCommand::SimulateLongLowPrioritySceneBuild(_) => {}
2421             DebugCommand::InvalidateGpuCache => {
2422                 match self.gpu_cache_texture.bus {
2423                     GpuCacheBus::PixelBuffer { ref mut rows, .. } => {
2424                         info!("Invalidating GPU caches");
2425                         for row in rows {
2426                             row.is_dirty = true;
2427                         }
2428                     }
2429                     GpuCacheBus::Scatter { .. } => {
2430                         warn!("Unable to invalidate scattered GPU cache");
2431                     }
2432                 }
2433             }
2434             DebugCommand::SetFlags(flags) => {
2435                 self.set_debug_flags(flags);
2436             }
2437         }
2438     }
2439 
2440     /// Set a callback for handling external images.
set_external_image_handler(&mut self, handler: Box<ExternalImageHandler>)2441     pub fn set_external_image_handler(&mut self, handler: Box<ExternalImageHandler>) {
2442         self.external_image_handler = Some(handler);
2443     }
2444 
2445     /// Set a callback for handling external outputs.
set_output_image_handler(&mut self, handler: Box<OutputImageHandler>)2446     pub fn set_output_image_handler(&mut self, handler: Box<OutputImageHandler>) {
2447         self.output_image_handler = Some(handler);
2448     }
2449 
2450     /// Retrieve (and clear) the current list of recorded frame profiles.
get_frame_profiles(&mut self) -> (Vec<CpuProfile>, Vec<GpuProfile>)2451     pub fn get_frame_profiles(&mut self) -> (Vec<CpuProfile>, Vec<GpuProfile>) {
2452         let cpu_profiles = self.cpu_profiles.drain(..).collect();
2453         let gpu_profiles = self.gpu_profiles.drain(..).collect();
2454         (cpu_profiles, gpu_profiles)
2455     }
2456 
2457     /// Returns `true` if the active rendered documents (that need depth buffer)
2458     /// intersect on the main framebuffer, in which case we don't clear
2459     /// the whole depth and instead clear each document area separately.
are_documents_intersecting_depth(&self) -> bool2460     fn are_documents_intersecting_depth(&self) -> bool {
2461         let document_rects = self.active_documents
2462             .iter()
2463             .filter_map(|&(_, ref render_doc)| {
2464                 match render_doc.frame.passes.last() {
2465                     Some(&RenderPass { kind: RenderPassKind::MainFramebuffer(ref target), .. })
2466                         if target.needs_depth() => Some(render_doc.frame.inner_rect),
2467                     _ => None,
2468                 }
2469             })
2470             .collect::<Vec<_>>();
2471 
2472         for (i, rect) in document_rects.iter().enumerate() {
2473             for other in &document_rects[i+1 ..] {
2474                 if rect.intersects(other) {
2475                     return true
2476                 }
2477             }
2478         }
2479 
2480         false
2481     }
2482 
notify_slow_frame(&mut self)2483     pub fn notify_slow_frame(&mut self) {
2484         self.slow_frame_indicator.changed();
2485     }
2486 
2487     /// Renders the current frame.
2488     ///
2489     /// A Frame is supplied by calling [`generate_frame()`][webrender_api::Transaction::generate_frame].
render( &mut self, framebuffer_size: DeviceIntSize, ) -> Result<RenderResults, Vec<RendererError>>2490     pub fn render(
2491         &mut self,
2492         framebuffer_size: DeviceIntSize,
2493     ) -> Result<RenderResults, Vec<RendererError>> {
2494         self.framebuffer_size = Some(framebuffer_size);
2495 
2496         let result = self.render_impl(Some(framebuffer_size));
2497 
2498         drain_filter(
2499             &mut self.notifications,
2500             |n| { n.when() == Checkpoint::FrameRendered },
2501             |n| { n.notify(); },
2502         );
2503 
2504         // This is the end of the rendering pipeline. If some notifications are is still there,
2505         // just clear them and they will autimatically fire the Checkpoint::TransactionDropped
2506         // event. Otherwise they would just pile up in this vector forever.
2507         self.notifications.clear();
2508 
2509         result
2510     }
2511 
2512     // If framebuffer_size is None, don't render
2513     // to the main frame buffer. This is useful
2514     // to update texture cache render tasks but
2515     // avoid doing a full frame render.
render_impl( &mut self, framebuffer_size: Option<DeviceIntSize>, ) -> Result<RenderResults, Vec<RendererError>>2516     fn render_impl(
2517         &mut self,
2518         framebuffer_size: Option<DeviceIntSize>,
2519     ) -> Result<RenderResults, Vec<RendererError>> {
2520         profile_scope!("render");
2521         let mut results = RenderResults::default();
2522         if self.active_documents.is_empty() {
2523             self.last_time = precise_time_ns();
2524             return Ok(results);
2525         }
2526 
2527         let mut frame_profiles = Vec::new();
2528         let mut profile_timers = RendererProfileTimers::new();
2529 
2530         let profile_samplers = {
2531             let _gm = self.gpu_profile.start_marker("build samples");
2532             // Block CPU waiting for last frame's GPU profiles to arrive.
2533             // In general this shouldn't block unless heavily GPU limited.
2534             let (gpu_frame_id, timers, samplers) = self.gpu_profile.build_samples();
2535 
2536             if self.max_recorded_profiles > 0 {
2537                 while self.gpu_profiles.len() >= self.max_recorded_profiles {
2538                     self.gpu_profiles.pop_front();
2539                 }
2540                 self.gpu_profiles
2541                     .push_back(GpuProfile::new(gpu_frame_id, &timers));
2542             }
2543             profile_timers.gpu_samples = timers;
2544             samplers
2545         };
2546 
2547 
2548         let cpu_frame_id = profile_timers.cpu_time.profile(|| {
2549             let _gm = self.gpu_profile.start_marker("begin frame");
2550             let frame_id = self.device.begin_frame();
2551             self.gpu_profile.begin_frame(frame_id);
2552 
2553             self.device.disable_scissor();
2554             self.device.disable_depth();
2555             self.set_blend(false, FramebufferKind::Main);
2556             //self.update_shaders();
2557 
2558             self.update_texture_cache();
2559 
2560             frame_id
2561         });
2562 
2563         profile_timers.cpu_time.profile(|| {
2564             let clear_depth_value = if self.are_documents_intersecting_depth() {
2565                 None
2566             } else {
2567                 Some(1.0)
2568             };
2569 
2570             //Note: another borrowck dance
2571             let mut active_documents = mem::replace(&mut self.active_documents, Vec::default());
2572             // sort by the document layer id
2573             active_documents.sort_by_key(|&(_, ref render_doc)| render_doc.frame.layer);
2574 
2575             // don't clear the framebuffer if one of the rendered documents will overwrite it
2576             if let Some(framebuffer_size) = framebuffer_size {
2577                 let needs_color_clear = !active_documents
2578                     .iter()
2579                     .any(|&(_, RenderedDocument { ref frame, .. })| {
2580                         frame.background_color.is_some() &&
2581                         frame.inner_rect.origin == DeviceIntPoint::zero() &&
2582                         frame.inner_rect.size == framebuffer_size
2583                     });
2584 
2585                 if needs_color_clear || clear_depth_value.is_some() {
2586                     let clear_color = if needs_color_clear {
2587                         self.clear_color.map(|color| color.to_array())
2588                     } else {
2589                         None
2590                     };
2591                     self.device.reset_draw_target();
2592                     self.device.enable_depth_write();
2593                     self.device.clear_target(clear_color, clear_depth_value, None);
2594                     self.device.disable_depth_write();
2595                 }
2596             }
2597 
2598             #[cfg(feature = "replay")]
2599             self.texture_resolver.external_images.extend(
2600                 self.owned_external_images.iter().map(|(key, value)| (*key, value.clone()))
2601             );
2602 
2603             for &mut (_, RenderedDocument { ref mut frame, .. }) in &mut active_documents {
2604                 frame.profile_counters.reset_targets();
2605                 self.prepare_gpu_cache(frame);
2606                 assert!(frame.gpu_cache_frame_id <= self.gpu_cache_frame_id,
2607                     "Received frame depends on a later GPU cache epoch ({:?}) than one we received last via `UpdateGpuCache` ({:?})",
2608                     frame.gpu_cache_frame_id, self.gpu_cache_frame_id);
2609 
2610                 self.draw_tile_frame(
2611                     frame,
2612                     framebuffer_size,
2613                     clear_depth_value.is_some(),
2614                     cpu_frame_id,
2615                     &mut results.stats
2616                 );
2617 
2618                 if self.debug_flags.contains(DebugFlags::PROFILER_DBG) {
2619                     frame_profiles.push(frame.profile_counters.clone());
2620                 }
2621 
2622                 let dirty_regions =
2623                     mem::replace(&mut frame.recorded_dirty_regions, Vec::new());
2624                 results.recorded_dirty_regions.extend(dirty_regions);
2625             }
2626 
2627             self.unlock_external_images();
2628             self.active_documents = active_documents;
2629         });
2630 
2631         let current_time = precise_time_ns();
2632         if framebuffer_size.is_some() {
2633             let ns = current_time - self.last_time;
2634             self.profile_counters.frame_time.set(ns);
2635         }
2636 
2637         if self.max_recorded_profiles > 0 {
2638             while self.cpu_profiles.len() >= self.max_recorded_profiles {
2639                 self.cpu_profiles.pop_front();
2640             }
2641             let cpu_profile = CpuProfile::new(
2642                 cpu_frame_id,
2643                 self.backend_profile_counters.total_time.get(),
2644                 profile_timers.cpu_time.get(),
2645                 self.profile_counters.draw_calls.get(),
2646             );
2647             self.cpu_profiles.push_back(cpu_profile);
2648         }
2649 
2650         if self.debug_flags.contains(DebugFlags::PROFILER_DBG) {
2651             if let Some(framebuffer_size) = framebuffer_size {
2652                 //TODO: take device/pixel ratio into equation?
2653                 if let Some(debug_renderer) = self.debug.get_mut(&mut self.device) {
2654                     let screen_fraction = 1.0 / framebuffer_size.to_f32().area();
2655                     self.profiler.draw_profile(
2656                         &frame_profiles,
2657                         &self.backend_profile_counters,
2658                         &self.profile_counters,
2659                         &mut profile_timers,
2660                         &profile_samplers,
2661                         screen_fraction,
2662                         debug_renderer,
2663                         self.debug_flags.contains(DebugFlags::COMPACT_PROFILER),
2664                     );
2665                 }
2666             }
2667         }
2668 
2669         let mut x = 0.0;
2670         if self.debug_flags.contains(DebugFlags::NEW_FRAME_INDICATOR) {
2671             if let Some(debug_renderer) = self.debug.get_mut(&mut self.device) {
2672                 self.new_frame_indicator.changed();
2673                 self.new_frame_indicator.draw(
2674                     x, 0.0,
2675                     ColorU::new(0, 110, 220, 255),
2676                     debug_renderer,
2677                 );
2678                 x += ChangeIndicator::width();
2679             }
2680         }
2681 
2682         if self.debug_flags.contains(DebugFlags::NEW_SCENE_INDICATOR) {
2683             if let Some(debug_renderer) = self.debug.get_mut(&mut self.device) {
2684                 self.new_scene_indicator.draw(
2685                     x, 0.0,
2686                     ColorU::new(0, 220, 110, 255),
2687                     debug_renderer,
2688                 );
2689                 x += ChangeIndicator::width();
2690             }
2691         }
2692 
2693         if self.debug_flags.contains(DebugFlags::SLOW_FRAME_INDICATOR) {
2694             if let Some(debug_renderer) = self.debug.get_mut(&mut self.device) {
2695                 self.slow_frame_indicator.draw(
2696                     x, 0.0,
2697                     ColorU::new(220, 30, 10, 255),
2698                     debug_renderer,
2699                 );
2700             }
2701         }
2702 
2703         if self.debug_flags.contains(DebugFlags::ECHO_DRIVER_MESSAGES) {
2704             self.device.echo_driver_messages();
2705         }
2706 
2707         results.stats.texture_upload_kb = self.profile_counters.texture_data_uploaded.get();
2708         self.backend_profile_counters.reset();
2709         self.profile_counters.reset();
2710         self.profile_counters.frame_counter.inc();
2711         results.stats.resource_upload_time = self.resource_upload_time;
2712         self.resource_upload_time = 0;
2713         results.stats.gpu_cache_upload_time = self.gpu_cache_upload_time;
2714         self.gpu_cache_upload_time = 0;
2715 
2716         profile_timers.cpu_time.profile(|| {
2717             let _gm = self.gpu_profile.start_marker("end frame");
2718             self.gpu_profile.end_frame();
2719             if let Some(debug_renderer) = self.debug.try_get_mut() {
2720                 debug_renderer.render(&mut self.device, framebuffer_size);
2721             }
2722             self.device.end_frame();
2723         });
2724         if framebuffer_size.is_some() {
2725             self.last_time = current_time;
2726         }
2727 
2728         if self.renderer_errors.is_empty() {
2729             Ok(results)
2730         } else {
2731             Err(mem::replace(&mut self.renderer_errors, Vec::new()))
2732         }
2733     }
2734 
update_gpu_cache(&mut self)2735     fn update_gpu_cache(&mut self) {
2736         let _gm = self.gpu_profile.start_marker("gpu cache update");
2737 
2738         // For an artificial stress test of GPU cache resizing,
2739         // always pass an extra update list with at least one block in it.
2740         let gpu_cache_height = self.gpu_cache_texture.get_height();
2741         if gpu_cache_height != 0 && GPU_CACHE_RESIZE_TEST {
2742             self.pending_gpu_cache_updates.push(GpuCacheUpdateList {
2743                 frame_id: FrameId::INVALID,
2744                 clear: false,
2745                 height: gpu_cache_height,
2746                 blocks: vec![[1f32; 4].into()],
2747                 updates: Vec::new(),
2748                 debug_commands: Vec::new(),
2749             });
2750         }
2751 
2752         let (updated_blocks, max_requested_height) = self
2753             .pending_gpu_cache_updates
2754             .iter()
2755             .fold((0, gpu_cache_height), |(count, height), list| {
2756                 (count + list.blocks.len(), cmp::max(height, list.height))
2757             });
2758 
2759         if max_requested_height > self.get_max_texture_size() && !self.gpu_cache_overflow {
2760             self.gpu_cache_overflow = true;
2761             self.renderer_errors.push(RendererError::MaxTextureSize);
2762         }
2763 
2764         // Note: if we decide to switch to scatter-style GPU cache update
2765         // permanently, we can have this code nicer with `BufferUploader` kind
2766         // of helper, similarly to how `TextureUploader` API is used.
2767         self.gpu_cache_texture.prepare_for_updates(
2768             &mut self.device,
2769             updated_blocks,
2770             max_requested_height,
2771         );
2772 
2773         for update_list in self.pending_gpu_cache_updates.drain(..) {
2774             assert!(update_list.height <= max_requested_height);
2775             if update_list.frame_id > self.gpu_cache_frame_id {
2776                 self.gpu_cache_frame_id = update_list.frame_id
2777             }
2778             self.gpu_cache_texture
2779                 .update(&mut self.device, &update_list);
2780         }
2781 
2782         let mut upload_time = TimeProfileCounter::new("GPU cache upload time", false);
2783         let updated_rows = upload_time.profile(|| {
2784             return self.gpu_cache_texture.flush(&mut self.device);
2785         });
2786         self.gpu_cache_upload_time += upload_time.get();
2787 
2788         let counters = &mut self.backend_profile_counters.resources.gpu_cache;
2789         counters.updated_rows.set(updated_rows);
2790         counters.updated_blocks.set(updated_blocks);
2791     }
2792 
prepare_gpu_cache(&mut self, frame: &Frame)2793     fn prepare_gpu_cache(&mut self, frame: &Frame) {
2794         if self.pending_gpu_cache_clear {
2795             let use_scatter =
2796                 matches!(self.gpu_cache_texture.bus, GpuCacheBus::Scatter { .. });
2797             let new_cache = GpuCacheTexture::new(&mut self.device, use_scatter).unwrap();
2798             let old_cache = mem::replace(&mut self.gpu_cache_texture, new_cache);
2799             old_cache.deinit(&mut self.device);
2800             self.pending_gpu_cache_clear = false;
2801         }
2802 
2803         let deferred_update_list = self.update_deferred_resolves(&frame.deferred_resolves);
2804         self.pending_gpu_cache_updates.extend(deferred_update_list);
2805 
2806         self.update_gpu_cache();
2807 
2808         // Note: the texture might have changed during the `update`,
2809         // so we need to bind it here.
2810         self.device.bind_texture(
2811             TextureSampler::GpuCache,
2812             self.gpu_cache_texture.texture.as_ref().unwrap(),
2813         );
2814     }
2815 
update_texture_cache(&mut self)2816     fn update_texture_cache(&mut self) {
2817         let _gm = self.gpu_profile.start_marker("texture cache update");
2818         let mut pending_texture_updates = mem::replace(&mut self.pending_texture_updates, vec![]);
2819 
2820         let mut upload_time = TimeProfileCounter::new("Resource upload time", false);
2821         upload_time.profile(|| {
2822             for update_list in pending_texture_updates.drain(..) {
2823                 for allocation in update_list.allocations {
2824                     let is_realloc = matches!(allocation.kind, TextureCacheAllocationKind::Realloc(..));
2825                     match allocation.kind {
2826                         TextureCacheAllocationKind::Alloc(info) |
2827                         TextureCacheAllocationKind::Realloc(info) => {
2828                             // Create a new native texture, as requested by the texture cache.
2829                             //
2830                             // Ensure no PBO is bound when creating the texture storage,
2831                             // or GL will attempt to read data from there.
2832                             let mut texture = self.device.create_texture(
2833                                 TextureTarget::Array,
2834                                 info.format,
2835                                 info.width,
2836                                 info.height,
2837                                 info.filter,
2838                                 // This needs to be a render target because some render
2839                                 // tasks get rendered into the texture cache.
2840                                 Some(RenderTargetInfo { has_depth: false }),
2841                                 info.layer_count,
2842                             );
2843 
2844                             if info.is_shared_cache {
2845                                 texture.flags_mut()
2846                                     .insert(TextureFlags::IS_SHARED_TEXTURE_CACHE);
2847 
2848                                 // Textures in the cache generally don't need to be cleared,
2849                                 // but we do so if the debug display is active to make it
2850                                 // easier to identify unallocated regions.
2851                                 if self.debug_flags.contains(DebugFlags::TEXTURE_CACHE_DBG) {
2852                                     self.clear_texture(&texture, TEXTURE_CACHE_DBG_CLEAR_COLOR);
2853                                 }
2854                             }
2855 
2856                             let old = self.texture_resolver.texture_cache_map.insert(allocation.id, texture);
2857                             assert_eq!(old.is_some(), is_realloc, "Renderer and RenderBackend disagree");
2858                             if let Some(old) = old {
2859                                 self.device.blit_renderable_texture(
2860                                     self.texture_resolver.texture_cache_map.get_mut(&allocation.id).unwrap(),
2861                                     &old
2862                                 );
2863                                 self.device.delete_texture(old);
2864                             }
2865                         },
2866                         TextureCacheAllocationKind::Free => {
2867                             let texture = self.texture_resolver.texture_cache_map.remove(&allocation.id).unwrap();
2868                             self.device.delete_texture(texture);
2869                         },
2870                     }
2871                 }
2872 
2873                 for update in update_list.updates {
2874                     let TextureCacheUpdate { id, rect, stride, offset, layer_index, source } = update;
2875                     let texture = &self.texture_resolver.texture_cache_map[&id];
2876 
2877                     let bytes_uploaded = match source {
2878                         TextureUpdateSource::Bytes { data } => {
2879                             let mut uploader = self.device.upload_texture(
2880                                 texture,
2881                                 &self.texture_cache_upload_pbo,
2882                                 0,
2883                             );
2884                             uploader.upload(
2885                                 rect, layer_index, stride,
2886                                 &data[offset as usize ..],
2887                             )
2888                         }
2889                         TextureUpdateSource::External { id, channel_index } => {
2890                             let mut uploader = self.device.upload_texture(
2891                                 texture,
2892                                 &self.texture_cache_upload_pbo,
2893                                 0,
2894                             );
2895                             let handler = self.external_image_handler
2896                                 .as_mut()
2897                                 .expect("Found external image, but no handler set!");
2898                             // The filter is only relevant for NativeTexture external images.
2899                             let size = match handler.lock(id, channel_index, ImageRendering::Auto).source {
2900                                 ExternalImageSource::RawData(data) => {
2901                                     uploader.upload(
2902                                         rect, layer_index, stride,
2903                                         &data[offset as usize ..],
2904                                     )
2905                                 }
2906                                 ExternalImageSource::Invalid => {
2907                                     // Create a local buffer to fill the pbo.
2908                                     let bpp = texture.get_format().bytes_per_pixel();
2909                                     let width = stride.unwrap_or(rect.size.width * bpp);
2910                                     let total_size = width * rect.size.height;
2911                                     // WR haven't support RGBAF32 format in texture_cache, so
2912                                     // we use u8 type here.
2913                                     let dummy_data: Vec<u8> = vec![255; total_size as usize];
2914                                     uploader.upload(rect, layer_index, stride, &dummy_data)
2915                                 }
2916                                 ExternalImageSource::NativeTexture(eid) => {
2917                                     panic!("Unexpected external texture {:?} for the texture cache update of {:?}", eid, id);
2918                                 }
2919                             };
2920                             handler.unlock(id, channel_index);
2921                             size
2922                         }
2923                         TextureUpdateSource::DebugClear => {
2924                             self.device.bind_draw_target(DrawTarget::Texture {
2925                                 texture,
2926                                 layer: layer_index as usize,
2927                                 with_depth: false,
2928                             });
2929                             self.device.clear_target(
2930                                 Some(TEXTURE_CACHE_DBG_CLEAR_COLOR),
2931                                 None,
2932                                 Some(rect.to_i32())
2933                             );
2934                             0
2935                         }
2936                     };
2937                     self.profile_counters.texture_data_uploaded.add(bytes_uploaded >> 10);
2938                 }
2939             }
2940 
2941             drain_filter(
2942                 &mut self.notifications,
2943                 |n| { n.when() == Checkpoint::FrameTexturesUpdated },
2944                 |n| { n.notify(); },
2945             );
2946         });
2947         self.resource_upload_time += upload_time.get();
2948     }
2949 
draw_instanced_batch<T>( &mut self, data: &[T], vertex_array_kind: VertexArrayKind, textures: &BatchTextures, stats: &mut RendererStats, )2950     pub(crate) fn draw_instanced_batch<T>(
2951         &mut self,
2952         data: &[T],
2953         vertex_array_kind: VertexArrayKind,
2954         textures: &BatchTextures,
2955         stats: &mut RendererStats,
2956     ) {
2957         for i in 0 .. textures.colors.len() {
2958             self.texture_resolver.bind(
2959                 &textures.colors[i],
2960                 TextureSampler::color(i),
2961                 &mut self.device,
2962             );
2963         }
2964 
2965         // TODO: this probably isn't the best place for this.
2966         if let Some(ref texture) = self.dither_matrix_texture {
2967             self.device.bind_texture(TextureSampler::Dither, texture);
2968         }
2969 
2970         self.draw_instanced_batch_with_previously_bound_textures(data, vertex_array_kind, stats)
2971     }
2972 
draw_instanced_batch_with_previously_bound_textures<T>( &mut self, data: &[T], vertex_array_kind: VertexArrayKind, stats: &mut RendererStats, )2973     pub(crate) fn draw_instanced_batch_with_previously_bound_textures<T>(
2974         &mut self,
2975         data: &[T],
2976         vertex_array_kind: VertexArrayKind,
2977         stats: &mut RendererStats,
2978     ) {
2979         // If we end up with an empty draw call here, that means we have
2980         // probably introduced unnecessary batch breaks during frame
2981         // building - so we should be catching this earlier and removing
2982         // the batch.
2983         debug_assert!(!data.is_empty());
2984 
2985         let vao = get_vao(vertex_array_kind, &self.vaos, &self.gpu_glyph_renderer);
2986 
2987         self.device.bind_vao(vao);
2988 
2989         let batched = !self.debug_flags.contains(DebugFlags::DISABLE_BATCHING);
2990 
2991         if batched {
2992             self.device
2993                 .update_vao_instances(vao, data, VertexUsageHint::Stream);
2994             self.device
2995                 .draw_indexed_triangles_instanced_u16(6, data.len() as i32);
2996             self.profile_counters.draw_calls.inc();
2997             stats.total_draw_calls += 1;
2998         } else {
2999             for i in 0 .. data.len() {
3000                 self.device
3001                     .update_vao_instances(vao, &data[i .. i + 1], VertexUsageHint::Stream);
3002                 self.device.draw_triangles_u16(0, 6);
3003                 self.profile_counters.draw_calls.inc();
3004                 stats.total_draw_calls += 1;
3005             }
3006         }
3007 
3008         self.profile_counters.vertices.add(6 * data.len());
3009     }
3010 
handle_readback_composite( &mut self, draw_target: DrawTarget, uses_scissor: bool, source: &RenderTask, backdrop: &RenderTask, readback: &RenderTask, )3011     fn handle_readback_composite(
3012         &mut self,
3013         draw_target: DrawTarget,
3014         uses_scissor: bool,
3015         source: &RenderTask,
3016         backdrop: &RenderTask,
3017         readback: &RenderTask,
3018     ) {
3019         if uses_scissor {
3020             self.device.disable_scissor();
3021         }
3022 
3023         let cache_texture = self.texture_resolver
3024             .resolve(&TextureSource::PrevPassColor)
3025             .unwrap();
3026 
3027         // Before submitting the composite batch, do the
3028         // framebuffer readbacks that are needed for each
3029         // composite operation in this batch.
3030         let (readback_rect, readback_layer) = readback.get_target_rect();
3031         let (backdrop_rect, _) = backdrop.get_target_rect();
3032         let backdrop_screen_origin = match backdrop.kind {
3033             RenderTaskKind::Picture(ref task_info) => task_info.content_origin,
3034             _ => panic!("bug: composite on non-picture?"),
3035         };
3036         let source_screen_origin = match source.kind {
3037             RenderTaskKind::Picture(ref task_info) => task_info.content_origin,
3038             _ => panic!("bug: composite on non-picture?"),
3039         };
3040 
3041         // Bind the FBO to blit the backdrop to.
3042         // Called per-instance in case the layer (and therefore FBO)
3043         // changes. The device will skip the GL call if the requested
3044         // target is already bound.
3045         let cache_draw_target = DrawTarget::Texture {
3046             texture: cache_texture,
3047             layer: readback_layer.0 as usize,
3048             with_depth: false,
3049         };
3050         self.device.bind_draw_target(cache_draw_target);
3051 
3052         let mut src = DeviceIntRect::new(
3053             source_screen_origin + (backdrop_rect.origin - backdrop_screen_origin),
3054             readback_rect.size,
3055         );
3056         let mut dest = readback_rect.to_i32();
3057 
3058         // Need to invert the y coordinates and flip the image vertically when
3059         // reading back from the framebuffer.
3060         if draw_target.is_default() {
3061             src.origin.y = draw_target.dimensions().height as i32 - src.size.height - src.origin.y;
3062             dest.origin.y += dest.size.height;
3063             dest.size.height = -dest.size.height;
3064         }
3065 
3066         self.device.bind_read_target(draw_target.into());
3067         self.device.blit_render_target(src, dest, TextureFilter::Linear);
3068 
3069         // Restore draw target to current pass render target + layer, and reset
3070         // the read target.
3071         self.device.bind_draw_target(draw_target);
3072         self.device.reset_read_target();
3073 
3074         if uses_scissor {
3075             self.device.enable_scissor();
3076         }
3077     }
3078 
handle_blits( &mut self, blits: &[BlitJob], render_tasks: &RenderTaskTree, )3079     fn handle_blits(
3080         &mut self,
3081         blits: &[BlitJob],
3082         render_tasks: &RenderTaskTree,
3083     ) {
3084         if blits.is_empty() {
3085             return;
3086         }
3087 
3088         let _timer = self.gpu_profile.start_timer(GPU_TAG_BLIT);
3089 
3090         // TODO(gw): For now, we don't bother batching these by source texture.
3091         //           If if ever shows up as an issue, we can easily batch them.
3092         for blit in blits {
3093             let source_rect = match blit.source {
3094                 BlitJobSource::Texture(texture_id, layer, source_rect) => {
3095                     // A blit from a texture into this target.
3096                     let texture = self.texture_resolver
3097                         .resolve(&texture_id)
3098                         .expect("BUG: invalid source texture");
3099                     self.device.bind_read_target(ReadTarget::Texture { texture, layer: layer as usize });
3100                     source_rect
3101                 }
3102                 BlitJobSource::RenderTask(task_id) => {
3103                     // A blit from the child render task into this target.
3104                     // TODO(gw): Support R8 format here once we start
3105                     //           creating mips for alpha masks.
3106                     let texture = self.texture_resolver
3107                         .resolve(&TextureSource::PrevPassColor)
3108                         .expect("BUG: invalid source texture");
3109                     let source = &render_tasks[task_id];
3110                     let (source_rect, layer) = source.get_target_rect();
3111                     self.device.bind_read_target(ReadTarget::Texture { texture, layer: layer.0 });
3112                     source_rect
3113                 }
3114             };
3115             debug_assert_eq!(source_rect.size, blit.target_rect.size);
3116             self.device.blit_render_target(
3117                 source_rect,
3118                 blit.target_rect,
3119                 TextureFilter::Linear,
3120             );
3121         }
3122     }
3123 
handle_scaling( &mut self, scalings: &[ScalingInstance], source: TextureSource, projection: &Transform3D<f32>, stats: &mut RendererStats, )3124     fn handle_scaling(
3125         &mut self,
3126         scalings: &[ScalingInstance],
3127         source: TextureSource,
3128         projection: &Transform3D<f32>,
3129         stats: &mut RendererStats,
3130     ) {
3131         if scalings.is_empty() {
3132             return
3133         }
3134 
3135         let _timer = self.gpu_profile.start_timer(GPU_TAG_SCALE);
3136 
3137         match source {
3138             TextureSource::PrevPassColor => {
3139                 self.shaders.borrow_mut().cs_scale_rgba8.bind(&mut self.device,
3140                                                               &projection,
3141                                                               &mut self.renderer_errors);
3142             }
3143             TextureSource::PrevPassAlpha => {
3144                 self.shaders.borrow_mut().cs_scale_a8.bind(&mut self.device,
3145                                                            &projection,
3146                                                            &mut self.renderer_errors);
3147             }
3148             _ => unreachable!(),
3149         }
3150 
3151         self.draw_instanced_batch(
3152             &scalings,
3153             VertexArrayKind::Scale,
3154             &BatchTextures::no_texture(),
3155             stats,
3156         );
3157     }
3158 
draw_color_target( &mut self, draw_target: DrawTarget, target: &ColorRenderTarget, framebuffer_target_rect: DeviceIntRect, depth_is_ready: bool, clear_color: Option<[f32; 4]>, render_tasks: &RenderTaskTree, projection: &Transform3D<f32>, frame_id: GpuFrameId, stats: &mut RendererStats, )3159     fn draw_color_target(
3160         &mut self,
3161         draw_target: DrawTarget,
3162         target: &ColorRenderTarget,
3163         framebuffer_target_rect: DeviceIntRect,
3164         depth_is_ready: bool,
3165         clear_color: Option<[f32; 4]>,
3166         render_tasks: &RenderTaskTree,
3167         projection: &Transform3D<f32>,
3168         frame_id: GpuFrameId,
3169         stats: &mut RendererStats,
3170     ) {
3171         self.profile_counters.color_targets.inc();
3172         let _gm = self.gpu_profile.start_marker("color target");
3173 
3174         // sanity check for the depth buffer
3175         if let DrawTarget::Texture { texture, .. } = draw_target {
3176             assert!(texture.supports_depth() >= target.needs_depth());
3177         }
3178 
3179         let framebuffer_kind = if draw_target.is_default() {
3180             FramebufferKind::Main
3181         } else {
3182             FramebufferKind::Other
3183         };
3184 
3185         {
3186             let _timer = self.gpu_profile.start_timer(GPU_TAG_SETUP_TARGET);
3187             self.device.bind_draw_target(draw_target);
3188             self.device.disable_depth();
3189             self.set_blend(false, framebuffer_kind);
3190 
3191             let depth_clear = if !depth_is_ready && target.needs_depth() {
3192                 self.device.enable_depth_write();
3193                 Some(1.0)
3194             } else {
3195                 None
3196             };
3197 
3198             let clear_rect = if !draw_target.is_default() {
3199                 if self.enable_clear_scissor {
3200                     // TODO(gw): Applying a scissor rect and minimal clear here
3201                     // is a very large performance win on the Intel and nVidia
3202                     // GPUs that I have tested with. It's possible it may be a
3203                     // performance penalty on other GPU types - we should test this
3204                     // and consider different code paths.
3205                     //
3206                     // Note: The above measurements were taken when render
3207                     // target slices were minimum 2048x2048. Now that we size
3208                     // them adaptively, this may be less of a win (except perhaps
3209                     // on a mostly-unused last slice of a large texture array).
3210                     Some(target.used_rect())
3211                 } else {
3212                     None
3213                 }
3214             } else if framebuffer_target_rect == DeviceIntRect::new(DeviceIntPoint::zero(), draw_target.dimensions()) {
3215                 // whole screen is covered, no need for scissor
3216                 None
3217             } else {
3218                 let mut rect = framebuffer_target_rect.to_i32();
3219                 // Note: `framebuffer_target_rect` needs a Y-flip before going to GL
3220                 // Note: at this point, the target rectangle is not guaranteed to be within the main framebuffer bounds
3221                 // but `clear_target_rect` is totally fine with negative origin, as long as width & height are positive
3222                 rect.origin.y = draw_target.dimensions().height as i32 - rect.origin.y - rect.size.height;
3223                 Some(rect)
3224             };
3225 
3226             self.device.clear_target(clear_color, depth_clear, clear_rect);
3227 
3228             if depth_clear.is_some() {
3229                 self.device.disable_depth_write();
3230             }
3231         }
3232 
3233         // Handle any blits from the texture cache to this target.
3234         self.handle_blits(&target.blits, render_tasks);
3235 
3236         // Draw any blurs for this target.
3237         // Blurs are rendered as a standard 2-pass
3238         // separable implementation.
3239         // TODO(gw): In the future, consider having
3240         //           fast path blur shaders for common
3241         //           blur radii with fixed weights.
3242         if !target.vertical_blurs.is_empty() || !target.horizontal_blurs.is_empty() {
3243             let _timer = self.gpu_profile.start_timer(GPU_TAG_BLUR);
3244 
3245             self.set_blend(false, framebuffer_kind);
3246             self.shaders.borrow_mut().cs_blur_rgba8
3247                 .bind(&mut self.device, projection, &mut self.renderer_errors);
3248 
3249             if !target.vertical_blurs.is_empty() {
3250                 self.draw_instanced_batch(
3251                     &target.vertical_blurs,
3252                     VertexArrayKind::Blur,
3253                     &BatchTextures::no_texture(),
3254                     stats,
3255                 );
3256             }
3257 
3258             if !target.horizontal_blurs.is_empty() {
3259                 self.draw_instanced_batch(
3260                     &target.horizontal_blurs,
3261                     VertexArrayKind::Blur,
3262                     &BatchTextures::no_texture(),
3263                     stats,
3264                 );
3265             }
3266         }
3267 
3268         self.handle_scaling(&target.scalings, TextureSource::PrevPassColor, projection, stats);
3269 
3270         // Small helper fn to iterate a regions list, also invoking the closure
3271         // if there are no regions.
iterate_regions<F>( regions: &[DeviceIntRect], mut f: F, ) where F: FnMut(Option<DeviceIntRect>)3272         fn iterate_regions<F>(
3273             regions: &[DeviceIntRect],
3274             mut f: F,
3275         ) where F: FnMut(Option<DeviceIntRect>) {
3276             if regions.is_empty() {
3277                 f(None)
3278             } else {
3279                 for region in regions {
3280                     f(Some(*region))
3281                 }
3282             }
3283         }
3284 
3285         for alpha_batch_container in &target.alpha_batch_containers {
3286             let uses_scissor = alpha_batch_container.task_scissor_rect.is_some() ||
3287                                !alpha_batch_container.regions.is_empty();
3288 
3289             if uses_scissor {
3290                 self.device.enable_scissor();
3291                 let scissor_rect = draw_target.build_scissor_rect(
3292                     alpha_batch_container.task_scissor_rect,
3293                     framebuffer_target_rect,
3294                 );
3295                 self.device.set_scissor_rect(scissor_rect)
3296             }
3297 
3298             if !alpha_batch_container.opaque_batches.is_empty() {
3299                 let _gl = self.gpu_profile.start_marker("opaque batches");
3300                 let opaque_sampler = self.gpu_profile.start_sampler(GPU_SAMPLER_TAG_OPAQUE);
3301                 self.set_blend(false, framebuffer_kind);
3302                 //Note: depth equality is needed for split planes
3303                 self.device.set_depth_func(DepthFunction::LessEqual);
3304                 self.device.enable_depth();
3305                 self.device.enable_depth_write();
3306 
3307                 // Draw opaque batches front-to-back for maximum
3308                 // z-buffer efficiency!
3309                 for batch in alpha_batch_container
3310                     .opaque_batches
3311                     .iter()
3312                     .rev()
3313                 {
3314                     self.shaders.borrow_mut()
3315                         .get(&batch.key, self.debug_flags)
3316                         .bind(
3317                             &mut self.device, projection,
3318                             &mut self.renderer_errors,
3319                         );
3320 
3321                     let _timer = self.gpu_profile.start_timer(batch.key.kind.sampler_tag());
3322 
3323                     iterate_regions(
3324                         &alpha_batch_container.regions,
3325                         |region| {
3326                             if let Some(region) = region {
3327                                 let scissor_rect = draw_target.build_scissor_rect(
3328                                     Some(region),
3329                                     framebuffer_target_rect,
3330                                 );
3331                                 self.device.set_scissor_rect(scissor_rect);
3332                             }
3333 
3334                             self.draw_instanced_batch(
3335                                 &batch.instances,
3336                                 VertexArrayKind::Primitive,
3337                                 &batch.key.textures,
3338                                 stats
3339                             );
3340                         }
3341                     );
3342                 }
3343 
3344                 self.device.disable_depth_write();
3345                 self.gpu_profile.finish_sampler(opaque_sampler);
3346             }
3347 
3348             if !alpha_batch_container.alpha_batches.is_empty() {
3349                 let _gl = self.gpu_profile.start_marker("alpha batches");
3350                 let transparent_sampler = self.gpu_profile.start_sampler(GPU_SAMPLER_TAG_TRANSPARENT);
3351                 self.set_blend(true, framebuffer_kind);
3352                 let mut prev_blend_mode = BlendMode::None;
3353 
3354                 for batch in &alpha_batch_container.alpha_batches {
3355                     self.shaders.borrow_mut()
3356                         .get(&batch.key, self.debug_flags)
3357                         .bind(
3358                             &mut self.device, projection,
3359                             &mut self.renderer_errors,
3360                         );
3361 
3362                     if batch.key.blend_mode != prev_blend_mode {
3363                         match batch.key.blend_mode {
3364                             _ if self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) &&
3365                                     framebuffer_kind == FramebufferKind::Main => {
3366                                 self.device.set_blend_mode_show_overdraw();
3367                             }
3368                             BlendMode::None => {
3369                                 unreachable!("bug: opaque blend in alpha pass");
3370                             }
3371                             BlendMode::Alpha => {
3372                                 self.device.set_blend_mode_alpha();
3373                             }
3374                             BlendMode::PremultipliedAlpha => {
3375                                 self.device.set_blend_mode_premultiplied_alpha();
3376                             }
3377                             BlendMode::PremultipliedDestOut => {
3378                                 self.device.set_blend_mode_premultiplied_dest_out();
3379                             }
3380                             BlendMode::SubpixelDualSource => {
3381                                 self.device.set_blend_mode_subpixel_dual_source();
3382                             }
3383                             BlendMode::SubpixelConstantTextColor(color) => {
3384                                 self.device.set_blend_mode_subpixel_constant_text_color(color);
3385                             }
3386                             BlendMode::SubpixelWithBgColor => {
3387                                 // Using the three pass "component alpha with font smoothing
3388                                 // background color" rendering technique:
3389                                 //
3390                                 // /webrender/doc/text-rendering.md
3391                                 //
3392                                 self.device.set_blend_mode_subpixel_with_bg_color_pass0();
3393                                 self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass0 as _);
3394                             }
3395                         }
3396                         prev_blend_mode = batch.key.blend_mode;
3397                     }
3398 
3399                     // Handle special case readback for composites.
3400                     if let BatchKind::Brush(BrushBatchKind::MixBlend { task_id, source_id, backdrop_id }) = batch.key.kind {
3401                         // composites can't be grouped together because
3402                         // they may overlap and affect each other.
3403                         debug_assert_eq!(batch.instances.len(), 1);
3404                         self.handle_readback_composite(
3405                             draw_target,
3406                             uses_scissor,
3407                             &render_tasks[source_id],
3408                             &render_tasks[task_id],
3409                             &render_tasks[backdrop_id],
3410                         );
3411                     }
3412 
3413                     let _timer = self.gpu_profile.start_timer(batch.key.kind.sampler_tag());
3414 
3415                     iterate_regions(
3416                         &alpha_batch_container.regions,
3417                         |region| {
3418                             if let Some(region) = region {
3419                                 let scissor_rect = draw_target.build_scissor_rect(
3420                                     Some(region),
3421                                     framebuffer_target_rect,
3422                                 );
3423                                 self.device.set_scissor_rect(scissor_rect);
3424                             }
3425 
3426                             self.draw_instanced_batch(
3427                                 &batch.instances,
3428                                 VertexArrayKind::Primitive,
3429                                 &batch.key.textures,
3430                                 stats
3431                             );
3432 
3433                             if batch.key.blend_mode == BlendMode::SubpixelWithBgColor {
3434                                 self.set_blend_mode_subpixel_with_bg_color_pass1(framebuffer_kind);
3435                                 self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass1 as _);
3436 
3437                                 // When drawing the 2nd and 3rd passes, we know that the VAO, textures etc
3438                                 // are all set up from the previous draw_instanced_batch call,
3439                                 // so just issue a draw call here to avoid re-uploading the
3440                                 // instances and re-binding textures etc.
3441                                 self.device
3442                                     .draw_indexed_triangles_instanced_u16(6, batch.instances.len() as i32);
3443 
3444                                 self.set_blend_mode_subpixel_with_bg_color_pass2(framebuffer_kind);
3445                                 self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass2 as _);
3446 
3447                                 self.device
3448                                     .draw_indexed_triangles_instanced_u16(6, batch.instances.len() as i32);
3449                             }
3450                         }
3451                     );
3452 
3453                     if batch.key.blend_mode == BlendMode::SubpixelWithBgColor {
3454                         prev_blend_mode = BlendMode::None;
3455                     }
3456                 }
3457 
3458                 self.device.disable_depth();
3459                 self.set_blend(false, framebuffer_kind);
3460                 self.gpu_profile.finish_sampler(transparent_sampler);
3461             }
3462 
3463             if uses_scissor {
3464                 self.device.disable_scissor();
3465             }
3466 
3467             // At the end of rendering a container, blit across any cache tiles
3468             // to the texture cache for use on subsequent frames.
3469             if !alpha_batch_container.tile_blits.is_empty() {
3470                 let _timer = self.gpu_profile.start_timer(GPU_TAG_BLIT);
3471 
3472                 self.device.bind_read_target(draw_target.into());
3473 
3474                 for blit in &alpha_batch_container.tile_blits {
3475                     let texture = self.texture_resolver
3476                         .resolve(&blit.target.texture_id)
3477                         .expect("BUG: invalid target texture");
3478 
3479                     self.device.bind_draw_target(DrawTarget::Texture {
3480                         texture,
3481                         layer: blit.target.texture_layer as usize,
3482                         with_depth: false,
3483                     });
3484 
3485                     let mut src_rect = DeviceIntRect::new(
3486                         blit.src_offset,
3487                         blit.size,
3488                     );
3489 
3490                     let target_rect = blit.target.uv_rect.to_i32();
3491 
3492                     let mut dest_rect = DeviceIntRect::new(
3493                         DeviceIntPoint::new(
3494                             blit.dest_offset.x + target_rect.origin.x,
3495                             blit.dest_offset.y + target_rect.origin.y,
3496                         ),
3497                         blit.size,
3498                     );
3499 
3500                     // Modify the src/dest rects since we are blitting from the framebuffer
3501                     src_rect.origin.y = draw_target.dimensions().height as i32 - src_rect.size.height - src_rect.origin.y;
3502                     dest_rect.origin.y += dest_rect.size.height;
3503                     dest_rect.size.height = -dest_rect.size.height;
3504 
3505                     self.device.blit_render_target(
3506                         src_rect,
3507                         dest_rect,
3508                         TextureFilter::Linear,
3509                     );
3510                 }
3511 
3512                 self.device.bind_draw_target(draw_target);
3513             }
3514         }
3515 
3516         // For any registered image outputs on this render target,
3517         // get the texture from caller and blit it.
3518         for output in &target.outputs {
3519             let handler = self.output_image_handler
3520                 .as_mut()
3521                 .expect("Found output image, but no handler set!");
3522             if let Some((texture_id, output_size)) = handler.lock(output.pipeline_id) {
3523                 let fbo_id = match self.output_targets.entry(texture_id) {
3524                     Entry::Vacant(entry) => {
3525                         let fbo_id = self.device.create_fbo_for_external_texture(texture_id);
3526                         entry.insert(FrameOutput {
3527                             fbo_id,
3528                             last_access: frame_id,
3529                         });
3530                         fbo_id
3531                     }
3532                     Entry::Occupied(mut entry) => {
3533                         let target = entry.get_mut();
3534                         target.last_access = frame_id;
3535                         target.fbo_id
3536                     }
3537                 };
3538                 let (src_rect, _) = render_tasks[output.task_id].get_target_rect();
3539                 let mut dest_rect = DeviceIntRect::new(DeviceIntPoint::zero(), output_size);
3540 
3541                 // Invert Y coordinates, to correctly convert between coordinate systems.
3542                 dest_rect.origin.y += dest_rect.size.height;
3543                 dest_rect.size.height *= -1;
3544 
3545                 self.device.bind_read_target(draw_target.into());
3546                 self.device.bind_external_draw_target(fbo_id);
3547                 self.device.blit_render_target(src_rect, dest_rect, TextureFilter::Linear);
3548                 handler.unlock(output.pipeline_id);
3549             }
3550         }
3551     }
3552 
draw_alpha_target( &mut self, draw_target: DrawTarget, target: &AlphaRenderTarget, projection: &Transform3D<f32>, render_tasks: &RenderTaskTree, stats: &mut RendererStats, )3553     fn draw_alpha_target(
3554         &mut self,
3555         draw_target: DrawTarget,
3556         target: &AlphaRenderTarget,
3557         projection: &Transform3D<f32>,
3558         render_tasks: &RenderTaskTree,
3559         stats: &mut RendererStats,
3560     ) {
3561         self.profile_counters.alpha_targets.inc();
3562         let _gm = self.gpu_profile.start_marker("alpha target");
3563         let alpha_sampler = self.gpu_profile.start_sampler(GPU_SAMPLER_TAG_ALPHA);
3564 
3565         {
3566             let _timer = self.gpu_profile.start_timer(GPU_TAG_SETUP_TARGET);
3567             self.device.bind_draw_target(draw_target);
3568             self.device.disable_depth();
3569             self.device.disable_depth_write();
3570 
3571             // TODO(gw): Applying a scissor rect and minimal clear here
3572             // is a very large performance win on the Intel and nVidia
3573             // GPUs that I have tested with. It's possible it may be a
3574             // performance penalty on other GPU types - we should test this
3575             // and consider different code paths.
3576             let clear_color = [1.0, 1.0, 1.0, 0.0];
3577             self.device.clear_target(
3578                 Some(clear_color),
3579                 None,
3580                 Some(target.used_rect()),
3581             );
3582 
3583             let zero_color = [0.0, 0.0, 0.0, 0.0];
3584             for &task_id in &target.zero_clears {
3585                 let (rect, _) = render_tasks[task_id].get_target_rect();
3586                 self.device.clear_target(
3587                     Some(zero_color),
3588                     None,
3589                     Some(rect),
3590                 );
3591             }
3592         }
3593 
3594         // Draw any blurs for this target.
3595         // Blurs are rendered as a standard 2-pass
3596         // separable implementation.
3597         // TODO(gw): In the future, consider having
3598         //           fast path blur shaders for common
3599         //           blur radii with fixed weights.
3600         if !target.vertical_blurs.is_empty() || !target.horizontal_blurs.is_empty() {
3601             let _timer = self.gpu_profile.start_timer(GPU_TAG_BLUR);
3602 
3603             self.set_blend(false, FramebufferKind::Other);
3604             self.shaders.borrow_mut().cs_blur_a8
3605                 .bind(&mut self.device, projection, &mut self.renderer_errors);
3606 
3607             if !target.vertical_blurs.is_empty() {
3608                 self.draw_instanced_batch(
3609                     &target.vertical_blurs,
3610                     VertexArrayKind::Blur,
3611                     &BatchTextures::no_texture(),
3612                     stats,
3613                 );
3614             }
3615 
3616             if !target.horizontal_blurs.is_empty() {
3617                 self.draw_instanced_batch(
3618                     &target.horizontal_blurs,
3619                     VertexArrayKind::Blur,
3620                     &BatchTextures::no_texture(),
3621                     stats,
3622                 );
3623             }
3624         }
3625 
3626         self.handle_scaling(&target.scalings, TextureSource::PrevPassAlpha, projection, stats);
3627 
3628         // Draw the clip items into the tiled alpha mask.
3629         {
3630             let _timer = self.gpu_profile.start_timer(GPU_TAG_CACHE_CLIP);
3631 
3632             // switch to multiplicative blending
3633             self.set_blend(true, FramebufferKind::Other);
3634             self.set_blend_mode_multiply(FramebufferKind::Other);
3635 
3636             // draw rounded cornered rectangles
3637             if !target.clip_batcher.rectangles.is_empty() {
3638                 let _gm2 = self.gpu_profile.start_marker("clip rectangles");
3639                 self.shaders.borrow_mut().cs_clip_rectangle.bind(
3640                     &mut self.device,
3641                     projection,
3642                     &mut self.renderer_errors,
3643                 );
3644                 self.draw_instanced_batch(
3645                     &target.clip_batcher.rectangles,
3646                     VertexArrayKind::Clip,
3647                     &BatchTextures::no_texture(),
3648                     stats,
3649                 );
3650             }
3651             // draw box-shadow clips
3652             for (mask_texture_id, items) in target.clip_batcher.box_shadows.iter() {
3653                 let _gm2 = self.gpu_profile.start_marker("box-shadows");
3654                 let textures = BatchTextures {
3655                     colors: [
3656                         mask_texture_id.clone(),
3657                         TextureSource::Invalid,
3658                         TextureSource::Invalid,
3659                     ],
3660                 };
3661                 self.shaders.borrow_mut().cs_clip_box_shadow
3662                     .bind(&mut self.device, projection, &mut self.renderer_errors);
3663                 self.draw_instanced_batch(
3664                     items,
3665                     VertexArrayKind::Clip,
3666                     &textures,
3667                     stats,
3668                 );
3669             }
3670 
3671             // draw image masks
3672             for (mask_texture_id, items) in target.clip_batcher.images.iter() {
3673                 let _gm2 = self.gpu_profile.start_marker("clip images");
3674                 let textures = BatchTextures {
3675                     colors: [
3676                         mask_texture_id.clone(),
3677                         TextureSource::Invalid,
3678                         TextureSource::Invalid,
3679                     ],
3680                 };
3681                 self.shaders.borrow_mut().cs_clip_image
3682                     .bind(&mut self.device, projection, &mut self.renderer_errors);
3683                 self.draw_instanced_batch(
3684                     items,
3685                     VertexArrayKind::Clip,
3686                     &textures,
3687                     stats,
3688                 );
3689             }
3690         }
3691 
3692         self.gpu_profile.finish_sampler(alpha_sampler);
3693     }
3694 
draw_texture_cache_target( &mut self, texture: &CacheTextureId, layer: LayerIndex, target: &TextureCacheRenderTarget, render_tasks: &RenderTaskTree, stats: &mut RendererStats, )3695     fn draw_texture_cache_target(
3696         &mut self,
3697         texture: &CacheTextureId,
3698         layer: LayerIndex,
3699         target: &TextureCacheRenderTarget,
3700         render_tasks: &RenderTaskTree,
3701         stats: &mut RendererStats,
3702     ) {
3703         let texture_source = TextureSource::TextureCache(*texture);
3704         let (target_size, projection) = {
3705             let texture = self.texture_resolver
3706                 .resolve(&texture_source)
3707                 .expect("BUG: invalid target texture");
3708             let target_size = texture.get_dimensions();
3709             let projection = Transform3D::ortho(
3710                 0.0,
3711                 target_size.width as f32,
3712                 0.0,
3713                 target_size.height as f32,
3714                 ORTHO_NEAR_PLANE,
3715                 ORTHO_FAR_PLANE,
3716             );
3717             (target_size, projection)
3718         };
3719 
3720         self.device.disable_depth();
3721         self.device.disable_depth_write();
3722 
3723         self.set_blend(false, FramebufferKind::Other);
3724 
3725         // Handle any Pathfinder glyphs.
3726         let stencil_page = self.stencil_glyphs(&target.glyphs, &projection, &target_size, stats);
3727 
3728         {
3729             let texture = self.texture_resolver
3730                 .resolve(&texture_source)
3731                 .expect("BUG: invalid target texture");
3732             self.device.bind_draw_target(DrawTarget::Texture {
3733                 texture,
3734                 layer,
3735                 with_depth: false,
3736             });
3737         }
3738 
3739         self.device.disable_depth();
3740         self.device.disable_depth_write();
3741         self.set_blend(false, FramebufferKind::Other);
3742 
3743         for rect in &target.clears {
3744             self.device.clear_target(Some([0.0, 0.0, 0.0, 0.0]), None, Some(*rect));
3745         }
3746 
3747         // Handle any blits to this texture from child tasks.
3748         self.handle_blits(&target.blits, render_tasks);
3749 
3750         // Draw any borders for this target.
3751         if !target.border_segments_solid.is_empty() ||
3752            !target.border_segments_complex.is_empty()
3753         {
3754             let _timer = self.gpu_profile.start_timer(GPU_TAG_CACHE_BORDER);
3755 
3756             self.set_blend(true, FramebufferKind::Other);
3757             self.set_blend_mode_premultiplied_alpha(FramebufferKind::Other);
3758 
3759             if !target.border_segments_solid.is_empty() {
3760                 self.shaders.borrow_mut().cs_border_solid.bind(
3761                     &mut self.device,
3762                     &projection,
3763                     &mut self.renderer_errors,
3764                 );
3765 
3766                 self.draw_instanced_batch(
3767                     &target.border_segments_solid,
3768                     VertexArrayKind::Border,
3769                     &BatchTextures::no_texture(),
3770                     stats,
3771                 );
3772             }
3773 
3774             if !target.border_segments_complex.is_empty() {
3775                 self.shaders.borrow_mut().cs_border_segment.bind(
3776                     &mut self.device,
3777                     &projection,
3778                     &mut self.renderer_errors,
3779                 );
3780 
3781                 self.draw_instanced_batch(
3782                     &target.border_segments_complex,
3783                     VertexArrayKind::Border,
3784                     &BatchTextures::no_texture(),
3785                     stats,
3786                 );
3787             }
3788 
3789             self.set_blend(false, FramebufferKind::Other);
3790         }
3791 
3792         // Draw any line decorations for this target.
3793         if !target.line_decorations.is_empty() {
3794             let _timer = self.gpu_profile.start_timer(GPU_TAG_CACHE_LINE_DECORATION);
3795 
3796             self.set_blend(true, FramebufferKind::Other);
3797             self.set_blend_mode_premultiplied_alpha(FramebufferKind::Other);
3798 
3799             if !target.line_decorations.is_empty() {
3800                 self.shaders.borrow_mut().cs_line_decoration.bind(
3801                     &mut self.device,
3802                     &projection,
3803                     &mut self.renderer_errors,
3804                 );
3805 
3806                 self.draw_instanced_batch(
3807                     &target.line_decorations,
3808                     VertexArrayKind::LineDecoration,
3809                     &BatchTextures::no_texture(),
3810                     stats,
3811                 );
3812             }
3813 
3814             self.set_blend(false, FramebufferKind::Other);
3815         }
3816 
3817         // Draw any blurs for this target.
3818         if !target.horizontal_blurs.is_empty() {
3819             let _timer = self.gpu_profile.start_timer(GPU_TAG_BLUR);
3820 
3821             {
3822                 let mut shaders = self.shaders.borrow_mut();
3823                 match target.target_kind {
3824                     RenderTargetKind::Alpha => &mut shaders.cs_blur_a8,
3825                     RenderTargetKind::Color => &mut shaders.cs_blur_rgba8,
3826                 }.bind(&mut self.device, &projection, &mut self.renderer_errors);
3827             }
3828 
3829             self.draw_instanced_batch(
3830                 &target.horizontal_blurs,
3831                 VertexArrayKind::Blur,
3832                 &BatchTextures::no_texture(),
3833                 stats,
3834             );
3835         }
3836 
3837         // Blit any Pathfinder glyphs to the cache texture.
3838         if let Some(stencil_page) = stencil_page {
3839             self.cover_glyphs(stencil_page, &projection, stats);
3840         }
3841     }
3842 
3843     #[cfg(not(feature = "pathfinder"))]
stencil_glyphs(&mut self, _: &[GlyphJob], _: &Transform3D<f32>, _: &DeviceIntSize, _: &mut RendererStats) -> Option<StenciledGlyphPage>3844     fn stencil_glyphs(&mut self,
3845                       _: &[GlyphJob],
3846                       _: &Transform3D<f32>,
3847                       _: &DeviceIntSize,
3848                       _: &mut RendererStats)
3849                       -> Option<StenciledGlyphPage> {
3850         None
3851     }
3852 
3853     #[cfg(not(feature = "pathfinder"))]
cover_glyphs(&mut self, _: StenciledGlyphPage, _: &Transform3D<f32>, _: &mut RendererStats)3854     fn cover_glyphs(&mut self,
3855                     _: StenciledGlyphPage,
3856                     _: &Transform3D<f32>,
3857                     _: &mut RendererStats) {}
3858 
update_deferred_resolves(&mut self, deferred_resolves: &[DeferredResolve]) -> Option<GpuCacheUpdateList>3859     fn update_deferred_resolves(&mut self, deferred_resolves: &[DeferredResolve]) -> Option<GpuCacheUpdateList> {
3860         // The first thing we do is run through any pending deferred
3861         // resolves, and use a callback to get the UV rect for this
3862         // custom item. Then we patch the resource_rects structure
3863         // here before it's uploaded to the GPU.
3864         if deferred_resolves.is_empty() {
3865             return None;
3866         }
3867 
3868         let handler = self.external_image_handler
3869             .as_mut()
3870             .expect("Found external image, but no handler set!");
3871 
3872         let mut list = GpuCacheUpdateList {
3873             frame_id: FrameId::INVALID,
3874             clear: false,
3875             height: self.gpu_cache_texture.get_height(),
3876             blocks: Vec::new(),
3877             updates: Vec::new(),
3878             debug_commands: Vec::new(),
3879         };
3880 
3881         for deferred_resolve in deferred_resolves {
3882             self.gpu_profile.place_marker("deferred resolve");
3883             let props = &deferred_resolve.image_properties;
3884             let ext_image = props
3885                 .external_image
3886                 .expect("BUG: Deferred resolves must be external images!");
3887             // Provide rendering information for NativeTexture external images.
3888             let image = handler.lock(ext_image.id, ext_image.channel_index, deferred_resolve.rendering);
3889             let texture_target = match ext_image.image_type {
3890                 ExternalImageType::TextureHandle(target) => target,
3891                 ExternalImageType::Buffer => {
3892                     panic!("not a suitable image type in update_deferred_resolves()");
3893                 }
3894             };
3895 
3896             // In order to produce the handle, the external image handler may call into
3897             // the GL context and change some states.
3898             self.device.reset_state();
3899 
3900             let texture = match image.source {
3901                 ExternalImageSource::NativeTexture(texture_id) => {
3902                     ExternalTexture::new(texture_id, texture_target)
3903                 }
3904                 ExternalImageSource::Invalid => {
3905                     warn!("Invalid ext-image");
3906                     debug!(
3907                         "For ext_id:{:?}, channel:{}.",
3908                         ext_image.id,
3909                         ext_image.channel_index
3910                     );
3911                     // Just use 0 as the gl handle for this failed case.
3912                     ExternalTexture::new(0, texture_target)
3913                 }
3914                 ExternalImageSource::RawData(_) => {
3915                     panic!("Raw external data is not expected for deferred resolves!");
3916                 }
3917             };
3918 
3919             self.texture_resolver
3920                 .external_images
3921                 .insert((ext_image.id, ext_image.channel_index), texture);
3922 
3923             list.updates.push(GpuCacheUpdate::Copy {
3924                 block_index: list.blocks.len(),
3925                 block_count: BLOCKS_PER_UV_RECT,
3926                 address: deferred_resolve.address,
3927             });
3928             list.blocks.push(image.uv.into());
3929             list.blocks.push([0f32; 4].into());
3930         }
3931 
3932         Some(list)
3933     }
3934 
unlock_external_images(&mut self)3935     fn unlock_external_images(&mut self) {
3936         if !self.texture_resolver.external_images.is_empty() {
3937             let handler = self.external_image_handler
3938                 .as_mut()
3939                 .expect("Found external image, but no handler set!");
3940 
3941             for (ext_data, _) in self.texture_resolver.external_images.drain() {
3942                 handler.unlock(ext_data.0, ext_data.1);
3943             }
3944         }
3945     }
3946 
3947     /// Allocates a texture to be used as the output for a rendering pass.
3948     ///
3949     /// We make an effort to reuse render targe textures across passes and
3950     /// across frames when the format and dimensions match. Because we use
3951     /// immutable storage, we can't resize textures.
3952     ///
3953     /// We could consider approaches to re-use part of a larger target, if
3954     /// available. However, we'd need to be careful about eviction. Currently,
3955     /// render targets are freed if they haven't been used in 30 frames. If we
3956     /// used partial targets, we'd need to track how _much_ of the target has
3957     /// been used in the last 30 frames, since we could otherwise end up
3958     /// keeping an enormous target alive indefinitely by constantly using it
3959     /// in situations where a much smaller target would suffice.
allocate_target_texture<T: RenderTarget>( &mut self, list: &mut RenderTargetList<T>, counters: &mut FrameProfileCounters, ) -> Option<ActiveTexture>3960     fn allocate_target_texture<T: RenderTarget>(
3961         &mut self,
3962         list: &mut RenderTargetList<T>,
3963         counters: &mut FrameProfileCounters,
3964     ) -> Option<ActiveTexture> {
3965         if list.targets.is_empty() {
3966             return None
3967         }
3968 
3969         // Get a bounding rect of all the layers, and round it up to a multiple
3970         // of 256. This improves render target reuse when resizing the window,
3971         // since we don't need to create a new render target for each slightly-
3972         // larger frame.
3973         let mut bounding_rect = DeviceIntRect::zero();
3974         for t in list.targets.iter() {
3975             bounding_rect = t.used_rect().union(&bounding_rect);
3976         }
3977         debug_assert_eq!(bounding_rect.origin, DeviceIntPoint::zero());
3978         let dimensions = DeviceIntSize::new(
3979             (bounding_rect.size.width + 255) & !255,
3980             (bounding_rect.size.height + 255) & !255,
3981         );
3982 
3983         counters.targets_used.inc();
3984 
3985         // Try finding a match in the existing pool. If there's no match, we'll
3986         // create a new texture.
3987         let selector = TargetSelector {
3988             size: dimensions,
3989             num_layers: list.targets.len(),
3990             format: list.format,
3991         };
3992         let index = self.texture_resolver.render_target_pool
3993             .iter()
3994             .position(|texture| {
3995                 selector == TargetSelector {
3996                     size: texture.get_dimensions(),
3997                     num_layers: texture.get_layer_count() as usize,
3998                     format: texture.get_format(),
3999                 }
4000             });
4001 
4002         let rt_info = RenderTargetInfo { has_depth: list.needs_depth() };
4003         let texture = if let Some(idx) = index {
4004             let mut t = self.texture_resolver.render_target_pool.swap_remove(idx);
4005             self.device.reuse_render_target::<u8>(&mut t, rt_info);
4006             t
4007         } else {
4008             counters.targets_created.inc();
4009             self.device.create_texture(
4010                 TextureTarget::Array,
4011                 list.format,
4012                 dimensions.width,
4013                 dimensions.height,
4014                 TextureFilter::Linear,
4015                 Some(rt_info),
4016                 list.targets.len() as _,
4017             )
4018         };
4019 
4020         list.check_ready(&texture);
4021         Some(ActiveTexture {
4022             texture,
4023             saved_index: list.saved_index.clone(),
4024         })
4025     }
4026 
bind_frame_data(&mut self, frame: &mut Frame)4027     fn bind_frame_data(&mut self, frame: &mut Frame) {
4028         let _timer = self.gpu_profile.start_timer(GPU_TAG_SETUP_DATA);
4029         self.device.set_device_pixel_ratio(frame.device_pixel_ratio);
4030 
4031         self.prim_header_f_texture.update(
4032             &mut self.device,
4033             &mut frame.prim_headers.headers_float,
4034         );
4035         self.device.bind_texture(
4036             TextureSampler::PrimitiveHeadersF,
4037             &self.prim_header_f_texture.texture(),
4038         );
4039 
4040         self.prim_header_i_texture.update(
4041             &mut self.device,
4042             &mut frame.prim_headers.headers_int,
4043         );
4044         self.device.bind_texture(
4045             TextureSampler::PrimitiveHeadersI,
4046             &self.prim_header_i_texture.texture(),
4047         );
4048 
4049         self.transforms_texture.update(
4050             &mut self.device,
4051             &mut frame.transform_palette,
4052         );
4053         self.device.bind_texture(
4054             TextureSampler::TransformPalette,
4055             &self.transforms_texture.texture(),
4056         );
4057 
4058         self.render_task_texture
4059             .update(&mut self.device, &mut frame.render_tasks.task_data);
4060         self.device.bind_texture(
4061             TextureSampler::RenderTasks,
4062             &self.render_task_texture.texture(),
4063         );
4064 
4065         debug_assert!(self.texture_resolver.prev_pass_alpha.is_none());
4066         debug_assert!(self.texture_resolver.prev_pass_color.is_none());
4067     }
4068 
draw_tile_frame( &mut self, frame: &mut Frame, framebuffer_size: Option<DeviceIntSize>, framebuffer_depth_is_ready: bool, frame_id: GpuFrameId, stats: &mut RendererStats, )4069     fn draw_tile_frame(
4070         &mut self,
4071         frame: &mut Frame,
4072         framebuffer_size: Option<DeviceIntSize>,
4073         framebuffer_depth_is_ready: bool,
4074         frame_id: GpuFrameId,
4075         stats: &mut RendererStats,
4076     ) {
4077         let _gm = self.gpu_profile.start_marker("tile frame draw");
4078 
4079         if frame.passes.is_empty() {
4080             frame.has_been_rendered = true;
4081             return;
4082         }
4083 
4084         self.device.disable_depth_write();
4085         self.set_blend(false, FramebufferKind::Other);
4086         self.device.disable_stencil();
4087 
4088         self.bind_frame_data(frame);
4089         self.texture_resolver.begin_frame();
4090 
4091         for (pass_index, pass) in frame.passes.iter_mut().enumerate() {
4092             let _gm = self.gpu_profile.start_marker(&format!("pass {}", pass_index));
4093 
4094             self.texture_resolver.bind(
4095                 &TextureSource::PrevPassAlpha,
4096                 TextureSampler::PrevPassAlpha,
4097                 &mut self.device,
4098             );
4099             self.texture_resolver.bind(
4100                 &TextureSource::PrevPassColor,
4101                 TextureSampler::PrevPassColor,
4102                 &mut self.device,
4103             );
4104 
4105             let (cur_alpha, cur_color) = match pass.kind {
4106                 RenderPassKind::MainFramebuffer(ref target) => {
4107                     if let Some(framebuffer_size) = framebuffer_size {
4108                         stats.color_target_count += 1;
4109 
4110                         let clear_color = frame.background_color.map(|color| color.to_array());
4111                         let projection = Transform3D::ortho(
4112                             0.0,
4113                             framebuffer_size.width as f32,
4114                             framebuffer_size.height as f32,
4115                             0.0,
4116                             ORTHO_NEAR_PLANE,
4117                             ORTHO_FAR_PLANE,
4118                         );
4119 
4120                         self.draw_color_target(
4121                             DrawTarget::Default(framebuffer_size),
4122                             target,
4123                             frame.inner_rect,
4124                             framebuffer_depth_is_ready,
4125                             clear_color,
4126                             &frame.render_tasks,
4127                             &projection,
4128                             frame_id,
4129                             stats,
4130                         );
4131                     }
4132 
4133                     (None, None)
4134                 }
4135                 RenderPassKind::OffScreen { ref mut alpha, ref mut color, ref mut texture_cache } => {
4136                     let alpha_tex = self.allocate_target_texture(alpha, &mut frame.profile_counters);
4137                     let color_tex = self.allocate_target_texture(color, &mut frame.profile_counters);
4138 
4139                     // If this frame has already been drawn, then any texture
4140                     // cache targets have already been updated and can be
4141                     // skipped this time.
4142                     if !frame.has_been_rendered {
4143                         for (&(texture_id, target_index), target) in texture_cache {
4144                             self.draw_texture_cache_target(
4145                                 &texture_id,
4146                                 target_index,
4147                                 target,
4148                                 &frame.render_tasks,
4149                                 stats,
4150                             );
4151                         }
4152                     }
4153 
4154                     for (target_index, target) in alpha.targets.iter().enumerate() {
4155                         stats.alpha_target_count += 1;
4156                         let draw_target = DrawTarget::Texture {
4157                             texture: &alpha_tex.as_ref().unwrap().texture,
4158                             layer: target_index,
4159                             with_depth: false,
4160                         };
4161 
4162                         let projection = Transform3D::ortho(
4163                             0.0,
4164                             draw_target.dimensions().width as f32,
4165                             0.0,
4166                             draw_target.dimensions().height as f32,
4167                             ORTHO_NEAR_PLANE,
4168                             ORTHO_FAR_PLANE,
4169                         );
4170 
4171                         self.draw_alpha_target(
4172                             draw_target,
4173                             target,
4174                             &projection,
4175                             &frame.render_tasks,
4176                             stats,
4177                         );
4178                     }
4179 
4180                     for (target_index, target) in color.targets.iter().enumerate() {
4181                         stats.color_target_count += 1;
4182                         let draw_target = DrawTarget::Texture {
4183                             texture: &color_tex.as_ref().unwrap().texture,
4184                             layer: target_index,
4185                             with_depth: target.needs_depth(),
4186                         };
4187 
4188                         let projection = Transform3D::ortho(
4189                             0.0,
4190                             draw_target.dimensions().width as f32,
4191                             0.0,
4192                             draw_target.dimensions().height as f32,
4193                             ORTHO_NEAR_PLANE,
4194                             ORTHO_FAR_PLANE,
4195                         );
4196 
4197                         self.draw_color_target(
4198                             draw_target,
4199                             target,
4200                             frame.inner_rect,
4201                             false,
4202                             Some([0.0, 0.0, 0.0, 0.0]),
4203                             &frame.render_tasks,
4204                             &projection,
4205                             frame_id,
4206                             stats,
4207                         );
4208                     }
4209 
4210                     (alpha_tex, color_tex)
4211                 }
4212             };
4213 
4214             self.texture_resolver.end_pass(
4215                 &mut self.device,
4216                 cur_alpha,
4217                 cur_color,
4218             );
4219         }
4220 
4221         self.texture_resolver.end_frame(&mut self.device, frame_id);
4222 
4223         if let Some(framebuffer_size) = framebuffer_size {
4224             self.draw_frame_debug_items(&frame.debug_items);
4225             self.draw_render_target_debug(framebuffer_size);
4226             self.draw_texture_cache_debug(framebuffer_size);
4227             self.draw_gpu_cache_debug(framebuffer_size);
4228             self.draw_zoom_debug(framebuffer_size);
4229         }
4230         self.draw_epoch_debug();
4231 
4232         // Garbage collect any frame outputs that weren't used this frame.
4233         let device = &mut self.device;
4234         self.output_targets
4235             .retain(|_, target| if target.last_access != frame_id {
4236                 device.delete_fbo(target.fbo_id);
4237                 false
4238             } else {
4239                 true
4240             });
4241 
4242         frame.has_been_rendered = true;
4243     }
4244 
debug_renderer<'b>(&'b mut self) -> Option<&'b mut DebugRenderer>4245     pub fn debug_renderer<'b>(&'b mut self) -> Option<&'b mut DebugRenderer> {
4246         self.debug.get_mut(&mut self.device)
4247     }
4248 
get_debug_flags(&self) -> DebugFlags4249     pub fn get_debug_flags(&self) -> DebugFlags {
4250         self.debug_flags
4251     }
4252 
set_debug_flags(&mut self, flags: DebugFlags)4253     pub fn set_debug_flags(&mut self, flags: DebugFlags) {
4254         if let Some(enabled) = flag_changed(self.debug_flags, flags, DebugFlags::GPU_TIME_QUERIES) {
4255             if enabled {
4256                 self.gpu_profile.enable_timers();
4257             } else {
4258                 self.gpu_profile.disable_timers();
4259             }
4260         }
4261         if let Some(enabled) = flag_changed(self.debug_flags, flags, DebugFlags::GPU_SAMPLE_QUERIES) {
4262             if enabled {
4263                 self.gpu_profile.enable_samplers();
4264             } else {
4265                 self.gpu_profile.disable_samplers();
4266             }
4267         }
4268 
4269         self.debug_flags = flags;
4270     }
4271 
save_cpu_profile(&self, filename: &str)4272     pub fn save_cpu_profile(&self, filename: &str) {
4273         write_profile(filename);
4274     }
4275 
draw_frame_debug_items(&mut self, items: &[DebugItem])4276     fn draw_frame_debug_items(&mut self, items: &[DebugItem]) {
4277         let debug_renderer = match self.debug.get_mut(&mut self.device) {
4278             Some(render) => render,
4279             None => return,
4280         };
4281 
4282         for item in items {
4283             match item {
4284                 DebugItem::Rect { rect, color } => {
4285                     let inner_color = color.scale_alpha(0.5).into();
4286                     let outer_color = (*color).into();
4287 
4288                     debug_renderer.add_quad(
4289                         rect.origin.x,
4290                         rect.origin.y,
4291                         rect.origin.x + rect.size.width,
4292                         rect.origin.y + rect.size.height,
4293                         inner_color,
4294                         inner_color,
4295                     );
4296 
4297                     debug_renderer.add_rect(
4298                         &rect.to_i32(),
4299                         outer_color,
4300                     );
4301                 }
4302                 DebugItem::Text { ref msg, position, color } => {
4303                     debug_renderer.add_text(
4304                         position.x,
4305                         position.y,
4306                         msg,
4307                         (*color).into(),
4308                         None,
4309                     );
4310                 }
4311             }
4312         }
4313     }
4314 
draw_render_target_debug(&mut self, framebuffer_size: DeviceIntSize)4315     fn draw_render_target_debug(&mut self, framebuffer_size: DeviceIntSize) {
4316         if !self.debug_flags.contains(DebugFlags::RENDER_TARGET_DBG) {
4317             return;
4318         }
4319 
4320         let debug_renderer = match self.debug.get_mut(&mut self.device) {
4321             Some(render) => render,
4322             None => return,
4323         };
4324 
4325         let textures =
4326             self.texture_resolver.render_target_pool.iter().collect::<Vec<&Texture>>();
4327 
4328         Self::do_debug_blit(
4329             &mut self.device,
4330             debug_renderer,
4331             textures,
4332             framebuffer_size,
4333             0,
4334             &|_| [0.0, 1.0, 0.0, 1.0], // Use green for all RTs.
4335         );
4336     }
4337 
draw_zoom_debug( &mut self, framebuffer_size: DeviceIntSize, )4338     fn draw_zoom_debug(
4339         &mut self,
4340         framebuffer_size: DeviceIntSize,
4341     ) {
4342         if !self.debug_flags.contains(DebugFlags::ZOOM_DBG) {
4343             return;
4344         }
4345 
4346         let debug_renderer = match self.debug.get_mut(&mut self.device) {
4347             Some(render) => render,
4348             None => return,
4349         };
4350 
4351         let source_size = DeviceIntSize::new(64, 64);
4352         let target_size = DeviceIntSize::new(1024, 1024);
4353 
4354         let source_origin = DeviceIntPoint::new(
4355             (self.cursor_position.x - source_size.width / 2)
4356                 .min(framebuffer_size.width - source_size.width)
4357                 .max(0),
4358             (self.cursor_position.y - source_size.height / 2)
4359                 .min(framebuffer_size.height - source_size.height)
4360                 .max(0),
4361         );
4362 
4363         let source_rect = DeviceIntRect::new(
4364             source_origin,
4365             source_size,
4366         );
4367 
4368         let target_rect = DeviceIntRect::new(
4369             DeviceIntPoint::new(
4370                 framebuffer_size.width - target_size.width - 64,
4371                 framebuffer_size.height - target_size.height - 64,
4372             ),
4373             target_size,
4374         );
4375 
4376         let texture_rect = DeviceIntRect::new(
4377             DeviceIntPoint::zero(),
4378             source_rect.size,
4379         );
4380 
4381         debug_renderer.add_rect(
4382             &target_rect.inflate(1, 1),
4383             debug_colors::RED.into(),
4384         );
4385 
4386         if self.zoom_debug_texture.is_none() {
4387             let texture = self.device.create_texture(
4388                 TextureTarget::Default,
4389                 ImageFormat::BGRA8,
4390                 source_rect.size.width,
4391                 source_rect.size.height,
4392                 TextureFilter::Nearest,
4393                 Some(RenderTargetInfo { has_depth: false }),
4394                 1,
4395             );
4396 
4397             self.zoom_debug_texture = Some(texture);
4398         }
4399 
4400         // Copy frame buffer into the zoom texture
4401         self.device.bind_read_target(ReadTarget::Default);
4402         self.device.bind_draw_target(DrawTarget::Texture {
4403             texture: self.zoom_debug_texture.as_ref().unwrap(),
4404             layer: 0,
4405             with_depth: false,
4406         });
4407         self.device.blit_render_target(
4408             DeviceIntRect::new(
4409                 DeviceIntPoint::new(
4410                     source_rect.origin.x,
4411                     framebuffer_size.height - source_rect.size.height - source_rect.origin.y,
4412                 ),
4413                 source_rect.size,
4414             ),
4415             texture_rect,
4416             TextureFilter::Nearest,
4417         );
4418 
4419         // Draw the zoom texture back to the framebuffer
4420         self.device.bind_read_target(ReadTarget::Texture {
4421             texture: self.zoom_debug_texture.as_ref().unwrap(),
4422             layer: 0,
4423         });
4424         self.device.bind_draw_target(DrawTarget::Default(framebuffer_size));
4425         self.device.blit_render_target(
4426             texture_rect,
4427             DeviceIntRect::new(
4428                 DeviceIntPoint::new(
4429                     target_rect.origin.x,
4430                     framebuffer_size.height - target_rect.size.height - target_rect.origin.y,
4431                 ),
4432                 target_rect.size,
4433             ),
4434             TextureFilter::Nearest,
4435         );
4436     }
4437 
draw_texture_cache_debug(&mut self, framebuffer_size: DeviceIntSize)4438     fn draw_texture_cache_debug(&mut self, framebuffer_size: DeviceIntSize) {
4439         if !self.debug_flags.contains(DebugFlags::TEXTURE_CACHE_DBG) {
4440             return;
4441         }
4442 
4443         let debug_renderer = match self.debug.get_mut(&mut self.device) {
4444             Some(render) => render,
4445             None => return,
4446         };
4447 
4448         let textures =
4449             self.texture_resolver.texture_cache_map.values().collect::<Vec<&Texture>>();
4450 
4451         fn select_color(texture: &Texture) -> [f32; 4] {
4452             if texture.flags().contains(TextureFlags::IS_SHARED_TEXTURE_CACHE) {
4453                 [1.0, 0.5, 0.0, 1.0] // Orange for shared.
4454             } else {
4455                 [1.0, 0.0, 1.0, 1.0] // Fuchsia for standalone.
4456             }
4457         }
4458 
4459         Self::do_debug_blit(
4460             &mut self.device,
4461             debug_renderer,
4462             textures,
4463             framebuffer_size,
4464             if self.debug_flags.contains(DebugFlags::RENDER_TARGET_DBG) { 544 } else { 0 },
4465             &select_color,
4466         );
4467     }
4468 
do_debug_blit( device: &mut Device, debug_renderer: &mut DebugRenderer, mut textures: Vec<&Texture>, framebuffer_size: DeviceIntSize, bottom: i32, select_color: &Fn(&Texture) -> [f32; 4], )4469     fn do_debug_blit(
4470         device: &mut Device,
4471         debug_renderer: &mut DebugRenderer,
4472         mut textures: Vec<&Texture>,
4473         framebuffer_size: DeviceIntSize,
4474         bottom: i32,
4475         select_color: &Fn(&Texture) -> [f32; 4],
4476     ) {
4477         let mut spacing = 16;
4478         let mut size = 512;
4479 
4480         let fb_width = framebuffer_size.width as i32;
4481         let fb_height = framebuffer_size.height as i32;
4482         let num_layers: i32 = textures.iter()
4483             .map(|texture| texture.get_layer_count())
4484             .sum();
4485 
4486         if num_layers * (size + spacing) > fb_width {
4487             let factor = fb_width as f32 / (num_layers * (size + spacing)) as f32;
4488             size = (size as f32 * factor) as i32;
4489             spacing = (spacing as f32 * factor) as i32;
4490         }
4491 
4492         // Sort the display by layer size (in bytes), so that left-to-right is
4493         // largest-to-smallest.
4494         //
4495         // Note that the vec here is in increasing order, because the elements
4496         // get drawn right-to-left.
4497         textures.sort_by_key(|t| t.layer_size_in_bytes());
4498 
4499         let mut i = 0;
4500         for texture in textures.iter() {
4501             let y = spacing + bottom;
4502             let dimensions = texture.get_dimensions();
4503             let src_rect = DeviceIntRect::new(
4504                 DeviceIntPoint::zero(),
4505                 DeviceIntSize::new(dimensions.width as i32, dimensions.height as i32),
4506             );
4507 
4508             let layer_count = texture.get_layer_count() as usize;
4509             for layer in 0 .. layer_count {
4510                 device.bind_read_target(ReadTarget::Texture { texture, layer});
4511 
4512                 let x = fb_width - (spacing + size) * (i as i32 + 1);
4513 
4514                 // If we have more targets than fit on one row in screen, just early exit.
4515                 if x > fb_width {
4516                     return;
4517                 }
4518 
4519                 // Draw the info tag.
4520                 let text_margin = 1;
4521                 let text_height = 14; // Visually aproximated.
4522                 let tag_height = text_height + text_margin * 2;
4523                 let tag_rect = rect(x, y, size, tag_height);
4524                 let tag_color = select_color(texture);
4525                 device.clear_target(Some(tag_color), None, Some(tag_rect));
4526 
4527                 // Draw the dimensions onto the tag.
4528                 let dim = texture.get_dimensions();
4529                 let mut text_rect = tag_rect;
4530                 text_rect.origin.y =
4531                     fb_height - text_rect.origin.y - text_rect.size.height; // Top-relative.
4532                 debug_renderer.add_text(
4533                     (x + text_margin) as f32,
4534                     (fb_height - y - text_margin) as f32, // Top-relative.
4535                     &format!("{}x{}", dim.width, dim.height),
4536                     ColorU::new(0, 0, 0, 255),
4537                     Some(text_rect.to_f32())
4538                 );
4539 
4540                 // Blit the contents of the layer. We need to invert Y because
4541                 // we're blitting from a texture to the main framebuffer, which
4542                 // use different conventions.
4543                 let dest_rect = rect(x, y + tag_height, size, size);
4544                 device.blit_render_target_invert_y(src_rect, dest_rect);
4545                 i += 1;
4546             }
4547         }
4548     }
4549 
draw_epoch_debug(&mut self)4550     fn draw_epoch_debug(&mut self) {
4551         if !self.debug_flags.contains(DebugFlags::EPOCHS) {
4552             return;
4553         }
4554 
4555         let debug_renderer = match self.debug.get_mut(&mut self.device) {
4556             Some(render) => render,
4557             None => return,
4558         };
4559 
4560         let dy = debug_renderer.line_height();
4561         let x0: f32 = 30.0;
4562         let y0: f32 = 30.0;
4563         let mut y = y0;
4564         let mut text_width = 0.0;
4565         for (pipeline, epoch) in  &self.pipeline_info.epochs {
4566             y += dy;
4567             let w = debug_renderer.add_text(
4568                 x0, y,
4569                 &format!("{:?}: {:?}", pipeline, epoch),
4570                 ColorU::new(255, 255, 0, 255),
4571                 None,
4572             ).size.width;
4573             text_width = f32::max(text_width, w);
4574         }
4575 
4576         let margin = 10.0;
4577         debug_renderer.add_quad(
4578             &x0 - margin,
4579             y0 - margin,
4580             x0 + text_width + margin,
4581             y + margin,
4582             ColorU::new(25, 25, 25, 200),
4583             ColorU::new(51, 51, 51, 200),
4584         );
4585     }
4586 
draw_gpu_cache_debug(&mut self, framebuffer_size: DeviceIntSize)4587     fn draw_gpu_cache_debug(&mut self, framebuffer_size: DeviceIntSize) {
4588         if !self.debug_flags.contains(DebugFlags::GPU_CACHE_DBG) {
4589             return;
4590         }
4591 
4592         let debug_renderer = match self.debug.get_mut(&mut self.device) {
4593             Some(render) => render,
4594             None => return,
4595         };
4596 
4597         let (x_off, y_off) = (30f32, 30f32);
4598         let height = self.gpu_cache_texture.texture
4599             .as_ref().map_or(0, |t| t.get_dimensions().height)
4600             .min(framebuffer_size.height - (y_off as i32) * 2) as usize;
4601         debug_renderer.add_quad(
4602             x_off,
4603             y_off,
4604             x_off + MAX_VERTEX_TEXTURE_WIDTH as f32,
4605             y_off + height as f32,
4606             ColorU::new(80, 80, 80, 80),
4607             ColorU::new(80, 80, 80, 80),
4608         );
4609 
4610         let upper = self.gpu_cache_debug_chunks.len().min(height);
4611         for chunk in self.gpu_cache_debug_chunks[0..upper].iter().flatten() {
4612             let color = ColorU::new(250, 0, 0, 200);
4613             debug_renderer.add_quad(
4614                 x_off + chunk.address.u as f32,
4615                 y_off + chunk.address.v as f32,
4616                 x_off + chunk.address.u as f32 + chunk.size as f32,
4617                 y_off + chunk.address.v as f32 + 1.0,
4618                 color,
4619                 color,
4620             );
4621         }
4622     }
4623 
4624     /// Pass-through to `Device::read_pixels_into`, used by Gecko's WR bindings.
read_pixels_into(&mut self, rect: DeviceIntRect, format: ReadPixelsFormat, output: &mut [u8])4625     pub fn read_pixels_into(&mut self, rect: DeviceIntRect, format: ReadPixelsFormat, output: &mut [u8]) {
4626         self.device.read_pixels_into(rect, format, output);
4627     }
4628 
read_pixels_rgba8(&mut self, rect: DeviceIntRect) -> Vec<u8>4629     pub fn read_pixels_rgba8(&mut self, rect: DeviceIntRect) -> Vec<u8> {
4630         let mut pixels = vec![0; (rect.size.width * rect.size.height * 4) as usize];
4631         self.device.read_pixels_into(rect, ReadPixelsFormat::Rgba8, &mut pixels);
4632         pixels
4633     }
4634 
read_gpu_cache(&mut self) -> (DeviceIntSize, Vec<u8>)4635     pub fn read_gpu_cache(&mut self) -> (DeviceIntSize, Vec<u8>) {
4636         let texture = self.gpu_cache_texture.texture.as_ref().unwrap();
4637         let size = texture.get_dimensions();
4638         let mut texels = vec![0; (size.width * size.height * 16) as usize];
4639         self.device.begin_frame();
4640         self.device.bind_read_target(ReadTarget::Texture { texture, layer: 0 });
4641         self.device.read_pixels_into(
4642             DeviceIntRect::new(DeviceIntPoint::zero(), size),
4643             ReadPixelsFormat::Standard(ImageFormat::RGBAF32),
4644             &mut texels,
4645         );
4646         self.device.reset_read_target();
4647         self.device.end_frame();
4648         (size, texels)
4649     }
4650 
4651     // De-initialize the Renderer safely, assuming the GL is still alive and active.
deinit(mut self)4652     pub fn deinit(mut self) {
4653         //Note: this is a fake frame, only needed because texture deletion is require to happen inside a frame
4654         self.device.begin_frame();
4655         self.gpu_cache_texture.deinit(&mut self.device);
4656         if let Some(dither_matrix_texture) = self.dither_matrix_texture {
4657             self.device.delete_texture(dither_matrix_texture);
4658         }
4659         if let Some(zoom_debug_texture) = self.zoom_debug_texture {
4660             self.device.delete_texture(zoom_debug_texture);
4661         }
4662         self.transforms_texture.deinit(&mut self.device);
4663         self.prim_header_f_texture.deinit(&mut self.device);
4664         self.prim_header_i_texture.deinit(&mut self.device);
4665         self.render_task_texture.deinit(&mut self.device);
4666         self.device.delete_pbo(self.texture_cache_upload_pbo);
4667         self.texture_resolver.deinit(&mut self.device);
4668         self.device.delete_vao(self.vaos.prim_vao);
4669         self.device.delete_vao(self.vaos.clip_vao);
4670         self.device.delete_vao(self.vaos.blur_vao);
4671         self.device.delete_vao(self.vaos.line_vao);
4672         self.device.delete_vao(self.vaos.border_vao);
4673         self.device.delete_vao(self.vaos.scale_vao);
4674 
4675         self.debug.deinit(&mut self.device);
4676 
4677         for (_, target) in self.output_targets {
4678             self.device.delete_fbo(target.fbo_id);
4679         }
4680         if let Ok(shaders) = Rc::try_unwrap(self.shaders) {
4681             shaders.into_inner().deinit(&mut self.device);
4682         }
4683         #[cfg(feature = "capture")]
4684         self.device.delete_fbo(self.read_fbo);
4685         #[cfg(feature = "replay")]
4686         for (_, ext) in self.owned_external_images {
4687             self.device.delete_external_texture(ext);
4688         }
4689         self.device.end_frame();
4690     }
4691 
size_of<T>(&self, ptr: *const T) -> usize4692     fn size_of<T>(&self, ptr: *const T) -> usize {
4693         let op = self.size_of_ops.as_ref().unwrap().size_of_op;
4694         unsafe { op(ptr as *const c_void) }
4695     }
4696 
4697     /// Collects a memory report.
report_memory(&self) -> MemoryReport4698     pub fn report_memory(&self) -> MemoryReport {
4699         let mut report = MemoryReport::default();
4700 
4701         // GPU cache CPU memory.
4702         if let GpuCacheBus::PixelBuffer{ref rows, ..} = self.gpu_cache_texture.bus {
4703             for row in rows.iter() {
4704                 report.gpu_cache_cpu_mirror += self.size_of(&*row.cpu_blocks as *const _);
4705             }
4706         }
4707 
4708         // GPU cache GPU memory.
4709         report.gpu_cache_textures +=
4710             self.gpu_cache_texture.texture.as_ref().map_or(0, |t| t.size_in_bytes());
4711 
4712         // Render task CPU memory.
4713         for (_id, doc) in &self.active_documents {
4714             report.render_tasks += self.size_of(doc.frame.render_tasks.tasks.as_ptr());
4715             report.render_tasks += self.size_of(doc.frame.render_tasks.task_data.as_ptr());
4716         }
4717 
4718         // Vertex data GPU memory.
4719         report.vertex_data_textures += self.prim_header_f_texture.size_in_bytes();
4720         report.vertex_data_textures += self.prim_header_i_texture.size_in_bytes();
4721         report.vertex_data_textures += self.transforms_texture.size_in_bytes();
4722         report.vertex_data_textures += self.render_task_texture.size_in_bytes();
4723 
4724         // Texture cache and render target GPU memory.
4725         report += self.texture_resolver.report_memory();
4726 
4727         // Textures held internally within the device layer.
4728         report += self.device.report_memory();
4729 
4730         report
4731     }
4732 
4733     // Sets the blend mode. Blend is unconditionally set if the "show overdraw" debugging mode is
4734     // enabled.
set_blend(&self, mut blend: bool, framebuffer_kind: FramebufferKind)4735     fn set_blend(&self, mut blend: bool, framebuffer_kind: FramebufferKind) {
4736         if framebuffer_kind == FramebufferKind::Main &&
4737                 self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) {
4738             blend = true
4739         }
4740         self.device.set_blend(blend)
4741     }
4742 
set_blend_mode_multiply(&self, framebuffer_kind: FramebufferKind)4743     fn set_blend_mode_multiply(&self, framebuffer_kind: FramebufferKind) {
4744         if framebuffer_kind == FramebufferKind::Main &&
4745                 self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) {
4746             self.device.set_blend_mode_show_overdraw();
4747         } else {
4748             self.device.set_blend_mode_multiply();
4749         }
4750     }
4751 
set_blend_mode_premultiplied_alpha(&self, framebuffer_kind: FramebufferKind)4752     fn set_blend_mode_premultiplied_alpha(&self, framebuffer_kind: FramebufferKind) {
4753         if framebuffer_kind == FramebufferKind::Main &&
4754                 self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) {
4755             self.device.set_blend_mode_show_overdraw();
4756         } else {
4757             self.device.set_blend_mode_premultiplied_alpha();
4758         }
4759     }
4760 
set_blend_mode_subpixel_with_bg_color_pass1(&self, framebuffer_kind: FramebufferKind)4761     fn set_blend_mode_subpixel_with_bg_color_pass1(&self, framebuffer_kind: FramebufferKind) {
4762         if framebuffer_kind == FramebufferKind::Main &&
4763                 self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) {
4764             self.device.set_blend_mode_show_overdraw();
4765         } else {
4766             self.device.set_blend_mode_subpixel_with_bg_color_pass1();
4767         }
4768     }
4769 
set_blend_mode_subpixel_with_bg_color_pass2(&self, framebuffer_kind: FramebufferKind)4770     fn set_blend_mode_subpixel_with_bg_color_pass2(&self, framebuffer_kind: FramebufferKind) {
4771         if framebuffer_kind == FramebufferKind::Main &&
4772                 self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) {
4773             self.device.set_blend_mode_show_overdraw();
4774         } else {
4775             self.device.set_blend_mode_subpixel_with_bg_color_pass2();
4776         }
4777     }
4778 
4779     /// Clears all the layers of a texture with a given color.
clear_texture(&mut self, texture: &Texture, color: [f32; 4])4780     fn clear_texture(&mut self, texture: &Texture, color: [f32; 4]) {
4781         for i in 0..texture.get_layer_count() {
4782             self.device.bind_draw_target(DrawTarget::Texture {
4783                 texture: &texture,
4784                 layer: i as usize,
4785                 with_depth: false,
4786             });
4787             self.device.clear_target(Some(color), None, None);
4788         }
4789     }
4790 }
4791 
4792 pub enum ExternalImageSource<'a> {
4793     RawData(&'a [u8]),  // raw buffers.
4794     NativeTexture(u32), // It's a gl::GLuint texture handle
4795     Invalid,
4796 }
4797 
4798 /// The data that an external client should provide about
4799 /// an external image. The timestamp is used to test if
4800 /// the renderer should upload new texture data this
4801 /// frame. For instance, if providing video frames, the
4802 /// application could call wr.render() whenever a new
4803 /// video frame is ready. If the callback increments
4804 /// the returned timestamp for a given image, the renderer
4805 /// will know to re-upload the image data to the GPU.
4806 /// Note that the UV coords are supplied in texel-space!
4807 pub struct ExternalImage<'a> {
4808     pub uv: TexelRect,
4809     pub source: ExternalImageSource<'a>,
4810 }
4811 
4812 /// The interfaces that an application can implement to support providing
4813 /// external image buffers.
4814 /// When the the application passes an external image to WR, it should kepp that
4815 /// external image life time. People could check the epoch id in RenderNotifier
4816 /// at the client side to make sure that the external image is not used by WR.
4817 /// Then, do the clean up for that external image.
4818 pub trait ExternalImageHandler {
4819     /// Lock the external image. Then, WR could start to read the image content.
4820     /// The WR client should not change the image content until the unlock()
4821     /// call. Provide ImageRendering for NativeTexture external images.
lock(&mut self, key: ExternalImageId, channel_index: u8, rendering: ImageRendering) -> ExternalImage4822     fn lock(&mut self, key: ExternalImageId, channel_index: u8, rendering: ImageRendering) -> ExternalImage;
4823     /// Unlock the external image. The WR should not read the image content
4824     /// after this call.
unlock(&mut self, key: ExternalImageId, channel_index: u8)4825     fn unlock(&mut self, key: ExternalImageId, channel_index: u8);
4826 }
4827 
4828 /// Allows callers to receive a texture with the contents of a specific
4829 /// pipeline copied to it. Lock should return the native texture handle
4830 /// and the size of the texture. Unlock will only be called if the lock()
4831 /// call succeeds, when WR has issued the GL commands to copy the output
4832 /// to the texture handle.
4833 pub trait OutputImageHandler {
lock(&mut self, pipeline_id: PipelineId) -> Option<(u32, DeviceIntSize)>4834     fn lock(&mut self, pipeline_id: PipelineId) -> Option<(u32, DeviceIntSize)>;
unlock(&mut self, pipeline_id: PipelineId)4835     fn unlock(&mut self, pipeline_id: PipelineId);
4836 }
4837 
4838 pub trait ThreadListener {
thread_started(&self, thread_name: &str)4839     fn thread_started(&self, thread_name: &str);
thread_stopped(&self, thread_name: &str)4840     fn thread_stopped(&self, thread_name: &str);
4841 }
4842 
4843 /// Allows callers to hook in at certain points of the async scene build. These
4844 /// functions are all called from the scene builder thread.
4845 pub trait SceneBuilderHooks {
4846     /// This is called exactly once, when the scene builder thread is started
4847     /// and before it processes anything.
register(&self)4848     fn register(&self);
4849     /// This is called before each scene build starts.
pre_scene_build(&self)4850     fn pre_scene_build(&self);
4851     /// This is called before each scene swap occurs.
pre_scene_swap(&self, scenebuild_time: u64)4852     fn pre_scene_swap(&self, scenebuild_time: u64);
4853     /// This is called after each scene swap occurs. The PipelineInfo contains
4854     /// the updated epochs and pipelines removed in the new scene compared to
4855     /// the old scene.
post_scene_swap(&self, info: PipelineInfo, sceneswap_time: u64)4856     fn post_scene_swap(&self, info: PipelineInfo, sceneswap_time: u64);
4857     /// This is called after a resource update operation on the scene builder
4858     /// thread, in the case where resource updates were applied without a scene
4859     /// build.
post_resource_update(&self)4860     fn post_resource_update(&self);
4861     /// This is called after a scene build completes without any changes being
4862     /// made. We guarantee that each pre_scene_build call will be matched with
4863     /// exactly one of post_scene_swap, post_resource_update or
4864     /// post_empty_scene_build.
post_empty_scene_build(&self)4865     fn post_empty_scene_build(&self);
4866     /// This is a generic callback which provides an opportunity to run code
4867     /// on the scene builder thread. This is called as part of the main message
4868     /// loop of the scene builder thread, but outside of any specific message
4869     /// handler.
poke(&self)4870     fn poke(&self);
4871     /// This is called exactly once, when the scene builder thread is about to
4872     /// terminate.
deregister(&self)4873     fn deregister(&self);
4874 }
4875 
4876 /// Allows callers to hook into the main render_backend loop and provide
4877 /// additional frame ops for generate_frame transactions. These functions
4878 /// are all called from the render backend thread.
4879 pub trait AsyncPropertySampler {
4880     /// This is called exactly once, when the render backend thread is started
4881     /// and before it processes anything.
register(&self)4882     fn register(&self);
4883     /// This is called for each transaction with the generate_frame flag set
4884     /// (i.e. that will trigger a render). The list of frame messages returned
4885     /// are processed as though they were part of the original transaction.
sample(&self) -> Vec<FrameMsg>4886     fn sample(&self) -> Vec<FrameMsg>;
4887     /// This is called exactly once, when the render backend thread is about to
4888     /// terminate.
deregister(&self)4889     fn deregister(&self);
4890 }
4891 
4892 /// Flags that control how shaders are pre-cached, if at all.
4893 bitflags! {
4894     #[derive(Default)]
4895     pub struct ShaderPrecacheFlags: u32 {
4896         /// Needed for const initialization
4897         const EMPTY                 = 0;
4898 
4899         /// Only start async compile
4900         const ASYNC_COMPILE         = 1 << 2;
4901 
4902         /// Do a full compile/link during startup
4903         const FULL_COMPILE          = 1 << 3;
4904     }
4905 }
4906 
4907 pub struct RendererOptions {
4908     pub device_pixel_ratio: f32,
4909     pub resource_override_path: Option<PathBuf>,
4910     pub enable_aa: bool,
4911     pub enable_dithering: bool,
4912     pub max_recorded_profiles: usize,
4913     pub precache_flags: ShaderPrecacheFlags,
4914     pub renderer_kind: RendererKind,
4915     pub enable_subpixel_aa: bool,
4916     pub clear_color: Option<ColorF>,
4917     pub enable_clear_scissor: bool,
4918     pub max_texture_size: Option<i32>,
4919     pub scatter_gpu_cache_updates: bool,
4920     pub upload_method: UploadMethod,
4921     pub workers: Option<Arc<ThreadPool>>,
4922     pub blob_image_handler: Option<Box<BlobImageHandler>>,
4923     pub recorder: Option<Box<ApiRecordingReceiver>>,
4924     pub thread_listener: Option<Box<ThreadListener + Send + Sync>>,
4925     pub size_of_op: Option<VoidPtrToSizeFn>,
4926     pub enclosing_size_of_op: Option<VoidPtrToSizeFn>,
4927     pub cached_programs: Option<Rc<ProgramCache>>,
4928     pub debug_flags: DebugFlags,
4929     pub renderer_id: Option<u64>,
4930     pub disable_dual_source_blending: bool,
4931     pub scene_builder_hooks: Option<Box<SceneBuilderHooks + Send>>,
4932     pub sampler: Option<Box<AsyncPropertySampler + Send>>,
4933     pub chase_primitive: ChasePrimitive,
4934     pub support_low_priority_transactions: bool,
4935     pub namespace_alloc_by_client: bool,
4936     pub enable_picture_caching: bool,
4937     pub testing: bool,
4938 }
4939 
4940 impl Default for RendererOptions {
default() -> Self4941     fn default() -> Self {
4942         RendererOptions {
4943             device_pixel_ratio: 1.0,
4944             resource_override_path: None,
4945             enable_aa: true,
4946             enable_dithering: true,
4947             debug_flags: DebugFlags::empty(),
4948             max_recorded_profiles: 0,
4949             precache_flags: ShaderPrecacheFlags::empty(),
4950             renderer_kind: RendererKind::Native,
4951             enable_subpixel_aa: false,
4952             clear_color: Some(ColorF::new(1.0, 1.0, 1.0, 1.0)),
4953             enable_clear_scissor: true,
4954             max_texture_size: None,
4955             // Scattered GPU cache updates haven't met a test that would show their superiority yet.
4956             scatter_gpu_cache_updates: false,
4957             // This is best as `Immediate` on Angle, or `Pixelbuffer(Dynamic)` on GL,
4958             // but we are unable to make this decision here, so picking the reasonable medium.
4959             upload_method: UploadMethod::PixelBuffer(VertexUsageHint::Stream),
4960             workers: None,
4961             blob_image_handler: None,
4962             recorder: None,
4963             thread_listener: None,
4964             size_of_op: None,
4965             enclosing_size_of_op: None,
4966             renderer_id: None,
4967             cached_programs: None,
4968             disable_dual_source_blending: false,
4969             scene_builder_hooks: None,
4970             sampler: None,
4971             chase_primitive: ChasePrimitive::Nothing,
4972             support_low_priority_transactions: false,
4973             namespace_alloc_by_client: false,
4974             enable_picture_caching: false,
4975             testing: false,
4976         }
4977     }
4978 }
4979 
4980 #[cfg(not(feature = "debugger"))]
4981 pub struct DebugServer;
4982 
4983 #[cfg(not(feature = "debugger"))]
4984 impl DebugServer {
new(_: MsgSender<ApiMsg>) -> Self4985     pub fn new(_: MsgSender<ApiMsg>) -> Self {
4986         DebugServer
4987     }
4988 
send(&mut self, _: String)4989     pub fn send(&mut self, _: String) {}
4990 }
4991 
4992 /// Some basic statistics about the rendered scene, used in Gecko, as
4993 /// well as in wrench reftests to ensure that tests are batching and/or
4994 /// allocating on render targets as we expect them to.
4995 #[repr(C)]
4996 #[derive(Debug, Default)]
4997 pub struct RendererStats {
4998     pub total_draw_calls: usize,
4999     pub alpha_target_count: usize,
5000     pub color_target_count: usize,
5001     pub texture_upload_kb: usize,
5002     pub resource_upload_time: u64,
5003     pub gpu_cache_upload_time: u64,
5004 }
5005 
5006 /// Return type from render(), which contains some repr(C) statistics as well as
5007 /// some non-repr(C) data.
5008 #[derive(Debug, Default)]
5009 pub struct RenderResults {
5010     pub stats: RendererStats,
5011     pub recorded_dirty_regions: Vec<RecordedDirtyRegion>,
5012 }
5013 
5014 #[cfg(any(feature = "capture", feature = "replay"))]
5015 #[cfg_attr(feature = "capture", derive(Serialize))]
5016 #[cfg_attr(feature = "replay", derive(Deserialize))]
5017 struct PlainTexture {
5018     data: String,
5019     size: (DeviceIntSize, i32),
5020     format: ImageFormat,
5021     filter: TextureFilter,
5022 }
5023 
5024 
5025 #[cfg(any(feature = "capture", feature = "replay"))]
5026 #[cfg_attr(feature = "capture", derive(Serialize))]
5027 #[cfg_attr(feature = "replay", derive(Deserialize))]
5028 struct PlainRenderer {
5029     gpu_cache: PlainTexture,
5030     gpu_cache_frame_id: FrameId,
5031     textures: FastHashMap<CacheTextureId, PlainTexture>,
5032     external_images: Vec<ExternalCaptureImage>
5033 }
5034 
5035 #[cfg(feature = "replay")]
5036 enum CapturedExternalImageData {
5037     NativeTexture(gl::GLuint),
5038     Buffer(Arc<Vec<u8>>),
5039 }
5040 
5041 #[cfg(feature = "replay")]
5042 struct DummyExternalImageHandler {
5043     data: FastHashMap<(ExternalImageId, u8), (CapturedExternalImageData, TexelRect)>,
5044 }
5045 
5046 #[cfg(feature = "replay")]
5047 impl ExternalImageHandler for DummyExternalImageHandler {
lock(&mut self, key: ExternalImageId, channel_index: u8, _rendering: ImageRendering) -> ExternalImage5048     fn lock(&mut self, key: ExternalImageId, channel_index: u8, _rendering: ImageRendering) -> ExternalImage {
5049         let (ref captured_data, ref uv) = self.data[&(key, channel_index)];
5050         ExternalImage {
5051             uv: *uv,
5052             source: match *captured_data {
5053                 CapturedExternalImageData::NativeTexture(tid) => ExternalImageSource::NativeTexture(tid),
5054                 CapturedExternalImageData::Buffer(ref arc) => ExternalImageSource::RawData(&*arc),
5055             }
5056         }
5057     }
unlock(&mut self, _key: ExternalImageId, _channel_index: u8)5058     fn unlock(&mut self, _key: ExternalImageId, _channel_index: u8) {}
5059 }
5060 
5061 #[cfg(feature = "replay")]
5062 impl OutputImageHandler for () {
lock(&mut self, _: PipelineId) -> Option<(u32, DeviceIntSize)>5063     fn lock(&mut self, _: PipelineId) -> Option<(u32, DeviceIntSize)> {
5064         None
5065     }
unlock(&mut self, _: PipelineId)5066     fn unlock(&mut self, _: PipelineId) {
5067         unreachable!()
5068     }
5069 }
5070 
5071 #[derive(Default)]
5072 pub struct PipelineInfo {
5073     pub epochs: FastHashMap<PipelineId, Epoch>,
5074     pub removed_pipelines: Vec<PipelineId>,
5075 }
5076 
5077 impl Renderer {
5078     #[cfg(feature = "capture")]
save_texture( texture: &Texture, name: &str, root: &PathBuf, device: &mut Device ) -> PlainTexture5079     fn save_texture(
5080         texture: &Texture, name: &str, root: &PathBuf, device: &mut Device
5081     ) -> PlainTexture {
5082         use std::fs;
5083         use std::io::Write;
5084 
5085         let short_path = format!("textures/{}.raw", name);
5086 
5087         let bytes_per_pixel = texture.get_format().bytes_per_pixel();
5088         let read_format = ReadPixelsFormat::Standard(texture.get_format());
5089         let rect = DeviceIntRect::new(
5090             DeviceIntPoint::zero(),
5091             texture.get_dimensions(),
5092         );
5093 
5094         let mut file = fs::File::create(root.join(&short_path))
5095             .expect(&format!("Unable to create {}", short_path));
5096         let bytes_per_layer = (rect.size.width * rect.size.height * bytes_per_pixel) as usize;
5097         let mut data = vec![0; bytes_per_layer];
5098 
5099         //TODO: instead of reading from an FBO with `read_pixels*`, we could
5100         // read from textures directly with `get_tex_image*`.
5101 
5102         for layer_id in 0 .. texture.get_layer_count() {
5103             device.attach_read_texture(texture, layer_id);
5104             #[cfg(feature = "png")]
5105             {
5106                 let mut png_data;
5107                 let (data_ref, format) = match texture.get_format() {
5108                     ImageFormat::RGBAF32 => {
5109                         png_data = vec![0; (rect.size.width * rect.size.height * 4) as usize];
5110                         device.read_pixels_into(rect, ReadPixelsFormat::Rgba8, &mut png_data);
5111                         (&png_data, ReadPixelsFormat::Rgba8)
5112                     }
5113                     fm => (&data, ReadPixelsFormat::Standard(fm)),
5114                 };
5115                 CaptureConfig::save_png(
5116                     root.join(format!("textures/{}-{}.png", name, layer_id)),
5117                     rect.size, format,
5118                     data_ref,
5119                 );
5120             }
5121             device.read_pixels_into(rect, read_format, &mut data);
5122             file.write_all(&data)
5123                 .unwrap();
5124         }
5125 
5126         PlainTexture {
5127             data: short_path,
5128             size: (rect.size, texture.get_layer_count()),
5129             format: texture.get_format(),
5130             filter: texture.get_filter(),
5131         }
5132     }
5133 
5134     #[cfg(feature = "replay")]
load_texture( target: TextureTarget, plain: &PlainTexture, rt_info: Option<RenderTargetInfo>, root: &PathBuf, device: &mut Device ) -> (Texture, Vec<u8>)5135     fn load_texture(
5136         target: TextureTarget,
5137         plain: &PlainTexture,
5138         rt_info: Option<RenderTargetInfo>,
5139         root: &PathBuf,
5140         device: &mut Device
5141     ) -> (Texture, Vec<u8>)
5142     {
5143         use std::fs::File;
5144         use std::io::Read;
5145 
5146         let mut texels = Vec::new();
5147         File::open(root.join(&plain.data))
5148             .expect(&format!("Unable to open texture at {}", plain.data))
5149             .read_to_end(&mut texels)
5150             .unwrap();
5151 
5152         let texture = device.create_texture(
5153             target,
5154             plain.format,
5155             plain.size.0.width,
5156             plain.size.0.height,
5157             plain.filter,
5158             rt_info,
5159             plain.size.1,
5160         );
5161         device.upload_texture_immediate(&texture, &texels);
5162 
5163         (texture, texels)
5164     }
5165 
5166     #[cfg(feature = "capture")]
save_capture( &mut self, config: CaptureConfig, deferred_images: Vec<ExternalCaptureImage>, )5167     fn save_capture(
5168         &mut self,
5169         config: CaptureConfig,
5170         deferred_images: Vec<ExternalCaptureImage>,
5171     ) {
5172         use std::fs;
5173         use std::io::Write;
5174         use api::{CaptureBits, ExternalImageData};
5175 
5176         self.device.begin_frame();
5177         let _gm = self.gpu_profile.start_marker("read GPU data");
5178         self.device.bind_read_target_impl(self.read_fbo);
5179 
5180         if !deferred_images.is_empty() {
5181             info!("saving external images");
5182             let mut arc_map = FastHashMap::<*const u8, String>::default();
5183             let mut tex_map = FastHashMap::<u32, String>::default();
5184             let handler = self.external_image_handler
5185                 .as_mut()
5186                 .expect("Unable to lock the external image handler!");
5187             for def in &deferred_images {
5188                 info!("\t{}", def.short_path);
5189                 let ExternalImageData { id, channel_index, image_type } = def.external;
5190                 // The image rendering parameter is irrelevant because no filtering happens during capturing.
5191                 let ext_image = handler.lock(id, channel_index, ImageRendering::Auto);
5192                 let (data, short_path) = match ext_image.source {
5193                     ExternalImageSource::RawData(data) => {
5194                         let arc_id = arc_map.len() + 1;
5195                         match arc_map.entry(data.as_ptr()) {
5196                             Entry::Occupied(e) => {
5197                                 (None, e.get().clone())
5198                             }
5199                             Entry::Vacant(e) => {
5200                                 let short_path = format!("externals/d{}.raw", arc_id);
5201                                 (Some(data.to_vec()), e.insert(short_path).clone())
5202                             }
5203                         }
5204                     }
5205                     ExternalImageSource::NativeTexture(gl_id) => {
5206                         let tex_id = tex_map.len() + 1;
5207                         match tex_map.entry(gl_id) {
5208                             Entry::Occupied(e) => {
5209                                 (None, e.get().clone())
5210                             }
5211                             Entry::Vacant(e) => {
5212                                 let target = match image_type {
5213                                     ExternalImageType::TextureHandle(target) => target,
5214                                     ExternalImageType::Buffer => unreachable!(),
5215                                 };
5216                                 info!("\t\tnative texture of target {:?}", target);
5217                                 let layer_index = 0; //TODO: what about layered textures?
5218                                 self.device.attach_read_texture_external(gl_id, target, layer_index);
5219                                 let data = self.device.read_pixels(&def.descriptor);
5220                                 let short_path = format!("externals/t{}.raw", tex_id);
5221                                 (Some(data), e.insert(short_path).clone())
5222                             }
5223                         }
5224                     }
5225                     ExternalImageSource::Invalid => {
5226                         info!("\t\tinvalid source!");
5227                         (None, String::new())
5228                     }
5229                 };
5230                 if let Some(bytes) = data {
5231                     fs::File::create(config.root.join(&short_path))
5232                         .expect(&format!("Unable to create {}", short_path))
5233                         .write_all(&bytes)
5234                         .unwrap();
5235                     #[cfg(feature = "png")]
5236                     CaptureConfig::save_png(
5237                         config.root.join(&short_path).with_extension("png"),
5238                         def.descriptor.size,
5239                         ReadPixelsFormat::Standard(def.descriptor.format),
5240                         &bytes,
5241                     );
5242                 }
5243                 let plain = PlainExternalImage {
5244                     data: short_path,
5245                     external: def.external,
5246                     uv: ext_image.uv,
5247                 };
5248                 config.serialize(&plain, &def.short_path);
5249             }
5250             for def in &deferred_images {
5251                 handler.unlock(def.external.id, def.external.channel_index);
5252             }
5253         }
5254 
5255         if config.bits.contains(CaptureBits::FRAME) {
5256             let path_textures = config.root.join("textures");
5257             if !path_textures.is_dir() {
5258                 fs::create_dir(&path_textures).unwrap();
5259             }
5260 
5261             info!("saving GPU cache");
5262             self.update_gpu_cache(); // flush pending updates
5263             let mut plain_self = PlainRenderer {
5264                 gpu_cache: Self::save_texture(
5265                     &self.gpu_cache_texture.texture.as_ref().unwrap(),
5266                     "gpu", &config.root, &mut self.device,
5267                 ),
5268                 gpu_cache_frame_id: self.gpu_cache_frame_id,
5269                 textures: FastHashMap::default(),
5270                 external_images: deferred_images,
5271             };
5272 
5273             info!("saving cached textures");
5274             for (id, texture) in &self.texture_resolver.texture_cache_map {
5275                 let file_name = format!("cache-{}", plain_self.textures.len() + 1);
5276                 info!("\t{}", file_name);
5277                 let plain = Self::save_texture(texture, &file_name, &config.root, &mut self.device);
5278                 plain_self.textures.insert(*id, plain);
5279             }
5280 
5281             config.serialize(&plain_self, "renderer");
5282         }
5283 
5284         self.device.reset_read_target();
5285         self.device.end_frame();
5286         info!("done.");
5287     }
5288 
5289     #[cfg(feature = "replay")]
load_capture( &mut self, root: PathBuf, plain_externals: Vec<PlainExternalImage> )5290     fn load_capture(
5291         &mut self, root: PathBuf, plain_externals: Vec<PlainExternalImage>
5292     ) {
5293         use std::fs::File;
5294         use std::io::Read;
5295         use std::slice;
5296 
5297         info!("loading external buffer-backed images");
5298         assert!(self.texture_resolver.external_images.is_empty());
5299         let mut raw_map = FastHashMap::<String, Arc<Vec<u8>>>::default();
5300         let mut image_handler = DummyExternalImageHandler {
5301             data: FastHashMap::default(),
5302         };
5303         // Note: this is a `SCENE` level population of the external image handlers
5304         // It would put both external buffers and texture into the map.
5305         // But latter are going to be overwritten later in this function
5306         // if we are in the `FRAME` level.
5307         for plain_ext in plain_externals {
5308             let data = match raw_map.entry(plain_ext.data) {
5309                 Entry::Occupied(e) => e.get().clone(),
5310                 Entry::Vacant(e) => {
5311                     let mut buffer = Vec::new();
5312                     File::open(root.join(e.key()))
5313                         .expect(&format!("Unable to open {}", e.key()))
5314                         .read_to_end(&mut buffer)
5315                         .unwrap();
5316                     e.insert(Arc::new(buffer)).clone()
5317                 }
5318             };
5319             let ext = plain_ext.external;
5320             let value = (CapturedExternalImageData::Buffer(data), plain_ext.uv);
5321             image_handler.data.insert((ext.id, ext.channel_index), value);
5322         }
5323 
5324         if let Some(renderer) = CaptureConfig::deserialize::<PlainRenderer, _>(&root, "renderer") {
5325             info!("loading cached textures");
5326             self.device.begin_frame();
5327 
5328             for (_id, texture) in self.texture_resolver.texture_cache_map.drain() {
5329                 self.device.delete_texture(texture);
5330             }
5331             for (id, texture) in renderer.textures {
5332                 info!("\t{}", texture.data);
5333                 let t = Self::load_texture(
5334                     TextureTarget::Array,
5335                     &texture,
5336                     Some(RenderTargetInfo { has_depth: false }),
5337                     &root,
5338                     &mut self.device
5339                 );
5340                 self.texture_resolver.texture_cache_map.insert(id, t.0);
5341             }
5342 
5343             info!("loading gpu cache");
5344             if let Some(t) = self.gpu_cache_texture.texture.take() {
5345                 self.device.delete_texture(t);
5346             }
5347             let (t, gpu_cache_data) = Self::load_texture(
5348                 TextureTarget::Default,
5349                 &renderer.gpu_cache,
5350                 Some(RenderTargetInfo { has_depth: false }),
5351                 &root,
5352                 &mut self.device,
5353             );
5354             self.gpu_cache_texture.texture = Some(t);
5355             match self.gpu_cache_texture.bus {
5356                 GpuCacheBus::PixelBuffer { ref mut rows, .. } => {
5357                     let dim = self.gpu_cache_texture.texture.as_ref().unwrap().get_dimensions();
5358                     let blocks = unsafe {
5359                         slice::from_raw_parts(
5360                             gpu_cache_data.as_ptr() as *const GpuBlockData,
5361                             gpu_cache_data.len() / mem::size_of::<GpuBlockData>(),
5362                         )
5363                     };
5364                     // fill up the CPU cache from the contents we just loaded
5365                     rows.clear();
5366                     rows.extend((0 .. dim.height).map(|_| CacheRow::new()));
5367                     let chunks = blocks.chunks(MAX_VERTEX_TEXTURE_WIDTH);
5368                     debug_assert_eq!(chunks.len(), rows.len());
5369                     for (row, chunk) in rows.iter_mut().zip(chunks) {
5370                         row.cpu_blocks.copy_from_slice(chunk);
5371                     }
5372                 }
5373                 GpuCacheBus::Scatter { .. } => {}
5374             }
5375             self.gpu_cache_frame_id = renderer.gpu_cache_frame_id;
5376 
5377             info!("loading external texture-backed images");
5378             let mut native_map = FastHashMap::<String, gl::GLuint>::default();
5379             for ExternalCaptureImage { short_path, external, descriptor } in renderer.external_images {
5380                 let target = match external.image_type {
5381                     ExternalImageType::TextureHandle(target) => target,
5382                     ExternalImageType::Buffer => continue,
5383                 };
5384                 let plain_ext = CaptureConfig::deserialize::<PlainExternalImage, _>(&root, &short_path)
5385                     .expect(&format!("Unable to read {}.ron", short_path));
5386                 let key = (external.id, external.channel_index);
5387 
5388                 let tid = match native_map.entry(plain_ext.data) {
5389                     Entry::Occupied(e) => e.get().clone(),
5390                     Entry::Vacant(e) => {
5391                         //TODO: provide a way to query both the layer count and the filter from external images
5392                         let (layer_count, filter) = (1, TextureFilter::Linear);
5393                         let plain_tex = PlainTexture {
5394                             data: e.key().clone(),
5395                             size: (descriptor.size, layer_count),
5396                             format: descriptor.format,
5397                             filter,
5398                         };
5399                         let t = Self::load_texture(
5400                             target,
5401                             &plain_tex,
5402                             None,
5403                             &root,
5404                             &mut self.device
5405                         );
5406                         let extex = t.0.into_external();
5407                         self.owned_external_images.insert(key, extex.clone());
5408                         e.insert(extex.internal_id()).clone()
5409                     }
5410                 };
5411 
5412                 let value = (CapturedExternalImageData::NativeTexture(tid), plain_ext.uv);
5413                 image_handler.data.insert(key, value);
5414             }
5415 
5416             self.device.end_frame();
5417         }
5418 
5419         self.output_image_handler = Some(Box::new(()) as Box<_>);
5420         self.external_image_handler = Some(Box::new(image_handler) as Box<_>);
5421         info!("done.");
5422     }
5423 }
5424 
5425 #[cfg(feature = "pathfinder")]
get_vao<'a>(vertex_array_kind: VertexArrayKind, vaos: &'a RendererVAOs, gpu_glyph_renderer: &'a GpuGlyphRenderer) -> &'a VAO5426 fn get_vao<'a>(vertex_array_kind: VertexArrayKind,
5427                vaos: &'a RendererVAOs,
5428                gpu_glyph_renderer: &'a GpuGlyphRenderer)
5429                -> &'a VAO {
5430     match vertex_array_kind {
5431         VertexArrayKind::Primitive => &vaos.prim_vao,
5432         VertexArrayKind::Clip => &vaos.clip_vao,
5433         VertexArrayKind::Blur => &vaos.blur_vao,
5434         VertexArrayKind::VectorStencil => &gpu_glyph_renderer.vector_stencil_vao,
5435         VertexArrayKind::VectorCover => &gpu_glyph_renderer.vector_cover_vao,
5436         VertexArrayKind::Border => &vaos.border_vao,
5437         VertexArrayKind::Scale => &vaos.scale_vao,
5438         VertexArrayKind::LineDecoration => &vaos.line_vao,
5439     }
5440 }
5441 
5442 #[cfg(not(feature = "pathfinder"))]
get_vao<'a>(vertex_array_kind: VertexArrayKind, vaos: &'a RendererVAOs, _: &'a GpuGlyphRenderer) -> &'a VAO5443 fn get_vao<'a>(vertex_array_kind: VertexArrayKind,
5444                vaos: &'a RendererVAOs,
5445                _: &'a GpuGlyphRenderer)
5446                -> &'a VAO {
5447     match vertex_array_kind {
5448         VertexArrayKind::Primitive => &vaos.prim_vao,
5449         VertexArrayKind::Clip => &vaos.clip_vao,
5450         VertexArrayKind::Blur => &vaos.blur_vao,
5451         VertexArrayKind::VectorStencil | VertexArrayKind::VectorCover => unreachable!(),
5452         VertexArrayKind::Border => &vaos.border_vao,
5453         VertexArrayKind::Scale => &vaos.scale_vao,
5454         VertexArrayKind::LineDecoration => &vaos.line_vao,
5455     }
5456 }
5457 
5458 #[derive(Clone, Copy, PartialEq)]
5459 enum FramebufferKind {
5460     Main,
5461     Other,
5462 }
5463 
5464