fune/gfx/webrender_traits/src/api.rs
Kartikaya Gupta 00385fa6ae Bug 1341968 - Update webrender to commit 501e3d79c8a3019762bd8bd2d00eecf7811a84de. r=jrmuizel
This also updates webrender_bindings for a few API changes:
- new offset field in ImageDescriptor
- new tiling argument to add_image
- change in set_root_display_list

MozReview-Commit-ID: JUgPviRdekc
2017-02-27 10:36:49 -05:00

277 lines
11 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use byteorder::{LittleEndian, WriteBytesExt};
use channel::{self, MsgSender, PayloadHelperMethods, PayloadSender};
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::cell::Cell;
use {ApiMsg, ColorF, DisplayListBuilder, Epoch, ImageDescriptor};
use {FontKey, IdNamespace, ImageKey, NativeFontHandle, PipelineId};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState, ScrollLocation, ServoScrollRootId};
use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand, TileSize};
use {DeviceIntSize, DynamicProperties, LayoutPoint, LayoutSize, WorldPoint, PropertyBindingKey, PropertyBindingId};
use {BuiltDisplayList, AuxiliaryLists};
use VRCompositorCommand;
use ExternalEvent;
use std::marker::PhantomData;
impl RenderApiSender {
pub fn new(api_sender: MsgSender<ApiMsg>,
payload_sender: PayloadSender)
-> RenderApiSender {
RenderApiSender {
api_sender: api_sender,
payload_sender: payload_sender,
}
}
pub fn create_api(&self) -> RenderApi {
let RenderApiSender {
ref api_sender,
ref payload_sender
} = *self;
let (sync_tx, sync_rx) = channel::msg_channel().unwrap();
let msg = ApiMsg::CloneApi(sync_tx);
api_sender.send(msg).unwrap();
RenderApi {
api_sender: api_sender.clone(),
payload_sender: payload_sender.clone(),
id_namespace: sync_rx.recv().unwrap(),
next_id: Cell::new(ResourceId(0)),
}
}
}
pub struct RenderApi {
pub api_sender: MsgSender<ApiMsg>,
pub payload_sender: PayloadSender,
pub id_namespace: IdNamespace,
pub next_id: Cell<ResourceId>,
}
impl RenderApi {
pub fn clone_sender(&self) -> RenderApiSender {
RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
}
pub fn generate_font_key(&self) -> FontKey {
let new_id = self.next_unique_id();
FontKey::new(new_id.0, new_id.1)
}
pub fn add_raw_font(&self, key: FontKey, bytes: Vec<u8>) {
let msg = ApiMsg::AddRawFont(key, bytes);
self.api_sender.send(msg).unwrap();
}
pub fn add_native_font(&self, key: FontKey, native_font_handle: NativeFontHandle) {
let msg = ApiMsg::AddNativeFont(key, native_font_handle);
self.api_sender.send(msg).unwrap();
}
/// Gets the dimensions for the supplied glyph keys
///
/// Note: Internally, the internal texture cache doesn't store
/// 'empty' textures (height or width = 0)
/// This means that glyph dimensions e.g. for spaces (' ') will mostly be None.
pub fn get_glyph_dimensions(&self, glyph_keys: Vec<GlyphKey>)
-> Vec<Option<GlyphDimensions>> {
let (tx, rx) = channel::msg_channel().unwrap();
let msg = ApiMsg::GetGlyphDimensions(glyph_keys, tx);
self.api_sender.send(msg).unwrap();
rx.recv().unwrap()
}
/// Creates an `ImageKey`.
pub fn generate_image_key(&self) -> ImageKey {
let new_id = self.next_unique_id();
ImageKey::new(new_id.0, new_id.1)
}
/// Adds an image identified by the `ImageKey`.
pub fn add_image(&self,
key: ImageKey,
descriptor: ImageDescriptor,
data: ImageData,
tiling: Option<TileSize>) {
let msg = ApiMsg::AddImage(key, descriptor, data, tiling);
self.api_sender.send(msg).unwrap();
}
/// Updates a specific image.
///
/// Currently doesn't support changing dimensions or format by updating.
// TODO: Support changing dimensions (and format) during image update?
pub fn update_image(&self,
key: ImageKey,
descriptor: ImageDescriptor,
bytes: Vec<u8>) {
let msg = ApiMsg::UpdateImage(key, descriptor, bytes);
self.api_sender.send(msg).unwrap();
}
/// Deletes the specific image.
pub fn delete_image(&self, key: ImageKey) {
let msg = ApiMsg::DeleteImage(key);
self.api_sender.send(msg).unwrap();
}
/// Sets the root pipeline.
///
/// # Examples
///
/// ```ignore
/// let (mut renderer, sender) = webrender::renderer::Renderer::new(opts);
/// let api = sender.create_api();
/// ...
/// let pipeline_id = PipelineId(0,0);
/// api.set_root_pipeline(pipeline_id);
/// ```
pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
let msg = ApiMsg::SetRootPipeline(pipeline_id);
self.api_sender.send(msg).unwrap();
}
/// Supplies a new frame to WebRender.
///
/// Non-blocking, it notifies a worker process which processes the display list.
/// When it's done and a RenderNotifier has been set in `webrender::renderer::Renderer`,
/// [new_frame_ready()][notifier] gets called.
///
/// Note: Scrolling doesn't require an own Frame.
///
/// Arguments:
///
/// * `background_color`: The background color of this pipeline.
/// * `epoch`: The unique Frame ID, monotonically increasing.
/// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
/// * `viewport_size`: The size of the viewport for this frame.
/// * `display_list`: The root Display list used in this frame.
/// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
/// * `preserve_frame_state`: If a previous frame exists which matches this pipeline
/// id, this setting determines if frame state (such as scrolling
/// position) should be preserved for this new display list.
///
/// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
pub fn set_root_display_list(&self,
background_color: Option<ColorF>,
epoch: Epoch,
viewport_size: LayoutSize,
(pipeline_id, display_list, auxiliary_lists): (PipelineId, BuiltDisplayList, AuxiliaryLists),
preserve_frame_state: bool) {
let msg = ApiMsg::SetRootDisplayList(background_color,
epoch,
pipeline_id,
viewport_size,
display_list.descriptor().clone(),
*auxiliary_lists.descriptor(),
preserve_frame_state);
self.api_sender.send(msg).unwrap();
let mut payload = vec![];
payload.write_u32::<LittleEndian>(epoch.0).unwrap();
payload.extend_from_slice(display_list.data());
payload.extend_from_slice(auxiliary_lists.data());
self.payload_sender.send_vec(payload).unwrap();
}
/// Scrolls the scrolling layer under the `cursor`
///
/// Webrender looks for the layer closest to the user
/// which has `ScrollPolicy::Scrollable` set.
pub fn scroll(&self, scroll_location: ScrollLocation, cursor: WorldPoint, phase: ScrollEventPhase) {
let msg = ApiMsg::Scroll(scroll_location, cursor, phase);
self.api_sender.send(msg).unwrap();
}
pub fn scroll_layers_with_scroll_root_id(&self,
new_scroll_origin: LayoutPoint,
pipeline_id: PipelineId,
scroll_root_id: ServoScrollRootId) {
let msg = ApiMsg::ScrollLayersWithScrollId(new_scroll_origin, pipeline_id, scroll_root_id);
self.api_sender.send(msg).unwrap();
}
pub fn tick_scrolling_bounce_animations(&self) {
let msg = ApiMsg::TickScrollingBounce;
self.api_sender.send(msg).unwrap();
}
/// Translates a point from viewport coordinates to layer space
pub fn translate_point_to_layer_space(&self, point: &WorldPoint)
-> (LayoutPoint, PipelineId) {
let (tx, rx) = channel::msg_channel().unwrap();
let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
self.api_sender.send(msg).unwrap();
rx.recv().unwrap()
}
pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
let (tx, rx) = channel::msg_channel().unwrap();
let msg = ApiMsg::GetScrollLayerState(tx);
self.api_sender.send(msg).unwrap();
rx.recv().unwrap()
}
pub fn request_webgl_context(&self, size: &DeviceIntSize, attributes: GLContextAttributes)
-> Result<(WebGLContextId, GLLimits), String> {
let (tx, rx) = channel::msg_channel().unwrap();
let msg = ApiMsg::RequestWebGLContext(*size, attributes, tx);
self.api_sender.send(msg).unwrap();
rx.recv().unwrap()
}
pub fn resize_webgl_context(&self, context_id: WebGLContextId, size: &DeviceIntSize) {
let msg = ApiMsg::ResizeWebGLContext(context_id, *size);
self.api_sender.send(msg).unwrap();
}
pub fn send_webgl_command(&self, context_id: WebGLContextId, command: WebGLCommand) {
let msg = ApiMsg::WebGLCommand(context_id, command);
self.api_sender.send(msg).unwrap();
}
/// Generate a new frame. Optionally, supply a list of animated
/// property bindings that should be used to resolve bindings
/// in the current display list.
pub fn generate_frame(&self, property_bindings: Option<DynamicProperties>) {
let msg = ApiMsg::GenerateFrame(property_bindings);
self.api_sender.send(msg).unwrap();
}
pub fn send_vr_compositor_command(&self, context_id: WebGLContextId, command: VRCompositorCommand) {
let msg = ApiMsg::VRCompositorCommand(context_id, command);
self.api_sender.send(msg).unwrap();
}
pub fn send_external_event(&self, evt: ExternalEvent) {
let msg = ApiMsg::ExternalEvent(evt);
self.api_sender.send(msg).unwrap();
}
pub fn shut_down(&self) {
self.api_sender.send(ApiMsg::ShutDown).unwrap();
}
/// Create a new unique key that can be used for
/// animated property bindings.
pub fn generate_property_binding_key<T: Copy>(&self) -> PropertyBindingKey<T> {
let new_id = self.next_unique_id();
PropertyBindingKey {
id: PropertyBindingId {
namespace: new_id.0,
uid: new_id.1,
},
_phantom: PhantomData,
}
}
#[inline]
fn next_unique_id(&self) -> (u32, u32) {
let IdNamespace(namespace) = self.id_namespace;
let ResourceId(id) = self.next_id.get();
self.next_id.set(ResourceId(id + 1));
(namespace, id)
}
}