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 use app_units::Au;
6 use channel::{self, MsgSender, Payload, PayloadSender, PayloadSenderHelperMethods};
7 use std::cell::Cell;
8 use std::fmt;
9 use std::marker::PhantomData;
10 use std::path::PathBuf;
11 use std::u32;
12 use {BuiltDisplayList, BuiltDisplayListDescriptor, ColorF, DeviceIntPoint, DeviceUintRect};
13 use {DeviceUintSize, ExternalScrollId, FontInstanceKey, FontInstanceOptions};
14 use {FontInstancePlatformOptions, FontKey, FontVariation, GlyphDimensions, GlyphKey, ImageData};
15 use {ImageDescriptor, ImageKey, ItemTag, LayoutPoint, LayoutSize, LayoutTransform, LayoutVector2D};
16 use {NativeFontHandle, WorldPoint};
17 
18 pub type TileSize = u16;
19 /// Documents are rendered in the ascending order of their associated layer values.
20 pub type DocumentLayer = i8;
21 
22 /// The resource updates for a given transaction (they must be applied in the same frame).
23 #[derive(Clone, Deserialize, Serialize)]
24 pub struct ResourceUpdates {
25     pub updates: Vec<ResourceUpdate>,
26 }
27 
28 #[derive(Clone, Deserialize, Serialize)]
29 pub enum ResourceUpdate {
30     AddImage(AddImage),
31     UpdateImage(UpdateImage),
32     DeleteImage(ImageKey),
33     AddFont(AddFont),
34     DeleteFont(FontKey),
35     AddFontInstance(AddFontInstance),
36     DeleteFontInstance(FontInstanceKey),
37 }
38 
39 impl ResourceUpdates {
new() -> Self40     pub fn new() -> Self {
41         ResourceUpdates {
42             updates: Vec::new(),
43         }
44     }
45 
add_image( &mut self, key: ImageKey, descriptor: ImageDescriptor, data: ImageData, tiling: Option<TileSize>, )46     pub fn add_image(
47         &mut self,
48         key: ImageKey,
49         descriptor: ImageDescriptor,
50         data: ImageData,
51         tiling: Option<TileSize>,
52     ) {
53         self.updates.push(ResourceUpdate::AddImage(AddImage {
54             key,
55             descriptor,
56             data,
57             tiling,
58         }));
59     }
60 
update_image( &mut self, key: ImageKey, descriptor: ImageDescriptor, data: ImageData, dirty_rect: Option<DeviceUintRect>, )61     pub fn update_image(
62         &mut self,
63         key: ImageKey,
64         descriptor: ImageDescriptor,
65         data: ImageData,
66         dirty_rect: Option<DeviceUintRect>,
67     ) {
68         self.updates.push(ResourceUpdate::UpdateImage(UpdateImage {
69             key,
70             descriptor,
71             data,
72             dirty_rect,
73         }));
74     }
75 
delete_image(&mut self, key: ImageKey)76     pub fn delete_image(&mut self, key: ImageKey) {
77         self.updates.push(ResourceUpdate::DeleteImage(key));
78     }
79 
add_raw_font(&mut self, key: FontKey, bytes: Vec<u8>, index: u32)80     pub fn add_raw_font(&mut self, key: FontKey, bytes: Vec<u8>, index: u32) {
81         self.updates
82             .push(ResourceUpdate::AddFont(AddFont::Raw(key, bytes, index)));
83     }
84 
add_native_font(&mut self, key: FontKey, native_handle: NativeFontHandle)85     pub fn add_native_font(&mut self, key: FontKey, native_handle: NativeFontHandle) {
86         self.updates
87             .push(ResourceUpdate::AddFont(AddFont::Native(key, native_handle)));
88     }
89 
delete_font(&mut self, key: FontKey)90     pub fn delete_font(&mut self, key: FontKey) {
91         self.updates.push(ResourceUpdate::DeleteFont(key));
92     }
93 
add_font_instance( &mut self, key: FontInstanceKey, font_key: FontKey, glyph_size: Au, options: Option<FontInstanceOptions>, platform_options: Option<FontInstancePlatformOptions>, variations: Vec<FontVariation>, )94     pub fn add_font_instance(
95         &mut self,
96         key: FontInstanceKey,
97         font_key: FontKey,
98         glyph_size: Au,
99         options: Option<FontInstanceOptions>,
100         platform_options: Option<FontInstancePlatformOptions>,
101         variations: Vec<FontVariation>,
102     ) {
103         self.updates
104             .push(ResourceUpdate::AddFontInstance(AddFontInstance {
105                 key,
106                 font_key,
107                 glyph_size,
108                 options,
109                 platform_options,
110                 variations,
111             }));
112     }
113 
delete_font_instance(&mut self, key: FontInstanceKey)114     pub fn delete_font_instance(&mut self, key: FontInstanceKey) {
115         self.updates.push(ResourceUpdate::DeleteFontInstance(key));
116     }
117 
merge(&mut self, mut other: ResourceUpdates)118     pub fn merge(&mut self, mut other: ResourceUpdates) {
119         self.updates.append(&mut other.updates);
120     }
121 
clear(&mut self)122     pub fn clear(&mut self) {
123         self.updates.clear()
124     }
125 }
126 
127 /// A Transaction is a group of commands to apply atomically to a document.
128 ///
129 /// This mechanism ensures that:
130 ///  - no other message can be interleaved between two commands that need to be applied together.
131 ///  - no redundant work is performed if two commands in the same transaction cause the scene or
132 ///    the frame to be rebuilt.
133 pub struct Transaction {
134     // Operations affecting the scene (applied before scene building).
135     scene_ops: Vec<SceneMsg>,
136     // Operations affecting the generation of frames (applied after scene building).
137     frame_ops: Vec<FrameMsg>,
138 
139     // Additional display list data.
140     payloads: Vec<Payload>,
141 
142     // Resource updates are applied after scene building.
143     resource_updates: ResourceUpdates,
144 
145     // If true the transaction is piped through the scene building thread, if false
146     // it will be applied directly on the render backend.
147     use_scene_builder_thread: bool,
148 
149     generate_frame: bool,
150 }
151 
152 impl Transaction {
new() -> Self153     pub fn new() -> Self {
154         Transaction {
155             scene_ops: Vec::new(),
156             frame_ops: Vec::new(),
157             resource_updates: ResourceUpdates::new(),
158             payloads: Vec::new(),
159             use_scene_builder_thread: false, // TODO: make this true by default.
160             generate_frame: false,
161         }
162     }
163 
164     // TODO: better name?
skip_scene_builder(&mut self)165     pub fn skip_scene_builder(&mut self) {
166         self.use_scene_builder_thread = false;
167     }
168 
169     // TODO: this is temporary, using the scene builder thread is the default for
170     // most transactions, and opt-in for specific cases like scrolling and async video.
use_scene_builder_thread(&mut self)171     pub fn use_scene_builder_thread(&mut self) {
172         self.use_scene_builder_thread = true;
173     }
174 
is_empty(&self) -> bool175     pub fn is_empty(&self) -> bool {
176         !self.generate_frame &&
177             self.scene_ops.is_empty() &&
178             self.frame_ops.is_empty() &&
179             self.resource_updates.updates.is_empty()
180     }
181 
update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch)182     pub fn update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch) {
183         // We track epochs before and after scene building.
184         // This one will be applied to the pending scene right away:
185         self.scene_ops.push(SceneMsg::UpdateEpoch(pipeline_id, epoch));
186         // And this one will be applied to the currently built scene at the end
187         // of the transaction (potentially long after the scene_ops one).
188         self.frame_ops.push(FrameMsg::UpdateEpoch(pipeline_id, epoch));
189         // We could avoid the duplication here by storing the epoch updates in a
190         // separate array and let the render backend schedule the updates at the
191         // proper times, but it wouldn't make things simpler.
192     }
193 
194     /// Sets the root pipeline.
195     ///
196     /// # Examples
197     ///
198     /// ```
199     /// # use webrender_api::{DeviceUintSize, PipelineId, RenderApiSender, Transaction};
200     /// # fn example() {
201     /// let pipeline_id = PipelineId(0, 0);
202     /// let mut txn = Transaction::new();
203     /// txn.set_root_pipeline(pipeline_id);
204     /// # }
205     /// ```
set_root_pipeline(&mut self, pipeline_id: PipelineId)206     pub fn set_root_pipeline(&mut self, pipeline_id: PipelineId) {
207         self.scene_ops.push(SceneMsg::SetRootPipeline(pipeline_id));
208     }
209 
210     /// Removes data associated with a pipeline from the internal data structures.
211     /// If the specified `pipeline_id` is for the root pipeline, the root pipeline
212     /// is reset back to `None`.
remove_pipeline(&mut self, pipeline_id: PipelineId)213     pub fn remove_pipeline(&mut self, pipeline_id: PipelineId) {
214         self.scene_ops.push(SceneMsg::RemovePipeline(pipeline_id));
215     }
216 
217     /// Supplies a new frame to WebRender.
218     ///
219     /// Non-blocking, it notifies a worker process which processes the display list.
220     /// When it's done and a RenderNotifier has been set in `webrender::Renderer`,
221     /// [new_frame_ready()][notifier] gets called.
222     ///
223     /// Note: Scrolling doesn't require an own Frame.
224     ///
225     /// Arguments:
226     ///
227     /// * `document_id`: Target Document ID.
228     /// * `epoch`: The unique Frame ID, monotonically increasing.
229     /// * `background`: The background color of this pipeline.
230     /// * `viewport_size`: The size of the viewport for this frame.
231     /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
232     /// * `content_size`: The total screen space size of this display list's display items.
233     /// * `display_list`: The root Display list used in this frame.
234     /// * `preserve_frame_state`: If a previous frame exists which matches this pipeline
235     ///                           id, this setting determines if frame state (such as scrolling
236     ///                           position) should be preserved for this new display list.
237     ///
238     /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
set_display_list( &mut self, epoch: Epoch, background: Option<ColorF>, viewport_size: LayoutSize, (pipeline_id, content_size, display_list): (PipelineId, LayoutSize, BuiltDisplayList), preserve_frame_state: bool, )239     pub fn set_display_list(
240         &mut self,
241         epoch: Epoch,
242         background: Option<ColorF>,
243         viewport_size: LayoutSize,
244         (pipeline_id, content_size, display_list): (PipelineId, LayoutSize, BuiltDisplayList),
245         preserve_frame_state: bool,
246     ) {
247         let (display_list_data, list_descriptor) = display_list.into_data();
248         self.scene_ops.push(
249             SceneMsg::SetDisplayList {
250                 epoch,
251                 pipeline_id,
252                 background,
253                 viewport_size,
254                 content_size,
255                 list_descriptor,
256                 preserve_frame_state,
257             }
258         );
259         self.payloads.push(Payload { epoch, pipeline_id, display_list_data });
260     }
261 
update_resources(&mut self, resources: ResourceUpdates)262     pub fn update_resources(&mut self, resources: ResourceUpdates) {
263         self.resource_updates.merge(resources);
264     }
265 
set_window_parameters( &mut self, window_size: DeviceUintSize, inner_rect: DeviceUintRect, device_pixel_ratio: f32, )266     pub fn set_window_parameters(
267         &mut self,
268         window_size: DeviceUintSize,
269         inner_rect: DeviceUintRect,
270         device_pixel_ratio: f32,
271     ) {
272         self.scene_ops.push(
273             SceneMsg::SetWindowParameters {
274                 window_size,
275                 inner_rect,
276                 device_pixel_ratio,
277             },
278         );
279     }
280 
281     /// Scrolls the scrolling layer under the `cursor`
282     ///
283     /// WebRender looks for the layer closest to the user
284     /// which has `ScrollPolicy::Scrollable` set.
scroll( &mut self, scroll_location: ScrollLocation, cursor: WorldPoint, phase: ScrollEventPhase, )285     pub fn scroll(
286         &mut self,
287         scroll_location: ScrollLocation,
288         cursor: WorldPoint,
289         phase: ScrollEventPhase,
290     ) {
291         self.frame_ops.push(FrameMsg::Scroll(scroll_location, cursor, phase));
292     }
293 
scroll_node_with_id( &mut self, origin: LayoutPoint, id: ExternalScrollId, clamp: ScrollClamping, )294     pub fn scroll_node_with_id(
295         &mut self,
296         origin: LayoutPoint,
297         id: ExternalScrollId,
298         clamp: ScrollClamping,
299     ) {
300         self.frame_ops.push(FrameMsg::ScrollNodeWithId(origin, id, clamp));
301     }
302 
set_page_zoom(&mut self, page_zoom: ZoomFactor)303     pub fn set_page_zoom(&mut self, page_zoom: ZoomFactor) {
304         self.scene_ops.push(SceneMsg::SetPageZoom(page_zoom));
305     }
306 
set_pinch_zoom(&mut self, pinch_zoom: ZoomFactor)307     pub fn set_pinch_zoom(&mut self, pinch_zoom: ZoomFactor) {
308         self.scene_ops.push(SceneMsg::SetPinchZoom(pinch_zoom));
309     }
310 
set_pan(&mut self, pan: DeviceIntPoint)311     pub fn set_pan(&mut self, pan: DeviceIntPoint) {
312         self.frame_ops.push(FrameMsg::SetPan(pan));
313     }
314 
tick_scrolling_bounce_animations(&mut self)315     pub fn tick_scrolling_bounce_animations(&mut self) {
316         self.frame_ops.push(FrameMsg::TickScrollingBounce);
317     }
318 
319     /// Generate a new frame.
generate_frame(&mut self)320     pub fn generate_frame(&mut self) {
321         self.generate_frame = true;
322     }
323 
324     /// Supply a list of animated property bindings that should be used to resolve
325     /// bindings in the current display list.
update_dynamic_properties(&mut self, properties: DynamicProperties)326     pub fn update_dynamic_properties(&mut self, properties: DynamicProperties) {
327         self.frame_ops.push(FrameMsg::UpdateDynamicProperties(properties));
328     }
329 
330     /// Enable copying of the output of this pipeline id to
331     /// an external texture for callers to consume.
enable_frame_output(&mut self, pipeline_id: PipelineId, enable: bool)332     pub fn enable_frame_output(&mut self, pipeline_id: PipelineId, enable: bool) {
333         self.frame_ops.push(FrameMsg::EnableFrameOutput(pipeline_id, enable));
334     }
335 
finalize(self) -> (TransactionMsg, Vec<Payload>)336     fn finalize(self) -> (TransactionMsg, Vec<Payload>) {
337         (
338             TransactionMsg {
339                 scene_ops: self.scene_ops,
340                 frame_ops: self.frame_ops,
341                 resource_updates: self.resource_updates,
342                 use_scene_builder_thread: self.use_scene_builder_thread,
343                 generate_frame: self.generate_frame,
344             },
345             self.payloads,
346         )
347     }
348 }
349 
350 /// Represents a transaction in the format sent through the channel.
351 #[derive(Clone, Deserialize, Serialize)]
352 pub struct TransactionMsg {
353     pub scene_ops: Vec<SceneMsg>,
354     pub frame_ops: Vec<FrameMsg>,
355     pub resource_updates: ResourceUpdates,
356     pub generate_frame: bool,
357     pub use_scene_builder_thread: bool,
358 }
359 
360 impl TransactionMsg {
is_empty(&self) -> bool361     pub fn is_empty(&self) -> bool {
362         !self.generate_frame &&
363             self.scene_ops.is_empty() &&
364             self.frame_ops.is_empty() &&
365             self.resource_updates.updates.is_empty()
366     }
367 
368     // TODO: We only need this for a few RenderApi methods which we should remove.
frame_message(msg: FrameMsg) -> Self369     fn frame_message(msg: FrameMsg) -> Self {
370         TransactionMsg {
371             scene_ops: Vec::new(),
372             frame_ops: vec![msg],
373             resource_updates: ResourceUpdates::new(),
374             generate_frame: false,
375             use_scene_builder_thread: false,
376         }
377     }
378 
scene_message(msg: SceneMsg) -> Self379     fn scene_message(msg: SceneMsg) -> Self {
380         TransactionMsg {
381             scene_ops: vec![msg],
382             frame_ops: Vec::new(),
383             resource_updates: ResourceUpdates::new(),
384             generate_frame: false,
385             use_scene_builder_thread: false,
386         }
387     }
388 }
389 
390 #[derive(Clone, Deserialize, Serialize)]
391 pub struct AddImage {
392     pub key: ImageKey,
393     pub descriptor: ImageDescriptor,
394     pub data: ImageData,
395     pub tiling: Option<TileSize>,
396 }
397 
398 #[derive(Clone, Deserialize, Serialize)]
399 pub struct UpdateImage {
400     pub key: ImageKey,
401     pub descriptor: ImageDescriptor,
402     pub data: ImageData,
403     pub dirty_rect: Option<DeviceUintRect>,
404 }
405 
406 #[derive(Clone, Deserialize, Serialize)]
407 pub enum AddFont {
408     Raw(FontKey, Vec<u8>, u32),
409     Native(FontKey, NativeFontHandle),
410 }
411 
412 #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
413 pub struct HitTestItem {
414     /// The pipeline that the display item that was hit belongs to.
415     pub pipeline: PipelineId,
416 
417     /// The tag of the hit display item.
418     pub tag: ItemTag,
419 
420     /// The hit point in the coordinate space of the "viewport" of the display item. The
421     /// viewport is the scroll node formed by the root reference frame of the display item's
422     /// pipeline.
423     pub point_in_viewport: LayoutPoint,
424 
425     /// The coordinates of the original hit test point relative to the origin of this item.
426     /// This is useful for calculating things like text offsets in the client.
427     pub point_relative_to_item: LayoutPoint,
428 }
429 
430 #[derive(Clone, Debug, Default, Deserialize, Serialize)]
431 pub struct HitTestResult {
432     pub items: Vec<HitTestItem>,
433 }
434 
435 bitflags! {
436     #[derive(Deserialize, Serialize)]
437     pub struct HitTestFlags: u8 {
438         const FIND_ALL = 0b00000001;
439         const POINT_RELATIVE_TO_PIPELINE_VIEWPORT = 0b00000010;
440     }
441 }
442 
443 #[derive(Clone, Deserialize, Serialize)]
444 pub struct AddFontInstance {
445     pub key: FontInstanceKey,
446     pub font_key: FontKey,
447     pub glyph_size: Au,
448     pub options: Option<FontInstanceOptions>,
449     pub platform_options: Option<FontInstancePlatformOptions>,
450     pub variations: Vec<FontVariation>,
451 }
452 
453 // Frame messages affect building the scene.
454 #[derive(Clone, Deserialize, Serialize)]
455 pub enum SceneMsg {
456     UpdateEpoch(PipelineId, Epoch),
457     SetPageZoom(ZoomFactor),
458     SetPinchZoom(ZoomFactor),
459     SetRootPipeline(PipelineId),
460     RemovePipeline(PipelineId),
461     SetDisplayList {
462         list_descriptor: BuiltDisplayListDescriptor,
463         epoch: Epoch,
464         pipeline_id: PipelineId,
465         background: Option<ColorF>,
466         viewport_size: LayoutSize,
467         content_size: LayoutSize,
468         preserve_frame_state: bool,
469     },
470     SetWindowParameters {
471         window_size: DeviceUintSize,
472         inner_rect: DeviceUintRect,
473         device_pixel_ratio: f32,
474     },
475 }
476 
477 // Frame messages affect frame generation (applied after building the scene).
478 #[derive(Clone, Deserialize, Serialize)]
479 pub enum FrameMsg {
480     UpdateEpoch(PipelineId, Epoch),
481     HitTest(Option<PipelineId>, WorldPoint, HitTestFlags, MsgSender<HitTestResult>),
482     SetPan(DeviceIntPoint),
483     EnableFrameOutput(PipelineId, bool),
484     Scroll(ScrollLocation, WorldPoint, ScrollEventPhase),
485     ScrollNodeWithId(LayoutPoint, ExternalScrollId, ScrollClamping),
486     TickScrollingBounce,
487     GetScrollNodeState(MsgSender<Vec<ScrollNodeState>>),
488     UpdateDynamicProperties(DynamicProperties),
489 }
490 
491 impl fmt::Debug for SceneMsg {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result492     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
493         f.write_str(match *self {
494             SceneMsg::UpdateEpoch(..) => "SceneMsg::UpdateEpoch",
495             SceneMsg::SetDisplayList { .. } => "SceneMsg::SetDisplayList",
496             SceneMsg::SetPageZoom(..) => "SceneMsg::SetPageZoom",
497             SceneMsg::SetPinchZoom(..) => "SceneMsg::SetPinchZoom",
498             SceneMsg::RemovePipeline(..) => "SceneMsg::RemovePipeline",
499             SceneMsg::SetWindowParameters { .. } => "SceneMsg::SetWindowParameters",
500             SceneMsg::SetRootPipeline(..) => "SceneMsg::SetRootPipeline",
501         })
502     }
503 }
504 
505 impl fmt::Debug for FrameMsg {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result506     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
507         f.write_str(match *self {
508             FrameMsg::UpdateEpoch(..) => "FrameMsg::UpdateEpoch",
509             FrameMsg::HitTest(..) => "FrameMsg::HitTest",
510             FrameMsg::SetPan(..) => "FrameMsg::SetPan",
511             FrameMsg::Scroll(..) => "FrameMsg::Scroll",
512             FrameMsg::ScrollNodeWithId(..) => "FrameMsg::ScrollNodeWithId",
513             FrameMsg::TickScrollingBounce => "FrameMsg::TickScrollingBounce",
514             FrameMsg::GetScrollNodeState(..) => "FrameMsg::GetScrollNodeState",
515             FrameMsg::EnableFrameOutput(..) => "FrameMsg::EnableFrameOutput",
516             FrameMsg::UpdateDynamicProperties(..) => "FrameMsg::UpdateDynamicProperties",
517         })
518     }
519 }
520 
521 bitflags!{
522     /// Bit flags for WR stages to store in a capture.
523     // Note: capturing `FRAME` without `SCENE` is not currently supported.
524     #[derive(Deserialize, Serialize)]
525     pub struct CaptureBits: u8 {
526         const SCENE = 0x1;
527         const FRAME = 0x2;
528     }
529 }
530 
531 bitflags!{
532     /// Mask for clearing caches in debug commands.
533     #[derive(Deserialize, Serialize)]
534     pub struct ClearCache: u8 {
535         const IMAGES = 0x1;
536         const GLYPHS = 0x2;
537         const GLYPH_DIMENSIONS = 0x4;
538         const RENDER_TASKS = 0x8;
539     }
540 }
541 
542 /// Information about a loaded capture of each document
543 /// that is returned by `RenderBackend`.
544 #[derive(Clone, Debug, Deserialize, Serialize)]
545 pub struct CapturedDocument {
546     pub document_id: DocumentId,
547     pub root_pipeline_id: Option<PipelineId>,
548     pub window_size: DeviceUintSize,
549 }
550 
551 #[derive(Clone, Deserialize, Serialize)]
552 pub enum DebugCommand {
553     /// Display the frame profiler on screen.
554     EnableProfiler(bool),
555     /// Display all texture cache pages on screen.
556     EnableTextureCacheDebug(bool),
557     /// Display intermediate render targets on screen.
558     EnableRenderTargetDebug(bool),
559     /// Display GPU timing results.
560     EnableGpuTimeQueries(bool),
561     /// Display GPU overdraw results
562     EnableGpuSampleQueries(bool),
563     /// Configure if dual-source blending is used, if available.
564     EnableDualSourceBlending(bool),
565     /// Fetch current documents and display lists.
566     FetchDocuments,
567     /// Fetch current passes and batches.
568     FetchPasses,
569     /// Fetch clip-scroll tree.
570     FetchClipScrollTree,
571     /// Fetch render tasks.
572     FetchRenderTasks,
573     /// Fetch screenshot.
574     FetchScreenshot,
575     /// Save a capture of all the documents state.
576     SaveCapture(PathBuf, CaptureBits),
577     /// Load a capture of all the documents state.
578     LoadCapture(PathBuf, MsgSender<CapturedDocument>),
579     /// Clear cached resources, forcing them to be re-uploaded from templates.
580     ClearCaches(ClearCache),
581     /// Invalidate GPU cache, forcing the update from the CPU mirror.
582     InvalidateGpuCache,
583 }
584 
585 #[derive(Clone, Deserialize, Serialize)]
586 pub enum ApiMsg {
587     /// Add/remove/update images and fonts.
588     UpdateResources(ResourceUpdates),
589     /// Gets the glyph dimensions
590     GetGlyphDimensions(
591         FontInstanceKey,
592         Vec<GlyphKey>,
593         MsgSender<Vec<Option<GlyphDimensions>>>,
594     ),
595     /// Gets the glyph indices from a string
596     GetGlyphIndices(FontKey, String, MsgSender<Vec<Option<u32>>>),
597     /// Adds a new document namespace.
598     CloneApi(MsgSender<IdNamespace>),
599     /// Adds a new document with given initial size.
600     AddDocument(DocumentId, DeviceUintSize, DocumentLayer),
601     /// A message targeted at a particular document.
602     UpdateDocument(DocumentId, TransactionMsg),
603     /// Deletes an existing document.
604     DeleteDocument(DocumentId),
605     /// An opaque handle that must be passed to the render notifier. It is used by Gecko
606     /// to forward gecko-specific messages to the render thread preserving the ordering
607     /// within the other messages.
608     ExternalEvent(ExternalEvent),
609     /// Removes all resources associated with a namespace.
610     ClearNamespace(IdNamespace),
611     /// Flush from the caches anything that isn't necessary, to free some memory.
612     MemoryPressure,
613     /// Change debugging options.
614     DebugCommand(DebugCommand),
615     /// Wakes the render backend's event loop up. Needed when an event is communicated
616     /// through another channel.
617     WakeUp,
618     ShutDown,
619 }
620 
621 impl fmt::Debug for ApiMsg {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result622     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
623         f.write_str(match *self {
624             ApiMsg::UpdateResources(..) => "ApiMsg::UpdateResources",
625             ApiMsg::GetGlyphDimensions(..) => "ApiMsg::GetGlyphDimensions",
626             ApiMsg::GetGlyphIndices(..) => "ApiMsg::GetGlyphIndices",
627             ApiMsg::CloneApi(..) => "ApiMsg::CloneApi",
628             ApiMsg::AddDocument(..) => "ApiMsg::AddDocument",
629             ApiMsg::UpdateDocument(..) => "ApiMsg::UpdateDocument",
630             ApiMsg::DeleteDocument(..) => "ApiMsg::DeleteDocument",
631             ApiMsg::ExternalEvent(..) => "ApiMsg::ExternalEvent",
632             ApiMsg::ClearNamespace(..) => "ApiMsg::ClearNamespace",
633             ApiMsg::MemoryPressure => "ApiMsg::MemoryPressure",
634             ApiMsg::DebugCommand(..) => "ApiMsg::DebugCommand",
635             ApiMsg::ShutDown => "ApiMsg::ShutDown",
636             ApiMsg::WakeUp => "ApiMsg::WakeUp",
637         })
638     }
639 }
640 
641 #[repr(C)]
642 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
643 pub struct Epoch(pub u32);
644 
645 impl Epoch {
invalid() -> Epoch646     pub fn invalid() -> Epoch {
647         Epoch(u32::MAX)
648     }
649 }
650 
651 #[repr(C)]
652 #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
653 pub struct IdNamespace(pub u32);
654 
655 #[repr(C)]
656 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
657 pub struct DocumentId(pub IdNamespace, pub u32);
658 
659 /// This type carries no valuable semantics for WR. However, it reflects the fact that
660 /// clients (Servo) may generate pipelines by different semi-independent sources.
661 /// These pipelines still belong to the same `IdNamespace` and the same `DocumentId`.
662 /// Having this extra Id field enables them to generate `PipelineId` without collision.
663 pub type PipelineSourceId = u32;
664 
665 /// From the point of view of WR, `PipelineId` is completely opaque and generic as long as
666 /// it's clonable, serializable, comparable, and hashable.
667 #[repr(C)]
668 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
669 pub struct PipelineId(pub PipelineSourceId, pub u32);
670 
671 impl PipelineId {
dummy() -> Self672     pub fn dummy() -> Self {
673         PipelineId(0, 0)
674     }
675 }
676 
677 
678 #[repr(C)]
679 #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
680 pub struct ResourceId(pub u32);
681 
682 /// An opaque pointer-sized value.
683 #[repr(C)]
684 #[derive(Clone, Deserialize, Serialize)]
685 pub struct ExternalEvent {
686     raw: usize,
687 }
688 
689 unsafe impl Send for ExternalEvent {}
690 
691 impl ExternalEvent {
from_raw(raw: usize) -> Self692     pub fn from_raw(raw: usize) -> Self {
693         ExternalEvent { raw: raw }
694     }
695     /// Consumes self to make it obvious that the event should be forwarded only once.
unwrap(self) -> usize696     pub fn unwrap(self) -> usize {
697         self.raw
698     }
699 }
700 
701 #[derive(Clone, Deserialize, Serialize)]
702 pub enum ScrollClamping {
703     ToContentBounds,
704     NoClamping,
705 }
706 
707 #[derive(Clone, Deserialize, Serialize)]
708 pub struct RenderApiSender {
709     api_sender: MsgSender<ApiMsg>,
710     payload_sender: PayloadSender,
711 }
712 
713 impl RenderApiSender {
new(api_sender: MsgSender<ApiMsg>, payload_sender: PayloadSender) -> Self714     pub fn new(api_sender: MsgSender<ApiMsg>, payload_sender: PayloadSender) -> Self {
715         RenderApiSender {
716             api_sender,
717             payload_sender,
718         }
719     }
720 
721     /// Creates a new resource API object with a dedicated namespace.
create_api(&self) -> RenderApi722     pub fn create_api(&self) -> RenderApi {
723         let (sync_tx, sync_rx) =
724             channel::msg_channel().expect("Failed to create channel");
725         let msg = ApiMsg::CloneApi(sync_tx);
726         self.api_sender.send(msg).expect("Failed to send CloneApi message");
727         let namespace_id = match sync_rx.recv() {
728             Ok(id) => id,
729             Err(e) => {
730                 // This is used to discover the underlying cause of https://github.com/servo/servo/issues/13480.
731                 let webrender_is_alive = self.api_sender.send(ApiMsg::WakeUp);
732                 if webrender_is_alive.is_err() {
733                     panic!("Webrender was shut down before processing CloneApi: {}", e);
734                 } else {
735                     panic!("CloneApi message response was dropped while Webrender was still alive: {}", e);
736                 }
737             }
738         };
739         RenderApi {
740             api_sender: self.api_sender.clone(),
741             payload_sender: self.payload_sender.clone(),
742             namespace_id: namespace_id,
743             next_id: Cell::new(ResourceId(0)),
744         }
745     }
746 }
747 
748 pub struct RenderApi {
749     api_sender: MsgSender<ApiMsg>,
750     payload_sender: PayloadSender,
751     namespace_id: IdNamespace,
752     next_id: Cell<ResourceId>,
753 }
754 
755 impl RenderApi {
get_namespace_id(&self) -> IdNamespace756     pub fn get_namespace_id(&self) -> IdNamespace {
757         self.namespace_id
758     }
759 
clone_sender(&self) -> RenderApiSender760     pub fn clone_sender(&self) -> RenderApiSender {
761         RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
762     }
763 
add_document(&self, initial_size: DeviceUintSize, layer: DocumentLayer) -> DocumentId764     pub fn add_document(&self, initial_size: DeviceUintSize, layer: DocumentLayer) -> DocumentId {
765         let new_id = self.next_unique_id();
766         let document_id = DocumentId(self.namespace_id, new_id);
767 
768         let msg = ApiMsg::AddDocument(document_id, initial_size, layer);
769         self.api_sender.send(msg).unwrap();
770 
771         document_id
772     }
773 
delete_document(&self, document_id: DocumentId)774     pub fn delete_document(&self, document_id: DocumentId) {
775         let msg = ApiMsg::DeleteDocument(document_id);
776         self.api_sender.send(msg).unwrap();
777     }
778 
generate_font_key(&self) -> FontKey779     pub fn generate_font_key(&self) -> FontKey {
780         let new_id = self.next_unique_id();
781         FontKey::new(self.namespace_id, new_id)
782     }
783 
generate_font_instance_key(&self) -> FontInstanceKey784     pub fn generate_font_instance_key(&self) -> FontInstanceKey {
785         let new_id = self.next_unique_id();
786         FontInstanceKey::new(self.namespace_id, new_id)
787     }
788 
789     /// Gets the dimensions for the supplied glyph keys
790     ///
791     /// Note: Internally, the internal texture cache doesn't store
792     /// 'empty' textures (height or width = 0)
793     /// This means that glyph dimensions e.g. for spaces (' ') will mostly be None.
get_glyph_dimensions( &self, font: FontInstanceKey, glyph_keys: Vec<GlyphKey>, ) -> Vec<Option<GlyphDimensions>>794     pub fn get_glyph_dimensions(
795         &self,
796         font: FontInstanceKey,
797         glyph_keys: Vec<GlyphKey>,
798     ) -> Vec<Option<GlyphDimensions>> {
799         let (tx, rx) = channel::msg_channel().unwrap();
800         let msg = ApiMsg::GetGlyphDimensions(font, glyph_keys, tx);
801         self.api_sender.send(msg).unwrap();
802         rx.recv().unwrap()
803     }
804 
805     /// Gets the glyph indices for the supplied string. These
806     /// can be used to construct GlyphKeys.
get_glyph_indices(&self, font_key: FontKey, text: &str) -> Vec<Option<u32>>807     pub fn get_glyph_indices(&self, font_key: FontKey, text: &str) -> Vec<Option<u32>> {
808         let (tx, rx) = channel::msg_channel().unwrap();
809         let msg = ApiMsg::GetGlyphIndices(font_key, text.to_string(), tx);
810         self.api_sender.send(msg).unwrap();
811         rx.recv().unwrap()
812     }
813 
814     /// Creates an `ImageKey`.
generate_image_key(&self) -> ImageKey815     pub fn generate_image_key(&self) -> ImageKey {
816         let new_id = self.next_unique_id();
817         ImageKey::new(self.namespace_id, new_id)
818     }
819 
820     /// Add/remove/update resources such as images and fonts.
update_resources(&self, resources: ResourceUpdates)821     pub fn update_resources(&self, resources: ResourceUpdates) {
822         if resources.updates.is_empty() {
823             return;
824         }
825         self.api_sender
826             .send(ApiMsg::UpdateResources(resources))
827             .unwrap();
828     }
829 
send_external_event(&self, evt: ExternalEvent)830     pub fn send_external_event(&self, evt: ExternalEvent) {
831         let msg = ApiMsg::ExternalEvent(evt);
832         self.api_sender.send(msg).unwrap();
833     }
834 
notify_memory_pressure(&self)835     pub fn notify_memory_pressure(&self) {
836         self.api_sender.send(ApiMsg::MemoryPressure).unwrap();
837     }
838 
shut_down(&self)839     pub fn shut_down(&self) {
840         self.api_sender.send(ApiMsg::ShutDown).unwrap();
841     }
842 
843     /// Create a new unique key that can be used for
844     /// animated property bindings.
generate_property_binding_key<T: Copy>(&self) -> PropertyBindingKey<T>845     pub fn generate_property_binding_key<T: Copy>(&self) -> PropertyBindingKey<T> {
846         let new_id = self.next_unique_id();
847         PropertyBindingKey {
848             id: PropertyBindingId {
849                 namespace: self.namespace_id,
850                 uid: new_id,
851             },
852             _phantom: PhantomData,
853         }
854     }
855 
856     #[inline]
next_unique_id(&self) -> u32857     fn next_unique_id(&self) -> u32 {
858         let ResourceId(id) = self.next_id.get();
859         self.next_id.set(ResourceId(id + 1));
860         id
861     }
862 
863     // For use in Wrench only
864     #[doc(hidden)]
send_message(&self, msg: ApiMsg)865     pub fn send_message(&self, msg: ApiMsg) {
866         self.api_sender.send(msg).unwrap();
867     }
868 
869     // For use in Wrench only
870     #[doc(hidden)]
send_payload(&self, data: &[u8])871     pub fn send_payload(&self, data: &[u8]) {
872         self.payload_sender
873             .send_payload(Payload::from_data(data))
874             .unwrap();
875     }
876 
877     /// A helper method to send document messages.
send_scene_msg(&self, document_id: DocumentId, msg: SceneMsg)878     fn send_scene_msg(&self, document_id: DocumentId, msg: SceneMsg) {
879         // This assertion fails on Servo use-cases, because it creates different
880         // `RenderApi` instances for layout and compositor.
881         //assert_eq!(document_id.0, self.namespace_id);
882         self.api_sender
883             .send(ApiMsg::UpdateDocument(document_id, TransactionMsg::scene_message(msg)))
884             .unwrap()
885     }
886 
887     /// A helper method to send document messages.
send_frame_msg(&self, document_id: DocumentId, msg: FrameMsg)888     fn send_frame_msg(&self, document_id: DocumentId, msg: FrameMsg) {
889         // This assertion fails on Servo use-cases, because it creates different
890         // `RenderApi` instances for layout and compositor.
891         //assert_eq!(document_id.0, self.namespace_id);
892         self.api_sender
893             .send(ApiMsg::UpdateDocument(document_id, TransactionMsg::frame_message(msg)))
894             .unwrap()
895     }
896 
send_transaction(&self, document_id: DocumentId, transaction: Transaction)897     pub fn send_transaction(&self, document_id: DocumentId, transaction: Transaction) {
898         let (msg, payloads) = transaction.finalize();
899         for payload in payloads {
900             self.payload_sender.send_payload(payload).unwrap();
901         }
902         self.api_sender.send(ApiMsg::UpdateDocument(document_id, msg)).unwrap();
903     }
904 
905     /// Does a hit test on display items in the specified document, at the given
906     /// point. If a pipeline_id is specified, it is used to further restrict the
907     /// hit results so that only items inside that pipeline are matched. If the
908     /// HitTestFlags argument contains the FIND_ALL flag, then the vector of hit
909     /// results will contain all display items that match, ordered from front
910     /// to back.
hit_test(&self, document_id: DocumentId, pipeline_id: Option<PipelineId>, point: WorldPoint, flags: HitTestFlags) -> HitTestResult911     pub fn hit_test(&self,
912                     document_id: DocumentId,
913                     pipeline_id: Option<PipelineId>,
914                     point: WorldPoint,
915                     flags: HitTestFlags)
916                     -> HitTestResult {
917         let (tx, rx) = channel::msg_channel().unwrap();
918 
919         self.send_frame_msg(
920             document_id,
921             FrameMsg::HitTest(pipeline_id, point, flags, tx)
922         );
923         rx.recv().unwrap()
924     }
925 
set_window_parameters( &self, document_id: DocumentId, window_size: DeviceUintSize, inner_rect: DeviceUintRect, device_pixel_ratio: f32, )926     pub fn set_window_parameters(
927         &self,
928         document_id: DocumentId,
929         window_size: DeviceUintSize,
930         inner_rect: DeviceUintRect,
931         device_pixel_ratio: f32,
932     ) {
933         self.send_scene_msg(
934             document_id,
935             SceneMsg::SetWindowParameters { window_size, inner_rect, device_pixel_ratio, },
936         );
937     }
938 
get_scroll_node_state(&self, document_id: DocumentId) -> Vec<ScrollNodeState>939     pub fn get_scroll_node_state(&self, document_id: DocumentId) -> Vec<ScrollNodeState> {
940         let (tx, rx) = channel::msg_channel().unwrap();
941         self.send_frame_msg(document_id, FrameMsg::GetScrollNodeState(tx));
942         rx.recv().unwrap()
943     }
944 
945     /// Save a capture of the current frame state for debugging.
save_capture(&self, path: PathBuf, bits: CaptureBits)946     pub fn save_capture(&self, path: PathBuf, bits: CaptureBits) {
947         let msg = ApiMsg::DebugCommand(DebugCommand::SaveCapture(path, bits));
948         self.send_message(msg);
949     }
950 
951     /// Load a capture of the current frame state for debugging.
load_capture(&self, path: PathBuf) -> Vec<CapturedDocument>952     pub fn load_capture(&self, path: PathBuf) -> Vec<CapturedDocument> {
953         let (tx, rx) = channel::msg_channel().unwrap();
954         let msg = ApiMsg::DebugCommand(DebugCommand::LoadCapture(path, tx));
955         self.send_message(msg);
956 
957         let mut documents = Vec::new();
958         while let Ok(captured_doc) = rx.recv() {
959             documents.push(captured_doc);
960         }
961         documents
962     }
963 
send_debug_cmd(&self, cmd: DebugCommand)964     pub fn send_debug_cmd(&self, cmd: DebugCommand) {
965         let msg = ApiMsg::DebugCommand(cmd);
966         self.send_message(msg);
967     }
968 }
969 
970 impl Drop for RenderApi {
drop(&mut self)971     fn drop(&mut self) {
972         let msg = ApiMsg::ClearNamespace(self.namespace_id);
973         let _ = self.api_sender.send(msg);
974     }
975 }
976 
977 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
978 pub enum ScrollEventPhase {
979     /// The user started scrolling.
980     Start,
981     /// The user performed a scroll. The Boolean flag indicates whether the user's fingers are
982     /// down, if a touchpad is in use. (If false, the event is a touchpad fling.)
983     Move(bool),
984     /// The user ended scrolling.
985     End,
986 }
987 
988 #[derive(Clone, Deserialize, Serialize)]
989 pub struct ScrollNodeState {
990     pub id: ExternalScrollId,
991     pub scroll_offset: LayoutVector2D,
992 }
993 
994 #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
995 pub enum ScrollLocation {
996     /// Scroll by a certain amount.
997     Delta(LayoutVector2D),
998     /// Scroll to very top of element.
999     Start,
1000     /// Scroll to very bottom of element.
1001     End,
1002 }
1003 
1004 /// Represents a zoom factor.
1005 #[derive(Clone, Copy, Serialize, Deserialize, Debug)]
1006 pub struct ZoomFactor(f32);
1007 
1008 impl ZoomFactor {
1009     /// Construct a new zoom factor.
new(scale: f32) -> ZoomFactor1010     pub fn new(scale: f32) -> ZoomFactor {
1011         ZoomFactor(scale)
1012     }
1013 
1014     /// Get the zoom factor as an untyped float.
get(&self) -> f321015     pub fn get(&self) -> f32 {
1016         self.0
1017     }
1018 }
1019 
1020 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Eq, Hash)]
1021 pub struct PropertyBindingId {
1022     namespace: IdNamespace,
1023     uid: u32,
1024 }
1025 
1026 impl PropertyBindingId {
new(value: u64) -> Self1027     pub fn new(value: u64) -> Self {
1028         PropertyBindingId {
1029             namespace: IdNamespace((value >> 32) as u32),
1030             uid: value as u32,
1031         }
1032     }
1033 }
1034 
1035 /// A unique key that is used for connecting animated property
1036 /// values to bindings in the display list.
1037 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
1038 pub struct PropertyBindingKey<T> {
1039     pub id: PropertyBindingId,
1040     _phantom: PhantomData<T>,
1041 }
1042 
1043 /// Construct a property value from a given key and value.
1044 impl<T: Copy> PropertyBindingKey<T> {
with(&self, value: T) -> PropertyValue<T>1045     pub fn with(&self, value: T) -> PropertyValue<T> {
1046         PropertyValue { key: *self, value }
1047     }
1048 }
1049 
1050 impl<T> PropertyBindingKey<T> {
new(value: u64) -> Self1051     pub fn new(value: u64) -> Self {
1052         PropertyBindingKey {
1053             id: PropertyBindingId::new(value),
1054             _phantom: PhantomData,
1055         }
1056     }
1057 }
1058 
1059 /// A binding property can either be a specific value
1060 /// (the normal, non-animated case) or point to a binding location
1061 /// to fetch the current value from.
1062 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
1063 pub enum PropertyBinding<T> {
1064     Value(T),
1065     Binding(PropertyBindingKey<T>),
1066 }
1067 
1068 impl<T> From<T> for PropertyBinding<T> {
from(value: T) -> PropertyBinding<T>1069     fn from(value: T) -> PropertyBinding<T> {
1070         PropertyBinding::Value(value)
1071     }
1072 }
1073 
1074 impl<T> From<PropertyBindingKey<T>> for PropertyBinding<T> {
from(key: PropertyBindingKey<T>) -> PropertyBinding<T>1075     fn from(key: PropertyBindingKey<T>) -> PropertyBinding<T> {
1076         PropertyBinding::Binding(key)
1077     }
1078 }
1079 
1080 /// The current value of an animated property. This is
1081 /// supplied by the calling code.
1082 #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
1083 pub struct PropertyValue<T> {
1084     pub key: PropertyBindingKey<T>,
1085     pub value: T,
1086 }
1087 
1088 /// When using `generate_frame()`, a list of `PropertyValue` structures
1089 /// can optionally be supplied to provide the current value of any
1090 /// animated properties.
1091 #[derive(Clone, Deserialize, Serialize, Debug)]
1092 pub struct DynamicProperties {
1093     pub transforms: Vec<PropertyValue<LayoutTransform>>,
1094     pub floats: Vec<PropertyValue<f32>>,
1095 }
1096 
1097 pub trait RenderNotifier: Send {
clone(&self) -> Box<RenderNotifier>1098     fn clone(&self) -> Box<RenderNotifier>;
wake_up(&self)1099     fn wake_up(&self);
new_document_ready(&self, DocumentId, scrolled: bool, composite_needed: bool)1100     fn new_document_ready(&self, DocumentId, scrolled: bool, composite_needed: bool);
external_event(&self, _evt: ExternalEvent)1101     fn external_event(&self, _evt: ExternalEvent) {
1102         unimplemented!()
1103     }
shut_down(&self)1104     fn shut_down(&self) {}
1105 }
1106