render_api.rs (56615B)
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 #![deny(missing_docs)] 6 7 use std::cell::Cell; 8 use std::fmt; 9 use std::marker::PhantomData; 10 use std::path::PathBuf; 11 use std::sync::Arc; 12 use std::u32; 13 use api::{MinimapData, SnapshotImageKey}; 14 use crate::api::channel::{Sender, single_msg_channel, unbounded_channel}; 15 use crate::api::{BuiltDisplayList, IdNamespace, ExternalScrollId, Parameter, BoolParameter}; 16 use crate::api::{FontKey, FontInstanceKey, NativeFontHandle}; 17 use crate::api::{BlobImageData, BlobImageKey, ImageData, ImageDescriptor, ImageKey, Epoch, QualitySettings}; 18 use crate::api::{BlobImageParams, BlobImageRequest, BlobImageResult, AsyncBlobImageRasterizer, BlobImageHandler}; 19 use crate::api::{DocumentId, PipelineId, PropertyBindingId, PropertyBindingKey, ExternalEvent}; 20 use crate::api::{HitTestResult, HitTesterRequest, ApiHitTester, PropertyValue, DynamicProperties}; 21 use crate::api::{SampledScrollOffset, TileSize, NotificationRequest, DebugFlags}; 22 use crate::api::{GlyphDimensionRequest, GlyphIndexRequest, GlyphIndex, GlyphDimensions}; 23 use crate::api::{FontInstanceOptions, FontInstancePlatformOptions, FontVariation, RenderReasons}; 24 use crate::api::DEFAULT_TILE_SIZE; 25 use crate::api::units::*; 26 use crate::api_resources::ApiResources; 27 use glyph_rasterizer::SharedFontResources; 28 use crate::scene_builder_thread::{SceneBuilderRequest, SceneBuilderResult}; 29 use crate::intern::InterningMemoryReport; 30 use crate::profiler::{self, TransactionProfile}; 31 #[cfg(feature = "debugger")] 32 use crate::debugger::{DebugQuery, DebuggerClient}; 33 34 #[repr(C)] 35 #[derive(Clone, Copy, Debug)] 36 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] 37 struct ResourceId(pub u32); 38 39 /// Update of a persistent resource in WebRender. 40 /// 41 /// ResourceUpdate changes keep theirs effect across display list changes. 42 #[derive(Clone)] 43 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] 44 pub enum ResourceUpdate { 45 /// See `AddImage`. 46 AddImage(AddImage), 47 /// See `UpdateImage`. 48 UpdateImage(UpdateImage), 49 /// Delete an existing image resource. 50 /// 51 /// It is invalid to continue referring to the image key in any display list 52 /// in the transaction that contains the `DeleteImage` message and subsequent 53 /// transactions. 54 DeleteImage(ImageKey), 55 /// See `AddBlobImage`. 56 AddBlobImage(AddBlobImage), 57 /// See `UpdateBlobImage`. 58 UpdateBlobImage(UpdateBlobImage), 59 /// Delete existing blob image resource. 60 DeleteBlobImage(BlobImageKey), 61 /// See `AddBlobImage::visible_area`. 62 SetBlobImageVisibleArea(BlobImageKey, DeviceIntRect), 63 /// See `AddSnapshotImage`. 64 AddSnapshotImage(AddSnapshotImage), 65 /// See `AddSnapshotImage`. 66 DeleteSnapshotImage(SnapshotImageKey), 67 /// See `AddFont`. 68 AddFont(AddFont), 69 /// Deletes an already existing font resource. 70 /// 71 /// It is invalid to continue referring to the font key in any display list 72 /// in the transaction that contains the `DeleteImage` message and subsequent 73 /// transactions. 74 DeleteFont(FontKey), 75 /// See `AddFontInstance`. 76 AddFontInstance(AddFontInstance), 77 /// Deletes an already existing font instance resource. 78 /// 79 /// It is invalid to continue referring to the font instance in any display 80 /// list in the transaction that contains the `DeleteImage` message and 81 /// subsequent transactions. 82 DeleteFontInstance(FontInstanceKey), 83 } 84 85 impl fmt::Debug for ResourceUpdate { 86 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 87 match self { 88 ResourceUpdate::AddImage(ref i) => f.write_fmt(format_args!( 89 "ResourceUpdate::AddImage size({:?})", 90 &i.descriptor.size 91 )), 92 ResourceUpdate::UpdateImage(ref i) => f.write_fmt(format_args!( 93 "ResourceUpdate::UpdateImage size({:?})", 94 &i.descriptor.size 95 )), 96 ResourceUpdate::AddBlobImage(ref i) => f.write_fmt(format_args!( 97 "ResourceUFpdate::AddBlobImage size({:?})", 98 &i.descriptor.size 99 )), 100 ResourceUpdate::UpdateBlobImage(i) => f.write_fmt(format_args!( 101 "ResourceUpdate::UpdateBlobImage size({:?})", 102 &i.descriptor.size 103 )), 104 ResourceUpdate::DeleteImage(..) => f.write_str("ResourceUpdate::DeleteImage"), 105 ResourceUpdate::DeleteBlobImage(..) => f.write_str("ResourceUpdate::DeleteBlobImage"), 106 ResourceUpdate::SetBlobImageVisibleArea(..) => f.write_str("ResourceUpdate::SetBlobImageVisibleArea"), 107 ResourceUpdate::AddSnapshotImage(..) => f.write_str("ResourceUpdate::AddSnapshotImage"), 108 ResourceUpdate::DeleteSnapshotImage(..) => f.write_str("ResourceUpdate::DeleteSnapshotImage"), 109 ResourceUpdate::AddFont(..) => f.write_str("ResourceUpdate::AddFont"), 110 ResourceUpdate::DeleteFont(..) => f.write_str("ResourceUpdate::DeleteFont"), 111 ResourceUpdate::AddFontInstance(..) => f.write_str("ResourceUpdate::AddFontInstance"), 112 ResourceUpdate::DeleteFontInstance(..) => f.write_str("ResourceUpdate::DeleteFontInstance"), 113 } 114 } 115 } 116 117 /// Whether to generate a frame, and if so, an id that allows tracking this 118 /// transaction through the various frame stages. 119 #[derive(Clone, Debug)] 120 pub enum GenerateFrame { 121 /// Generate a frame if something changed. 122 Yes { 123 /// An id that allows tracking the frame transaction through the various 124 /// frame stages. Specified by the caller of generate_frame(). 125 id: u64, 126 /// If false, (a subset of) the frame will be rendered, but nothing will 127 /// be presented on the window. 128 present: bool, 129 /// This flag is used by Firefox to differentiate between frames that 130 /// participate or not in the frame throttling mechanism. 131 tracked: bool, 132 }, 133 /// Don't generate a frame even if something has changed. 134 No, 135 } 136 137 impl GenerateFrame { 138 /// 139 pub fn as_bool(&self) -> bool { 140 match self { 141 GenerateFrame::Yes { .. } => true, 142 GenerateFrame::No => false, 143 } 144 } 145 146 /// If false, a frame may be (partially) generated but it will not be 147 /// presented to the window. 148 pub fn present(&self) -> bool { 149 match self { 150 GenerateFrame::Yes { present, .. } => *present, 151 GenerateFrame::No => false, 152 } 153 } 154 155 /// This flag is used by Gecko to indicate whether the transaction 156 /// participates in frame throttling mechanisms. 157 pub fn tracked(&self) -> bool { 158 match self { 159 GenerateFrame::Yes { tracked, .. } => *tracked, 160 GenerateFrame::No => false, 161 } 162 } 163 164 /// Return the frame ID, if a frame is generated. 165 pub fn id(&self) -> Option<u64> { 166 match self { 167 GenerateFrame::Yes { id, .. } => Some(*id), 168 GenerateFrame::No => None, 169 } 170 } 171 } 172 173 /// A Transaction is a group of commands to apply atomically to a document. 174 /// 175 /// This mechanism ensures that: 176 /// - no other message can be interleaved between two commands that need to be applied together. 177 /// - no redundant work is performed if two commands in the same transaction cause the scene or 178 /// the frame to be rebuilt. 179 pub struct Transaction { 180 /// Operations affecting the scene (applied before scene building). 181 scene_ops: Vec<SceneMsg>, 182 /// Operations affecting the generation of frames (applied after scene building). 183 frame_ops: Vec<FrameMsg>, 184 185 notifications: Vec<NotificationRequest>, 186 187 /// Persistent resource updates to apply as part of this transaction. 188 pub resource_updates: Vec<ResourceUpdate>, 189 190 /// True if the transaction needs the scene building thread's attention. 191 /// False for things that can skip the scene builder, like APZ changes and 192 /// async images. 193 /// 194 /// Before this `Transaction` is converted to a `TransactionMsg`, we look 195 /// over its contents and set this if we're doing anything the scene builder 196 /// needs to know about, so this is only a default. 197 use_scene_builder_thread: bool, 198 199 /// Whether to generate a frame, and if so, an id that allows tracking this 200 /// transaction through the various frame stages. Specified by the caller of 201 /// generate_frame(). 202 generate_frame: GenerateFrame, 203 204 /// Time when this transaction was constructed. 205 creation_time: u64, 206 207 /// Set to true in order to force re-rendering even if WebRender can't internally 208 /// detect that something has changed. 209 pub invalidate_rendered_frame: bool, 210 211 low_priority: bool, 212 213 /// 214 pub render_reasons: RenderReasons, 215 } 216 217 impl Transaction { 218 /// Constructor. 219 pub fn new() -> Self { 220 Transaction { 221 scene_ops: Vec::new(), 222 frame_ops: Vec::new(), 223 resource_updates: Vec::new(), 224 notifications: Vec::new(), 225 use_scene_builder_thread: true, 226 generate_frame: GenerateFrame::No, 227 creation_time: zeitstempel::now(), 228 invalidate_rendered_frame: false, 229 low_priority: false, 230 render_reasons: RenderReasons::empty(), 231 } 232 } 233 234 /// Marks this transaction to allow it to skip going through the scene builder 235 /// thread. 236 /// 237 /// This is useful to avoid jank in transaction associated with animated 238 /// property updates, panning and zooming. 239 /// 240 /// Note that transactions that skip the scene builder thread can race ahead of 241 /// transactions that don't skip it. 242 pub fn skip_scene_builder(&mut self) { 243 self.use_scene_builder_thread = false; 244 } 245 246 /// Marks this transaction to enforce going through the scene builder thread. 247 pub fn use_scene_builder_thread(&mut self) { 248 self.use_scene_builder_thread = true; 249 } 250 251 /// Returns true if the transaction has no effect. 252 pub fn is_empty(&self) -> bool { 253 !self.generate_frame.as_bool() && 254 !self.invalidate_rendered_frame && 255 self.scene_ops.is_empty() && 256 self.frame_ops.is_empty() && 257 self.resource_updates.is_empty() && 258 self.notifications.is_empty() 259 } 260 261 /// Update a pipeline's epoch. 262 pub fn update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch) { 263 // We track epochs before and after scene building. 264 // This one will be applied to the pending scene right away: 265 self.scene_ops.push(SceneMsg::UpdateEpoch(pipeline_id, epoch)); 266 // And this one will be applied to the currently built scene at the end 267 // of the transaction (potentially long after the scene_ops one). 268 self.frame_ops.push(FrameMsg::UpdateEpoch(pipeline_id, epoch)); 269 // We could avoid the duplication here by storing the epoch updates in a 270 // separate array and let the render backend schedule the updates at the 271 // proper times, but it wouldn't make things simpler. 272 } 273 274 /// Sets the root pipeline. 275 /// 276 /// # Examples 277 /// 278 /// ``` 279 /// # use webrender::api::{PipelineId}; 280 /// # use webrender::api::units::{DeviceIntSize}; 281 /// # use webrender::render_api::{RenderApiSender, Transaction}; 282 /// # fn example() { 283 /// let pipeline_id = PipelineId(0, 0); 284 /// let mut txn = Transaction::new(); 285 /// txn.set_root_pipeline(pipeline_id); 286 /// # } 287 /// ``` 288 pub fn set_root_pipeline(&mut self, pipeline_id: PipelineId) { 289 self.scene_ops.push(SceneMsg::SetRootPipeline(pipeline_id)); 290 } 291 292 /// Removes data associated with a pipeline from the internal data structures. 293 /// If the specified `pipeline_id` is for the root pipeline, the root pipeline 294 /// is reset back to `None`. 295 pub fn remove_pipeline(&mut self, pipeline_id: PipelineId) { 296 self.scene_ops.push(SceneMsg::RemovePipeline(pipeline_id)); 297 } 298 299 /// Supplies a new frame to WebRender. 300 /// 301 /// Non-blocking, it notifies a worker process which processes the display list. 302 /// 303 /// Note: Scrolling doesn't require an own Frame. 304 /// 305 /// Arguments: 306 /// 307 /// * `epoch`: The unique Frame ID, monotonically increasing. 308 /// * `pipeline_id`: The ID of the pipeline that is supplying this display list. 309 /// * `display_list`: The root Display list used in this frame. 310 pub fn set_display_list( 311 &mut self, 312 epoch: Epoch, 313 (pipeline_id, mut display_list): (PipelineId, BuiltDisplayList), 314 ) { 315 display_list.set_send_time_ns(zeitstempel::now()); 316 self.scene_ops.push( 317 SceneMsg::SetDisplayList { 318 display_list, 319 epoch, 320 pipeline_id, 321 } 322 ); 323 } 324 325 /// Add a set of persistent resource updates to apply as part of this transaction. 326 pub fn update_resources(&mut self, mut resources: Vec<ResourceUpdate>) { 327 self.resource_updates.append(&mut resources); 328 } 329 330 // Note: Gecko uses this to get notified when a transaction that contains 331 // potentially long blob rasterization or scene build is ready to be rendered. 332 // so that the tab-switching integration can react adequately when tab 333 // switching takes too long. For this use case when matters is that the 334 // notification doesn't fire before scene building and blob rasterization. 335 336 /// Trigger a notification at a certain stage of the rendering pipeline. 337 /// 338 /// Not that notification requests are skipped during serialization, so is is 339 /// best to use them for synchronization purposes and not for things that could 340 /// affect the WebRender's state. 341 pub fn notify(&mut self, event: NotificationRequest) { 342 self.notifications.push(event); 343 } 344 345 /// Setup the output region in the framebuffer for a given document. 346 pub fn set_document_view( 347 &mut self, 348 device_rect: DeviceIntRect, 349 ) { 350 window_size_sanity_check(device_rect.size()); 351 self.scene_ops.push( 352 SceneMsg::SetDocumentView { 353 device_rect, 354 }, 355 ); 356 } 357 358 /// Set multiple scroll offsets with generations to the node identified by 359 /// the given external scroll id, the scroll offsets are relative to the 360 /// pre-scrolled offset for the scrolling layer. 361 pub fn set_scroll_offsets( 362 &mut self, 363 id: ExternalScrollId, 364 sampled_scroll_offsets: Vec<SampledScrollOffset>, 365 ) { 366 self.frame_ops.push(FrameMsg::SetScrollOffsets(id, sampled_scroll_offsets)); 367 } 368 369 /// Set the current quality / performance settings for this document. 370 pub fn set_quality_settings(&mut self, settings: QualitySettings) { 371 self.scene_ops.push(SceneMsg::SetQualitySettings { settings }); 372 } 373 374 /// 375 pub fn set_is_transform_async_zooming(&mut self, is_zooming: bool, animation_id: PropertyBindingId) { 376 self.frame_ops.push(FrameMsg::SetIsTransformAsyncZooming(is_zooming, animation_id)); 377 } 378 379 /// Specify data for APZ minimap debug overlay to be composited 380 pub fn set_minimap_data(&mut self, id: ExternalScrollId, minimap_data: MinimapData) { 381 self.frame_ops.push(FrameMsg::SetMinimapData(id, minimap_data)); 382 } 383 384 /// Generate a new frame. When it's done and a RenderNotifier has been set 385 /// in `webrender::Renderer`, [new_frame_ready()][notifier] gets called. 386 /// Note that the notifier is called even if the frame generation was a 387 /// no-op; the arguments passed to `new_frame_ready` will provide information 388 /// as to when happened. 389 /// 390 /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready 391 pub fn generate_frame(&mut self, id: u64, present: bool, tracked: bool, reasons: RenderReasons) { 392 self.generate_frame = GenerateFrame::Yes{ id, present, tracked }; 393 self.render_reasons |= reasons; 394 } 395 396 /// Invalidate rendered frame. It ensure that frame will be rendered during 397 /// next frame generation. WebRender could skip frame rendering if there 398 /// is no update. 399 /// But there are cases that needs to force rendering. 400 /// - Content of image is updated by reusing same ExternalImageId. 401 /// - Platform requests it if pixels become stale (like wakeup from standby). 402 pub fn invalidate_rendered_frame(&mut self, reasons: RenderReasons) { 403 self.invalidate_rendered_frame = true; 404 self.render_reasons |= reasons 405 } 406 407 /// Reset the list of animated property bindings that should be used to resolve 408 /// bindings in the current display list. 409 pub fn reset_dynamic_properties(&mut self) { 410 self.frame_ops.push(FrameMsg::ResetDynamicProperties); 411 } 412 413 /// Add to the list of animated property bindings that should be used to resolve 414 /// bindings in the current display list. 415 pub fn append_dynamic_properties(&mut self, properties: DynamicProperties) { 416 self.frame_ops.push(FrameMsg::AppendDynamicProperties(properties)); 417 } 418 419 /// Add to the list of animated property bindings that should be used to 420 /// resolve bindings in the current display list. This is a convenience method 421 /// so the caller doesn't have to figure out all the dynamic properties before 422 /// setting them on the transaction but can do them incrementally. 423 pub fn append_dynamic_transform_properties(&mut self, transforms: Vec<PropertyValue<LayoutTransform>>) { 424 self.frame_ops.push(FrameMsg::AppendDynamicTransformProperties(transforms)); 425 } 426 427 /// Consumes this object and just returns the frame ops. 428 pub fn get_frame_ops(self) -> Vec<FrameMsg> { 429 self.frame_ops 430 } 431 432 fn finalize(self, document_id: DocumentId) -> Box<TransactionMsg> { 433 Box::new(TransactionMsg { 434 document_id, 435 scene_ops: self.scene_ops, 436 frame_ops: self.frame_ops, 437 resource_updates: self.resource_updates, 438 notifications: self.notifications, 439 use_scene_builder_thread: self.use_scene_builder_thread, 440 generate_frame: self.generate_frame, 441 creation_time: Some(self.creation_time), 442 invalidate_rendered_frame: self.invalidate_rendered_frame, 443 low_priority: self.low_priority, 444 blob_rasterizer: None, 445 blob_requests: Vec::new(), 446 rasterized_blobs: Vec::new(), 447 profile: TransactionProfile::new(), 448 render_reasons: self.render_reasons, 449 }) 450 } 451 452 /// See `ResourceUpdate::AddImage`. 453 pub fn add_image( 454 &mut self, 455 key: ImageKey, 456 descriptor: ImageDescriptor, 457 data: ImageData, 458 tiling: Option<TileSize>, 459 ) { 460 self.resource_updates.push(ResourceUpdate::AddImage(AddImage { 461 key, 462 descriptor, 463 data, 464 tiling, 465 })); 466 } 467 468 /// See `ResourceUpdate::UpdateImage`. 469 pub fn update_image( 470 &mut self, 471 key: ImageKey, 472 descriptor: ImageDescriptor, 473 data: ImageData, 474 dirty_rect: &ImageDirtyRect, 475 ) { 476 self.resource_updates.push(ResourceUpdate::UpdateImage(UpdateImage { 477 key, 478 descriptor, 479 data, 480 dirty_rect: *dirty_rect, 481 })); 482 } 483 484 /// See `ResourceUpdate::DeleteImage`. 485 pub fn delete_image(&mut self, key: ImageKey) { 486 self.resource_updates.push(ResourceUpdate::DeleteImage(key)); 487 } 488 489 /// See `ResourceUpdate::AddBlobImage`. 490 pub fn add_blob_image( 491 &mut self, 492 key: BlobImageKey, 493 descriptor: ImageDescriptor, 494 data: Arc<BlobImageData>, 495 visible_rect: DeviceIntRect, 496 tile_size: Option<TileSize>, 497 ) { 498 self.resource_updates.push( 499 ResourceUpdate::AddBlobImage(AddBlobImage { 500 key, 501 descriptor, 502 data, 503 visible_rect, 504 tile_size: tile_size.unwrap_or(DEFAULT_TILE_SIZE), 505 }) 506 ); 507 } 508 509 /// See `ResourceUpdate::UpdateBlobImage`. 510 pub fn update_blob_image( 511 &mut self, 512 key: BlobImageKey, 513 descriptor: ImageDescriptor, 514 data: Arc<BlobImageData>, 515 visible_rect: DeviceIntRect, 516 dirty_rect: &BlobDirtyRect, 517 ) { 518 self.resource_updates.push( 519 ResourceUpdate::UpdateBlobImage(UpdateBlobImage { 520 key, 521 descriptor, 522 data, 523 visible_rect, 524 dirty_rect: *dirty_rect, 525 }) 526 ); 527 } 528 529 /// See `ResourceUpdate::DeleteBlobImage`. 530 pub fn delete_blob_image(&mut self, key: BlobImageKey) { 531 self.resource_updates.push(ResourceUpdate::DeleteBlobImage(key)); 532 } 533 534 /// See `ResourceUpdate::SetBlobImageVisibleArea`. 535 pub fn set_blob_image_visible_area(&mut self, key: BlobImageKey, area: DeviceIntRect) { 536 self.resource_updates.push(ResourceUpdate::SetBlobImageVisibleArea(key, area)); 537 } 538 539 /// See `ResourceUpdate::AddSnapshotImage`. 540 pub fn add_snapshot_image( 541 &mut self, 542 key: SnapshotImageKey, 543 ) { 544 self.resource_updates.push( 545 ResourceUpdate::AddSnapshotImage(AddSnapshotImage { key }) 546 ); 547 } 548 549 /// See `ResourceUpdate::DeleteSnapshotImage`. 550 pub fn delete_snapshot_image(&mut self, key: SnapshotImageKey) { 551 self.resource_updates.push(ResourceUpdate::DeleteSnapshotImage(key)); 552 } 553 554 /// See `ResourceUpdate::AddFont`. 555 pub fn add_raw_font(&mut self, key: FontKey, bytes: Vec<u8>, index: u32) { 556 self.resource_updates 557 .push(ResourceUpdate::AddFont(AddFont::Raw(key, Arc::new(bytes), index))); 558 } 559 560 /// See `ResourceUpdate::AddFont`. 561 pub fn add_native_font(&mut self, key: FontKey, native_handle: NativeFontHandle) { 562 self.resource_updates 563 .push(ResourceUpdate::AddFont(AddFont::Native(key, native_handle))); 564 } 565 566 /// See `ResourceUpdate::DeleteFont`. 567 pub fn delete_font(&mut self, key: FontKey) { 568 self.resource_updates.push(ResourceUpdate::DeleteFont(key)); 569 } 570 571 /// See `ResourceUpdate::AddFontInstance`. 572 pub fn add_font_instance( 573 &mut self, 574 key: FontInstanceKey, 575 font_key: FontKey, 576 glyph_size: f32, 577 options: Option<FontInstanceOptions>, 578 platform_options: Option<FontInstancePlatformOptions>, 579 variations: Vec<FontVariation>, 580 ) { 581 self.resource_updates 582 .push(ResourceUpdate::AddFontInstance(AddFontInstance { 583 key, 584 font_key, 585 glyph_size, 586 options, 587 platform_options, 588 variations, 589 })); 590 } 591 592 /// See `ResourceUpdate::DeleteFontInstance`. 593 pub fn delete_font_instance(&mut self, key: FontInstanceKey) { 594 self.resource_updates.push(ResourceUpdate::DeleteFontInstance(key)); 595 } 596 597 /// A hint that this transaction can be processed at a lower priority. High- 598 /// priority transactions can jump ahead of regular-priority transactions, 599 /// but both high- and regular-priority transactions are processed in order 600 /// relative to other transactions of the same priority. 601 pub fn set_low_priority(&mut self, low_priority: bool) { 602 self.low_priority = low_priority; 603 } 604 605 /// Returns whether this transaction is marked as low priority. 606 pub fn is_low_priority(&self) -> bool { 607 self.low_priority 608 } 609 610 /// Render a pipeline offscreen immediately without waiting for vsync 611 /// and without affecting the state of the current scene. 612 /// 613 /// Snapshotted stacking contexts will be persisted in the texture cache. 614 pub fn render_offscreen(&mut self, pipeline_id: PipelineId) { 615 self.scene_ops.push(SceneMsg::RenderOffscreen(pipeline_id)); 616 } 617 } 618 619 /// 620 pub struct DocumentTransaction { 621 /// 622 pub document_id: DocumentId, 623 /// 624 pub transaction: Transaction, 625 } 626 627 /// Represents a transaction in the format sent through the channel. 628 pub struct TransactionMsg { 629 /// 630 pub document_id: DocumentId, 631 /// Changes that require re-building the scene. 632 pub scene_ops: Vec<SceneMsg>, 633 /// Changes to animated properties that do not require re-building the scene. 634 pub frame_ops: Vec<FrameMsg>, 635 /// Updates to resources that persist across display lists. 636 pub resource_updates: Vec<ResourceUpdate>, 637 /// Whether to trigger frame building and rendering if something has changed. 638 pub generate_frame: GenerateFrame, 639 /// Creation time of this transaction. 640 pub creation_time: Option<u64>, 641 /// Whether to force frame building and rendering even if no changes are internally 642 /// observed. 643 pub invalidate_rendered_frame: bool, 644 /// Whether to enforce that this transaction go through the scene builder. 645 pub use_scene_builder_thread: bool, 646 /// 647 pub low_priority: bool, 648 649 /// Handlers to notify at certain points of the pipeline. 650 pub notifications: Vec<NotificationRequest>, 651 /// 652 pub blob_rasterizer: Option<Box<dyn AsyncBlobImageRasterizer>>, 653 /// 654 pub blob_requests: Vec<BlobImageParams>, 655 /// 656 pub rasterized_blobs: Vec<(BlobImageRequest, BlobImageResult)>, 657 /// Collect various data along the rendering pipeline to display it in the embedded profiler. 658 pub profile: TransactionProfile, 659 /// Keep track of who asks rendering to happen. 660 pub render_reasons: RenderReasons, 661 } 662 663 impl fmt::Debug for TransactionMsg { 664 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 665 writeln!(f, "threaded={}, genframe={:?}, invalidate={}, low_priority={}", 666 self.use_scene_builder_thread, 667 self.generate_frame, 668 self.invalidate_rendered_frame, 669 self.low_priority, 670 ).unwrap(); 671 for scene_op in &self.scene_ops { 672 writeln!(f, "\t\t{:?}", scene_op).unwrap(); 673 } 674 675 for frame_op in &self.frame_ops { 676 writeln!(f, "\t\t{:?}", frame_op).unwrap(); 677 } 678 679 for resource_update in &self.resource_updates { 680 writeln!(f, "\t\t{:?}", resource_update).unwrap(); 681 } 682 Ok(()) 683 } 684 } 685 686 impl TransactionMsg { 687 /// Returns true if this transaction has no effect. 688 pub fn is_empty(&self) -> bool { 689 !self.generate_frame.as_bool() && 690 !self.invalidate_rendered_frame && 691 self.scene_ops.is_empty() && 692 self.frame_ops.is_empty() && 693 self.resource_updates.is_empty() && 694 self.notifications.is_empty() 695 } 696 } 697 698 /// Creates an image resource with provided parameters. 699 /// 700 /// Must be matched with a `DeleteImage` at some point to prevent memory leaks. 701 #[derive(Clone)] 702 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] 703 pub struct AddImage { 704 /// A key to identify the image resource. 705 pub key: ImageKey, 706 /// Properties of the image. 707 pub descriptor: ImageDescriptor, 708 /// The pixels of the image. 709 pub data: ImageData, 710 /// An optional tiling scheme to apply when storing the image's data 711 /// on the GPU. Applies to both width and heights of the tiles. 712 /// 713 /// Note that WebRender may internally chose to tile large images 714 /// even if this member is set to `None`. 715 pub tiling: Option<TileSize>, 716 } 717 718 /// Updates an already existing image resource. 719 #[derive(Clone)] 720 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] 721 pub struct UpdateImage { 722 /// The key identfying the image resource to update. 723 pub key: ImageKey, 724 /// Properties of the image. 725 pub descriptor: ImageDescriptor, 726 /// The pixels of the image. 727 pub data: ImageData, 728 /// An optional dirty rect that lets WebRender optimize the amount of 729 /// data to transfer to the GPU. 730 /// 731 /// The data provided must still represent the entire image. 732 pub dirty_rect: ImageDirtyRect, 733 } 734 735 /// Creates a blob-image resource with provided parameters. 736 /// 737 /// Must be matched with a `DeleteImage` at some point to prevent memory leaks. 738 #[derive(Clone)] 739 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] 740 pub struct AddBlobImage { 741 /// A key to identify the blob-image resource. 742 pub key: BlobImageKey, 743 /// Properties of the image. 744 pub descriptor: ImageDescriptor, 745 /// The blob-image's serialized commands. 746 pub data: Arc<BlobImageData>, 747 /// The portion of the plane in the blob-image's internal coordinate 748 /// system that is stretched to fill the image display item. 749 /// 750 /// Unlike regular images, blob images are not limited in size. The 751 /// top-left corner of their internal coordinate system is also not 752 /// necessary at (0, 0). 753 /// This means that blob images can be updated to insert/remove content 754 /// in any direction to support panning and zooming. 755 pub visible_rect: DeviceIntRect, 756 /// The blob image's tile size to apply when rasterizing the blob-image 757 /// and when storing its rasterized data on the GPU. 758 /// Applies to both width and heights of the tiles. 759 /// 760 /// All blob images are tiled. 761 pub tile_size: TileSize, 762 } 763 764 /// Updates an already existing blob-image resource. 765 #[derive(Clone)] 766 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] 767 pub struct UpdateBlobImage { 768 /// The key identfying the blob-image resource to update. 769 pub key: BlobImageKey, 770 /// Properties of the image. 771 pub descriptor: ImageDescriptor, 772 /// The blob-image's serialized commands. 773 pub data: Arc<BlobImageData>, 774 /// See `AddBlobImage::visible_rect`. 775 pub visible_rect: DeviceIntRect, 776 /// An optional dirty rect that lets WebRender optimize the amount of 777 /// data to to rasterize and transfer to the GPU. 778 pub dirty_rect: BlobDirtyRect, 779 } 780 781 /// Creates a snapshot image resource. 782 /// 783 /// Must be matched with a `DeleteSnapshotImage` at some point to prevent memory leaks. 784 #[derive(Clone)] 785 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] 786 pub struct AddSnapshotImage { 787 /// The key identfying the snapshot resource. 788 pub key: SnapshotImageKey, 789 } 790 791 /// Creates a font resource. 792 /// 793 /// Must be matched with a corresponding `ResourceUpdate::DeleteFont` at some point to prevent 794 /// memory leaks. 795 #[derive(Clone)] 796 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] 797 pub enum AddFont { 798 /// 799 Raw(FontKey, Arc<Vec<u8>>, u32), 800 /// 801 Native(FontKey, NativeFontHandle), 802 } 803 804 /// Creates a font instance resource. 805 /// 806 /// Must be matched with a corresponding `DeleteFontInstance` at some point 807 /// to prevent memory leaks. 808 #[derive(Clone)] 809 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] 810 pub struct AddFontInstance { 811 /// A key to identify the font instance. 812 pub key: FontInstanceKey, 813 /// The font resource's key. 814 pub font_key: FontKey, 815 /// Glyph size in app units. 816 pub glyph_size: f32, 817 /// 818 pub options: Option<FontInstanceOptions>, 819 /// 820 pub platform_options: Option<FontInstancePlatformOptions>, 821 /// 822 pub variations: Vec<FontVariation>, 823 } 824 825 /// Frame messages affect building the scene. 826 pub enum SceneMsg { 827 /// 828 UpdateEpoch(PipelineId, Epoch), 829 /// 830 SetRootPipeline(PipelineId), 831 /// 832 RemovePipeline(PipelineId), 833 /// 834 SetDisplayList { 835 /// 836 display_list: BuiltDisplayList, 837 /// 838 epoch: Epoch, 839 /// 840 pipeline_id: PipelineId, 841 }, 842 /// Build a scene without affecting any retained state. 843 /// 844 /// Useful to render an offscreen scene in the background without affecting 845 /// what is currently displayed. 846 RenderOffscreen(PipelineId), 847 /// 848 SetDocumentView { 849 /// 850 device_rect: DeviceIntRect, 851 }, 852 /// Set the current quality / performance configuration for this document. 853 SetQualitySettings { 854 /// The set of available quality / performance config values. 855 settings: QualitySettings, 856 }, 857 } 858 859 /// Frame messages affect frame generation (applied after building the scene). 860 pub enum FrameMsg { 861 /// 862 UpdateEpoch(PipelineId, Epoch), 863 /// 864 HitTest(WorldPoint, Sender<HitTestResult>), 865 /// 866 RequestHitTester(Sender<Arc<dyn ApiHitTester>>), 867 /// 868 SetScrollOffsets(ExternalScrollId, Vec<SampledScrollOffset>), 869 /// 870 ResetDynamicProperties, 871 /// 872 AppendDynamicProperties(DynamicProperties), 873 /// 874 AppendDynamicTransformProperties(Vec<PropertyValue<LayoutTransform>>), 875 /// 876 SetIsTransformAsyncZooming(bool, PropertyBindingId), 877 /// 878 SetMinimapData(ExternalScrollId, MinimapData) 879 } 880 881 impl fmt::Debug for SceneMsg { 882 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 883 f.write_str(match *self { 884 SceneMsg::UpdateEpoch(..) => "SceneMsg::UpdateEpoch", 885 SceneMsg::SetDisplayList { .. } => "SceneMsg::SetDisplayList", 886 SceneMsg::RemovePipeline(..) => "SceneMsg::RemovePipeline", 887 SceneMsg::SetDocumentView { .. } => "SceneMsg::SetDocumentView", 888 SceneMsg::SetRootPipeline(..) => "SceneMsg::SetRootPipeline", 889 SceneMsg::SetQualitySettings { .. } => "SceneMsg::SetQualitySettings", 890 SceneMsg::RenderOffscreen(..) => "SceneMsg::BuildOffscreen", 891 }) 892 } 893 } 894 895 impl fmt::Debug for FrameMsg { 896 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 897 f.write_str(match *self { 898 FrameMsg::UpdateEpoch(..) => "FrameMsg::UpdateEpoch", 899 FrameMsg::HitTest(..) => "FrameMsg::HitTest", 900 FrameMsg::RequestHitTester(..) => "FrameMsg::RequestHitTester", 901 FrameMsg::SetScrollOffsets(..) => "FrameMsg::SetScrollOffsets", 902 FrameMsg::ResetDynamicProperties => "FrameMsg::ResetDynamicProperties", 903 FrameMsg::AppendDynamicProperties(..) => "FrameMsg::AppendDynamicProperties", 904 FrameMsg::AppendDynamicTransformProperties(..) => "FrameMsg::AppendDynamicTransformProperties", 905 FrameMsg::SetIsTransformAsyncZooming(..) => "FrameMsg::SetIsTransformAsyncZooming", 906 FrameMsg::SetMinimapData(..) => "FrameMsg::SetMinimapData", 907 }) 908 } 909 } 910 911 bitflags!{ 912 /// Bit flags for WR stages to store in a capture. 913 // Note: capturing `FRAME` without `SCENE` is not currently supported. 914 #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] 915 pub struct CaptureBits: u8 { 916 /// 917 const SCENE = 0x1; 918 /// 919 const FRAME = 0x2; 920 /// 921 const TILE_CACHE = 0x4; 922 /// 923 const EXTERNAL_RESOURCES = 0x8; 924 } 925 } 926 927 bitflags!{ 928 /// Mask for clearing caches in debug commands. 929 #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] 930 pub struct ClearCache: u8 { 931 /// 932 const IMAGES = 0b1; 933 /// 934 const GLYPHS = 0b10; 935 /// 936 const GLYPH_DIMENSIONS = 0b100; 937 /// 938 const RENDER_TASKS = 0b1000; 939 /// 940 const TEXTURE_CACHE = 0b10000; 941 /// Clear render target pool 942 const RENDER_TARGETS = 0b100000; 943 } 944 } 945 946 /// Information about a loaded capture of each document 947 /// that is returned by `RenderBackend`. 948 #[derive(Clone, Debug)] 949 pub struct CapturedDocument { 950 /// 951 pub document_id: DocumentId, 952 /// 953 pub root_pipeline_id: Option<PipelineId>, 954 } 955 956 /// Update of the state of built-in debugging facilities. 957 pub enum DebugCommand { 958 /// Sets the provided debug flags. 959 SetFlags(DebugFlags), 960 /// Get current debug flags 961 GetDebugFlags(Sender<DebugFlags>), 962 /// Enable/Disable render command logging. 963 SetRenderCommandLog(bool), 964 /// Save a capture of all the documents state. 965 SaveCapture(PathBuf, CaptureBits), 966 /// Load a capture of all the documents state. 967 LoadCapture(PathBuf, Option<(u32, u32)>, Sender<CapturedDocument>), 968 /// Start capturing a sequence of scene/frame changes. 969 StartCaptureSequence(PathBuf, CaptureBits), 970 /// Stop capturing a sequence of scene/frame changes. 971 StopCaptureSequence, 972 /// Clear cached resources, forcing them to be re-uploaded from templates. 973 ClearCaches(ClearCache), 974 /// Enable/disable native compositor usage 975 EnableNativeCompositor(bool), 976 /// Sets the maximum amount of existing batches to visit before creating a new one. 977 SetBatchingLookback(u32), 978 /// Causes the scene builder to pause for a given amount of milliseconds each time it 979 /// processes a transaction. 980 SimulateLongSceneBuild(u32), 981 /// Set an override tile size to use for picture caches 982 SetPictureTileSize(Option<DeviceIntSize>), 983 /// Set an override for max off-screen surface size 984 SetMaximumSurfaceSize(Option<usize>), 985 /// Generate a frame to force a redraw / recomposite 986 GenerateFrame, 987 #[cfg(feature = "debugger")] 988 /// Query internal information about WR 989 Query(DebugQuery), 990 #[cfg(feature = "debugger")] 991 /// Add a new profiler consumer 992 AddDebugClient(DebuggerClient), 993 } 994 995 /// Message sent by the `RenderApi` to the render backend thread. 996 pub enum ApiMsg { 997 /// Adds a new document namespace. 998 CloneApi(Sender<IdNamespace>), 999 /// Adds a new document namespace. 1000 CloneApiByClient(IdNamespace), 1001 /// Adds a new document with given initial size. 1002 AddDocument(DocumentId, DeviceIntSize), 1003 /// A message targeted at a particular document. 1004 UpdateDocuments(Vec<Box<TransactionMsg>>), 1005 /// Flush from the caches anything that isn't necessary, to free some memory. 1006 MemoryPressure, 1007 /// Collects a memory report. 1008 ReportMemory(Sender<Box<MemoryReport>>), 1009 /// Change debugging options. 1010 DebugCommand(DebugCommand), 1011 /// Message from the scene builder thread. 1012 SceneBuilderResult(SceneBuilderResult), 1013 } 1014 1015 impl fmt::Debug for ApiMsg { 1016 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1017 f.write_str(match *self { 1018 ApiMsg::CloneApi(..) => "ApiMsg::CloneApi", 1019 ApiMsg::CloneApiByClient(..) => "ApiMsg::CloneApiByClient", 1020 ApiMsg::AddDocument(..) => "ApiMsg::AddDocument", 1021 ApiMsg::UpdateDocuments(..) => "ApiMsg::UpdateDocuments", 1022 ApiMsg::MemoryPressure => "ApiMsg::MemoryPressure", 1023 ApiMsg::ReportMemory(..) => "ApiMsg::ReportMemory", 1024 ApiMsg::DebugCommand(..) => "ApiMsg::DebugCommand", 1025 ApiMsg::SceneBuilderResult(..) => "ApiMsg::SceneBuilderResult", 1026 }) 1027 } 1028 } 1029 1030 /// Allows the API to communicate with WebRender. 1031 /// 1032 /// This object is created along with the `Renderer` and it's main use from a 1033 /// user perspective is to create one or several `RenderApi` objects. 1034 pub struct RenderApiSender { 1035 api_sender: Sender<ApiMsg>, 1036 scene_sender: Sender<SceneBuilderRequest>, 1037 low_priority_scene_sender: Sender<SceneBuilderRequest>, 1038 blob_image_handler: Option<Box<dyn BlobImageHandler>>, 1039 fonts: SharedFontResources, 1040 } 1041 1042 impl RenderApiSender { 1043 /// Used internally by the `Renderer`. 1044 pub fn new( 1045 api_sender: Sender<ApiMsg>, 1046 scene_sender: Sender<SceneBuilderRequest>, 1047 low_priority_scene_sender: Sender<SceneBuilderRequest>, 1048 blob_image_handler: Option<Box<dyn BlobImageHandler>>, 1049 fonts: SharedFontResources, 1050 ) -> Self { 1051 RenderApiSender { 1052 api_sender, 1053 scene_sender, 1054 low_priority_scene_sender, 1055 blob_image_handler, 1056 fonts, 1057 } 1058 } 1059 1060 /// Creates a new resource API object with a dedicated namespace. 1061 pub fn create_api(&self) -> RenderApi { 1062 let (sync_tx, sync_rx) = single_msg_channel(); 1063 let msg = ApiMsg::CloneApi(sync_tx); 1064 self.api_sender.send(msg).expect("Failed to send CloneApi message"); 1065 let namespace_id = sync_rx.recv().expect("Failed to receive CloneApi reply"); 1066 RenderApi { 1067 api_sender: self.api_sender.clone(), 1068 scene_sender: self.scene_sender.clone(), 1069 low_priority_scene_sender: self.low_priority_scene_sender.clone(), 1070 namespace_id, 1071 next_id: Cell::new(ResourceId(0)), 1072 resources: ApiResources::new( 1073 self.blob_image_handler.as_ref().map(|handler| handler.create_similar()), 1074 self.fonts.clone(), 1075 ), 1076 } 1077 } 1078 1079 /// Creates a new resource API object with a dedicated namespace. 1080 /// Namespace id is allocated by client. 1081 /// 1082 /// The function could be used only when WebRenderOptions::namespace_alloc_by_client is true. 1083 /// When the option is true, create_api() could not be used to prevent namespace id conflict. 1084 pub fn create_api_by_client(&self, namespace_id: IdNamespace) -> RenderApi { 1085 let msg = ApiMsg::CloneApiByClient(namespace_id); 1086 self.api_sender.send(msg).expect("Failed to send CloneApiByClient message"); 1087 RenderApi { 1088 api_sender: self.api_sender.clone(), 1089 scene_sender: self.scene_sender.clone(), 1090 low_priority_scene_sender: self.low_priority_scene_sender.clone(), 1091 namespace_id, 1092 next_id: Cell::new(ResourceId(0)), 1093 resources: ApiResources::new( 1094 self.blob_image_handler.as_ref().map(|handler| handler.create_similar()), 1095 self.fonts.clone(), 1096 ), 1097 } 1098 } 1099 } 1100 1101 /// The main entry point to interact with WebRender. 1102 pub struct RenderApi { 1103 api_sender: Sender<ApiMsg>, 1104 scene_sender: Sender<SceneBuilderRequest>, 1105 low_priority_scene_sender: Sender<SceneBuilderRequest>, 1106 namespace_id: IdNamespace, 1107 next_id: Cell<ResourceId>, 1108 resources: ApiResources, 1109 } 1110 1111 impl RenderApi { 1112 /// Returns the namespace ID used by this API object. 1113 pub fn get_namespace_id(&self) -> IdNamespace { 1114 self.namespace_id 1115 } 1116 1117 /// Returns a clone of the API message sender for internal use 1118 #[allow(unused)] 1119 pub(crate) fn get_api_sender(&self) -> Sender<ApiMsg> { 1120 self.api_sender.clone() 1121 } 1122 1123 /// 1124 pub fn create_sender(&self) -> RenderApiSender { 1125 RenderApiSender::new( 1126 self.api_sender.clone(), 1127 self.scene_sender.clone(), 1128 self.low_priority_scene_sender.clone(), 1129 self.resources.blob_image_handler.as_ref().map(|handler| handler.create_similar()), 1130 self.resources.get_fonts(), 1131 ) 1132 } 1133 1134 /// Add a document to the WebRender instance. 1135 /// 1136 /// Instances can manage one or several documents (using the same render backend thread). 1137 /// Each document will internally correspond to a single scene, and scenes are made of 1138 /// one or several pipelines. 1139 pub fn add_document(&self, initial_size: DeviceIntSize) -> DocumentId { 1140 let new_id = self.next_unique_id(); 1141 self.add_document_with_id(initial_size, new_id) 1142 } 1143 1144 /// See `add_document` 1145 pub fn add_document_with_id(&self, 1146 initial_size: DeviceIntSize, 1147 id: u32) -> DocumentId { 1148 window_size_sanity_check(initial_size); 1149 1150 let document_id = DocumentId::new(self.namespace_id, id); 1151 1152 // We send this message to both the render backend and the scene builder instead of having 1153 // the scene builder thread forward it to the render backend as we do elswhere. This is because 1154 // some transactions can skip the scene builder thread and we want to avoid them arriving before 1155 // the render backend knows about the existence of the corresponding document id. 1156 // It may not be necessary, though. 1157 self.api_sender.send( 1158 ApiMsg::AddDocument(document_id, initial_size) 1159 ).unwrap(); 1160 self.scene_sender.send( 1161 SceneBuilderRequest::AddDocument(document_id, initial_size) 1162 ).unwrap(); 1163 1164 document_id 1165 } 1166 1167 /// Delete a document. 1168 pub fn delete_document(&self, document_id: DocumentId) { 1169 self.low_priority_scene_sender.send( 1170 SceneBuilderRequest::DeleteDocument(document_id) 1171 ).unwrap(); 1172 } 1173 1174 /// Generate a new font key 1175 pub fn generate_font_key(&self) -> FontKey { 1176 let new_id = self.next_unique_id(); 1177 FontKey::new(self.namespace_id, new_id) 1178 } 1179 1180 /// Generate a new font instance key 1181 pub fn generate_font_instance_key(&self) -> FontInstanceKey { 1182 let new_id = self.next_unique_id(); 1183 FontInstanceKey::new(self.namespace_id, new_id) 1184 } 1185 1186 /// Gets the dimensions for the supplied glyph keys 1187 /// 1188 /// Note: Internally, the internal texture cache doesn't store 1189 /// 'empty' textures (height or width = 0) 1190 /// This means that glyph dimensions e.g. for spaces (' ') will mostly be None. 1191 pub fn get_glyph_dimensions( 1192 &self, 1193 key: FontInstanceKey, 1194 glyph_indices: Vec<GlyphIndex>, 1195 ) -> Vec<Option<GlyphDimensions>> { 1196 let (sender, rx) = single_msg_channel(); 1197 let msg = SceneBuilderRequest::GetGlyphDimensions(GlyphDimensionRequest { 1198 key, 1199 glyph_indices, 1200 sender 1201 }); 1202 self.low_priority_scene_sender.send(msg).unwrap(); 1203 rx.recv().unwrap() 1204 } 1205 1206 /// Gets the glyph indices for the supplied string. These 1207 /// can be used to construct GlyphKeys. 1208 pub fn get_glyph_indices(&self, key: FontKey, text: &str) -> Vec<Option<u32>> { 1209 let (sender, rx) = single_msg_channel(); 1210 let msg = SceneBuilderRequest::GetGlyphIndices(GlyphIndexRequest { 1211 key, 1212 text: text.to_string(), 1213 sender, 1214 }); 1215 self.low_priority_scene_sender.send(msg).unwrap(); 1216 rx.recv().unwrap() 1217 } 1218 1219 /// Creates an `ImageKey`. 1220 pub fn generate_image_key(&self) -> ImageKey { 1221 let new_id = self.next_unique_id(); 1222 ImageKey::new(self.namespace_id, new_id) 1223 } 1224 1225 /// Creates a `BlobImageKey`. 1226 pub fn generate_blob_image_key(&self) -> BlobImageKey { 1227 BlobImageKey(self.generate_image_key()) 1228 } 1229 1230 /// A Gecko-specific notification mechanism to get some code executed on the 1231 /// `Renderer`'s thread, mostly replaced by `NotificationHandler`. You should 1232 /// probably use the latter instead. 1233 pub fn send_external_event(&self, evt: ExternalEvent) { 1234 let msg = SceneBuilderRequest::ExternalEvent(evt); 1235 self.low_priority_scene_sender.send(msg).unwrap(); 1236 } 1237 1238 /// Notify WebRender that now is a good time to flush caches and release 1239 /// as much memory as possible. 1240 pub fn notify_memory_pressure(&self) { 1241 self.api_sender.send(ApiMsg::MemoryPressure).unwrap(); 1242 } 1243 1244 /// Synchronously requests memory report. 1245 pub fn report_memory(&self, _ops: malloc_size_of::MallocSizeOfOps) -> MemoryReport { 1246 let (tx, rx) = single_msg_channel(); 1247 self.api_sender.send(ApiMsg::ReportMemory(tx)).unwrap(); 1248 *rx.recv().unwrap() 1249 } 1250 1251 /// Update debugging flags. 1252 pub fn set_debug_flags(&mut self, flags: DebugFlags) { 1253 self.resources.set_debug_flags(flags); 1254 let cmd = DebugCommand::SetFlags(flags); 1255 self.api_sender.send(ApiMsg::DebugCommand(cmd)).unwrap(); 1256 self.scene_sender.send(SceneBuilderRequest ::SetFlags(flags)).unwrap(); 1257 self.low_priority_scene_sender.send(SceneBuilderRequest ::SetFlags(flags)).unwrap(); 1258 } 1259 1260 /// Stop RenderBackend's task until shut down 1261 pub fn stop_render_backend(&self) { 1262 self.low_priority_scene_sender.send(SceneBuilderRequest::StopRenderBackend).unwrap(); 1263 } 1264 1265 /// Shut the WebRender instance down. 1266 pub fn shut_down(&self, synchronously: bool) { 1267 if synchronously { 1268 let (tx, rx) = single_msg_channel(); 1269 self.low_priority_scene_sender.send(SceneBuilderRequest::ShutDown(Some(tx))).unwrap(); 1270 rx.recv().unwrap(); 1271 } else { 1272 self.low_priority_scene_sender.send(SceneBuilderRequest::ShutDown(None)).unwrap(); 1273 } 1274 } 1275 1276 /// Create a new unique key that can be used for 1277 /// animated property bindings. 1278 pub fn generate_property_binding_key<T: Copy>(&self) -> PropertyBindingKey<T> { 1279 let new_id = self.next_unique_id(); 1280 PropertyBindingKey { 1281 id: PropertyBindingId { 1282 namespace: self.namespace_id, 1283 uid: new_id, 1284 }, 1285 _phantom: PhantomData, 1286 } 1287 } 1288 1289 #[inline] 1290 fn next_unique_id(&self) -> u32 { 1291 let ResourceId(id) = self.next_id.get(); 1292 self.next_id.set(ResourceId(id + 1)); 1293 id 1294 } 1295 1296 // For use in Wrench only 1297 #[doc(hidden)] 1298 pub fn send_message(&self, msg: ApiMsg) { 1299 self.api_sender.send(msg).unwrap(); 1300 } 1301 1302 /// Creates a transaction message from a single frame message. 1303 fn frame_message(&self, msg: FrameMsg, document_id: DocumentId) -> Box<TransactionMsg> { 1304 Box::new(TransactionMsg { 1305 document_id, 1306 scene_ops: Vec::new(), 1307 frame_ops: vec![msg], 1308 resource_updates: Vec::new(), 1309 notifications: Vec::new(), 1310 generate_frame: GenerateFrame::No, 1311 creation_time: None, 1312 invalidate_rendered_frame: false, 1313 use_scene_builder_thread: false, 1314 low_priority: false, 1315 blob_rasterizer: None, 1316 blob_requests: Vec::new(), 1317 rasterized_blobs: Vec::new(), 1318 profile: TransactionProfile::new(), 1319 render_reasons: RenderReasons::empty(), 1320 }) 1321 } 1322 1323 /// A helper method to send document messages. 1324 fn send_frame_msg(&self, document_id: DocumentId, msg: FrameMsg) { 1325 // This assertion fails on Servo use-cases, because it creates different 1326 // `RenderApi` instances for layout and compositor. 1327 //assert_eq!(document_id.0, self.namespace_id); 1328 self.api_sender 1329 .send(ApiMsg::UpdateDocuments(vec![self.frame_message(msg, document_id)])) 1330 .unwrap() 1331 } 1332 1333 /// Send a transaction to WebRender. 1334 pub fn send_transaction(&mut self, document_id: DocumentId, transaction: Transaction) { 1335 let mut transaction = transaction.finalize(document_id); 1336 1337 self.resources.update(&mut transaction); 1338 1339 if transaction.generate_frame.as_bool() { 1340 transaction.profile.start_time(profiler::API_SEND_TIME); 1341 transaction.profile.start_time(profiler::TOTAL_FRAME_CPU_TIME); 1342 } 1343 1344 if transaction.use_scene_builder_thread { 1345 let sender = if transaction.low_priority { 1346 &mut self.low_priority_scene_sender 1347 } else { 1348 &mut self.scene_sender 1349 }; 1350 1351 sender.send(SceneBuilderRequest::Transactions(vec![transaction])) 1352 .expect("send by scene sender failed"); 1353 } else { 1354 self.api_sender.send(ApiMsg::UpdateDocuments(vec![transaction])) 1355 .expect("send by api sender failed"); 1356 } 1357 } 1358 1359 /// Does a hit test on display items in the specified document, at the given 1360 /// point. If a pipeline_id is specified, it is used to further restrict the 1361 /// hit results so that only items inside that pipeline are matched. The vector 1362 /// of hit results will contain all display items that match, ordered from 1363 /// front to back. 1364 pub fn hit_test(&self, 1365 document_id: DocumentId, 1366 point: WorldPoint, 1367 ) -> HitTestResult { 1368 let (tx, rx) = single_msg_channel(); 1369 1370 self.send_frame_msg( 1371 document_id, 1372 FrameMsg::HitTest(point, tx) 1373 ); 1374 rx.recv().unwrap() 1375 } 1376 1377 /// Synchronously request an object that can perform fast hit testing queries. 1378 pub fn request_hit_tester(&self, document_id: DocumentId) -> HitTesterRequest { 1379 let (tx, rx) = single_msg_channel(); 1380 self.send_frame_msg( 1381 document_id, 1382 FrameMsg::RequestHitTester(tx) 1383 ); 1384 1385 HitTesterRequest { rx } 1386 } 1387 1388 // Some internal scheduling magic that leaked into the API. 1389 // Buckle up and see APZUpdater.cpp for more info about what this is about. 1390 #[doc(hidden)] 1391 pub fn wake_scene_builder(&self) { 1392 self.scene_sender.send(SceneBuilderRequest::WakeUp).unwrap(); 1393 } 1394 1395 /// Block until a round-trip to the scene builder thread has completed. This 1396 /// ensures that any transactions (including ones deferred to the scene 1397 /// builder thread) have been processed. 1398 pub fn flush_scene_builder(&self) { 1399 let (tx, rx) = single_msg_channel(); 1400 self.low_priority_scene_sender.send(SceneBuilderRequest::Flush(tx)).unwrap(); 1401 rx.recv().unwrap(); // Block until done. 1402 } 1403 1404 /// Save a capture of the current frame state for debugging. 1405 pub fn save_capture(&self, path: PathBuf, bits: CaptureBits) { 1406 let msg = ApiMsg::DebugCommand(DebugCommand::SaveCapture(path, bits)); 1407 self.send_message(msg); 1408 } 1409 1410 /// Load a capture of the current frame state for debugging. 1411 pub fn load_capture(&self, path: PathBuf, ids: Option<(u32, u32)>) -> Vec<CapturedDocument> { 1412 // First flush the scene builder otherwise async scenes might clobber 1413 // the capture we are about to load. 1414 self.flush_scene_builder(); 1415 1416 let (tx, rx) = unbounded_channel(); 1417 let msg = ApiMsg::DebugCommand(DebugCommand::LoadCapture(path, ids, tx)); 1418 self.send_message(msg); 1419 1420 let mut documents = Vec::new(); 1421 while let Ok(captured_doc) = rx.recv() { 1422 documents.push(captured_doc); 1423 } 1424 documents 1425 } 1426 1427 /// Start capturing a sequence of frames. 1428 pub fn start_capture_sequence(&self, path: PathBuf, bits: CaptureBits) { 1429 let msg = ApiMsg::DebugCommand(DebugCommand::StartCaptureSequence(path, bits)); 1430 self.send_message(msg); 1431 } 1432 1433 /// Stop capturing sequences of frames. 1434 pub fn stop_capture_sequence(&self) { 1435 let msg = ApiMsg::DebugCommand(DebugCommand::StopCaptureSequence); 1436 self.send_message(msg); 1437 } 1438 1439 /// Get the current debug flags 1440 pub fn get_debug_flags(&self) -> DebugFlags { 1441 let (tx, rx) = unbounded_channel(); 1442 let msg = ApiMsg::DebugCommand(DebugCommand::GetDebugFlags(tx)); 1443 self.send_message(msg); 1444 rx.recv().unwrap() 1445 } 1446 1447 /// Update the state of builtin debugging facilities. 1448 pub fn send_debug_cmd(&self, cmd: DebugCommand) { 1449 let msg = ApiMsg::DebugCommand(cmd); 1450 self.send_message(msg); 1451 } 1452 1453 /// Update a instance-global parameter. 1454 pub fn set_parameter(&mut self, parameter: Parameter) { 1455 if let Parameter::Bool(BoolParameter::Multithreading, enabled) = parameter { 1456 self.resources.enable_multithreading(enabled); 1457 } 1458 1459 let _ = self.low_priority_scene_sender.send( 1460 SceneBuilderRequest::SetParameter(parameter) 1461 ); 1462 } 1463 } 1464 1465 impl Drop for RenderApi { 1466 fn drop(&mut self) { 1467 let msg = SceneBuilderRequest::ClearNamespace(self.namespace_id); 1468 let _ = self.low_priority_scene_sender.send(msg); 1469 } 1470 } 1471 1472 1473 fn window_size_sanity_check(size: DeviceIntSize) { 1474 // Anything bigger than this will crash later when attempting to create 1475 // a render task. 1476 use crate::api::MAX_RENDER_TASK_SIZE; 1477 if size.width > MAX_RENDER_TASK_SIZE || size.height > MAX_RENDER_TASK_SIZE { 1478 panic!("Attempting to create a {}x{} window/document", size.width, size.height); 1479 } 1480 } 1481 1482 /// Collection of heap sizes, in bytes. 1483 /// cbindgen:derive-eq=false 1484 /// cbindgen:derive-ostream=false 1485 #[repr(C)] 1486 #[allow(missing_docs)] 1487 #[derive(AddAssign, Clone, Debug, Default)] 1488 pub struct MemoryReport { 1489 // 1490 // CPU Memory. 1491 // 1492 pub clip_stores: usize, 1493 pub hit_testers: usize, 1494 pub fonts: usize, 1495 pub weak_fonts: usize, 1496 pub images: usize, 1497 pub rasterized_blobs: usize, 1498 pub shader_cache: usize, 1499 pub interning: InterningMemoryReport, 1500 pub display_list: usize, 1501 pub upload_staging_memory: usize, 1502 pub swgl: usize, 1503 pub frame_allocator: usize, 1504 pub render_tasks: usize, 1505 1506 // 1507 // GPU memory. 1508 // 1509 pub vertex_data_textures: usize, 1510 pub render_target_textures: usize, 1511 pub picture_tile_textures: usize, 1512 pub atlas_textures: usize, 1513 pub standalone_textures: usize, 1514 pub texture_cache_structures: usize, 1515 pub depth_target_textures: usize, 1516 pub texture_upload_pbos: usize, 1517 pub swap_chain: usize, 1518 pub render_texture_hosts: usize, 1519 pub upload_staging_textures: usize, 1520 }