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