mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Upgrade WebRender to e491e1ae637b2eed1e7195855d88357e5eb3ddf9 (#30323)
* Upgrade vendored version of WebRender * Patch WebRender: upgrade version of gleam * Restore hit testing implementation * Fix WebRender warnings * Adapt Servo to new WebRender * Update results * Add a workaround for #30313 This slightly expands text boundaries in order to take into account the fact that layout isn't measuring glyph boundaries.
This commit is contained in:
parent
c079acb3c3
commit
a9d37cb85a
563 changed files with 48524 additions and 51657 deletions
65
Cargo.lock
generated
65
Cargo.lock
generated
|
@ -332,15 +332,6 @@ dependencies = [
|
|||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
|
@ -970,6 +961,7 @@ dependencies = [
|
|||
"servo_url",
|
||||
"style_traits",
|
||||
"webgpu",
|
||||
"webrender",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
"webxr-api",
|
||||
|
@ -1186,22 +1178,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cstr"
|
||||
version = "0.1.7"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19f7a08ed4ecd7e077d4cee63937473e6f7cf57b702a9114ef41751b2cbc0f60"
|
||||
checksum = "8aa998c33a6d3271e3678950a22134cd7dd27cef86dee1b611b5b14207d1d90b"
|
||||
dependencies = [
|
||||
"cstr-macros",
|
||||
"procedural-masquerade",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cstr-macros"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd670e5ff58768ef624207fb95709ce63b8d05573fb9a05165f0eef471ea6a3a"
|
||||
dependencies = [
|
||||
"procedural-masquerade",
|
||||
"syn 1.0.103",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1651,6 +1633,17 @@ dependencies = [
|
|||
"str-buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "etagere"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcf22f748754352918e082e0039335ee92454a5d62bcaf69b5e8daf5907d9644"
|
||||
dependencies = [
|
||||
"euclid",
|
||||
"serde",
|
||||
"svg_fmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.22.7"
|
||||
|
@ -2119,9 +2112,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gleam"
|
||||
version = "0.12.2"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6da1b0a7e3f0833efe2c59f11c0e196d6208735018693c340eded4bd7aacb49"
|
||||
checksum = "0173481f2bb6e809bf4985de2e86c83876d84d2805830e3301cd37355e897f0f"
|
||||
dependencies = [
|
||||
"gl_generator 0.14.0",
|
||||
]
|
||||
|
@ -4480,12 +4473,6 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "procedural-masquerade"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1383dff4092fe903ac180e391a8d4121cc48f08ccf850614b0290c6673b69d"
|
||||
|
||||
[[package]]
|
||||
name = "profile"
|
||||
version = "0.0.1"
|
||||
|
@ -4732,11 +4719,11 @@ checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422"
|
|||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
version = "0.5.1"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5"
|
||||
checksum = "86018df177b1beef6c7c8ef949969c4f7cb9a9344181b92486b23c79995bdaa4"
|
||||
dependencies = [
|
||||
"base64 0.10.1",
|
||||
"base64 0.13.0",
|
||||
"bitflags 1.3.2",
|
||||
"serde",
|
||||
]
|
||||
|
@ -6822,6 +6809,7 @@ dependencies = [
|
|||
"serde",
|
||||
"servo_config",
|
||||
"smallvec",
|
||||
"webrender",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
"wgpu-core",
|
||||
|
@ -6851,17 +6839,17 @@ dependencies = [
|
|||
name = "webrender"
|
||||
version = "0.61.0"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bincode",
|
||||
"bitflags 1.3.2",
|
||||
"build-parallel",
|
||||
"byteorder",
|
||||
"cfg-if 0.1.10",
|
||||
"core-foundation 0.9.3",
|
||||
"core-graphics",
|
||||
"core-text",
|
||||
"cstr",
|
||||
"derive_more",
|
||||
"dwrote",
|
||||
"etagere",
|
||||
"euclid",
|
||||
"freetype",
|
||||
"fxhash",
|
||||
|
@ -6872,11 +6860,11 @@ dependencies = [
|
|||
"log",
|
||||
"malloc_size_of_derive",
|
||||
"num-traits",
|
||||
"objc",
|
||||
"plane-split",
|
||||
"rayon",
|
||||
"ron 0.5.1",
|
||||
"ron 0.6.6",
|
||||
"serde",
|
||||
"sig",
|
||||
"smallvec",
|
||||
"svg_fmt",
|
||||
"time 0.1.45",
|
||||
|
@ -6895,6 +6883,7 @@ dependencies = [
|
|||
"byteorder",
|
||||
"core-foundation 0.9.3",
|
||||
"core-graphics",
|
||||
"crossbeam-channel",
|
||||
"derive_more",
|
||||
"euclid",
|
||||
"malloc_size_of_derive",
|
||||
|
|
|
@ -32,7 +32,7 @@ env_logger = "0.8"
|
|||
fnv = "1.0"
|
||||
fxhash = "0.2"
|
||||
getopts = "0.2.11"
|
||||
gleam = "0.12"
|
||||
gleam = "0.15"
|
||||
headers = "0.3"
|
||||
html5ever = "0.26"
|
||||
http = "0.2"
|
||||
|
|
|
@ -13,7 +13,8 @@ use std::default::Default;
|
|||
use std::sync::{Arc, Mutex};
|
||||
use surfman::chains::{SwapChainAPI, SwapChains, SwapChainsAPI};
|
||||
use surfman::{Device, SurfaceInfo, SurfaceTexture};
|
||||
use webrender_api::{DocumentId, RenderApiSender};
|
||||
use webrender::RenderApiSender;
|
||||
use webrender_api::DocumentId;
|
||||
use webrender_surfman::WebrenderSurfman;
|
||||
use webrender_traits::{
|
||||
WebrenderExternalImageApi, WebrenderExternalImageRegistry, WebrenderImageSource,
|
||||
|
|
|
@ -63,10 +63,11 @@ use surfman::{
|
|||
self, Adapter, Connection, Context, ContextAttributeFlags, ContextAttributes, Device,
|
||||
GLVersion, SurfaceAccess, SurfaceInfo, SurfaceType,
|
||||
};
|
||||
use webrender::{RenderApi, RenderApiSender, Transaction};
|
||||
use webrender_api::{
|
||||
units::DeviceIntSize, DirtyRect, DocumentId, ExternalImageData, ExternalImageId,
|
||||
ExternalImageType, ImageData, ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey,
|
||||
RenderApi, RenderApiSender, TextureTarget, Transaction,
|
||||
ExternalImageType, ImageBufferKind, ImageData, ImageDescriptor, ImageDescriptorFlags,
|
||||
ImageFormat, ImageKey,
|
||||
};
|
||||
use webrender_traits::{WebrenderExternalImageRegistry, WebrenderImageHandlerType};
|
||||
use webxr::SurfmanGL as WebXRSurfman;
|
||||
|
@ -608,7 +609,7 @@ impl WebGLThread {
|
|||
let descriptor_attributes = self.device.context_descriptor_attributes(&descriptor);
|
||||
let gl_version = descriptor_attributes.version;
|
||||
let has_alpha = requested_flags.contains(ContextAttributeFlags::ALPHA);
|
||||
let texture_target = current_wr_texture_target(&self.device);
|
||||
let image_buffer_kind = current_wr_image_buffer_kind(&self.device);
|
||||
|
||||
self.device.make_context_current(&ctx).unwrap();
|
||||
let framebuffer = self
|
||||
|
@ -667,7 +668,7 @@ impl WebGLThread {
|
|||
size.to_i32(),
|
||||
has_alpha,
|
||||
id,
|
||||
texture_target,
|
||||
image_buffer_kind,
|
||||
);
|
||||
|
||||
self.cached_context_info
|
||||
|
@ -723,7 +724,7 @@ impl WebGLThread {
|
|||
.state
|
||||
.requested_flags
|
||||
.contains(ContextAttributeFlags::ALPHA);
|
||||
let texture_target = current_wr_texture_target(&self.device);
|
||||
let image_buffer_kind = current_wr_image_buffer_kind(&self.device);
|
||||
Self::update_wr_external_image(
|
||||
&mut self.webrender_api,
|
||||
self.webrender_doc,
|
||||
|
@ -731,7 +732,7 @@ impl WebGLThread {
|
|||
has_alpha,
|
||||
context_id,
|
||||
info.image_key,
|
||||
texture_target,
|
||||
image_buffer_kind,
|
||||
);
|
||||
|
||||
debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR);
|
||||
|
@ -927,10 +928,10 @@ impl WebGLThread {
|
|||
size: Size2D<i32>,
|
||||
alpha: bool,
|
||||
context_id: WebGLContextId,
|
||||
target: TextureTarget,
|
||||
image_buffer_kind: ImageBufferKind,
|
||||
) -> ImageKey {
|
||||
let descriptor = Self::image_descriptor(size, alpha);
|
||||
let data = Self::external_image_data(context_id, target);
|
||||
let data = Self::external_image_data(context_id, image_buffer_kind);
|
||||
|
||||
let image_key = webrender_api.generate_image_key();
|
||||
let mut txn = Transaction::new();
|
||||
|
@ -948,10 +949,10 @@ impl WebGLThread {
|
|||
alpha: bool,
|
||||
context_id: WebGLContextId,
|
||||
image_key: ImageKey,
|
||||
target: TextureTarget,
|
||||
image_buffer_kind: ImageBufferKind,
|
||||
) {
|
||||
let descriptor = Self::image_descriptor(size, alpha);
|
||||
let data = Self::external_image_data(context_id, target);
|
||||
let data = Self::external_image_data(context_id, image_buffer_kind);
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
txn.update_image(image_key, descriptor, data, &DirtyRect::All);
|
||||
|
@ -972,11 +973,14 @@ impl WebGLThread {
|
|||
}
|
||||
|
||||
/// Helper function to create a `ImageData::External` instance.
|
||||
fn external_image_data(context_id: WebGLContextId, target: TextureTarget) -> ImageData {
|
||||
fn external_image_data(
|
||||
context_id: WebGLContextId,
|
||||
image_buffer_kind: ImageBufferKind,
|
||||
) -> ImageData {
|
||||
let data = ExternalImageData {
|
||||
id: ExternalImageId(context_id.0 as u64),
|
||||
channel_index: 0,
|
||||
image_type: ExternalImageType::TextureHandle(target),
|
||||
image_type: ExternalImageType::TextureHandle(image_buffer_kind),
|
||||
};
|
||||
ImageData::External(data)
|
||||
}
|
||||
|
@ -1006,10 +1010,10 @@ struct WebGLContextInfo {
|
|||
}
|
||||
|
||||
// TODO(pcwalton): Add `GL_TEXTURE_EXTERNAL_OES`?
|
||||
fn current_wr_texture_target(device: &Device) -> TextureTarget {
|
||||
fn current_wr_image_buffer_kind(device: &Device) -> ImageBufferKind {
|
||||
match device.surface_gl_texture_target() {
|
||||
gl::TEXTURE_RECTANGLE => TextureTarget::Rect,
|
||||
_ => TextureTarget::Default,
|
||||
gl::TEXTURE_RECTANGLE => ImageBufferKind::TextureRect,
|
||||
_ => ImageBufferKind::Texture2D,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,13 +48,14 @@ use std::num::NonZeroU32;
|
|||
use std::rc::Rc;
|
||||
use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
|
||||
use time::{now, precise_time_ns, precise_time_s};
|
||||
use webrender;
|
||||
use webrender::{CaptureBits, RenderApi, Transaction};
|
||||
use webrender_api::units::{
|
||||
DeviceIntPoint, DeviceIntSize, DevicePoint, LayoutPoint, LayoutVector2D, WorldPoint,
|
||||
};
|
||||
use webrender_api::{
|
||||
self, BuiltDisplayList, CaptureBits, DirtyRect, DocumentId, Epoch as WebRenderEpoch,
|
||||
ExternalScrollId, HitTestFlags, PipelineId as WebRenderPipelineId, RenderApi, ScrollClamping,
|
||||
ScrollLocation, Transaction, ZoomFactor,
|
||||
self, BuiltDisplayList, DirtyRect, DocumentId, Epoch as WebRenderEpoch, ExternalScrollId,
|
||||
HitTestFlags, PipelineId as WebRenderPipelineId, ScrollClamping, ScrollLocation, ZoomFactor,
|
||||
};
|
||||
use webrender_surfman::WebrenderSurfman;
|
||||
|
||||
|
@ -649,58 +650,55 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
WebRenderEpoch(0),
|
||||
None,
|
||||
Default::default(),
|
||||
(pipeline, Default::default(), Default::default()),
|
||||
(pipeline, Default::default()),
|
||||
false,
|
||||
);
|
||||
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
WebrenderMsg::Layout(script_traits::WebrenderMsg::SendScrollNode(
|
||||
point,
|
||||
scroll_id,
|
||||
clamping,
|
||||
)) => {
|
||||
WebrenderMsg::Layout(script_traits::WebrenderMsg::SendScrollNode(point, scroll_id)) => {
|
||||
self.waiting_for_results_of_scroll = true;
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
txn.scroll_node_with_id(point, scroll_id, clamping);
|
||||
txn.generate_frame();
|
||||
txn.scroll_node_with_id(point, scroll_id, ScrollClamping::ToContentBounds);
|
||||
txn.generate_frame(0);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
WebrenderMsg::Layout(script_traits::WebrenderMsg::SendDisplayList {
|
||||
display_list_info,
|
||||
content_size,
|
||||
display_list_descriptor,
|
||||
display_list_receiver,
|
||||
}) => match display_list_receiver.recv() {
|
||||
Ok(data) => {
|
||||
self.waiting_on_pending_frame = true;
|
||||
}) => {
|
||||
let display_list_data = match display_list_receiver.recv() {
|
||||
Ok(display_list_data) => display_list_data,
|
||||
_ => return warn!("Could not recieve WebRender display list."),
|
||||
};
|
||||
|
||||
let pipeline_id = display_list_info.pipeline_id;
|
||||
let details = self.pipeline_details(PipelineId::from_webrender(pipeline_id));
|
||||
details.hit_test_items = display_list_info.hit_test_info;
|
||||
details.install_new_scroll_tree(display_list_info.scroll_tree);
|
||||
self.waiting_on_pending_frame = true;
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
txn.set_display_list(
|
||||
display_list_info.epoch,
|
||||
None,
|
||||
display_list_info.viewport_size,
|
||||
(
|
||||
pipeline_id,
|
||||
content_size,
|
||||
BuiltDisplayList::from_data(data, display_list_descriptor),
|
||||
),
|
||||
true,
|
||||
);
|
||||
txn.generate_frame();
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
Err(e) => warn!("error receiving display list data: {e:?}"),
|
||||
let pipeline_id = display_list_info.pipeline_id;
|
||||
let details = self.pipeline_details(PipelineId::from_webrender(pipeline_id));
|
||||
details.hit_test_items = display_list_info.hit_test_info;
|
||||
details.install_new_scroll_tree(display_list_info.scroll_tree);
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
txn.set_display_list(
|
||||
display_list_info.epoch,
|
||||
None,
|
||||
display_list_info.viewport_size,
|
||||
(
|
||||
pipeline_id,
|
||||
BuiltDisplayList::from_data(display_list_data, display_list_descriptor),
|
||||
),
|
||||
true,
|
||||
);
|
||||
txn.generate_frame(0);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
WebrenderMsg::Layout(script_traits::WebrenderMsg::HitTest(
|
||||
|
@ -876,7 +874,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
let pipeline_id = frame_tree.pipeline.id.to_webrender();
|
||||
let mut txn = Transaction::new();
|
||||
txn.set_root_pipeline(pipeline_id);
|
||||
txn.generate_frame();
|
||||
txn.generate_frame(0);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, txn);
|
||||
|
||||
|
@ -925,14 +923,16 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
self.pipeline_details.remove(&pipeline_id);
|
||||
}
|
||||
|
||||
fn send_window_size(&self, size_type: WindowSizeType) {
|
||||
fn send_window_size(&mut self, size_type: WindowSizeType) {
|
||||
let dppx = self.page_zoom * self.embedder_coordinates.hidpi_factor;
|
||||
|
||||
self.webrender_api.set_document_view(
|
||||
self.webrender_document,
|
||||
let mut transaction = Transaction::new();
|
||||
transaction.set_document_view(
|
||||
self.embedder_coordinates.get_viewport(),
|
||||
self.embedder_coordinates.hidpi_factor.get(),
|
||||
);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, transaction);
|
||||
|
||||
let initial_viewport = self.embedder_coordinates.viewport.size.to_f32() / dppx;
|
||||
|
||||
|
@ -1195,17 +1195,17 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
|
||||
pub fn on_scroll_event(
|
||||
&mut self,
|
||||
delta: ScrollLocation,
|
||||
scroll_location: ScrollLocation,
|
||||
cursor: DeviceIntPoint,
|
||||
phase: TouchEventType,
|
||||
) {
|
||||
match phase {
|
||||
TouchEventType::Move => self.on_scroll_window_event(delta, cursor),
|
||||
TouchEventType::Move => self.on_scroll_window_event(scroll_location, cursor),
|
||||
TouchEventType::Up | TouchEventType::Cancel => {
|
||||
self.on_scroll_window_event(delta, cursor);
|
||||
self.on_scroll_window_event(scroll_location, cursor);
|
||||
},
|
||||
TouchEventType::Down => {
|
||||
self.on_scroll_window_event(delta, cursor);
|
||||
self.on_scroll_window_event(scroll_location, cursor);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1213,7 +1213,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
fn on_scroll_window_event(&mut self, scroll_location: ScrollLocation, cursor: DeviceIntPoint) {
|
||||
self.pending_scroll_zoom_events.push(ScrollZoomEvent {
|
||||
magnification: 1.0,
|
||||
scroll_location: scroll_location,
|
||||
scroll_location,
|
||||
cursor: cursor,
|
||||
event_count: 1,
|
||||
});
|
||||
|
@ -1307,7 +1307,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
self.set_pinch_zoom_level(old_zoom * combined_event.magnification);
|
||||
txn.set_pinch_zoom(ZoomFactor::new(self.pinch_zoom_level()));
|
||||
}
|
||||
txn.generate_frame();
|
||||
txn.generate_frame(0);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, txn);
|
||||
self.waiting_for_results_of_scroll = true
|
||||
|
@ -1395,7 +1395,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
fn update_page_zoom_for_webrender(&mut self) {
|
||||
let page_zoom = ZoomFactor::new(self.page_zoom.get());
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
let mut txn = webrender::Transaction::new();
|
||||
txn.set_page_zoom(page_zoom);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, txn);
|
||||
|
@ -1609,7 +1609,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
// Paint the scene.
|
||||
// TODO(gw): Take notice of any errors the renderer returns!
|
||||
self.clear_background();
|
||||
self.webrender.render(size).ok();
|
||||
self.webrender.render(size, 0 /* buffer_age */).ok();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -1904,7 +1904,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
self.webrender.set_debug_flags(flags);
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
txn.generate_frame();
|
||||
txn.generate_frame(0);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, txn);
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ use crossbeam_channel::Sender;
|
|||
use profile_traits::mem;
|
||||
use profile_traits::time;
|
||||
use std::rc::Rc;
|
||||
use webrender::RenderApi;
|
||||
use webrender_api::DocumentId;
|
||||
use webrender_api::RenderApi;
|
||||
use webrender_surfman::WebrenderSurfman;
|
||||
|
||||
mod compositor;
|
||||
|
|
|
@ -42,6 +42,7 @@ servo_remutex = { path = "../remutex" }
|
|||
servo_url = { path = "../url" }
|
||||
style_traits = { path = "../style_traits" }
|
||||
webgpu = { path = "../webgpu" }
|
||||
webrender = { workspace = true }
|
||||
webrender_api = { workspace = true }
|
||||
webrender_traits = { path = "../webrender_traits" }
|
||||
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
|
||||
|
|
|
@ -179,7 +179,8 @@ use std::sync::{Arc, Mutex};
|
|||
use std::thread;
|
||||
use style_traits::CSSPixel;
|
||||
use webgpu::{self, WebGPU, WebGPURequest};
|
||||
use webrender_api::{DocumentId, RenderApi, RenderApiSender};
|
||||
use webrender::{RenderApi, RenderApiSender};
|
||||
use webrender_api::DocumentId;
|
||||
use webrender_traits::WebrenderExternalImageRegistry;
|
||||
|
||||
type PendingApprovalNavigations = HashMap<PipelineId, (LoadData, HistoryEntryReplacement)>;
|
||||
|
|
|
@ -71,10 +71,11 @@ use style::values::specified::ui::CursorKind;
|
|||
use style::values::RGBA;
|
||||
use style_traits::{CSSPixel, ToCss};
|
||||
use webrender_api::units::{LayoutRect, LayoutTransform, LayoutVector2D};
|
||||
use webrender_api::{self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF};
|
||||
use webrender_api::{ColorU, ExternalScrollId, FilterOp, GlyphInstance, ImageRendering, LineStyle};
|
||||
use webrender_api::{NinePatchBorder, NinePatchBorderSource, NormalBorder, PropertyBinding};
|
||||
use webrender_api::{ScrollSensitivity, StickyOffsetBounds};
|
||||
use webrender_api::{
|
||||
self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF, ColorU,
|
||||
ExternalScrollId, FilterOp, GlyphInstance, ImageRendering, LineStyle, NinePatchBorder,
|
||||
NinePatchBorderSource, NormalBorder, PropertyBinding, ScrollSensitivity, StickyOffsetBounds,
|
||||
};
|
||||
|
||||
static THREAD_TINT_COLORS: [ColorF; 8] = [
|
||||
ColorF {
|
||||
|
@ -2117,7 +2118,7 @@ impl Fragment {
|
|||
}
|
||||
|
||||
// Text
|
||||
let mut glyphs = convert_text_run_to_glyphs(
|
||||
let (largest_advance, mut glyphs) = convert_text_run_to_glyphs(
|
||||
text_fragment.run.clone(),
|
||||
text_fragment.range,
|
||||
baseline_origin,
|
||||
|
@ -2131,6 +2132,22 @@ impl Fragment {
|
|||
};
|
||||
state.indexable_text.insert(self.node, indexable_text);
|
||||
|
||||
// FIXME(mrobinson, #30313): This is a serious hack to enable a WebRender upgrade.
|
||||
// Servo is not calculating glyph boundaries and is instead relying on the
|
||||
// measured size of the content box here -- which is based on the positioning
|
||||
// of the text. The issue is that glyphs can extend beyond the boundaries
|
||||
// established by their brush origin and advance. Servo should be measuring
|
||||
// the ink boundary rectangle based on the brush origin and the glyph extents
|
||||
// instead.
|
||||
//
|
||||
// We don't yet have that information here, so in the meantime simply expand
|
||||
// the boundary rectangle of the text by the largest character advance of the
|
||||
// painted text run in all directions. This is used as a heuristic for a
|
||||
// reasonable amount of "fudge" space to include the entire text run.
|
||||
let inflated_bounds = stacking_relative_content_box
|
||||
.inflate(largest_advance, largest_advance)
|
||||
.to_layout();
|
||||
|
||||
// Process glyphs in chunks to avoid overflowing WebRender's internal limits (#17230).
|
||||
while !glyphs.is_empty() {
|
||||
let mut rest_of_glyphs = vec![];
|
||||
|
@ -2142,7 +2159,7 @@ impl Fragment {
|
|||
state.add_display_item(DisplayItem::Text(CommonDisplayItem::with_data(
|
||||
base.clone(),
|
||||
webrender_api::TextDisplayItem {
|
||||
bounds: stacking_relative_content_box.to_layout(),
|
||||
bounds: inflated_bounds,
|
||||
common: items::empty_common_item_properties(),
|
||||
font_key: text_fragment.run.font_key,
|
||||
color: text_color.to_layout(),
|
||||
|
@ -3013,7 +3030,8 @@ fn convert_text_run_to_glyphs(
|
|||
text_run: Arc<TextRun>,
|
||||
range: Range<ByteIndex>,
|
||||
mut origin: Point2D<Au>,
|
||||
) -> Vec<GlyphInstance> {
|
||||
) -> (Au, Vec<GlyphInstance>) {
|
||||
let mut largest_advance = Au(0);
|
||||
let mut glyphs = vec![];
|
||||
|
||||
for slice in text_run.natural_word_slices_in_visual_order(&range) {
|
||||
|
@ -3023,6 +3041,8 @@ fn convert_text_run_to_glyphs(
|
|||
} else {
|
||||
glyph.advance()
|
||||
};
|
||||
largest_advance = largest_advance.max(glyph.advance());
|
||||
|
||||
if !slice.glyphs.is_whitespace() {
|
||||
let glyph_offset = glyph.offset().unwrap_or(Point2D::zero());
|
||||
let point = origin + glyph_offset.to_vector();
|
||||
|
@ -3035,7 +3055,7 @@ fn convert_text_run_to_glyphs(
|
|||
origin.x += glyph_advance;
|
||||
}
|
||||
}
|
||||
return glyphs;
|
||||
(largest_advance, glyphs)
|
||||
}
|
||||
|
||||
pub struct IndexableTextItem {
|
||||
|
|
|
@ -39,7 +39,7 @@ impl ToLayout for Filter {
|
|||
type Type = wr::FilterOp;
|
||||
fn to_layout(&self) -> Self::Type {
|
||||
match *self {
|
||||
Filter::Blur(radius) => wr::FilterOp::Blur(radius.px()),
|
||||
Filter::Blur(radius) => wr::FilterOp::Blur(radius.px(), radius.px()),
|
||||
Filter::Brightness(amount) => wr::FilterOp::Brightness(amount.0),
|
||||
Filter::Contrast(amount) => wr::FilterOp::Contrast(amount.0),
|
||||
Filter::Grayscale(amount) => wr::FilterOp::Grayscale(amount.0),
|
||||
|
|
|
@ -29,11 +29,10 @@ use style::computed_values::_servo_top_layer::T as InTopLayer;
|
|||
use webrender_api as wr;
|
||||
use webrender_api::units::{LayoutPixel, LayoutRect, LayoutTransform};
|
||||
use webrender_api::{
|
||||
BorderRadius, ClipId, ClipMode, CommonItemProperties, ComplexClipRegion, ExternalScrollId,
|
||||
FilterOp, GlyphInstance, GradientStop, ImageKey, MixBlendMode, PrimitiveFlags,
|
||||
ScrollSensitivity, Shadow, SpatialId, StickyOffsetBounds, TransformStyle,
|
||||
BorderRadius, ClipChainId, ClipId, ClipMode, CommonItemProperties, ComplexClipRegion,
|
||||
ExternalScrollId, FilterOp, GlyphInstance, GradientStop, ImageKey, MixBlendMode,
|
||||
PrimitiveFlags, ScrollSensitivity, Shadow, SpatialId, StickyOffsetBounds, TransformStyle,
|
||||
};
|
||||
use wr::ClipChainId;
|
||||
|
||||
pub use style::dom::OpaqueNode;
|
||||
|
||||
|
@ -497,7 +496,6 @@ pub fn empty_common_item_properties() -> CommonItemProperties {
|
|||
clip_rect: LayoutRect::max_rect(),
|
||||
clip_id: ClipId::root(wr::PipelineId::dummy()),
|
||||
spatial_id: SpatialId::root_scroll_node(wr::PipelineId::dummy()),
|
||||
hit_info: None,
|
||||
flags: PrimitiveFlags::empty(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ impl<'a> ClipScrollState<'a> {
|
|||
|
||||
let root_clip_chain =
|
||||
builder.define_clip_chain(None, [ClipId::root(state.compositor_info.pipeline_id)]);
|
||||
|
||||
state.add_clip_node_mapping(0, root_clip_chain);
|
||||
state.add_clip_node_mapping(1, root_clip_chain);
|
||||
|
||||
|
@ -111,11 +112,7 @@ impl DisplayList {
|
|||
epoch: Epoch,
|
||||
) -> (DisplayListBuilder, CompositorDisplayListInfo, IsContentful) {
|
||||
let webrender_pipeline = pipeline_id.to_webrender();
|
||||
let mut builder = DisplayListBuilder::with_capacity(
|
||||
webrender_pipeline,
|
||||
self.bounds().size,
|
||||
1024 * 1024, // 1 MB of space
|
||||
);
|
||||
let mut builder = DisplayListBuilder::new(webrender_pipeline);
|
||||
|
||||
let content_size = self.bounds().size;
|
||||
let mut state = ClipScrollState::new(
|
||||
|
@ -153,17 +150,16 @@ impl DisplayItem {
|
|||
let internal_clip_id = clip_and_scroll_indices
|
||||
.clipping
|
||||
.unwrap_or(clip_and_scroll_indices.scrolling);
|
||||
let current_clip_id = state.webrender_clip_id_for_index(internal_clip_id.to_index());
|
||||
let current_clip_chain_id = state.webrender_clip_id_for_index(internal_clip_id.to_index());
|
||||
let hit_test_bounds = self.bounds().intersection(&self.base().clip_rect);
|
||||
|
||||
let build_common_item_properties = |base: &BaseDisplayItem| {
|
||||
CommonItemProperties {
|
||||
clip_rect: base.clip_rect,
|
||||
spatial_id: current_scroll_node_id.spatial_id,
|
||||
clip_id: ClipId::ClipChain(current_clip_id),
|
||||
clip_id: ClipId::ClipChain(current_clip_chain_id),
|
||||
// TODO(gw): Make use of the WR backface visibility functionality.
|
||||
flags: PrimitiveFlags::default(),
|
||||
hit_info: None,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -184,10 +180,15 @@ impl DisplayItem {
|
|||
current_scroll_node_id,
|
||||
);
|
||||
|
||||
let mut common = build_common_item_properties(base);
|
||||
common.hit_info = Some((hit_test_index as u64, 0u16));
|
||||
common.clip_rect = bounds;
|
||||
builder.push_hit_test(&common);
|
||||
builder.push_hit_test(
|
||||
&CommonItemProperties {
|
||||
clip_rect: bounds,
|
||||
spatial_id: current_scroll_node_id.spatial_id,
|
||||
clip_id: ClipId::ClipChain(current_clip_chain_id),
|
||||
flags: PrimitiveFlags::default(),
|
||||
},
|
||||
(hit_test_index as u64, 0u16),
|
||||
);
|
||||
};
|
||||
|
||||
match *self {
|
||||
|
@ -299,7 +300,13 @@ impl DisplayItem {
|
|||
scrolling_relative_to: None,
|
||||
},
|
||||
),
|
||||
(Some(t), None) => (t, ReferenceFrameKind::Transform),
|
||||
(Some(t), None) => (
|
||||
t,
|
||||
ReferenceFrameKind::Transform {
|
||||
is_2d_scale_translation: false,
|
||||
should_snap: false,
|
||||
},
|
||||
),
|
||||
(Some(t), Some(p)) => (
|
||||
p.then(&t),
|
||||
ReferenceFrameKind::Perspective {
|
||||
|
@ -318,7 +325,7 @@ impl DisplayItem {
|
|||
);
|
||||
|
||||
let index = frame_index.to_index();
|
||||
state.add_clip_node_mapping(index, current_clip_id);
|
||||
state.add_clip_node_mapping(index, current_clip_chain_id);
|
||||
state.register_spatial_node(
|
||||
index,
|
||||
new_spatial_id,
|
||||
|
@ -405,7 +412,7 @@ impl DisplayItem {
|
|||
let spatial_id = builder
|
||||
.define_scroll_frame(
|
||||
&parent_space_and_clip_info,
|
||||
Some(external_id),
|
||||
external_id,
|
||||
node.content_rect,
|
||||
item_rect,
|
||||
scroll_sensitivity,
|
||||
|
|
|
@ -64,8 +64,8 @@ pub(super) fn painting_area<'a>(
|
|||
};
|
||||
// The 'backgound-clip' property maps directly to `clip_rect` in `CommonItemProperties`:
|
||||
let mut common = builder.common_properties(*painting_area, &fb.fragment.style);
|
||||
if let Some(clip_id) = clip {
|
||||
common.clip_id = clip_id
|
||||
if let Some(clip_chain_id) = clip {
|
||||
common.clip_id = wr::ClipId::ClipChain(clip_chain_id)
|
||||
}
|
||||
(painting_area, common)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ impl ToWebRender for ComputedFilter {
|
|||
type Type = FilterOp;
|
||||
fn to_webrender(&self) -> Self::Type {
|
||||
match *self {
|
||||
ComputedFilter::Blur(radius) => FilterOp::Blur(radius.px()),
|
||||
ComputedFilter::Blur(radius) => FilterOp::Blur(radius.px(), radius.px()),
|
||||
ComputedFilter::Brightness(amount) => FilterOp::Brightness(amount.0),
|
||||
ComputedFilter::Contrast(amount) => FilterOp::Contrast(amount.0),
|
||||
ComputedFilter::Grayscale(amount) => FilterOp::Grayscale(amount.0),
|
||||
|
|
|
@ -26,7 +26,7 @@ use style::values::computed::{BorderStyle, Color, Length, LengthPercentage, Outl
|
|||
use style::values::specified::text::TextDecorationLine;
|
||||
use style::values::specified::ui::CursorKind;
|
||||
use style_traits::CSSPixel;
|
||||
use webrender_api::{self as wr, units};
|
||||
use webrender_api::{self as wr, units, ClipChainId, ClipId, CommonItemProperties};
|
||||
|
||||
mod background;
|
||||
mod conversions;
|
||||
|
@ -71,7 +71,7 @@ impl DisplayList {
|
|||
epoch: wr::Epoch,
|
||||
) -> Self {
|
||||
Self {
|
||||
wr: wr::DisplayListBuilder::new(pipeline_id, content_size),
|
||||
wr: wr::DisplayListBuilder::new(pipeline_id),
|
||||
compositor_info: CompositorDisplayListInfo::new(
|
||||
viewport_size,
|
||||
content_size,
|
||||
|
@ -93,7 +93,7 @@ pub(crate) struct DisplayListBuilder<'a> {
|
|||
/// only passing the builder instead passing the containing
|
||||
/// [stacking_context::StackingContextFragment] as an argument to display
|
||||
/// list building functions.
|
||||
current_clip_id: wr::ClipId,
|
||||
current_clip_chain_id: ClipChainId,
|
||||
|
||||
/// The [OpaqueNode] handle to the node used to paint the page background
|
||||
/// if the background was a canvas.
|
||||
|
@ -126,8 +126,8 @@ impl DisplayList {
|
|||
root_stacking_context: &StackingContext,
|
||||
) -> (FnvHashMap<BrowsingContextId, Size2D<f32, CSSPixel>>, bool) {
|
||||
let mut builder = DisplayListBuilder {
|
||||
current_scroll_node_id: self.compositor_info.root_scroll_node_id,
|
||||
current_clip_id: wr::ClipId::root(self.wr.pipeline_id),
|
||||
current_scroll_node_id: self.compositor_info.root_reference_frame_id,
|
||||
current_clip_chain_id: ClipChainId(0, self.compositor_info.pipeline_id),
|
||||
element_for_canvas_background: fragment_tree.canvas_background.from_element,
|
||||
is_contentful: false,
|
||||
context,
|
||||
|
@ -155,8 +155,7 @@ impl<'a> DisplayListBuilder<'a> {
|
|||
wr::CommonItemProperties {
|
||||
clip_rect,
|
||||
spatial_id: self.current_scroll_node_id.spatial_id,
|
||||
clip_id: self.current_clip_id,
|
||||
hit_info: None,
|
||||
clip_id: ClipId::ClipChain(self.current_clip_chain_id),
|
||||
flags: style.get_webrender_primitive_flags(),
|
||||
}
|
||||
}
|
||||
|
@ -281,12 +280,21 @@ impl Fragment {
|
|||
return;
|
||||
}
|
||||
|
||||
let common = builder.common_properties(rect.to_webrender(), &fragment.parent_style);
|
||||
|
||||
let hit_info = builder.hit_info(&fragment.parent_style, fragment.base.tag, Cursor::Text);
|
||||
let mut hit_test_common = common.clone();
|
||||
hit_test_common.hit_info = hit_info;
|
||||
builder.wr().push_hit_test(&hit_test_common);
|
||||
if let Some(hit_info) =
|
||||
builder.hit_info(&fragment.parent_style, fragment.base.tag, Cursor::Text)
|
||||
{
|
||||
let clip_chain_id = builder.current_clip_chain_id;
|
||||
let spatial_id = builder.current_scroll_node_id.spatial_id;
|
||||
builder.wr().push_hit_test(
|
||||
&CommonItemProperties {
|
||||
clip_rect: rect.to_webrender(),
|
||||
clip_id: ClipId::ClipChain(clip_chain_id),
|
||||
spatial_id,
|
||||
flags: fragment.parent_style.get_webrender_primitive_flags(),
|
||||
},
|
||||
hit_info,
|
||||
);
|
||||
}
|
||||
|
||||
let color = fragment.parent_style.clone_color();
|
||||
let font_metrics = &fragment.font_metrics;
|
||||
|
@ -318,6 +326,7 @@ impl Fragment {
|
|||
}
|
||||
|
||||
// Text.
|
||||
let common = builder.common_properties(rect.to_webrender(), &fragment.parent_style);
|
||||
builder.wr().push_text(
|
||||
&common,
|
||||
rect.to_webrender(),
|
||||
|
@ -376,9 +385,9 @@ struct BuilderForBoxFragment<'a> {
|
|||
padding_rect: OnceCell<units::LayoutRect>,
|
||||
content_rect: OnceCell<units::LayoutRect>,
|
||||
border_radius: wr::BorderRadius,
|
||||
border_edge_clip_id: OnceCell<Option<wr::ClipId>>,
|
||||
padding_edge_clip_id: OnceCell<Option<wr::ClipId>>,
|
||||
content_edge_clip_id: OnceCell<Option<wr::ClipId>>,
|
||||
border_edge_clip_chain_id: OnceCell<Option<ClipChainId>>,
|
||||
padding_edge_clip_chain_id: OnceCell<Option<ClipChainId>>,
|
||||
content_edge_clip_chain_id: OnceCell<Option<ClipChainId>>,
|
||||
}
|
||||
|
||||
impl<'a> BuilderForBoxFragment<'a> {
|
||||
|
@ -433,9 +442,9 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
border_radius,
|
||||
padding_rect: OnceCell::new(),
|
||||
content_rect: OnceCell::new(),
|
||||
border_edge_clip_id: OnceCell::new(),
|
||||
padding_edge_clip_id: OnceCell::new(),
|
||||
content_edge_clip_id: OnceCell::new(),
|
||||
border_edge_clip_chain_id: OnceCell::new(),
|
||||
padding_edge_clip_chain_id: OnceCell::new(),
|
||||
content_edge_clip_chain_id: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -459,14 +468,14 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn border_edge_clip(&self, builder: &mut DisplayListBuilder) -> Option<wr::ClipId> {
|
||||
fn border_edge_clip(&self, builder: &mut DisplayListBuilder) -> Option<ClipChainId> {
|
||||
*self
|
||||
.border_edge_clip_id
|
||||
.border_edge_clip_chain_id
|
||||
.get_or_init(|| clip_for_radii(self.border_radius, self.border_rect, builder))
|
||||
}
|
||||
|
||||
fn padding_edge_clip(&self, builder: &mut DisplayListBuilder) -> Option<wr::ClipId> {
|
||||
*self.padding_edge_clip_id.get_or_init(|| {
|
||||
fn padding_edge_clip(&self, builder: &mut DisplayListBuilder) -> Option<ClipChainId> {
|
||||
*self.padding_edge_clip_chain_id.get_or_init(|| {
|
||||
clip_for_radii(
|
||||
inner_radii(
|
||||
self.border_radius,
|
||||
|
@ -481,8 +490,8 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn content_edge_clip(&self, builder: &mut DisplayListBuilder) -> Option<wr::ClipId> {
|
||||
*self.content_edge_clip_id.get_or_init(|| {
|
||||
fn content_edge_clip(&self, builder: &mut DisplayListBuilder) -> Option<ClipChainId> {
|
||||
*self.content_edge_clip_chain_id.get_or_init(|| {
|
||||
clip_for_radii(
|
||||
inner_radii(
|
||||
self.border_radius,
|
||||
|
@ -512,14 +521,16 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
self.fragment.base.tag,
|
||||
Cursor::Default,
|
||||
);
|
||||
if hit_info.is_some() {
|
||||
let mut common = builder.common_properties(self.border_rect, &self.fragment.style);
|
||||
common.hit_info = hit_info;
|
||||
if let Some(clip_id) = self.border_edge_clip(builder) {
|
||||
common.clip_id = clip_id
|
||||
}
|
||||
builder.wr().push_hit_test(&common)
|
||||
let hit_info = match hit_info {
|
||||
Some(hit_info) => hit_info,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let mut common = builder.common_properties(self.border_rect, &self.fragment.style);
|
||||
if let Some(clip_chain_id) = self.border_edge_clip(builder) {
|
||||
common.clip_id = ClipId::ClipChain(clip_chain_id);
|
||||
}
|
||||
builder.wr().push_hit_test(&common, hit_info);
|
||||
}
|
||||
|
||||
fn build_background(&mut self, builder: &mut DisplayListBuilder) {
|
||||
|
@ -868,21 +879,27 @@ fn clip_for_radii(
|
|||
radii: wr::BorderRadius,
|
||||
rect: units::LayoutRect,
|
||||
builder: &mut DisplayListBuilder,
|
||||
) -> Option<wr::ClipId> {
|
||||
) -> Option<ClipChainId> {
|
||||
if radii.is_zero() {
|
||||
None
|
||||
} else {
|
||||
let clip_chain_id = builder.current_clip_chain_id.clone();
|
||||
let parent_space_and_clip = wr::SpaceAndClipInfo {
|
||||
spatial_id: builder.current_scroll_node_id.spatial_id,
|
||||
clip_id: builder.current_clip_id,
|
||||
clip_id: ClipId::ClipChain(clip_chain_id),
|
||||
};
|
||||
Some(builder.wr().define_clip_rounded_rect(
|
||||
let new_clip_id = builder.wr().define_clip_rounded_rect(
|
||||
&parent_space_and_clip,
|
||||
wr::ComplexClipRegion {
|
||||
rect,
|
||||
radii,
|
||||
mode: wr::ClipMode::Clip,
|
||||
},
|
||||
))
|
||||
);
|
||||
Some(
|
||||
builder
|
||||
.wr()
|
||||
.define_clip_chain(Some(clip_chain_id), [new_clip_id]),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ use style::values::generics::transform;
|
|||
use style::values::specified::box_::DisplayOutside;
|
||||
use webrender_api as wr;
|
||||
use webrender_api::units::{LayoutPoint, LayoutRect, LayoutTransform, LayoutVector2D};
|
||||
use webrender_api::ScrollSensitivity;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct ContainingBlock {
|
||||
|
@ -150,17 +151,16 @@ impl DisplayList {
|
|||
external_id: wr::ExternalScrollId,
|
||||
content_rect: LayoutRect,
|
||||
clip_rect: LayoutRect,
|
||||
scroll_sensitivity: wr::ScrollSensitivity,
|
||||
external_scroll_offset: LayoutVector2D,
|
||||
scroll_sensitivity: ScrollSensitivity,
|
||||
) -> (ScrollTreeNodeId, wr::ClipChainId) {
|
||||
let parent_space_and_clip_info = wr::SpaceAndClipInfo {
|
||||
spatial_id: parent_scroll_node_id.spatial_id,
|
||||
clip_id: wr::ClipId::root(self.wr.pipeline_id),
|
||||
};
|
||||
|
||||
let new_clip_id = self
|
||||
.wr
|
||||
.define_clip_rect(&parent_space_and_clip_info, clip_rect);
|
||||
|
||||
let new_clip_chain_id = self
|
||||
.wr
|
||||
.define_clip_chain(Some(*parent_clip_chain_id), [new_clip_id]);
|
||||
|
@ -169,11 +169,11 @@ impl DisplayList {
|
|||
.wr
|
||||
.define_scroll_frame(
|
||||
&parent_space_and_clip_info,
|
||||
Some(external_id),
|
||||
external_id,
|
||||
content_rect,
|
||||
clip_rect,
|
||||
scroll_sensitivity,
|
||||
external_scroll_offset,
|
||||
LayoutVector2D::zero(), /* external_scroll_offset */
|
||||
)
|
||||
.spatial_id;
|
||||
|
||||
|
@ -202,7 +202,7 @@ pub(crate) struct StackingContextFragment {
|
|||
impl StackingContextFragment {
|
||||
fn build_display_list(&self, builder: &mut DisplayListBuilder) {
|
||||
builder.current_scroll_node_id = self.scroll_node_id;
|
||||
builder.current_clip_id = wr::ClipId::ClipChain(self.clip_chain_id);
|
||||
builder.current_clip_chain_id = self.clip_chain_id;
|
||||
self.fragment
|
||||
.borrow()
|
||||
.build_display_list(builder, &self.containing_block, self.section);
|
||||
|
@ -964,9 +964,9 @@ impl BoxFragment {
|
|||
|
||||
let sensitivity =
|
||||
if ComputedOverflow::Hidden == overflow_x && ComputedOverflow::Hidden == overflow_y {
|
||||
wr::ScrollSensitivity::Script
|
||||
ScrollSensitivity::Script
|
||||
} else {
|
||||
wr::ScrollSensitivity::ScriptAndInputEvents
|
||||
ScrollSensitivity::ScriptAndInputEvents
|
||||
};
|
||||
|
||||
let padding_rect = self
|
||||
|
@ -984,7 +984,6 @@ impl BoxFragment {
|
|||
.to_webrender(),
|
||||
padding_rect,
|
||||
sensitivity,
|
||||
LayoutVector2D::zero(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -1013,7 +1012,13 @@ impl BoxFragment {
|
|||
scrolling_relative_to: None,
|
||||
},
|
||||
),
|
||||
(Some(transform), None) => (transform, wr::ReferenceFrameKind::Transform),
|
||||
(Some(transform), None) => (
|
||||
transform,
|
||||
wr::ReferenceFrameKind::Transform {
|
||||
is_2d_scale_translation: false,
|
||||
should_snap: false,
|
||||
},
|
||||
),
|
||||
(Some(transform), Some(perspective)) => (
|
||||
perspective.then(&transform),
|
||||
wr::ReferenceFrameKind::Perspective {
|
||||
|
|
|
@ -109,7 +109,7 @@ use style::traversal_flags::TraversalFlags;
|
|||
use style_traits::CSSPixel;
|
||||
use style_traits::DevicePixel;
|
||||
use style_traits::SpeculativePainter;
|
||||
use webrender_api::{units, ColorF, HitTestFlags, ScrollClamping};
|
||||
use webrender_api::{units, ColorF, HitTestFlags};
|
||||
|
||||
/// Information needed by the layout thread.
|
||||
pub struct LayoutThread {
|
||||
|
@ -1073,7 +1073,7 @@ impl LayoutThread {
|
|||
.maybe_observe_paint_time(self, epoch, is_contentful.0);
|
||||
|
||||
self.webrender_api
|
||||
.send_display_list(compositor_info, builder.finalize());
|
||||
.send_display_list(compositor_info, builder.finalize().1);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -1508,11 +1508,8 @@ impl LayoutThread {
|
|||
.insert(state.scroll_id, state.scroll_offset);
|
||||
|
||||
let point = Point2D::new(-state.scroll_offset.x, -state.scroll_offset.y);
|
||||
self.webrender_api.send_scroll_node(
|
||||
units::LayoutPoint::from_untyped(point),
|
||||
state.scroll_id,
|
||||
ScrollClamping::ToContentBounds,
|
||||
);
|
||||
self.webrender_api
|
||||
.send_scroll_node(units::LayoutPoint::from_untyped(point), state.scroll_id);
|
||||
}
|
||||
|
||||
fn set_scroll_states<'a, 'b>(
|
||||
|
|
|
@ -95,7 +95,7 @@ use style::traversal_flags::TraversalFlags;
|
|||
use style_traits::CSSPixel;
|
||||
use style_traits::DevicePixel;
|
||||
use style_traits::SpeculativePainter;
|
||||
use webrender_api::{units, HitTestFlags, ScrollClamping};
|
||||
use webrender_api::{units, HitTestFlags};
|
||||
|
||||
/// Information needed by the layout thread.
|
||||
pub struct LayoutThread {
|
||||
|
@ -1173,11 +1173,8 @@ impl LayoutThread {
|
|||
.insert(state.scroll_id, state.scroll_offset);
|
||||
|
||||
let point = Point2D::new(-state.scroll_offset.x, -state.scroll_offset.y);
|
||||
self.webrender_api.send_scroll_node(
|
||||
units::LayoutPoint::from_untyped(point),
|
||||
state.scroll_id,
|
||||
ScrollClamping::ToContentBounds,
|
||||
);
|
||||
self.webrender_api
|
||||
.send_scroll_node(units::LayoutPoint::from_untyped(point), state.scroll_id);
|
||||
}
|
||||
|
||||
fn set_scroll_states<'a, 'b>(
|
||||
|
@ -1284,7 +1281,7 @@ impl LayoutThread {
|
|||
.maybe_observe_paint_time(self, epoch, is_contentful);
|
||||
|
||||
self.webrender_api
|
||||
.send_display_list(display_list.compositor_info, display_list.wr.finalize());
|
||||
.send_display_list(display_list.compositor_info, display_list.wr.finalize().1);
|
||||
|
||||
self.update_iframe_sizes(iframe_sizes);
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ use webrender_api::{
|
|||
BorderRadius, BorderStyle, BoxShadowClipMode, ColorF, ComplexClipRegion, ExtendMode,
|
||||
ExternalScrollId, FilterOp, FontInstanceKey, GlyphInstance, GradientStop, ImageKey,
|
||||
ImageRendering, LineStyle, MixBlendMode, NinePatchBorder, NormalBorder, RepeatMode,
|
||||
ScrollSensitivity, StickyOffsetBounds, TransformStyle,
|
||||
StickyOffsetBounds, TransformStyle,
|
||||
};
|
||||
|
||||
/// A C function that takes a pointer to a heap allocation and returns its size.
|
||||
|
@ -844,8 +844,6 @@ malloc_size_of_is_0!(NormalBorder);
|
|||
#[cfg(feature = "webrender_api")]
|
||||
malloc_size_of_is_0!(RepeatMode);
|
||||
#[cfg(feature = "webrender_api")]
|
||||
malloc_size_of_is_0!(ScrollSensitivity);
|
||||
#[cfg(feature = "webrender_api")]
|
||||
malloc_size_of_is_0!(StickyOffsetBounds);
|
||||
#[cfg(feature = "webrender_api")]
|
||||
malloc_size_of_is_0!(TransformStyle);
|
||||
|
|
|
@ -96,7 +96,7 @@ use std::rc::Rc;
|
|||
use std::sync::{Arc, Mutex};
|
||||
use time::{self, Duration, Timespec};
|
||||
use webrender_api::ImageKey;
|
||||
use webrender_api::{ExternalImageData, ExternalImageId, ExternalImageType, TextureTarget};
|
||||
use webrender_api::{ExternalImageData, ExternalImageId, ExternalImageType, ImageBufferKind};
|
||||
use webrender_api::{ImageData, ImageDescriptor, ImageDescriptorFlags, ImageFormat};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
|
@ -225,9 +225,9 @@ impl VideoFrameRenderer for MediaFrameRenderer {
|
|||
|
||||
let image_data = if frame.is_gl_texture() && self.player_id.is_some() {
|
||||
let texture_target = if frame.is_external_oes() {
|
||||
TextureTarget::External
|
||||
ImageBufferKind::TextureExternal
|
||||
} else {
|
||||
TextureTarget::Default
|
||||
ImageBufferKind::Texture2D
|
||||
};
|
||||
|
||||
ImageData::External(ExternalImageData {
|
||||
|
@ -254,9 +254,9 @@ impl VideoFrameRenderer for MediaFrameRenderer {
|
|||
|
||||
let image_data = if frame.is_gl_texture() && self.player_id.is_some() {
|
||||
let texture_target = if frame.is_external_oes() {
|
||||
TextureTarget::External
|
||||
ImageBufferKind::TextureExternal
|
||||
} else {
|
||||
TextureTarget::Default
|
||||
ImageBufferKind::Texture2D
|
||||
};
|
||||
|
||||
ImageData::External(ExternalImageData {
|
||||
|
|
|
@ -220,6 +220,9 @@ pub struct CompositorDisplayListInfo {
|
|||
/// The size of the viewport that this display list renders into.
|
||||
pub viewport_size: LayoutSize,
|
||||
|
||||
/// The size of this display list's content.
|
||||
pub content_size: LayoutSize,
|
||||
|
||||
/// The epoch of the display list.
|
||||
pub epoch: Epoch,
|
||||
|
||||
|
@ -270,6 +273,7 @@ impl CompositorDisplayListInfo {
|
|||
CompositorDisplayListInfo {
|
||||
pipeline_id,
|
||||
viewport_size,
|
||||
content_size,
|
||||
epoch,
|
||||
hit_test_info: Default::default(),
|
||||
scroll_tree,
|
||||
|
|
|
@ -69,13 +69,10 @@ use std::sync::Arc;
|
|||
use style_traits::CSSPixel;
|
||||
use style_traits::SpeculativePainter;
|
||||
use webgpu::identity::WebGPUMsg;
|
||||
use webrender_api::units::{
|
||||
DeviceIntSize, DevicePixel, LayoutPixel, LayoutPoint, LayoutSize, WorldPoint,
|
||||
};
|
||||
use webrender_api::units::{DeviceIntSize, DevicePixel, LayoutPixel, LayoutPoint, WorldPoint};
|
||||
use webrender_api::{
|
||||
BuiltDisplayList, BuiltDisplayListDescriptor, DocumentId, ExternalImageData, ExternalScrollId,
|
||||
HitTestFlags, ImageData, ImageDescriptor, ImageKey, PipelineId as WebRenderPipelineId,
|
||||
ScrollClamping,
|
||||
};
|
||||
|
||||
/// The address of a node. Layout sends these back. They must be validated via
|
||||
|
@ -1125,13 +1122,11 @@ pub enum WebrenderMsg {
|
|||
/// Inform WebRender of the existence of this pipeline.
|
||||
SendInitialTransaction(WebRenderPipelineId),
|
||||
/// Perform a scroll operation.
|
||||
SendScrollNode(LayoutPoint, ExternalScrollId, ScrollClamping),
|
||||
SendScrollNode(LayoutPoint, ExternalScrollId),
|
||||
/// Inform WebRender of a new display list for the given pipeline.
|
||||
SendDisplayList {
|
||||
/// The [CompositorDisplayListInfo] that describes the display list being sent.
|
||||
display_list_info: CompositorDisplayListInfo,
|
||||
/// The content size of this display list as calculated by WebRender.
|
||||
content_size: LayoutSize,
|
||||
/// A descriptor of this display list used to construct this display list from raw data.
|
||||
display_list_descriptor: BuiltDisplayListDescriptor,
|
||||
/// An [ipc::IpcBytesReceiver] used to send the raw data of the display list.
|
||||
|
@ -1170,16 +1165,8 @@ impl WebrenderIpcSender {
|
|||
}
|
||||
|
||||
/// Perform a scroll operation.
|
||||
pub fn send_scroll_node(
|
||||
&self,
|
||||
point: LayoutPoint,
|
||||
scroll_id: ExternalScrollId,
|
||||
clamping: ScrollClamping,
|
||||
) {
|
||||
if let Err(e) = self
|
||||
.0
|
||||
.send(WebrenderMsg::SendScrollNode(point, scroll_id, clamping))
|
||||
{
|
||||
pub fn send_scroll_node(&self, point: LayoutPoint, scroll_id: ExternalScrollId) {
|
||||
if let Err(e) = self.0.send(WebrenderMsg::SendScrollNode(point, scroll_id)) {
|
||||
warn!("Error sending scroll node: {}", e);
|
||||
}
|
||||
}
|
||||
|
@ -1188,13 +1175,12 @@ impl WebrenderIpcSender {
|
|||
pub fn send_display_list(
|
||||
&self,
|
||||
display_list_info: CompositorDisplayListInfo,
|
||||
(_, content_size, list): (WebRenderPipelineId, LayoutSize, BuiltDisplayList),
|
||||
list: BuiltDisplayList,
|
||||
) {
|
||||
let (display_list_data, display_list_descriptor) = list.into_data();
|
||||
let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap();
|
||||
if let Err(e) = self.0.send(WebrenderMsg::SendDisplayList {
|
||||
display_list_info,
|
||||
content_size,
|
||||
display_list_descriptor,
|
||||
display_list_receiver,
|
||||
}) {
|
||||
|
|
|
@ -29,11 +29,14 @@ pub use devtools_traits;
|
|||
pub use embedder_traits;
|
||||
pub use euclid;
|
||||
pub use gfx;
|
||||
pub use gleam::gl;
|
||||
pub use ipc_channel;
|
||||
pub use keyboard_types;
|
||||
pub use layout_thread_2013;
|
||||
pub use layout_thread_2020;
|
||||
pub use media;
|
||||
pub use msg;
|
||||
pub use msg::constellation_msg::TopLevelBrowsingContextId as BrowserId;
|
||||
pub use net;
|
||||
pub use net_traits;
|
||||
pub use profile;
|
||||
|
@ -41,25 +44,18 @@ pub use profile_traits;
|
|||
pub use script;
|
||||
pub use script_layout_interface;
|
||||
pub use script_traits;
|
||||
pub use servo_config as config;
|
||||
pub use servo_config;
|
||||
pub use servo_geometry;
|
||||
pub use servo_url as url;
|
||||
pub use servo_url;
|
||||
pub use style;
|
||||
pub use style_traits;
|
||||
pub use webgpu;
|
||||
pub use webrender_api;
|
||||
use webrender_api::{DocumentId, FontInstanceKey, FontKey, ImageKey, RenderApiSender};
|
||||
pub use webrender_surfman;
|
||||
pub use webrender_traits;
|
||||
|
||||
#[cfg(feature = "webdriver")]
|
||||
fn webdriver(port: u16, constellation: Sender<ConstellationMsg>) {
|
||||
webdriver_server::start_server(port, constellation);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "webdriver"))]
|
||||
fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) {}
|
||||
|
||||
use bluetooth::BluetoothThreadFactory;
|
||||
use bluetooth_traits::BluetoothRequest;
|
||||
use canvas::canvas_paint_thread::{self, CanvasPaintThread};
|
||||
|
@ -84,7 +80,7 @@ use constellation::{FromCompositorLogger, FromScriptLogger};
|
|||
use crossbeam_channel::{unbounded, Sender};
|
||||
use embedder_traits::{EmbedderMsg, EmbedderProxy, EmbedderReceiver, EventLoopWaker};
|
||||
use env_logger::Builder as EnvLoggerBuilder;
|
||||
use euclid::{Scale, Size2D};
|
||||
use euclid::Scale;
|
||||
#[cfg(all(
|
||||
not(target_os = "windows"),
|
||||
not(target_os = "ios"),
|
||||
|
@ -119,16 +115,19 @@ use std::rc::Rc;
|
|||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use surfman::GLApi;
|
||||
use webrender::ShaderPrecacheFlags;
|
||||
use webrender::{RenderApiSender, ShaderPrecacheFlags};
|
||||
use webrender_api::{DocumentId, FontInstanceKey, FontKey, ImageKey};
|
||||
use webrender_traits::WebrenderExternalImageHandlers;
|
||||
use webrender_traits::WebrenderExternalImageRegistry;
|
||||
use webrender_traits::WebrenderImageHandlerType;
|
||||
|
||||
pub use gleam::gl;
|
||||
pub use keyboard_types;
|
||||
pub use msg::constellation_msg::TopLevelBrowsingContextId as BrowserId;
|
||||
pub use servo_config as config;
|
||||
pub use servo_url as url;
|
||||
#[cfg(feature = "webdriver")]
|
||||
fn webdriver(port: u16, constellation: Sender<ConstellationMsg>) {
|
||||
webdriver_server::start_server(port, constellation);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "webdriver"))]
|
||||
fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) {}
|
||||
|
||||
#[cfg(feature = "media-gstreamer")]
|
||||
mod media_platform {
|
||||
|
@ -217,9 +216,11 @@ impl webrender_api::RenderNotifier for RenderNotifier {
|
|||
Box::new(RenderNotifier::new(self.compositor_proxy.clone()))
|
||||
}
|
||||
|
||||
fn wake_up(&self) {
|
||||
self.compositor_proxy
|
||||
.recomposite(CompositingReason::NewWebRenderFrame);
|
||||
fn wake_up(&self, composite_needed: bool) {
|
||||
if composite_needed {
|
||||
self.compositor_proxy
|
||||
.recomposite(CompositingReason::NewWebRenderFrame);
|
||||
}
|
||||
}
|
||||
|
||||
fn new_frame_ready(
|
||||
|
@ -233,7 +234,7 @@ impl webrender_api::RenderNotifier for RenderNotifier {
|
|||
self.compositor_proxy
|
||||
.send(CompositorMsg::NewScrollFrameReady(composite_needed));
|
||||
} else {
|
||||
self.wake_up();
|
||||
self.wake_up(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -333,7 +334,7 @@ where
|
|||
None
|
||||
};
|
||||
|
||||
let coordinates = window.get_coordinates();
|
||||
let coordinates: compositing::windowing::EmbedderCoordinates = window.get_coordinates();
|
||||
let device_pixel_ratio = coordinates.hidpi_factor.get();
|
||||
let viewport_size = coordinates.viewport.size.to_f32() / device_pixel_ratio;
|
||||
|
||||
|
@ -345,10 +346,6 @@ where
|
|||
);
|
||||
|
||||
let render_notifier = Box::new(RenderNotifier::new(compositor_proxy.clone()));
|
||||
|
||||
// Cast from `DeviceIndependentPixel` to `DevicePixel`
|
||||
let window_size = Size2D::from_untyped(viewport_size.to_i32().to_untyped());
|
||||
|
||||
webrender::Renderer::new(
|
||||
webrender_gl.clone(),
|
||||
render_notifier,
|
||||
|
@ -369,20 +366,12 @@ where
|
|||
..Default::default()
|
||||
},
|
||||
None,
|
||||
window_size,
|
||||
)
|
||||
.expect("Unable to initialize webrender!")
|
||||
};
|
||||
|
||||
let webrender_api = webrender_api_sender.create_api();
|
||||
let wr_document_layer = 0; //TODO
|
||||
let webrender_document =
|
||||
webrender_api.add_document(coordinates.framebuffer, wr_document_layer);
|
||||
webrender_api.set_document_view(
|
||||
webrender_document,
|
||||
coordinates.get_viewport(),
|
||||
coordinates.hidpi_factor.get(),
|
||||
);
|
||||
let webrender_document = webrender_api.add_document(coordinates.get_viewport().size);
|
||||
|
||||
// Important that this call is done in a single-threaded fashion, we
|
||||
// can't defer it after `create_constellation` has started.
|
||||
|
@ -575,8 +564,9 @@ where
|
|||
self.compositor.on_wheel_event(delta, location);
|
||||
},
|
||||
|
||||
EmbedderEvent::Scroll(delta, cursor, phase) => {
|
||||
self.compositor.on_scroll_event(delta, cursor, phase);
|
||||
EmbedderEvent::Scroll(scroll_location, cursor, phase) => {
|
||||
self.compositor
|
||||
.on_scroll_event(scroll_location, cursor, phase);
|
||||
},
|
||||
|
||||
EmbedderEvent::Zoom(magnification) => {
|
||||
|
|
|
@ -20,6 +20,7 @@ msg = { path = "../msg" }
|
|||
serde = { workspace = true, features = ["serde_derive"] }
|
||||
servo_config = { path = "../config" }
|
||||
smallvec = { workspace = true, features = ["serde"] }
|
||||
webrender = { workspace = true }
|
||||
webrender_api = { workspace = true }
|
||||
webrender_traits = { path = "../webrender_traits" }
|
||||
wgpu-core = { version = "0.17", features = ["replay", "trace", "serial-pass", "wgsl"] }
|
||||
|
|
|
@ -26,10 +26,8 @@ use std::rc::Rc;
|
|||
use std::slice;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
use webrender_api::{
|
||||
DirtyRect, DocumentId, ExternalImageId, ImageData, ImageDescriptor, ImageKey, RenderApi,
|
||||
RenderApiSender, Transaction,
|
||||
};
|
||||
use webrender::{RenderApi, RenderApiSender, Transaction};
|
||||
use webrender_api::{DirtyRect, DocumentId, ExternalImageId, ImageData, ImageDescriptor, ImageKey};
|
||||
use webrender_traits::{
|
||||
WebrenderExternalImageApi, WebrenderExternalImageRegistry, WebrenderImageHandlerType,
|
||||
WebrenderImageSource,
|
||||
|
|
|
@ -51,7 +51,7 @@ egui_glow = { version = "0.22.0", features = ["winit"] }
|
|||
egui-winit = { version = "0.22.0", default-features = false, features = ["clipboard", "wayland"] }
|
||||
euclid = { workspace = true }
|
||||
getopts = { workspace = true }
|
||||
gleam = "0.12"
|
||||
gleam = { workspace = true }
|
||||
glow = "0.12.2"
|
||||
keyboard-types = { workspace = true }
|
||||
lazy_static = { workspace = true }
|
||||
|
|
|
@ -543,7 +543,9 @@ impl WindowMethods for Window {
|
|||
let inner_size = Size2D::new(width as f32, height as f32) * dpr;
|
||||
let viewport_size = inner_size - Size2D::new(0f32, toolbar_height);
|
||||
let viewport_origin = DeviceIntPoint::zero(); // bottom left
|
||||
let viewport = DeviceIntRect::new(viewport_origin, viewport_size.to_i32());
|
||||
let viewport = DeviceIntRect::new(
|
||||
viewport_origin, viewport_size.to_i32()
|
||||
);
|
||||
|
||||
let framebuffer = DeviceIntSize::from_untyped(viewport.size.to_untyped());
|
||||
EmbedderCoordinates {
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[background-attachment-fixed-inline-scrolled.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[background-size-041.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[background-size-042.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[position-sticky-escape-scroller-002.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[position-sticky-escape-scroller-004.html]
|
||||
expected: FAIL
|
|
@ -1,4 +0,0 @@
|
|||
[elementFromPoint-mixed-font-sizes.html]
|
||||
[document.elementFromPoint finds container SPAN in the empty region above a child SPAN with a smaller font size]
|
||||
expected: FAIL
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[background-attachment-fixed-inline-scrolled.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[background-size-041.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[background-size-042.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[flexbox-mbp-horiz-003-reverse.xhtml]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[flexbox-mbp-horiz-003.xhtml]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[flexbox-mbp-horiz-003v.xhtml]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[position-sticky-escape-scroller-002.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[perspective-split-by-zero-w.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[filtered-html-is-not-container.html]
|
||||
expected: FAIL
|
|
@ -1,2 +1,2 @@
|
|||
[border-radius-image.html]
|
||||
fuzzy: /_mozilla/css/border-radius-image-ref.html:63;696
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[pixel_snapping_position_a.html]
|
||||
expected: FAIL
|
|
@ -1,3 +0,0 @@
|
|||
[opacity-background-1.html]
|
||||
expected:
|
||||
if os == "linux": FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[scroll_root.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[pixel_snapping_position_a.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[opacity-background-1.html]
|
||||
expected: FAIL
|
3
tests/wpt/mozilla/meta/mozilla/scrollBy.html.ini
Normal file
3
tests/wpt/mozilla/meta/mozilla/scrollBy.html.ini
Normal file
|
@ -0,0 +1,3 @@
|
|||
[scrollBy.html]
|
||||
[Ensure that the window.scrollBy function affects scroll position as expected]
|
||||
expected: FAIL
|
2
tests/wpt/mozilla/meta/mozilla/scroll_root.html.ini
Normal file
2
tests/wpt/mozilla/meta/mozilla/scroll_root.html.ini
Normal file
|
@ -0,0 +1,2 @@
|
|||
[scroll_root.html]
|
||||
expected: FAIL
|
1752
third_party/webrender/Cargo.lock
generated
vendored
1752
third_party/webrender/Cargo.lock
generated
vendored
File diff suppressed because it is too large
Load diff
10
third_party/webrender/Cargo.toml
vendored
10
third_party/webrender/Cargo.toml
vendored
|
@ -1,6 +1,5 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"direct-composition",
|
||||
"examples",
|
||||
"webrender",
|
||||
"webrender_api",
|
||||
|
@ -16,6 +15,13 @@ panic = "abort"
|
|||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
# optimizing glsl more makes a big difference in swgl build times
|
||||
[profile.dev.package.glsl]
|
||||
opt-level = 2
|
||||
|
||||
[profile.release.package.glsl]
|
||||
opt-level = 2
|
||||
|
||||
# Running wrench on android built with master cargo-apk results in a crash
|
||||
# due to a mismatched version of android_glue (a dependency of winit).
|
||||
# Override it to use a suitable version of android_glue.
|
||||
|
@ -23,3 +29,5 @@ panic = "abort"
|
|||
# This can be removed once a new version of android_glue is published to crates.io.
|
||||
[patch.crates-io]
|
||||
android_glue = { git = "https://github.com/rust-windowing/android-rs-glue.git", rev = "e3ac6edea5814e1faca0c31ea8fac6877cb929ea" }
|
||||
# this is a version that fixes some incompatibilites with newer rust/aarch64
|
||||
winit = { version = "0.19", git = "https://github.com/jrmuizel/winit", branch="wr" }
|
||||
|
|
|
@ -14,15 +14,19 @@ test "$(whoami)" == 'root'
|
|||
# Install stuff we need
|
||||
apt-get -y update
|
||||
apt-get install -y \
|
||||
bison \
|
||||
bzip2 \
|
||||
cmake \
|
||||
curl \
|
||||
flex \
|
||||
gcc \
|
||||
git \
|
||||
g++ \
|
||||
libfontconfig1-dev \
|
||||
libgl1-mesa-dev \
|
||||
libx11-dev \
|
||||
llvm-dev \
|
||||
ninja-build \
|
||||
openjdk-8-jdk \
|
||||
pkg-config \
|
||||
python \
|
||||
|
@ -31,7 +35,10 @@ apt-get install -y \
|
|||
python-setuptools \
|
||||
python-voluptuous \
|
||||
python-yaml \
|
||||
software-properties-common
|
||||
python3-pip \
|
||||
python3-mako \
|
||||
software-properties-common \
|
||||
clang
|
||||
|
||||
# Other stuff we need
|
||||
pip install servo-tidy==0.3.0
|
||||
|
|
18
third_party/webrender/ci-scripts/etc/wr-darwin.meson
vendored
Normal file
18
third_party/webrender/ci-scripts/etc/wr-darwin.meson
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
[binaries]
|
||||
llvm-config = '/builds/worker/fetches/clang/bin/llvm-config'
|
||||
|
||||
[properties]
|
||||
# When linking `libOSMesa.dylib` Meson uses options provided by `llvm-config`.
|
||||
# The binary for `llvm-config` in Firefox CI comes from a native Linux clang,
|
||||
# which gives the link options for the Linux libLLVM-11.so in the Linux clang.
|
||||
# However, we want to link against a native macOS clang's libLLVM.dylib, which
|
||||
# we have available in a separate directory.
|
||||
# Meson will still have -lLLVM-11 on the command line, but the linker will
|
||||
# only warn that it has the wrong format (because it's not for macOS).
|
||||
cpp_link_args = ['-L/builds/worker/fetches/clang-mac/clang/lib', '-lLLVM']
|
||||
|
||||
[host_machine]
|
||||
system = 'darwin'
|
||||
cpu_family = 'x86_64'
|
||||
cpu = 'i686'
|
||||
endian = 'little'
|
22
third_party/webrender/ci-scripts/install-meson.sh
vendored
Executable file
22
third_party/webrender/ci-scripts/install-meson.sh
vendored
Executable file
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# 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/. */
|
||||
|
||||
# This file downloads and installs meson which is required for building
|
||||
# osmesa-src, a dependency of wrench.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
MESON_VER=0.55.1
|
||||
MESON_BASE_URL="https://github.com/mesonbuild/meson/releases/download"
|
||||
|
||||
curl -L ${MESON_BASE_URL}/${MESON_VER}/meson-${MESON_VER}.tar.gz -o meson.tar.gz
|
||||
tar -xf meson.tar.gz
|
||||
mv meson-${MESON_VER} meson
|
||||
cd meson
|
||||
ln -s meson.py meson
|
|
@ -32,5 +32,5 @@ cargo build ${CARGOFLAGS}
|
|||
popd
|
||||
|
||||
cargo test ${CARGOFLAGS} \
|
||||
--all --exclude compositor-windows --exclude compositor \
|
||||
--exclude glsl-to-cxx --exclude swgl
|
||||
--all --exclude compositor --exclude compositor-wayland \
|
||||
--exclude compositor-windows --exclude glsl-to-cxx --exclude swgl
|
||||
|
|
|
@ -16,7 +16,13 @@ set -o xtrace
|
|||
CARGOFLAGS=${CARGOFLAGS:-""} # default to empty if not set
|
||||
|
||||
pushd wrench
|
||||
# Test that all shaders compile successfully.
|
||||
python script/headless.py --precache test_init
|
||||
python script/headless.py --precache --use-unoptimized-shaders test_init
|
||||
|
||||
python script/headless.py reftest
|
||||
python script/headless.py rawtest
|
||||
cargo build ${CARGOFLAGS} --release
|
||||
python script/headless.py test_invalidation
|
||||
CXX=clang++ cargo run ${CARGOFLAGS} --release --features=software -- \
|
||||
--software --headless reftest
|
||||
popd
|
||||
|
|
|
@ -38,5 +38,5 @@ cargo check ${CARGOFLAGS}
|
|||
popd
|
||||
|
||||
cargo test ${CARGOFLAGS} ${CARGOTESTFLAGS} \
|
||||
--all --exclude compositor-windows --exclude compositor \
|
||||
--exclude glsl-to-cxx --exclude swgl
|
||||
--all --exclude compositor --exclude compositor-wayland \
|
||||
--exclude compositor-windows --exclude glsl-to-cxx --exclude swgl
|
||||
|
|
|
@ -19,7 +19,13 @@ CARGOFLAGS=${CARGOFLAGS:-""} # default to empty if not set
|
|||
WRENCH_BINARY=${WRENCH_BINARY:-""}
|
||||
|
||||
pushd wrench
|
||||
|
||||
# Test that all shaders compile successfully.
|
||||
python script/headless.py --precache test_init
|
||||
python script/headless.py --precache --use-unoptimized-shaders test_init
|
||||
|
||||
python script/headless.py reftest
|
||||
python script/headless.py test_invalidation
|
||||
if [[ -z "${WRENCH_BINARY}" ]]; then
|
||||
cargo build ${CARGOFLAGS} --release
|
||||
WRENCH_BINARY="../target/release/wrench"
|
||||
|
|
|
@ -21,6 +21,13 @@ popd
|
|||
pushd wrench
|
||||
cargo test --verbose
|
||||
if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL%
|
||||
:: Test that all shaders compile successfully. --precache compiles all shaders
|
||||
:: during initialization, therefore if init is successful then the shaders compile.
|
||||
cargo run --release -- --angle --precache test_init
|
||||
if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL%
|
||||
cargo run --release -- --angle --precache --use-unoptimized-shaders test_init
|
||||
if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL%
|
||||
|
||||
cargo run --release -- --angle reftest
|
||||
if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL%
|
||||
popd
|
||||
|
@ -29,8 +36,3 @@ pushd examples
|
|||
cargo check --verbose
|
||||
if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL%
|
||||
popd
|
||||
|
||||
pushd direct-composition
|
||||
cargo check --verbose
|
||||
if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL%
|
||||
popd
|
||||
|
|
6
third_party/webrender/debugger/.babelrc
vendored
6
third_party/webrender/debugger/.babelrc
vendored
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
["env", { "modules": false }],
|
||||
"stage-3"
|
||||
]
|
||||
}
|
11
third_party/webrender/debugger/.gitignore
vendored
11
third_party/webrender/debugger/.gitignore
vendored
|
@ -1,11 +0,0 @@
|
|||
.DS_Store
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
23
third_party/webrender/debugger/README.md
vendored
23
third_party/webrender/debugger/README.md
vendored
|
@ -1,23 +0,0 @@
|
|||
# WebRender Debugger
|
||||
A web based debugger for WebRender.
|
||||
|
||||
## Using the debugger
|
||||
Build your application with the debugger feature enabled, for example in wrench:
|
||||
|
||||
```
|
||||
cargo build --features=debugger
|
||||
```
|
||||
|
||||
Now, open your browser and open the debugger/index.html file. Click Connect and
|
||||
the debugger will attempt to connect to WR via websocket.
|
||||
|
||||
## Using the debugger with Gecko
|
||||
|
||||
In the Gecko source tree, open ```gfx/webrender_bindings/Cargo.toml``` in a text editor.
|
||||
|
||||
Add ```features = ['debugger']``` to the end of the file (in the ```dependencies.webrender``` section).
|
||||
|
||||
Vendor the rust dependencies locally for the debugger (we don't want these committed to the repo):
|
||||
```./mach vendor rust```
|
||||
|
||||
Now, build and run as usual, and the debugger will be available.
|
13
third_party/webrender/debugger/dist/build.js
vendored
13
third_party/webrender/debugger/dist/build.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
11
third_party/webrender/debugger/index.html
vendored
11
third_party/webrender/debugger/index.html
vendored
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebRender Debugger</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="dist/build.js"></script>
|
||||
</body>
|
||||
</html>
|
7606
third_party/webrender/debugger/package-lock.json
generated
vendored
7606
third_party/webrender/debugger/package-lock.json
generated
vendored
File diff suppressed because it is too large
Load diff
36
third_party/webrender/debugger/package.json
vendored
36
third_party/webrender/debugger/package.json
vendored
|
@ -1,36 +0,0 @@
|
|||
{
|
||||
"name": "debugger",
|
||||
"description": "WebRender Debugger",
|
||||
"version": "1.0.0",
|
||||
"author": "Glenn Watson <github@intuitionlibrary.com>",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
|
||||
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
|
||||
},
|
||||
"dependencies": {
|
||||
"buefy": "^0.6.7",
|
||||
"vue": "^2.5.11",
|
||||
"vue-material-design-icons": "^0.8.2",
|
||||
"vuex": "^3.0.1"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not ie <= 8"
|
||||
],
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"babel-preset-stage-3": "^6.24.1",
|
||||
"cross-env": "^5.0.5",
|
||||
"css-loader": "^0.28.7",
|
||||
"file-loader": "^1.1.4",
|
||||
"vue-loader": "^13.0.5",
|
||||
"vue-template-compiler": "^2.4.4",
|
||||
"webpack": "^3.6.0",
|
||||
"webpack-dev-server": "^2.9.1"
|
||||
}
|
||||
}
|
55
third_party/webrender/debugger/src/App.vue
vendored
55
third_party/webrender/debugger/src/App.vue
vendored
|
@ -1,55 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<app-navbar></app-navbar>
|
||||
<div class="section">
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column is-3">
|
||||
<app-navmenu></app-navmenu>
|
||||
</div>
|
||||
<div class="column">
|
||||
<app-options v-if="page == 'options'"></app-options>
|
||||
<app-passview v-if="page == 'passes'"></app-passview>
|
||||
<app-rendertaskview v-if="page == 'render_tasks'"></app-rendertaskview>
|
||||
<app-documentview v-if="page == 'documents'"></app-documentview>
|
||||
<app-clipscrolltreeview v-if="page == 'clip_scroll_tree'"></app-clipscrolltreeview>
|
||||
<app-screenshotview v-if="page == 'screenshot'"></app-screenshotview>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NavBar from './components/NavBar.vue'
|
||||
import NavMenu from './components/NavMenu.vue'
|
||||
import OptionsPage from './components/OptionsPage.vue'
|
||||
import PassViewPage from './components/PassViewPage.vue'
|
||||
import RenderTaskViewPage from './components/RenderTaskViewPage.vue'
|
||||
import DocumentViewPage from './components/DocumentViewPage.vue'
|
||||
import ClipScrollTreeViewPage from './components/ClipScrollTreeViewPage.vue'
|
||||
import ScreenshotPage from './components/ScreenshotPage.vue'
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {
|
||||
'app-navbar': NavBar,
|
||||
'app-navmenu': NavMenu,
|
||||
'app-options': OptionsPage,
|
||||
'app-passview': PassViewPage,
|
||||
'app-rendertaskview': RenderTaskViewPage,
|
||||
'app-documentview': DocumentViewPage,
|
||||
'app-clipscrolltreeview': ClipScrollTreeViewPage,
|
||||
'app-screenshotview': ScreenshotPage,
|
||||
},
|
||||
computed: {
|
||||
page() {
|
||||
return this.$store.state.page;
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -1,37 +0,0 @@
|
|||
<template>
|
||||
<div class="box">
|
||||
<h1 class="title">Clip-Scroll Tree <a :disabled="disabled" v-on:click="fetch" class="button is-info">Refresh</a></h1>
|
||||
<hr/>
|
||||
<div>
|
||||
<ul>
|
||||
<app-treeview :model=clip_scroll_tree></app-treeview>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TreeView from './TreeView.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
'app-treeview': TreeView,
|
||||
},
|
||||
methods: {
|
||||
fetch: function() {
|
||||
this.$store.dispatch('sendMessage', "fetch_clip_scroll_tree");
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
disabled() {
|
||||
return !this.$store.state.connected
|
||||
},
|
||||
clip_scroll_tree() {
|
||||
return this.$store.state.clip_scroll_tree
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -1,37 +0,0 @@
|
|||
<template>
|
||||
<div class="box">
|
||||
<h1 class="title">Documents <a :disabled="disabled" v-on:click="fetch" class="button is-info">Refresh</a></h1>
|
||||
<hr/>
|
||||
<div>
|
||||
<ul>
|
||||
<app-treeview :model=documents></app-treeview>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TreeView from './TreeView.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
'app-treeview': TreeView,
|
||||
},
|
||||
methods: {
|
||||
fetch: function() {
|
||||
this.$store.dispatch('sendMessage', "fetch_documents");
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
disabled() {
|
||||
return !this.$store.state.connected
|
||||
},
|
||||
documents() {
|
||||
return this.$store.state.documents
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -1,41 +0,0 @@
|
|||
<template>
|
||||
<nav class="navbar has-shadow">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="#">WebRender Debugger</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-start"></div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<p class="control">
|
||||
<button v-if="isConnected" @click="disconnect" class="button is-danger">Disconnect</button>
|
||||
<button v-else @click="connect" class="button is-success">Connect</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
isConnected() {
|
||||
return this.$store.state.connected;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
connect() {
|
||||
this.$store.dispatch('connect');
|
||||
},
|
||||
disconnect() {
|
||||
this.$store.dispatch('disconnect');
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -1,33 +0,0 @@
|
|||
<template>
|
||||
<aside class="menu">
|
||||
<p class="menu-label">
|
||||
Pages
|
||||
</p>
|
||||
<ul class="menu-list">
|
||||
<li><a @click="setPage('options')" :class="{ 'is-active': page == 'options' }">Debug Options</a></li>
|
||||
<li><a @click="setPage('passes')" :class="{ 'is-active': page == 'passes' }">Passes</a></li>
|
||||
<li><a @click="setPage('render_tasks')" :class="{ 'is-active': page == 'render_tasks' }">Render Tasks</a></li>
|
||||
<li><a @click="setPage('documents')" :class="{ 'is-active': page == 'documents' }">Documents</a></li>
|
||||
<li><a @click="setPage('clip_scroll_tree')" v-bind:class="{ 'is-active': page == 'clip_scroll_tree' }">Clip-Scroll Tree</a></li>
|
||||
<li><a @click="setPage('screenshot')" v-bind:class="{ 'is-active': page == 'screenshot' }">Screenshot</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
setPage(name) {
|
||||
this.$store.commit('setPage', name);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
page() {
|
||||
return this.$store.state.page;
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -1,162 +0,0 @@
|
|||
<template>
|
||||
<div class="box">
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" :disabled="disabled" v-on:click="setProfiler($event.target.checked)">
|
||||
Profiler
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" :disabled="disabled" v-on:click="setTextureCacheDebugger($event.target.checked)">
|
||||
Texture cache debugger
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" :disabled="disabled" v-on:click="setRenderTargetDebugger($event.target.checked)">
|
||||
Render target debugger
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" :disabled="disabled" v-on:click="setAlphaRectsDebugger($event.target.checked)">
|
||||
Alpha primitive rects debugger
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" :disabled="disabled" v-on:click="setGpuTimeQueries($event.target.checked)">
|
||||
Enable GPU time queries
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" :disabled="disabled" v-on:click="setGpuSampleQueries($event.target.checked)">
|
||||
Enable GPU sample queries
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" :disabled="disabled" v-on:click="setOpaquePass(!$event.target.checked)">
|
||||
Disable opaque pass
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" :disabled="disabled" v-on:click="setAlphaPass(!$event.target.checked)">
|
||||
Disable alpha pass
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" :disabled="disabled" v-on:click="setClipMasks(!$event.target.checked)">
|
||||
Disable clip masks
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" :disabled="disabled" v-on:click="setTextPrims(!$event.target.checked)">
|
||||
Disable text primitives
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" :disabled="disabled" v-on:click="setGradientPrims(!$event.target.checked)">
|
||||
Disable gradient primitives
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
disabled() {
|
||||
return !this.$store.state.connected
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setProfiler(enabled) {
|
||||
if (enabled) {
|
||||
this.$store.dispatch('sendMessage', "enable_profiler");
|
||||
} else {
|
||||
this.$store.dispatch('sendMessage', "disable_profiler");
|
||||
}
|
||||
},
|
||||
setTextureCacheDebugger(enabled) {
|
||||
if (enabled) {
|
||||
this.$store.dispatch('sendMessage', "enable_texture_cache_debug");
|
||||
} else {
|
||||
this.$store.dispatch('sendMessage', "disable_texture_cache_debug");
|
||||
}
|
||||
},
|
||||
setRenderTargetDebugger(enabled) {
|
||||
if (enabled) {
|
||||
this.$store.dispatch('sendMessage', "enable_render_target_debug");
|
||||
} else {
|
||||
this.$store.dispatch('sendMessage', "disable_render_target_debug");
|
||||
}
|
||||
},
|
||||
setAlphaRectsDebugger(enabled) {
|
||||
if (enabled) {
|
||||
this.$store.dispatch('sendMessage', "enable_alpha_rects_debug");
|
||||
} else {
|
||||
this.$store.dispatch('sendMessage', "disable_alpha_rects_debug");
|
||||
}
|
||||
},
|
||||
setGpuTimeQueries(enabled) {
|
||||
if (enabled) {
|
||||
this.$store.dispatch('sendMessage', "enable_gpu_time_queries");
|
||||
} else {
|
||||
this.$store.dispatch('sendMessage', "disable_gpu_time_queries");
|
||||
}
|
||||
},
|
||||
setGpuSampleQueries(enabled) {
|
||||
if (enabled) {
|
||||
this.$store.dispatch('sendMessage', "enable_gpu_sample_queries");
|
||||
} else {
|
||||
this.$store.dispatch('sendMessage', "disable_gpu_sample_queries");
|
||||
}
|
||||
},
|
||||
setOpaquePass(enabled) {
|
||||
if (enabled) {
|
||||
this.$store.dispatch('sendMessage', "enable_opaque_pass");
|
||||
} else {
|
||||
this.$store.dispatch('sendMessage', "disable_opaque_pass");
|
||||
}
|
||||
},
|
||||
setAlphaPass(enabled) {
|
||||
if (enabled) {
|
||||
this.$store.dispatch('sendMessage', "enable_alpha_pass");
|
||||
} else {
|
||||
this.$store.dispatch('sendMessage', "disable_alpha_pass");
|
||||
}
|
||||
},
|
||||
setClipMasks(enabled) {
|
||||
if (enabled) {
|
||||
this.$store.dispatch('sendMessage', "enable_clip_masks");
|
||||
} else {
|
||||
this.$store.dispatch('sendMessage', "disable_clip_masks");
|
||||
}
|
||||
},
|
||||
setTextPrims(enabled) {
|
||||
if (enabled) {
|
||||
this.$store.dispatch('sendMessage', "enable_text_prims");
|
||||
} else {
|
||||
this.$store.dispatch('sendMessage', "disable_text_prims");
|
||||
}
|
||||
},
|
||||
setGradientPrims(enabled) {
|
||||
if (enabled) {
|
||||
this.$store.dispatch('sendMessage', "enable_gradient_prims");
|
||||
} else {
|
||||
this.$store.dispatch('sendMessage', "disable_gradient_prims");
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -1,37 +0,0 @@
|
|||
<template>
|
||||
<div class="box">
|
||||
<h1 class="title">Passes <a :disabled="disabled" v-on:click="fetch" class="button is-info">Refresh</a></h1>
|
||||
<hr/>
|
||||
<div v-for="(pass, pass_index) in passes">
|
||||
<p class="has-text-black-bis">Pass {{pass_index}}</p>
|
||||
<div v-for="(target, target_index) in pass.targets">
|
||||
<p style="text-indent: 2em;" class="has-text-grey-dark">Target {{target_index}} ({{target.kind}})</p>
|
||||
<div v-for="(batch, batch_index) in target.batches">
|
||||
<p style="text-indent: 4em;" class="has-text-grey">Batch {{batch_index}} ({{batch.description}}, {{batch.kind}}, {{batch.count}} instances)</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
fetch: function() {
|
||||
this.$store.dispatch('sendMessage', "fetch_passes");
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
disabled() {
|
||||
return !this.$store.state.connected
|
||||
},
|
||||
passes() {
|
||||
return this.$store.state.passes
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -1,37 +0,0 @@
|
|||
<template>
|
||||
<div class="box">
|
||||
<h1 class="title">Render Tasks <a :disabled="disabled" v-on:click="fetch" class="button is-info">Refresh</a></h1>
|
||||
<hr/>
|
||||
<div>
|
||||
<ul>
|
||||
<app-treeview :model=render_tasks></app-treeview>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TreeView from './TreeView.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
'app-treeview': TreeView,
|
||||
},
|
||||
methods: {
|
||||
fetch: function() {
|
||||
this.$store.dispatch('sendMessage', "fetch_render_tasks");
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
disabled() {
|
||||
return !this.$store.state.connected
|
||||
},
|
||||
render_tasks() {
|
||||
return this.$store.state.render_tasks
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -1,32 +0,0 @@
|
|||
<template>
|
||||
<div class="box">
|
||||
<h1 class="title">Screenshot <a :disabled="disabled" v-on:click="fetch" class="button is-info">Refresh</a></h1>
|
||||
<hr/>
|
||||
<div>
|
||||
<ul>
|
||||
<img v-if="screenshot.length > 0" style="transform: scaleY(-1); width: 1024px; height:768px" :src="'data:image/png;base64,' + screenshot" />
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
disabled() {
|
||||
return !this.$store.state.connected
|
||||
},
|
||||
screenshot() {
|
||||
return this.$store.state.screenshot
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
fetch: function() {
|
||||
this.$store.dispatch('sendMessage', "fetch_screenshot");
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -1,40 +0,0 @@
|
|||
<template>
|
||||
<li>
|
||||
<div v-on:click="toggle">
|
||||
<span v-if="isFolder">[{{open ? '-' : '+'}}]</span>
|
||||
{{model.description}}
|
||||
</div>
|
||||
<ul style="padding-left: 1em; line-height: 1.5em;" v-show="open" v-if="isFolder">
|
||||
<treeview v-for="model in model.children" :model="model"></treeview>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'treeview',
|
||||
props: [
|
||||
'model',
|
||||
],
|
||||
data: function () {
|
||||
return {
|
||||
open: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isFolder: function () {
|
||||
return this.model.children && this.model.children.length
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggle: function () {
|
||||
if (this.isFolder) {
|
||||
this.open = !this.open
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
14
third_party/webrender/debugger/src/main.js
vendored
14
third_party/webrender/debugger/src/main.js
vendored
|
@ -1,14 +0,0 @@
|
|||
import Vue from 'vue';
|
||||
import Buefy from 'buefy';
|
||||
import 'buefy/dist/buefy.css';
|
||||
import "vue-material-design-icons/styles.css";
|
||||
import App from './App.vue';
|
||||
import store from './store';
|
||||
|
||||
Vue.use(Buefy);
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
store,
|
||||
render: h => h(App)
|
||||
})
|
105
third_party/webrender/debugger/src/store/index.js
vendored
105
third_party/webrender/debugger/src/store/index.js
vendored
|
@ -1,105 +0,0 @@
|
|||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
class Connection {
|
||||
constructor() {
|
||||
this.ws = null;
|
||||
}
|
||||
|
||||
connect(context) {
|
||||
var ws = new WebSocket("ws://127.0.0.1:3583");
|
||||
|
||||
ws.onopen = function() {
|
||||
context.commit('setConnected', true);
|
||||
}
|
||||
|
||||
ws.onmessage = function(evt) {
|
||||
var json = JSON.parse(evt.data);
|
||||
if (json['kind'] == "passes") {
|
||||
context.commit('setPasses', json['passes']);
|
||||
} else if (json['kind'] == "render_tasks") {
|
||||
context.commit('setRenderTasks', json['root']);
|
||||
} else if (json['kind'] == "documents") {
|
||||
context.commit('setDocuments', json['root']);
|
||||
} else if (json['kind'] == "clip_scroll_tree") {
|
||||
context.commit('setClipScrollTree', json['root']);
|
||||
} else if (json['kind'] == "screenshot") {
|
||||
context.commit('setScreenshot', json['data']);
|
||||
} else {
|
||||
console.warn("unknown message kind: " + json['kind']);
|
||||
}
|
||||
}
|
||||
|
||||
ws.onclose = function() {
|
||||
context.commit('setConnected', false);
|
||||
}
|
||||
|
||||
this.ws = ws;
|
||||
}
|
||||
|
||||
send(msg) {
|
||||
if (this.ws !== null) {
|
||||
this.ws.send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if (this.ws !== null) {
|
||||
this.ws.close();
|
||||
this.ws = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var connection = new Connection();
|
||||
|
||||
const store = new Vuex.Store({
|
||||
strict: true,
|
||||
state: {
|
||||
connected: false,
|
||||
page: 'options',
|
||||
passes: [],
|
||||
render_tasks: [],
|
||||
documents: [],
|
||||
clip_scroll_tree: [],
|
||||
screenshot: [],
|
||||
},
|
||||
mutations: {
|
||||
setConnected(state, connected) {
|
||||
state.connected = connected;
|
||||
},
|
||||
setPage(state, name) {
|
||||
state.page = name;
|
||||
},
|
||||
setPasses(state, passes) {
|
||||
state.passes = passes;
|
||||
},
|
||||
setRenderTasks(state, render_tasks) {
|
||||
state.render_tasks = render_tasks;
|
||||
},
|
||||
setDocuments(state, documents) {
|
||||
state.documents = documents;
|
||||
},
|
||||
setClipScrollTree(state, clip_scroll_tree) {
|
||||
state.clip_scroll_tree = clip_scroll_tree;
|
||||
},
|
||||
setScreenshot(state, screenshot) {
|
||||
state.screenshot = screenshot;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
connect(context) {
|
||||
connection.connect(context);
|
||||
},
|
||||
disconnect(context) {
|
||||
connection.disconnect();
|
||||
},
|
||||
sendMessage(context, msg) {
|
||||
connection.send(msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default store;
|
81
third_party/webrender/debugger/webpack.config.js
vendored
81
third_party/webrender/debugger/webpack.config.js
vendored
|
@ -1,81 +0,0 @@
|
|||
var path = require('path')
|
||||
var webpack = require('webpack')
|
||||
|
||||
module.exports = {
|
||||
entry: './src/main.js',
|
||||
output: {
|
||||
path: path.resolve(__dirname, './dist'),
|
||||
publicPath: '/dist/',
|
||||
filename: 'build.js'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'vue-style-loader',
|
||||
'css-loader'
|
||||
],
|
||||
}, {
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader',
|
||||
options: {
|
||||
loaders: {
|
||||
}
|
||||
// other vue-loader options go here
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg|gif|svg)$/,
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[ext]?[hash]'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'vue$': 'vue/dist/vue.esm.js'
|
||||
},
|
||||
alias : {
|
||||
"icons": path.resolve(__dirname, "node_modules/vue-material-design-icons")
|
||||
},
|
||||
extensions: ['*', '.js', '.vue', '.json']
|
||||
},
|
||||
devServer: {
|
||||
historyApiFallback: true,
|
||||
noInfo: true,
|
||||
overlay: true
|
||||
},
|
||||
performance: {
|
||||
hints: false
|
||||
},
|
||||
devtool: '#eval-source-map'
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
module.exports.devtool = '#source-map'
|
||||
// http://vue-loader.vuejs.org/en/workflow/production.html
|
||||
module.exports.plugins = (module.exports.plugins || []).concat([
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: '"production"'
|
||||
}
|
||||
}),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
sourceMap: true,
|
||||
compress: {
|
||||
warnings: false
|
||||
}
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
minimize: true
|
||||
})
|
||||
])
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
[package]
|
||||
name = "direct-composition"
|
||||
version = "0.1.0"
|
||||
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
|
||||
license = "MPL-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
euclid = "0.22"
|
||||
gleam = "0.12"
|
||||
mozangle = {version = "0.3.1", features = ["egl"]}
|
||||
webrender = {path = "../webrender"}
|
||||
winapi = {version = "0.3", features = ["winerror", "d3d11", "dcomp"]}
|
||||
winit = "0.19"
|
112
third_party/webrender/direct-composition/src/com.rs
vendored
112
third_party/webrender/direct-composition/src/com.rs
vendored
|
@ -1,112 +0,0 @@
|
|||
/* 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 std::ops;
|
||||
use std::ptr;
|
||||
use winapi::Interface;
|
||||
use winapi::ctypes::c_void;
|
||||
use winapi::shared::guiddef::GUID;
|
||||
use winapi::shared::winerror::HRESULT;
|
||||
use winapi::shared::winerror::SUCCEEDED;
|
||||
use winapi::um::unknwnbase::IUnknown;
|
||||
|
||||
pub fn as_ptr<T>(x: &T) -> *mut T {
|
||||
x as *const T as _
|
||||
}
|
||||
|
||||
pub trait CheckHResult {
|
||||
fn check_hresult(self);
|
||||
}
|
||||
|
||||
impl CheckHResult for HRESULT {
|
||||
fn check_hresult(self) {
|
||||
if !SUCCEEDED(self) {
|
||||
panic_com(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn panic_com(hresult: HRESULT) -> ! {
|
||||
panic!("COM error 0x{:08X}", hresult as u32)
|
||||
}
|
||||
|
||||
/// Forked from <https://github.com/retep998/wio-rs/blob/44093f7db8/src/com.rs>
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct ComPtr<T>(*mut T) where T: Interface;
|
||||
|
||||
impl<T> ComPtr<T> where T: Interface {
|
||||
/// Creates a `ComPtr` to wrap a raw pointer.
|
||||
/// It takes ownership over the pointer which means it does __not__ call `AddRef`.
|
||||
/// `T` __must__ be a COM interface that inherits from `IUnknown`.
|
||||
pub unsafe fn from_raw(ptr: *mut T) -> ComPtr<T> {
|
||||
assert!(!ptr.is_null());
|
||||
ComPtr(ptr)
|
||||
}
|
||||
|
||||
/// For use with APIs that take an interface UUID and
|
||||
/// "return" a new COM object through a `*mut *mut c_void` out-parameter.
|
||||
pub unsafe fn new_with_uuid<F>(f: F) -> Self
|
||||
where F: FnOnce(&GUID, *mut *mut c_void) -> HRESULT
|
||||
{
|
||||
Self::new_with(|ptr| f(&T::uuidof(), ptr as _))
|
||||
}
|
||||
|
||||
/// For use with APIs that "return" a new COM object through a `*mut *mut T` out-parameter.
|
||||
pub unsafe fn new_with<F>(f: F) -> Self
|
||||
where F: FnOnce(*mut *mut T) -> HRESULT
|
||||
{
|
||||
let mut ptr = ptr::null_mut();
|
||||
let hresult = f(&mut ptr);
|
||||
if SUCCEEDED(hresult) {
|
||||
ComPtr::from_raw(ptr)
|
||||
} else {
|
||||
if !ptr.is_null() {
|
||||
let ptr = ptr as *mut IUnknown;
|
||||
(*ptr).Release();
|
||||
}
|
||||
panic_com(hresult)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_raw(&self) -> *mut T {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn as_unknown(&self) -> &IUnknown {
|
||||
unsafe {
|
||||
&*(self.0 as *mut IUnknown)
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs QueryInterface fun.
|
||||
pub fn cast<U>(&self) -> ComPtr<U> where U: Interface {
|
||||
unsafe {
|
||||
ComPtr::<U>::new_with_uuid(|uuid, ptr| self.as_unknown().QueryInterface(uuid, ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ops::Deref for ComPtr<T> where T: Interface {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { &*self.0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for ComPtr<T> where T: Interface {
|
||||
fn clone(&self) -> Self {
|
||||
unsafe {
|
||||
self.as_unknown().AddRef();
|
||||
ComPtr(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for ComPtr<T> where T: Interface {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.as_unknown().Release();
|
||||
}
|
||||
}
|
||||
}
|
174
third_party/webrender/direct-composition/src/egl.rs
vendored
174
third_party/webrender/direct-composition/src/egl.rs
vendored
|
@ -1,174 +0,0 @@
|
|||
/* 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 mozangle::egl::ffi::*;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use winapi::um::d3d11::ID3D11Device;
|
||||
use winapi::um::d3d11::ID3D11Texture2D;
|
||||
|
||||
pub use mozangle::egl::get_proc_address;
|
||||
|
||||
pub struct SharedEglThings {
|
||||
device: EGLDeviceEXT,
|
||||
display: types::EGLDisplay,
|
||||
config: types::EGLConfig,
|
||||
context: types::EGLContext,
|
||||
}
|
||||
|
||||
fn cast_attributes(slice: &[types::EGLenum]) -> &EGLint {
|
||||
unsafe {
|
||||
&*(slice.as_ptr() as *const EGLint)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! attributes {
|
||||
($( $key: expr => $value: expr, )*) => {
|
||||
cast_attributes(&[
|
||||
$( $key, $value, )*
|
||||
NONE,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl SharedEglThings {
|
||||
pub unsafe fn new(d3d_device: *mut ID3D11Device) -> Rc<Self> {
|
||||
let device = eglCreateDeviceANGLE(
|
||||
D3D11_DEVICE_ANGLE,
|
||||
d3d_device as *mut c_void,
|
||||
ptr::null(),
|
||||
).check();
|
||||
let display = GetPlatformDisplayEXT(
|
||||
PLATFORM_DEVICE_EXT,
|
||||
device,
|
||||
attributes! [
|
||||
EXPERIMENTAL_PRESENT_PATH_ANGLE => EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE,
|
||||
],
|
||||
).check();
|
||||
Initialize(display, ptr::null_mut(), ptr::null_mut()).check();
|
||||
|
||||
// Adapted from
|
||||
// https://searchfox.org/mozilla-central/rev/056a4057/gfx/gl/GLContextProviderEGL.cpp#635
|
||||
let mut configs = [ptr::null(); 64];
|
||||
let mut num_configs = 0;
|
||||
ChooseConfig(
|
||||
display,
|
||||
attributes! [
|
||||
SURFACE_TYPE => WINDOW_BIT,
|
||||
RENDERABLE_TYPE => OPENGL_ES2_BIT,
|
||||
RED_SIZE => 8,
|
||||
GREEN_SIZE => 8,
|
||||
BLUE_SIZE => 8,
|
||||
ALPHA_SIZE => 8,
|
||||
],
|
||||
configs.as_mut_ptr(),
|
||||
configs.len() as i32,
|
||||
&mut num_configs,
|
||||
).check();
|
||||
let config = pick_config(&configs[..num_configs as usize]);
|
||||
|
||||
let context = CreateContext(
|
||||
display, config, NO_CONTEXT,
|
||||
attributes![
|
||||
CONTEXT_CLIENT_VERSION => 3,
|
||||
]
|
||||
).check();
|
||||
MakeCurrent(display, NO_SURFACE, NO_SURFACE, context).check();
|
||||
|
||||
Rc::new(SharedEglThings { device, display, config, context })
|
||||
}
|
||||
}
|
||||
|
||||
fn pick_config(configs: &[types::EGLConfig]) -> types::EGLConfig {
|
||||
// FIXME: better criteria to make this choice?
|
||||
// Firefox uses GetConfigAttrib to find a config that has the requested r/g/b/a sizes
|
||||
// https://searchfox.org/mozilla-central/rev/056a4057/gfx/gl/GLContextProviderEGL.cpp#662-685
|
||||
|
||||
configs[0]
|
||||
}
|
||||
|
||||
impl Drop for SharedEglThings {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// FIXME does EGLDisplay or EGLConfig need clean up? How?
|
||||
DestroyContext(self.display, self.context).check();
|
||||
eglReleaseDeviceANGLE(self.device).check();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PerVisualEglThings {
|
||||
shared: Rc<SharedEglThings>,
|
||||
surface: types::EGLSurface,
|
||||
}
|
||||
|
||||
impl PerVisualEglThings {
|
||||
pub unsafe fn new(shared: Rc<SharedEglThings>, buffer: *const ID3D11Texture2D,
|
||||
width: u32, height: u32)
|
||||
-> Self {
|
||||
let surface = CreatePbufferFromClientBuffer(
|
||||
shared.display,
|
||||
D3D_TEXTURE_ANGLE,
|
||||
buffer as types::EGLClientBuffer,
|
||||
shared.config,
|
||||
attributes! [
|
||||
WIDTH => width,
|
||||
HEIGHT => height,
|
||||
FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE => TRUE,
|
||||
],
|
||||
).check();
|
||||
|
||||
PerVisualEglThings { shared, surface }
|
||||
}
|
||||
|
||||
pub fn make_current(&self) {
|
||||
unsafe {
|
||||
MakeCurrent(self.shared.display, self.surface, self.surface, self.shared.context).check();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PerVisualEglThings {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
DestroySurface(self.shared.display, self.surface).check();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_error() {
|
||||
unsafe {
|
||||
let error = GetError() as types::EGLenum;
|
||||
assert_eq!(error, SUCCESS, "0x{:x} != 0x{:x}", error, SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
trait Check {
|
||||
fn check(self) -> Self;
|
||||
}
|
||||
|
||||
impl Check for *const c_void {
|
||||
fn check(self) -> Self {
|
||||
check_error();
|
||||
assert!(!self.is_null());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for *mut c_void {
|
||||
fn check(self) -> Self {
|
||||
check_error();
|
||||
assert!(!self.is_null());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for types::EGLBoolean {
|
||||
fn check(self) -> Self {
|
||||
check_error();
|
||||
assert_eq!(self, TRUE);
|
||||
self
|
||||
}
|
||||
}
|
179
third_party/webrender/direct-composition/src/lib.rs
vendored
179
third_party/webrender/direct-composition/src/lib.rs
vendored
|
@ -1,179 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
#![cfg(windows)]
|
||||
|
||||
use gleam;
|
||||
use mozangle;
|
||||
use winapi;
|
||||
|
||||
use com::{ComPtr, CheckHResult, as_ptr};
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use winapi::shared::dxgi1_2::DXGI_SWAP_CHAIN_DESC1;
|
||||
use winapi::shared::dxgi1_2::IDXGIFactory2;
|
||||
use winapi::shared::minwindef::{TRUE, FALSE};
|
||||
use winapi::shared::windef::HWND;
|
||||
use winapi::um::d3d11::ID3D11Device;
|
||||
use winapi::um::dcomp::IDCompositionDevice;
|
||||
use winapi::um::dcomp::IDCompositionTarget;
|
||||
use winapi::um::dcomp::IDCompositionVisual;
|
||||
|
||||
mod com;
|
||||
mod egl;
|
||||
|
||||
pub struct DirectComposition {
|
||||
d3d_device: ComPtr<ID3D11Device>,
|
||||
dxgi_factory: ComPtr<IDXGIFactory2>,
|
||||
|
||||
egl: Rc<egl::SharedEglThings>,
|
||||
pub gleam: Rc<dyn gleam::gl::Gl>,
|
||||
|
||||
composition_device: ComPtr<IDCompositionDevice>,
|
||||
root_visual: ComPtr<IDCompositionVisual>,
|
||||
|
||||
#[allow(unused)] // Needs to be kept alive
|
||||
composition_target: ComPtr<IDCompositionTarget>,
|
||||
}
|
||||
|
||||
impl DirectComposition {
|
||||
/// Initialize DirectComposition in the given window
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `hwnd` must be a valid handle to a window.
|
||||
pub unsafe fn new(hwnd: HWND) -> Self {
|
||||
let d3d_device = ComPtr::new_with(|ptr_ptr| winapi::um::d3d11::D3D11CreateDevice(
|
||||
ptr::null_mut(),
|
||||
winapi::um::d3dcommon::D3D_DRIVER_TYPE_HARDWARE,
|
||||
ptr::null_mut(),
|
||||
winapi::um::d3d11::D3D11_CREATE_DEVICE_BGRA_SUPPORT |
|
||||
if cfg!(debug_assertions) {
|
||||
winapi::um::d3d11::D3D11_CREATE_DEVICE_DEBUG
|
||||
} else {
|
||||
0
|
||||
},
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
winapi::um::d3d11::D3D11_SDK_VERSION,
|
||||
ptr_ptr,
|
||||
&mut 0,
|
||||
ptr::null_mut(),
|
||||
));
|
||||
|
||||
let egl = egl::SharedEglThings::new(d3d_device.as_raw());
|
||||
let gleam = gleam::gl::GlesFns::load_with(egl::get_proc_address);
|
||||
|
||||
let dxgi_device = d3d_device.cast::<winapi::shared::dxgi::IDXGIDevice>();
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/hh404556(v=vs.85).aspx#code-snippet-1
|
||||
// “Because you can create a Direct3D device without creating a swap chain,
|
||||
// you might need to retrieve the factory that is used to create the device
|
||||
// in order to create a swap chain.”
|
||||
let adapter = ComPtr::new_with(|ptr_ptr| dxgi_device.GetAdapter(ptr_ptr));
|
||||
let dxgi_factory = ComPtr::<IDXGIFactory2>::new_with_uuid(|uuid, ptr_ptr| {
|
||||
adapter.GetParent(uuid, ptr_ptr)
|
||||
});
|
||||
|
||||
// Create the DirectComposition device object.
|
||||
let composition_device = ComPtr::<IDCompositionDevice>::new_with_uuid(|uuid, ptr_ptr| {
|
||||
winapi::um::dcomp::DCompositionCreateDevice(&*dxgi_device, uuid, ptr_ptr)
|
||||
});
|
||||
|
||||
// Create the composition target object based on the
|
||||
// specified application window.
|
||||
let composition_target = ComPtr::new_with(|ptr_ptr| {
|
||||
composition_device.CreateTargetForHwnd(hwnd, TRUE, ptr_ptr)
|
||||
});
|
||||
|
||||
let root_visual = ComPtr::new_with(|ptr_ptr| composition_device.CreateVisual(ptr_ptr));
|
||||
composition_target.SetRoot(&*root_visual).check_hresult();
|
||||
|
||||
DirectComposition {
|
||||
d3d_device, dxgi_factory,
|
||||
egl, gleam,
|
||||
composition_device, composition_target, root_visual,
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute changes to the DirectComposition scene.
|
||||
pub fn commit(&self) {
|
||||
unsafe {
|
||||
self.composition_device.Commit().check_hresult()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_angle_visual(&self, width: u32, height: u32) -> AngleVisual {
|
||||
unsafe {
|
||||
let desc = DXGI_SWAP_CHAIN_DESC1 {
|
||||
Width: width,
|
||||
Height: height,
|
||||
Format: winapi::shared::dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
Stereo: FALSE,
|
||||
SampleDesc: winapi::shared::dxgitype::DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
BufferUsage: winapi::shared::dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
BufferCount: 2,
|
||||
Scaling: winapi::shared::dxgi1_2::DXGI_SCALING_STRETCH,
|
||||
SwapEffect: winapi::shared::dxgi::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
|
||||
AlphaMode: winapi::shared::dxgi1_2::DXGI_ALPHA_MODE_PREMULTIPLIED,
|
||||
Flags: 0,
|
||||
};
|
||||
let swap_chain = ComPtr::<winapi::shared::dxgi1_2::IDXGISwapChain1>::new_with(|ptr_ptr| {
|
||||
self.dxgi_factory.CreateSwapChainForComposition(
|
||||
as_ptr(&self.d3d_device),
|
||||
&desc,
|
||||
ptr::null_mut(),
|
||||
ptr_ptr,
|
||||
)
|
||||
});
|
||||
let back_buffer = ComPtr::<winapi::um::d3d11::ID3D11Texture2D>::new_with_uuid(|uuid, ptr_ptr| {
|
||||
swap_chain.GetBuffer(0, uuid, ptr_ptr)
|
||||
});
|
||||
let egl = egl::PerVisualEglThings::new(self.egl.clone(), &*back_buffer, width, height);
|
||||
let gleam = self.gleam.clone();
|
||||
|
||||
let visual = ComPtr::new_with(|ptr_ptr| self.composition_device.CreateVisual(ptr_ptr));
|
||||
visual.SetContent(&*****swap_chain).check_hresult();
|
||||
self.root_visual.AddVisual(&*visual, FALSE, ptr::null_mut()).check_hresult();
|
||||
|
||||
AngleVisual { visual, swap_chain, egl, gleam }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A DirectComposition "visual" configured for rendering with Direct3D.
|
||||
pub struct AngleVisual {
|
||||
visual: ComPtr<IDCompositionVisual>,
|
||||
swap_chain: ComPtr<winapi::shared::dxgi1_2::IDXGISwapChain1>,
|
||||
egl: egl::PerVisualEglThings,
|
||||
pub gleam: Rc<dyn gleam::gl::Gl>,
|
||||
}
|
||||
|
||||
impl AngleVisual {
|
||||
pub fn set_offset_x(&self, offset_x: f32) {
|
||||
unsafe {
|
||||
self.visual.SetOffsetX_1(offset_x).check_hresult()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_offset_y(&self, offset_y: f32) {
|
||||
unsafe {
|
||||
self.visual.SetOffsetY_1(offset_y).check_hresult()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_current(&self) {
|
||||
self.egl.make_current()
|
||||
}
|
||||
|
||||
pub fn present(&self) {
|
||||
self.gleam.finish();
|
||||
unsafe {
|
||||
self.swap_chain.Present(0, 0).check_hresult()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,212 +0,0 @@
|
|||
/* 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 direct_composition;
|
||||
use euclid;
|
||||
use gleam;
|
||||
use webrender;
|
||||
use winit;
|
||||
|
||||
use euclid::size2;
|
||||
use direct_composition::DirectComposition;
|
||||
use std::sync::mpsc;
|
||||
use webrender::api;
|
||||
use winit::os::windows::{WindowExt, WindowBuilderExt};
|
||||
use winit::dpi::LogicalSize;
|
||||
|
||||
fn main() {
|
||||
let mut events_loop = winit::EventsLoop::new();
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let notifier = Box::new(Notifier { events_proxy: events_loop.create_proxy(), tx });
|
||||
|
||||
let window = winit::WindowBuilder::new()
|
||||
.with_title("WebRender + ANGLE + DirectComposition")
|
||||
.with_dimensions(LogicalSize::new(1024., 768.))
|
||||
.with_decorations(true)
|
||||
.with_transparency(true)
|
||||
.with_no_redirection_bitmap(true)
|
||||
.build(&events_loop)
|
||||
.unwrap();
|
||||
|
||||
let composition = direct_composition_from_window(&window);
|
||||
let factor = window.get_hidpi_factor() as f32;
|
||||
|
||||
let mut clicks: usize = 0;
|
||||
let mut offset_y = 100.;
|
||||
let mut rects = [
|
||||
Rectangle::new(&composition, ¬ifier, factor, size2(300, 200), 0., 0.2, 0.4, 1.),
|
||||
Rectangle::new(&composition, ¬ifier, factor, size2(400, 300), 0., 0.5, 0., 0.5),
|
||||
];
|
||||
rects[0].render(factor, &rx);
|
||||
rects[1].render(factor, &rx);
|
||||
|
||||
rects[0].visual.set_offset_x(100.);
|
||||
rects[0].visual.set_offset_y(50.);
|
||||
|
||||
rects[1].visual.set_offset_x(200.);
|
||||
rects[1].visual.set_offset_y(offset_y);
|
||||
|
||||
composition.commit();
|
||||
|
||||
events_loop.run_forever(|event| {
|
||||
if let winit::Event::WindowEvent { event, .. } = event {
|
||||
match event {
|
||||
winit::WindowEvent::CloseRequested => {
|
||||
return winit::ControlFlow::Break
|
||||
}
|
||||
winit::WindowEvent::MouseWheel { delta, .. } => {
|
||||
let dy = match delta {
|
||||
winit::MouseScrollDelta::LineDelta(_, dy) => dy,
|
||||
winit::MouseScrollDelta::PixelDelta(pos) => pos.y as f32,
|
||||
};
|
||||
offset_y = (offset_y - 10. * dy).max(0.).min(468.);
|
||||
|
||||
rects[1].visual.set_offset_y(offset_y);
|
||||
composition.commit();
|
||||
}
|
||||
winit::WindowEvent::MouseInput {
|
||||
button: winit::MouseButton::Left,
|
||||
state: winit::ElementState::Pressed,
|
||||
..
|
||||
} => {
|
||||
clicks += 1;
|
||||
let rect = &mut rects[clicks % 2];
|
||||
rect.color.g += 0.1;
|
||||
rect.color.g %= 1.;
|
||||
rect.render(factor, &rx)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
winit::ControlFlow::Continue
|
||||
});
|
||||
}
|
||||
|
||||
fn direct_composition_from_window(window: &winit::Window) -> DirectComposition {
|
||||
unsafe {
|
||||
DirectComposition::new(window.get_hwnd() as _)
|
||||
}
|
||||
}
|
||||
|
||||
struct Rectangle {
|
||||
visual: direct_composition::AngleVisual,
|
||||
renderer: Option<webrender::Renderer>,
|
||||
api: api::RenderApi,
|
||||
document_id: api::DocumentId,
|
||||
size: api::units::DeviceIntSize,
|
||||
color: api::ColorF,
|
||||
}
|
||||
|
||||
impl Rectangle {
|
||||
fn new(composition: &DirectComposition, notifier: &Box<Notifier>,
|
||||
device_pixel_ratio: f32, size: api::units::DeviceIntSize, r: f32, g: f32, b: f32, a: f32)
|
||||
-> Self {
|
||||
let visual = composition.create_angle_visual(size.width as u32, size.height as u32);
|
||||
visual.make_current();
|
||||
|
||||
let (renderer, sender) = webrender::Renderer::new(
|
||||
composition.gleam.clone(),
|
||||
notifier.clone(),
|
||||
webrender::RendererOptions {
|
||||
clear_color: Some(api::ColorF::new(0., 0., 0., 0.)),
|
||||
device_pixel_ratio,
|
||||
..webrender::RendererOptions::default()
|
||||
},
|
||||
None,
|
||||
size,
|
||||
).unwrap();
|
||||
let api = sender.create_api();
|
||||
|
||||
Rectangle {
|
||||
visual,
|
||||
renderer: Some(renderer),
|
||||
document_id: api.add_document(size, 0),
|
||||
api,
|
||||
size,
|
||||
color: api::ColorF { r, g, b, a },
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, device_pixel_ratio: f32, rx: &mpsc::Receiver<()>) {
|
||||
self.visual.make_current();
|
||||
|
||||
let pipeline_id = api::PipelineId(0, 0);
|
||||
let layout_size = self.size.to_f32() / euclid::Scale::new(device_pixel_ratio);
|
||||
let mut builder = api::DisplayListBuilder::new(pipeline_id, layout_size);
|
||||
|
||||
let rect = euclid::Rect::new(euclid::Point2D::zero(), layout_size);
|
||||
|
||||
let region = api::ComplexClipRegion::new(
|
||||
rect,
|
||||
api::BorderRadius::uniform(20.),
|
||||
api::ClipMode::Clip
|
||||
);
|
||||
let clip_id = builder.define_clip_rounded_rect(
|
||||
&api::SpaceAndClipInfo::root_scroll(pipeline_id),
|
||||
region,
|
||||
);
|
||||
|
||||
builder.push_rect(
|
||||
&api::CommonItemProperties::new(
|
||||
rect,
|
||||
api::SpaceAndClipInfo {
|
||||
spatial_id: api::SpatialId::root_scroll_node(pipeline_id),
|
||||
clip_id,
|
||||
},
|
||||
),
|
||||
rect,
|
||||
self.color,
|
||||
);
|
||||
|
||||
let mut transaction = api::Transaction::new();
|
||||
transaction.set_display_list(
|
||||
api::Epoch(0),
|
||||
None,
|
||||
layout_size,
|
||||
builder.finalize(),
|
||||
true,
|
||||
);
|
||||
transaction.set_root_pipeline(pipeline_id);
|
||||
transaction.generate_frame();
|
||||
self.api.send_transaction(self.document_id, transaction);
|
||||
rx.recv().unwrap();
|
||||
let renderer = self.renderer.as_mut().unwrap();
|
||||
renderer.update();
|
||||
renderer.render(self.size).unwrap();
|
||||
let _ = renderer.flush_pipeline_info();
|
||||
self.visual.present();
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Rectangle {
|
||||
fn drop(&mut self) {
|
||||
self.renderer.take().unwrap().deinit()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Notifier {
|
||||
events_proxy: winit::EventsLoopProxy,
|
||||
tx: mpsc::Sender<()>,
|
||||
}
|
||||
|
||||
impl api::RenderNotifier for Notifier {
|
||||
fn clone(&self) -> Box<dyn api::RenderNotifier> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
|
||||
fn wake_up(&self) {
|
||||
self.tx.send(()).unwrap();
|
||||
let _ = self.events_proxy.wakeup();
|
||||
}
|
||||
|
||||
fn new_frame_ready(&self,
|
||||
_: api::DocumentId,
|
||||
_: bool,
|
||||
_: bool,
|
||||
_: Option<u64>) {
|
||||
self.wake_up();
|
||||
}
|
||||
}
|
11
third_party/webrender/example-compositor/compositor-wayland/Cargo.toml
vendored
Normal file
11
third_party/webrender/example-compositor/compositor-wayland/Cargo.toml
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "compositor-wayland"
|
||||
version = "0.1.0"
|
||||
authors = ["Glenn Watson <gw@intuitionlibrary.com>",
|
||||
"Robert Mader <robert.mader@posteo.de>"]
|
||||
edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
pkg-config = "^0.3.17"
|
63
third_party/webrender/example-compositor/compositor-wayland/build.rs
vendored
Normal file
63
third_party/webrender/example-compositor/compositor-wayland/build.rs
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* 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 std::process::Command;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
|
||||
extern crate pkg_config;
|
||||
|
||||
fn main() {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
|
||||
fs::create_dir_all(&format!("{}/include", out_dir)).unwrap();
|
||||
Command::new("wayland-scanner")
|
||||
.args(&["client-header", "/usr/share/wayland-protocols/stable/viewporter/viewporter.xml"])
|
||||
.arg(&format!("{}/include/viewporter-client-protocol.h", out_dir))
|
||||
.status().unwrap();
|
||||
|
||||
Command::new("wayland-scanner")
|
||||
.args(&["public-code", "/usr/share/wayland-protocols/stable/viewporter/viewporter.xml"])
|
||||
.arg(&format!("{}/viewporter-protocol.c", out_dir))
|
||||
.status().unwrap();
|
||||
|
||||
Command::new("wayland-scanner")
|
||||
.args(&["client-header", "/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml"])
|
||||
.arg(&format!("{}/include/xdg-shell-client-protocol.h", out_dir))
|
||||
.status().unwrap();
|
||||
|
||||
Command::new("wayland-scanner")
|
||||
.args(&["public-code", "/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml"])
|
||||
.arg(&format!("{}/xdg-shell-protocol.c", out_dir))
|
||||
.status().unwrap();
|
||||
|
||||
cc::Build::new()
|
||||
.include(&format!("{}/include", out_dir))
|
||||
.file("src/lib.cpp")
|
||||
.file(&format!("{}/viewporter-protocol.c", out_dir))
|
||||
.file(&format!("{}/xdg-shell-protocol.c", out_dir))
|
||||
.compile("wayland");
|
||||
|
||||
println!("cargo:rustc-link-lib=dylib=stdc++");
|
||||
|
||||
pkg_config::Config::new()
|
||||
.atleast_version("1")
|
||||
.probe("egl")
|
||||
.unwrap();
|
||||
pkg_config::Config::new()
|
||||
.atleast_version("1")
|
||||
.probe("gl")
|
||||
.unwrap();
|
||||
pkg_config::Config::new()
|
||||
.atleast_version("1")
|
||||
.probe("wayland-client")
|
||||
.unwrap();
|
||||
pkg_config::Config::new()
|
||||
.atleast_version("1")
|
||||
.probe("wayland-egl")
|
||||
.unwrap();
|
||||
|
||||
println!("cargo:rerun-if-changed=src/lib.rs");
|
||||
println!("cargo:rerun-if-changed=src/lib.cpp");
|
||||
}
|
772
third_party/webrender/example-compositor/compositor-wayland/src/lib.cpp
vendored
Normal file
772
third_party/webrender/example-compositor/compositor-wayland/src/lib.cpp
vendored
Normal file
|
@ -0,0 +1,772 @@
|
|||
/* 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/. */
|
||||
|
||||
#define UNICODE
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <map>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include <wayland-egl.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||
|
||||
#define NUM_QUERIES 2
|
||||
|
||||
#define VIRTUAL_OFFSET 512 * 1024
|
||||
|
||||
enum SyncMode {
|
||||
None_ = 0,
|
||||
Swap = 1,
|
||||
Commit = 2,
|
||||
Flush = 3,
|
||||
Query = 4,
|
||||
};
|
||||
|
||||
// The OS compositor representation of a picture cache tile.
|
||||
struct Tile {
|
||||
uint64_t surface_id;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
struct wl_surface* surface;
|
||||
struct wl_subsurface* subsurface;
|
||||
struct wp_viewport* viewport;
|
||||
struct wl_egl_window* egl_window;
|
||||
EGLSurface egl_surface;
|
||||
bool is_visible;
|
||||
|
||||
std::vector<EGLint> damage_rects;
|
||||
};
|
||||
|
||||
struct TileKey {
|
||||
int x;
|
||||
int y;
|
||||
|
||||
TileKey(int ax, int ay) : x(ax), y(ay) {}
|
||||
};
|
||||
|
||||
bool operator==(const TileKey& k0, const TileKey& k1) {
|
||||
return k0.x == k1.x && k0.y == k1.y;
|
||||
}
|
||||
|
||||
struct TileKeyHasher {
|
||||
size_t operator()(const TileKey& key) const { return key.x ^ key.y; }
|
||||
};
|
||||
|
||||
struct Surface {
|
||||
uint64_t id;
|
||||
int tile_width;
|
||||
int tile_height;
|
||||
bool is_opaque;
|
||||
std::unordered_map<TileKey, Tile*, TileKeyHasher> tiles;
|
||||
};
|
||||
|
||||
struct WLDisplay {
|
||||
struct wl_display* display;
|
||||
struct wl_registry* registry;
|
||||
struct wl_compositor* compositor;
|
||||
struct wl_subcompositor* subcompositor;
|
||||
struct xdg_wm_base* wm_base;
|
||||
struct wl_seat* seat;
|
||||
struct wl_pointer* pointer;
|
||||
struct wl_touch* touch;
|
||||
struct wl_keyboard* keyboard;
|
||||
struct wl_shm* shm;
|
||||
struct wl_cursor_theme* cursor_theme;
|
||||
struct wl_cursor* default_cursor;
|
||||
struct wl_surface* cursor_surface;
|
||||
struct wp_viewporter* viewporter;
|
||||
|
||||
PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
|
||||
};
|
||||
|
||||
struct WLGeometry {
|
||||
int width, height;
|
||||
};
|
||||
|
||||
struct WLWindow {
|
||||
WLGeometry geometry;
|
||||
bool enable_compositor;
|
||||
SyncMode sync_mode;
|
||||
bool closed;
|
||||
|
||||
WLDisplay* display;
|
||||
struct wl_surface* surface;
|
||||
struct xdg_surface* xdg_surface;
|
||||
struct xdg_toplevel* xdg_toplevel;
|
||||
struct wl_callback* callback;
|
||||
struct wp_viewport* viewport;
|
||||
bool wait_for_configure;
|
||||
|
||||
struct wl_egl_window* egl_window;
|
||||
EGLSurface egl_surface;
|
||||
|
||||
EGLDeviceEXT eglDevice;
|
||||
EGLDisplay eglDisplay;
|
||||
EGLContext eglContext;
|
||||
EGLConfig config;
|
||||
|
||||
// Maintain list of layer state between frames to avoid visual tree rebuild.
|
||||
std::vector<uint64_t> currentLayers;
|
||||
std::vector<uint64_t> prevLayers;
|
||||
|
||||
// Maps WR surface IDs to each OS surface
|
||||
std::unordered_map<uint64_t, Surface> surfaces;
|
||||
std::vector<Tile*> destroyedTiles;
|
||||
std::vector<Tile*> hiddenTiles;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void init_wl_registry(WLWindow* window);
|
||||
static void init_xdg_window(WLWindow* window);
|
||||
|
||||
WLWindow* com_wl_create_window(int width, int height, bool enable_compositor,
|
||||
SyncMode sync_mode) {
|
||||
WLDisplay* display = new WLDisplay;
|
||||
WLWindow* window = new WLWindow;
|
||||
|
||||
window->display = display;
|
||||
window->geometry.width = width;
|
||||
window->geometry.height = height;
|
||||
window->enable_compositor = enable_compositor;
|
||||
window->sync_mode = sync_mode;
|
||||
window->closed = false;
|
||||
|
||||
display->display = wl_display_connect(NULL);
|
||||
assert(display->display);
|
||||
|
||||
init_wl_registry(window);
|
||||
if (enable_compositor && !display->viewporter) {
|
||||
fprintf(stderr, "Native compositor mode requires wp_viewporter support\n");
|
||||
window->closed = true;
|
||||
}
|
||||
|
||||
window->eglDisplay =
|
||||
eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, display->display, NULL);
|
||||
|
||||
eglInitialize(window->eglDisplay, nullptr, nullptr);
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
|
||||
EGLint num_configs = 0;
|
||||
EGLint cfg_attribs[] = {EGL_SURFACE_TYPE,
|
||||
EGL_WINDOW_BIT,
|
||||
EGL_RENDERABLE_TYPE,
|
||||
EGL_OPENGL_BIT,
|
||||
EGL_RED_SIZE,
|
||||
8,
|
||||
EGL_GREEN_SIZE,
|
||||
8,
|
||||
EGL_BLUE_SIZE,
|
||||
8,
|
||||
EGL_ALPHA_SIZE,
|
||||
8,
|
||||
EGL_DEPTH_SIZE,
|
||||
24,
|
||||
EGL_NONE};
|
||||
EGLConfig configs[32];
|
||||
|
||||
eglChooseConfig(window->eglDisplay, cfg_attribs, configs,
|
||||
sizeof(configs) / sizeof(EGLConfig), &num_configs);
|
||||
assert(num_configs > 0);
|
||||
window->config = configs[0];
|
||||
|
||||
EGLint ctx_attribs[] = {EGL_CONTEXT_OPENGL_PROFILE_MASK,
|
||||
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
||||
EGL_CONTEXT_MAJOR_VERSION,
|
||||
3,
|
||||
EGL_CONTEXT_MINOR_VERSION,
|
||||
2,
|
||||
EGL_NONE};
|
||||
|
||||
// Create an EGL context that can be used for drawing
|
||||
window->eglContext = eglCreateContext(window->eglDisplay, window->config,
|
||||
EGL_NO_CONTEXT, ctx_attribs);
|
||||
|
||||
window->surface = wl_compositor_create_surface(display->compositor);
|
||||
init_xdg_window(window);
|
||||
|
||||
struct wl_region* region =
|
||||
wl_compositor_create_region(window->display->compositor);
|
||||
wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
|
||||
wl_surface_set_opaque_region(window->surface, region);
|
||||
wl_region_destroy(region);
|
||||
|
||||
if (enable_compositor) {
|
||||
xdg_toplevel_set_title(window->xdg_toplevel,
|
||||
"example-compositor (Wayland)");
|
||||
} else {
|
||||
xdg_toplevel_set_title(window->xdg_toplevel, "example-compositor (Simple)");
|
||||
}
|
||||
|
||||
window->wait_for_configure = true;
|
||||
wl_surface_commit(window->surface);
|
||||
|
||||
EGLBoolean ok = eglMakeCurrent(window->eglDisplay, EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE, window->eglContext);
|
||||
assert(ok);
|
||||
|
||||
display->swap_buffers_with_damage =
|
||||
(PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC)eglGetProcAddress(
|
||||
"eglSwapBuffersWithDamageKHR");
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
bool com_wl_tick(WLWindow* window) {
|
||||
if (window->wait_for_configure) {
|
||||
int ret = 0;
|
||||
while (window->wait_for_configure && !window->closed && ret != -1) {
|
||||
wl_display_dispatch(window->display->display);
|
||||
}
|
||||
} else {
|
||||
wl_display_dispatch_pending(window->display->display);
|
||||
}
|
||||
|
||||
return !window->closed;
|
||||
}
|
||||
|
||||
static void unmap_hidden_tiles(WLWindow* window) {
|
||||
for (Tile* tile : window->hiddenTiles) {
|
||||
if (tile->subsurface) {
|
||||
wl_subsurface_destroy(tile->subsurface);
|
||||
tile->subsurface = nullptr;
|
||||
}
|
||||
}
|
||||
window->hiddenTiles.clear();
|
||||
}
|
||||
|
||||
static void clean_up_tiles(WLWindow* window) {
|
||||
for (Tile* tile : window->destroyedTiles) {
|
||||
eglDestroySurface(window->eglDisplay, tile->egl_surface);
|
||||
wl_egl_window_destroy(tile->egl_window);
|
||||
wp_viewport_destroy(tile->viewport);
|
||||
wl_surface_destroy(tile->surface);
|
||||
delete tile;
|
||||
}
|
||||
window->destroyedTiles.clear();
|
||||
}
|
||||
|
||||
static void handle_callback(void* data, struct wl_callback* callback,
|
||||
uint32_t time) {
|
||||
WLWindow* window = (WLWindow*)data;
|
||||
UNUSED(time);
|
||||
|
||||
assert(window->callback == callback);
|
||||
|
||||
wl_callback_destroy(callback);
|
||||
window->callback = nullptr;
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener frame_listener = {handle_callback};
|
||||
|
||||
void com_wl_swap_buffers(WLWindow* window) {
|
||||
if (window->enable_compositor) {
|
||||
for (auto surface_it = window->surfaces.begin();
|
||||
surface_it != window->surfaces.end(); ++surface_it) {
|
||||
Surface* surface = &surface_it->second;
|
||||
|
||||
for (auto tile_it = surface->tiles.begin();
|
||||
tile_it != surface->tiles.end(); ++tile_it) {
|
||||
Tile* tile = tile_it->second;
|
||||
|
||||
if (!tile->damage_rects.empty() && tile->is_visible) {
|
||||
eglMakeCurrent(window->eglDisplay, tile->egl_surface,
|
||||
tile->egl_surface, window->eglContext);
|
||||
eglSwapInterval(window->eglDisplay, 0);
|
||||
|
||||
/* if (window->display->swap_buffers_with_damage) {
|
||||
window->display->swap_buffers_with_damage(
|
||||
window->eglDisplay, tile->egl_surface,
|
||||
tile->damage_rects.data(), tile->damage_rects.size() / 4);
|
||||
} else */
|
||||
eglSwapBuffers(window->eglDisplay, tile->egl_surface);
|
||||
tile->damage_rects.clear();
|
||||
|
||||
eglMakeCurrent(window->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
window->eglContext);
|
||||
} else {
|
||||
wl_surface_commit(tile->surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
wl_surface_commit(window->surface);
|
||||
unmap_hidden_tiles(window);
|
||||
clean_up_tiles(window);
|
||||
|
||||
int ret = 0;
|
||||
switch (window->sync_mode) {
|
||||
case SyncMode::None_:
|
||||
wl_display_roundtrip(window->display->display);
|
||||
break;
|
||||
case SyncMode::Swap:
|
||||
window->callback = wl_surface_frame(window->surface);
|
||||
wl_callback_add_listener(window->callback, &frame_listener, window);
|
||||
wl_surface_commit(window->surface);
|
||||
|
||||
while (window->callback && !window->closed && ret != -1) {
|
||||
ret = wl_display_dispatch(window->display->display);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// If not using native mode, then do a normal EGL swap buffers.
|
||||
switch (window->sync_mode) {
|
||||
case SyncMode::None_:
|
||||
eglSwapInterval(window->eglDisplay, 0);
|
||||
break;
|
||||
case SyncMode::Swap:
|
||||
eglSwapInterval(window->eglDisplay, 1);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
eglSwapBuffers(window->eglDisplay, window->egl_surface);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new native surface
|
||||
void com_wl_create_surface(WLWindow* window, uint64_t surface_id,
|
||||
int tile_width, int tile_height, bool is_opaque) {
|
||||
assert(window->surfaces.count(surface_id) == 0);
|
||||
|
||||
Surface surface;
|
||||
surface.id = surface_id;
|
||||
surface.tile_width = tile_width;
|
||||
surface.tile_height = tile_height;
|
||||
surface.is_opaque = is_opaque;
|
||||
|
||||
window->surfaces.emplace(surface_id, surface);
|
||||
}
|
||||
|
||||
void com_wl_create_tile(WLWindow* window, uint64_t surface_id, int x, int y) {
|
||||
WLDisplay* display = window->display;
|
||||
|
||||
assert(window->surfaces.count(surface_id) == 1);
|
||||
Surface* surface = &window->surfaces.at(surface_id);
|
||||
|
||||
TileKey key(x, y);
|
||||
assert(surface->tiles.count(key) == 0);
|
||||
|
||||
Tile* tile = new Tile;
|
||||
tile->surface_id = surface_id;
|
||||
tile->x = x;
|
||||
tile->y = y;
|
||||
tile->is_visible = false;
|
||||
|
||||
tile->surface = wl_compositor_create_surface(display->compositor);
|
||||
tile->viewport =
|
||||
wp_viewporter_get_viewport(display->viewporter, tile->surface);
|
||||
|
||||
if (surface->is_opaque) {
|
||||
struct wl_region* region =
|
||||
wl_compositor_create_region(window->display->compositor);
|
||||
wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
|
||||
wl_surface_set_opaque_region(tile->surface, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
|
||||
tile->egl_window = wl_egl_window_create(tile->surface, surface->tile_width,
|
||||
surface->tile_height);
|
||||
tile->egl_surface = eglCreateWindowSurface(window->eglDisplay, window->config,
|
||||
tile->egl_window, NULL);
|
||||
assert(tile->egl_surface != EGL_NO_SURFACE);
|
||||
|
||||
surface->tiles.emplace(key, tile);
|
||||
}
|
||||
|
||||
static void show_tile(WLWindow* window, Tile* tile) {
|
||||
if (tile->is_visible) {
|
||||
assert(tile->subsurface);
|
||||
return;
|
||||
}
|
||||
|
||||
tile->subsurface = wl_subcompositor_get_subsurface(
|
||||
window->display->subcompositor, tile->surface, window->surface);
|
||||
|
||||
/* This is not comprehensive yet, see hide_tile() */
|
||||
Surface* surface = &window->surfaces.at(tile->surface_id);
|
||||
for (auto tile_it = surface->tiles.begin(); tile_it != surface->tiles.end();
|
||||
++tile_it) {
|
||||
Tile* other_tile = tile_it->second;
|
||||
|
||||
if (other_tile->is_visible) {
|
||||
wl_subsurface_place_above(tile->subsurface, other_tile->surface);
|
||||
}
|
||||
}
|
||||
|
||||
tile->is_visible = true;
|
||||
}
|
||||
|
||||
static void hide_tile(WLWindow* window, Tile* tile) {
|
||||
if (!tile->is_visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a workaround for missing API on the egl-wayland platform. We
|
||||
* likely want to replace it a solution that detaches the buffer from
|
||||
* the surface, which would require us to manage buffers manually.
|
||||
*/
|
||||
wl_subsurface_set_position(tile->subsurface, window->geometry.width / 2,
|
||||
window->geometry.height / 2);
|
||||
wp_viewport_set_source(tile->viewport, wl_fixed_from_int(0),
|
||||
wl_fixed_from_int(0), wl_fixed_from_int(1),
|
||||
wl_fixed_from_int(1));
|
||||
wl_subsurface_place_below(tile->subsurface, window->surface);
|
||||
tile->is_visible = false;
|
||||
window->hiddenTiles.push_back(tile);
|
||||
}
|
||||
|
||||
void com_wl_destroy_tile(WLWindow* window, uint64_t surface_id, int x, int y) {
|
||||
assert(window->surfaces.count(surface_id) == 1);
|
||||
|
||||
Surface* surface = &window->surfaces.at(surface_id);
|
||||
TileKey key(x, y);
|
||||
assert(surface->tiles.count(key) == 1);
|
||||
Tile* tile = surface->tiles[key];
|
||||
|
||||
hide_tile(window, tile);
|
||||
wl_surface_commit(tile->surface);
|
||||
|
||||
window->destroyedTiles.push_back(tile);
|
||||
surface->tiles.erase(key);
|
||||
}
|
||||
|
||||
void com_wl_destroy_surface(WLWindow* window, uint64_t surface_id) {
|
||||
assert(window->surfaces.count(surface_id) == 1);
|
||||
|
||||
Surface* surface = &window->surfaces.at(surface_id);
|
||||
for (auto tile_it = surface->tiles.begin(); tile_it != surface->tiles.end();
|
||||
tile_it = surface->tiles.begin()) {
|
||||
Tile* tile = tile_it->second;
|
||||
|
||||
com_wl_destroy_tile(window, surface_id, tile->x, tile->y);
|
||||
}
|
||||
|
||||
window->surfaces.erase(surface_id);
|
||||
}
|
||||
|
||||
void com_wl_destroy_window(WLWindow* window) {
|
||||
for (auto surface_it = window->surfaces.begin();
|
||||
surface_it != window->surfaces.end(); ++surface_it) {
|
||||
Surface& surface = surface_it->second;
|
||||
|
||||
com_wl_destroy_surface(window, surface.id);
|
||||
}
|
||||
|
||||
if (window->egl_surface != EGL_NO_SURFACE) {
|
||||
eglDestroySurface(window->eglDisplay, window->egl_surface);
|
||||
}
|
||||
eglDestroyContext(window->eglDisplay, window->eglContext);
|
||||
eglTerminate(window->eglDisplay);
|
||||
|
||||
delete window;
|
||||
}
|
||||
|
||||
// Bind a native surface to allow issuing GL commands to it
|
||||
GLuint com_wl_bind_surface(WLWindow* window, uint64_t surface_id, int tile_x,
|
||||
int tile_y, int* x_offset, int* y_offset,
|
||||
int dirty_x0, int dirty_y0, int dirty_width,
|
||||
int dirty_height) {
|
||||
*x_offset = 0;
|
||||
*y_offset = 0;
|
||||
|
||||
assert(window->surfaces.count(surface_id) == 1);
|
||||
Surface* surface = &window->surfaces[surface_id];
|
||||
|
||||
TileKey key(tile_x, tile_y);
|
||||
assert(surface->tiles.count(key) == 1);
|
||||
Tile* tile = surface->tiles[key];
|
||||
|
||||
tile->damage_rects.push_back(dirty_x0);
|
||||
tile->damage_rects.push_back(dirty_y0);
|
||||
tile->damage_rects.push_back(dirty_width);
|
||||
tile->damage_rects.push_back(dirty_height);
|
||||
|
||||
EGLBoolean ok = eglMakeCurrent(window->eglDisplay, tile->egl_surface,
|
||||
tile->egl_surface, window->eglContext);
|
||||
assert(ok);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Unbind a currently bound native surface
|
||||
void com_wl_unbind_surface(WLWindow* window) {
|
||||
eglMakeCurrent(window->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
window->eglContext);
|
||||
}
|
||||
|
||||
void com_wl_begin_transaction(WLWindow*) {}
|
||||
|
||||
// Add a native surface to the visual tree. Called per-frame to build the
|
||||
// composition.
|
||||
void com_wl_add_surface(WLWindow* window, uint64_t surface_id, int offset_x,
|
||||
int offset_y, int clip_x, int clip_y, int clip_w,
|
||||
int clip_h) {
|
||||
Surface* surface = &window->surfaces[surface_id];
|
||||
window->currentLayers.push_back(surface_id);
|
||||
|
||||
for (auto tile_it = surface->tiles.begin(); tile_it != surface->tiles.end();
|
||||
++tile_it) {
|
||||
Tile* tile = tile_it->second;
|
||||
|
||||
int pos_x = MAX((tile->x * surface->tile_width) + offset_x, clip_x);
|
||||
int pos_y = MAX((tile->y * surface->tile_height) + offset_y, clip_y);
|
||||
|
||||
float view_x = MAX((clip_x - offset_x) - tile->x * surface->tile_width, 0);
|
||||
float view_y = MAX((clip_y - offset_y) - tile->y * surface->tile_height, 0);
|
||||
|
||||
float view_w = MIN(surface->tile_width - view_x, (clip_x + clip_w) - pos_x);
|
||||
float view_h =
|
||||
MIN(surface->tile_height - view_y, (clip_y + clip_h) - pos_y);
|
||||
view_w = MIN(window->geometry.width - pos_x, view_w);
|
||||
view_h = MIN(window->geometry.height - pos_y, view_h);
|
||||
|
||||
if (view_w > 0 && view_h > 0) {
|
||||
show_tile(window, tile);
|
||||
|
||||
wl_surface_set_buffer_transform(tile->surface,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_180);
|
||||
wl_subsurface_set_position(tile->subsurface, pos_x, pos_y);
|
||||
wp_viewport_set_source(tile->viewport, wl_fixed_from_double(view_x),
|
||||
wl_fixed_from_double(view_y),
|
||||
wl_fixed_from_double(view_w),
|
||||
wl_fixed_from_double(view_h));
|
||||
} else {
|
||||
hide_tile(window, tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void com_wl_end_transaction(WLWindow* window) {
|
||||
bool same = window->prevLayers == window->currentLayers;
|
||||
if (!same) {
|
||||
struct wl_surface* prev_surface = window->surface;
|
||||
|
||||
for (auto it = window->currentLayers.begin();
|
||||
it != window->currentLayers.end(); ++it) {
|
||||
Surface* surface = &window->surfaces[*it];
|
||||
|
||||
struct wl_surface* next_surface = nullptr;
|
||||
for (auto tile_it = surface->tiles.begin();
|
||||
tile_it != surface->tiles.end(); ++tile_it) {
|
||||
Tile* tile = tile_it->second;
|
||||
|
||||
if (tile->is_visible) {
|
||||
wl_subsurface_place_above(tile->subsurface, prev_surface);
|
||||
|
||||
if (!next_surface) {
|
||||
next_surface = tile->surface;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev_surface = next_surface;
|
||||
}
|
||||
}
|
||||
|
||||
window->prevLayers.swap(window->currentLayers);
|
||||
window->currentLayers.clear();
|
||||
}
|
||||
|
||||
void glInvalidateFramebuffer(GLenum target, GLsizei numAttachments,
|
||||
const GLenum* attachments) {
|
||||
UNUSED(target);
|
||||
UNUSED(numAttachments);
|
||||
UNUSED(attachments);
|
||||
}
|
||||
|
||||
// Get a pointer to an EGL symbol
|
||||
void* com_wl_get_proc_address(const char* name) {
|
||||
/* Disable glInvalidateFramebuffer for now as it triggers errors.
|
||||
* This is likely due to the egl-wayland platform, which we may want to
|
||||
* replace with a custom implementation in order to have more control
|
||||
* over the low-lever bits.
|
||||
*/
|
||||
if (strcmp(name, "glInvalidateFramebuffer") == 0) {
|
||||
return (void*)glInvalidateFramebuffer;
|
||||
}
|
||||
|
||||
return (void*)eglGetProcAddress(name);
|
||||
}
|
||||
|
||||
void com_wl_deinit(WLWindow* window) { UNUSED(window); }
|
||||
|
||||
static void handle_xdg_surface_configure(void* data,
|
||||
struct xdg_surface* surface,
|
||||
uint32_t serial) {
|
||||
WLWindow* window = (WLWindow*)data;
|
||||
|
||||
xdg_surface_ack_configure(surface, serial);
|
||||
|
||||
if (window->wait_for_configure) {
|
||||
if (window->enable_compositor) {
|
||||
int width = window->geometry.width;
|
||||
int height = window->geometry.height;
|
||||
|
||||
window->egl_window = wl_egl_window_create(window->surface, 1, 1);
|
||||
window->egl_surface = eglCreateWindowSurface(
|
||||
window->eglDisplay, window->config, window->egl_window, NULL);
|
||||
assert(window->egl_surface != EGL_NO_SURFACE);
|
||||
|
||||
EGLBoolean ok = eglMakeCurrent(window->eglDisplay, window->egl_surface,
|
||||
window->egl_surface, window->eglContext);
|
||||
assert(ok);
|
||||
|
||||
glClearColor(1.0, 1.0, 1.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
window->viewport = wp_viewporter_get_viewport(window->display->viewporter,
|
||||
window->surface);
|
||||
wp_viewport_set_destination(window->viewport, width, height);
|
||||
|
||||
eglSwapBuffers(window->eglDisplay, window->egl_surface);
|
||||
} else {
|
||||
window->egl_window = wl_egl_window_create(
|
||||
window->surface, window->geometry.width, window->geometry.height);
|
||||
window->egl_surface = eglCreateWindowSurface(
|
||||
window->eglDisplay, window->config, window->egl_window, NULL);
|
||||
assert(window->egl_surface != EGL_NO_SURFACE);
|
||||
|
||||
EGLBoolean ok = eglMakeCurrent(window->eglDisplay, window->egl_surface,
|
||||
window->egl_surface, window->eglContext);
|
||||
assert(ok);
|
||||
}
|
||||
}
|
||||
|
||||
window->wait_for_configure = false;
|
||||
}
|
||||
|
||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||
handle_xdg_surface_configure};
|
||||
|
||||
static void handle_xdg_toplevel_configure(void* data,
|
||||
struct xdg_toplevel* toplevel,
|
||||
int32_t width, int32_t height,
|
||||
struct wl_array* states) {
|
||||
WLWindow* window = (WLWindow*)data;
|
||||
UNUSED(toplevel);
|
||||
UNUSED(states);
|
||||
|
||||
if (width > 0 && height > 0) {
|
||||
window->geometry.width = width;
|
||||
window->geometry.height = height;
|
||||
|
||||
if (!window->wait_for_configure) {
|
||||
if (window->enable_compositor) {
|
||||
wp_viewport_set_destination(window->viewport, window->geometry.width,
|
||||
window->geometry.height);
|
||||
} else {
|
||||
wl_egl_window_resize(window->egl_window, window->geometry.width,
|
||||
window->geometry.height, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_xdg_toplevel_close(void* data,
|
||||
struct xdg_toplevel* toplevel) {
|
||||
UNUSED(toplevel);
|
||||
WLWindow* window = (WLWindow*)data;
|
||||
window->closed = true;
|
||||
}
|
||||
|
||||
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
||||
handle_xdg_toplevel_configure,
|
||||
handle_xdg_toplevel_close,
|
||||
};
|
||||
|
||||
static void xdg_wm_base_ping(void* data, struct xdg_wm_base* shell,
|
||||
uint32_t serial) {
|
||||
UNUSED(data);
|
||||
xdg_wm_base_pong(shell, serial);
|
||||
}
|
||||
|
||||
static const struct xdg_wm_base_listener wm_base_listener = {
|
||||
xdg_wm_base_ping,
|
||||
};
|
||||
|
||||
static void registry_handle_global(void* data, struct wl_registry* registry,
|
||||
uint32_t name, const char* interface,
|
||||
uint32_t version) {
|
||||
WLDisplay* d = (WLDisplay*)data;
|
||||
|
||||
if (strcmp(interface, "wl_compositor") == 0) {
|
||||
d->compositor = (struct wl_compositor*)wl_registry_bind(
|
||||
registry, name, &wl_compositor_interface, MIN(version, 4));
|
||||
} else if (strcmp(interface, "wp_viewporter") == 0) {
|
||||
d->viewporter = (struct wp_viewporter*)wl_registry_bind(
|
||||
registry, name, &wp_viewporter_interface, 1);
|
||||
} else if (strcmp(interface, "xdg_wm_base") == 0) {
|
||||
d->wm_base = (struct xdg_wm_base*)wl_registry_bind(
|
||||
registry, name, &xdg_wm_base_interface, 1);
|
||||
xdg_wm_base_add_listener(d->wm_base, &wm_base_listener, NULL);
|
||||
} else if (strcmp(interface, "wl_subcompositor") == 0) {
|
||||
d->subcompositor = (struct wl_subcompositor*)wl_registry_bind(
|
||||
registry, name, &wl_subcompositor_interface, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void registry_handle_global_remove(void* data,
|
||||
struct wl_registry* registry,
|
||||
uint32_t name) {
|
||||
UNUSED(data);
|
||||
UNUSED(registry);
|
||||
UNUSED(name);
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener registry_listener = {
|
||||
registry_handle_global, registry_handle_global_remove};
|
||||
|
||||
static void init_wl_registry(WLWindow* window) {
|
||||
WLDisplay* display = window->display;
|
||||
|
||||
display->registry = wl_display_get_registry(display->display);
|
||||
wl_registry_add_listener(display->registry, ®istry_listener, display);
|
||||
|
||||
wl_display_roundtrip(display->display);
|
||||
|
||||
assert(display->compositor);
|
||||
assert(display->wm_base);
|
||||
assert(display->subcompositor);
|
||||
}
|
||||
|
||||
static void init_xdg_window(WLWindow* window) {
|
||||
window->xdg_surface =
|
||||
xdg_wm_base_get_xdg_surface(window->display->wm_base, window->surface);
|
||||
assert(window->xdg_surface);
|
||||
xdg_surface_add_listener(window->xdg_surface, &xdg_surface_listener, window);
|
||||
|
||||
window->xdg_toplevel = xdg_surface_get_toplevel(window->xdg_surface);
|
||||
xdg_toplevel_add_listener(window->xdg_toplevel, &xdg_toplevel_listener,
|
||||
window);
|
||||
assert(window->xdg_toplevel);
|
||||
}
|
||||
}
|
269
third_party/webrender/example-compositor/compositor-wayland/src/lib.rs
vendored
Normal file
269
third_party/webrender/example-compositor/compositor-wayland/src/lib.rs
vendored
Normal file
|
@ -0,0 +1,269 @@
|
|||
/* 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 std::os::raw::{c_void, c_char};
|
||||
|
||||
/*
|
||||
|
||||
This is a very simple (and unsafe!) rust wrapper for the Wayland / EGL
|
||||
implementation in lib.cpp.
|
||||
|
||||
It just proxies the calls from the Compositor impl to the C99 code. This is very
|
||||
hacky and not suitable for production!
|
||||
|
||||
*/
|
||||
|
||||
// Opaque wrapper for the Window type in lib.cpp
|
||||
#[repr(C)]
|
||||
pub struct Window {
|
||||
_unused: [u8; 0]
|
||||
}
|
||||
|
||||
// C99 functions that do the compositor work
|
||||
extern {
|
||||
fn com_wl_create_window(
|
||||
width: i32,
|
||||
height: i32,
|
||||
enable_compositor: bool,
|
||||
sync_mode: i32,
|
||||
) -> *mut Window;
|
||||
fn com_wl_destroy_window(window: *mut Window);
|
||||
fn com_wl_tick(window: *mut Window) -> bool;
|
||||
fn com_wl_get_proc_address(name: *const c_char) -> *const c_void;
|
||||
fn com_wl_swap_buffers(window: *mut Window);
|
||||
|
||||
fn com_wl_create_surface(
|
||||
window: *mut Window,
|
||||
id: u64,
|
||||
tile_width: i32,
|
||||
tile_height: i32,
|
||||
is_opaque: bool,
|
||||
);
|
||||
|
||||
fn com_wl_create_tile(
|
||||
window: *mut Window,
|
||||
id: u64,
|
||||
x: i32,
|
||||
y: i32,
|
||||
);
|
||||
|
||||
fn com_wl_destroy_tile(
|
||||
window: *mut Window,
|
||||
id: u64,
|
||||
x: i32,
|
||||
y: i32,
|
||||
);
|
||||
|
||||
fn com_wl_destroy_surface(
|
||||
window: *mut Window,
|
||||
id: u64,
|
||||
);
|
||||
|
||||
fn com_wl_bind_surface(
|
||||
window: *mut Window,
|
||||
surface_id: u64,
|
||||
tile_x: i32,
|
||||
tile_y: i32,
|
||||
x_offset: &mut i32,
|
||||
y_offset: &mut i32,
|
||||
dirty_x0: i32,
|
||||
dirty_y0: i32,
|
||||
dirty_width: i32,
|
||||
dirty_height: i32,
|
||||
) -> u32;
|
||||
fn com_wl_unbind_surface(window: *mut Window);
|
||||
|
||||
fn com_wl_begin_transaction(window: *mut Window);
|
||||
|
||||
fn com_wl_add_surface(
|
||||
window: *mut Window,
|
||||
id: u64,
|
||||
x: i32,
|
||||
y: i32,
|
||||
clip_x: i32,
|
||||
clip_y: i32,
|
||||
clip_w: i32,
|
||||
clip_h: i32,
|
||||
);
|
||||
|
||||
fn com_wl_end_transaction(window: *mut Window);
|
||||
|
||||
fn com_wl_deinit(window: *mut Window);
|
||||
}
|
||||
|
||||
pub fn create_window(
|
||||
width: i32,
|
||||
height: i32,
|
||||
enable_compositor: bool,
|
||||
sync_mode: i32,
|
||||
) -> *mut Window {
|
||||
unsafe {
|
||||
com_wl_create_window(width, height, enable_compositor, sync_mode)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroy_window(window: *mut Window) {
|
||||
unsafe {
|
||||
com_wl_destroy_window(window);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick(window: *mut Window) -> bool {
|
||||
unsafe {
|
||||
com_wl_tick(window)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_proc_address(name: *const c_char) -> *const c_void {
|
||||
unsafe {
|
||||
com_wl_get_proc_address(name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_surface(
|
||||
window: *mut Window,
|
||||
id: u64,
|
||||
tile_width: i32,
|
||||
tile_height: i32,
|
||||
is_opaque: bool,
|
||||
) {
|
||||
unsafe {
|
||||
com_wl_create_surface(
|
||||
window,
|
||||
id,
|
||||
tile_width,
|
||||
tile_height,
|
||||
is_opaque,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_tile(
|
||||
window: *mut Window,
|
||||
id: u64,
|
||||
x: i32,
|
||||
y: i32,
|
||||
) {
|
||||
unsafe {
|
||||
com_wl_create_tile(
|
||||
window,
|
||||
id,
|
||||
x,
|
||||
y,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroy_tile(
|
||||
window: *mut Window,
|
||||
id: u64,
|
||||
x: i32,
|
||||
y: i32,
|
||||
) {
|
||||
unsafe {
|
||||
com_wl_destroy_tile(
|
||||
window,
|
||||
id,
|
||||
x,
|
||||
y,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroy_surface(
|
||||
window: *mut Window,
|
||||
id: u64,
|
||||
) {
|
||||
unsafe {
|
||||
com_wl_destroy_surface(
|
||||
window,
|
||||
id,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_surface(
|
||||
window: *mut Window,
|
||||
surface_id: u64,
|
||||
tile_x: i32,
|
||||
tile_y: i32,
|
||||
dirty_x0: i32,
|
||||
dirty_y0: i32,
|
||||
dirty_width: i32,
|
||||
dirty_height: i32,
|
||||
) -> (u32, i32, i32) {
|
||||
unsafe {
|
||||
let mut x_offset = 0;
|
||||
let mut y_offset = 0;
|
||||
|
||||
let fbo_id = com_wl_bind_surface(
|
||||
window,
|
||||
surface_id,
|
||||
tile_x,
|
||||
tile_y,
|
||||
&mut x_offset,
|
||||
&mut y_offset,
|
||||
dirty_x0,
|
||||
dirty_y0,
|
||||
dirty_width,
|
||||
dirty_height,
|
||||
);
|
||||
|
||||
(fbo_id, x_offset, y_offset)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_surface(
|
||||
window: *mut Window,
|
||||
id: u64,
|
||||
x: i32,
|
||||
y: i32,
|
||||
clip_x: i32,
|
||||
clip_y: i32,
|
||||
clip_w: i32,
|
||||
clip_h: i32,
|
||||
) {
|
||||
unsafe {
|
||||
com_wl_add_surface(
|
||||
window,
|
||||
id,
|
||||
x,
|
||||
y,
|
||||
clip_x,
|
||||
clip_y,
|
||||
clip_w,
|
||||
clip_h,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn begin_transaction(window: *mut Window) {
|
||||
unsafe {
|
||||
com_wl_begin_transaction(window)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unbind_surface(window: *mut Window) {
|
||||
unsafe {
|
||||
com_wl_unbind_surface(window)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end_transaction(window: *mut Window) {
|
||||
unsafe {
|
||||
com_wl_end_transaction(window)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn swap_buffers(window: *mut Window) {
|
||||
unsafe {
|
||||
com_wl_swap_buffers(window);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deinit(window: *mut Window) {
|
||||
unsafe {
|
||||
com_wl_deinit(window);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -88,6 +88,8 @@ extern {
|
|||
);
|
||||
|
||||
fn com_dc_end_transaction(window: *mut Window);
|
||||
|
||||
fn deinit(window: *mut Window);
|
||||
}
|
||||
|
||||
pub fn create_window(
|
||||
|
@ -259,3 +261,7 @@ pub fn swap_buffers(window: *mut Window) {
|
|||
com_dc_swap_buffers(window);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deinit(window: *mut Window) {
|
||||
todo!()
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@ license = "MPL-2.0"
|
|||
|
||||
[dependencies]
|
||||
webrender = { path = "../../webrender" }
|
||||
gleam = "0.12.0"
|
||||
gleam = "0.15"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
compositor-windows = { path = "../compositor-windows" }
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
compositor-wayland = { path = "../compositor-wayland" }
|
||||
|
|
|
@ -16,10 +16,12 @@ use euclid::Angle;
|
|||
use gleam::gl;
|
||||
use std::ffi::CString;
|
||||
use std::sync::mpsc;
|
||||
use webrender::api::*;
|
||||
use webrender::{CompositorSurfaceTransform, Transaction, api::*, euclid::point2};
|
||||
use webrender::api::units::*;
|
||||
#[cfg(target_os = "windows")]
|
||||
use compositor_windows as compositor;
|
||||
#[cfg(target_os = "linux")]
|
||||
use compositor_wayland as compositor;
|
||||
use std::{env, f32, process};
|
||||
|
||||
// A very hacky integration with DirectComposite. It proxies calls from the compositor
|
||||
|
@ -42,6 +44,7 @@ impl webrender::Compositor for DirectCompositeInterface {
|
|||
fn create_surface(
|
||||
&mut self,
|
||||
id: webrender::NativeSurfaceId,
|
||||
_virtual_offset: DeviceIntPoint,
|
||||
tile_size: DeviceIntSize,
|
||||
is_opaque: bool,
|
||||
) {
|
||||
|
@ -89,6 +92,7 @@ impl webrender::Compositor for DirectCompositeInterface {
|
|||
&mut self,
|
||||
id: webrender::NativeTileId,
|
||||
dirty_rect: DeviceIntRect,
|
||||
_valid_rect: DeviceIntRect,
|
||||
) -> webrender::NativeSurfaceInfo {
|
||||
let (fbo_id, x, y) = compositor::bind_surface(
|
||||
self.window,
|
||||
|
@ -118,14 +122,15 @@ impl webrender::Compositor for DirectCompositeInterface {
|
|||
fn add_surface(
|
||||
&mut self,
|
||||
id: webrender::NativeSurfaceId,
|
||||
position: DeviceIntPoint,
|
||||
transform: CompositorSurfaceTransform,
|
||||
clip_rect: DeviceIntRect,
|
||||
_image_rendering: ImageRendering,
|
||||
) {
|
||||
compositor::add_surface(
|
||||
self.window,
|
||||
id.0,
|
||||
position.x,
|
||||
position.y,
|
||||
transform.transform_point2d(point2(0., 0.)).unwrap().x as i32,
|
||||
transform.transform_point2d(point2(0., 0.)).unwrap().y as i32,
|
||||
clip_rect.origin.x,
|
||||
clip_rect.origin.y,
|
||||
clip_rect.size.width,
|
||||
|
@ -136,6 +141,42 @@ impl webrender::Compositor for DirectCompositeInterface {
|
|||
fn end_frame(&mut self) {
|
||||
compositor::end_transaction(self.window);
|
||||
}
|
||||
fn create_external_surface(&mut self, _: webrender::NativeSurfaceId, _: bool) { todo!() }
|
||||
|
||||
fn attach_external_image(
|
||||
&mut self,
|
||||
_id: webrender::NativeSurfaceId,
|
||||
_external_image: ExternalImageId
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn enable_native_compositor(&mut self, _enable: bool) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn deinit(&mut self) {
|
||||
compositor::deinit(self.window);
|
||||
}
|
||||
|
||||
fn get_capabilities(&self) -> webrender::CompositorCapabilities {
|
||||
webrender::CompositorCapabilities {
|
||||
virtual_surface_size: 1024 * 1024,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn invalidate_tile(
|
||||
&mut self,
|
||||
_id: webrender::NativeTileId,
|
||||
_valid_rect: DeviceIntRect,
|
||||
) {}
|
||||
|
||||
fn start_compositing(
|
||||
&mut self,
|
||||
_dirty_rects: &[DeviceIntRect],
|
||||
_opaque_rects: &[DeviceIntRect],
|
||||
) {}
|
||||
}
|
||||
|
||||
// Simplisitic implementation of the WR notifier interface to know when a frame
|
||||
|
@ -159,7 +200,7 @@ impl RenderNotifier for Notifier {
|
|||
})
|
||||
}
|
||||
|
||||
fn wake_up(&self) {
|
||||
fn wake_up(&self, _composite_needed: bool) {
|
||||
}
|
||||
|
||||
fn new_frame_ready(&self,
|
||||
|
@ -181,7 +222,7 @@ fn push_rotated_rect(
|
|||
time: f32,
|
||||
) {
|
||||
let color = color.scale_rgb(time);
|
||||
let rotation = LayoutTransform::create_rotation(
|
||||
let rotation = LayoutTransform::rotation(
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
|
@ -194,13 +235,16 @@ fn push_rotated_rect(
|
|||
);
|
||||
let transform = rotation
|
||||
.pre_translate(-transform_origin)
|
||||
.post_translate(transform_origin);
|
||||
.then_translate(transform_origin);
|
||||
let spatial_id = builder.push_reference_frame(
|
||||
LayoutPoint::zero(),
|
||||
spatial_id,
|
||||
TransformStyle::Flat,
|
||||
PropertyBinding::Value(transform),
|
||||
ReferenceFrameKind::Transform,
|
||||
ReferenceFrameKind::Transform {
|
||||
is_2d_scale_translation: false,
|
||||
should_snap: false,
|
||||
},
|
||||
);
|
||||
builder.push_rect(
|
||||
&CommonItemProperties::new(
|
||||
|
@ -235,7 +279,7 @@ fn build_display_list(
|
|||
|
||||
let scroll_space_info = builder.define_scroll_frame(
|
||||
&fixed_space_info,
|
||||
Some(scroll_id),
|
||||
scroll_id,
|
||||
LayoutRect::new(LayoutPoint::zero(), layout_size),
|
||||
LayoutRect::new(LayoutPoint::zero(), layout_size),
|
||||
ScrollSensitivity::Script,
|
||||
|
@ -289,6 +333,32 @@ fn build_display_list(
|
|||
0.1,
|
||||
time,
|
||||
);
|
||||
|
||||
push_rotated_rect(
|
||||
builder,
|
||||
LayoutRect::new(
|
||||
LayoutPoint::new(100.0, 600.0),
|
||||
LayoutSize::new(size_factor * 400.0, size_factor * 400.0),
|
||||
),
|
||||
ColorF::new(1.0, 1.0, 0.0, 1.0),
|
||||
scroll_space_info.spatial_id,
|
||||
root_pipeline_id,
|
||||
time,
|
||||
time,
|
||||
);
|
||||
|
||||
push_rotated_rect(
|
||||
builder,
|
||||
LayoutRect::new(
|
||||
LayoutPoint::new(700.0, 600.0),
|
||||
LayoutSize::new(size_factor * 400.0, size_factor * 400.0),
|
||||
),
|
||||
ColorF::new(0.0, 1.0, 1.0, 1.0),
|
||||
scroll_space_info.spatial_id,
|
||||
root_pipeline_id,
|
||||
time,
|
||||
time,
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -358,13 +428,15 @@ fn main() {
|
|||
} else {
|
||||
webrender::CompositorConfig::Draw {
|
||||
max_partial_present_rects: 0,
|
||||
draw_previous_partial_present_regions: false,
|
||||
partial_present: None,
|
||||
}
|
||||
};
|
||||
let opts = webrender::RendererOptions {
|
||||
clear_color: Some(ColorF::new(1.0, 1.0, 1.0, 1.0)),
|
||||
debug_flags,
|
||||
enable_picture_caching: true,
|
||||
compositor_config,
|
||||
surface_origin_is_top_left: false,
|
||||
..webrender::RendererOptions::default()
|
||||
};
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
@ -383,10 +455,9 @@ fn main() {
|
|||
notifier,
|
||||
opts,
|
||||
None,
|
||||
device_size,
|
||||
).unwrap();
|
||||
let api = sender.create_api();
|
||||
let document_id = api.add_document(device_size, 0);
|
||||
let mut api = sender.create_api();
|
||||
let document_id = api.add_document(device_size);
|
||||
let device_pixel_ratio = 1.0;
|
||||
let mut current_epoch = Epoch(0);
|
||||
let root_pipeline_id = PipelineId(0, 0);
|
||||
|
@ -399,7 +470,7 @@ fn main() {
|
|||
txn.set_root_pipeline(root_pipeline_id);
|
||||
|
||||
if let Invalidations::Scrolling = inv_mode {
|
||||
let mut root_builder = DisplayListBuilder::new(root_pipeline_id, layout_size);
|
||||
let mut root_builder = DisplayListBuilder::new(root_pipeline_id);
|
||||
|
||||
build_display_list(
|
||||
&mut root_builder,
|
||||
|
@ -419,7 +490,7 @@ fn main() {
|
|||
);
|
||||
}
|
||||
|
||||
txn.generate_frame();
|
||||
txn.generate_frame(0);
|
||||
api.send_transaction(document_id, txn);
|
||||
|
||||
// Tick the compositor (in this sample, we don't block on UI events)
|
||||
|
@ -429,7 +500,7 @@ fn main() {
|
|||
// Update and render. This will invoke the native compositor interface implemented above
|
||||
// as required.
|
||||
renderer.update();
|
||||
renderer.render(device_size).unwrap();
|
||||
renderer.render(device_size, 0).unwrap();
|
||||
let _ = renderer.flush_pipeline_info();
|
||||
|
||||
// Construct a simple display list that can be drawn and composited by DC.
|
||||
|
@ -437,7 +508,7 @@ fn main() {
|
|||
|
||||
match inv_mode {
|
||||
Invalidations::Small | Invalidations::Large => {
|
||||
let mut root_builder = DisplayListBuilder::new(root_pipeline_id, layout_size);
|
||||
let mut root_builder = DisplayListBuilder::new(root_pipeline_id);
|
||||
|
||||
build_display_list(
|
||||
&mut root_builder,
|
||||
|
@ -466,7 +537,7 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
txn.generate_frame();
|
||||
txn.generate_frame(0);
|
||||
api.send_transaction(document_id, txn);
|
||||
current_epoch.0 += 1;
|
||||
time += 0.001;
|
||||
|
|
8
third_party/webrender/examples/Cargo.toml
vendored
8
third_party/webrender/examples/Cargo.toml
vendored
|
@ -26,10 +26,6 @@ path = "blob.rs"
|
|||
name = "document"
|
||||
path = "document.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "frame_output"
|
||||
path = "frame_output.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "iframe"
|
||||
path = "iframe.rs"
|
||||
|
@ -55,13 +51,13 @@ name = "yuv"
|
|||
path = "yuv.rs"
|
||||
|
||||
[features]
|
||||
debug = ["webrender/capture", "webrender/debugger", "webrender/profiler"]
|
||||
debug = ["webrender/capture", "webrender/profiler"]
|
||||
|
||||
[dependencies]
|
||||
app_units = "0.7"
|
||||
env_logger = "0.5"
|
||||
euclid = "0.22"
|
||||
gleam = "0.12"
|
||||
gleam = "0.15"
|
||||
glutin = "0.21"
|
||||
rayon = "1"
|
||||
webrender = { path = "../webrender" }
|
||||
|
|
11
third_party/webrender/examples/alpha_perf.rs
vendored
11
third_party/webrender/examples/alpha_perf.rs
vendored
|
@ -2,11 +2,11 @@
|
|||
* 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 euclid;
|
||||
use gleam;
|
||||
use glutin;
|
||||
use webrender;
|
||||
use winit;
|
||||
extern crate euclid;
|
||||
extern crate gleam;
|
||||
extern crate glutin;
|
||||
extern crate webrender;
|
||||
extern crate winit;
|
||||
|
||||
#[path = "common/boilerplate.rs"]
|
||||
mod boilerplate;
|
||||
|
@ -14,6 +14,7 @@ mod boilerplate;
|
|||
use crate::boilerplate::{Example, HandyDandyRectBuilder};
|
||||
use std::cmp;
|
||||
use webrender::api::*;
|
||||
use webrender::render_api::*;
|
||||
use webrender::api::units::DeviceIntSize;
|
||||
|
||||
|
||||
|
|
18
third_party/webrender/examples/animation.rs
vendored
18
third_party/webrender/examples/animation.rs
vendored
|
@ -10,11 +10,11 @@
|
|||
//! rounded cornered rectangle, which is done automatically during the
|
||||
//! scene building for render optimization.
|
||||
|
||||
use euclid;
|
||||
use gleam;
|
||||
use glutin;
|
||||
use webrender;
|
||||
use winit;
|
||||
extern crate euclid;
|
||||
extern crate gleam;
|
||||
extern crate glutin;
|
||||
extern crate webrender;
|
||||
extern crate winit;
|
||||
|
||||
#[path = "common/boilerplate.rs"]
|
||||
mod boilerplate;
|
||||
|
@ -22,6 +22,7 @@ mod boilerplate;
|
|||
use crate::boilerplate::{Example, HandyDandyRectBuilder};
|
||||
use euclid::Angle;
|
||||
use webrender::api::*;
|
||||
use webrender::render_api::*;
|
||||
use webrender::api::units::*;
|
||||
|
||||
|
||||
|
@ -62,7 +63,10 @@ impl App {
|
|||
SpatialId::root_scroll_node(pipeline_id),
|
||||
TransformStyle::Flat,
|
||||
PropertyBinding::Binding(property_key, LayoutTransform::identity()),
|
||||
ReferenceFrameKind::Transform,
|
||||
ReferenceFrameKind::Transform {
|
||||
is_2d_scale_translation: false,
|
||||
should_snap: false,
|
||||
},
|
||||
);
|
||||
|
||||
builder.push_simple_stacking_context_with_filters(
|
||||
|
@ -194,7 +198,7 @@ impl Example for App {
|
|||
colors: vec![],
|
||||
},
|
||||
);
|
||||
txn.generate_frame();
|
||||
txn.generate_frame(0);
|
||||
api.send_transaction(document_id, txn);
|
||||
}
|
||||
_ => (),
|
||||
|
|
17
third_party/webrender/examples/basic.rs
vendored
17
third_party/webrender/examples/basic.rs
vendored
|
@ -2,11 +2,11 @@
|
|||
* 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 euclid;
|
||||
use gleam;
|
||||
use glutin;
|
||||
use webrender;
|
||||
use winit;
|
||||
extern crate euclid;
|
||||
extern crate gleam;
|
||||
extern crate glutin;
|
||||
extern crate webrender;
|
||||
extern crate winit;
|
||||
|
||||
#[path = "common/boilerplate.rs"]
|
||||
mod boilerplate;
|
||||
|
@ -17,6 +17,7 @@ use winit::TouchPhase;
|
|||
use std::collections::HashMap;
|
||||
use webrender::ShaderPrecacheFlags;
|
||||
use webrender::api::*;
|
||||
use webrender::render_api::*;
|
||||
use webrender::api::units::*;
|
||||
|
||||
|
||||
|
@ -190,7 +191,7 @@ impl Example for App {
|
|||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let content_bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
|
||||
let content_bounds = LayoutRect::new(LayoutPoint::zero(), LayoutSize::new(800.0, 600.0));
|
||||
let root_space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
let spatial_id = root_space_and_clip.spatial_id;
|
||||
|
||||
|
@ -220,6 +221,8 @@ impl Example for App {
|
|||
let mask_clip_id = builder.define_clip_image_mask(
|
||||
&root_space_and_clip,
|
||||
mask,
|
||||
&vec![],
|
||||
FillRule::Nonzero,
|
||||
);
|
||||
let clip_id = builder.define_clip_rounded_rect(
|
||||
&SpaceAndClipInfo {
|
||||
|
@ -312,7 +315,7 @@ impl Example for App {
|
|||
}
|
||||
|
||||
if !txn.is_empty() {
|
||||
txn.generate_frame();
|
||||
txn.generate_frame(0);
|
||||
api.send_transaction(document_id, txn);
|
||||
}
|
||||
|
||||
|
|
13
third_party/webrender/examples/blob.rs
vendored
13
third_party/webrender/examples/blob.rs
vendored
|
@ -2,11 +2,11 @@
|
|||
* 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 gleam;
|
||||
use glutin;
|
||||
use rayon;
|
||||
use webrender;
|
||||
use winit;
|
||||
extern crate gleam;
|
||||
extern crate glutin;
|
||||
extern crate rayon;
|
||||
extern crate webrender;
|
||||
extern crate winit;
|
||||
|
||||
#[path = "common/boilerplate.rs"]
|
||||
mod boilerplate;
|
||||
|
@ -16,9 +16,10 @@ use rayon::{ThreadPool, ThreadPoolBuilder};
|
|||
use rayon::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use webrender::api::{self, DisplayListBuilder, DocumentId, PipelineId, PrimitiveFlags, RenderApi, Transaction};
|
||||
use webrender::api::{self, DisplayListBuilder, DocumentId, PipelineId, PrimitiveFlags};
|
||||
use webrender::api::{ColorF, CommonItemProperties, SpaceAndClipInfo, ImageDescriptorFlags};
|
||||
use webrender::api::units::*;
|
||||
use webrender::render_api::*;
|
||||
use webrender::euclid::size2;
|
||||
|
||||
// This example shows how to implement a very basic BlobImageHandler that can only render
|
||||
|
|
|
@ -10,6 +10,7 @@ use webrender;
|
|||
use winit;
|
||||
use webrender::{DebugFlags, ShaderPrecacheFlags};
|
||||
use webrender::api::*;
|
||||
use webrender::render_api::*;
|
||||
use webrender::api::units::*;
|
||||
|
||||
struct Notifier {
|
||||
|
@ -29,7 +30,7 @@ impl RenderNotifier for Notifier {
|
|||
})
|
||||
}
|
||||
|
||||
fn wake_up(&self) {
|
||||
fn wake_up(&self, _composite_needed: bool) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
let _ = self.events_proxy.wakeup();
|
||||
}
|
||||
|
@ -37,9 +38,9 @@ impl RenderNotifier for Notifier {
|
|||
fn new_frame_ready(&self,
|
||||
_: DocumentId,
|
||||
_scrolled: bool,
|
||||
_composite_needed: bool,
|
||||
composite_needed: bool,
|
||||
_render_time: Option<u64>) {
|
||||
self.wake_up();
|
||||
self.wake_up(composite_needed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,12 +89,11 @@ pub trait Example {
|
|||
) -> bool {
|
||||
false
|
||||
}
|
||||
fn get_image_handlers(
|
||||
fn get_image_handler(
|
||||
&mut self,
|
||||
_gl: &dyn gl::Gl,
|
||||
) -> (Option<Box<dyn ExternalImageHandler>>,
|
||||
Option<Box<dyn OutputImageHandler>>) {
|
||||
(None, None)
|
||||
) -> Option<Box<dyn ExternalImageHandler>> {
|
||||
None
|
||||
}
|
||||
fn draw_custom(&mut self, _gl: &dyn gl::Gl) {
|
||||
}
|
||||
|
@ -183,16 +183,11 @@ pub fn main_wrapper<E: Example>(
|
|||
notifier,
|
||||
opts,
|
||||
None,
|
||||
device_size,
|
||||
).unwrap();
|
||||
let mut api = sender.create_api();
|
||||
let document_id = api.add_document(device_size, 0);
|
||||
let document_id = api.add_document(device_size);
|
||||
|
||||
let (external, output) = example.get_image_handlers(&*gl);
|
||||
|
||||
if let Some(output_image_handler) = output {
|
||||
renderer.set_output_image_handler(output_image_handler);
|
||||
}
|
||||
let external = example.get_image_handler(&*gl);
|
||||
|
||||
if let Some(external_image_handler) = external {
|
||||
renderer.set_external_image_handler(external_image_handler);
|
||||
|
@ -201,7 +196,7 @@ pub fn main_wrapper<E: Example>(
|
|||
let epoch = Epoch(0);
|
||||
let pipeline_id = PipelineId(0, 0);
|
||||
let layout_size = device_size.to_f32() / euclid::Scale::new(device_pixel_ratio);
|
||||
let mut builder = DisplayListBuilder::new(pipeline_id, layout_size);
|
||||
let mut builder = DisplayListBuilder::new(pipeline_id);
|
||||
let mut txn = Transaction::new();
|
||||
|
||||
example.render(
|
||||
|
@ -220,7 +215,7 @@ pub fn main_wrapper<E: Example>(
|
|||
true,
|
||||
);
|
||||
txn.set_root_pipeline(pipeline_id);
|
||||
txn.generate_frame();
|
||||
txn.generate_frame(0);
|
||||
api.send_transaction(document_id, txn);
|
||||
|
||||
println!("Entering event loop");
|
||||
|
@ -259,14 +254,10 @@ pub fn main_wrapper<E: Example>(
|
|||
winit::VirtualKeyCode::P => debug_flags.toggle(DebugFlags::PROFILER_DBG),
|
||||
winit::VirtualKeyCode::O => debug_flags.toggle(DebugFlags::RENDER_TARGET_DBG),
|
||||
winit::VirtualKeyCode::I => debug_flags.toggle(DebugFlags::TEXTURE_CACHE_DBG),
|
||||
winit::VirtualKeyCode::S => debug_flags.toggle(DebugFlags::COMPACT_PROFILER),
|
||||
winit::VirtualKeyCode::T => debug_flags.toggle(DebugFlags::PICTURE_CACHING_DBG),
|
||||
winit::VirtualKeyCode::Q => debug_flags.toggle(
|
||||
DebugFlags::GPU_TIME_QUERIES | DebugFlags::GPU_SAMPLE_QUERIES
|
||||
),
|
||||
winit::VirtualKeyCode::F => debug_flags.toggle(
|
||||
DebugFlags::NEW_FRAME_INDICATOR | DebugFlags::NEW_SCENE_INDICATOR
|
||||
),
|
||||
winit::VirtualKeyCode::G => debug_flags.toggle(DebugFlags::GPU_CACHE_DBG),
|
||||
winit::VirtualKeyCode::Key1 => txn.set_document_view(
|
||||
device_size.into(),
|
||||
|
@ -304,7 +295,7 @@ pub fn main_wrapper<E: Example>(
|
|||
}
|
||||
|
||||
if custom_event {
|
||||
let mut builder = DisplayListBuilder::new(pipeline_id, layout_size);
|
||||
let mut builder = DisplayListBuilder::new(pipeline_id);
|
||||
|
||||
example.render(
|
||||
&mut api,
|
||||
|
@ -321,12 +312,12 @@ pub fn main_wrapper<E: Example>(
|
|||
builder.finalize(),
|
||||
true,
|
||||
);
|
||||
txn.generate_frame();
|
||||
txn.generate_frame(0);
|
||||
}
|
||||
api.send_transaction(document_id, txn);
|
||||
|
||||
renderer.update();
|
||||
renderer.render(device_size).unwrap();
|
||||
renderer.render(device_size, 0).unwrap();
|
||||
let _ = renderer.flush_pipeline_info();
|
||||
example.draw_custom(&*gl);
|
||||
windowed_context.swap_buffers().ok();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue