mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Update surfman to 0.2 and remove glutin
This commit is contained in:
parent
9dbc6554f0
commit
8bb1732258
94 changed files with 2265 additions and 1513 deletions
100
Cargo.lock
generated
100
Cargo.lock
generated
|
@ -502,12 +502,13 @@ dependencies = [
|
||||||
"raqote",
|
"raqote",
|
||||||
"servo_config",
|
"servo_config",
|
||||||
"sparkle",
|
"sparkle",
|
||||||
"surfman 0.1.4",
|
"surfman",
|
||||||
"surfman-chains 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"surfman-chains",
|
||||||
"surfman-chains-api",
|
"surfman-chains-api",
|
||||||
"time",
|
"time",
|
||||||
"webrender",
|
"webrender",
|
||||||
"webrender_api",
|
"webrender_api",
|
||||||
|
"webrender_surfman",
|
||||||
"webrender_traits",
|
"webrender_traits",
|
||||||
"webxr-api",
|
"webxr-api",
|
||||||
]
|
]
|
||||||
|
@ -591,6 +592,12 @@ version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg_aliases"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6da2b592f5a2e590c3d94c44313bab369f2286cfe1e4134c830bf3317814866"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cgl"
|
name = "cgl"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
@ -772,6 +779,7 @@ dependencies = [
|
||||||
"toml",
|
"toml",
|
||||||
"webrender",
|
"webrender",
|
||||||
"webrender_api",
|
"webrender_api",
|
||||||
|
"webrender_surfman",
|
||||||
"webxr",
|
"webxr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -3203,11 +3211,12 @@ dependencies = [
|
||||||
"sparkle",
|
"sparkle",
|
||||||
"style",
|
"style",
|
||||||
"style_traits",
|
"style_traits",
|
||||||
"surfman 0.1.4",
|
"surfman",
|
||||||
"webdriver_server",
|
"webdriver_server",
|
||||||
"webgpu",
|
"webgpu",
|
||||||
"webrender",
|
"webrender",
|
||||||
"webrender_api",
|
"webrender_api",
|
||||||
|
"webrender_surfman",
|
||||||
"webrender_traits",
|
"webrender_traits",
|
||||||
"webxr",
|
"webxr",
|
||||||
"webxr-api",
|
"webxr-api",
|
||||||
|
@ -3976,11 +3985,6 @@ version = "0.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
|
checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "osmesa-src"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "git+https://github.com/servo/osmesa-src#1a9519c3675ebc1117cbb18ed6db420b5941cb8b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "osmesa-sys"
|
name = "osmesa-sys"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -4946,22 +4950,21 @@ dependencies = [
|
||||||
"euclid",
|
"euclid",
|
||||||
"getopts",
|
"getopts",
|
||||||
"gleam 0.9.2",
|
"gleam 0.9.2",
|
||||||
"glutin",
|
|
||||||
"image",
|
"image",
|
||||||
"keyboard-types",
|
"keyboard-types",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"libservo",
|
"libservo",
|
||||||
"log",
|
"log",
|
||||||
"osmesa-src",
|
|
||||||
"osmesa-sys",
|
|
||||||
"servo-media",
|
"servo-media",
|
||||||
"shellwords",
|
"shellwords",
|
||||||
"sig",
|
"sig",
|
||||||
|
"surfman",
|
||||||
"tinyfiledialogs",
|
"tinyfiledialogs",
|
||||||
"webxr",
|
"webxr",
|
||||||
"webxr-api",
|
"webxr-api",
|
||||||
"winapi",
|
"winapi",
|
||||||
|
"winit",
|
||||||
"winres",
|
"winres",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -5025,8 +5028,8 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"servo-media",
|
"servo-media",
|
||||||
"sparkle",
|
"sparkle",
|
||||||
"surfman 0.2.0",
|
"surfman",
|
||||||
"surfman-chains 0.3.0 (git+https://github.com/asajeffrey/surfman-chains?branch=multi)",
|
"surfman-chains",
|
||||||
"surfman-chains-api",
|
"surfman-chains-api",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -5370,6 +5373,7 @@ dependencies = [
|
||||||
"libservo",
|
"libservo",
|
||||||
"log",
|
"log",
|
||||||
"servo-media",
|
"servo-media",
|
||||||
|
"surfman",
|
||||||
"webxr",
|
"webxr",
|
||||||
"webxr-api",
|
"webxr-api",
|
||||||
"winapi",
|
"winapi",
|
||||||
|
@ -5386,6 +5390,7 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"simpleservo",
|
"simpleservo",
|
||||||
|
"surfman",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -5676,47 +5681,20 @@ dependencies = [
|
||||||
"webrender_api",
|
"webrender_api",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "surfman"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "43bf043642ad98aaa51956091c4f829a400bad5f023b5f0095ecda61f925c63d"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"cgl 0.3.2",
|
|
||||||
"cocoa 0.19.1",
|
|
||||||
"core-foundation 0.6.4",
|
|
||||||
"core-graphics 0.17.3",
|
|
||||||
"display-link",
|
|
||||||
"euclid",
|
|
||||||
"gl_generator 0.11.0",
|
|
||||||
"io-surface",
|
|
||||||
"lazy_static",
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"mach",
|
|
||||||
"objc",
|
|
||||||
"osmesa-sys",
|
|
||||||
"wayland-sys 0.24.0",
|
|
||||||
"winapi",
|
|
||||||
"winit",
|
|
||||||
"wio",
|
|
||||||
"x11",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "surfman"
|
name = "surfman"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/pcwalton/surfman?branch=multi#fb782262617e7ca839a4e487b116a5199afaf963"
|
source = "git+https://github.com/servo/surfman#41ac1ee64bc2d1978aeed0f8bf549c57f20ec7c8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
"cfg_aliases",
|
||||||
"cgl 0.3.2",
|
"cgl 0.3.2",
|
||||||
"cocoa 0.19.1",
|
"cocoa 0.19.1",
|
||||||
"core-foundation 0.6.4",
|
"core-foundation 0.6.4",
|
||||||
"core-graphics 0.17.3",
|
"core-graphics 0.17.3",
|
||||||
"display-link",
|
"display-link",
|
||||||
"euclid",
|
"euclid",
|
||||||
"gl_generator 0.11.0",
|
"gl_generator 0.13.1",
|
||||||
"io-surface",
|
"io-surface",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -5734,27 +5712,13 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "surfman-chains"
|
name = "surfman-chains"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/asajeffrey/surfman-chains?branch=multi#e775b8c7807659958a4f20cf8e6eca4290f35124"
|
source = "git+https://github.com/asajeffrey/surfman-chains#b949a240d73ef86d3c4bd22bc3d93933fac21ee9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"euclid",
|
"euclid",
|
||||||
"fnv",
|
"fnv",
|
||||||
"log",
|
"log",
|
||||||
"sparkle",
|
"sparkle",
|
||||||
"surfman 0.2.0",
|
"surfman",
|
||||||
"surfman-chains-api",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "surfman-chains"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a2a679f5be9644bbf93662f3b1a704cc6b81c147d4b7d6d5c8d8b6f453176f01"
|
|
||||||
dependencies = [
|
|
||||||
"euclid",
|
|
||||||
"fnv",
|
|
||||||
"log",
|
|
||||||
"sparkle",
|
|
||||||
"surfman 0.1.4",
|
|
||||||
"surfman-chains-api",
|
"surfman-chains-api",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -6591,18 +6555,28 @@ dependencies = [
|
||||||
"sha2",
|
"sha2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webrender_surfman"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"euclid",
|
||||||
|
"surfman",
|
||||||
|
"surfman-chains",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webrender_traits"
|
name = "webrender_traits"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"euclid",
|
"euclid",
|
||||||
|
"servo_geometry",
|
||||||
"webrender_api",
|
"webrender_api",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webxr"
|
name = "webxr"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://github.com/servo/webxr#373a2fa762a859054070dad921ace05bea9fa712"
|
source = "git+https://github.com/servo/webxr#0d9c83f333920b98d95adf9666b0a365258990a3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android_injected_glue",
|
"android_injected_glue",
|
||||||
"bindgen",
|
"bindgen",
|
||||||
|
@ -6615,8 +6589,8 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"openxr",
|
"openxr",
|
||||||
"serde",
|
"serde",
|
||||||
"surfman 0.1.4",
|
"surfman",
|
||||||
"surfman-chains 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"surfman-chains",
|
||||||
"time",
|
"time",
|
||||||
"webxr-api",
|
"webxr-api",
|
||||||
"winapi",
|
"winapi",
|
||||||
|
@ -6626,7 +6600,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webxr-api"
|
name = "webxr-api"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://github.com/servo/webxr#373a2fa762a859054070dad921ace05bea9fa712"
|
source = "git+https://github.com/servo/webxr#0d9c83f333920b98d95adf9666b0a365258990a3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"euclid",
|
"euclid",
|
||||||
"ipc-channel",
|
"ipc-channel",
|
||||||
|
|
|
@ -32,3 +32,5 @@ mio = { git = "https://github.com/servo/mio.git", branch = "servo" }
|
||||||
winapi = { git = "https://github.com/servo/winapi-rs", branch = "patch-1" }
|
winapi = { git = "https://github.com/servo/winapi-rs", branch = "patch-1" }
|
||||||
spirv_cross = { git = "https://github.com/servo/spirv_cross", branch = "wgpu-servo" }
|
spirv_cross = { git = "https://github.com/servo/spirv_cross", branch = "wgpu-servo" }
|
||||||
backtrace = { git = "https://github.com/MeFisto94/backtrace-rs", branch = "fix-strtab-freeing-crash" }
|
backtrace = { git = "https://github.com/MeFisto94/backtrace-rs", branch = "fix-strtab-freeing-crash" }
|
||||||
|
surfman-chains = { git = "https://github.com/asajeffrey/surfman-chains" }
|
||||||
|
surfman = { git = "https://github.com/servo/surfman" }
|
||||||
|
|
|
@ -38,9 +38,10 @@ servo_config = {path = "../config"}
|
||||||
sparkle = "0.1.22"
|
sparkle = "0.1.22"
|
||||||
webrender = {git = "https://github.com/servo/webrender"}
|
webrender = {git = "https://github.com/servo/webrender"}
|
||||||
webrender_api = {git = "https://github.com/servo/webrender"}
|
webrender_api = {git = "https://github.com/servo/webrender"}
|
||||||
|
webrender_surfman = {path = "../webrender_surfman"}
|
||||||
webrender_traits = {path = "../webrender_traits"}
|
webrender_traits = {path = "../webrender_traits"}
|
||||||
webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]}
|
webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]}
|
||||||
# NOTE: the sm-angle feature only enables angle on windows, not other platforms!
|
# NOTE: the sm-angle feature only enables angle on windows, not other platforms!
|
||||||
surfman = { version = "0.1", features = ["sm-angle", "sm-osmesa"] }
|
surfman = { version = "0.2", features = ["sm-angle","sm-angle-default"] }
|
||||||
surfman-chains = "0.3"
|
surfman-chains = "0.3"
|
||||||
surfman-chains-api = "0.2"
|
surfman-chains-api = "0.2"
|
||||||
|
|
|
@ -15,19 +15,19 @@ use std::collections::HashMap;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use surfman::platform::generic::universal::context::Context;
|
use surfman::Device;
|
||||||
use surfman::platform::generic::universal::device::Device;
|
|
||||||
use surfman::platform::generic::universal::surface::SurfaceTexture;
|
|
||||||
use surfman::SurfaceInfo;
|
use surfman::SurfaceInfo;
|
||||||
|
use surfman::SurfaceTexture;
|
||||||
use surfman_chains::SwapChains;
|
use surfman_chains::SwapChains;
|
||||||
use surfman_chains_api::SwapChainAPI;
|
use surfman_chains_api::SwapChainAPI;
|
||||||
use surfman_chains_api::SwapChainsAPI;
|
use surfman_chains_api::SwapChainsAPI;
|
||||||
|
use webrender_surfman::WebrenderSurfman;
|
||||||
use webrender_traits::{WebrenderExternalImageApi, WebrenderExternalImageRegistry};
|
use webrender_traits::{WebrenderExternalImageApi, WebrenderExternalImageRegistry};
|
||||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||||
|
|
||||||
pub struct WebGLComm {
|
pub struct WebGLComm {
|
||||||
pub webgl_threads: WebGLThreads,
|
pub webgl_threads: WebGLThreads,
|
||||||
pub webxr_swap_chains: SwapChains<WebXRSwapChainId>,
|
pub webxr_swap_chains: SwapChains<WebXRSwapChainId, Device>,
|
||||||
pub webxr_surface_providers: SurfaceProviders,
|
pub webxr_surface_providers: SurfaceProviders,
|
||||||
pub image_handler: Box<dyn WebrenderExternalImageApi>,
|
pub image_handler: Box<dyn WebrenderExternalImageApi>,
|
||||||
pub output_handler: Option<Box<dyn webrender_api::OutputImageHandler>>,
|
pub output_handler: Option<Box<dyn webrender_api::OutputImageHandler>>,
|
||||||
|
@ -37,8 +37,7 @@ pub struct WebGLComm {
|
||||||
impl WebGLComm {
|
impl WebGLComm {
|
||||||
/// Creates a new `WebGLComm` object.
|
/// Creates a new `WebGLComm` object.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: Device,
|
surfman: WebrenderSurfman,
|
||||||
context: Context,
|
|
||||||
webrender_gl: Rc<dyn gleam::gl::Gl>,
|
webrender_gl: Rc<dyn gleam::gl::Gl>,
|
||||||
webrender_api_sender: webrender_api::RenderApiSender,
|
webrender_api_sender: webrender_api::RenderApiSender,
|
||||||
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
||||||
|
@ -60,8 +59,8 @@ impl WebGLComm {
|
||||||
webrender_swap_chains: webrender_swap_chains.clone(),
|
webrender_swap_chains: webrender_swap_chains.clone(),
|
||||||
webxr_swap_chains: webxr_swap_chains.clone(),
|
webxr_swap_chains: webxr_swap_chains.clone(),
|
||||||
webxr_surface_providers: webxr_surface_providers.clone(),
|
webxr_surface_providers: webxr_surface_providers.clone(),
|
||||||
connection: device.connection(),
|
connection: surfman.connection(),
|
||||||
adapter: device.adapter(),
|
adapter: surfman.adapter(),
|
||||||
api_type,
|
api_type,
|
||||||
runnable_receiver,
|
runnable_receiver,
|
||||||
};
|
};
|
||||||
|
@ -72,7 +71,7 @@ impl WebGLComm {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let external = WebGLExternalImages::new(device, context, webrender_swap_chains);
|
let external = WebGLExternalImages::new(surfman, webrender_swap_chains);
|
||||||
|
|
||||||
WebGLThread::run_on_own_thread(init);
|
WebGLThread::run_on_own_thread(init);
|
||||||
|
|
||||||
|
@ -89,23 +88,15 @@ impl WebGLComm {
|
||||||
|
|
||||||
/// Bridge between the webrender::ExternalImage callbacks and the WebGLThreads.
|
/// Bridge between the webrender::ExternalImage callbacks and the WebGLThreads.
|
||||||
struct WebGLExternalImages {
|
struct WebGLExternalImages {
|
||||||
device: Device,
|
surfman: WebrenderSurfman,
|
||||||
context: Context,
|
swap_chains: SwapChains<WebGLContextId, Device>,
|
||||||
swap_chains: SwapChains<WebGLContextId>,
|
|
||||||
locked_front_buffers: FnvHashMap<WebGLContextId, SurfaceTexture>,
|
locked_front_buffers: FnvHashMap<WebGLContextId, SurfaceTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for WebGLExternalImages {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let _ = self.device.destroy_context(&mut self.context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WebGLExternalImages {
|
impl WebGLExternalImages {
|
||||||
fn new(device: Device, context: Context, swap_chains: SwapChains<WebGLContextId>) -> Self {
|
fn new(surfman: WebrenderSurfman, swap_chains: SwapChains<WebGLContextId, Device>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
device,
|
surfman,
|
||||||
context,
|
|
||||||
swap_chains,
|
swap_chains,
|
||||||
locked_front_buffers: FnvHashMap::default(),
|
locked_front_buffers: FnvHashMap::default(),
|
||||||
}
|
}
|
||||||
|
@ -119,13 +110,10 @@ impl WebGLExternalImages {
|
||||||
id: front_buffer_id,
|
id: front_buffer_id,
|
||||||
size,
|
size,
|
||||||
..
|
..
|
||||||
} = self.device.surface_info(&front_buffer);
|
} = self.surfman.surface_info(&front_buffer);
|
||||||
debug!("... getting texture for surface {:?}", front_buffer_id);
|
debug!("... getting texture for surface {:?}", front_buffer_id);
|
||||||
let front_buffer_texture = self
|
let front_buffer_texture = self.surfman.create_surface_texture(front_buffer).unwrap();
|
||||||
.device
|
let gl_texture = self.surfman.surface_texture_object(&front_buffer_texture);
|
||||||
.create_surface_texture(&mut self.context, front_buffer)
|
|
||||||
.unwrap();
|
|
||||||
let gl_texture = front_buffer_texture.gl_texture();
|
|
||||||
|
|
||||||
self.locked_front_buffers.insert(id, front_buffer_texture);
|
self.locked_front_buffers.insert(id, front_buffer_texture);
|
||||||
|
|
||||||
|
@ -135,8 +123,8 @@ impl WebGLExternalImages {
|
||||||
fn unlock_swap_chain(&mut self, id: WebGLContextId) -> Option<()> {
|
fn unlock_swap_chain(&mut self, id: WebGLContextId) -> Option<()> {
|
||||||
let locked_front_buffer = self.locked_front_buffers.remove(&id)?;
|
let locked_front_buffer = self.locked_front_buffers.remove(&id)?;
|
||||||
let locked_front_buffer = self
|
let locked_front_buffer = self
|
||||||
.device
|
.surfman
|
||||||
.destroy_surface_texture(&mut self.context, locked_front_buffer)
|
.destroy_surface_texture(locked_front_buffer)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
debug!("... unlocked chain {:?}", id);
|
debug!("... unlocked chain {:?}", id);
|
||||||
|
|
|
@ -47,7 +47,6 @@ use euclid::default::Size2D;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use half::f16;
|
use half::f16;
|
||||||
use pixels::{self, PixelFormat};
|
use pixels::{self, PixelFormat};
|
||||||
use servo_config::opts;
|
|
||||||
use sparkle::gl;
|
use sparkle::gl;
|
||||||
use sparkle::gl::GLint;
|
use sparkle::gl::GLint;
|
||||||
use sparkle::gl::GLuint;
|
use sparkle::gl::GLuint;
|
||||||
|
@ -59,12 +58,12 @@ use std::slice;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use surfman;
|
use surfman;
|
||||||
use surfman::platform::generic::universal::adapter::Adapter;
|
use surfman::Adapter;
|
||||||
use surfman::platform::generic::universal::connection::Connection;
|
use surfman::Connection;
|
||||||
use surfman::platform::generic::universal::context::Context;
|
use surfman::Context;
|
||||||
use surfman::platform::generic::universal::device::Device;
|
|
||||||
use surfman::ContextAttributeFlags;
|
use surfman::ContextAttributeFlags;
|
||||||
use surfman::ContextAttributes;
|
use surfman::ContextAttributes;
|
||||||
|
use surfman::Device;
|
||||||
use surfman::GLVersion;
|
use surfman::GLVersion;
|
||||||
use surfman::SurfaceAccess;
|
use surfman::SurfaceAccess;
|
||||||
use surfman::SurfaceInfo;
|
use surfman::SurfaceInfo;
|
||||||
|
@ -87,30 +86,130 @@ struct GLContextData {
|
||||||
attributes: GLContextAttributes,
|
attributes: GLContextAttributes,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct GLState {
|
pub struct GLState {
|
||||||
webgl_version: WebGLVersion,
|
webgl_version: WebGLVersion,
|
||||||
gl_version: GLVersion,
|
gl_version: GLVersion,
|
||||||
|
requested_flags: ContextAttributeFlags,
|
||||||
|
// This is the WebGL view of the color mask
|
||||||
|
// The GL view may be different: if the GL context supports alpha
|
||||||
|
// but the WebGL context doesn't, then color_write_mask.3 might be true
|
||||||
|
// but the GL color write mask is false.
|
||||||
|
color_write_mask: [bool; 4],
|
||||||
clear_color: (f32, f32, f32, f32),
|
clear_color: (f32, f32, f32, f32),
|
||||||
scissor_test_enabled: bool,
|
scissor_test_enabled: bool,
|
||||||
|
// The WebGL view of the stencil write mask (see comment re `color_write_mask`)
|
||||||
stencil_write_mask: (u32, u32),
|
stencil_write_mask: (u32, u32),
|
||||||
|
stencil_test_enabled: bool,
|
||||||
stencil_clear_value: i32,
|
stencil_clear_value: i32,
|
||||||
|
// The WebGL view of the depth write mask (see comment re `color_write_mask`)
|
||||||
depth_write_mask: bool,
|
depth_write_mask: bool,
|
||||||
|
depth_test_enabled: bool,
|
||||||
depth_clear_value: f64,
|
depth_clear_value: f64,
|
||||||
|
// True when the default framebuffer is bound to DRAW_FRAMEBUFFER
|
||||||
|
drawing_to_default_framebuffer: bool,
|
||||||
default_vao: gl::GLuint,
|
default_vao: gl::GLuint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GLState {
|
||||||
|
// Are we faking having no alpha / depth / stencil?
|
||||||
|
fn fake_no_alpha(&self) -> bool {
|
||||||
|
self.drawing_to_default_framebuffer &
|
||||||
|
!self.requested_flags.contains(ContextAttributeFlags::ALPHA)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_no_depth(&self) -> bool {
|
||||||
|
self.drawing_to_default_framebuffer &
|
||||||
|
!self.requested_flags.contains(ContextAttributeFlags::DEPTH)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_no_stencil(&self) -> bool {
|
||||||
|
self.drawing_to_default_framebuffer &
|
||||||
|
!self
|
||||||
|
.requested_flags
|
||||||
|
.contains(ContextAttributeFlags::STENCIL)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We maintain invariants between the GLState object and the GL state.
|
||||||
|
fn restore_invariant(&self, gl: &Gl) {
|
||||||
|
self.restore_clear_color_invariant(gl);
|
||||||
|
self.restore_scissor_invariant(gl);
|
||||||
|
self.restore_alpha_invariant(gl);
|
||||||
|
self.restore_depth_invariant(gl);
|
||||||
|
self.restore_stencil_invariant(gl);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restore_clear_color_invariant(&self, gl: &Gl) {
|
||||||
|
let (r, g, b, a) = self.clear_color;
|
||||||
|
gl.clear_color(r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restore_scissor_invariant(&self, gl: &Gl) {
|
||||||
|
if self.scissor_test_enabled {
|
||||||
|
gl.enable(gl::SCISSOR_TEST);
|
||||||
|
} else {
|
||||||
|
gl.disable(gl::SCISSOR_TEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restore_alpha_invariant(&self, gl: &Gl) {
|
||||||
|
let [r, g, b, a] = self.color_write_mask;
|
||||||
|
if self.fake_no_alpha() {
|
||||||
|
gl.color_mask(r, g, b, false);
|
||||||
|
} else {
|
||||||
|
gl.color_mask(r, g, b, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restore_depth_invariant(&self, gl: &Gl) {
|
||||||
|
if self.fake_no_depth() {
|
||||||
|
gl.depth_mask(false);
|
||||||
|
gl.disable(gl::DEPTH_TEST);
|
||||||
|
} else {
|
||||||
|
gl.depth_mask(self.depth_write_mask);
|
||||||
|
if self.depth_test_enabled {
|
||||||
|
gl.enable(gl::DEPTH_TEST);
|
||||||
|
} else {
|
||||||
|
gl.disable(gl::DEPTH_TEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restore_stencil_invariant(&self, gl: &Gl) {
|
||||||
|
if self.fake_no_stencil() {
|
||||||
|
gl.stencil_mask(0);
|
||||||
|
gl.disable(gl::STENCIL_TEST);
|
||||||
|
} else {
|
||||||
|
let (f, b) = self.stencil_write_mask;
|
||||||
|
gl.stencil_mask_separate(gl::FRONT, f);
|
||||||
|
gl.stencil_mask_separate(gl::BACK, b);
|
||||||
|
if self.stencil_test_enabled {
|
||||||
|
gl.enable(gl::STENCIL_TEST);
|
||||||
|
} else {
|
||||||
|
gl.disable(gl::STENCIL_TEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for GLState {
|
impl Default for GLState {
|
||||||
fn default() -> GLState {
|
fn default() -> GLState {
|
||||||
GLState {
|
GLState {
|
||||||
gl_version: GLVersion { major: 1, minor: 0 },
|
gl_version: GLVersion { major: 1, minor: 0 },
|
||||||
webgl_version: WebGLVersion::WebGL1,
|
webgl_version: WebGLVersion::WebGL1,
|
||||||
|
requested_flags: ContextAttributeFlags::empty(),
|
||||||
|
color_write_mask: [true, true, true, true],
|
||||||
clear_color: (0., 0., 0., 0.),
|
clear_color: (0., 0., 0., 0.),
|
||||||
scissor_test_enabled: false,
|
scissor_test_enabled: false,
|
||||||
|
// Should these be 0xFFFF_FFFF?
|
||||||
stencil_write_mask: (0, 0),
|
stencil_write_mask: (0, 0),
|
||||||
|
stencil_test_enabled: false,
|
||||||
stencil_clear_value: 0,
|
stencil_clear_value: 0,
|
||||||
depth_write_mask: true,
|
depth_write_mask: true,
|
||||||
|
depth_test_enabled: false,
|
||||||
depth_clear_value: 1.,
|
depth_clear_value: 1.,
|
||||||
default_vao: 0,
|
default_vao: 0,
|
||||||
|
drawing_to_default_framebuffer: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,9 +237,9 @@ pub(crate) struct WebGLThread {
|
||||||
/// The receiver that should be used to send WebGL messages for processing.
|
/// The receiver that should be used to send WebGL messages for processing.
|
||||||
sender: WebGLSender<WebGLMsg>,
|
sender: WebGLSender<WebGLMsg>,
|
||||||
/// The swap chains used by webrender
|
/// The swap chains used by webrender
|
||||||
webrender_swap_chains: SwapChains<WebGLContextId>,
|
webrender_swap_chains: SwapChains<WebGLContextId, Device>,
|
||||||
/// The swap chains used by webxr
|
/// The swap chains used by webxr
|
||||||
webxr_swap_chains: SwapChains<WebXRSwapChainId>,
|
webxr_swap_chains: SwapChains<WebXRSwapChainId, Device>,
|
||||||
/// The set of all surface providers corresponding to WebXR sessions.
|
/// The set of all surface providers corresponding to WebXR sessions.
|
||||||
webxr_surface_providers: SurfaceProviders,
|
webxr_surface_providers: SurfaceProviders,
|
||||||
/// A channel to allow arbitrary threads to execute tasks that run in the WebGL thread.
|
/// A channel to allow arbitrary threads to execute tasks that run in the WebGL thread.
|
||||||
|
@ -150,9 +249,9 @@ pub(crate) struct WebGLThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type WebGlExecutor = crossbeam_channel::Sender<WebGlRunnable>;
|
pub type WebGlExecutor = crossbeam_channel::Sender<WebGlRunnable>;
|
||||||
pub type WebGlRunnable = Box<dyn FnOnce() + Send>;
|
pub type WebGlRunnable = Box<dyn FnOnce(&Device) + Send>;
|
||||||
pub type SurfaceProviders = Arc<Mutex<HashMap<SessionId, SurfaceProvider>>>;
|
pub type SurfaceProviders = Arc<Mutex<HashMap<SessionId, SurfaceProvider>>>;
|
||||||
pub type SurfaceProvider = Box<dyn surfman_chains::SurfaceProvider + Send>;
|
pub type SurfaceProvider = Box<dyn surfman_chains::SurfaceProvider<Device> + Send>;
|
||||||
|
|
||||||
/// The data required to initialize an instance of the WebGLThread type.
|
/// The data required to initialize an instance of the WebGLThread type.
|
||||||
pub(crate) struct WebGLThreadInit {
|
pub(crate) struct WebGLThreadInit {
|
||||||
|
@ -161,8 +260,8 @@ pub(crate) struct WebGLThreadInit {
|
||||||
pub external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
pub external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
||||||
pub sender: WebGLSender<WebGLMsg>,
|
pub sender: WebGLSender<WebGLMsg>,
|
||||||
pub receiver: WebGLReceiver<WebGLMsg>,
|
pub receiver: WebGLReceiver<WebGLMsg>,
|
||||||
pub webrender_swap_chains: SwapChains<WebGLContextId>,
|
pub webrender_swap_chains: SwapChains<WebGLContextId, Device>,
|
||||||
pub webxr_swap_chains: SwapChains<WebXRSwapChainId>,
|
pub webxr_swap_chains: SwapChains<WebXRSwapChainId, Device>,
|
||||||
pub connection: Connection,
|
pub connection: Connection,
|
||||||
pub adapter: Adapter,
|
pub adapter: Adapter,
|
||||||
pub api_type: gl::GlType,
|
pub api_type: gl::GlType,
|
||||||
|
@ -190,7 +289,9 @@ impl WebGLThread {
|
||||||
}: WebGLThreadInit,
|
}: WebGLThreadInit,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
WebGLThread {
|
WebGLThread {
|
||||||
device: Device::new(&connection, &adapter).expect("Couldn't open WebGL device!"),
|
device: connection
|
||||||
|
.create_device(&adapter)
|
||||||
|
.expect("Couldn't open WebGL device!"),
|
||||||
webrender_api: webrender_api_sender.create_api(),
|
webrender_api: webrender_api_sender.create_api(),
|
||||||
contexts: Default::default(),
|
contexts: Default::default(),
|
||||||
cached_context_info: Default::default(),
|
cached_context_info: Default::default(),
|
||||||
|
@ -236,7 +337,7 @@ impl WebGLThread {
|
||||||
}
|
}
|
||||||
recv(self.runnable_receiver) -> msg => {
|
recv(self.runnable_receiver) -> msg => {
|
||||||
if let Ok(msg) = msg {
|
if let Ok(msg) = msg {
|
||||||
msg();
|
msg(&self.device);
|
||||||
} else {
|
} else {
|
||||||
self.runnable_receiver = crossbeam_channel::never();
|
self.runnable_receiver = crossbeam_channel::never();
|
||||||
}
|
}
|
||||||
|
@ -303,7 +404,7 @@ impl WebGLThread {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
},
|
},
|
||||||
WebGLMsg::ResizeContext(ctx_id, size, sender) => {
|
WebGLMsg::ResizeContext(ctx_id, size, sender) => {
|
||||||
self.resize_webgl_context(ctx_id, size, sender);
|
let _ = sender.send(self.resize_webgl_context(ctx_id, size));
|
||||||
},
|
},
|
||||||
WebGLMsg::RemoveContext(ctx_id) => {
|
WebGLMsg::RemoveContext(ctx_id) => {
|
||||||
self.remove_webgl_context(ctx_id);
|
self.remove_webgl_context(ctx_id);
|
||||||
|
@ -394,21 +495,35 @@ impl WebGLThread {
|
||||||
requested_size: Size2D<u32>,
|
requested_size: Size2D<u32>,
|
||||||
attributes: GLContextAttributes,
|
attributes: GLContextAttributes,
|
||||||
) -> Result<(WebGLContextId, webgl::GLLimits), String> {
|
) -> Result<(WebGLContextId, webgl::GLLimits), String> {
|
||||||
debug!("WebGLThread::create_webgl_context({:?})", requested_size);
|
debug!(
|
||||||
|
"WebGLThread::create_webgl_context({:?}, {:?}, {:?})",
|
||||||
|
webgl_version, requested_size, attributes
|
||||||
|
);
|
||||||
|
|
||||||
// Creating a new GLContext may make the current bound context_id dirty.
|
// Creating a new GLContext may make the current bound context_id dirty.
|
||||||
// Clear it to ensure that make_current() is called in subsequent commands.
|
// Clear it to ensure that make_current() is called in subsequent commands.
|
||||||
self.bound_context_id = None;
|
self.bound_context_id = None;
|
||||||
|
|
||||||
|
let requested_flags =
|
||||||
|
attributes.to_surfman_context_attribute_flags(webgl_version, self.api_type);
|
||||||
|
// Some GL implementations seem to only allow famebuffers
|
||||||
|
// to have alpha, depth and stencil if their creating context does.
|
||||||
|
// WebGL requires all contexts to be able to create framebuffers with
|
||||||
|
// alpha, depth and stencil. So we always create a context with them,
|
||||||
|
// and fake not having them if requested.
|
||||||
|
let flags = requested_flags |
|
||||||
|
ContextAttributeFlags::ALPHA |
|
||||||
|
ContextAttributeFlags::DEPTH |
|
||||||
|
ContextAttributeFlags::STENCIL;
|
||||||
let context_attributes = &ContextAttributes {
|
let context_attributes = &ContextAttributes {
|
||||||
version: webgl_version.to_surfman_version(),
|
version: webgl_version.to_surfman_version(self.api_type),
|
||||||
flags: attributes.to_surfman_context_attribute_flags(webgl_version),
|
flags: flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
let context_descriptor = self
|
let context_descriptor = self
|
||||||
.device
|
.device
|
||||||
.create_context_descriptor(&context_attributes)
|
.create_context_descriptor(&context_attributes)
|
||||||
.unwrap();
|
.map_err(|err| format!("Failed to create context descriptor: {:?}", err))?;
|
||||||
|
|
||||||
let safe_size = Size2D::new(
|
let safe_size = Size2D::new(
|
||||||
requested_size.width.min(SAFE_VIEWPORT_DIMS[0]).max(1),
|
requested_size.width.min(SAFE_VIEWPORT_DIMS[0]).max(1),
|
||||||
|
@ -423,30 +538,30 @@ impl WebGLThread {
|
||||||
let mut ctx = self
|
let mut ctx = self
|
||||||
.device
|
.device
|
||||||
.create_context(&context_descriptor)
|
.create_context(&context_descriptor)
|
||||||
.expect("Failed to create the GL context!");
|
.map_err(|err| format!("Failed to create the GL context: {:?}", err))?;
|
||||||
let surface = self
|
let surface = self
|
||||||
.device
|
.device
|
||||||
.create_surface(&ctx, surface_access, &surface_type)
|
.create_surface(&ctx, surface_access, surface_type)
|
||||||
.expect("Failed to create the initial surface!");
|
.map_err(|err| format!("Failed to create the initial surface: {:?}", err))?;
|
||||||
self.device
|
self.device
|
||||||
.bind_surface_to_context(&mut ctx, surface)
|
.bind_surface_to_context(&mut ctx, surface)
|
||||||
.unwrap();
|
.map_err(|err| format!("Failed to bind initial surface: {:?}", err))?;
|
||||||
// https://github.com/pcwalton/surfman/issues/7
|
// https://github.com/pcwalton/surfman/issues/7
|
||||||
self.device
|
self.device
|
||||||
.make_context_current(&ctx)
|
.make_context_current(&ctx)
|
||||||
.expect("failed to make new context current");
|
.map_err(|err| format!("Failed to make new context current: {:?}", err))?;
|
||||||
|
|
||||||
let id = WebGLContextId(
|
let id = WebGLContextId(
|
||||||
self.external_images
|
self.external_images
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.expect("Lock poisoned?")
|
||||||
.next_id(WebrenderImageHandlerType::WebGL)
|
.next_id(WebrenderImageHandlerType::WebGL)
|
||||||
.0,
|
.0,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.webrender_swap_chains
|
self.webrender_swap_chains
|
||||||
.create_attached_swap_chain(id, &mut self.device, &mut ctx, surface_provider)
|
.create_attached_swap_chain(id, &mut self.device, &mut ctx, surface_provider)
|
||||||
.expect("Failed to create the swap chain");
|
.map_err(|err| format!("Failed to create swap chain: {:?}", err))?;
|
||||||
|
|
||||||
let swap_chain = self
|
let swap_chain = self
|
||||||
.webrender_swap_chains
|
.webrender_swap_chains
|
||||||
|
@ -456,7 +571,7 @@ impl WebGLThread {
|
||||||
debug!(
|
debug!(
|
||||||
"Created webgl context {:?}/{:?}",
|
"Created webgl context {:?}/{:?}",
|
||||||
id,
|
id,
|
||||||
self.device.context_id(&ctx)
|
self.device.context_id(&ctx),
|
||||||
);
|
);
|
||||||
|
|
||||||
let gl = match self.api_type {
|
let gl = match self.api_type {
|
||||||
|
@ -475,34 +590,33 @@ impl WebGLThread {
|
||||||
debug!("Resizing swap chain from {} to {}", safe_size, size);
|
debug!("Resizing swap chain from {} to {}", safe_size, size);
|
||||||
swap_chain
|
swap_chain
|
||||||
.resize(&mut self.device, &mut ctx, size.to_i32())
|
.resize(&mut self.device, &mut ctx, size.to_i32())
|
||||||
.expect("Failed to resize swap chain");
|
.map_err(|err| format!("Failed to resize swap chain: {:?}", err))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let descriptor = self.device.context_descriptor(&ctx);
|
||||||
|
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);
|
||||||
|
|
||||||
self.device.make_context_current(&ctx).unwrap();
|
self.device.make_context_current(&ctx).unwrap();
|
||||||
let framebuffer = self
|
let framebuffer = self
|
||||||
.device
|
.device
|
||||||
.context_surface_info(&ctx)
|
.context_surface_info(&ctx)
|
||||||
.unwrap()
|
.map_err(|err| format!("Failed to get context surface info: {:?}", err))?
|
||||||
.unwrap()
|
.ok_or_else(|| format!("Failed to get context surface info"))?
|
||||||
.framebuffer_object;
|
.framebuffer_object;
|
||||||
|
|
||||||
gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer);
|
gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer);
|
||||||
gl.viewport(0, 0, size.width as i32, size.height as i32);
|
gl.viewport(0, 0, size.width as i32, size.height as i32);
|
||||||
gl.scissor(0, 0, size.width as i32, size.height as i32);
|
gl.scissor(0, 0, size.width as i32, size.height as i32);
|
||||||
gl.clear_color(0., 0., 0., 0.);
|
gl.clear_color(0., 0., 0., !has_alpha as u32 as f32);
|
||||||
gl.clear_depth(1.);
|
gl.clear_depth(1.);
|
||||||
gl.clear_stencil(0);
|
gl.clear_stencil(0);
|
||||||
gl.clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
|
gl.clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
|
||||||
|
gl.clear_color(0., 0., 0., 0.);
|
||||||
debug_assert_eq!(gl.get_error(), gl::NO_ERROR);
|
debug_assert_eq!(gl.get_error(), gl::NO_ERROR);
|
||||||
|
|
||||||
let descriptor = self.device.context_descriptor(&ctx);
|
|
||||||
let descriptor_attributes = self.device.context_descriptor_attributes(&descriptor);
|
|
||||||
|
|
||||||
let gl_version = descriptor_attributes.version;
|
|
||||||
let has_alpha = descriptor_attributes
|
|
||||||
.flags
|
|
||||||
.contains(ContextAttributeFlags::ALPHA);
|
|
||||||
let texture_target = current_wr_texture_target(&self.device);
|
|
||||||
|
|
||||||
let use_apple_vertex_array = WebGLImpl::needs_apple_vertex_arrays(gl_version);
|
let use_apple_vertex_array = WebGLImpl::needs_apple_vertex_arrays(gl_version);
|
||||||
let default_vao = if let Some(vao) =
|
let default_vao = if let Some(vao) =
|
||||||
WebGLImpl::create_vertex_array(&gl, use_apple_vertex_array, webgl_version)
|
WebGLImpl::create_vertex_array(&gl, use_apple_vertex_array, webgl_version)
|
||||||
|
@ -517,9 +631,15 @@ impl WebGLThread {
|
||||||
let state = GLState {
|
let state = GLState {
|
||||||
gl_version,
|
gl_version,
|
||||||
webgl_version,
|
webgl_version,
|
||||||
|
requested_flags,
|
||||||
default_vao,
|
default_vao,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
debug!("Created state {:?}", state);
|
||||||
|
|
||||||
|
state.restore_invariant(&*gl);
|
||||||
|
debug_assert_eq!(gl.get_error(), gl::NO_ERROR);
|
||||||
|
|
||||||
self.contexts.insert(
|
self.contexts.insert(
|
||||||
id,
|
id,
|
||||||
GLContextData {
|
GLContextData {
|
||||||
|
@ -549,8 +669,7 @@ impl WebGLThread {
|
||||||
&mut self,
|
&mut self,
|
||||||
context_id: WebGLContextId,
|
context_id: WebGLContextId,
|
||||||
requested_size: Size2D<u32>,
|
requested_size: Size2D<u32>,
|
||||||
sender: WebGLSender<Result<(), String>>,
|
) -> Result<(), String> {
|
||||||
) {
|
|
||||||
let data = Self::make_current_if_needed_mut(
|
let data = Self::make_current_if_needed_mut(
|
||||||
&self.device,
|
&self.device,
|
||||||
context_id,
|
context_id,
|
||||||
|
@ -568,16 +687,17 @@ impl WebGLThread {
|
||||||
|
|
||||||
// Resize the swap chains
|
// Resize the swap chains
|
||||||
if let Some(swap_chain) = self.webrender_swap_chains.get(context_id) {
|
if let Some(swap_chain) = self.webrender_swap_chains.get(context_id) {
|
||||||
|
let alpha = data
|
||||||
|
.state
|
||||||
|
.requested_flags
|
||||||
|
.contains(ContextAttributeFlags::ALPHA);
|
||||||
|
let clear_color = [0.0, 0.0, 0.0, !alpha as i32 as f32];
|
||||||
swap_chain
|
swap_chain
|
||||||
.resize(&mut self.device, &mut data.ctx, size.to_i32())
|
.resize(&mut self.device, &mut data.ctx, size.to_i32())
|
||||||
.expect("Failed to resize swap chain");
|
.map_err(|err| format!("Failed to resize swap chain: {:?}", err))?;
|
||||||
// temporary, till https://github.com/pcwalton/surfman/issues/35 is fixed
|
|
||||||
self.device
|
|
||||||
.make_context_current(&data.ctx)
|
|
||||||
.expect("Failed to make context current again");
|
|
||||||
swap_chain
|
swap_chain
|
||||||
.clear_surface(&mut self.device, &mut data.ctx, &*data.gl)
|
.clear_surface(&mut self.device, &mut data.ctx, &*data.gl, clear_color)
|
||||||
.expect("Failed to clear resized swap chain");
|
.map_err(|err| format!("Failed to clear resized swap chain: {:?}", err))?;
|
||||||
} else {
|
} else {
|
||||||
error!("Failed to find swap chain");
|
error!("Failed to find swap chain");
|
||||||
}
|
}
|
||||||
|
@ -587,11 +707,9 @@ impl WebGLThread {
|
||||||
|
|
||||||
// Update WR image if needed.
|
// Update WR image if needed.
|
||||||
let info = self.cached_context_info.get_mut(&context_id).unwrap();
|
let info = self.cached_context_info.get_mut(&context_id).unwrap();
|
||||||
let context_descriptor = self.device.context_descriptor(&data.ctx);
|
let has_alpha = data
|
||||||
let has_alpha = self
|
.state
|
||||||
.device
|
.requested_flags
|
||||||
.context_descriptor_attributes(&context_descriptor)
|
|
||||||
.flags
|
|
||||||
.contains(ContextAttributeFlags::ALPHA);
|
.contains(ContextAttributeFlags::ALPHA);
|
||||||
let texture_target = current_wr_texture_target(&self.device);
|
let texture_target = current_wr_texture_target(&self.device);
|
||||||
Self::update_wr_external_image(
|
Self::update_wr_external_image(
|
||||||
|
@ -605,7 +723,7 @@ impl WebGLThread {
|
||||||
|
|
||||||
debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR);
|
debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR);
|
||||||
|
|
||||||
sender.send(Ok(())).unwrap();
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a WebGLContext and releases attached resources.
|
/// Removes a WebGLContext and releases attached resources.
|
||||||
|
@ -697,8 +815,13 @@ impl WebGLThread {
|
||||||
// TODO: if preserveDrawingBuffer is true, then blit the front buffer to the back buffer
|
// TODO: if preserveDrawingBuffer is true, then blit the front buffer to the back buffer
|
||||||
// https://github.com/servo/servo/issues/24604
|
// https://github.com/servo/servo/issues/24604
|
||||||
debug!("Clearing {:?}", swap_id);
|
debug!("Clearing {:?}", swap_id);
|
||||||
|
let alpha = data
|
||||||
|
.state
|
||||||
|
.requested_flags
|
||||||
|
.contains(ContextAttributeFlags::ALPHA);
|
||||||
|
let clear_color = [0.0, 0.0, 0.0, !alpha as i32 as f32];
|
||||||
swap_chain
|
swap_chain
|
||||||
.clear_surface(&mut self.device, &mut data.ctx, &*data.gl)
|
.clear_surface(&mut self.device, &mut data.ctx, &*data.gl, clear_color)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR);
|
debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR);
|
||||||
|
|
||||||
|
@ -1084,7 +1207,10 @@ impl WebGLImpl {
|
||||||
state.stencil_clear_value = stencil;
|
state.stencil_clear_value = stencil;
|
||||||
gl.clear_stencil(stencil);
|
gl.clear_stencil(stencil);
|
||||||
},
|
},
|
||||||
WebGLCommand::ColorMask(r, g, b, a) => gl.color_mask(r, g, b, a),
|
WebGLCommand::ColorMask(r, g, b, a) => {
|
||||||
|
state.color_write_mask = [r, g, b, a];
|
||||||
|
state.restore_alpha_invariant(gl);
|
||||||
|
},
|
||||||
WebGLCommand::CopyTexImage2D(
|
WebGLCommand::CopyTexImage2D(
|
||||||
target,
|
target,
|
||||||
level,
|
level,
|
||||||
|
@ -1109,22 +1235,40 @@ impl WebGLImpl {
|
||||||
WebGLCommand::DepthFunc(func) => gl.depth_func(func),
|
WebGLCommand::DepthFunc(func) => gl.depth_func(func),
|
||||||
WebGLCommand::DepthMask(flag) => {
|
WebGLCommand::DepthMask(flag) => {
|
||||||
state.depth_write_mask = flag;
|
state.depth_write_mask = flag;
|
||||||
gl.depth_mask(flag);
|
state.restore_depth_invariant(gl);
|
||||||
},
|
},
|
||||||
WebGLCommand::DepthRange(near, far) => {
|
WebGLCommand::DepthRange(near, far) => {
|
||||||
gl.depth_range(near.max(0.).min(1.) as f64, far.max(0.).min(1.) as f64)
|
gl.depth_range(near.max(0.).min(1.) as f64, far.max(0.).min(1.) as f64)
|
||||||
},
|
},
|
||||||
WebGLCommand::Disable(cap) => {
|
WebGLCommand::Disable(cap) => match cap {
|
||||||
if cap == gl::SCISSOR_TEST {
|
gl::SCISSOR_TEST => {
|
||||||
state.scissor_test_enabled = false;
|
state.scissor_test_enabled = false;
|
||||||
}
|
state.restore_scissor_invariant(gl);
|
||||||
gl.disable(cap);
|
|
||||||
},
|
},
|
||||||
WebGLCommand::Enable(cap) => {
|
gl::DEPTH_TEST => {
|
||||||
if cap == gl::SCISSOR_TEST {
|
state.depth_test_enabled = false;
|
||||||
|
state.restore_depth_invariant(gl);
|
||||||
|
},
|
||||||
|
gl::STENCIL_TEST => {
|
||||||
|
state.stencil_test_enabled = false;
|
||||||
|
state.restore_stencil_invariant(gl);
|
||||||
|
},
|
||||||
|
_ => gl.disable(cap),
|
||||||
|
},
|
||||||
|
WebGLCommand::Enable(cap) => match cap {
|
||||||
|
gl::SCISSOR_TEST => {
|
||||||
state.scissor_test_enabled = true;
|
state.scissor_test_enabled = true;
|
||||||
}
|
state.restore_scissor_invariant(gl);
|
||||||
gl.enable(cap);
|
},
|
||||||
|
gl::DEPTH_TEST => {
|
||||||
|
state.depth_test_enabled = true;
|
||||||
|
state.restore_depth_invariant(gl);
|
||||||
|
},
|
||||||
|
gl::STENCIL_TEST => {
|
||||||
|
state.stencil_test_enabled = true;
|
||||||
|
state.restore_stencil_invariant(gl);
|
||||||
|
},
|
||||||
|
_ => gl.enable(cap),
|
||||||
},
|
},
|
||||||
WebGLCommand::FramebufferRenderbuffer(target, attachment, renderbuffertarget, rb) => {
|
WebGLCommand::FramebufferRenderbuffer(target, attachment, renderbuffertarget, rb) => {
|
||||||
let attach = |attachment| {
|
let attach = |attachment| {
|
||||||
|
@ -1221,7 +1365,7 @@ impl WebGLImpl {
|
||||||
},
|
},
|
||||||
WebGLCommand::StencilMask(mask) => {
|
WebGLCommand::StencilMask(mask) => {
|
||||||
state.stencil_write_mask = (mask, mask);
|
state.stencil_write_mask = (mask, mask);
|
||||||
gl.stencil_mask(mask);
|
state.restore_stencil_invariant(gl);
|
||||||
},
|
},
|
||||||
WebGLCommand::StencilMaskSeparate(face, mask) => {
|
WebGLCommand::StencilMaskSeparate(face, mask) => {
|
||||||
if face == gl::FRONT {
|
if face == gl::FRONT {
|
||||||
|
@ -1229,7 +1373,7 @@ impl WebGLImpl {
|
||||||
} else {
|
} else {
|
||||||
state.stencil_write_mask.1 = mask;
|
state.stencil_write_mask.1 = mask;
|
||||||
}
|
}
|
||||||
gl.stencil_mask_separate(face, mask);
|
state.restore_stencil_invariant(gl);
|
||||||
},
|
},
|
||||||
WebGLCommand::StencilOp(fail, zfail, zpass) => gl.stencil_op(fail, zfail, zpass),
|
WebGLCommand::StencilOp(fail, zfail, zpass) => gl.stencil_op(fail, zfail, zpass),
|
||||||
WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass) => {
|
WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass) => {
|
||||||
|
@ -1321,7 +1465,7 @@ impl WebGLImpl {
|
||||||
gl.bind_buffer(target, id.map_or(0, WebGLBufferId::get))
|
gl.bind_buffer(target, id.map_or(0, WebGLBufferId::get))
|
||||||
},
|
},
|
||||||
WebGLCommand::BindFramebuffer(target, request) => {
|
WebGLCommand::BindFramebuffer(target, request) => {
|
||||||
Self::bind_framebuffer(gl, target, request, ctx, device)
|
Self::bind_framebuffer(gl, target, request, ctx, device, state)
|
||||||
},
|
},
|
||||||
WebGLCommand::BindRenderbuffer(target, id) => {
|
WebGLCommand::BindRenderbuffer(target, id) => {
|
||||||
gl.bind_renderbuffer(target, id.map_or(0, WebGLRenderbufferId::get))
|
gl.bind_renderbuffer(target, id.map_or(0, WebGLRenderbufferId::get))
|
||||||
|
@ -1557,11 +1701,15 @@ impl WebGLImpl {
|
||||||
Self::bind_vertex_array(gl, id, use_apple_vertex_array, state.webgl_version);
|
Self::bind_vertex_array(gl, id, use_apple_vertex_array, state.webgl_version);
|
||||||
},
|
},
|
||||||
WebGLCommand::GetParameterBool(param, ref sender) => {
|
WebGLCommand::GetParameterBool(param, ref sender) => {
|
||||||
|
let value = match param {
|
||||||
|
webgl::ParameterBool::DepthWritemask => state.depth_write_mask,
|
||||||
|
_ => unsafe {
|
||||||
let mut value = [0];
|
let mut value = [0];
|
||||||
unsafe {
|
|
||||||
gl.get_boolean_v(param as u32, &mut value);
|
gl.get_boolean_v(param as u32, &mut value);
|
||||||
}
|
value[0] != 0
|
||||||
sender.send(value[0] != 0).unwrap()
|
},
|
||||||
|
};
|
||||||
|
sender.send(value).unwrap()
|
||||||
},
|
},
|
||||||
WebGLCommand::FenceSync(ref sender) => {
|
WebGLCommand::FenceSync(ref sender) => {
|
||||||
let value = gl.fence_sync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0);
|
let value = gl.fence_sync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
|
@ -1588,19 +1736,25 @@ impl WebGLImpl {
|
||||||
gl.delete_sync(sync_id.get() as *const _);
|
gl.delete_sync(sync_id.get() as *const _);
|
||||||
},
|
},
|
||||||
WebGLCommand::GetParameterBool4(param, ref sender) => {
|
WebGLCommand::GetParameterBool4(param, ref sender) => {
|
||||||
let mut value = [0; 4];
|
let value = match param {
|
||||||
unsafe {
|
webgl::ParameterBool4::ColorWritemask => state.color_write_mask,
|
||||||
gl.get_boolean_v(param as u32, &mut value);
|
};
|
||||||
}
|
|
||||||
let value = [value[0] != 0, value[1] != 0, value[2] != 0, value[3] != 0];
|
|
||||||
sender.send(value).unwrap()
|
sender.send(value).unwrap()
|
||||||
},
|
},
|
||||||
WebGLCommand::GetParameterInt(param, ref sender) => {
|
WebGLCommand::GetParameterInt(param, ref sender) => {
|
||||||
|
let value = match param {
|
||||||
|
webgl::ParameterInt::AlphaBits if state.fake_no_alpha() => 0,
|
||||||
|
webgl::ParameterInt::DepthBits if state.fake_no_depth() => 0,
|
||||||
|
webgl::ParameterInt::StencilBits if state.fake_no_stencil() => 0,
|
||||||
|
webgl::ParameterInt::StencilWritemask => state.stencil_write_mask.0 as i32,
|
||||||
|
webgl::ParameterInt::StencilBackWritemask => state.stencil_write_mask.1 as i32,
|
||||||
|
_ => unsafe {
|
||||||
let mut value = [0];
|
let mut value = [0];
|
||||||
unsafe {
|
|
||||||
gl.get_integer_v(param as u32, &mut value);
|
gl.get_integer_v(param as u32, &mut value);
|
||||||
}
|
value[0]
|
||||||
sender.send(value[0]).unwrap()
|
},
|
||||||
|
};
|
||||||
|
sender.send(value).unwrap()
|
||||||
},
|
},
|
||||||
WebGLCommand::GetParameterInt2(param, ref sender) => {
|
WebGLCommand::GetParameterInt2(param, ref sender) => {
|
||||||
let mut value = [0; 2];
|
let mut value = [0; 2];
|
||||||
|
@ -1978,15 +2132,25 @@ impl WebGLImpl {
|
||||||
sender.send(value).unwrap();
|
sender.send(value).unwrap();
|
||||||
},
|
},
|
||||||
WebGLCommand::BindBufferBase(target, index, id) => {
|
WebGLCommand::BindBufferBase(target, index, id) => {
|
||||||
gl.bind_buffer_base(target, index, id.map_or(0, WebGLBufferId::get))
|
// https://searchfox.org/mozilla-central/rev/13b081a62d3f3e3e3120f95564529257b0bf451c/dom/canvas/WebGLContextBuffers.cpp#208-210
|
||||||
|
// BindBufferBase/Range will fail (on some drivers) if the buffer name has
|
||||||
|
// never been bound. (GenBuffers makes a name, but BindBuffer initializes
|
||||||
|
// that name as a real buffer object)
|
||||||
|
let id = id.map_or(0, WebGLBufferId::get);
|
||||||
|
gl.bind_buffer(target, id);
|
||||||
|
gl.bind_buffer(target, 0);
|
||||||
|
gl.bind_buffer_base(target, index, id);
|
||||||
|
},
|
||||||
|
WebGLCommand::BindBufferRange(target, index, id, offset, size) => {
|
||||||
|
// https://searchfox.org/mozilla-central/rev/13b081a62d3f3e3e3120f95564529257b0bf451c/dom/canvas/WebGLContextBuffers.cpp#208-210
|
||||||
|
// BindBufferBase/Range will fail (on some drivers) if the buffer name has
|
||||||
|
// never been bound. (GenBuffers makes a name, but BindBuffer initializes
|
||||||
|
// that name as a real buffer object)
|
||||||
|
let id = id.map_or(0, WebGLBufferId::get);
|
||||||
|
gl.bind_buffer(target, id);
|
||||||
|
gl.bind_buffer(target, 0);
|
||||||
|
gl.bind_buffer_range(target, index, id, offset as isize, size as isize);
|
||||||
},
|
},
|
||||||
WebGLCommand::BindBufferRange(target, index, id, offset, size) => gl.bind_buffer_range(
|
|
||||||
target,
|
|
||||||
index,
|
|
||||||
id.map_or(0, WebGLBufferId::get),
|
|
||||||
offset as isize,
|
|
||||||
size as isize,
|
|
||||||
),
|
|
||||||
WebGLCommand::ClearBufferfv(buffer, draw_buffer, ref value) => {
|
WebGLCommand::ClearBufferfv(buffer, draw_buffer, ref value) => {
|
||||||
gl.clear_buffer_fv(buffer, draw_buffer, value)
|
gl.clear_buffer_fv(buffer, draw_buffer, value)
|
||||||
},
|
},
|
||||||
|
@ -2065,47 +2229,17 @@ impl WebGLImpl {
|
||||||
bits | if enabled { bit } else { 0 }
|
bits | if enabled { bit } else { 0 }
|
||||||
});
|
});
|
||||||
|
|
||||||
if state.scissor_test_enabled {
|
|
||||||
gl.disable(gl::SCISSOR_TEST);
|
gl.disable(gl::SCISSOR_TEST);
|
||||||
}
|
gl.color_mask(true, true, true, true);
|
||||||
|
|
||||||
if color {
|
|
||||||
gl.clear_color(0., 0., 0., 0.);
|
gl.clear_color(0., 0., 0., 0.);
|
||||||
}
|
|
||||||
|
|
||||||
if depth {
|
|
||||||
gl.depth_mask(true);
|
gl.depth_mask(true);
|
||||||
gl.clear_depth(1.);
|
gl.clear_depth(1.);
|
||||||
}
|
|
||||||
|
|
||||||
if stencil {
|
|
||||||
gl.stencil_mask_separate(gl::FRONT, 0xFFFFFFFF);
|
gl.stencil_mask_separate(gl::FRONT, 0xFFFFFFFF);
|
||||||
gl.stencil_mask_separate(gl::BACK, 0xFFFFFFFF);
|
gl.stencil_mask_separate(gl::BACK, 0xFFFFFFFF);
|
||||||
gl.clear_stencil(0);
|
gl.clear_stencil(0);
|
||||||
}
|
|
||||||
|
|
||||||
gl.clear(bits);
|
gl.clear(bits);
|
||||||
|
|
||||||
if state.scissor_test_enabled {
|
state.restore_invariant(gl);
|
||||||
gl.enable(gl::SCISSOR_TEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
if color {
|
|
||||||
let (r, g, b, a) = state.clear_color;
|
|
||||||
gl.clear_color(r, g, b, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
if depth {
|
|
||||||
gl.depth_mask(state.depth_write_mask);
|
|
||||||
gl.clear_depth(state.depth_clear_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if stencil {
|
|
||||||
let (front, back) = state.stencil_write_mask;
|
|
||||||
gl.stencil_mask_separate(gl::FRONT, front);
|
|
||||||
gl.stencil_mask_separate(gl::BACK, back);
|
|
||||||
gl.clear_stencil(state.stencil_clear_value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
@ -2213,6 +2347,7 @@ impl WebGLImpl {
|
||||||
&mut transform_feedback_mode,
|
&mut transform_feedback_mode,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramLinkInfo {
|
ProgramLinkInfo {
|
||||||
linked: true,
|
linked: true,
|
||||||
active_attribs,
|
active_attribs,
|
||||||
|
@ -2243,7 +2378,7 @@ impl WebGLImpl {
|
||||||
// array object functions, but support a set of APPLE extension functions that
|
// array object functions, but support a set of APPLE extension functions that
|
||||||
// provide VAO support instead.
|
// provide VAO support instead.
|
||||||
fn needs_apple_vertex_arrays(gl_version: GLVersion) -> bool {
|
fn needs_apple_vertex_arrays(gl_version: GLVersion) -> bool {
|
||||||
cfg!(target_os = "macos") && !opts::get().headless && gl_version.major < 3
|
cfg!(target_os = "macos") && gl_version.major < 3
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
@ -2427,8 +2562,8 @@ impl WebGLImpl {
|
||||||
/// Updates the swap buffers if the context surface needs to be changed
|
/// Updates the swap buffers if the context surface needs to be changed
|
||||||
fn attach_surface(
|
fn attach_surface(
|
||||||
context_id: WebGLContextId,
|
context_id: WebGLContextId,
|
||||||
webrender_swap_chains: &SwapChains<WebGLContextId>,
|
webrender_swap_chains: &SwapChains<WebGLContextId, Device>,
|
||||||
webxr_swap_chains: &SwapChains<WebXRSwapChainId>,
|
webxr_swap_chains: &SwapChains<WebXRSwapChainId, Device>,
|
||||||
request: WebGLFramebufferBindingRequest,
|
request: WebGLFramebufferBindingRequest,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
device: &mut Device,
|
device: &mut Device,
|
||||||
|
@ -2479,6 +2614,7 @@ impl WebGLImpl {
|
||||||
request: WebGLFramebufferBindingRequest,
|
request: WebGLFramebufferBindingRequest,
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
device: &Device,
|
device: &Device,
|
||||||
|
state: &mut GLState,
|
||||||
) {
|
) {
|
||||||
let id = match request {
|
let id = match request {
|
||||||
WebGLFramebufferBindingRequest::Explicit(WebGLFramebufferId::Transparent(id)) => {
|
WebGLFramebufferBindingRequest::Explicit(WebGLFramebufferId::Transparent(id)) => {
|
||||||
|
@ -2496,6 +2632,12 @@ impl WebGLImpl {
|
||||||
|
|
||||||
debug!("WebGLImpl::bind_framebuffer: {:?}", id);
|
debug!("WebGLImpl::bind_framebuffer: {:?}", id);
|
||||||
gl.bind_framebuffer(target, id);
|
gl.bind_framebuffer(target, id);
|
||||||
|
|
||||||
|
if (target == gl::FRAMEBUFFER) || (target == gl::DRAW_FRAMEBUFFER) {
|
||||||
|
state.drawing_to_default_framebuffer =
|
||||||
|
request == WebGLFramebufferBindingRequest::Default;
|
||||||
|
state.restore_invariant(gl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2885,27 +3027,41 @@ fn flip_pixels_y(
|
||||||
|
|
||||||
// Clamp a size to the current GL context's max viewport
|
// Clamp a size to the current GL context's max viewport
|
||||||
fn clamp_viewport(gl: &Gl, size: Size2D<u32>) -> Size2D<u32> {
|
fn clamp_viewport(gl: &Gl, size: Size2D<u32>) -> Size2D<u32> {
|
||||||
let mut max_size = [i32::max_value(), i32::max_value()];
|
let mut max_viewport = [i32::max_value(), i32::max_value()];
|
||||||
|
let mut max_renderbuffer = [i32::max_value()];
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe {
|
unsafe {
|
||||||
gl.get_integer_v(gl::MAX_VIEWPORT_DIMS, &mut max_size);
|
gl.get_integer_v(gl::MAX_VIEWPORT_DIMS, &mut max_viewport);
|
||||||
|
gl.get_integer_v(gl::MAX_RENDERBUFFER_SIZE, &mut max_renderbuffer);
|
||||||
debug_assert_eq!(gl.get_error(), gl::NO_ERROR);
|
debug_assert_eq!(gl.get_error(), gl::NO_ERROR);
|
||||||
}
|
}
|
||||||
Size2D::new(
|
Size2D::new(
|
||||||
size.width.min(max_size[0] as u32).max(1),
|
size.width
|
||||||
size.height.min(max_size[1] as u32).max(1),
|
.min(max_viewport[0] as u32)
|
||||||
|
.min(max_renderbuffer[0] as u32)
|
||||||
|
.max(1),
|
||||||
|
size.height
|
||||||
|
.min(max_viewport[1] as u32)
|
||||||
|
.min(max_renderbuffer[0] as u32)
|
||||||
|
.max(1),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ToSurfmanVersion {
|
trait ToSurfmanVersion {
|
||||||
fn to_surfman_version(self) -> GLVersion;
|
fn to_surfman_version(self, api_type: gl::GlType) -> GLVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToSurfmanVersion for WebGLVersion {
|
impl ToSurfmanVersion for WebGLVersion {
|
||||||
fn to_surfman_version(self) -> GLVersion {
|
fn to_surfman_version(self, api_type: gl::GlType) -> GLVersion {
|
||||||
|
if api_type == gl::GlType::Gles {
|
||||||
|
return GLVersion::new(3, 0);
|
||||||
|
}
|
||||||
match self {
|
match self {
|
||||||
WebGLVersion::WebGL1 => GLVersion::new(2, 0),
|
// We make use of GL_PACK_PIXEL_BUFFER, which needs at least GL2.1
|
||||||
WebGLVersion::WebGL2 => GLVersion::new(3, 0),
|
// We make use of compatibility mode, which needs at most GL3.0
|
||||||
|
WebGLVersion::WebGL1 => GLVersion::new(2, 1),
|
||||||
|
// The WebGL2 conformance tests use std140 layout, which needs at GL3.1
|
||||||
|
WebGLVersion::WebGL2 => GLVersion::new(3, 2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2914,6 +3070,7 @@ trait SurfmanContextAttributeFlagsConvert {
|
||||||
fn to_surfman_context_attribute_flags(
|
fn to_surfman_context_attribute_flags(
|
||||||
&self,
|
&self,
|
||||||
webgl_version: WebGLVersion,
|
webgl_version: WebGLVersion,
|
||||||
|
api_type: gl::GlType,
|
||||||
) -> ContextAttributeFlags;
|
) -> ContextAttributeFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2921,12 +3078,13 @@ impl SurfmanContextAttributeFlagsConvert for GLContextAttributes {
|
||||||
fn to_surfman_context_attribute_flags(
|
fn to_surfman_context_attribute_flags(
|
||||||
&self,
|
&self,
|
||||||
webgl_version: WebGLVersion,
|
webgl_version: WebGLVersion,
|
||||||
|
api_type: gl::GlType,
|
||||||
) -> ContextAttributeFlags {
|
) -> ContextAttributeFlags {
|
||||||
let mut flags = ContextAttributeFlags::empty();
|
let mut flags = ContextAttributeFlags::empty();
|
||||||
flags.set(ContextAttributeFlags::ALPHA, self.alpha);
|
flags.set(ContextAttributeFlags::ALPHA, self.alpha);
|
||||||
flags.set(ContextAttributeFlags::DEPTH, self.depth);
|
flags.set(ContextAttributeFlags::DEPTH, self.depth);
|
||||||
flags.set(ContextAttributeFlags::STENCIL, self.stencil);
|
flags.set(ContextAttributeFlags::STENCIL, self.stencil);
|
||||||
if webgl_version == WebGLVersion::WebGL1 {
|
if (webgl_version == WebGLVersion::WebGL1) && (api_type == gl::GlType::Gl) {
|
||||||
flags.set(ContextAttributeFlags::COMPATIBILITY_PROFILE, true);
|
flags.set(ContextAttributeFlags::COMPATIBILITY_PROFILE, true);
|
||||||
}
|
}
|
||||||
flags
|
flags
|
||||||
|
|
|
@ -667,7 +667,7 @@ pub enum WebGLFramebufferId {
|
||||||
Opaque(WebGLOpaqueFramebufferId),
|
Opaque(WebGLOpaqueFramebufferId),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
pub enum WebGLFramebufferBindingRequest {
|
pub enum WebGLFramebufferBindingRequest {
|
||||||
Explicit(WebGLFramebufferId),
|
Explicit(WebGLFramebufferId),
|
||||||
Default,
|
Default,
|
||||||
|
|
|
@ -40,6 +40,7 @@ style_traits = {path = "../style_traits"}
|
||||||
time = "0.1.17"
|
time = "0.1.17"
|
||||||
webrender = {git = "https://github.com/servo/webrender", features = ["capture"]}
|
webrender = {git = "https://github.com/servo/webrender", features = ["capture"]}
|
||||||
webrender_api = {git = "https://github.com/servo/webrender"}
|
webrender_api = {git = "https://github.com/servo/webrender"}
|
||||||
|
webrender_surfman = {path = "../webrender_surfman"}
|
||||||
webxr = {git = "https://github.com/servo/webxr"}
|
webxr = {git = "https://github.com/servo/webxr"}
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|
|
@ -19,6 +19,7 @@ use gfx_traits::Epoch;
|
||||||
use image::{DynamicImage, ImageFormat};
|
use image::{DynamicImage, ImageFormat};
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
|
use log::warn;
|
||||||
use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId};
|
use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId};
|
||||||
use net_traits::image::base::Image;
|
use net_traits::image::base::Image;
|
||||||
use net_traits::image_cache::CorsStatus;
|
use net_traits::image_cache::CorsStatus;
|
||||||
|
@ -46,6 +47,7 @@ use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
|
||||||
use time::{now, precise_time_ns, precise_time_s};
|
use time::{now, precise_time_ns, precise_time_s};
|
||||||
use webrender_api::units::{DeviceIntPoint, DeviceIntSize, DevicePoint, LayoutVector2D};
|
use webrender_api::units::{DeviceIntPoint, DeviceIntSize, DevicePoint, LayoutVector2D};
|
||||||
use webrender_api::{self, HitTestFlags, HitTestResult, ScrollLocation};
|
use webrender_api::{self, HitTestFlags, HitTestResult, ScrollLocation};
|
||||||
|
use webrender_surfman::WebrenderSurfman;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum UnableToComposite {
|
enum UnableToComposite {
|
||||||
|
@ -178,6 +180,12 @@ pub struct IOCompositor<Window: WindowMethods + ?Sized> {
|
||||||
/// The webrender interface, if enabled.
|
/// The webrender interface, if enabled.
|
||||||
webrender_api: webrender_api::RenderApi,
|
webrender_api: webrender_api::RenderApi,
|
||||||
|
|
||||||
|
/// The surfman instance that webrender targets
|
||||||
|
webrender_surfman: WebrenderSurfman,
|
||||||
|
|
||||||
|
/// The GL bindings for webrender
|
||||||
|
webrender_gl: Rc<dyn gleam::gl::Gl>,
|
||||||
|
|
||||||
/// Some XR devices want to run on the main thread.
|
/// Some XR devices want to run on the main thread.
|
||||||
pub webxr_main_thread: webxr::MainThreadRegistry,
|
pub webxr_main_thread: webxr::MainThreadRegistry,
|
||||||
|
|
||||||
|
@ -316,6 +324,8 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
||||||
webrender: state.webrender,
|
webrender: state.webrender,
|
||||||
webrender_document: state.webrender_document,
|
webrender_document: state.webrender_document,
|
||||||
webrender_api: state.webrender_api,
|
webrender_api: state.webrender_api,
|
||||||
|
webrender_surfman: state.webrender_surfman,
|
||||||
|
webrender_gl: state.webrender_gl,
|
||||||
webxr_main_thread: state.webxr_main_thread,
|
webxr_main_thread: state.webxr_main_thread,
|
||||||
pending_paint_metrics: HashMap::new(),
|
pending_paint_metrics: HashMap::new(),
|
||||||
cursor: Cursor::None,
|
cursor: Cursor::None,
|
||||||
|
@ -345,6 +355,9 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
||||||
convert_mouse_to_touch,
|
convert_mouse_to_touch,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Make sure the GL state is OK
|
||||||
|
compositor.assert_gl_framebuffer_complete();
|
||||||
|
|
||||||
// Set the size of the root layer.
|
// Set the size of the root layer.
|
||||||
compositor.update_zoom_transform();
|
compositor.update_zoom_transform();
|
||||||
|
|
||||||
|
@ -352,7 +365,9 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self) {
|
pub fn deinit(self) {
|
||||||
self.window.make_gl_context_current();
|
if let Err(err) = self.webrender_surfman.make_gl_context_current() {
|
||||||
|
warn!("Failed to make GL context current: {:?}", err);
|
||||||
|
}
|
||||||
self.webrender.deinit();
|
self.webrender.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1238,7 +1253,22 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
||||||
) -> Result<Option<Image>, UnableToComposite> {
|
) -> Result<Option<Image>, UnableToComposite> {
|
||||||
let size = self.embedder_coordinates.framebuffer.to_u32();
|
let size = self.embedder_coordinates.framebuffer.to_u32();
|
||||||
|
|
||||||
self.window.make_gl_context_current();
|
if let Err(err) = self.webrender_surfman.make_gl_context_current() {
|
||||||
|
warn!("Failed to make GL context current: {:?}", err);
|
||||||
|
}
|
||||||
|
self.assert_no_gl_error();
|
||||||
|
|
||||||
|
// Bind the webrender framebuffer
|
||||||
|
let framebuffer_object = self
|
||||||
|
.webrender_surfman
|
||||||
|
.context_surface_info()
|
||||||
|
.unwrap_or(None)
|
||||||
|
.map(|info| info.framebuffer_object)
|
||||||
|
.unwrap_or(0);
|
||||||
|
self.webrender_gl
|
||||||
|
.bind_framebuffer(gleam::gl::FRAMEBUFFER, framebuffer_object);
|
||||||
|
self.assert_gl_framebuffer_complete();
|
||||||
|
|
||||||
self.webrender.update();
|
self.webrender.update();
|
||||||
|
|
||||||
let wait_for_stable_image = match target {
|
let wait_for_stable_image = match target {
|
||||||
|
@ -1266,7 +1296,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
||||||
CompositeTarget::Window => gl::RenderTargetInfo::default(),
|
CompositeTarget::Window => gl::RenderTargetInfo::default(),
|
||||||
#[cfg(feature = "gl")]
|
#[cfg(feature = "gl")]
|
||||||
CompositeTarget::WindowAndPng | CompositeTarget::PngFile => gl::initialize_png(
|
CompositeTarget::WindowAndPng | CompositeTarget::PngFile => gl::initialize_png(
|
||||||
&*self.window.gl(),
|
&*self.webrender_gl,
|
||||||
FramebufferUintLength::new(size.width),
|
FramebufferUintLength::new(size.width),
|
||||||
FramebufferUintLength::new(size.height),
|
FramebufferUintLength::new(size.height),
|
||||||
),
|
),
|
||||||
|
@ -1347,7 +1377,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
||||||
#[cfg(feature = "gl")]
|
#[cfg(feature = "gl")]
|
||||||
CompositeTarget::WindowAndPng => {
|
CompositeTarget::WindowAndPng => {
|
||||||
let img = gl::draw_img(
|
let img = gl::draw_img(
|
||||||
&*self.window.gl(),
|
&*self.webrender_gl,
|
||||||
rt_info,
|
rt_info,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
|
@ -1365,7 +1395,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
||||||
},
|
},
|
||||||
#[cfg(feature = "gl")]
|
#[cfg(feature = "gl")]
|
||||||
CompositeTarget::PngFile => {
|
CompositeTarget::PngFile => {
|
||||||
let gl = &*self.window.gl();
|
let gl = &*self.webrender_gl;
|
||||||
profile(
|
profile(
|
||||||
ProfilerCategory::ImageSaving,
|
ProfilerCategory::ImageSaving,
|
||||||
None,
|
None,
|
||||||
|
@ -1399,7 +1429,9 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Perform the page flip. This will likely block for a while.
|
// Perform the page flip. This will likely block for a while.
|
||||||
self.window.present();
|
if let Err(err) = self.webrender_surfman.present() {
|
||||||
|
warn!("Failed to present surface: {:?}", err);
|
||||||
|
}
|
||||||
|
|
||||||
self.last_composite_time = precise_time_ns();
|
self.last_composite_time = precise_time_ns();
|
||||||
|
|
||||||
|
@ -1426,11 +1458,13 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_background(&self) {
|
fn clear_background(&self) {
|
||||||
let gl = self.window.gl();
|
let gl = &self.webrender_gl;
|
||||||
|
self.assert_gl_framebuffer_complete();
|
||||||
|
|
||||||
// Make framebuffer fully transparent.
|
// Make framebuffer fully transparent.
|
||||||
gl.clear_color(0.0, 0.0, 0.0, 0.0);
|
gl.clear_color(0.0, 0.0, 0.0, 0.0);
|
||||||
gl.clear(gleam::gl::COLOR_BUFFER_BIT);
|
gl.clear(gleam::gl::COLOR_BUFFER_BIT);
|
||||||
|
self.assert_gl_framebuffer_complete();
|
||||||
|
|
||||||
// Make the viewport white.
|
// Make the viewport white.
|
||||||
let viewport = self.embedder_coordinates.get_flipped_viewport();
|
let viewport = self.embedder_coordinates.get_flipped_viewport();
|
||||||
|
@ -1444,6 +1478,24 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
||||||
gl.enable(gleam::gl::SCISSOR_TEST);
|
gl.enable(gleam::gl::SCISSOR_TEST);
|
||||||
gl.clear(gleam::gl::COLOR_BUFFER_BIT);
|
gl.clear(gleam::gl::COLOR_BUFFER_BIT);
|
||||||
gl.disable(gleam::gl::SCISSOR_TEST);
|
gl.disable(gleam::gl::SCISSOR_TEST);
|
||||||
|
self.assert_gl_framebuffer_complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn assert_no_gl_error(&self) {
|
||||||
|
debug_assert_eq!(self.webrender_gl.get_error(), gleam::gl::NO_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn assert_gl_framebuffer_complete(&self) {
|
||||||
|
debug_assert_eq!(
|
||||||
|
(
|
||||||
|
self.webrender_gl.get_error(),
|
||||||
|
self.webrender_gl
|
||||||
|
.check_frame_buffer_status(gleam::gl::FRAMEBUFFER)
|
||||||
|
),
|
||||||
|
(gleam::gl::NO_ERROR, gleam::gl::FRAMEBUFFER_COMPLETE)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_root_pipeline_id(&self) -> Option<PipelineId> {
|
fn get_root_pipeline_id(&self) -> Option<PipelineId> {
|
||||||
|
|
|
@ -17,12 +17,14 @@ use profile_traits::mem;
|
||||||
use profile_traits::time;
|
use profile_traits::time;
|
||||||
use script_traits::{AnimationState, EventResult, MouseButton, MouseEventType};
|
use script_traits::{AnimationState, EventResult, MouseButton, MouseEventType};
|
||||||
use std::fmt::{Debug, Error, Formatter};
|
use std::fmt::{Debug, Error, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style_traits::viewport::ViewportConstraints;
|
use style_traits::viewport::ViewportConstraints;
|
||||||
use style_traits::CSSPixel;
|
use style_traits::CSSPixel;
|
||||||
use webrender_api;
|
use webrender_api;
|
||||||
use webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
use webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
||||||
|
use webrender_surfman::WebrenderSurfman;
|
||||||
|
|
||||||
/// Sends messages to the compositor.
|
/// Sends messages to the compositor.
|
||||||
pub struct CompositorProxy {
|
pub struct CompositorProxy {
|
||||||
|
@ -166,6 +168,8 @@ pub struct InitialCompositorState {
|
||||||
pub webrender: webrender::Renderer,
|
pub webrender: webrender::Renderer,
|
||||||
pub webrender_document: webrender_api::DocumentId,
|
pub webrender_document: webrender_api::DocumentId,
|
||||||
pub webrender_api: webrender_api::RenderApi,
|
pub webrender_api: webrender_api::RenderApi,
|
||||||
|
pub webrender_surfman: WebrenderSurfman,
|
||||||
|
pub webrender_gl: Rc<dyn gleam::gl::Gl>,
|
||||||
pub webxr_main_thread: webxr::MainThreadRegistry,
|
pub webxr_main_thread: webxr::MainThreadRegistry,
|
||||||
pub pending_wr_frame: Arc<AtomicBool>,
|
pub pending_wr_frame: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
|
#![feature(track_caller)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
use canvas::{SurfaceProviders, WebGlExecutor};
|
use canvas::{SurfaceProviders, WebGlExecutor};
|
||||||
use embedder_traits::{EmbedderProxy, EventLoopWaker};
|
use embedder_traits::{EmbedderProxy, EventLoopWaker};
|
||||||
use euclid::Scale;
|
use euclid::Scale;
|
||||||
#[cfg(feature = "gl")]
|
|
||||||
use gleam::gl;
|
|
||||||
use keyboard_types::KeyboardEvent;
|
use keyboard_types::KeyboardEvent;
|
||||||
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId, TraversalDirection};
|
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId, TraversalDirection};
|
||||||
use script_traits::{MediaSessionActionType, MouseButton, TouchEventType, TouchId, WheelDelta};
|
use script_traits::{MediaSessionActionType, MouseButton, TouchEventType, TouchId, WheelDelta};
|
||||||
|
@ -16,14 +14,13 @@ use servo_geometry::DeviceIndependentPixel;
|
||||||
use servo_media::player::context::{GlApi, GlContext, NativeDisplay};
|
use servo_media::player::context::{GlApi, GlContext, NativeDisplay};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::fmt::{Debug, Error, Formatter};
|
use std::fmt::{Debug, Error, Formatter};
|
||||||
#[cfg(feature = "gl")]
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use style_traits::DevicePixel;
|
use style_traits::DevicePixel;
|
||||||
|
|
||||||
use webrender_api::units::DevicePoint;
|
use webrender_api::units::DevicePoint;
|
||||||
use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||||
use webrender_api::ScrollLocation;
|
use webrender_api::ScrollLocation;
|
||||||
|
use webrender_surfman::WebrenderSurfman;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum MouseWindowEvent {
|
pub enum MouseWindowEvent {
|
||||||
|
@ -148,14 +145,10 @@ pub enum AnimationState {
|
||||||
Animating,
|
Animating,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this trait assumes that the window is responsible
|
||||||
|
// for creating the GL context, making it current, buffer
|
||||||
|
// swapping, etc. Really that should all be done by surfman.
|
||||||
pub trait WindowMethods {
|
pub trait WindowMethods {
|
||||||
/// Presents the window to the screen (perhaps by page flipping).
|
|
||||||
fn present(&self);
|
|
||||||
/// Make the OpenGL context current.
|
|
||||||
fn make_gl_context_current(&self);
|
|
||||||
/// Return the GL function pointer trait.
|
|
||||||
#[cfg(feature = "gl")]
|
|
||||||
fn gl(&self) -> Rc<dyn gl::Gl>;
|
|
||||||
/// Get the coordinates of the native window, the screen and the framebuffer.
|
/// Get the coordinates of the native window, the screen and the framebuffer.
|
||||||
fn get_coordinates(&self) -> EmbedderCoordinates;
|
fn get_coordinates(&self) -> EmbedderCoordinates;
|
||||||
/// Set whether the application is currently animating.
|
/// Set whether the application is currently animating.
|
||||||
|
@ -163,12 +156,14 @@ pub trait WindowMethods {
|
||||||
/// will want to avoid blocking on UI events, and just
|
/// will want to avoid blocking on UI events, and just
|
||||||
/// run the event loop at the vsync interval.
|
/// run the event loop at the vsync interval.
|
||||||
fn set_animation_state(&self, _state: AnimationState);
|
fn set_animation_state(&self, _state: AnimationState);
|
||||||
/// Get the GL context
|
/// Get the media GL context
|
||||||
fn get_gl_context(&self) -> GlContext;
|
fn get_gl_context(&self) -> GlContext;
|
||||||
/// Get the native display
|
/// Get the media native display
|
||||||
fn get_native_display(&self) -> NativeDisplay;
|
fn get_native_display(&self) -> NativeDisplay;
|
||||||
/// Get the GL api
|
/// Get the GL api
|
||||||
fn get_gl_api(&self) -> GlApi;
|
fn get_gl_api(&self) -> GlApi;
|
||||||
|
/// Get the webrender surfman instance
|
||||||
|
fn webrender_surfman(&self) -> WebrenderSurfman;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait EmbedderMethods {
|
pub trait EmbedderMethods {
|
||||||
|
|
|
@ -321,7 +321,11 @@ mod gen {
|
||||||
subpixel_text_antialiasing: {
|
subpixel_text_antialiasing: {
|
||||||
#[serde(rename = "gfx.subpixel-text-antialiasing.enabled")]
|
#[serde(rename = "gfx.subpixel-text-antialiasing.enabled")]
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
}
|
},
|
||||||
|
texture_swizzling: {
|
||||||
|
#[serde(rename = "gfx.texture-swizzling.enabled")]
|
||||||
|
enabled: bool,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
js: {
|
js: {
|
||||||
asmjs: {
|
asmjs: {
|
||||||
|
|
|
@ -52,12 +52,24 @@ const DEFAULT_DISABLED_GET_PARAMETER_NAMES_WEBGL1: [GLenum; 3] = [
|
||||||
OESVertexArrayObjectConstants::VERTEX_ARRAY_BINDING_OES,
|
OESVertexArrayObjectConstants::VERTEX_ARRAY_BINDING_OES,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Param names that are implemented for glGetParameter in a WebGL 2.0 context
|
||||||
|
// but must trigger a InvalidEnum error until the related WebGL Extensions are enabled.
|
||||||
|
// Example: https://www.khronos.org/registry/webgl/extensions/EXT_texture_filter_anisotropic/
|
||||||
|
const DEFAULT_DISABLED_GET_PARAMETER_NAMES_WEBGL2: [GLenum; 1] =
|
||||||
|
[EXTTextureFilterAnisotropicConstants::MAX_TEXTURE_MAX_ANISOTROPY_EXT];
|
||||||
|
|
||||||
// Param names that are implemented for glGetTexParameter in a WebGL 1.0 context
|
// Param names that are implemented for glGetTexParameter in a WebGL 1.0 context
|
||||||
// but must trigger a InvalidEnum error until the related WebGL Extensions are enabled.
|
// but must trigger a InvalidEnum error until the related WebGL Extensions are enabled.
|
||||||
// Example: https://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/
|
// Example: https://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/
|
||||||
const DEFAULT_DISABLED_GET_TEX_PARAMETER_NAMES_WEBGL1: [GLenum; 1] =
|
const DEFAULT_DISABLED_GET_TEX_PARAMETER_NAMES_WEBGL1: [GLenum; 1] =
|
||||||
[EXTTextureFilterAnisotropicConstants::TEXTURE_MAX_ANISOTROPY_EXT];
|
[EXTTextureFilterAnisotropicConstants::TEXTURE_MAX_ANISOTROPY_EXT];
|
||||||
|
|
||||||
|
// Param names that are implemented for glGetTexParameter in a WebGL 2.0 context
|
||||||
|
// but must trigger a InvalidEnum error until the related WebGL Extensions are enabled.
|
||||||
|
// Example: https://www.khronos.org/registry/webgl/extensions/EXT_texture_filter_anisotropic/
|
||||||
|
const DEFAULT_DISABLED_GET_TEX_PARAMETER_NAMES_WEBGL2: [GLenum; 1] =
|
||||||
|
[EXTTextureFilterAnisotropicConstants::TEXTURE_MAX_ANISOTROPY_EXT];
|
||||||
|
|
||||||
// Param names that are implemented for glGetVertexAttrib in a WebGL 1.0 context
|
// Param names that are implemented for glGetVertexAttrib in a WebGL 1.0 context
|
||||||
// but must trigger a InvalidEnum error until the related WebGL Extensions are enabled.
|
// but must trigger a InvalidEnum error until the related WebGL Extensions are enabled.
|
||||||
// Example: https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
|
// Example: https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
|
||||||
|
@ -116,8 +128,14 @@ impl WebGLExtensionFeatures {
|
||||||
),
|
),
|
||||||
WebGLVersion::WebGL2 => (
|
WebGLVersion::WebGL2 => (
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Default::default(),
|
DEFAULT_DISABLED_GET_PARAMETER_NAMES_WEBGL2
|
||||||
Default::default(),
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
DEFAULT_DISABLED_GET_TEX_PARAMETER_NAMES_WEBGL2
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
|
|
@ -233,7 +233,7 @@ impl WebGLRenderbuffer {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
let samples = receiver.recv().unwrap();
|
let samples = receiver.recv().unwrap();
|
||||||
if sample_count < 0 || sample_count as usize > samples.len() {
|
if sample_count < 0 || sample_count > samples.get(0).cloned().unwrap_or(0) {
|
||||||
return Err(WebGLError::InvalidOperation);
|
return Err(WebGLError::InvalidOperation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,8 +277,49 @@ impl WebGLShader {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
match validator.compile_and_translate(&[&source]) {
|
// Replicating
|
||||||
Ok(translated_source) => {
|
// https://searchfox.org/mozilla-central/rev/c621276fbdd9591f52009042d959b9e19b66d49f/dom/canvas/WebGLShaderValidator.cpp#32
|
||||||
|
let options = mozangle::shaders::ffi::SH_VARIABLES |
|
||||||
|
mozangle::shaders::ffi::SH_ENFORCE_PACKING_RESTRICTIONS |
|
||||||
|
mozangle::shaders::ffi::SH_OBJECT_CODE |
|
||||||
|
mozangle::shaders::ffi::SH_INIT_GL_POSITION |
|
||||||
|
mozangle::shaders::ffi::SH_INITIALIZE_UNINITIALIZED_LOCALS |
|
||||||
|
mozangle::shaders::ffi::SH_INIT_OUTPUT_VARIABLES |
|
||||||
|
mozangle::shaders::ffi::SH_LIMIT_EXPRESSION_COMPLEXITY |
|
||||||
|
mozangle::shaders::ffi::SH_LIMIT_CALL_STACK_DEPTH |
|
||||||
|
if cfg!(target_os = "macos") {
|
||||||
|
// Work around https://bugs.webkit.org/show_bug.cgi?id=124684,
|
||||||
|
// https://chromium.googlesource.com/angle/angle/+/5e70cf9d0b1bb
|
||||||
|
mozangle::shaders::ffi::SH_UNFOLD_SHORT_CIRCUIT |
|
||||||
|
// Work around that Mac drivers handle struct scopes incorrectly.
|
||||||
|
mozangle::shaders::ffi::SH_REGENERATE_STRUCT_NAMES |
|
||||||
|
// Work around that Intel drivers on Mac OSX handle for-loop incorrectly.
|
||||||
|
mozangle::shaders::ffi::SH_ADD_AND_TRUE_TO_LOOP_CONDITION
|
||||||
|
} else {
|
||||||
|
// We want to do this everywhere, but to do this on Mac, we need
|
||||||
|
// to do it only on Mac OSX > 10.6 as this causes the shader
|
||||||
|
// compiler in 10.6 to crash
|
||||||
|
mozangle::shaders::ffi::SH_CLAMP_INDIRECT_ARRAY_BOUNDS
|
||||||
|
};
|
||||||
|
|
||||||
|
// Replicating
|
||||||
|
// https://github.com/servo/mozangle/blob/706a9baaf8026c1a3cb6c67ba63aa5f4734264d0/src/shaders/mod.rs#L226
|
||||||
|
let options = options |
|
||||||
|
mozangle::shaders::ffi::SH_VALIDATE |
|
||||||
|
mozangle::shaders::ffi::SH_OBJECT_CODE |
|
||||||
|
mozangle::shaders::ffi::SH_VARIABLES | // For uniform_name_map()
|
||||||
|
mozangle::shaders::ffi::SH_EMULATE_ABS_INT_FUNCTION | // To workaround drivers
|
||||||
|
mozangle::shaders::ffi::SH_EMULATE_ISNAN_FLOAT_FUNCTION | // To workaround drivers
|
||||||
|
mozangle::shaders::ffi::SH_EMULATE_ATAN2_FLOAT_FUNCTION | // To workaround drivers
|
||||||
|
mozangle::shaders::ffi::SH_CLAMP_INDIRECT_ARRAY_BOUNDS |
|
||||||
|
mozangle::shaders::ffi::SH_INIT_GL_POSITION |
|
||||||
|
mozangle::shaders::ffi::SH_ENFORCE_PACKING_RESTRICTIONS |
|
||||||
|
mozangle::shaders::ffi::SH_LIMIT_EXPRESSION_COMPLEXITY |
|
||||||
|
mozangle::shaders::ffi::SH_LIMIT_CALL_STACK_DEPTH;
|
||||||
|
|
||||||
|
match validator.compile(&[&source], options) {
|
||||||
|
Ok(()) => {
|
||||||
|
let translated_source = validator.object_code();
|
||||||
debug!("Shader translated: {}", translated_source);
|
debug!("Shader translated: {}", translated_source);
|
||||||
// NOTE: At this point we should be pretty sure that the compilation in the paint thread
|
// NOTE: At this point we should be pretty sure that the compilation in the paint thread
|
||||||
// will succeed.
|
// will succeed.
|
||||||
|
|
|
@ -81,11 +81,12 @@ style_traits = {path = "../style_traits", features = ["servo"]}
|
||||||
webgpu = {path = "../webgpu"}
|
webgpu = {path = "../webgpu"}
|
||||||
webrender = {git = "https://github.com/servo/webrender"}
|
webrender = {git = "https://github.com/servo/webrender"}
|
||||||
webrender_api = {git = "https://github.com/servo/webrender"}
|
webrender_api = {git = "https://github.com/servo/webrender"}
|
||||||
|
webrender_surfman = {path = "../webrender_surfman"}
|
||||||
webrender_traits = {path = "../webrender_traits"}
|
webrender_traits = {path = "../webrender_traits"}
|
||||||
webdriver_server = {path = "../webdriver_server", optional = true}
|
webdriver_server = {path = "../webdriver_server", optional = true}
|
||||||
webxr-api = {git = "https://github.com/servo/webxr"}
|
webxr-api = {git = "https://github.com/servo/webxr"}
|
||||||
webxr = {git = "https://github.com/servo/webxr"}
|
webxr = {git = "https://github.com/servo/webxr"}
|
||||||
surfman = { version = "0.1", features = ["sm-osmesa"] }
|
surfman = "0.2"
|
||||||
gstreamer = { version = "0.15", optional = true }
|
gstreamer = { version = "0.15", optional = true }
|
||||||
|
|
||||||
[target.'cfg(all(not(target_os = "windows"), not(target_os = "ios"), not(target_os="android"), not(target_arch="arm"), not(target_arch="aarch64")))'.dependencies]
|
[target.'cfg(all(not(target_os = "windows"), not(target_os = "ios"), not(target_os="android"), not(target_arch="arm"), not(target_arch="aarch64")))'.dependencies]
|
||||||
|
|
|
@ -51,6 +51,7 @@ pub use style;
|
||||||
pub use style_traits;
|
pub use style_traits;
|
||||||
pub use webgpu;
|
pub use webgpu;
|
||||||
pub use webrender_api;
|
pub use webrender_api;
|
||||||
|
pub use webrender_surfman;
|
||||||
pub use webrender_traits;
|
pub use webrender_traits;
|
||||||
|
|
||||||
#[cfg(feature = "webdriver")]
|
#[cfg(feature = "webdriver")]
|
||||||
|
@ -116,14 +117,9 @@ use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
#[cfg(not(target_os = "windows"))]
|
use surfman::GLApi;
|
||||||
use surfman::platform::default::device::Device as HWDevice;
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
use surfman::platform::generic::osmesa::device::Device as SWDevice;
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
use surfman::platform::generic::universal::context::Context;
|
|
||||||
use surfman::platform::generic::universal::device::Device;
|
|
||||||
use webrender::{RendererKind, ShaderPrecacheFlags};
|
use webrender::{RendererKind, ShaderPrecacheFlags};
|
||||||
|
use webrender_surfman::WebrenderSurfman;
|
||||||
use webrender_traits::WebrenderImageHandlerType;
|
use webrender_traits::WebrenderImageHandlerType;
|
||||||
use webrender_traits::{WebrenderExternalImageHandlers, WebrenderExternalImageRegistry};
|
use webrender_traits::{WebrenderExternalImageHandlers, WebrenderExternalImageRegistry};
|
||||||
|
|
||||||
|
@ -353,8 +349,28 @@ where
|
||||||
.unwrap_or(default_user_agent_string_for(DEFAULT_USER_AGENT).into()),
|
.unwrap_or(default_user_agent_string_for(DEFAULT_USER_AGENT).into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Initialize surfman
|
||||||
|
let webrender_surfman = window.webrender_surfman();
|
||||||
|
|
||||||
|
// Get GL bindings
|
||||||
|
let webrender_gl = match webrender_surfman.connection().gl_api() {
|
||||||
|
GLApi::GL => unsafe { gl::GlFns::load_with(|s| webrender_surfman.get_proc_address(s)) },
|
||||||
|
GLApi::GLES => unsafe {
|
||||||
|
gl::GlesFns::load_with(|s| webrender_surfman.get_proc_address(s))
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Make sure the gl context is made current.
|
// Make sure the gl context is made current.
|
||||||
window.make_gl_context_current();
|
webrender_surfman.make_gl_context_current().unwrap();
|
||||||
|
debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR,);
|
||||||
|
|
||||||
|
// Bind the webrender framebuffer
|
||||||
|
let framebuffer_object = webrender_surfman
|
||||||
|
.context_surface_info()
|
||||||
|
.unwrap_or(None)
|
||||||
|
.map(|info| info.framebuffer_object)
|
||||||
|
.unwrap_or(0);
|
||||||
|
webrender_gl.bind_framebuffer(gleam::gl::FRAMEBUFFER, framebuffer_object);
|
||||||
|
|
||||||
// Reserving a namespace to create TopLevelBrowserContextId.
|
// Reserving a namespace to create TopLevelBrowserContextId.
|
||||||
PipelineNamespace::install(PipelineNamespaceId(0));
|
PipelineNamespace::install(PipelineNamespaceId(0));
|
||||||
|
@ -407,7 +423,7 @@ where
|
||||||
let window_size = Size2D::from_untyped(viewport_size.to_i32().to_untyped());
|
let window_size = Size2D::from_untyped(viewport_size.to_i32().to_untyped());
|
||||||
|
|
||||||
webrender::Renderer::new(
|
webrender::Renderer::new(
|
||||||
window.gl(),
|
webrender_gl.clone(),
|
||||||
render_notifier,
|
render_notifier,
|
||||||
webrender::RendererOptions {
|
webrender::RendererOptions {
|
||||||
device_pixel_ratio,
|
device_pixel_ratio,
|
||||||
|
@ -422,6 +438,7 @@ where
|
||||||
},
|
},
|
||||||
renderer_kind: renderer_kind,
|
renderer_kind: renderer_kind,
|
||||||
enable_subpixel_aa: opts.enable_subpixel_text_antialiasing,
|
enable_subpixel_aa: opts.enable_subpixel_text_antialiasing,
|
||||||
|
allow_texture_swizzling: pref!(gfx.texture_swizzling.enabled),
|
||||||
clear_color: None,
|
clear_color: None,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
@ -451,7 +468,8 @@ where
|
||||||
.expect("Failed to create WebXR device registry");
|
.expect("Failed to create WebXR device registry");
|
||||||
|
|
||||||
let (webgl_threads, webgl_extras) = create_webgl_threads(
|
let (webgl_threads, webgl_extras) = create_webgl_threads(
|
||||||
&*window,
|
webrender_surfman.clone(),
|
||||||
|
webrender_gl.clone(),
|
||||||
&mut webrender,
|
&mut webrender,
|
||||||
webrender_api_sender.clone(),
|
webrender_api_sender.clone(),
|
||||||
&mut webxr_main_thread,
|
&mut webxr_main_thread,
|
||||||
|
@ -542,6 +560,8 @@ where
|
||||||
webrender,
|
webrender,
|
||||||
webrender_document,
|
webrender_document,
|
||||||
webrender_api,
|
webrender_api,
|
||||||
|
webrender_surfman,
|
||||||
|
webrender_gl,
|
||||||
webxr_main_thread,
|
webxr_main_thread,
|
||||||
pending_wr_frame,
|
pending_wr_frame,
|
||||||
},
|
},
|
||||||
|
@ -806,6 +826,10 @@ where
|
||||||
log::set_max_level(filter);
|
log::set_max_level(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn window(&self) -> &Window {
|
||||||
|
&self.compositor.window
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self) {
|
pub fn deinit(self) {
|
||||||
self.compositor.deinit();
|
self.compositor.deinit();
|
||||||
}
|
}
|
||||||
|
@ -1030,8 +1054,9 @@ fn create_sandbox() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes the WebGL thread.
|
// Initializes the WebGL thread.
|
||||||
fn create_webgl_threads<W>(
|
fn create_webgl_threads(
|
||||||
window: &W,
|
webrender_surfman: WebrenderSurfman,
|
||||||
|
webrender_gl: Rc<dyn gl::Gl>,
|
||||||
webrender: &mut webrender::Renderer,
|
webrender: &mut webrender::Renderer,
|
||||||
webrender_api_sender: webrender_api::RenderApiSender,
|
webrender_api_sender: webrender_api::RenderApiSender,
|
||||||
webxr_main_thread: &mut webxr::MainThreadRegistry,
|
webxr_main_thread: &mut webxr::MainThreadRegistry,
|
||||||
|
@ -1040,45 +1065,8 @@ fn create_webgl_threads<W>(
|
||||||
) -> (
|
) -> (
|
||||||
Option<WebGLThreads>,
|
Option<WebGLThreads>,
|
||||||
Option<(SurfaceProviders, WebGlExecutor)>,
|
Option<(SurfaceProviders, WebGlExecutor)>,
|
||||||
)
|
) {
|
||||||
where
|
let gl_type = match webrender_gl.get_type() {
|
||||||
W: WindowMethods + 'static + ?Sized,
|
|
||||||
{
|
|
||||||
// Create a `surfman` device and context.
|
|
||||||
window.make_gl_context_current();
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
let (device, context) = unsafe {
|
|
||||||
if opts::get().headless {
|
|
||||||
let (device, context) = match SWDevice::from_current_context() {
|
|
||||||
Ok(a) => a,
|
|
||||||
Err(e) => {
|
|
||||||
warn!("Failed to create software graphics context: {:?}", e);
|
|
||||||
return (None, None);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
(Device::Software(device), Context::Software(context))
|
|
||||||
} else {
|
|
||||||
let (device, context) = match HWDevice::from_current_context() {
|
|
||||||
Ok(a) => a,
|
|
||||||
Err(e) => {
|
|
||||||
warn!("Failed to create hardware graphics context: {:?}", e);
|
|
||||||
return (None, None);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
(Device::Hardware(device), Context::Hardware(context))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
let (device, context) = match unsafe { Device::from_current_context() } {
|
|
||||||
Ok(a) => a,
|
|
||||||
Err(e) => {
|
|
||||||
warn!("Failed to create graphics context: {:?}", e);
|
|
||||||
return (None, None);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let gl_type = match window.gl().get_type() {
|
|
||||||
gleam::gl::GlType::Gl => sparkle::gl::GlType::Gl,
|
gleam::gl::GlType::Gl => sparkle::gl::GlType::Gl,
|
||||||
gleam::gl::GlType::Gles => sparkle::gl::GlType::Gles,
|
gleam::gl::GlType::Gles => sparkle::gl::GlType::Gles,
|
||||||
};
|
};
|
||||||
|
@ -1091,9 +1079,8 @@ where
|
||||||
output_handler,
|
output_handler,
|
||||||
webgl_executor,
|
webgl_executor,
|
||||||
} = WebGLComm::new(
|
} = WebGLComm::new(
|
||||||
device,
|
webrender_surfman,
|
||||||
context,
|
webrender_gl,
|
||||||
window.gl(),
|
|
||||||
webrender_api_sender,
|
webrender_api_sender,
|
||||||
external_images,
|
external_images,
|
||||||
gl_type,
|
gl_type,
|
||||||
|
|
17
components/webrender_surfman/Cargo.toml
Normal file
17
components/webrender_surfman/Cargo.toml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "webrender_surfman"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = ["The Servo Project Developers"]
|
||||||
|
license = "MPL-2.0"
|
||||||
|
edition = "2018"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "webrender_surfman"
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
euclid = "0.20"
|
||||||
|
surfman = "0.2"
|
||||||
|
surfman-chains = "0.3"
|
||||||
|
|
213
components/webrender_surfman/lib.rs
Normal file
213
components/webrender_surfman/lib.rs
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#![deny(unsafe_code)]
|
||||||
|
|
||||||
|
use euclid::default::Size2D;
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::ffi::c_void;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use surfman::Adapter;
|
||||||
|
use surfman::Connection;
|
||||||
|
use surfman::Context;
|
||||||
|
use surfman::ContextAttributeFlags;
|
||||||
|
use surfman::ContextAttributes;
|
||||||
|
use surfman::Device;
|
||||||
|
use surfman::Error;
|
||||||
|
use surfman::GLApi;
|
||||||
|
use surfman::GLVersion;
|
||||||
|
use surfman::NativeContext;
|
||||||
|
use surfman::NativeDevice;
|
||||||
|
use surfman::NativeWidget;
|
||||||
|
use surfman::Surface;
|
||||||
|
use surfman::SurfaceAccess;
|
||||||
|
use surfman::SurfaceInfo;
|
||||||
|
use surfman::SurfaceTexture;
|
||||||
|
use surfman::SurfaceType;
|
||||||
|
use surfman_chains::SurfmanProvider;
|
||||||
|
use surfman_chains::SwapChain;
|
||||||
|
|
||||||
|
/// A bridge between webrender and surfman
|
||||||
|
// TODO: move this into a different crate so that script doesn't depend on surfman
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct WebrenderSurfman(Rc<WebrenderSurfmanData>);
|
||||||
|
|
||||||
|
struct WebrenderSurfmanData {
|
||||||
|
device: RefCell<Device>,
|
||||||
|
context: RefCell<Context>,
|
||||||
|
// We either render to a swap buffer or to a native widget
|
||||||
|
swap_chain: Option<SwapChain<Device>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for WebrenderSurfmanData {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let ref mut device = self.device.borrow_mut();
|
||||||
|
let ref mut context = self.context.borrow_mut();
|
||||||
|
if let Some(ref swap_chain) = self.swap_chain {
|
||||||
|
let _ = swap_chain.destroy(device, context);
|
||||||
|
}
|
||||||
|
let _ = device.destroy_context(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WebrenderSurfman {
|
||||||
|
pub fn create(
|
||||||
|
connection: &Connection,
|
||||||
|
adapter: &Adapter,
|
||||||
|
surface_type: SurfaceType<NativeWidget>,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let mut device = connection.create_device(&adapter)?;
|
||||||
|
let flags = ContextAttributeFlags::ALPHA |
|
||||||
|
ContextAttributeFlags::DEPTH |
|
||||||
|
ContextAttributeFlags::STENCIL;
|
||||||
|
let version = match connection.gl_api() {
|
||||||
|
GLApi::GLES => GLVersion { major: 3, minor: 0 },
|
||||||
|
GLApi::GL => GLVersion { major: 3, minor: 2 },
|
||||||
|
};
|
||||||
|
let context_attributes = ContextAttributes { flags, version };
|
||||||
|
let context_descriptor = device.create_context_descriptor(&context_attributes)?;
|
||||||
|
let mut context = device.create_context(&context_descriptor)?;
|
||||||
|
let surface_access = SurfaceAccess::GPUOnly;
|
||||||
|
let headless = match surface_type {
|
||||||
|
SurfaceType::Widget { .. } => false,
|
||||||
|
SurfaceType::Generic { .. } => true,
|
||||||
|
};
|
||||||
|
let surface = device.create_surface(&context, surface_access, surface_type)?;
|
||||||
|
device
|
||||||
|
.bind_surface_to_context(&mut context, surface)
|
||||||
|
.map_err(|(err, mut surface)| {
|
||||||
|
let _ = device.destroy_surface(&mut context, &mut surface);
|
||||||
|
err
|
||||||
|
})?;
|
||||||
|
let swap_chain = if headless {
|
||||||
|
let surface_provider = Box::new(SurfmanProvider::new(surface_access));
|
||||||
|
Some(SwapChain::create_attached(
|
||||||
|
&mut device,
|
||||||
|
&mut context,
|
||||||
|
surface_provider,
|
||||||
|
)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let device = RefCell::new(device);
|
||||||
|
let context = RefCell::new(context);
|
||||||
|
let data = WebrenderSurfmanData {
|
||||||
|
device,
|
||||||
|
context,
|
||||||
|
swap_chain,
|
||||||
|
};
|
||||||
|
Ok(WebrenderSurfman(Rc::new(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_surface_texture(
|
||||||
|
&self,
|
||||||
|
surface: Surface,
|
||||||
|
) -> Result<SurfaceTexture, (Error, Surface)> {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
let ref mut context = self.0.context.borrow_mut();
|
||||||
|
device.create_surface_texture(context, surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destroy_surface_texture(
|
||||||
|
&self,
|
||||||
|
surface_texture: SurfaceTexture,
|
||||||
|
) -> Result<Surface, (Error, SurfaceTexture)> {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
let ref mut context = self.0.context.borrow_mut();
|
||||||
|
device.destroy_surface_texture(context, surface_texture)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_gl_context_current(&self) -> Result<(), Error> {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
let ref context = self.0.context.borrow();
|
||||||
|
device.make_context_current(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn swap_chain(&self) -> Result<&SwapChain<Device>, Error> {
|
||||||
|
self.0.swap_chain.as_ref().ok_or(Error::WidgetAttached)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resize(&self, size: Size2D<i32>) -> Result<(), Error> {
|
||||||
|
let ref mut device = self.0.device.borrow_mut();
|
||||||
|
let ref mut context = self.0.context.borrow_mut();
|
||||||
|
if let Some(swap_chain) = self.0.swap_chain.as_ref() {
|
||||||
|
return swap_chain.resize(device, context, size);
|
||||||
|
}
|
||||||
|
let mut surface = device.unbind_surface_from_context(context)?.unwrap();
|
||||||
|
device.resize_surface(context, &mut surface, size)?;
|
||||||
|
device
|
||||||
|
.bind_surface_to_context(context, surface)
|
||||||
|
.map_err(|(err, mut surface)| {
|
||||||
|
let _ = device.destroy_surface(context, &mut surface);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn present(&self) -> Result<(), Error> {
|
||||||
|
let ref mut device = self.0.device.borrow_mut();
|
||||||
|
let ref mut context = self.0.context.borrow_mut();
|
||||||
|
if let Some(ref swap_chain) = self.0.swap_chain {
|
||||||
|
return swap_chain.swap_buffers(device, context);
|
||||||
|
}
|
||||||
|
let mut surface = device.unbind_surface_from_context(context)?.unwrap();
|
||||||
|
device.present_surface(context, &mut surface)?;
|
||||||
|
device
|
||||||
|
.bind_surface_to_context(context, surface)
|
||||||
|
.map_err(|(err, mut surface)| {
|
||||||
|
let _ = device.destroy_surface(context, &mut surface);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connection(&self) -> Connection {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
device.connection()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn adapter(&self) -> Adapter {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
device.adapter()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn native_context(&self) -> NativeContext {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
let ref context = self.0.context.borrow();
|
||||||
|
device.native_context(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn native_device(&self) -> NativeDevice {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
device.native_device()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn context_attributes(&self) -> ContextAttributes {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
let ref context = self.0.context.borrow();
|
||||||
|
let ref descriptor = device.context_descriptor(context);
|
||||||
|
device.context_descriptor_attributes(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn context_surface_info(&self) -> Result<Option<SurfaceInfo>, Error> {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
let ref context = self.0.context.borrow();
|
||||||
|
device.context_surface_info(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn surface_info(&self, surface: &Surface) -> SurfaceInfo {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
device.surface_info(surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn surface_texture_object(&self, surface: &SurfaceTexture) -> u32 {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
device.surface_texture_object(surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_proc_address(&self, name: &str) -> *const c_void {
|
||||||
|
let ref device = self.0.device.borrow();
|
||||||
|
let ref context = self.0.context.borrow();
|
||||||
|
device.get_proc_address(context, name)
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,5 +12,6 @@ path = "lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
euclid = "0.20"
|
euclid = "0.20"
|
||||||
|
servo_geometry = {path = "../geometry"}
|
||||||
webrender_api = {git = "https://github.com/servo/webrender"}
|
webrender_api = {git = "https://github.com/servo/webrender"}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
|
|
||||||
use euclid::default::Size2D;
|
use euclid::default::Size2D;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use webrender_api::units::TexelRect;
|
use webrender_api::units::TexelRect;
|
||||||
|
|
||||||
/// This trait is used as a bridge between the different GL clients
|
/// This trait is used as a bridge between the different GL clients
|
||||||
|
|
|
@ -492,9 +492,7 @@ def macos_release_build_with_debug_assertions(priority=None):
|
||||||
"./etc/ci/lockfile_changed.sh",
|
"./etc/ci/lockfile_changed.sh",
|
||||||
"tar -czf target.tar.gz" +
|
"tar -czf target.tar.gz" +
|
||||||
" target/release/servo" +
|
" target/release/servo" +
|
||||||
" target/release/build/osmesa-src-*/output" +
|
" resources",
|
||||||
" target/release/build/osmesa-src-*/out/src/gallium/targets/osmesa/.libs" +
|
|
||||||
" target/release/build/osmesa-src-*/out/src/mapi/shared-glapi/.libs",
|
|
||||||
]))
|
]))
|
||||||
.with_artifacts("repo/target.tar.gz")
|
.with_artifacts("repo/target.tar.gz")
|
||||||
.find_or_create("build.macos_x64_release_w_assertions." + CONFIG.tree_hash())
|
.find_or_create("build.macos_x64_release_w_assertions." + CONFIG.tree_hash())
|
||||||
|
@ -522,8 +520,7 @@ def linux_release_build_with_debug_assertions(layout_2020):
|
||||||
./etc/ci/lockfile_changed.sh
|
./etc/ci/lockfile_changed.sh
|
||||||
tar -czf /target.tar.gz \
|
tar -czf /target.tar.gz \
|
||||||
target/release/servo \
|
target/release/servo \
|
||||||
target/release/build/osmesa-src-*/output \
|
resources
|
||||||
target/release/build/osmesa-src-*/out/lib/gallium
|
|
||||||
sccache --show-stats
|
sccache --show-stats
|
||||||
""" % build_args)
|
""" % build_args)
|
||||||
.with_artifacts("/target.tar.gz")
|
.with_artifacts("/target.tar.gz")
|
||||||
|
@ -573,12 +570,17 @@ def wpt_chunks(platform, make_chunk_task, build_task, total_chunks, processes,
|
||||||
start = 1 # Skip the "extra" WPT testing, a.k.a. chunk 0
|
start = 1 # Skip the "extra" WPT testing, a.k.a. chunk 0
|
||||||
name_prefix = "Layout 2020 "
|
name_prefix = "Layout 2020 "
|
||||||
job_id_prefix = "2020-"
|
job_id_prefix = "2020-"
|
||||||
args = "--layout-2020"
|
args = ["--layout-2020"]
|
||||||
else:
|
else:
|
||||||
start = 0
|
start = 0
|
||||||
name_prefix = ""
|
name_prefix = ""
|
||||||
job_id_prefix = ""
|
job_id_prefix = ""
|
||||||
args = ""
|
args = []
|
||||||
|
|
||||||
|
# Our Mac CI runs on machines with an Intel 4000 GPU, so need to work around
|
||||||
|
# https://github.com/servo/webrender/wiki/Driver-issues#bug-1570736---texture-swizzling-affects-wrap-modes-on-some-intel-gpus
|
||||||
|
if platform == "macOS x64":
|
||||||
|
args += ["--pref gfx.texture-swizzling.enabled=false"]
|
||||||
|
|
||||||
if chunks == "all":
|
if chunks == "all":
|
||||||
chunks = range(start, total_chunks + 1)
|
chunks = range(start, total_chunks + 1)
|
||||||
|
@ -604,7 +606,7 @@ def wpt_chunks(platform, make_chunk_task, build_task, total_chunks, processes,
|
||||||
TOTAL_CHUNKS=str(total_chunks),
|
TOTAL_CHUNKS=str(total_chunks),
|
||||||
THIS_CHUNK=str(this_chunk),
|
THIS_CHUNK=str(this_chunk),
|
||||||
PROCESSES=str(processes),
|
PROCESSES=str(processes),
|
||||||
WPT_ARGS=args,
|
WPT_ARGS=" ".join(args),
|
||||||
GST_DEBUG="3",
|
GST_DEBUG="3",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -613,7 +615,6 @@ def wpt_chunks(platform, make_chunk_task, build_task, total_chunks, processes,
|
||||||
# https://github.com/servo/servo/issues/22438
|
# https://github.com/servo/servo/issues/22438
|
||||||
if this_chunk == 0:
|
if this_chunk == 0:
|
||||||
task.with_script("""
|
task.with_script("""
|
||||||
./mach test-wpt-failure
|
|
||||||
time python2 ./mach test-wpt --release --binary-arg=--multiprocess \
|
time python2 ./mach test-wpt --release --binary-arg=--multiprocess \
|
||||||
--processes $PROCESSES \
|
--processes $PROCESSES \
|
||||||
--log-raw test-wpt-mp.log \
|
--log-raw test-wpt-mp.log \
|
||||||
|
|
|
@ -53,7 +53,6 @@ clipboard = "0.5"
|
||||||
euclid = "0.20"
|
euclid = "0.20"
|
||||||
getopts = "0.2.11"
|
getopts = "0.2.11"
|
||||||
gleam = "0.9"
|
gleam = "0.9"
|
||||||
glutin = "0.21.0"
|
|
||||||
keyboard-types = "0.4.3"
|
keyboard-types = "0.4.3"
|
||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
libservo = {path = "../../components/servo"}
|
libservo = {path = "../../components/servo"}
|
||||||
|
@ -61,19 +60,17 @@ libc = "0.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
servo-media = {git = "https://github.com/servo/media"}
|
servo-media = {git = "https://github.com/servo/media"}
|
||||||
shellwords = "1.0.0"
|
shellwords = "1.0.0"
|
||||||
|
surfman = { version = "0.2", features = ["sm-winit", "sm-x11"] }
|
||||||
tinyfiledialogs = "3.0"
|
tinyfiledialogs = "3.0"
|
||||||
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
|
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
|
||||||
webxr = { git = "https://github.com/servo/webxr", features = ["ipc", "glwindow", "headless"] }
|
webxr = { git = "https://github.com/servo/webxr", features = ["ipc", "glwindow", "headless"] }
|
||||||
|
winit = "0.19"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies]
|
[target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies]
|
||||||
image = "0.23"
|
image = "0.23"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
|
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
|
||||||
osmesa-sys = "0.1.2"
|
|
||||||
sig = "1.0"
|
sig = "1.0"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["wingdi", "winuser", "winnt", "winbase", "processenv", "namedpipeapi", "ntdef", "minwindef", "handleapi", "debugapi"] }
|
winapi = { version = "0.3", features = ["wingdi", "winuser", "winnt", "winbase", "processenv", "namedpipeapi", "ntdef", "minwindef", "handleapi", "debugapi"] }
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "macos", all(target_arch = "x86_64", target_os = "linux")))'.dependencies]
|
|
||||||
osmesa-src = {git = "https://github.com/servo/osmesa-src"}
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::embedder::EmbedderCallbacks;
|
||||||
use crate::events_loop::EventsLoop;
|
use crate::events_loop::EventsLoop;
|
||||||
use crate::window_trait::WindowPortsMethods;
|
use crate::window_trait::WindowPortsMethods;
|
||||||
use crate::{headed_window, headless_window};
|
use crate::{headed_window, headless_window};
|
||||||
use glutin::WindowId;
|
use winit::WindowId;
|
||||||
use servo::compositing::windowing::WindowEvent;
|
use servo::compositing::windowing::WindowEvent;
|
||||||
use servo::config::opts::{self, parse_url_or_filename};
|
use servo::config::opts::{self, parse_url_or_filename};
|
||||||
use servo::servo_config::pref;
|
use servo::servo_config::pref;
|
||||||
|
@ -20,6 +20,7 @@ use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use webxr::glwindow::GlWindowDiscovery;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
pub static WINDOWS: RefCell<HashMap<WindowId, Rc<dyn WindowPortsMethods>>> = RefCell::new(HashMap::new());
|
pub static WINDOWS: RefCell<HashMap<WindowId, Rc<dyn WindowPortsMethods>>> = RefCell::new(HashMap::new());
|
||||||
|
@ -35,9 +36,6 @@ pub struct App {
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn run(
|
pub fn run(
|
||||||
angle: bool,
|
|
||||||
enable_vsync: bool,
|
|
||||||
use_msaa: bool,
|
|
||||||
no_native_titlebar: bool,
|
no_native_titlebar: bool,
|
||||||
device_pixels_per_px: Option<f32>,
|
device_pixels_per_px: Option<f32>,
|
||||||
user_agent: Option<String>,
|
user_agent: Option<String>,
|
||||||
|
@ -50,21 +48,31 @@ impl App {
|
||||||
} else {
|
} else {
|
||||||
Rc::new(headed_window::Window::new(
|
Rc::new(headed_window::Window::new(
|
||||||
opts::get().initial_window_size,
|
opts::get().initial_window_size,
|
||||||
None,
|
|
||||||
events_loop.clone(),
|
events_loop.clone(),
|
||||||
angle,
|
|
||||||
enable_vsync,
|
|
||||||
use_msaa,
|
|
||||||
no_native_titlebar,
|
no_native_titlebar,
|
||||||
device_pixels_per_px,
|
device_pixels_per_px,
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let xr_discovery = if pref!(dom.webxr.glwindow) {
|
||||||
|
let window = window.clone();
|
||||||
|
let surfman = window.webrender_surfman();
|
||||||
|
let events_loop = events_loop.clone();
|
||||||
|
let factory = Box::new(move || Ok(window.new_glwindow(&*events_loop.borrow())));
|
||||||
|
Some(GlWindowDiscovery::new(
|
||||||
|
surfman.connection(),
|
||||||
|
surfman.adapter(),
|
||||||
|
surfman.context_attributes(),
|
||||||
|
factory,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
// Implements embedder methods, used by libservo and constellation.
|
// Implements embedder methods, used by libservo and constellation.
|
||||||
let embedder = Box::new(EmbedderCallbacks::new(
|
let embedder = Box::new(EmbedderCallbacks::new(
|
||||||
window.clone(),
|
|
||||||
events_loop.clone(),
|
events_loop.clone(),
|
||||||
window.gl(),
|
xr_discovery,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Handle browser state.
|
// Handle browser state.
|
||||||
|
@ -93,36 +101,36 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function decides whether the event should be handled during `run_forever`.
|
// This function decides whether the event should be handled during `run_forever`.
|
||||||
fn winit_event_to_servo_event(&self, event: glutin::Event) -> glutin::ControlFlow {
|
fn winit_event_to_servo_event(&self, event: winit::Event) -> winit::ControlFlow {
|
||||||
match event {
|
match event {
|
||||||
// App level events
|
// App level events
|
||||||
glutin::Event::Suspended(suspended) => {
|
winit::Event::Suspended(suspended) => {
|
||||||
self.suspended.set(suspended);
|
self.suspended.set(suspended);
|
||||||
if !suspended {
|
if !suspended {
|
||||||
self.event_queue.borrow_mut().push(WindowEvent::Idle);
|
self.event_queue.borrow_mut().push(WindowEvent::Idle);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
glutin::Event::Awakened => {
|
winit::Event::Awakened => {
|
||||||
self.event_queue.borrow_mut().push(WindowEvent::Idle);
|
self.event_queue.borrow_mut().push(WindowEvent::Idle);
|
||||||
},
|
},
|
||||||
glutin::Event::DeviceEvent { .. } => {},
|
winit::Event::DeviceEvent { .. } => {},
|
||||||
|
|
||||||
// Window level events
|
// Window level events
|
||||||
glutin::Event::WindowEvent {
|
winit::Event::WindowEvent {
|
||||||
window_id, event, ..
|
window_id, event, ..
|
||||||
} => {
|
} => {
|
||||||
return WINDOWS.with(|windows| {
|
return WINDOWS.with(|windows| {
|
||||||
match windows.borrow().get(&window_id) {
|
match windows.borrow().get(&window_id) {
|
||||||
None => {
|
None => {
|
||||||
warn!("Got an event from unknown window");
|
warn!("Got an event from unknown window");
|
||||||
glutin::ControlFlow::Break
|
winit::ControlFlow::Break
|
||||||
},
|
},
|
||||||
Some(window) => {
|
Some(window) => {
|
||||||
// Resize events need to be handled during run_forever
|
// Resize events need to be handled during run_forever
|
||||||
let cont = if let glutin::WindowEvent::Resized(_) = event {
|
let cont = if let winit::WindowEvent::Resized(_) = event {
|
||||||
glutin::ControlFlow::Continue
|
winit::ControlFlow::Continue
|
||||||
} else {
|
} else {
|
||||||
glutin::ControlFlow::Break
|
winit::ControlFlow::Break
|
||||||
};
|
};
|
||||||
window.winit_event_to_servo_event(event);
|
window.winit_event_to_servo_event(event);
|
||||||
return cont;
|
return cont;
|
||||||
|
@ -131,7 +139,7 @@ impl App {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
glutin::ControlFlow::Break
|
winit::ControlFlow::Break
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_loop(self) {
|
fn run_loop(self) {
|
||||||
|
@ -146,7 +154,7 @@ impl App {
|
||||||
// If there's no animations running then we block on the window event loop.
|
// If there's no animations running then we block on the window event loop.
|
||||||
self.events_loop.borrow_mut().run_forever(|e| {
|
self.events_loop.borrow_mut().run_forever(|e| {
|
||||||
let cont = self.winit_event_to_servo_event(e);
|
let cont = self.winit_event_to_servo_event(e);
|
||||||
if cont == glutin::ControlFlow::Continue {
|
if cont == winit::ControlFlow::Continue {
|
||||||
// Note we need to be careful to make sure that any events
|
// Note we need to be careful to make sure that any events
|
||||||
// that are handled during run_forever aren't re-entrant,
|
// that are handled during run_forever aren't re-entrant,
|
||||||
// since we are handling them while holding onto a mutable borrow
|
// since we are handling them while holding onto a mutable borrow
|
||||||
|
@ -237,14 +245,3 @@ pub fn register_window(window: Rc<dyn WindowPortsMethods>) {
|
||||||
w.borrow_mut().insert(window.id(), window);
|
w.borrow_mut().insert(window.id(), window);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gl_version(angle: bool) -> glutin::GlRequest {
|
|
||||||
if angle {
|
|
||||||
glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0))
|
|
||||||
} else {
|
|
||||||
glutin::GlRequest::GlThenGles {
|
|
||||||
opengl_version: (3, 2),
|
|
||||||
opengles_version: (3, 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,172 +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 https://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
use glutin::os::ContextTraitExt;
|
|
||||||
use glutin::{ContextBuilder, CreationError, EventsLoop, NotCurrent, PossiblyCurrent, WindowedContext, WindowBuilder};
|
|
||||||
use servo_media::player::context::GlContext as RawContext;
|
|
||||||
use std::os::raw;
|
|
||||||
|
|
||||||
pub enum GlContext {
|
|
||||||
Current(WindowedContext<PossiblyCurrent>),
|
|
||||||
NotCurrent(WindowedContext<NotCurrent>),
|
|
||||||
// Used a temporary value as we switch from Current to NotCurrent.
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GlContext {
|
|
||||||
pub fn window(&self) -> &glutin::Window {
|
|
||||||
match self {
|
|
||||||
GlContext::Current(c) => c.window(),
|
|
||||||
GlContext::NotCurrent(c) => c.window(),
|
|
||||||
GlContext::None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn resize(&mut self, size: glutin::dpi::PhysicalSize) {
|
|
||||||
if let GlContext::NotCurrent(_) = self {
|
|
||||||
self.make_current();
|
|
||||||
}
|
|
||||||
match self {
|
|
||||||
GlContext::Current(c) => c.resize(size),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn make_current(&mut self) {
|
|
||||||
*self = match std::mem::replace(self, GlContext::None) {
|
|
||||||
GlContext::Current(c) => {
|
|
||||||
warn!("Making an already current context current");
|
|
||||||
// Servo thinks that that this window is current,
|
|
||||||
// but it might be wrong, since other code may have
|
|
||||||
// changed the current GL context. Just to be on
|
|
||||||
// the safe side, we make it current anyway.
|
|
||||||
let c = unsafe {
|
|
||||||
c.make_current().expect("Couldn't make window current")
|
|
||||||
};
|
|
||||||
GlContext::Current(c)
|
|
||||||
},
|
|
||||||
GlContext::NotCurrent(c) => {
|
|
||||||
let c = unsafe {
|
|
||||||
c.make_current().expect("Couldn't make window current")
|
|
||||||
};
|
|
||||||
GlContext::Current(c)
|
|
||||||
}
|
|
||||||
GlContext::None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn make_not_current(&mut self) {
|
|
||||||
*self = match std::mem::replace(self, GlContext::None) {
|
|
||||||
GlContext::Current(c) => {
|
|
||||||
let c = unsafe {
|
|
||||||
c.make_not_current().expect("Couldn't make window not current")
|
|
||||||
};
|
|
||||||
GlContext::NotCurrent(c)
|
|
||||||
},
|
|
||||||
GlContext::NotCurrent(c) => {
|
|
||||||
warn!("Making an already not current context not current");
|
|
||||||
GlContext::NotCurrent(c)
|
|
||||||
}
|
|
||||||
GlContext::None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn swap_buffers(&self) {
|
|
||||||
match self {
|
|
||||||
GlContext::Current(c) => {
|
|
||||||
if let Err(err) = c.swap_buffers() {
|
|
||||||
warn!("Failed to swap window buffers ({}).", err);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
GlContext::NotCurrent(_) => {
|
|
||||||
error!("Context is not current. Forgot to call prepare_for_composite?");
|
|
||||||
},
|
|
||||||
GlContext::None => unreachable!(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#[allow(unreachable_code, unused_variables)]
|
|
||||||
pub fn raw_context(&self) -> RawContext {
|
|
||||||
match self {
|
|
||||||
GlContext::Current(c) => {
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
{
|
|
||||||
use glutin::os::unix::RawHandle;
|
|
||||||
|
|
||||||
let raw_handle = unsafe { c.raw_handle() };
|
|
||||||
return match raw_handle {
|
|
||||||
RawHandle::Egl(handle) => RawContext::Egl(handle as usize),
|
|
||||||
RawHandle::Glx(handle) => RawContext::Glx(handle as usize),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
{
|
|
||||||
use glutin::os::windows::RawHandle;
|
|
||||||
|
|
||||||
let raw_handle = unsafe { c.raw_handle() };
|
|
||||||
return match raw_handle {
|
|
||||||
RawHandle::Egl(handle) => RawContext::Egl(handle as usize),
|
|
||||||
// @TODO(victor): RawContext::Wgl in servo-media
|
|
||||||
RawHandle::Wgl(_) => unimplemented!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @TODO(victor): https://github.com/rust-windowing/glutin/pull/1221
|
|
||||||
// https://github.com/servo/media/pull/315
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
return unimplemented!();
|
|
||||||
|
|
||||||
#[cfg(not(any(
|
|
||||||
target_os = "linux",
|
|
||||||
target_os = "windows",
|
|
||||||
target_os = "macos",
|
|
||||||
)))]
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
GlContext::NotCurrent(_) => {
|
|
||||||
error!("Context is not current.");
|
|
||||||
RawContext::Unknown
|
|
||||||
}
|
|
||||||
GlContext::None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_window<T>(
|
|
||||||
&self,
|
|
||||||
cb: ContextBuilder<T>,
|
|
||||||
wb: WindowBuilder,
|
|
||||||
el: &EventsLoop
|
|
||||||
) -> Result<WindowedContext<NotCurrent>, CreationError>
|
|
||||||
where
|
|
||||||
T: glutin::ContextCurrentState,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
GlContext::Current(ref c) => {
|
|
||||||
cb.with_shared_lists(c).build_windowed(wb, el)
|
|
||||||
},
|
|
||||||
GlContext::NotCurrent(ref c) => {
|
|
||||||
cb.with_shared_lists(c).build_windowed(wb, el)
|
|
||||||
},
|
|
||||||
GlContext::None => {
|
|
||||||
cb.build_windowed(wb, el)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn egl_display(&self) -> Option<*const raw::c_void> {
|
|
||||||
match self {
|
|
||||||
GlContext::Current(c) => unsafe { c.get_egl_display() },
|
|
||||||
GlContext::NotCurrent(_) => {
|
|
||||||
error!("Context is not current.");
|
|
||||||
None
|
|
||||||
},
|
|
||||||
GlContext::None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_api(&self) -> glutin::Api {
|
|
||||||
match self {
|
|
||||||
GlContext::Current(c) => c.get_api(),
|
|
||||||
GlContext::NotCurrent(c) => c.get_api(),
|
|
||||||
GlContext::None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,31 +5,27 @@
|
||||||
//! Implements the global methods required by Servo (not window/gl/compositor related).
|
//! Implements the global methods required by Servo (not window/gl/compositor related).
|
||||||
|
|
||||||
use crate::events_loop::EventsLoop;
|
use crate::events_loop::EventsLoop;
|
||||||
use crate::window_trait::WindowPortsMethods;
|
|
||||||
use gleam::gl;
|
|
||||||
use servo::canvas::{SurfaceProviders, WebGlExecutor};
|
use servo::canvas::{SurfaceProviders, WebGlExecutor};
|
||||||
use servo::compositing::windowing::EmbedderMethods;
|
use servo::compositing::windowing::EmbedderMethods;
|
||||||
use servo::embedder_traits::{EmbedderProxy, EventLoopWaker};
|
use servo::embedder_traits::{EmbedderProxy, EventLoopWaker};
|
||||||
use servo::servo_config::{opts, pref};
|
use servo::servo_config::pref;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use webxr::glwindow::GlWindowDiscovery;
|
||||||
|
|
||||||
pub struct EmbedderCallbacks {
|
pub struct EmbedderCallbacks {
|
||||||
window: Rc<dyn WindowPortsMethods>,
|
|
||||||
events_loop: Rc<RefCell<EventsLoop>>,
|
events_loop: Rc<RefCell<EventsLoop>>,
|
||||||
gl: Rc<dyn gl::Gl>,
|
xr_discovery: Option<GlWindowDiscovery>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmbedderCallbacks {
|
impl EmbedderCallbacks {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
window: Rc<dyn WindowPortsMethods>,
|
|
||||||
events_loop: Rc<RefCell<EventsLoop>>,
|
events_loop: Rc<RefCell<EventsLoop>>,
|
||||||
gl: Rc<dyn gl::Gl>,
|
xr_discovery: Option<GlWindowDiscovery>,
|
||||||
) -> EmbedderCallbacks {
|
) -> EmbedderCallbacks {
|
||||||
EmbedderCallbacks {
|
EmbedderCallbacks {
|
||||||
window,
|
|
||||||
events_loop,
|
events_loop,
|
||||||
gl,
|
xr_discovery,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,13 +44,8 @@ impl EmbedderMethods for EmbedderCallbacks {
|
||||||
) {
|
) {
|
||||||
if pref!(dom.webxr.test) {
|
if pref!(dom.webxr.test) {
|
||||||
xr.register_mock(webxr::headless::HeadlessMockDiscovery::new());
|
xr.register_mock(webxr::headless::HeadlessMockDiscovery::new());
|
||||||
} else if !opts::get().headless && pref!(dom.webxr.glwindow) {
|
} else if let Some(xr_discovery) = self.xr_discovery.take() {
|
||||||
warn!("Creating test XR device");
|
xr.register(xr_discovery);
|
||||||
let gl = self.gl.clone();
|
|
||||||
let window = self.window.clone();
|
|
||||||
let factory = Box::new(move || window.new_window());
|
|
||||||
let discovery = webxr::glwindow::GlWindowDiscovery::new(gl, factory);
|
|
||||||
xr.register(discovery);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! An event loop implementation that works in headless mode.
|
//! An event loop implementation that works in headless mode.
|
||||||
|
|
||||||
|
|
||||||
use glutin;
|
use winit;
|
||||||
use servo::embedder_traits::EventLoopWaker;
|
use servo::embedder_traits::EventLoopWaker;
|
||||||
use std::sync::{Arc, Condvar, Mutex};
|
use std::sync::{Arc, Condvar, Mutex};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -14,8 +14,8 @@ use std::time;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
enum EventLoop {
|
enum EventLoop {
|
||||||
/// A real Glutin windowing event loop.
|
/// A real Winit windowing event loop.
|
||||||
Glutin(Option<glutin::EventsLoop>),
|
Winit(Option<winit::EventsLoop>),
|
||||||
/// A fake event loop which contains a signalling flag used to ensure
|
/// A fake event loop which contains a signalling flag used to ensure
|
||||||
/// that pending events get processed in a timely fashion, and a condition
|
/// that pending events get processed in a timely fashion, and a condition
|
||||||
/// variable to allow waiting on that flag changing state.
|
/// variable to allow waiting on that flag changing state.
|
||||||
|
@ -29,14 +29,14 @@ impl EventsLoop {
|
||||||
// but on Linux, the event loop requires a X11 server.
|
// but on Linux, the event loop requires a X11 server.
|
||||||
#[cfg(not(target_os = "linux"))]
|
#[cfg(not(target_os = "linux"))]
|
||||||
pub fn new(_headless: bool) -> Rc<RefCell<EventsLoop>> {
|
pub fn new(_headless: bool) -> Rc<RefCell<EventsLoop>> {
|
||||||
Rc::new(RefCell::new(EventsLoop(EventLoop::Glutin(Some(glutin::EventsLoop::new())))))
|
Rc::new(RefCell::new(EventsLoop(EventLoop::Winit(Some(winit::EventsLoop::new())))))
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub fn new(headless: bool) -> Rc<RefCell<EventsLoop>> {
|
pub fn new(headless: bool) -> Rc<RefCell<EventsLoop>> {
|
||||||
let events_loop = if headless {
|
let events_loop = if headless {
|
||||||
EventLoop::Headless(Arc::new((Mutex::new(false), Condvar::new())))
|
EventLoop::Headless(Arc::new((Mutex::new(false), Condvar::new())))
|
||||||
} else {
|
} else {
|
||||||
EventLoop::Glutin(Some(glutin::EventsLoop::new()))
|
EventLoop::Winit(Some(winit::EventsLoop::new()))
|
||||||
};
|
};
|
||||||
Rc::new(RefCell::new(EventsLoop(events_loop)))
|
Rc::new(RefCell::new(EventsLoop(events_loop)))
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ impl EventsLoop {
|
||||||
impl EventsLoop {
|
impl EventsLoop {
|
||||||
pub fn create_event_loop_waker(&self) -> Box<dyn EventLoopWaker> {
|
pub fn create_event_loop_waker(&self) -> Box<dyn EventLoopWaker> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
EventLoop::Glutin(ref events_loop) => {
|
EventLoop::Winit(ref events_loop) => {
|
||||||
let events_loop = events_loop
|
let events_loop = events_loop
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("Can't create waker for unavailable event loop.");
|
.expect("Can't create waker for unavailable event loop.");
|
||||||
|
@ -55,17 +55,18 @@ impl EventsLoop {
|
||||||
Box::new(HeadlessEventLoopWaker(data.clone())),
|
Box::new(HeadlessEventLoopWaker(data.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn as_winit(&self) -> &glutin::EventsLoop {
|
pub fn as_winit(&self) -> &winit::EventsLoop {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
EventLoop::Glutin(Some(ref event_loop)) => event_loop,
|
EventLoop::Winit(Some(ref event_loop)) => event_loop,
|
||||||
EventLoop::Glutin(None) | EventLoop::Headless(..) =>
|
EventLoop::Winit(None) | EventLoop::Headless(..) =>
|
||||||
panic!("Can't access winit event loop while using the fake headless event loop"),
|
panic!("Can't access winit event loop while using the fake headless event loop"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn poll_events<F>(&mut self, callback: F) where F: FnMut(glutin::Event) {
|
|
||||||
|
pub fn poll_events<F>(&mut self, callback: F) where F: FnMut(winit::Event) {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
EventLoop::Glutin(Some(ref mut events_loop)) => events_loop.poll_events(callback),
|
EventLoop::Winit(Some(ref mut events_loop)) => events_loop.poll_events(callback),
|
||||||
EventLoop::Glutin(None) => (),
|
EventLoop::Winit(None) => (),
|
||||||
EventLoop::Headless(ref data) => {
|
EventLoop::Headless(ref data) => {
|
||||||
// This is subtle - the use of the event loop in App::run_loop
|
// This is subtle - the use of the event loop in App::run_loop
|
||||||
// optionally calls run_forever, then always calls poll_events.
|
// optionally calls run_forever, then always calls poll_events.
|
||||||
|
@ -80,9 +81,9 @@ impl EventsLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn run_forever<F>(&mut self, mut callback: F) where F: FnMut(glutin::Event) -> glutin::ControlFlow {
|
pub fn run_forever<F>(&mut self, mut callback: F) where F: FnMut(winit::Event) -> winit::ControlFlow {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
EventLoop::Glutin(ref mut events_loop) => {
|
EventLoop::Winit(ref mut events_loop) => {
|
||||||
let events_loop = events_loop
|
let events_loop = events_loop
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.expect("Can't run an unavailable event loop.");
|
.expect("Can't run an unavailable event loop.");
|
||||||
|
@ -92,7 +93,7 @@ impl EventsLoop {
|
||||||
let &(ref flag, ref condvar) = &**data;
|
let &(ref flag, ref condvar) = &**data;
|
||||||
while !*flag.lock().unwrap() {
|
while !*flag.lock().unwrap() {
|
||||||
self.sleep(flag, condvar);
|
self.sleep(flag, condvar);
|
||||||
if callback(glutin::Event::Awakened) == glutin::ControlFlow::Break {
|
if callback(winit::Event::Awakened) == winit::ControlFlow::Break {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,10 +116,10 @@ impl EventsLoop {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HeadedEventLoopWaker {
|
struct HeadedEventLoopWaker {
|
||||||
proxy: Arc<glutin::EventsLoopProxy>,
|
proxy: Arc<winit::EventsLoopProxy>,
|
||||||
}
|
}
|
||||||
impl HeadedEventLoopWaker {
|
impl HeadedEventLoopWaker {
|
||||||
fn new(events_loop: &glutin::EventsLoop) -> HeadedEventLoopWaker {
|
fn new(events_loop: &winit::EventsLoop) -> HeadedEventLoopWaker {
|
||||||
let proxy = Arc::new(events_loop.create_proxy());
|
let proxy = Arc::new(events_loop.create_proxy());
|
||||||
HeadedEventLoopWaker { proxy }
|
HeadedEventLoopWaker { proxy }
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,27 +2,21 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
//! A glutin window implementation.
|
//! A winit window implementation.
|
||||||
|
|
||||||
use crate::app;
|
|
||||||
use crate::context::GlContext;
|
|
||||||
use crate::events_loop::EventsLoop;
|
use crate::events_loop::EventsLoop;
|
||||||
use crate::keyutils::keyboard_event_from_winit;
|
use crate::keyutils::keyboard_event_from_winit;
|
||||||
use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT};
|
use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT};
|
||||||
use euclid::{
|
use euclid::{
|
||||||
Angle, default::Size2D as UntypedSize2D, Point2D, Rotation3D, Scale, Size2D, UnknownUnit,
|
Angle, Point2D, Rotation3D, Scale, Size2D, UnknownUnit,
|
||||||
Vector2D, Vector3D,
|
Vector2D, Vector3D,
|
||||||
};
|
};
|
||||||
use gleam::gl;
|
use winit::dpi::{LogicalPosition, LogicalSize, PhysicalSize};
|
||||||
use glutin::dpi::{LogicalPosition, LogicalSize, PhysicalSize};
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use glutin::os::macos::{ActivationPolicy, WindowBuilderExt};
|
use winit::os::macos::{ActivationPolicy, WindowBuilderExt};
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
use glutin::os::unix::WindowExt;
|
|
||||||
use glutin::Api;
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||||
use glutin::Icon;
|
use winit::Icon;
|
||||||
use glutin::{ElementState, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode};
|
use winit::{ElementState, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode};
|
||||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||||
use image;
|
use image;
|
||||||
use keyboard_types::{Key, KeyState, KeyboardEvent};
|
use keyboard_types::{Key, KeyState, KeyboardEvent};
|
||||||
|
@ -30,22 +24,32 @@ use servo::compositing::windowing::{AnimationState, MouseWindowEvent, WindowEven
|
||||||
use servo::compositing::windowing::{EmbedderCoordinates, WindowMethods};
|
use servo::compositing::windowing::{EmbedderCoordinates, WindowMethods};
|
||||||
use servo::embedder_traits::Cursor;
|
use servo::embedder_traits::Cursor;
|
||||||
use servo::script_traits::{TouchEventType, WheelMode, WheelDelta};
|
use servo::script_traits::{TouchEventType, WheelMode, WheelDelta};
|
||||||
use servo::servo_config::{opts, pref};
|
use servo::servo_config::opts;
|
||||||
|
use servo::servo_config::pref;
|
||||||
use servo::servo_geometry::DeviceIndependentPixel;
|
use servo::servo_geometry::DeviceIndependentPixel;
|
||||||
use servo::style_traits::DevicePixel;
|
use servo::style_traits::DevicePixel;
|
||||||
use servo::webrender_api::ScrollLocation;
|
use servo::webrender_api::ScrollLocation;
|
||||||
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||||
|
use servo::webrender_surfman::WebrenderSurfman;
|
||||||
use servo_media::player::context::{GlApi, GlContext as PlayerGLContext, NativeDisplay};
|
use servo_media::player::context::{GlApi, GlContext as PlayerGLContext, NativeDisplay};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
use surfman::platform::generic::multi::connection::NativeConnection;
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
use surfman::platform::generic::multi::context::NativeContext;
|
||||||
|
use surfman::Connection;
|
||||||
|
use surfman::Device;
|
||||||
|
use surfman::GLApi;
|
||||||
|
use surfman::GLVersion;
|
||||||
|
use surfman::NativeWidget;
|
||||||
|
use surfman::SurfaceType;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use winapi;
|
use winapi;
|
||||||
|
|
||||||
const MULTISAMPLES: u16 = 16;
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
fn builder_with_platform_options(mut builder: glutin::WindowBuilder) -> glutin::WindowBuilder {
|
fn builder_with_platform_options(mut builder: winit::WindowBuilder) -> winit::WindowBuilder {
|
||||||
if opts::get().output_file.is_some() {
|
if opts::get().output_file.is_some() {
|
||||||
// Prevent the window from showing in Dock.app, stealing focus,
|
// Prevent the window from showing in Dock.app, stealing focus,
|
||||||
// when generating an output file.
|
// when generating an output file.
|
||||||
|
@ -55,31 +59,25 @@ fn builder_with_platform_options(mut builder: glutin::WindowBuilder) -> glutin::
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
fn builder_with_platform_options(builder: glutin::WindowBuilder) -> glutin::WindowBuilder {
|
fn builder_with_platform_options(builder: winit::WindowBuilder) -> winit::WindowBuilder {
|
||||||
builder
|
builder
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
gl_context: RefCell<GlContext>,
|
winit_window: winit::Window,
|
||||||
events_loop: Rc<RefCell<EventsLoop>>,
|
webrender_surfman: WebrenderSurfman,
|
||||||
screen_size: Size2D<u32, DeviceIndependentPixel>,
|
screen_size: Size2D<u32, DeviceIndependentPixel>,
|
||||||
inner_size: Cell<Size2D<u32, DeviceIndependentPixel>>,
|
inner_size: Cell<Size2D<u32, DeviceIndependentPixel>>,
|
||||||
mouse_down_button: Cell<Option<glutin::MouseButton>>,
|
mouse_down_button: Cell<Option<winit::MouseButton>>,
|
||||||
mouse_down_point: Cell<Point2D<i32, DevicePixel>>,
|
mouse_down_point: Cell<Point2D<i32, DevicePixel>>,
|
||||||
primary_monitor: glutin::MonitorId,
|
primary_monitor: winit::MonitorId,
|
||||||
event_queue: RefCell<Vec<WindowEvent>>,
|
event_queue: RefCell<Vec<WindowEvent>>,
|
||||||
mouse_pos: Cell<Point2D<i32, DevicePixel>>,
|
mouse_pos: Cell<Point2D<i32, DevicePixel>>,
|
||||||
last_pressed: Cell<Option<KeyboardEvent>>,
|
last_pressed: Cell<Option<KeyboardEvent>>,
|
||||||
animation_state: Cell<AnimationState>,
|
animation_state: Cell<AnimationState>,
|
||||||
fullscreen: Cell<bool>,
|
fullscreen: Cell<bool>,
|
||||||
gl: Rc<dyn gl::Gl>,
|
|
||||||
xr_rotation: Cell<Rotation3D<f32, UnknownUnit, UnknownUnit>>,
|
|
||||||
xr_translation: Cell<Vector3D<f32, UnknownUnit>>,
|
|
||||||
angle: bool,
|
|
||||||
enable_vsync: bool,
|
|
||||||
use_msaa: bool,
|
|
||||||
no_native_titlebar: bool,
|
|
||||||
device_pixels_per_px: Option<f32>,
|
device_pixels_per_px: Option<f32>,
|
||||||
|
xr_window_poses: RefCell<Vec<Rc<XRWindowPose>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
@ -97,11 +95,7 @@ fn window_creation_scale_factor() -> Scale<f32, DeviceIndependentPixel, DevicePi
|
||||||
impl Window {
|
impl Window {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
win_size: Size2D<u32, DeviceIndependentPixel>,
|
win_size: Size2D<u32, DeviceIndependentPixel>,
|
||||||
sharing: Option<&Window>,
|
|
||||||
events_loop: Rc<RefCell<EventsLoop>>,
|
events_loop: Rc<RefCell<EventsLoop>>,
|
||||||
angle: bool,
|
|
||||||
enable_vsync: bool,
|
|
||||||
use_msaa: bool,
|
|
||||||
no_native_titlebar: bool,
|
no_native_titlebar: bool,
|
||||||
device_pixels_per_px: Option<f32>,
|
device_pixels_per_px: Option<f32>,
|
||||||
) -> Window {
|
) -> Window {
|
||||||
|
@ -117,7 +111,7 @@ impl Window {
|
||||||
let width = win_size.to_untyped().width;
|
let width = win_size.to_untyped().width;
|
||||||
let height = win_size.to_untyped().height;
|
let height = win_size.to_untyped().height;
|
||||||
|
|
||||||
let mut window_builder = glutin::WindowBuilder::new()
|
let mut window_builder = winit::WindowBuilder::new()
|
||||||
.with_title("Servo".to_string())
|
.with_title("Servo".to_string())
|
||||||
.with_decorations(!no_native_titlebar)
|
.with_decorations(!no_native_titlebar)
|
||||||
.with_transparency(no_native_titlebar)
|
.with_transparency(no_native_titlebar)
|
||||||
|
@ -127,39 +121,14 @@ impl Window {
|
||||||
|
|
||||||
window_builder = builder_with_platform_options(window_builder);
|
window_builder = builder_with_platform_options(window_builder);
|
||||||
|
|
||||||
let mut context_builder = glutin::ContextBuilder::new()
|
let winit_window = window_builder.build(events_loop.borrow().as_winit()).expect("Failed to create window.");
|
||||||
.with_gl(app::gl_version(angle))
|
|
||||||
.with_vsync(enable_vsync);
|
|
||||||
|
|
||||||
if use_msaa {
|
|
||||||
context_builder = context_builder.with_multisampling(MULTISAMPLES)
|
|
||||||
}
|
|
||||||
|
|
||||||
let context = match sharing {
|
|
||||||
Some(sharing) => sharing.gl_context.borrow().new_window(
|
|
||||||
context_builder,
|
|
||||||
window_builder,
|
|
||||||
events_loop.borrow().as_winit()
|
|
||||||
),
|
|
||||||
None => context_builder.build_windowed(window_builder, events_loop.borrow().as_winit()),
|
|
||||||
}.expect("Failed to create window.");
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||||
{
|
{
|
||||||
let icon_bytes = include_bytes!("../../resources/servo64.png");
|
let icon_bytes = include_bytes!("../../resources/servo64.png");
|
||||||
context.window().set_window_icon(Some(load_icon(icon_bytes)));
|
winit_window.set_window_icon(Some(load_icon(icon_bytes)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(sharing) = sharing {
|
|
||||||
debug!("Making window {:?} not current", sharing.gl_context.borrow().window().id());
|
|
||||||
sharing.gl_context.borrow_mut().make_not_current();
|
|
||||||
}
|
|
||||||
|
|
||||||
let context = unsafe {
|
|
||||||
debug!("Making window {:?} current", context.window().id());
|
|
||||||
context.make_current().expect("Couldn't make window current")
|
|
||||||
};
|
|
||||||
|
|
||||||
let primary_monitor = events_loop.borrow().as_winit().get_primary_monitor();
|
let primary_monitor = events_loop.borrow().as_winit().get_primary_monitor();
|
||||||
|
|
||||||
let PhysicalSize {
|
let PhysicalSize {
|
||||||
|
@ -168,59 +137,43 @@ impl Window {
|
||||||
} = primary_monitor.get_dimensions();
|
} = primary_monitor.get_dimensions();
|
||||||
let screen_size = Size2D::new(screen_width as u32, screen_height as u32);
|
let screen_size = Size2D::new(screen_width as u32, screen_height as u32);
|
||||||
// TODO(ajeffrey): can this fail?
|
// TODO(ajeffrey): can this fail?
|
||||||
let LogicalSize { width, height } = context
|
let LogicalSize { width, height } = winit_window
|
||||||
.window()
|
|
||||||
.get_inner_size()
|
.get_inner_size()
|
||||||
.expect("Failed to get window inner size.");
|
.expect("Failed to get window inner size.");
|
||||||
let inner_size = Size2D::new(width as u32, height as u32);
|
let inner_size = Size2D::new(width as u32, height as u32);
|
||||||
|
|
||||||
context.window().show();
|
winit_window.show();
|
||||||
|
|
||||||
let gl = if let Some(sharing) = sharing {
|
// Initialize surfman
|
||||||
sharing.gl.clone()
|
let connection = Connection::from_winit_window(&winit_window).expect("Failed to create connection");
|
||||||
} else { match context.get_api() {
|
let adapter = connection.create_adapter().expect("Failed to create adapter");
|
||||||
Api::OpenGl => unsafe {
|
let native_widget = connection
|
||||||
gl::GlFns::load_with(|s| context.get_proc_address(s) as *const _)
|
.create_native_widget_from_winit_window(&winit_window)
|
||||||
},
|
.expect("Failed to create native widget");
|
||||||
Api::OpenGlEs => unsafe {
|
let surface_type = SurfaceType::Widget { native_widget };
|
||||||
gl::GlesFns::load_with(|s| context.get_proc_address(s) as *const _)
|
let webrender_surfman = WebrenderSurfman::create(
|
||||||
},
|
&connection,
|
||||||
Api::WebGl => unreachable!("webgl is unsupported"),
|
&adapter,
|
||||||
} };
|
surface_type,
|
||||||
|
).expect("Failed to create WR surfman");
|
||||||
|
|
||||||
gl.clear_color(0.6, 0.6, 0.6, 1.0);
|
debug!("Created window {:?}", winit_window.id());
|
||||||
gl.clear(gl::COLOR_BUFFER_BIT);
|
Window {
|
||||||
gl.finish();
|
winit_window,
|
||||||
|
webrender_surfman,
|
||||||
let context = GlContext::Current(context);
|
|
||||||
|
|
||||||
debug!("Created window {:?}", context.window().id());
|
|
||||||
let window = Window {
|
|
||||||
gl_context: RefCell::new(context),
|
|
||||||
events_loop,
|
|
||||||
event_queue: RefCell::new(vec![]),
|
event_queue: RefCell::new(vec![]),
|
||||||
mouse_down_button: Cell::new(None),
|
mouse_down_button: Cell::new(None),
|
||||||
mouse_down_point: Cell::new(Point2D::new(0, 0)),
|
mouse_down_point: Cell::new(Point2D::new(0, 0)),
|
||||||
mouse_pos: Cell::new(Point2D::new(0, 0)),
|
mouse_pos: Cell::new(Point2D::new(0, 0)),
|
||||||
last_pressed: Cell::new(None),
|
last_pressed: Cell::new(None),
|
||||||
gl: gl.clone(),
|
|
||||||
animation_state: Cell::new(AnimationState::Idle),
|
animation_state: Cell::new(AnimationState::Idle),
|
||||||
fullscreen: Cell::new(false),
|
fullscreen: Cell::new(false),
|
||||||
inner_size: Cell::new(inner_size),
|
inner_size: Cell::new(inner_size),
|
||||||
primary_monitor,
|
primary_monitor,
|
||||||
screen_size,
|
screen_size,
|
||||||
xr_rotation: Cell::new(Rotation3D::identity()),
|
|
||||||
xr_translation: Cell::new(Vector3D::zero()),
|
|
||||||
angle,
|
|
||||||
enable_vsync,
|
|
||||||
use_msaa,
|
|
||||||
no_native_titlebar,
|
|
||||||
device_pixels_per_px,
|
device_pixels_per_px,
|
||||||
};
|
xr_window_poses: RefCell::new(vec![]),
|
||||||
|
}
|
||||||
window.present();
|
|
||||||
|
|
||||||
window
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_received_character(&self, mut ch: char) {
|
fn handle_received_character(&self, mut ch: char) {
|
||||||
|
@ -245,7 +198,10 @@ impl Window {
|
||||||
KeyboardEvent::default()
|
KeyboardEvent::default()
|
||||||
};
|
};
|
||||||
event.key = Key::Character(ch.to_string());
|
event.key = Key::Character(ch.to_string());
|
||||||
self.handle_xr_translation(&event);
|
let xr_poses = self.xr_window_poses.borrow();
|
||||||
|
for xr_window_pose in &*xr_poses {
|
||||||
|
xr_window_pose.handle_xr_translation(&event);
|
||||||
|
}
|
||||||
self.event_queue
|
self.event_queue
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.push(WindowEvent::Keyboard(event));
|
.push(WindowEvent::Keyboard(event));
|
||||||
|
@ -258,68 +214,21 @@ impl Window {
|
||||||
self.last_pressed.set(Some(event));
|
self.last_pressed.set(Some(event));
|
||||||
} else if event.key != Key::Unidentified {
|
} else if event.key != Key::Unidentified {
|
||||||
self.last_pressed.set(None);
|
self.last_pressed.set(None);
|
||||||
self.handle_xr_rotation(&input);
|
let xr_poses = self.xr_window_poses.borrow();
|
||||||
|
for xr_window_pose in &*xr_poses {
|
||||||
|
xr_window_pose.handle_xr_rotation(&input);
|
||||||
|
}
|
||||||
self.event_queue
|
self.event_queue
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.push(WindowEvent::Keyboard(event));
|
.push(WindowEvent::Keyboard(event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_xr_translation(&self, input: &KeyboardEvent) {
|
|
||||||
if input.state != KeyState::Down {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const NORMAL_TRANSLATE: f32 = 0.1;
|
|
||||||
const QUICK_TRANSLATE: f32 = 1.0;
|
|
||||||
let mut x = 0.0;
|
|
||||||
let mut z = 0.0;
|
|
||||||
match input.key {
|
|
||||||
Key::Character(ref k) => match &**k {
|
|
||||||
"w" => z = -NORMAL_TRANSLATE,
|
|
||||||
"W" => z = -QUICK_TRANSLATE,
|
|
||||||
"s" => z = NORMAL_TRANSLATE,
|
|
||||||
"S" => z = QUICK_TRANSLATE,
|
|
||||||
"a" => x = -NORMAL_TRANSLATE,
|
|
||||||
"A" => x = -QUICK_TRANSLATE,
|
|
||||||
"d" => x = NORMAL_TRANSLATE,
|
|
||||||
"D" => x = QUICK_TRANSLATE,
|
|
||||||
_ => return,
|
|
||||||
},
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
let (old_x, old_y, old_z) = self.xr_translation.get().to_tuple();
|
|
||||||
let vec = Vector3D::new(x + old_x, old_y, z + old_z);
|
|
||||||
self.xr_translation.set(vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_xr_rotation(&self, input: &KeyboardInput) {
|
|
||||||
if input.state != glutin::ElementState::Pressed {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut x = 0.0;
|
|
||||||
let mut y = 0.0;
|
|
||||||
match input.virtual_keycode {
|
|
||||||
Some(VirtualKeyCode::Up) => x = 1.0,
|
|
||||||
Some(VirtualKeyCode::Down) => x = -1.0,
|
|
||||||
Some(VirtualKeyCode::Left) => y = 1.0,
|
|
||||||
Some(VirtualKeyCode::Right) => y = -1.0,
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
if input.modifiers.shift {
|
|
||||||
x = 10.0 * x;
|
|
||||||
y = 10.0 * y;
|
|
||||||
}
|
|
||||||
let x: Rotation3D<_, UnknownUnit, UnknownUnit> = Rotation3D::around_x(Angle::degrees(x));
|
|
||||||
let y: Rotation3D<_, UnknownUnit, UnknownUnit> = Rotation3D::around_y(Angle::degrees(y));
|
|
||||||
let rotation = self.xr_rotation.get().post_rotate(&x).post_rotate(&y);
|
|
||||||
self.xr_rotation.set(rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper function to handle a click
|
/// Helper function to handle a click
|
||||||
fn handle_mouse(
|
fn handle_mouse(
|
||||||
&self,
|
&self,
|
||||||
button: glutin::MouseButton,
|
button: winit::MouseButton,
|
||||||
action: glutin::ElementState,
|
action: winit::ElementState,
|
||||||
coords: Point2D<i32, DevicePixel>,
|
coords: Point2D<i32, DevicePixel>,
|
||||||
) {
|
) {
|
||||||
use servo::script_traits::MouseButton;
|
use servo::script_traits::MouseButton;
|
||||||
|
@ -359,7 +268,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn device_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
|
fn device_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
|
||||||
Scale::new(self.gl_context.borrow().window().get_hidpi_factor() as f32)
|
Scale::new(self.winit_window.get_hidpi_factor() as f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn servo_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
|
fn servo_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
|
||||||
|
@ -385,33 +294,31 @@ impl WindowPortsMethods for Window {
|
||||||
fn page_height(&self) -> f32 {
|
fn page_height(&self) -> f32 {
|
||||||
let dpr = self.servo_hidpi_factor();
|
let dpr = self.servo_hidpi_factor();
|
||||||
let size = self
|
let size = self
|
||||||
.gl_context
|
.winit_window
|
||||||
.borrow()
|
|
||||||
.window()
|
|
||||||
.get_inner_size()
|
.get_inner_size()
|
||||||
.expect("Failed to get window inner size.");
|
.expect("Failed to get window inner size.");
|
||||||
size.height as f32 * dpr.get()
|
size.height as f32 * dpr.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_title(&self, title: &str) {
|
fn set_title(&self, title: &str) {
|
||||||
self.gl_context.borrow().window().set_title(title);
|
self.winit_window.set_title(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_inner_size(&self, size: DeviceIntSize) {
|
fn set_inner_size(&self, size: DeviceIntSize) {
|
||||||
let size = size.to_f32() / self.device_hidpi_factor();
|
let size = size.to_f32() / self.device_hidpi_factor();
|
||||||
self.gl_context.borrow_mut().window()
|
self.winit_window
|
||||||
.set_inner_size(LogicalSize::new(size.width.into(), size.height.into()))
|
.set_inner_size(LogicalSize::new(size.width.into(), size.height.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_position(&self, point: DeviceIntPoint) {
|
fn set_position(&self, point: DeviceIntPoint) {
|
||||||
let point = point.to_f32() / self.device_hidpi_factor();
|
let point = point.to_f32() / self.device_hidpi_factor();
|
||||||
self.gl_context.borrow_mut().window()
|
self.winit_window
|
||||||
.set_position(LogicalPosition::new(point.x.into(), point.y.into()))
|
.set_position(LogicalPosition::new(point.x.into(), point.y.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_fullscreen(&self, state: bool) {
|
fn set_fullscreen(&self, state: bool) {
|
||||||
if self.fullscreen.get() != state {
|
if self.fullscreen.get() != state {
|
||||||
self.gl_context.borrow_mut().window()
|
self.winit_window
|
||||||
.set_fullscreen(if state { Some(self.primary_monitor.clone()) } else { None });
|
.set_fullscreen(if state { Some(self.primary_monitor.clone()) } else { None });
|
||||||
}
|
}
|
||||||
self.fullscreen.set(state);
|
self.fullscreen.set(state);
|
||||||
|
@ -422,7 +329,7 @@ impl WindowPortsMethods for Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_cursor(&self, cursor: Cursor) {
|
fn set_cursor(&self, cursor: Cursor) {
|
||||||
use glutin::MouseCursor;
|
use winit::MouseCursor;
|
||||||
|
|
||||||
let winit_cursor = match cursor {
|
let winit_cursor = match cursor {
|
||||||
Cursor::Default => MouseCursor::Default,
|
Cursor::Default => MouseCursor::Default,
|
||||||
|
@ -461,27 +368,27 @@ impl WindowPortsMethods for Window {
|
||||||
Cursor::ZoomOut => MouseCursor::ZoomOut,
|
Cursor::ZoomOut => MouseCursor::ZoomOut,
|
||||||
_ => MouseCursor::Default,
|
_ => MouseCursor::Default,
|
||||||
};
|
};
|
||||||
self.gl_context.borrow_mut().window().set_cursor(winit_cursor);
|
self.winit_window.set_cursor(winit_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_animating(&self) -> bool {
|
fn is_animating(&self) -> bool {
|
||||||
self.animation_state.get() == AnimationState::Animating
|
self.animation_state.get() == AnimationState::Animating
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id(&self) -> glutin::WindowId {
|
fn id(&self) -> winit::WindowId {
|
||||||
self.gl_context.borrow().window().id()
|
self.winit_window.id()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn winit_event_to_servo_event(&self, event: glutin::WindowEvent) {
|
fn winit_event_to_servo_event(&self, event: winit::WindowEvent) {
|
||||||
match event {
|
match event {
|
||||||
glutin::WindowEvent::ReceivedCharacter(ch) => self.handle_received_character(ch),
|
winit::WindowEvent::ReceivedCharacter(ch) => self.handle_received_character(ch),
|
||||||
glutin::WindowEvent::KeyboardInput { input, .. } => self.handle_keyboard_input(input),
|
winit::WindowEvent::KeyboardInput { input, .. } => self.handle_keyboard_input(input),
|
||||||
glutin::WindowEvent::MouseInput { state, button, .. } => {
|
winit::WindowEvent::MouseInput { state, button, .. } => {
|
||||||
if button == MouseButton::Left || button == MouseButton::Right {
|
if button == MouseButton::Left || button == MouseButton::Right {
|
||||||
self.handle_mouse(button, state, self.mouse_pos.get());
|
self.handle_mouse(button, state, self.mouse_pos.get());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
glutin::WindowEvent::CursorMoved { position, .. } => {
|
winit::WindowEvent::CursorMoved { position, .. } => {
|
||||||
let pos = position.to_physical(self.device_hidpi_factor().get() as f64);
|
let pos = position.to_physical(self.device_hidpi_factor().get() as f64);
|
||||||
let (x, y): (i32, i32) = pos.into();
|
let (x, y): (i32, i32) = pos.into();
|
||||||
self.mouse_pos.set(Point2D::new(x, y));
|
self.mouse_pos.set(Point2D::new(x, y));
|
||||||
|
@ -491,7 +398,7 @@ impl WindowPortsMethods for Window {
|
||||||
x as f32, y as f32,
|
x as f32, y as f32,
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
glutin::WindowEvent::MouseWheel { delta, phase, .. } => {
|
winit::WindowEvent::MouseWheel { delta, phase, .. } => {
|
||||||
let (mut dx, mut dy, mode) = match delta {
|
let (mut dx, mut dy, mode) = match delta {
|
||||||
MouseScrollDelta::LineDelta(dx, dy) => (dx as f64, (dy * LINE_HEIGHT) as f64,
|
MouseScrollDelta::LineDelta(dx, dy) => (dx as f64, (dy * LINE_HEIGHT) as f64,
|
||||||
WheelMode::DeltaLine),
|
WheelMode::DeltaLine),
|
||||||
|
@ -524,7 +431,7 @@ impl WindowPortsMethods for Window {
|
||||||
self.event_queue.borrow_mut().push(wheel_event);
|
self.event_queue.borrow_mut().push(wheel_event);
|
||||||
self.event_queue.borrow_mut().push(scroll_event);
|
self.event_queue.borrow_mut().push(scroll_event);
|
||||||
},
|
},
|
||||||
glutin::WindowEvent::Touch(touch) => {
|
winit::WindowEvent::Touch(touch) => {
|
||||||
use servo::script_traits::TouchId;
|
use servo::script_traits::TouchId;
|
||||||
|
|
||||||
let phase = winit_phase_to_touch_event_type(touch.phase);
|
let phase = winit_phase_to_touch_event_type(touch.phase);
|
||||||
|
@ -537,19 +444,19 @@ impl WindowPortsMethods for Window {
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.push(WindowEvent::Touch(phase, id, point));
|
.push(WindowEvent::Touch(phase, id, point));
|
||||||
},
|
},
|
||||||
glutin::WindowEvent::Refresh => {
|
winit::WindowEvent::Refresh => {
|
||||||
self.event_queue.borrow_mut().push(WindowEvent::Refresh);
|
self.event_queue.borrow_mut().push(WindowEvent::Refresh);
|
||||||
},
|
},
|
||||||
glutin::WindowEvent::CloseRequested => {
|
winit::WindowEvent::CloseRequested => {
|
||||||
self.event_queue.borrow_mut().push(WindowEvent::Quit);
|
self.event_queue.borrow_mut().push(WindowEvent::Quit);
|
||||||
},
|
},
|
||||||
glutin::WindowEvent::Resized(size) => {
|
winit::WindowEvent::Resized(size) => {
|
||||||
let physical_size = size.to_physical(self.device_hidpi_factor().get() as f64);
|
|
||||||
self.gl_context.borrow_mut().resize(physical_size);
|
|
||||||
// window.set_inner_size() takes DeviceIndependentPixel.
|
|
||||||
let (width, height) = size.into();
|
let (width, height) = size.into();
|
||||||
let new_size = Size2D::new(width, height);
|
let new_size = Size2D::new(width, height);
|
||||||
if self.inner_size.get() != new_size {
|
if self.inner_size.get() != new_size {
|
||||||
|
let physical_size = size.to_physical(self.device_hidpi_factor().get() as f64);
|
||||||
|
let physical_size = Size2D::new(physical_size.width, physical_size.height);
|
||||||
|
self.webrender_surfman.resize(physical_size.to_i32()).expect("Failed to resize");
|
||||||
self.inner_size.set(new_size);
|
self.inner_size.set(new_size);
|
||||||
self.event_queue.borrow_mut().push(WindowEvent::Resize);
|
self.event_queue.borrow_mut().push(WindowEvent::Resize);
|
||||||
}
|
}
|
||||||
|
@ -557,75 +464,40 @@ impl WindowPortsMethods for Window {
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl webxr::glwindow::GlWindow for Window {
|
fn new_glwindow(&self, events_loop: &EventsLoop) -> Box<dyn webxr::glwindow::GlWindow> {
|
||||||
fn make_current(&self) {
|
let size = self.winit_window.get_outer_size()
|
||||||
debug!("Making window {:?} current", self.gl_context.borrow().window().id());
|
.expect("Failed to get window outer size");
|
||||||
self.gl_context.borrow_mut().make_current();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn swap_buffers(&self) {
|
let mut window_builder = winit::WindowBuilder::new()
|
||||||
debug!("Swapping buffers on window {:?}", self.gl_context.borrow().window().id());
|
.with_title("Servo XR".to_string())
|
||||||
self.gl_context.borrow().swap_buffers();
|
.with_dimensions(size)
|
||||||
self.gl_context.borrow_mut().make_not_current();
|
.with_visibility(true);
|
||||||
}
|
|
||||||
|
|
||||||
fn size(&self) -> UntypedSize2D<gl::GLsizei> {
|
window_builder = builder_with_platform_options(window_builder);
|
||||||
let dpr = self.device_hidpi_factor().get() as f64;
|
|
||||||
let size = self
|
|
||||||
.gl_context
|
|
||||||
.borrow()
|
|
||||||
.window()
|
|
||||||
.get_inner_size()
|
|
||||||
.expect("Failed to get window inner size.");
|
|
||||||
let size = size.to_physical(dpr);
|
|
||||||
let (w, h): (u32, u32) = size.into();
|
|
||||||
Size2D::new(w as i32, h as i32)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_rotation(&self) -> Rotation3D<f32, UnknownUnit, UnknownUnit> {
|
let winit_window = window_builder.build(events_loop.as_winit())
|
||||||
self.xr_rotation.get().clone()
|
.expect("Failed to create window.");
|
||||||
}
|
|
||||||
|
|
||||||
fn get_translation(&self) -> Vector3D<f32, UnknownUnit> {
|
let pose = Rc::new(XRWindowPose {
|
||||||
self.xr_translation.get().clone()
|
xr_rotation: Cell::new(Rotation3D::identity()),
|
||||||
}
|
xr_translation: Cell::new(Vector3D::zero()),
|
||||||
|
});
|
||||||
fn new_window(&self) -> Result<Rc<dyn webxr::glwindow::GlWindow>, ()> {
|
self.xr_window_poses.borrow_mut().push(pose.clone());
|
||||||
let window = Rc::new(Window::new(
|
Box::new(XRWindow { winit_window, pose })
|
||||||
self.inner_size.get(),
|
|
||||||
Some(self),
|
|
||||||
self.events_loop.clone(),
|
|
||||||
self.angle,
|
|
||||||
self.enable_vsync,
|
|
||||||
self.use_msaa,
|
|
||||||
self.no_native_titlebar,
|
|
||||||
self.device_pixels_per_px,
|
|
||||||
));
|
|
||||||
app::register_window(window.clone());
|
|
||||||
Ok(window)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowMethods for Window {
|
impl WindowMethods for Window {
|
||||||
fn gl(&self) -> Rc<dyn gl::Gl> {
|
|
||||||
self.gl.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_coordinates(&self) -> EmbedderCoordinates {
|
fn get_coordinates(&self) -> EmbedderCoordinates {
|
||||||
// TODO(ajeffrey): can this fail?
|
// TODO(ajeffrey): can this fail?
|
||||||
let dpr = self.device_hidpi_factor();
|
let dpr = self.device_hidpi_factor();
|
||||||
let LogicalSize { width, height } = self
|
let LogicalSize { width, height } = self
|
||||||
.gl_context
|
.winit_window
|
||||||
.borrow()
|
|
||||||
.window()
|
|
||||||
.get_outer_size()
|
.get_outer_size()
|
||||||
.expect("Failed to get window outer size.");
|
.expect("Failed to get window outer size.");
|
||||||
let LogicalPosition { x, y } = self
|
let LogicalPosition { x, y } = self
|
||||||
.gl_context
|
.winit_window
|
||||||
.borrow()
|
|
||||||
.window()
|
|
||||||
.get_position()
|
.get_position()
|
||||||
.unwrap_or(LogicalPosition::new(0., 0.));
|
.unwrap_or(LogicalPosition::new(0., 0.));
|
||||||
let win_size = (Size2D::new(width as f32, height as f32) * dpr).to_i32();
|
let win_size = (Size2D::new(width as f32, height as f32) * dpr).to_i32();
|
||||||
|
@ -633,45 +505,58 @@ impl WindowMethods for Window {
|
||||||
let screen = (self.screen_size.to_f32() * dpr).to_i32();
|
let screen = (self.screen_size.to_f32() * dpr).to_i32();
|
||||||
|
|
||||||
let LogicalSize { width, height } = self
|
let LogicalSize { width, height } = self
|
||||||
.gl_context
|
.winit_window
|
||||||
.borrow()
|
|
||||||
.window()
|
|
||||||
.get_inner_size()
|
.get_inner_size()
|
||||||
.expect("Failed to get window inner size.");
|
.expect("Failed to get window inner size.");
|
||||||
let inner_size = (Size2D::new(width as f32, height as f32) * dpr).to_i32();
|
let inner_size = (Size2D::new(width as f32, height as f32) * dpr).to_i32();
|
||||||
let viewport = DeviceIntRect::new(Point2D::zero(), inner_size);
|
let viewport = DeviceIntRect::new(Point2D::zero(), inner_size);
|
||||||
let framebuffer = DeviceIntSize::from_untyped(viewport.size.to_untyped());
|
let framebuffer = DeviceIntSize::from_untyped(viewport.size.to_untyped());
|
||||||
|
|
||||||
EmbedderCoordinates {
|
EmbedderCoordinates {
|
||||||
viewport,
|
viewport,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
window: (win_size, win_origin),
|
window: (win_size, win_origin),
|
||||||
screen: screen,
|
screen: screen,
|
||||||
// FIXME: Glutin doesn't have API for available size. Fallback to screen size
|
// FIXME: Winit doesn't have API for available size. Fallback to screen size
|
||||||
screen_avail: screen,
|
screen_avail: screen,
|
||||||
hidpi_factor: self.servo_hidpi_factor(),
|
hidpi_factor: self.servo_hidpi_factor(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn present(&self) {
|
|
||||||
self.gl_context.borrow().swap_buffers();
|
|
||||||
self.gl_context.borrow_mut().make_not_current();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_animation_state(&self, state: AnimationState) {
|
fn set_animation_state(&self, state: AnimationState) {
|
||||||
self.animation_state.set(state);
|
self.animation_state.set(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_gl_context_current(&self) {
|
fn webrender_surfman(&self) -> WebrenderSurfman {
|
||||||
self.gl_context.borrow_mut().make_current();
|
self.webrender_surfman.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_gl_context(&self) -> PlayerGLContext {
|
fn get_gl_context(&self) -> PlayerGLContext {
|
||||||
if pref!(media.glvideo.enabled) {
|
if !pref!(media.glvideo.enabled) {
|
||||||
return self.gl_context.borrow().raw_context();
|
return PlayerGLContext::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PlayerGLContext::Unknown;
|
#[allow(unused_variables)]
|
||||||
|
let native_context = self.webrender_surfman.native_context();
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
return PlayerGLContext::Egl(native_context.egl_context as usize);
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
return match native_context {
|
||||||
|
NativeContext::Default(NativeContext::Default(native_context)) =>
|
||||||
|
PlayerGLContext::Egl(native_context.egl_context as usize),
|
||||||
|
NativeContext::Default(NativeContext::Alternate(native_context)) =>
|
||||||
|
PlayerGLContext::Egl(native_context.egl_context as usize),
|
||||||
|
NativeContext::Alternate(_) => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// @TODO(victor): https://github.com/servo/media/pull/315
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
#[allow(unreachable_code)]
|
||||||
|
return unimplemented!();
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "linux", target_os = "windows", target_os = "macos")))]
|
||||||
|
return unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_native_display(&self) -> NativeDisplay {
|
fn get_native_display(&self) -> NativeDisplay {
|
||||||
|
@ -679,48 +564,41 @@ impl WindowMethods for Window {
|
||||||
return NativeDisplay::Unknown;
|
return NativeDisplay::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
let native_connection = self.webrender_surfman.connection().native_connection();
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
let native_device = self.webrender_surfman.native_device();
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
return NativeDisplay::Egl(native_device.egl_display as usize);
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
{
|
return match native_connection {
|
||||||
if let Some(display) = self.gl_context.borrow().window().get_wayland_display() {
|
NativeConnection::Default(NativeConnection::Default(conn)) =>
|
||||||
return NativeDisplay::Wayland(display as usize);
|
NativeDisplay::Egl(conn.0 as usize),
|
||||||
} else if let Some(display) =
|
NativeConnection::Default(NativeConnection::Alternate(conn)) =>
|
||||||
self.gl_context.borrow().window().get_xlib_display()
|
NativeDisplay::X11(conn.x11_display as usize),
|
||||||
{
|
NativeConnection::Alternate(_) => unimplemented!(),
|
||||||
return NativeDisplay::X11(display as usize);
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
// @TODO(victor): https://github.com/servo/media/pull/315
|
||||||
{
|
#[cfg(target_os = "macos")]
|
||||||
if let Some(display) = self.gl_context.borrow().egl_display() {
|
#[allow(unreachable_code)]
|
||||||
return NativeDisplay::Egl(display as usize);
|
return unimplemented!();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeDisplay::Unknown
|
#[cfg(not(any(target_os = "linux", target_os = "windows", target_os = "macos")))]
|
||||||
|
return unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_gl_api(&self) -> GlApi {
|
fn get_gl_api(&self) -> GlApi {
|
||||||
let api = self.gl_context.borrow().get_api();
|
let api = self.webrender_surfman.connection().gl_api();
|
||||||
|
let attributes = self.webrender_surfman.context_attributes();
|
||||||
let version = self.gl.get_string(gl::VERSION);
|
let GLVersion { major, minor } = attributes.version;
|
||||||
let version = version.trim_start_matches("OpenGL ES ");
|
|
||||||
let mut values = version.split(&['.', ' '][..]);
|
|
||||||
let major = values
|
|
||||||
.next()
|
|
||||||
.and_then(|v| v.parse::<u32>().ok())
|
|
||||||
.unwrap_or(1);
|
|
||||||
let minor = values
|
|
||||||
.next()
|
|
||||||
.and_then(|v| v.parse::<u32>().ok())
|
|
||||||
.unwrap_or(20);
|
|
||||||
|
|
||||||
match api {
|
match api {
|
||||||
glutin::Api::OpenGl if major >= 3 && minor >= 2 => GlApi::OpenGL3,
|
GLApi::GL if major >= 3 && minor >= 2 => GlApi::OpenGL3,
|
||||||
glutin::Api::OpenGl => GlApi::OpenGL,
|
GLApi::GL => GlApi::OpenGL,
|
||||||
glutin::Api::OpenGlEs if major > 1 => GlApi::Gles2,
|
GLApi::GLES if major > 1 => GlApi::Gles2,
|
||||||
glutin::Api::OpenGlEs => GlApi::Gles1,
|
GLApi::GLES => GlApi::Gles1,
|
||||||
_ => GlApi::None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -748,3 +626,81 @@ fn load_icon(icon_bytes: &[u8]) -> Icon {
|
||||||
};
|
};
|
||||||
Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to load icon")
|
Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to load icon")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct XRWindow {
|
||||||
|
winit_window: winit::Window,
|
||||||
|
pose: Rc<XRWindowPose>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct XRWindowPose {
|
||||||
|
xr_rotation: Cell<Rotation3D<f32, UnknownUnit, UnknownUnit>>,
|
||||||
|
xr_translation: Cell<Vector3D<f32, UnknownUnit>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl webxr::glwindow::GlWindow for XRWindow {
|
||||||
|
fn get_native_widget(&self, device: &Device) -> NativeWidget {
|
||||||
|
device.connection()
|
||||||
|
.create_native_widget_from_winit_window(&self.winit_window)
|
||||||
|
.expect("Failed to create native widget")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_rotation(&self) -> Rotation3D<f32, UnknownUnit, UnknownUnit> {
|
||||||
|
self.pose.xr_rotation.get().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_translation(&self) -> Vector3D<f32, UnknownUnit> {
|
||||||
|
self.pose.xr_translation.get().clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRWindowPose {
|
||||||
|
fn handle_xr_translation(&self, input: &KeyboardEvent) {
|
||||||
|
if input.state != KeyState::Down {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const NORMAL_TRANSLATE: f32 = 0.1;
|
||||||
|
const QUICK_TRANSLATE: f32 = 1.0;
|
||||||
|
let mut x = 0.0;
|
||||||
|
let mut z = 0.0;
|
||||||
|
match input.key {
|
||||||
|
Key::Character(ref k) => match &**k {
|
||||||
|
"w" => z = -NORMAL_TRANSLATE,
|
||||||
|
"W" => z = -QUICK_TRANSLATE,
|
||||||
|
"s" => z = NORMAL_TRANSLATE,
|
||||||
|
"S" => z = QUICK_TRANSLATE,
|
||||||
|
"a" => x = -NORMAL_TRANSLATE,
|
||||||
|
"A" => x = -QUICK_TRANSLATE,
|
||||||
|
"d" => x = NORMAL_TRANSLATE,
|
||||||
|
"D" => x = QUICK_TRANSLATE,
|
||||||
|
_ => return,
|
||||||
|
},
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
let (old_x, old_y, old_z) = self.xr_translation.get().to_tuple();
|
||||||
|
let vec = Vector3D::new(x + old_x, old_y, z + old_z);
|
||||||
|
self.xr_translation.set(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_xr_rotation(&self, input: &KeyboardInput) {
|
||||||
|
if input.state != winit::ElementState::Pressed {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut x = 0.0;
|
||||||
|
let mut y = 0.0;
|
||||||
|
match input.virtual_keycode {
|
||||||
|
Some(VirtualKeyCode::Up) => x = 1.0,
|
||||||
|
Some(VirtualKeyCode::Down) => x = -1.0,
|
||||||
|
Some(VirtualKeyCode::Left) => y = 1.0,
|
||||||
|
Some(VirtualKeyCode::Right) => y = -1.0,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
if input.modifiers.shift {
|
||||||
|
x = 10.0 * x;
|
||||||
|
y = 10.0 * y;
|
||||||
|
}
|
||||||
|
let x: Rotation3D<_, UnknownUnit, UnknownUnit> = Rotation3D::around_x(Angle::degrees(x));
|
||||||
|
let y: Rotation3D<_, UnknownUnit, UnknownUnit> = Rotation3D::around_y(Angle::degrees(y));
|
||||||
|
let rotation = self.xr_rotation.get().post_rotate(&x).post_rotate(&y);
|
||||||
|
self.xr_rotation.set(rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,93 +4,28 @@
|
||||||
|
|
||||||
//! A headless window implementation.
|
//! A headless window implementation.
|
||||||
|
|
||||||
|
use crate::events_loop::EventsLoop;
|
||||||
use crate::window_trait::WindowPortsMethods;
|
use crate::window_trait::WindowPortsMethods;
|
||||||
use euclid::{default::Size2D as UntypedSize2D, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
|
use euclid::{Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
|
||||||
use gleam::gl;
|
use winit;
|
||||||
use glutin;
|
|
||||||
use servo::compositing::windowing::{AnimationState, WindowEvent};
|
use servo::compositing::windowing::{AnimationState, WindowEvent};
|
||||||
use servo::compositing::windowing::{EmbedderCoordinates, WindowMethods};
|
use servo::compositing::windowing::{EmbedderCoordinates, WindowMethods};
|
||||||
use servo::servo_geometry::DeviceIndependentPixel;
|
use servo::servo_geometry::DeviceIndependentPixel;
|
||||||
use servo::style_traits::DevicePixel;
|
use servo::style_traits::DevicePixel;
|
||||||
use servo::webrender_api::units::{DeviceIntRect, DeviceIntSize};
|
use servo::webrender_api::units::DeviceIntRect;
|
||||||
use servo_media::player::context as MediaPlayerCtxt;
|
use servo_media::player::context as MediaPlayerCtxt;
|
||||||
|
use servo::webrender_surfman::WebrenderSurfman;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
|
||||||
use std::cell::RefCell;
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
|
||||||
use std::ffi::CString;
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
|
||||||
use std::mem;
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::ptr;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use surfman::Connection;
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
use surfman::Device;
|
||||||
struct HeadlessContext {
|
use surfman::NativeWidget;
|
||||||
width: u32,
|
use surfman::SurfaceType;
|
||||||
height: u32,
|
|
||||||
context: osmesa_sys::OSMesaContext,
|
|
||||||
buffer: RefCell<Vec<u32>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
|
||||||
struct HeadlessContext {
|
|
||||||
width: u32,
|
|
||||||
height: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HeadlessContext {
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
|
||||||
fn new(width: u32, height: u32, share: Option<&HeadlessContext>) -> HeadlessContext {
|
|
||||||
let mut attribs = Vec::new();
|
|
||||||
|
|
||||||
attribs.push(osmesa_sys::OSMESA_PROFILE);
|
|
||||||
attribs.push(osmesa_sys::OSMESA_CORE_PROFILE);
|
|
||||||
attribs.push(osmesa_sys::OSMESA_CONTEXT_MAJOR_VERSION);
|
|
||||||
attribs.push(3);
|
|
||||||
attribs.push(osmesa_sys::OSMESA_CONTEXT_MINOR_VERSION);
|
|
||||||
attribs.push(3);
|
|
||||||
attribs.push(0);
|
|
||||||
|
|
||||||
let share = share.map_or(ptr::null_mut(), |share| share.context as *mut _);
|
|
||||||
|
|
||||||
let context = unsafe { osmesa_sys::OSMesaCreateContextAttribs(attribs.as_ptr(), share) };
|
|
||||||
|
|
||||||
assert!(!context.is_null());
|
|
||||||
|
|
||||||
HeadlessContext {
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
context: context,
|
|
||||||
buffer: RefCell::new(vec![0; (width * height) as usize]),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
|
||||||
fn new(width: u32, height: u32, _share: Option<&HeadlessContext>) -> HeadlessContext {
|
|
||||||
HeadlessContext {
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
|
||||||
fn get_proc_address(s: &str) -> *const c_void {
|
|
||||||
let c_str = CString::new(s).expect("Unable to create CString");
|
|
||||||
unsafe { mem::transmute(osmesa_sys::OSMesaGetProcAddress(c_str.as_ptr())) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
|
||||||
fn get_proc_address(_: &str) -> *const c_void {
|
|
||||||
ptr::null() as *const _
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
context: HeadlessContext,
|
webrender_surfman: WebrenderSurfman,
|
||||||
animation_state: Cell<AnimationState>,
|
animation_state: Cell<AnimationState>,
|
||||||
fullscreen: Cell<bool>,
|
fullscreen: Cell<bool>,
|
||||||
gl: Rc<dyn gl::Gl>,
|
|
||||||
device_pixels_per_px: Option<f32>,
|
device_pixels_per_px: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,18 +34,19 @@ impl Window {
|
||||||
size: Size2D<u32, DeviceIndependentPixel>,
|
size: Size2D<u32, DeviceIndependentPixel>,
|
||||||
device_pixels_per_px: Option<f32>,
|
device_pixels_per_px: Option<f32>,
|
||||||
) -> Rc<dyn WindowPortsMethods> {
|
) -> Rc<dyn WindowPortsMethods> {
|
||||||
let context = HeadlessContext::new(size.width, size.height, None);
|
// Initialize surfman
|
||||||
let gl = unsafe { gl::GlFns::load_with(|s| HeadlessContext::get_proc_address(s)) };
|
let connection = Connection::new().expect("Failed to create connection");
|
||||||
|
let adapter = connection.create_software_adapter().expect("Failed to create adapter");
|
||||||
// Print some information about the headless renderer that
|
let size = size.to_untyped().to_i32();
|
||||||
// can be useful in diagnosing CI failures on build machines.
|
let surface_type = SurfaceType::Generic { size };
|
||||||
println!("{}", gl.get_string(gl::VENDOR));
|
let webrender_surfman = WebrenderSurfman::create(
|
||||||
println!("{}", gl.get_string(gl::RENDERER));
|
&connection,
|
||||||
println!("{}", gl.get_string(gl::VERSION));
|
&adapter,
|
||||||
|
surface_type,
|
||||||
|
).expect("Failed to create WR surfman");
|
||||||
|
|
||||||
let window = Window {
|
let window = Window {
|
||||||
context,
|
webrender_surfman,
|
||||||
gl,
|
|
||||||
animation_state: Cell::new(AnimationState::Idle),
|
animation_state: Cell::new(AnimationState::Idle),
|
||||||
fullscreen: Cell::new(false),
|
fullscreen: Cell::new(false),
|
||||||
device_pixels_per_px,
|
device_pixels_per_px,
|
||||||
|
@ -136,13 +72,18 @@ impl WindowPortsMethods for Window {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id(&self) -> glutin::WindowId {
|
fn id(&self) -> winit::WindowId {
|
||||||
unsafe { glutin::WindowId::dummy() }
|
unsafe { winit::WindowId::dummy() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn page_height(&self) -> f32 {
|
fn page_height(&self) -> f32 {
|
||||||
|
let height = self.webrender_surfman
|
||||||
|
.context_surface_info()
|
||||||
|
.unwrap_or(None)
|
||||||
|
.map(|info| info.size.height)
|
||||||
|
.unwrap_or(0);
|
||||||
let dpr = self.servo_hidpi_factor();
|
let dpr = self.servo_hidpi_factor();
|
||||||
self.context.height as f32 * dpr.get()
|
height as f32 * dpr.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_fullscreen(&self, state: bool) {
|
fn set_fullscreen(&self, state: bool) {
|
||||||
|
@ -157,24 +98,27 @@ impl WindowPortsMethods for Window {
|
||||||
self.animation_state.get() == AnimationState::Animating
|
self.animation_state.get() == AnimationState::Animating
|
||||||
}
|
}
|
||||||
|
|
||||||
fn winit_event_to_servo_event(&self, _event: glutin::WindowEvent) {
|
fn winit_event_to_servo_event(&self, _event: winit::WindowEvent) {
|
||||||
// Not expecting any winit events.
|
// Not expecting any winit events.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_glwindow(&self, _events_loop: &EventsLoop) -> Box<dyn webxr::glwindow::GlWindow> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowMethods for Window {
|
impl WindowMethods for Window {
|
||||||
fn gl(&self) -> Rc<dyn gl::Gl> {
|
|
||||||
self.gl.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_coordinates(&self) -> EmbedderCoordinates {
|
fn get_coordinates(&self) -> EmbedderCoordinates {
|
||||||
let dpr = self.servo_hidpi_factor();
|
let dpr = self.servo_hidpi_factor();
|
||||||
let size = (Size2D::new(self.context.width, self.context.height).to_f32() * dpr).to_i32();
|
let size = self.webrender_surfman
|
||||||
|
.context_surface_info()
|
||||||
|
.unwrap_or(None)
|
||||||
|
.map(|info| Size2D::from_untyped(info.size))
|
||||||
|
.unwrap_or(Size2D::new(0, 0));
|
||||||
let viewport = DeviceIntRect::new(Point2D::zero(), size);
|
let viewport = DeviceIntRect::new(Point2D::zero(), size);
|
||||||
let framebuffer = DeviceIntSize::from_untyped(size.to_untyped());
|
|
||||||
EmbedderCoordinates {
|
EmbedderCoordinates {
|
||||||
viewport,
|
viewport,
|
||||||
framebuffer,
|
framebuffer: size,
|
||||||
window: (size, Point2D::zero()),
|
window: (size, Point2D::zero()),
|
||||||
screen: size,
|
screen: size,
|
||||||
screen_avail: size,
|
screen_avail: size,
|
||||||
|
@ -182,30 +126,10 @@ impl WindowMethods for Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn present(&self) {}
|
|
||||||
|
|
||||||
fn set_animation_state(&self, state: AnimationState) {
|
fn set_animation_state(&self, state: AnimationState) {
|
||||||
self.animation_state.set(state);
|
self.animation_state.set(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
|
||||||
fn make_gl_context_current(&self) {
|
|
||||||
unsafe {
|
|
||||||
let mut buffer = self.context.buffer.borrow_mut();
|
|
||||||
let ret = osmesa_sys::OSMesaMakeCurrent(
|
|
||||||
self.context.context,
|
|
||||||
buffer.as_mut_ptr() as *mut _,
|
|
||||||
gl::UNSIGNED_BYTE,
|
|
||||||
self.context.width as i32,
|
|
||||||
self.context.height as i32,
|
|
||||||
);
|
|
||||||
assert_ne!(ret, 0);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
|
||||||
fn make_gl_context_current(&self) {}
|
|
||||||
|
|
||||||
fn get_gl_context(&self) -> MediaPlayerCtxt::GlContext {
|
fn get_gl_context(&self) -> MediaPlayerCtxt::GlContext {
|
||||||
MediaPlayerCtxt::GlContext::Unknown
|
MediaPlayerCtxt::GlContext::Unknown
|
||||||
}
|
}
|
||||||
|
@ -217,32 +141,17 @@ impl WindowMethods for Window {
|
||||||
fn get_gl_api(&self) -> MediaPlayerCtxt::GlApi {
|
fn get_gl_api(&self) -> MediaPlayerCtxt::GlApi {
|
||||||
MediaPlayerCtxt::GlApi::None
|
MediaPlayerCtxt::GlApi::None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn webrender_surfman(&self) -> WebrenderSurfman {
|
||||||
|
self.webrender_surfman.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl webxr::glwindow::GlWindow for Window {
|
impl webxr::glwindow::GlWindow for Window {
|
||||||
fn make_current(&self) {}
|
fn get_native_widget(&self, _device: &Device) -> NativeWidget {
|
||||||
fn swap_buffers(&self) {}
|
unimplemented!()
|
||||||
fn size(&self) -> UntypedSize2D<gl::GLsizei> {
|
|
||||||
let dpr = self.servo_hidpi_factor().get();
|
|
||||||
Size2D::new(
|
|
||||||
(self.context.width as f32 * dpr) as gl::GLsizei,
|
|
||||||
(self.context.height as f32 * dpr) as gl::GLsizei,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fn new_window(&self) -> Result<Rc<dyn webxr::glwindow::GlWindow>, ()> {
|
|
||||||
let width = self.context.width;
|
|
||||||
let height = self.context.height;
|
|
||||||
let share = Some(&self.context);
|
|
||||||
let context = HeadlessContext::new(width, height, share);
|
|
||||||
let gl = self.gl.clone();
|
|
||||||
Ok(Rc::new(Window {
|
|
||||||
context,
|
|
||||||
gl,
|
|
||||||
animation_state: Cell::new(AnimationState::Idle),
|
|
||||||
fullscreen: Cell::new(false),
|
|
||||||
device_pixels_per_px: self.device_pixels_per_px,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_rotation(&self) -> Rotation3D<f32, UnknownUnit, UnknownUnit> {
|
fn get_rotation(&self) -> Rotation3D<f32, UnknownUnit, UnknownUnit> {
|
||||||
Rotation3D::identity()
|
Rotation3D::identity()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use glutin::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode};
|
use winit::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode};
|
||||||
use keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers};
|
use keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers};
|
||||||
|
|
||||||
// Some shortcuts use Cmd on Mac and Control on other systems.
|
// Some shortcuts use Cmd on Mac and Control on other systems.
|
||||||
|
@ -18,7 +18,7 @@ pub const CMD_OR_ALT: Modifiers = Modifiers::META;
|
||||||
pub const CMD_OR_ALT: Modifiers = Modifiers::ALT;
|
pub const CMD_OR_ALT: Modifiers = Modifiers::ALT;
|
||||||
|
|
||||||
fn get_servo_key_from_winit_key(key: Option<VirtualKeyCode>) -> Key {
|
fn get_servo_key_from_winit_key(key: Option<VirtualKeyCode>) -> Key {
|
||||||
use glutin::VirtualKeyCode::*;
|
use winit::VirtualKeyCode::*;
|
||||||
// TODO: figure out how to map NavigateForward, NavigateBackward
|
// TODO: figure out how to map NavigateForward, NavigateBackward
|
||||||
// TODO: map the remaining keys if possible
|
// TODO: map the remaining keys if possible
|
||||||
let key = if let Some(key) = key {
|
let key = if let Some(key) = key {
|
||||||
|
@ -127,7 +127,7 @@ fn get_servo_key_from_winit_key(key: Option<VirtualKeyCode>) -> Key {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_servo_location_from_winit_key(key: Option<VirtualKeyCode>) -> Location {
|
fn get_servo_location_from_winit_key(key: Option<VirtualKeyCode>) -> Location {
|
||||||
use glutin::VirtualKeyCode::*;
|
use winit::VirtualKeyCode::*;
|
||||||
// TODO: add more numpad keys
|
// TODO: add more numpad keys
|
||||||
let key = if let Some(key) = key {
|
let key = if let Some(key) = key {
|
||||||
key
|
key
|
||||||
|
|
|
@ -13,7 +13,6 @@ extern crate sig;
|
||||||
mod app;
|
mod app;
|
||||||
mod backtrace;
|
mod backtrace;
|
||||||
mod browser;
|
mod browser;
|
||||||
mod context;
|
|
||||||
mod embedder;
|
mod embedder;
|
||||||
mod events_loop;
|
mod events_loop;
|
||||||
mod headed_window;
|
mod headed_window;
|
||||||
|
@ -95,12 +94,6 @@ pub fn main() {
|
||||||
"clean-shutdown",
|
"clean-shutdown",
|
||||||
"Do not shutdown until all threads have finished (macos only)",
|
"Do not shutdown until all threads have finished (macos only)",
|
||||||
);
|
);
|
||||||
opts.optflag(
|
|
||||||
"",
|
|
||||||
"disable-vsync",
|
|
||||||
"Disable vsync mode in the compositor to allow profiling at more than monitor refresh rate",
|
|
||||||
);
|
|
||||||
opts.optflag("", "msaa", "Use multisample antialiasing in WebRender.");
|
|
||||||
opts.optflag("b", "no-native-titlebar", "Do not use native titlebar");
|
opts.optflag("b", "no-native-titlebar", "Do not use native titlebar");
|
||||||
opts.optopt("", "device-pixel-ratio", "Device pixels per px", "");
|
opts.optopt("", "device-pixel-ratio", "Device pixels per px", "");
|
||||||
opts.optopt(
|
opts.optopt(
|
||||||
|
@ -170,28 +163,19 @@ pub fn main() {
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let angle = opts_matches.opt_present("angle");
|
|
||||||
let clean_shutdown = opts_matches.opt_present("clean-shutdown");
|
let clean_shutdown = opts_matches.opt_present("clean-shutdown");
|
||||||
let do_not_use_native_titlebar =
|
let do_not_use_native_titlebar =
|
||||||
opts_matches.opt_present("no-native-titlebar") || !(pref!(shell.native_titlebar.enabled));
|
opts_matches.opt_present("no-native-titlebar") || !(pref!(shell.native_titlebar.enabled));
|
||||||
let enable_vsync = !opts_matches.opt_present("disable-vsync");
|
|
||||||
let use_msaa = opts_matches.opt_present("msaa");
|
|
||||||
let device_pixels_per_px = opts_matches.opt_str("device-pixel-ratio").map(|dppx_str| {
|
let device_pixels_per_px = opts_matches.opt_str("device-pixel-ratio").map(|dppx_str| {
|
||||||
dppx_str.parse().unwrap_or_else(|err| {
|
dppx_str.parse().unwrap_or_else(|err| {
|
||||||
error!("Error parsing option: --device-pixel-ratio ({})", err);
|
error!("Error parsing option: --device-pixel-ratio ({})", err);
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let user_agent = opts_matches.opt_str("u");
|
let user_agent = opts_matches.opt_str("u");
|
||||||
|
|
||||||
App::run(
|
App::run(do_not_use_native_titlebar, device_pixels_per_px, user_agent);
|
||||||
angle,
|
|
||||||
enable_vsync,
|
|
||||||
use_msaa,
|
|
||||||
do_not_use_native_titlebar,
|
|
||||||
device_pixels_per_px,
|
|
||||||
user_agent,
|
|
||||||
);
|
|
||||||
|
|
||||||
platform::deinit(clean_shutdown)
|
platform::deinit(clean_shutdown)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
//! Definition of Window.
|
//! Definition of Window.
|
||||||
//! Implemented by headless and headed windows.
|
//! Implemented by headless and headed windows.
|
||||||
|
|
||||||
use glutin;
|
use crate::events_loop::EventsLoop;
|
||||||
|
use winit;
|
||||||
use servo::compositing::windowing::{WindowEvent, WindowMethods};
|
use servo::compositing::windowing::{WindowEvent, WindowMethods};
|
||||||
use servo::embedder_traits::Cursor;
|
use servo::embedder_traits::Cursor;
|
||||||
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
||||||
|
@ -13,17 +14,18 @@ use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
||||||
// This should vary by zoom level and maybe actual text size (focused or under cursor)
|
// This should vary by zoom level and maybe actual text size (focused or under cursor)
|
||||||
pub const LINE_HEIGHT: f32 = 38.0;
|
pub const LINE_HEIGHT: f32 = 38.0;
|
||||||
|
|
||||||
pub trait WindowPortsMethods: WindowMethods + webxr::glwindow::GlWindow {
|
pub trait WindowPortsMethods: WindowMethods {
|
||||||
fn get_events(&self) -> Vec<WindowEvent>;
|
fn get_events(&self) -> Vec<WindowEvent>;
|
||||||
fn id(&self) -> glutin::WindowId;
|
fn id(&self) -> winit::WindowId;
|
||||||
fn has_events(&self) -> bool;
|
fn has_events(&self) -> bool;
|
||||||
fn page_height(&self) -> f32;
|
fn page_height(&self) -> f32;
|
||||||
fn get_fullscreen(&self) -> bool;
|
fn get_fullscreen(&self) -> bool;
|
||||||
fn winit_event_to_servo_event(&self, event: glutin::WindowEvent);
|
fn winit_event_to_servo_event(&self, event: winit::WindowEvent);
|
||||||
fn is_animating(&self) -> bool;
|
fn is_animating(&self) -> bool;
|
||||||
fn set_title(&self, _title: &str) {}
|
fn set_title(&self, _title: &str) {}
|
||||||
fn set_inner_size(&self, _size: DeviceIntSize) {}
|
fn set_inner_size(&self, _size: DeviceIntSize) {}
|
||||||
fn set_position(&self, _point: DeviceIntPoint) {}
|
fn set_position(&self, _point: DeviceIntPoint) {}
|
||||||
fn set_fullscreen(&self, _state: bool) {}
|
fn set_fullscreen(&self, _state: bool) {}
|
||||||
fn set_cursor(&self, _cursor: Cursor) {}
|
fn set_cursor(&self, _cursor: Cursor) {}
|
||||||
|
fn new_glwindow(&self, events_loop: &EventsLoop) -> Box<dyn webxr::glwindow::GlWindow>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,9 @@ lazy_static = "1.4"
|
||||||
libservo = {path = "../../components/servo"}
|
libservo = {path = "../../components/servo"}
|
||||||
servo-media = {git = "https://github.com/servo/media"}
|
servo-media = {git = "https://github.com/servo/media"}
|
||||||
sparkle = "0.1"
|
sparkle = "0.1"
|
||||||
surfman = { git = "https://github.com/pcwalton/surfman", branch = "multi" }
|
surfman = { git = "https://github.com/servo/surfman" }
|
||||||
surfman-chains-api = "0.2"
|
surfman-chains-api = "0.2"
|
||||||
surfman-chains = { git = "https://github.com/asajeffrey/surfman-chains", branch = "multi" }
|
surfman-chains = { git = "https://github.com/asajeffrey/surfman-chains" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gst-plugin-version-helper = "0.1"
|
gst-plugin-version-helper = "0.1"
|
||||||
|
|
|
@ -76,35 +76,20 @@ use servo::embedder_traits::EventLoopWaker;
|
||||||
use servo::msg::constellation_msg::TopLevelBrowsingContextId;
|
use servo::msg::constellation_msg::TopLevelBrowsingContextId;
|
||||||
use servo::servo_url::ServoUrl;
|
use servo::servo_url::ServoUrl;
|
||||||
use servo::webrender_api::units::DevicePixel;
|
use servo::webrender_api::units::DevicePixel;
|
||||||
|
use servo::webrender_surfman::WebrenderSurfman;
|
||||||
use servo::Servo;
|
use servo::Servo;
|
||||||
|
|
||||||
use sparkle::gl;
|
use sparkle::gl;
|
||||||
use sparkle::gl::types::GLuint;
|
use sparkle::gl::types::GLuint;
|
||||||
use sparkle::gl::Gl;
|
use sparkle::gl::Gl;
|
||||||
|
|
||||||
use surfman::connection::Connection as ConnectionAPI;
|
use surfman::Connection;
|
||||||
use surfman::device::Device as DeviceAPI;
|
use surfman::Context;
|
||||||
use surfman::ContextAttributeFlags;
|
use surfman::Device;
|
||||||
use surfman::ContextAttributes;
|
|
||||||
use surfman::GLApi;
|
|
||||||
use surfman::GLVersion;
|
|
||||||
use surfman::SurfaceAccess;
|
|
||||||
use surfman::SurfaceType;
|
use surfman::SurfaceType;
|
||||||
use surfman_chains::SurfmanProvider;
|
|
||||||
use surfman_chains::SwapChain;
|
use surfman_chains::SwapChain;
|
||||||
use surfman_chains_api::SwapChainAPI;
|
use surfman_chains_api::SwapChainAPI;
|
||||||
|
|
||||||
// For the moment, we only support wayland and cgl.
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
use surfman::platform::macos::cgl::device::Device;
|
|
||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
|
||||||
use surfman::platform::unix::wayland::device::Device;
|
|
||||||
|
|
||||||
type Context = <Device as DeviceAPI>::Context;
|
|
||||||
type Connection = <Device as DeviceAPI>::Connection;
|
|
||||||
type NativeContext = <Device as DeviceAPI>::NativeContext;
|
|
||||||
type NativeConnection = <Connection as ConnectionAPI>::NativeConnection;
|
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
@ -165,7 +150,7 @@ impl std::fmt::Debug for ConnectionWhichImplementsDebug {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum ServoWebSrcMsg {
|
enum ServoWebSrcMsg {
|
||||||
Start(ConnectionWhichImplementsDebug, GLVersion, ServoUrl),
|
Start(ConnectionWhichImplementsDebug, ServoUrl),
|
||||||
GetSwapChain(Sender<SwapChain<Device>>),
|
GetSwapChain(Sender<SwapChain<Device>>),
|
||||||
Resize(Size2D<i32, DevicePixel>),
|
Resize(Size2D<i32, DevicePixel>),
|
||||||
Heartbeat,
|
Heartbeat,
|
||||||
|
@ -180,41 +165,25 @@ const DEFAULT_FRAME_DURATION: Duration = Duration::from_micros(16_667);
|
||||||
|
|
||||||
struct ServoThread {
|
struct ServoThread {
|
||||||
receiver: Receiver<ServoWebSrcMsg>,
|
receiver: Receiver<ServoWebSrcMsg>,
|
||||||
swap_chain: SwapChain<Device>,
|
|
||||||
gfx: Rc<RefCell<ServoThreadGfx>>,
|
|
||||||
servo: Servo<ServoWebSrcWindow>,
|
servo: Servo<ServoWebSrcWindow>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ServoThreadGfx {
|
|
||||||
device: Device,
|
|
||||||
context: Context,
|
|
||||||
gl: Rc<Gl>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ServoThread {
|
impl ServoThread {
|
||||||
fn new(receiver: Receiver<ServoWebSrcMsg>) -> Self {
|
fn new(receiver: Receiver<ServoWebSrcMsg>) -> Self {
|
||||||
let (connection, version, url) = match receiver.recv() {
|
let (connection, url) = match receiver.recv() {
|
||||||
Ok(ServoWebSrcMsg::Start(connection, version, url)) => (connection.0, version, url),
|
Ok(ServoWebSrcMsg::Start(connection, url)) => (connection.0, url),
|
||||||
e => panic!("Failed to start ({:?})", e),
|
e => panic!("Failed to start ({:?})", e),
|
||||||
};
|
};
|
||||||
info!(
|
info!("Created new servo thread for {}", url);
|
||||||
"Created new servo thread (GL v{}.{} for {})",
|
|
||||||
version.major, version.minor, url
|
|
||||||
);
|
|
||||||
let embedder = Box::new(ServoWebSrcEmbedder);
|
let embedder = Box::new(ServoWebSrcEmbedder);
|
||||||
let window = Rc::new(ServoWebSrcWindow::new(connection, version));
|
let window = Rc::new(ServoWebSrcWindow::new(connection));
|
||||||
let swap_chain = window.swap_chain.clone();
|
|
||||||
let gfx = window.gfx.clone();
|
|
||||||
let mut servo = Servo::new(embedder, window, None);
|
let mut servo = Servo::new(embedder, window, None);
|
||||||
|
|
||||||
let id = TopLevelBrowsingContextId::new();
|
let id = TopLevelBrowsingContextId::new();
|
||||||
servo.handle_events(vec![WindowEvent::NewBrowser(url, id)]);
|
servo.handle_events(vec![WindowEvent::NewBrowser(url, id)]);
|
||||||
|
|
||||||
Self {
|
Self { receiver, servo }
|
||||||
receiver,
|
|
||||||
swap_chain,
|
|
||||||
gfx,
|
|
||||||
servo,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&mut self) {
|
fn run(&mut self) {
|
||||||
|
@ -222,9 +191,7 @@ impl ServoThread {
|
||||||
debug!("Servo thread handling message {:?}", msg);
|
debug!("Servo thread handling message {:?}", msg);
|
||||||
match msg {
|
match msg {
|
||||||
ServoWebSrcMsg::Start(..) => error!("Already started"),
|
ServoWebSrcMsg::Start(..) => error!("Already started"),
|
||||||
ServoWebSrcMsg::GetSwapChain(sender) => sender
|
ServoWebSrcMsg::GetSwapChain(sender) => self.send_swap_chain(sender),
|
||||||
.send(self.swap_chain.clone())
|
|
||||||
.expect("Failed to send swap chain"),
|
|
||||||
ServoWebSrcMsg::Resize(size) => self.resize(size),
|
ServoWebSrcMsg::Resize(size) => self.resize(size),
|
||||||
ServoWebSrcMsg::Heartbeat => self.servo.handle_events(vec![]),
|
ServoWebSrcMsg::Heartbeat => self.servo.handle_events(vec![]),
|
||||||
ServoWebSrcMsg::Stop => break,
|
ServoWebSrcMsg::Stop => break,
|
||||||
|
@ -233,43 +200,24 @@ impl ServoThread {
|
||||||
self.servo.handle_events(vec![WindowEvent::Quit]);
|
self.servo.handle_events(vec![WindowEvent::Quit]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&mut self, size: Size2D<i32, DevicePixel>) {
|
fn send_swap_chain(&mut self, sender: Sender<SwapChain<Device>>) {
|
||||||
{
|
let swap_chain = self
|
||||||
let mut gfx = self.gfx.borrow_mut();
|
.servo
|
||||||
let gfx = &mut *gfx;
|
.window()
|
||||||
self.swap_chain
|
.webrender_surfman
|
||||||
.resize(&mut gfx.device, &mut gfx.context, size.to_untyped())
|
.swap_chain()
|
||||||
.expect("Failed to resize");
|
.expect("Failed to get swap chain")
|
||||||
gfx.gl.viewport(0, 0, size.width, size.height);
|
.clone();
|
||||||
let fbo = gfx
|
sender.send(swap_chain).expect("Failed to send swap chain");
|
||||||
.device
|
|
||||||
.context_surface_info(&gfx.context)
|
|
||||||
.expect("Failed to get context info")
|
|
||||||
.expect("Failed to get context info")
|
|
||||||
.framebuffer_object;
|
|
||||||
gfx.device
|
|
||||||
.make_context_current(&gfx.context)
|
|
||||||
.expect("Failed to make current");
|
|
||||||
gfx.gl.bind_framebuffer(gl::FRAMEBUFFER, fbo);
|
|
||||||
debug_assert_eq!(
|
|
||||||
(
|
|
||||||
gfx.gl.check_framebuffer_status(gl::FRAMEBUFFER),
|
|
||||||
gfx.gl.get_error()
|
|
||||||
),
|
|
||||||
(gl::FRAMEBUFFER_COMPLETE, gl::NO_ERROR)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
self.servo.handle_events(vec![WindowEvent::Resize]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for ServoThread {
|
fn resize(&mut self, size: Size2D<i32, DevicePixel>) {
|
||||||
fn drop(&mut self) {
|
let _ = self
|
||||||
let mut gfx = self.gfx.borrow_mut();
|
.servo
|
||||||
let gfx = &mut *gfx;
|
.window()
|
||||||
self.swap_chain
|
.webrender_surfman
|
||||||
.destroy(&mut gfx.device, &mut gfx.context)
|
.resize(size.to_untyped());
|
||||||
.expect("Failed to destroy swap chain")
|
self.servo.handle_events(vec![WindowEvent::Resize]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,154 +238,35 @@ impl EventLoopWaker for ServoWebSrcEmbedder {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ServoWebSrcWindow {
|
struct ServoWebSrcWindow {
|
||||||
swap_chain: SwapChain<Device>,
|
webrender_surfman: WebrenderSurfman,
|
||||||
gfx: Rc<RefCell<ServoThreadGfx>>,
|
|
||||||
gl: Rc<dyn gleam::gl::Gl>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServoWebSrcWindow {
|
impl ServoWebSrcWindow {
|
||||||
fn new(connection: Connection, version: GLVersion) -> Self {
|
fn new(connection: Connection) -> Self {
|
||||||
let flags = ContextAttributeFlags::DEPTH |
|
|
||||||
ContextAttributeFlags::STENCIL |
|
|
||||||
ContextAttributeFlags::ALPHA;
|
|
||||||
let attributes = ContextAttributes { version, flags };
|
|
||||||
|
|
||||||
let adapter = connection
|
let adapter = connection
|
||||||
.create_adapter()
|
.create_adapter()
|
||||||
.expect("Failed to create adapter");
|
.expect("Failed to create adapter");
|
||||||
let mut device = connection
|
|
||||||
.create_device(&adapter)
|
|
||||||
.expect("Failed to create device");
|
|
||||||
let descriptor = device
|
|
||||||
.create_context_descriptor(&attributes)
|
|
||||||
.expect("Failed to create descriptor");
|
|
||||||
let mut context = device
|
|
||||||
.create_context(&descriptor)
|
|
||||||
.expect("Failed to create context");
|
|
||||||
|
|
||||||
let (gleam, gl) = unsafe {
|
|
||||||
match device.gl_api() {
|
|
||||||
GLApi::GL => (
|
|
||||||
gleam::gl::GlFns::load_with(|s| device.get_proc_address(&context, s)),
|
|
||||||
Gl::gl_fns(gl::ffi_gl::Gl::load_with(|s| {
|
|
||||||
device.get_proc_address(&context, s)
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
GLApi::GLES => (
|
|
||||||
gleam::gl::GlesFns::load_with(|s| device.get_proc_address(&context, s)),
|
|
||||||
Gl::gles_fns(gl::ffi_gles::Gles2::load_with(|s| {
|
|
||||||
device.get_proc_address(&context, s)
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
device
|
|
||||||
.make_context_current(&mut context)
|
|
||||||
.expect("Failed to make context current");
|
|
||||||
debug_assert_eq!(gl.get_error(), gl::NO_ERROR);
|
|
||||||
let access = SurfaceAccess::GPUOnly;
|
|
||||||
let size = Size2D::new(512, 512);
|
let size = Size2D::new(512, 512);
|
||||||
let surface_type = SurfaceType::Generic { size };
|
let surface_type = SurfaceType::Generic { size };
|
||||||
let surface = device
|
let webrender_surfman = WebrenderSurfman::create(&connection, &adapter, surface_type)
|
||||||
.create_surface(&mut context, access, surface_type)
|
.expect("Failed to create surfman");
|
||||||
.expect("Failed to create surface");
|
|
||||||
|
|
||||||
device
|
Self { webrender_surfman }
|
||||||
.bind_surface_to_context(&mut context, surface)
|
|
||||||
.expect("Failed to bind surface");
|
|
||||||
let fbo = device
|
|
||||||
.context_surface_info(&context)
|
|
||||||
.expect("Failed to get context info")
|
|
||||||
.expect("Failed to get context info")
|
|
||||||
.framebuffer_object;
|
|
||||||
gl.viewport(0, 0, size.width, size.height);
|
|
||||||
gl.bind_framebuffer(gl::FRAMEBUFFER, fbo);
|
|
||||||
gl.clear_color(0.0, 0.0, 0.0, 1.0);
|
|
||||||
gl.clear(gl::COLOR_BUFFER_BIT);
|
|
||||||
debug_assert_eq!(
|
|
||||||
(gl.check_framebuffer_status(gl::FRAMEBUFFER), gl.get_error()),
|
|
||||||
(gl::FRAMEBUFFER_COMPLETE, gl::NO_ERROR)
|
|
||||||
);
|
|
||||||
|
|
||||||
let provider = Box::new(SurfmanProvider::new(access));
|
|
||||||
let swap_chain = SwapChain::create_attached(&mut device, &mut context, provider)
|
|
||||||
.expect("Failed to create swap chain");
|
|
||||||
|
|
||||||
device.make_no_context_current().unwrap();
|
|
||||||
|
|
||||||
let gfx = Rc::new(RefCell::new(ServoThreadGfx {
|
|
||||||
device,
|
|
||||||
context,
|
|
||||||
gl,
|
|
||||||
}));
|
|
||||||
|
|
||||||
Self {
|
|
||||||
swap_chain,
|
|
||||||
gfx,
|
|
||||||
gl: gleam,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowMethods for ServoWebSrcWindow {
|
impl WindowMethods for ServoWebSrcWindow {
|
||||||
fn present(&self) {
|
fn webrender_surfman(&self) -> WebrenderSurfman {
|
||||||
debug!("EMBEDDER present");
|
self.webrender_surfman.clone()
|
||||||
let mut gfx = self.gfx.borrow_mut();
|
|
||||||
let gfx = &mut *gfx;
|
|
||||||
gfx.device
|
|
||||||
.make_context_current(&mut gfx.context)
|
|
||||||
.expect("Failed to make context current");
|
|
||||||
debug_assert_eq!(
|
|
||||||
(
|
|
||||||
gfx.gl.check_framebuffer_status(gl::FRAMEBUFFER),
|
|
||||||
gfx.gl.get_error()
|
|
||||||
),
|
|
||||||
(gl::FRAMEBUFFER_COMPLETE, gl::NO_ERROR)
|
|
||||||
);
|
|
||||||
self.swap_chain
|
|
||||||
.swap_buffers(&mut gfx.device, &mut gfx.context)
|
|
||||||
.expect("Failed to swap buffers");
|
|
||||||
let fbo = gfx
|
|
||||||
.device
|
|
||||||
.context_surface_info(&gfx.context)
|
|
||||||
.expect("Failed to get context info")
|
|
||||||
.expect("Failed to get context info")
|
|
||||||
.framebuffer_object;
|
|
||||||
gfx.gl.bind_framebuffer(gl::FRAMEBUFFER, fbo);
|
|
||||||
debug_assert_eq!(
|
|
||||||
(
|
|
||||||
gfx.gl.check_framebuffer_status(gl::FRAMEBUFFER),
|
|
||||||
gfx.gl.get_error()
|
|
||||||
),
|
|
||||||
(gl::FRAMEBUFFER_COMPLETE, gl::NO_ERROR)
|
|
||||||
);
|
|
||||||
let _ = gfx.device.make_no_context_current();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_gl_context_current(&self) {
|
|
||||||
debug!("EMBEDDER make_context_current");
|
|
||||||
let mut gfx = self.gfx.borrow_mut();
|
|
||||||
let gfx = &mut *gfx;
|
|
||||||
gfx.device
|
|
||||||
.make_context_current(&mut gfx.context)
|
|
||||||
.expect("Failed to make context current");
|
|
||||||
debug!("EMBEDDER done make_context_current");
|
|
||||||
debug_assert_eq!(
|
|
||||||
(
|
|
||||||
gfx.gl.check_framebuffer_status(gl::FRAMEBUFFER),
|
|
||||||
gfx.gl.get_error()
|
|
||||||
),
|
|
||||||
(gl::FRAMEBUFFER_COMPLETE, gl::NO_ERROR)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gl(&self) -> Rc<dyn gleam::gl::Gl> {
|
|
||||||
self.gl.clone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_coordinates(&self) -> EmbedderCoordinates {
|
fn get_coordinates(&self) -> EmbedderCoordinates {
|
||||||
let size = Size2D::from_untyped(self.swap_chain.size());
|
let size = self
|
||||||
|
.webrender_surfman
|
||||||
|
.context_surface_info()
|
||||||
|
.unwrap_or(None)
|
||||||
|
.map(|info| Size2D::from_untyped(info.size))
|
||||||
|
.unwrap_or(Size2D::new(0, 0));
|
||||||
info!("EMBEDDER coordinates {}", size);
|
info!("EMBEDDER coordinates {}", size);
|
||||||
let origin = Point2D::origin();
|
let origin = Point2D::origin();
|
||||||
EmbedderCoordinates {
|
EmbedderCoordinates {
|
||||||
|
@ -658,11 +487,6 @@ impl BaseSrcImpl for ServoWebSrc {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let gl_context = unsafe { GLContext::from_glib_borrow(gst_gl_context) };
|
let gl_context = unsafe { GLContext::from_glib_borrow(gst_gl_context) };
|
||||||
let gl_version = gl_context.get_gl_version();
|
|
||||||
let version = GLVersion {
|
|
||||||
major: gl_version.0 as u8,
|
|
||||||
minor: gl_version.1 as u8,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the surfman connection on the GL thread
|
// Get the surfman connection on the GL thread
|
||||||
let mut task = BootstrapSurfmanOnGLThread {
|
let mut task = BootstrapSurfmanOnGLThread {
|
||||||
|
@ -683,7 +507,6 @@ impl BaseSrcImpl for ServoWebSrc {
|
||||||
// Inform servo we're starting
|
// Inform servo we're starting
|
||||||
let _ = self.sender.send(ServoWebSrcMsg::Start(
|
let _ = self.sender.send(ServoWebSrcMsg::Start(
|
||||||
ConnectionWhichImplementsDebug(connection),
|
ConnectionWhichImplementsDebug(connection),
|
||||||
version,
|
|
||||||
url,
|
url,
|
||||||
));
|
));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -784,6 +607,26 @@ impl ServoWebSrc {
|
||||||
gl_context
|
gl_context
|
||||||
.activate(true)
|
.activate(true)
|
||||||
.expect("Failed to activate GL context");
|
.expect("Failed to activate GL context");
|
||||||
|
// TODO: support other connections on linux?
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
use surfman::platform::generic::multi;
|
||||||
|
use surfman::platform::unix::wayland;
|
||||||
|
let native_connection = wayland::connection::NativeConnection::current()
|
||||||
|
.expect("Failed to bootstrap native connection");
|
||||||
|
let wayland_connection = unsafe {
|
||||||
|
wayland::connection::Connection::from_native_connection(native_connection)
|
||||||
|
.expect("Failed to bootstrap wayland connection")
|
||||||
|
};
|
||||||
|
let connection = multi::connection::Connection::Default(
|
||||||
|
multi::connection::Connection::Default(wayland_connection),
|
||||||
|
);
|
||||||
|
Some(connection)
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
{
|
||||||
|
use surfman::connection::Connection as ConnectionAPI;
|
||||||
|
type NativeConnection = <Connection as ConnectionAPI>::NativeConnection;
|
||||||
let native_connection =
|
let native_connection =
|
||||||
NativeConnection::current().expect("Failed to bootstrap native connection");
|
NativeConnection::current().expect("Failed to bootstrap native connection");
|
||||||
let connection = unsafe { Connection::from_native_connection(native_connection) }
|
let connection = unsafe { Connection::from_native_connection(native_connection) }
|
||||||
|
@ -791,6 +634,7 @@ impl ServoWebSrc {
|
||||||
Some(connection)
|
Some(connection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct FillOnGLThread<'a> {
|
struct FillOnGLThread<'a> {
|
||||||
servo_web_src: &'a ServoWebSrc,
|
servo_web_src: &'a ServoWebSrc,
|
||||||
|
@ -840,8 +684,21 @@ impl ServoWebSrc {
|
||||||
let device = connection
|
let device = connection
|
||||||
.create_device(&adapter)
|
.create_device(&adapter)
|
||||||
.expect("Failed to bootstrap surfman device");
|
.expect("Failed to bootstrap surfman device");
|
||||||
let native_context =
|
#[cfg(target_os = "linux")]
|
||||||
NativeContext::current().expect("Failed to bootstrap native context");
|
let native_context = {
|
||||||
|
use surfman::platform::generic::multi;
|
||||||
|
use surfman::platform::unix::wayland;
|
||||||
|
multi::context::NativeContext::Default(multi::context::NativeContext::Default(
|
||||||
|
wayland::context::NativeContext::current()
|
||||||
|
.expect("Failed to bootstrap native context"),
|
||||||
|
))
|
||||||
|
};
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
let native_context = {
|
||||||
|
use surfman::device::Device as DeviceAPI;
|
||||||
|
type NativeContext = <Device as DeviceAPI>::NativeContext;
|
||||||
|
NativeContext::current().expect("Failed to bootstrap native context")
|
||||||
|
};
|
||||||
let context = unsafe {
|
let context = unsafe {
|
||||||
device
|
device
|
||||||
.create_context_from_native_context(native_context)
|
.create_context_from_native_context(native_context)
|
||||||
|
@ -995,5 +852,3 @@ impl ServoWebSrc {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement that trait for more platforms
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ ipc-channel = "0.14"
|
||||||
libservo = { path = "../../../components/servo" }
|
libservo = { path = "../../../components/servo" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
servo-media = { git = "https://github.com/servo/media" }
|
servo-media = { git = "https://github.com/servo/media" }
|
||||||
|
surfman = { version = "0.2", features = ["sm-angle-default"] }
|
||||||
|
|
||||||
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
|
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
|
||||||
webxr = { git = "https://github.com/servo/webxr"}
|
webxr = { git = "https://github.com/servo/webxr"}
|
||||||
|
|
|
@ -32,6 +32,7 @@ use servo::servo_config::{pref, set_pref};
|
||||||
use servo::servo_url::ServoUrl;
|
use servo::servo_url::ServoUrl;
|
||||||
use servo::webrender_api::units::DevicePixel;
|
use servo::webrender_api::units::DevicePixel;
|
||||||
use servo::webrender_api::ScrollLocation;
|
use servo::webrender_api::ScrollLocation;
|
||||||
|
use servo::webrender_surfman::WebrenderSurfman;
|
||||||
use servo::{self, gl, BrowserId, Servo};
|
use servo::{self, gl, BrowserId, Servo};
|
||||||
use servo_media::player::context as MediaPlayerContext;
|
use servo_media::player::context as MediaPlayerContext;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -39,6 +40,8 @@ use std::mem;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use surfman::Connection;
|
||||||
|
use surfman::SurfaceType;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
pub static SERVO: RefCell<Option<ServoGlue>> = RefCell::new(None);
|
pub static SERVO: RefCell<Option<ServoGlue>> = RefCell::new(None);
|
||||||
|
@ -58,6 +61,7 @@ pub struct InitOptions {
|
||||||
pub enable_subpixel_text_antialiasing: bool,
|
pub enable_subpixel_text_antialiasing: bool,
|
||||||
pub gl_context_pointer: Option<*const c_void>,
|
pub gl_context_pointer: Option<*const c_void>,
|
||||||
pub native_display_pointer: Option<*const c_void>,
|
pub native_display_pointer: Option<*const c_void>,
|
||||||
|
pub native_widget: *mut c_void,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -84,12 +88,6 @@ impl Coordinates {
|
||||||
|
|
||||||
/// Callbacks. Implemented by embedder. Called by Servo.
|
/// Callbacks. Implemented by embedder. Called by Servo.
|
||||||
pub trait HostTrait {
|
pub trait HostTrait {
|
||||||
/// Will be called from the thread used for the init call.
|
|
||||||
/// Will be called when the GL buffer has been updated.
|
|
||||||
fn flush(&self);
|
|
||||||
/// Will be called before drawing.
|
|
||||||
/// Time to make the targetted GL context current.
|
|
||||||
fn make_current(&self);
|
|
||||||
/// Show alert.
|
/// Show alert.
|
||||||
fn prompt_alert(&self, msg: String, trusted: bool);
|
fn prompt_alert(&self, msg: String, trusted: bool);
|
||||||
/// Ask Yes/No question.
|
/// Ask Yes/No question.
|
||||||
|
@ -211,13 +209,28 @@ pub fn init(
|
||||||
gl.clear(gl::COLOR_BUFFER_BIT);
|
gl.clear(gl::COLOR_BUFFER_BIT);
|
||||||
gl.finish();
|
gl.finish();
|
||||||
|
|
||||||
|
// Initialize surfman
|
||||||
|
let connection = Connection::new().or(Err("Failed to create connection"))?;
|
||||||
|
let adapter = connection
|
||||||
|
.create_adapter()
|
||||||
|
.or(Err("Failed to create adapter"))?;
|
||||||
|
let native_widget = unsafe {
|
||||||
|
connection.create_native_widget_from_ptr(
|
||||||
|
init_opts.native_widget,
|
||||||
|
init_opts.coordinates.framebuffer.to_untyped(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let surface_type = SurfaceType::Widget { native_widget };
|
||||||
|
let webrender_surfman = WebrenderSurfman::create(&connection, &adapter, surface_type)
|
||||||
|
.or(Err("Failed to create surface manager"))?;
|
||||||
|
|
||||||
let window_callbacks = Rc::new(ServoWindowCallbacks {
|
let window_callbacks = Rc::new(ServoWindowCallbacks {
|
||||||
host_callbacks: callbacks,
|
host_callbacks: callbacks,
|
||||||
gl: gl.clone(),
|
|
||||||
coordinates: RefCell::new(init_opts.coordinates),
|
coordinates: RefCell::new(init_opts.coordinates),
|
||||||
density: init_opts.density,
|
density: init_opts.density,
|
||||||
gl_context_pointer: init_opts.gl_context_pointer,
|
gl_context_pointer: init_opts.gl_context_pointer,
|
||||||
native_display_pointer: init_opts.native_display_pointer,
|
native_display_pointer: init_opts.native_display_pointer,
|
||||||
|
webrender_surfman,
|
||||||
});
|
});
|
||||||
|
|
||||||
let embedder_callbacks = Box::new(ServoEmbedderCallbacks {
|
let embedder_callbacks = Box::new(ServoEmbedderCallbacks {
|
||||||
|
@ -723,12 +736,12 @@ struct ServoEmbedderCallbacks {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ServoWindowCallbacks {
|
struct ServoWindowCallbacks {
|
||||||
gl: Rc<dyn gl::Gl>,
|
|
||||||
host_callbacks: Box<dyn HostTrait>,
|
host_callbacks: Box<dyn HostTrait>,
|
||||||
coordinates: RefCell<Coordinates>,
|
coordinates: RefCell<Coordinates>,
|
||||||
density: f32,
|
density: f32,
|
||||||
gl_context_pointer: Option<*const c_void>,
|
gl_context_pointer: Option<*const c_void>,
|
||||||
native_display_pointer: Option<*const c_void>,
|
native_display_pointer: Option<*const c_void>,
|
||||||
|
webrender_surfman: WebrenderSurfman,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmbedderMethods for ServoEmbedderCallbacks {
|
impl EmbedderMethods for ServoEmbedderCallbacks {
|
||||||
|
@ -798,7 +811,7 @@ impl EmbedderMethods for ServoEmbedderCallbacks {
|
||||||
|
|
||||||
struct GlThread(WebGlExecutor);
|
struct GlThread(WebGlExecutor);
|
||||||
impl webxr::openxr::GlThread for GlThread {
|
impl webxr::openxr::GlThread for GlThread {
|
||||||
fn execute(&self, runnable: Box<dyn FnOnce() + Send>) {
|
fn execute(&self, runnable: Box<dyn FnOnce(&surfman::Device) + Send>) {
|
||||||
let _ = self.0.send(runnable);
|
let _ = self.0.send(runnable);
|
||||||
}
|
}
|
||||||
fn clone(&self) -> Box<dyn webxr::openxr::GlThread> {
|
fn clone(&self) -> Box<dyn webxr::openxr::GlThread> {
|
||||||
|
@ -835,19 +848,8 @@ impl EmbedderMethods for ServoEmbedderCallbacks {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowMethods for ServoWindowCallbacks {
|
impl WindowMethods for ServoWindowCallbacks {
|
||||||
fn make_gl_context_current(&self) {
|
fn webrender_surfman(&self) -> WebrenderSurfman {
|
||||||
debug!("WindowMethods::prepare_for_composite");
|
self.webrender_surfman.clone()
|
||||||
self.host_callbacks.make_current();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn present(&self) {
|
|
||||||
debug!("WindowMethods::present");
|
|
||||||
self.host_callbacks.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gl(&self) -> Rc<dyn gl::Gl> {
|
|
||||||
debug!("WindowMethods::gl");
|
|
||||||
self.gl.clone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_animation_state(&self, state: AnimationState) {
|
fn set_animation_state(&self, state: AnimationState) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ log = "0.4"
|
||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
env_logger = "0.7"
|
env_logger = "0.7"
|
||||||
backtrace = "0.3"
|
backtrace = "0.3"
|
||||||
|
surfman = "0.2"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|
|
@ -203,8 +203,6 @@ where
|
||||||
/// Callback used by Servo internals
|
/// Callback used by Servo internals
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct CHostCallbacks {
|
pub struct CHostCallbacks {
|
||||||
pub flush: extern "C" fn(),
|
|
||||||
pub make_current: extern "C" fn(),
|
|
||||||
pub on_load_started: extern "C" fn(),
|
pub on_load_started: extern "C" fn(),
|
||||||
pub on_load_ended: extern "C" fn(),
|
pub on_load_ended: extern "C" fn(),
|
||||||
pub on_title_changed: extern "C" fn(title: *const c_char),
|
pub on_title_changed: extern "C" fn(title: *const c_char),
|
||||||
|
@ -245,6 +243,7 @@ pub struct CInitOptions {
|
||||||
pub enable_subpixel_text_antialiasing: bool,
|
pub enable_subpixel_text_antialiasing: bool,
|
||||||
pub vslogger_mod_list: *const *const c_char,
|
pub vslogger_mod_list: *const *const c_char,
|
||||||
pub vslogger_mod_size: u32,
|
pub vslogger_mod_size: u32,
|
||||||
|
pub native_widget: *mut c_void,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -442,6 +441,7 @@ unsafe fn init(
|
||||||
enable_subpixel_text_antialiasing: opts.enable_subpixel_text_antialiasing,
|
enable_subpixel_text_antialiasing: opts.enable_subpixel_text_antialiasing,
|
||||||
gl_context_pointer: gl_context,
|
gl_context_pointer: gl_context,
|
||||||
native_display_pointer: display,
|
native_display_pointer: display,
|
||||||
|
native_widget: opts.native_widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
let wakeup = Box::new(WakeupCallback::new(wakeup));
|
let wakeup = Box::new(WakeupCallback::new(wakeup));
|
||||||
|
@ -750,16 +750,6 @@ impl HostCallbacks {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HostTrait for HostCallbacks {
|
impl HostTrait for HostCallbacks {
|
||||||
fn flush(&self) {
|
|
||||||
debug!("flush");
|
|
||||||
(self.0.flush)();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_current(&self) {
|
|
||||||
debug!("make_current");
|
|
||||||
(self.0.make_current)();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_load_started(&self) {
|
fn on_load_started(&self) {
|
||||||
debug!("on_load_started");
|
debug!("on_load_started");
|
||||||
(self.0.on_load_started)();
|
(self.0.on_load_started)();
|
||||||
|
|
|
@ -223,34 +223,6 @@ def append_to_path_env(string, env, name):
|
||||||
env[name] = variable
|
env[name] = variable
|
||||||
|
|
||||||
|
|
||||||
def set_osmesa_env(bin_path, env, show_vars):
|
|
||||||
"""Set proper LD_LIBRARY_PATH and DRIVE for software rendering on Linux and OSX"""
|
|
||||||
if is_linux():
|
|
||||||
dep_path = find_dep_path_newest('osmesa-src', bin_path)
|
|
||||||
if not dep_path:
|
|
||||||
return None
|
|
||||||
osmesa_path = path.join(dep_path, "out", "lib", "gallium")
|
|
||||||
append_to_path_env(osmesa_path, env, "LD_LIBRARY_PATH")
|
|
||||||
env["GALLIUM_DRIVER"] = "softpipe"
|
|
||||||
if show_vars:
|
|
||||||
print("GALLIUM_DRIVER=" + env["GALLIUM_DRIVER"])
|
|
||||||
print("LD_LIBRARY_PATH=" + env["LD_LIBRARY_PATH"])
|
|
||||||
elif is_macosx():
|
|
||||||
osmesa_dep_path = find_dep_path_newest('osmesa-src', bin_path)
|
|
||||||
if not osmesa_dep_path:
|
|
||||||
return None
|
|
||||||
osmesa_path = path.join(osmesa_dep_path,
|
|
||||||
"out", "src", "gallium", "targets", "osmesa", ".libs")
|
|
||||||
glapi_path = path.join(osmesa_dep_path,
|
|
||||||
"out", "src", "mapi", "shared-glapi", ".libs")
|
|
||||||
append_to_path_env(osmesa_path + ":" + glapi_path, env, "DYLD_LIBRARY_PATH")
|
|
||||||
env["GALLIUM_DRIVER"] = "softpipe"
|
|
||||||
if show_vars:
|
|
||||||
print("GALLIUM_DRIVER=" + env["GALLIUM_DRIVER"])
|
|
||||||
print("DYLD_LIBRARY_PATH=" + env["DYLD_LIBRARY_PATH"])
|
|
||||||
return env
|
|
||||||
|
|
||||||
|
|
||||||
def gstreamer_root(target, env, topdir=None):
|
def gstreamer_root(target, env, topdir=None):
|
||||||
if is_windows():
|
if is_windows():
|
||||||
arch = {
|
arch = {
|
||||||
|
|
|
@ -24,7 +24,7 @@ from mach.decorators import (
|
||||||
from servo.command_base import (
|
from servo.command_base import (
|
||||||
CommandBase,
|
CommandBase,
|
||||||
check_call, check_output, BIN_SUFFIX,
|
check_call, check_output, BIN_SUFFIX,
|
||||||
is_linux, set_osmesa_env,
|
is_linux,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,7 +126,6 @@ class PostBuildCommands(CommandBase):
|
||||||
args = [bin or self.get_nightly_binary_path(nightly) or self.get_binary_path(release, dev)]
|
args = [bin or self.get_nightly_binary_path(nightly) or self.get_binary_path(release, dev)]
|
||||||
|
|
||||||
if headless:
|
if headless:
|
||||||
set_osmesa_env(args[0], env, debugger is not None)
|
|
||||||
args.append('-z')
|
args.append('-z')
|
||||||
|
|
||||||
if software:
|
if software:
|
||||||
|
|
|
@ -33,8 +33,8 @@ from mach.decorators import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from servo.command_base import (
|
from servo.command_base import (
|
||||||
BuildNotFound, CommandBase,
|
CommandBase,
|
||||||
call, check_call, check_output, set_osmesa_env,
|
call, check_call, check_output,
|
||||||
)
|
)
|
||||||
from servo.util import host_triple
|
from servo.util import host_triple
|
||||||
|
|
||||||
|
@ -197,8 +197,6 @@ class MachCommands(CommandBase):
|
||||||
@CommandArgument('--submit', '-a', default=False, action="store_true",
|
@CommandArgument('--submit', '-a', default=False, action="store_true",
|
||||||
help="submit the data to perfherder")
|
help="submit the data to perfherder")
|
||||||
def test_perf(self, base=None, date=None, submit=False):
|
def test_perf(self, base=None, date=None, submit=False):
|
||||||
self.set_software_rendering_env(True, False)
|
|
||||||
|
|
||||||
env = self.build_env()
|
env = self.build_env()
|
||||||
cmd = ["bash", "test_perf.sh"]
|
cmd = ["bash", "test_perf.sh"]
|
||||||
if base:
|
if base:
|
||||||
|
@ -441,8 +439,6 @@ class MachCommands(CommandBase):
|
||||||
|
|
||||||
# Helper for test_css and test_wpt:
|
# Helper for test_css and test_wpt:
|
||||||
def wptrunner(self, run_file, **kwargs):
|
def wptrunner(self, run_file, **kwargs):
|
||||||
self.set_software_rendering_env(kwargs['release'], kwargs['debugger'])
|
|
||||||
|
|
||||||
# By default, Rayon selects the number of worker threads
|
# By default, Rayon selects the number of worker threads
|
||||||
# based on the available CPU count. This doesn't work very
|
# based on the available CPU count. This doesn't work very
|
||||||
# well when running tests on CI, since we run so many
|
# well when running tests on CI, since we run so many
|
||||||
|
@ -753,18 +749,6 @@ class MachCommands(CommandBase):
|
||||||
return check_call(
|
return check_call(
|
||||||
[run_file, "|".join(tests), bin_path, base_dir])
|
[run_file, "|".join(tests), bin_path, base_dir])
|
||||||
|
|
||||||
def set_software_rendering_env(self, use_release, show_vars):
|
|
||||||
# On Linux and mac, find the OSMesa software rendering library and
|
|
||||||
# add it to the dynamic linker search path.
|
|
||||||
try:
|
|
||||||
bin_path = self.get_binary_path(use_release, not use_release)
|
|
||||||
if not set_osmesa_env(bin_path, os.environ, show_vars):
|
|
||||||
print("Warning: Cannot set the path to OSMesa library.")
|
|
||||||
except BuildNotFound:
|
|
||||||
# This can occur when cross compiling (e.g. arm64), in which case
|
|
||||||
# we won't run the tests anyway so can safely ignore this step.
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def setup_clangfmt(env):
|
def setup_clangfmt(env):
|
||||||
cmd = "clang-format.exe" if sys.platform == "win32" else "clang-format"
|
cmd = "clang-format.exe" if sys.platform == "win32" else "clang-format"
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
"dom.webxr.test": false,
|
"dom.webxr.test": false,
|
||||||
"dom.worklet.timeout_ms": 10,
|
"dom.worklet.timeout_ms": 10,
|
||||||
"gfx.subpixel-text-antialiasing.enabled": true,
|
"gfx.subpixel-text-antialiasing.enabled": true,
|
||||||
|
"gfx.texture-swizzling.enabled": true,
|
||||||
"js.asmjs.enabled": true,
|
"js.asmjs.enabled": true,
|
||||||
"js.asyncstack.enabled": false,
|
"js.asyncstack.enabled": false,
|
||||||
"js.baseline.enabled": true,
|
"js.baseline.enabled": true,
|
||||||
|
|
|
@ -48,10 +48,6 @@ packages = [
|
||||||
"quote",
|
"quote",
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
|
|
||||||
# These can be removed once servo is updated to surfman 0.2
|
|
||||||
"surfman",
|
|
||||||
"surfman-chains",
|
|
||||||
|
|
||||||
# https://github.com/servo/servo/pull/25518
|
# https://github.com/servo/servo/pull/25518
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
|
|
|
@ -947,7 +947,7 @@
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||||
<Import Project="..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.targets" Condition="Exists('..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.targets')" />
|
<Import Project="..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.targets" Condition="Exists('..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.targets')" />
|
||||||
<Import Project="..\packages\ANGLE.WindowsStore.Servo.2.1.16\build\native\ANGLE.WindowsStore.Servo.targets" Condition="Exists('..\packages\ANGLE.WindowsStore.Servo.2.1.16\build\native\ANGLE.WindowsStore.Servo.targets')" />
|
<Import Project="..\packages\ANGLE.WindowsStore.Servo.2.1.19\build\native\ANGLE.WindowsStore.Servo.targets" Condition="Exists('..\packages\ANGLE.WindowsStore.Servo.2.1.19\build\native\ANGLE.WindowsStore.Servo.targets')" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
@ -957,6 +957,6 @@
|
||||||
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||||
<Error Condition="!Exists('..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.props'))" />
|
<Error Condition="!Exists('..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.props'))" />
|
||||||
<Error Condition="!Exists('..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.targets'))" />
|
<Error Condition="!Exists('..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\OpenXR.Loader.1.0.3\build\native\OpenXR.Loader.targets'))" />
|
||||||
<Error Condition="!Exists('..\packages\ANGLE.WindowsStore.Servo.2.1.16\build\native\ANGLE.WindowsStore.Servo.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ANGLE.WindowsStore.Servo.2.1.16\build\native\ANGLE.WindowsStore.Servo.targets'))" />
|
<Error Condition="!Exists('..\packages\ANGLE.WindowsStore.Servo.2.1.19\build\native\ANGLE.WindowsStore.Servo.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ANGLE.WindowsStore.Servo.2.1.19\build\native\ANGLE.WindowsStore.Servo.targets'))" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -187,51 +187,3 @@ void OpenGLES::Reset() {
|
||||||
Cleanup();
|
Cleanup();
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLSurface OpenGLES::CreateSurface(SwapChainPanel const &panel, float dpi) {
|
|
||||||
EGLSurface surface = EGL_NO_SURFACE;
|
|
||||||
|
|
||||||
const EGLint surfaceAttributes[] = {EGL_NONE};
|
|
||||||
|
|
||||||
PropertySet surfaceCreationProperties;
|
|
||||||
|
|
||||||
surfaceCreationProperties.Insert(EGLNativeWindowTypeProperty, panel);
|
|
||||||
// How to set size and or scale:
|
|
||||||
// Insert(EGLRenderSurfaceSizeProperty),
|
|
||||||
// PropertyValue::CreateSize(*renderSurfaceSize));
|
|
||||||
surfaceCreationProperties.Insert(EGLRenderResolutionScaleProperty,
|
|
||||||
PropertyValue::CreateSingle(dpi));
|
|
||||||
|
|
||||||
EGLNativeWindowType win = static_cast<EGLNativeWindowType>(
|
|
||||||
winrt::get_abi(surfaceCreationProperties));
|
|
||||||
surface =
|
|
||||||
eglCreateWindowSurface(mEglDisplay, mEglConfig, win, surfaceAttributes);
|
|
||||||
|
|
||||||
if (surface == EGL_NO_SURFACE) {
|
|
||||||
throw winrt::hresult_error(E_FAIL, L"Failed to create EGL surface");
|
|
||||||
}
|
|
||||||
|
|
||||||
return surface;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLES::GetSurfaceDimensions(const EGLSurface surface, EGLint *width,
|
|
||||||
EGLint *height) {
|
|
||||||
eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width);
|
|
||||||
eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLES::DestroySurface(const EGLSurface surface) {
|
|
||||||
if (mEglDisplay != EGL_NO_DISPLAY && surface != EGL_NO_SURFACE) {
|
|
||||||
eglDestroySurface(mEglDisplay, surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLES::MakeCurrent(const EGLSurface surface) {
|
|
||||||
if (eglMakeCurrent(mEglDisplay, surface, surface, mEglContext) == EGL_FALSE) {
|
|
||||||
throw winrt::hresult_error(E_FAIL, L"Failed to make EGLSurface current");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EGLBoolean OpenGLES::SwapBuffers(const EGLSurface surface) {
|
|
||||||
return (eglSwapBuffers(mEglDisplay, surface));
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,15 +9,10 @@ public:
|
||||||
OpenGLES();
|
OpenGLES();
|
||||||
~OpenGLES();
|
~OpenGLES();
|
||||||
|
|
||||||
EGLSurface
|
EGLNativeWindowType
|
||||||
CreateSurface(winrt::Windows::UI::Xaml::Controls::SwapChainPanel const &,
|
GetNativeWindow(winrt::Windows::UI::Xaml::Controls::SwapChainPanel const &,
|
||||||
float dpi);
|
float dpi);
|
||||||
|
|
||||||
void GetSurfaceDimensions(const EGLSurface surface, EGLint *width,
|
|
||||||
EGLint *height);
|
|
||||||
void DestroySurface(const EGLSurface surface);
|
|
||||||
void MakeCurrent(const EGLSurface surface);
|
|
||||||
EGLBoolean SwapBuffers(const EGLSurface surface);
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Servo.h"
|
#include "Servo.h"
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
|
||||||
namespace winrt::servo {
|
namespace winrt::servo {
|
||||||
|
|
||||||
|
@ -21,10 +22,6 @@ void on_url_changed(const char *url) {
|
||||||
sServo->Delegate().OnServoURLChanged(char2hstring(url));
|
sServo->Delegate().OnServoURLChanged(char2hstring(url));
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush() { sServo->Delegate().Flush(); }
|
|
||||||
|
|
||||||
void make_current() { sServo->Delegate().MakeCurrent(); }
|
|
||||||
|
|
||||||
void wakeup() { sServo->Delegate().WakeUp(); }
|
void wakeup() { sServo->Delegate().WakeUp(); }
|
||||||
|
|
||||||
bool on_allow_navigation(const char *url) {
|
bool on_allow_navigation(const char *url) {
|
||||||
|
@ -107,7 +104,8 @@ const char *prompt_input(const char *message, const char *default,
|
||||||
}
|
}
|
||||||
|
|
||||||
Servo::Servo(hstring url, hstring args, GLsizei width, GLsizei height,
|
Servo::Servo(hstring url, hstring args, GLsizei width, GLsizei height,
|
||||||
float dpi, ServoDelegate &aDelegate)
|
EGLNativeWindowType eglNativeWindow, float dpi,
|
||||||
|
ServoDelegate &aDelegate)
|
||||||
: mWindowHeight(height), mWindowWidth(width), mDelegate(aDelegate) {
|
: mWindowHeight(height), mWindowWidth(width), mDelegate(aDelegate) {
|
||||||
SetEnvironmentVariableA("PreviewRuntimeEnabled", "1");
|
SetEnvironmentVariableA("PreviewRuntimeEnabled", "1");
|
||||||
|
|
||||||
|
@ -119,6 +117,7 @@ Servo::Servo(hstring url, hstring args, GLsizei width, GLsizei height,
|
||||||
o.height = mWindowHeight;
|
o.height = mWindowHeight;
|
||||||
o.density = dpi;
|
o.density = dpi;
|
||||||
o.enable_subpixel_text_antialiasing = false;
|
o.enable_subpixel_text_antialiasing = false;
|
||||||
|
o.native_widget = eglNativeWindow;
|
||||||
|
|
||||||
// Note about logs:
|
// Note about logs:
|
||||||
// By default: all modules are enabled. Only warn level-logs are displayed.
|
// By default: all modules are enabled. Only warn level-logs are displayed.
|
||||||
|
@ -142,8 +141,6 @@ Servo::Servo(hstring url, hstring args, GLsizei width, GLsizei height,
|
||||||
sServo = this; // FIXME;
|
sServo = this; // FIXME;
|
||||||
|
|
||||||
capi::CHostCallbacks c;
|
capi::CHostCallbacks c;
|
||||||
c.flush = &flush;
|
|
||||||
c.make_current = &make_current;
|
|
||||||
c.on_load_started = &on_load_started;
|
c.on_load_started = &on_load_started;
|
||||||
c.on_load_ended = &on_load_ended;
|
c.on_load_ended = &on_load_ended;
|
||||||
c.on_title_changed = &on_title_changed;
|
c.on_title_changed = &on_title_changed;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
#include <EGL/egl.h>
|
||||||
#include "logs.h"
|
#include "logs.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -23,7 +24,8 @@ class ServoDelegate;
|
||||||
|
|
||||||
class Servo {
|
class Servo {
|
||||||
public:
|
public:
|
||||||
Servo(hstring, hstring, GLsizei, GLsizei, float, ServoDelegate &);
|
Servo(hstring, hstring, GLsizei, GLsizei, EGLNativeWindowType, float,
|
||||||
|
ServoDelegate &);
|
||||||
~Servo();
|
~Servo();
|
||||||
ServoDelegate &Delegate() { return mDelegate; }
|
ServoDelegate &Delegate() { return mDelegate; }
|
||||||
|
|
||||||
|
@ -100,8 +102,6 @@ public:
|
||||||
virtual void OnServoAnimatingChanged(bool) = 0;
|
virtual void OnServoAnimatingChanged(bool) = 0;
|
||||||
virtual void OnServoIMEStateChanged(bool) = 0;
|
virtual void OnServoIMEStateChanged(bool) = 0;
|
||||||
virtual void OnServoDevtoolsStarted(bool, const unsigned int) = 0;
|
virtual void OnServoDevtoolsStarted(bool, const unsigned int) = 0;
|
||||||
virtual void Flush() = 0;
|
|
||||||
virtual void MakeCurrent() = 0;
|
|
||||||
virtual void OnServoMediaSessionMetadata(hstring, hstring, hstring) = 0;
|
virtual void OnServoMediaSessionMetadata(hstring, hstring, hstring) = 0;
|
||||||
virtual void OnServoMediaSessionPlaybackStateChange(int) = 0;
|
virtual void OnServoMediaSessionPlaybackStateChange(int) = 0;
|
||||||
virtual void OnServoPromptAlert(hstring, bool) = 0;
|
virtual void OnServoPromptAlert(hstring, bool) = 0;
|
||||||
|
|
|
@ -72,7 +72,7 @@ void ServoControl::OnLoaded(IInspectable const &, RoutedEventArgs const &) {
|
||||||
InitializeCriticalSection(&mGLLock);
|
InitializeCriticalSection(&mGLLock);
|
||||||
InitializeConditionVariable(&mDialogCondVar);
|
InitializeConditionVariable(&mDialogCondVar);
|
||||||
InitializeCriticalSection(&mDialogLock);
|
InitializeCriticalSection(&mDialogLock);
|
||||||
CreateRenderSurface();
|
CreateNativeWindow();
|
||||||
StartRenderLoop();
|
StartRenderLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,22 +80,26 @@ Controls::SwapChainPanel ServoControl::Panel() {
|
||||||
return GetTemplateChild(L"swapChainPanel").as<Controls::SwapChainPanel>();
|
return GetTemplateChild(L"swapChainPanel").as<Controls::SwapChainPanel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServoControl::CreateRenderSurface() {
|
void ServoControl::CreateNativeWindow() {
|
||||||
if (mRenderSurface == EGL_NO_SURFACE) {
|
mPanelWidth = Panel().ActualWidth() * mDPI;
|
||||||
mRenderSurface = mOpenGLES.CreateSurface(Panel(), mDPI);
|
mPanelHeight = Panel().ActualHeight() * mDPI;
|
||||||
}
|
mNativeWindowProperties.Insert(EGLNativeWindowTypeProperty, Panel());
|
||||||
|
// How to set size and or scale:
|
||||||
|
// Insert(EGLRenderSurfaceSizeProperty),
|
||||||
|
// PropertyValue::CreateSize(*renderSurfaceSize));
|
||||||
|
mNativeWindowProperties.Insert(EGLRenderResolutionScaleProperty,
|
||||||
|
PropertyValue::CreateSingle(mDPI));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServoControl::DestroyRenderSurface() {
|
EGLNativeWindowType ServoControl::GetNativeWindow() {
|
||||||
mOpenGLES.DestroySurface(mRenderSurface);
|
EGLNativeWindowType win =
|
||||||
mRenderSurface = EGL_NO_SURFACE;
|
static_cast<EGLNativeWindowType>(winrt::get_abi(mNativeWindowProperties));
|
||||||
|
|
||||||
|
return win;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServoControl::RecoverFromLostDevice() {
|
void ServoControl::RecoverFromLostDevice() {
|
||||||
StopRenderLoop();
|
StopRenderLoop();
|
||||||
DestroyRenderSurface();
|
|
||||||
mOpenGLES.Reset();
|
|
||||||
CreateRenderSurface();
|
|
||||||
StartRenderLoop();
|
StartRenderLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,18 +315,12 @@ void ServoControl::RunOnGLThread(std::function<void()> task) {
|
||||||
void ServoControl::Loop() {
|
void ServoControl::Loop() {
|
||||||
log("BrowserPage::Loop(). GL thread: %i", GetCurrentThreadId());
|
log("BrowserPage::Loop(). GL thread: %i", GetCurrentThreadId());
|
||||||
|
|
||||||
mOpenGLES.MakeCurrent(mRenderSurface);
|
|
||||||
|
|
||||||
EGLint panelWidth = 0;
|
|
||||||
EGLint panelHeight = 0;
|
|
||||||
mOpenGLES.GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight);
|
|
||||||
glViewport(0, 0, panelWidth, panelHeight);
|
|
||||||
|
|
||||||
if (mServo == nullptr) {
|
if (mServo == nullptr) {
|
||||||
log("Entering loop");
|
log("Entering loop");
|
||||||
ServoDelegate *sd = static_cast<ServoDelegate *>(this);
|
ServoDelegate *sd = static_cast<ServoDelegate *>(this);
|
||||||
mServo = std::make_unique<Servo>(mInitialURL, mArgs, panelWidth,
|
EGLNativeWindowType win = GetNativeWindow();
|
||||||
panelHeight, mDPI, *sd);
|
mServo = std::make_unique<Servo>(mInitialURL, mArgs, mPanelWidth,
|
||||||
|
mPanelHeight, win, mDPI, *sd);
|
||||||
} else {
|
} else {
|
||||||
// FIXME: this will fail since create_task didn't pick the thread
|
// FIXME: this will fail since create_task didn't pick the thread
|
||||||
// where Servo was running initially.
|
// where Servo was running initially.
|
||||||
|
@ -406,17 +404,6 @@ void ServoControl::OnServoURLChanged(hstring url) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServoControl::Flush() {
|
|
||||||
if (mOpenGLES.SwapBuffers(mRenderSurface) != GL_TRUE) {
|
|
||||||
// The call to eglSwapBuffers might not be successful (i.e. due to Device
|
|
||||||
// Lost) If the call fails, then we must reinitialize EGL and the GL
|
|
||||||
// resources.
|
|
||||||
RunOnUIThread([=] { RecoverFromLostDevice(); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServoControl::MakeCurrent() { mOpenGLES.MakeCurrent(mRenderSurface); }
|
|
||||||
|
|
||||||
void ServoControl::WakeUp() {
|
void ServoControl::WakeUp() {
|
||||||
RunOnGLThread([=] {});
|
RunOnGLThread([=] {});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "Servo.h"
|
#include "Servo.h"
|
||||||
#include "DefaultUrl.h"
|
#include "DefaultUrl.h"
|
||||||
|
|
||||||
|
using namespace winrt::Windows::Foundation::Collections;
|
||||||
|
|
||||||
namespace winrt::ServoApp::implementation {
|
namespace winrt::ServoApp::implementation {
|
||||||
struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
|
struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
|
||||||
|
|
||||||
|
@ -108,8 +110,6 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
|
||||||
virtual void OnServoShutdownComplete();
|
virtual void OnServoShutdownComplete();
|
||||||
virtual void OnServoTitleChanged(winrt::hstring);
|
virtual void OnServoTitleChanged(winrt::hstring);
|
||||||
virtual void OnServoURLChanged(winrt::hstring);
|
virtual void OnServoURLChanged(winrt::hstring);
|
||||||
virtual void Flush();
|
|
||||||
virtual void MakeCurrent();
|
|
||||||
virtual bool OnServoAllowNavigation(winrt::hstring);
|
virtual bool OnServoAllowNavigation(winrt::hstring);
|
||||||
virtual void OnServoAnimatingChanged(bool);
|
virtual void OnServoAnimatingChanged(bool);
|
||||||
virtual void OnServoIMEStateChanged(bool);
|
virtual void OnServoIMEStateChanged(bool);
|
||||||
|
@ -150,14 +150,16 @@ private:
|
||||||
std::optional<hstring> secondaryButton,
|
std::optional<hstring> secondaryButton,
|
||||||
std::optional<hstring> input);
|
std::optional<hstring> input);
|
||||||
|
|
||||||
|
int mPanelHeight = 0;
|
||||||
|
int mPanelWidth = 0;
|
||||||
float mDPI = 1;
|
float mDPI = 1;
|
||||||
hstring mInitialURL = DEFAULT_URL;
|
hstring mInitialURL = DEFAULT_URL;
|
||||||
hstring mCurrentUrl = L"";
|
hstring mCurrentUrl = L"";
|
||||||
bool mTransient = false;
|
bool mTransient = false;
|
||||||
|
|
||||||
Windows::UI::Xaml::Controls::SwapChainPanel ServoControl::Panel();
|
Windows::UI::Xaml::Controls::SwapChainPanel ServoControl::Panel();
|
||||||
void CreateRenderSurface();
|
void CreateNativeWindow();
|
||||||
void DestroyRenderSurface();
|
EGLNativeWindowType GetNativeWindow();
|
||||||
void RecoverFromLostDevice();
|
void RecoverFromLostDevice();
|
||||||
|
|
||||||
void StartRenderLoop();
|
void StartRenderLoop();
|
||||||
|
@ -204,7 +206,7 @@ private:
|
||||||
void TryLoadUri(hstring);
|
void TryLoadUri(hstring);
|
||||||
|
|
||||||
std::unique_ptr<servo::Servo> mServo;
|
std::unique_ptr<servo::Servo> mServo;
|
||||||
EGLSurface mRenderSurface{EGL_NO_SURFACE};
|
PropertySet mNativeWindowProperties;
|
||||||
OpenGLES mOpenGLES;
|
OpenGLES mOpenGLES;
|
||||||
bool mAnimating = false;
|
bool mAnimating = false;
|
||||||
bool mLooping = false;
|
bool mLooping = false;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="ANGLE.WindowsStore.Servo" version="2.1.16" targetFramework="native" />
|
<package id="ANGLE.WindowsStore.Servo" version="2.1.19" targetFramework="native" />
|
||||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.190620.2" targetFramework="native" />
|
<package id="Microsoft.Windows.CppWinRT" version="2.0.190620.2" targetFramework="native" />
|
||||||
<package id="OpenXR.Loader" version="1.0.3" targetFramework="native" />
|
<package id="OpenXR.Loader" version="1.0.3" targetFramework="native" />
|
||||||
</packages>
|
</packages>
|
|
@ -0,0 +1,4 @@
|
||||||
|
[gradients-with-border.html]
|
||||||
|
type: reftest
|
||||||
|
fuzzy: /css/css-images/gradients-with-border-ref.html:0-1;0-1
|
||||||
|
expected: PASS
|
|
@ -1,2 +0,0 @@
|
||||||
[text_node_opacity.html]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[text_node_opacity.html]
|
|
||||||
expected: FAIL
|
|
|
@ -10867,7 +10867,7 @@
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"shader-varying-packing-restrictions.html": [
|
"shader-varying-packing-restrictions.html": [
|
||||||
"8a7fd1a4201883e63af071122cd5003120dfb23e",
|
"d289bbeabb9b2db31cb6ba50df97d63ccce7d5c6",
|
||||||
[
|
[
|
||||||
null,
|
null,
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
[gl-disabled-vertex-attrib.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/26004
|
||||||
|
[WebGL test #15: should be green\nat (0, 0) expected: 0,255,0,255 was 255,255,255,255]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[gl-vertex-attrib-unconsumed-out-of-bounds.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/26004
|
||||||
|
expected:
|
||||||
|
if os == "mac": CRASH
|
|
@ -0,0 +1,42 @@
|
||||||
|
[gl-vertex-attrib-zero-issues.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/26004
|
||||||
|
[WebGL test #19: canvas should be green\nat (0, 0) expected: 0,255,0,255 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #31: canvas should be green\nat (0, 0) expected: 0,255,0,255 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #11: canvas should be green\nat (0, 0) expected: 0,255,0,255 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #13: canvas should be green\nat (0, 0) expected: 0,255,0,255 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #25: canvas should be green\nat (0, 0) expected: 0,255,0,255 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #7: canvas should be green\nat (0, 0) expected: 0,255,0,255 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #23: canvas should be green\nat (0, 0) expected: 0,255,0,255 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #29: canvas should be green\nat (0, 0) expected: 0,255,0,255 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #5: canvas should be green\nat (0, 0) expected: 0,255,0,255 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #17: canvas should be green\nat (0, 0) expected: 0,255,0,255 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
[angle-instanced-arrays-out-of-bounds.html]
|
[angle-instanced-arrays-out-of-bounds.html]
|
||||||
bug: https://github.com/servo/servo/issues/20599
|
bug: https://github.com/servo/servo/issues/20599 https://github.com/servo/servo/issues/25990
|
||||||
|
expected:
|
||||||
|
if os == "mac": CRASH
|
||||||
|
|
||||||
[WebGL test #32: getError expected: INVALID_OPERATION. Was NO_ERROR : after evaluating: ext.drawElementsInstancedANGLE(gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, 0, 1)]
|
[WebGL test #32: getError expected: INVALID_OPERATION. Was NO_ERROR : after evaluating: ext.drawElementsInstancedANGLE(gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, 0, 1)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,41 +1,72 @@
|
||||||
[shader-varying-packing-restrictions.html]
|
[shader-varying-packing-restrictions.html]
|
||||||
bug: https://github.com/servo/servo/issues/20601
|
[WebGL test #9: [unexpected link status\] shaders with varying array of vec2 with one more than the maximum number of elements accessing first element should fail]
|
||||||
[WebGL test #2: [unexpected link status\] shaders with varying array of float with 33 elements (one past maximum) accessing last element should fail]
|
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #3: [unexpected link status\] shaders with varying array of float with 33 elements (one past maximum) accessing first element should fail]
|
[WebGL test #8: [unexpected link status\] shaders with varying array of vec2 with one more than the maximum number of elements accessing last element should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #8: [unexpected link status\] shaders with varying array of vec2 with 33 elements (one past maximum) accessing last element should fail]
|
[WebGL test #34: [unexpected link status\] shaders with one more than the maximum number of varyings of mat3 should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #9: [unexpected link status\] shaders with varying array of vec2 with 33 elements (one past maximum) accessing first element should fail]
|
[WebGL test #14: [unexpected link status\] shaders with varying array of vec3 with one more than the maximum number of elements accessing last element should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #14: [unexpected link status\] shaders with varying array of vec3 with 33 elements (one past maximum) accessing last element should fail]
|
[WebGL test #32: [unexpected link status\] shaders with varying array of mat3 with one more than the maximum number of elements accessing last element should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #15: [unexpected link status\] shaders with varying array of vec3 with 33 elements (one past maximum) accessing first element should fail]
|
[WebGL test #28: [unexpected link status\] shaders with one more than the maximum number of varyings of mat2 should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #16: [unexpected link status\] shaders with 33 varyings of vec3 (one past maximum) should fail]
|
[WebGL test #16: [unexpected link status\] shaders with one more than the maximum number of varyings of vec3 should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #26: [unexpected link status\] shaders with varying array of mat2 with 17 elements (one past maximum) accessing last element should fail]
|
[WebGL test #26: [unexpected link status\] shaders with varying array of mat2 with one more than the maximum number of elements accessing last element should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #27: [unexpected link status\] shaders with varying array of mat2 with 17 elements (one past maximum) accessing first element should fail]
|
[WebGL test #27: [unexpected link status\] shaders with varying array of mat2 with one more than the maximum number of elements accessing first element should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #28: [unexpected link status\] shaders with 17 varyings of mat2 (one past maximum) should fail]
|
[WebGL test #33: [unexpected link status\] shaders with varying array of mat3 with one more than the maximum number of elements accessing first element should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #32: [unexpected link status\] shaders with varying array of mat3 with 11 elements (one past maximum) accessing last element should fail]
|
[WebGL test #3: [unexpected link status\] shaders with varying array of float with one more than the maximum number of elements accessing first element should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #33: [unexpected link status\] shaders with varying array of mat3 with 11 elements (one past maximum) accessing first element should fail]
|
[WebGL test #2: [unexpected link status\] shaders with varying array of float with one more than the maximum number of elements accessing last element should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #34: [unexpected link status\] shaders with 11 varyings of mat3 (one past maximum) should fail]
|
[WebGL test #15: [unexpected link status\] shaders with varying array of vec3 with one more than the maximum number of elements accessing first element should fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #10: [unexpected link status\] shaders with one more than the maximum number of varyings of vec2 should fail]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #38: [unexpected link status\] shaders with varying array of mat4 with one more than the maximum number of elements accessing last element should fail]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #21: [unexpected link status\] shaders with varying array of vec4 with one more than the maximum number of elements accessing first element should fail]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #40: [unexpected link status\] shaders with one more than the maximum number of varyings of mat4 should fail]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #22: [unexpected link status\] shaders with one more than the maximum number of varyings of vec4 should fail]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #4: [unexpected link status\] shaders with one more than the maximum number of varyings of float should fail]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #39: [unexpected link status\] shaders with varying array of mat4 with one more than the maximum number of elements accessing first element should fail]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #20: [unexpected link status\] shaders with varying array of vec4 with one more than the maximum number of elements accessing last element should fail]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
|
|
@ -9,3 +9,15 @@
|
||||||
[WebGL test #12: [unexpected link status\] vertex shader with variant gl_PointSize and fragment shader with invariant gl_PointCoord must fail]
|
[WebGL test #12: [unexpected link status\] vertex shader with variant gl_PointSize and fragment shader with invariant gl_PointCoord must fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #3: [unexpected link status\] vertex shader with invariant (global setting) varying and fragment shader with invariant varying must succeed]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #2: [unexpected link status\] vertex shader with invariant (global setting) varying and fragment shader with variant varying must fail]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #8: [unexpected link status\] vertex shader with invariant gl_Position and fragment shader with invariant gl_FragCoord must succeed]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
[gl-bind-attrib-location-long-names-test.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/26004
|
||||||
|
[WebGL test #4: should be green\nat (0, 0) expected: 0,255,0,255 was 255,255,255,255]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #8: should be green\nat (0, 0) expected: 255,0,0,255 was 255,255,255,255]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
[gl-bind-attrib-location-test.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/26004
|
||||||
|
[WebGL test #13: Line 15 should be red for at least 10 rgba pixels starting 20 pixels in\nat (20, 15) expected: 255,0,0,255 was 0,0,0,255]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #7: Line 15 should be red for at least 10 rgba pixels starting 20 pixels in\nat (20, 15) expected: 0,255,0,255 was 0,0,0,255]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
|
@ -1,3 +1,62 @@
|
||||||
[read-pixels-test.html]
|
[read-pixels-test.html]
|
||||||
bug: https://github.com/servo/servo/issues/12859
|
bug: https://github.com/servo/servo/issues/12859
|
||||||
expected: TIMEOUT
|
[WebGL test #49: getError expected: INVALID_OPERATION. Was INVALID_ENUM : Should not be able to read as ALPHA / UNSIGNED_BYTE]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #45: getError expected: INVALID_OPERATION. Was INVALID_ENUM : Should not be able to read as RGB / UNSIGNED_BYTE]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #47: getError expected: INVALID_OPERATION. Was INVALID_ENUM : Should not be able to read as RGBA / UNSIGNED_SHORT_5_5_5_1]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #46: getError expected: INVALID_OPERATION. Was INVALID_ENUM : Should not be able to read as RGB / UNSIGNED_SHORT_5_6_5]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #48: getError expected: INVALID_OPERATION. Was INVALID_ENUM : Should not be able to read as RGBA / UNSIGNED_SHORT_4_4_4_4]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #37: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as 0x8d99]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #33: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as LUMINANCE]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #42: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as UNSIGNED_INT]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #38: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as 0x84fa]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #30: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as DEPTH_STENCIL]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #43: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as 0x8368]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #29: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as DEPTH_COMPONENT]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #35: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as 0x1903]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #41: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as BYTE]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #31: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as 0x8229]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #36: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as 0x8228]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #32: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as RGBA4]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #40: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as SHORT]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #34: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as LUMINANCE_ALPHA]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #39: getError expected: INVALID_ENUM. Was INVALID_OPERATION : Should not be able to read as UNSIGNED_SHORT]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -3,3 +3,6 @@
|
||||||
[WebGL test #3: getError expected: INVALID_OPERATION. Was NO_ERROR : after draw with invalid feedback loop]
|
[WebGL test #3: getError expected: INVALID_OPERATION. Was NO_ERROR : after draw with invalid feedback loop]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #5: Should be blue.\nat (0, 0) expected: 0,0,255,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
[line-rendering-quality.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/25937
|
||||||
|
[WebGL test #5: Found 0 lines, looking in the vertical direction, expected 2]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #11: Found 0 lines, looking in the vertical direction, expected 2]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
[point-no-attributes.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/26004
|
||||||
|
[WebGL test #1: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[rendering-stencil-large-viewport.html]
|
|
||||||
expected: TIMEOUT
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
[copy-tex-image-2d-formats.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/25995
|
||||||
|
[WebGL test #43: should be 64,64,64,255\nat (0, 0) expected: 64,64,64,255 was 0,0,0,255]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #2: should be 0,0,0,127\nat (0, 0) expected: 0,0,0,127 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #5: should be 64,64,64,255\nat (0, 0) expected: 64,64,64,255 was 0,0,0,255]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #8: should be 64,64,64,127\nat (0, 0) expected: 64,64,64,127 was 0,0,0,0]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
[copy-tex-image-and-sub-image-2d.html]
|
[copy-tex-image-and-sub-image-2d.html]
|
||||||
|
disabled:
|
||||||
|
if os == "mac": https://github.com/servo/servo/issues/26000
|
||||||
[WebGL test #315: 0, 1 should render 0,0,0,0 (+/-1)\nat (0, 1) expected: 0,0,0,0 was 136,136,136,136]
|
[WebGL test #315: 0, 1 should render 0,0,0,0 (+/-1)\nat (0, 1) expected: 0,0,0,0 was 136,136,136,136]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
[out-of-bounds-uniform-array-access.html]
|
[out-of-bounds-uniform-array-access.html]
|
||||||
expected: TIMEOUT
|
expected:
|
||||||
|
if os == "linux": TIMEOUT
|
||||||
[Overall test]
|
[Overall test]
|
||||||
expected: NOTRUN
|
expected:
|
||||||
|
if os == "linux": NOTRUN
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
[bound-buffer-size-change-test.html]
|
||||||
|
[WebGL test #38: gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #23: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #4: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #28: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0) should be 4. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #22: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0) should be 4. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #33: gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1) should be 12. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #16: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #7: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #35: gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #37: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 16. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #39: gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1) should be 12. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #21: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0) should be 8. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #40: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 16. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #15: gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #25: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0) should be 4. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #32: gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #14: gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #11: gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #36: gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1) should be 12. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #3: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #5: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #6: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #24: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0) should be 8. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #34: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 16. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #26: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #2: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #20: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #27: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0) should be 8. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #12: gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #13: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #34: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 256. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #37: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 256. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #40: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 256. Threw exception TypeError: gl.getIndexedParameter is not a function]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
[vector-dynamic-indexing-swizzled-lvalue.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/26004
|
||||||
|
[WebGL test #0: should be green\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
[read-pixels-pack-parameters.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/26004
|
||||||
|
[WebGL test #243: last pixel of row 0: expected [249,102,0,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #257: first pixel of row 1: expected [2,200,102,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #246: first pixel of row 2: expected [134,87,234,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #245: last pixel of row 1: expected [2,200,102,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #256: last pixel of row 0: expected [249,102,0,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #254: skipped bytes changed at index 0: expected 1 got 249]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #241: skipped bytes changed at index 0: expected 1 got 249]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #260: last pixel of row 2: expected [134,87,234,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #244: first pixel of row 1: expected [2,200,102,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #247: last pixel of row 2: expected [134,87,234,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #242: first pixel of row 0: expected [249,102,0,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #255: first pixel of row 0: expected [249,102,0,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #259: first pixel of row 2: expected [134,87,234,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #258: last pixel of row 1: expected [2,200,102,255\], got [1,2,3,4\]]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
[framebuffer-object-attachment.html]
|
[framebuffer-object-attachment.html]
|
||||||
|
expected:
|
||||||
|
if os == "mac": TIMEOUT
|
||||||
[WebGL test #45: getError expected: NO_ERROR. Was INVALID_ENUM : ]
|
[WebGL test #45: getError expected: NO_ERROR. Was INVALID_ENUM : ]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
[framebuffer-test.html]
|
[framebuffer-test.html]
|
||||||
|
[WebGL test #37: gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE) should be 0. Was 8.]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
[WebGL test #38: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read framebuffer with no attachment.]
|
[WebGL test #38: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read framebuffer with no attachment.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
[invalidate-framebuffer.html]
|
[invalidate-framebuffer.html]
|
||||||
expected: ERROR
|
bug: https://github.com/servo/servo/issues/20529
|
||||||
|
expected:
|
||||||
|
if os == "linux": ERROR
|
||||||
|
if os == "mac": TIMEOUT
|
||||||
[WebGL test #17: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
[WebGL test #17: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
[blitframebuffer-filter-outofbounds.html]
|
[blitframebuffer-filter-outofbounds.html]
|
||||||
[WebGL test #1: framebuffer not complete]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #2: framebuffer not complete]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #3: framebuffer not complete]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #4: framebuffer not complete]
|
[WebGL test #4: framebuffer not complete]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #5: framebuffer not complete]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #6: framebuffer not complete]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #7: framebuffer not complete]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #8: framebuffer not complete]
|
[WebGL test #8: framebuffer not complete]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #1: framebuffer not complete]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #6: framebuffer not complete]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #3: framebuffer not complete]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #2: framebuffer not complete]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #7: framebuffer not complete]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #5: framebuffer not complete]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,20 @@
|
||||||
[blitframebuffer-multisampled-readbuffer.html]
|
[blitframebuffer-multisampled-readbuffer.html]
|
||||||
[WebGL test #2: Framebuffer incomplete.]
|
expected:
|
||||||
expected: FAIL
|
if os =="mac": ERROR
|
||||||
|
|
||||||
[WebGL test #1: Framebuffer incomplete.]
|
[WebGL test #1: Framebuffer incomplete.]
|
||||||
expected: FAIL
|
expected:
|
||||||
|
if os == "linux": FAIL
|
||||||
|
|
||||||
|
[WebGL test #2: Framebuffer incomplete.]
|
||||||
|
expected:
|
||||||
|
if os == "linux": FAIL
|
||||||
|
|
||||||
|
[WebGL test #1: getError expected: NO_ERROR. Was INVALID_ENUM : setup draw framebuffer should succeed]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #2: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
[blitframebuffer-outside-readbuffer.html]
|
[blitframebuffer-outside-readbuffer.html]
|
||||||
[WebGL test #1: framebuffer not complete]
|
[WebGL test #4: framebuffer not complete]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #2: framebuffer not complete]
|
[WebGL test #1: framebuffer not complete]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #3: framebuffer not complete]
|
[WebGL test #3: framebuffer not complete]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #4: framebuffer not complete]
|
[WebGL test #2: framebuffer not complete]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
[blitframebuffer-scissor-enabled.html]
|
[blitframebuffer-scissor-enabled.html]
|
||||||
[WebGL test #1: Framebuffer incomplete.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #2: Framebuffer incomplete.]
|
[WebGL test #2: Framebuffer incomplete.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #3: Framebuffer incomplete.]
|
[WebGL test #3: Framebuffer incomplete.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #4: Framebuffer incomplete.]
|
[WebGL test #8: Framebuffer incomplete.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #5: Framebuffer incomplete.]
|
[WebGL test #1: Framebuffer incomplete.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #4: Framebuffer incomplete.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #6: Framebuffer incomplete.]
|
[WebGL test #6: Framebuffer incomplete.]
|
||||||
|
@ -20,6 +20,6 @@
|
||||||
[WebGL test #7: Framebuffer incomplete.]
|
[WebGL test #7: Framebuffer incomplete.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #8: Framebuffer incomplete.]
|
[WebGL test #5: Framebuffer incomplete.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,31 @@
|
||||||
[clear-func-buffer-type-match.html]
|
[clear-func-buffer-type-match.html]
|
||||||
expected: TIMEOUT
|
[WebGL test #18: getError expected: INVALID_OPERATION. Was NO_ERROR : clearBufferiv and RGBA8 buffer]
|
||||||
[WebGL test #1: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #7: getError expected: INVALID_OPERATION. Was NO_ERROR : clearBufferuiv and float buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #10: getError expected: INVALID_OPERATION. Was NO_ERROR : clearBufferfv and UINT buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #14: getError expected: INVALID_OPERATION. Was NO_ERROR : clearBufferiv and float buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #11: getError expected: INVALID_OPERATION. Was NO_ERROR : clearBufferiv and UINT buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #4: getError expected: INVALID_OPERATION. Was NO_ERROR : clearBufferuiv and INT buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #3: getError expected: INVALID_OPERATION. Was NO_ERROR : clearBufferfv and INT buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #2: getError expected: INVALID_OPERATION. Was NO_ERROR : clear and INT buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #9: getError expected: INVALID_OPERATION. Was NO_ERROR : clear and UINT buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #19: getError expected: INVALID_OPERATION. Was NO_ERROR : clearBufferuiv and RGBA8 buffer]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
[framebuffer-unsupported.html]
|
[framebuffer-unsupported.html]
|
||||||
expected: ERROR
|
expected: ERROR
|
||||||
[WebGL test #4: checkFramebufferStatus expects [FRAMEBUFFER_UNSUPPORTED\], was FRAMEBUFFER_COMPLETE]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #7: checkFramebufferStatus expects [FRAMEBUFFER_UNSUPPORTED\], was FRAMEBUFFER_COMPLETE]
|
[WebGL test #7: checkFramebufferStatus expects [FRAMEBUFFER_UNSUPPORTED\], was FRAMEBUFFER_COMPLETE]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[WebGL test #8: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
[WebGL test #8: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #4: checkFramebufferStatus expects [FRAMEBUFFER_UNSUPPORTED\], was FRAMEBUFFER_COMPLETE]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,28 @@
|
||||||
[fs-color-type-mismatch-color-buffer-type.html]
|
[fs-color-type-mismatch-color-buffer-type.html]
|
||||||
expected: TIMEOUT
|
[WebGL test #2: Framebuffer incomplete.]
|
||||||
[WebGL test #2: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #3: Framebuffer incomplete.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #8: getError expected: NO_ERROR. Was INVALID_ENUM : If color buffers' type mismatch the type of fragment shader's outputs, geneate INVALID_OPERATION. Otherwise, it should be NO_ERROR]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #4: Framebuffer incomplete.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #11: getError expected: INVALID_OPERATION. Was NO_ERROR : If color buffers' type mismatch the type of fragment shader's outputs, geneate INVALID_OPERATION. Otherwise, it should be NO_ERROR]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #6: Framebuffer incomplete.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #7: Framebuffer incomplete.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #13: getError expected: INVALID_OPERATION. Was NO_ERROR : If color buffers' type mismatch the type of fragment shader's outputs, geneate INVALID_OPERATION. Otherwise, it should be NO_ERROR]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #5: Framebuffer incomplete.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
[line-rendering-quality.html]
|
[line-rendering-quality.html]
|
||||||
expected: ERROR
|
expected: ERROR
|
||||||
|
bug: https://github.com/servo/servo/issues/25937
|
||||||
|
[WebGL test #5: Found 0 lines, looking in the vertical direction, expected 2]
|
||||||
|
expected:
|
||||||
|
if os == "linux": FAIL
|
||||||
[WebGL test #10: successfullyParsed should be true. Threw exception ReferenceError: can't access lexical declaration `successfullyParsed' before initialization]
|
[WebGL test #10: successfullyParsed should be true. Threw exception ReferenceError: can't access lexical declaration `successfullyParsed' before initialization]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,25 @@
|
||||||
[rgb-format-support.html]
|
[rgb-format-support.html]
|
||||||
[WebGL test #15: getError expected: NO_ERROR. Was INVALID_FRAMEBUFFER_OPERATION : should be no errors from clear()]
|
[WebGL test #24: getError expected: NO_ERROR. Was INVALID_FRAMEBUFFER_OPERATION : should be no errors from clear()]
|
||||||
expected: FAIL
|
expected:
|
||||||
|
if os == "linux": FAIL
|
||||||
|
|
||||||
[WebGL test #14: framebuffer with texture is incomplete]
|
[WebGL test #23: framebuffer with texture is incomplete]
|
||||||
expected: FAIL
|
expected:
|
||||||
|
if os == "linux": FAIL
|
||||||
|
|
||||||
[WebGL test #13: getError expected: NO_ERROR. Was INVALID_ENUM : should be no errors from texture setup]
|
[WebGL test #22: getError expected: NO_ERROR. Was INVALID_ENUM : should be no errors from texture setup]
|
||||||
expected: FAIL
|
expected:
|
||||||
|
if os == "linux": FAIL
|
||||||
|
|
||||||
|
[WebGL test #18: getError expected: NO_ERROR. Was INVALID_FRAMEBUFFER_OPERATION : should be no errors from clear()]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #17: framebuffer with texture is incomplete]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #16: getError expected: NO_ERROR. Was INVALID_ENUM : should be no errors from texture setup]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[uniform-block-buffer-size.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/25990
|
||||||
|
expected:
|
||||||
|
if os == "mac": CRASH
|
|
@ -1,4 +1,8 @@
|
||||||
[gl-object-get-calls.html]
|
[gl-object-get-calls.html]
|
||||||
|
bug: https://github.com/servo/servo/issues/26128
|
||||||
|
expected:
|
||||||
|
if os == "mac": TIMEOUT
|
||||||
|
|
||||||
[WebGL test #201: gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R) should be 33071 (of type number). Was null (of type object).]
|
[WebGL test #201: gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R) should be 33071 (of type number). Was null (of type object).]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -104,3 +108,5 @@
|
||||||
[WebGL test #183: getRenderbufferParameter did not generate INVALID_ENUM for invalid parameter enum: NO_ERROR]
|
[WebGL test #183: getRenderbufferParameter did not generate INVALID_ENUM for invalid parameter enum: NO_ERROR]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #183: getRenderbufferParameter did not generate INVALID_ENUM for invalid parameter enum: NO_ERROR]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -1,2 +1,360 @@
|
||||||
[too-small-buffers.html]
|
[too-small-buffers.html]
|
||||||
expected: TIMEOUT
|
expected:
|
||||||
|
if os == "linux": TIMEOUT
|
||||||
|
|
||||||
|
[WebGL test #60: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #87: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #121: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #11: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #71: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #47: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #9: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #110: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #84: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #107: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #117: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #54: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #29: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #19: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #83: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #37: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #78: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #130: getError expected: INVALID_OPERATION. Was NO_ERROR : integer overflow and/or buffer too small]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #66: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #12: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #7: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #34: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #77: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #74: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #31: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #15: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #120: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #49: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #56: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #73: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #33: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #97: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #116: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #91: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #90: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #95: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #119: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #65: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #23: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #35: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #68: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #16: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #57: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #61: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #38: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #21: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #129: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #89: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #32: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #115: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #14: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #25: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #113: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #102: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #5: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #42: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #108: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #18: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #36: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #99: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #100: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #55: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #67: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #80: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #53: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #105: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #79: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #63: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #24: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #125: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #76: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #96: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #98: buffer should match expected values]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #122: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #93: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #109: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #75: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #6: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #58: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #118: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #13: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #26: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #41: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #126: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #51: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #48: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #3: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #103: getError expected: INVALID_OPERATION. Was NO_ERROR : draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
[WebGL test #45: getError expected: NO_ERROR. Was INVALID_OPERATION : before draw]
|
||||||
|
expected:
|
||||||
|
if os == "mac": FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
[unwritten-output-defaults-to-zero.html]
|
|
||||||
[WebGL test #4: buffer should match expected values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -135,7 +135,8 @@ for (var ii = 0; ii < varyingTypes.length; ++ii) {
|
||||||
fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: minVars, fcode: fcode}, info),
|
fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: minVars, fcode: fcode}, info),
|
||||||
fShaderSuccess: true,
|
fShaderSuccess: true,
|
||||||
linkSuccess: true,
|
linkSuccess: true,
|
||||||
passMsg: "shaders with varying array of " + info.type + " with " + minVars + " elements (the minimum required) should succeed",
|
// Try to use deterministic test names
|
||||||
|
passMsg: "shaders with varying array of " + info.type + " with the minimum number of elements should succeed",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test array[max + 1] accessing last element. WebGL requires this to fail.
|
// Test array[max + 1] accessing last element. WebGL requires this to fail.
|
||||||
|
@ -147,7 +148,8 @@ for (var ii = 0; ii < varyingTypes.length; ++ii) {
|
||||||
fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: numVars + 1, fcode: fcode}, info),
|
fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: numVars + 1, fcode: fcode}, info),
|
||||||
fShaderSuccess: false,
|
fShaderSuccess: false,
|
||||||
linkSuccess: false,
|
linkSuccess: false,
|
||||||
passMsg: "shaders with varying array of " + info.type + " with " + (numVars + 1) + " elements (one past maximum) accessing last element should fail",
|
// Try to use deterministic test names
|
||||||
|
passMsg: "shaders with varying array of " + info.type + " with one more than the maximum number of elements accessing last element should fail",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test array[max + 1] accessing first element. WebGL requires this to fail but ES allows truncating array.
|
// Test array[max + 1] accessing first element. WebGL requires this to fail but ES allows truncating array.
|
||||||
|
@ -159,7 +161,8 @@ for (var ii = 0; ii < varyingTypes.length; ++ii) {
|
||||||
fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: numVars + 1, fcode: fcode}, info),
|
fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: numVars + 1, fcode: fcode}, info),
|
||||||
fShaderSuccess: false,
|
fShaderSuccess: false,
|
||||||
linkSuccess: false,
|
linkSuccess: false,
|
||||||
passMsg: "shaders with varying array of " + info.type + " with " + (numVars + 1) + " elements (one past maximum) accessing first element should fail",
|
// Try to use deterministic test names
|
||||||
|
passMsg: "shaders with varying array of " + info.type + " with one more than the maximum number of elements accessing first element should fail",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Note: We can't test max varyings as actual GL drivers are only required to be able to
|
// Note: We can't test max varyings as actual GL drivers are only required to be able to
|
||||||
|
@ -189,7 +192,8 @@ for (var ii = 0; ii < varyingTypes.length; ++ii) {
|
||||||
fShaderSource: wtu.replaceParams(fVaryingTestSource, generateCode(numMax + 1), info),
|
fShaderSource: wtu.replaceParams(fVaryingTestSource, generateCode(numMax + 1), info),
|
||||||
fShaderSuccess: false,
|
fShaderSuccess: false,
|
||||||
linkSuccess: false,
|
linkSuccess: false,
|
||||||
passMsg: "shaders with " + (numMax + 1) + " varyings of " + info.type + " (one past maximum) should fail",
|
// Try to use deterministic test names
|
||||||
|
passMsg: "shaders with one more than the maximum number of varyings of " + info.type + " should fail",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test required varyings of type.
|
// Test required varyings of type.
|
||||||
|
@ -199,7 +203,8 @@ for (var ii = 0; ii < varyingTypes.length; ++ii) {
|
||||||
fShaderSource: wtu.replaceParams(fVaryingTestSource, generateCode(minVars), info),
|
fShaderSource: wtu.replaceParams(fVaryingTestSource, generateCode(minVars), info),
|
||||||
fShaderSuccess: true,
|
fShaderSuccess: true,
|
||||||
linkSuccess: true,
|
linkSuccess: true,
|
||||||
passMsg: "shaders with " + minVars + " varyings of " + info.type + " (the minimum required) should succeed",
|
// Try to use deterministic test names
|
||||||
|
passMsg: "shaders with the minimum number of varyings of " + info.type + " should succeed",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ PATCHES = [
|
||||||
("timeout.patch", None),
|
("timeout.patch", None),
|
||||||
("set-zero-timeout.patch", "js/webgl-test-utils.js"),
|
("set-zero-timeout.patch", "js/webgl-test-utils.js"),
|
||||||
("compressed-images.patch", "conformance/extensions/webgl-compressed-texture-s3tc.html"),
|
("compressed-images.patch", "conformance/extensions/webgl-compressed-texture-s3tc.html"),
|
||||||
|
("shader-varying-packing-restrictions.patch", "conformance/glsl/misc/shader-varying-packing-restrictions.html"),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Fix for 'UnicodeDecodeError: 'ascii' codec can't decode byte'
|
# Fix for 'UnicodeDecodeError: 'ascii' codec can't decode byte'
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
diff --git a/tests/wpt/webgl/tests/conformance/glsl/misc/shader-varying-packing-restrictions.html b/tests/wpt/webgl/tests/conformance/glsl/misc/shader-varying-packing-restrictions.html
|
||||||
|
index 8a7fd1a420..d289bbeabb 100644
|
||||||
|
--- a/tests/wpt/webgl/tests/conformance/glsl/misc/shader-varying-packing-restrictions.html
|
||||||
|
+++ b/tests/wpt/webgl/tests/conformance/glsl/misc/shader-varying-packing-restrictions.html
|
||||||
|
@@ -135,7 +135,8 @@ for (var ii = 0; ii < varyingTypes.length; ++ii) {
|
||||||
|
fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: minVars, fcode: fcode}, info),
|
||||||
|
fShaderSuccess: true,
|
||||||
|
linkSuccess: true,
|
||||||
|
- passMsg: "shaders with varying array of " + info.type + " with " + minVars + " elements (the minimum required) should succeed",
|
||||||
|
+ // Try to use deterministic test names
|
||||||
|
+ passMsg: "shaders with varying array of " + info.type + " with the minimum number of elements should succeed",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test array[max + 1] accessing last element. WebGL requires this to fail.
|
||||||
|
@@ -147,7 +148,8 @@ for (var ii = 0; ii < varyingTypes.length; ++ii) {
|
||||||
|
fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: numVars + 1, fcode: fcode}, info),
|
||||||
|
fShaderSuccess: false,
|
||||||
|
linkSuccess: false,
|
||||||
|
- passMsg: "shaders with varying array of " + info.type + " with " + (numVars + 1) + " elements (one past maximum) accessing last element should fail",
|
||||||
|
+ // Try to use deterministic test names
|
||||||
|
+ passMsg: "shaders with varying array of " + info.type + " with one more than the maximum number of elements accessing last element should fail",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test array[max + 1] accessing first element. WebGL requires this to fail but ES allows truncating array.
|
||||||
|
@@ -159,7 +161,8 @@ for (var ii = 0; ii < varyingTypes.length; ++ii) {
|
||||||
|
fShaderSource: wtu.replaceParams(fArrayTestSource, {numTestType: numVars + 1, fcode: fcode}, info),
|
||||||
|
fShaderSuccess: false,
|
||||||
|
linkSuccess: false,
|
||||||
|
- passMsg: "shaders with varying array of " + info.type + " with " + (numVars + 1) + " elements (one past maximum) accessing first element should fail",
|
||||||
|
+ // Try to use deterministic test names
|
||||||
|
+ passMsg: "shaders with varying array of " + info.type + " with one more than the maximum number of elements accessing first element should fail",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Note: We can't test max varyings as actual GL drivers are only required to be able to
|
||||||
|
@@ -189,7 +192,8 @@ for (var ii = 0; ii < varyingTypes.length; ++ii) {
|
||||||
|
fShaderSource: wtu.replaceParams(fVaryingTestSource, generateCode(numMax + 1), info),
|
||||||
|
fShaderSuccess: false,
|
||||||
|
linkSuccess: false,
|
||||||
|
- passMsg: "shaders with " + (numMax + 1) + " varyings of " + info.type + " (one past maximum) should fail",
|
||||||
|
+ // Try to use deterministic test names
|
||||||
|
+ passMsg: "shaders with one more than the maximum number of varyings of " + info.type + " should fail",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test required varyings of type.
|
||||||
|
@@ -199,7 +203,8 @@ for (var ii = 0; ii < varyingTypes.length; ++ii) {
|
||||||
|
fShaderSource: wtu.replaceParams(fVaryingTestSource, generateCode(minVars), info),
|
||||||
|
fShaderSuccess: true,
|
||||||
|
linkSuccess: true,
|
||||||
|
- passMsg: "shaders with " + minVars + " varyings of " + info.type + " (the minimum required) should succeed",
|
||||||
|
+ // Try to use deterministic test names
|
||||||
|
+ passMsg: "shaders with the minimum number of varyings of " + info.type + " should succeed",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue