mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00: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",
|
||||
"servo_config",
|
||||
"sparkle",
|
||||
"surfman 0.1.4",
|
||||
"surfman-chains 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"surfman",
|
||||
"surfman-chains",
|
||||
"surfman-chains-api",
|
||||
"time",
|
||||
"webrender",
|
||||
"webrender_api",
|
||||
"webrender_surfman",
|
||||
"webrender_traits",
|
||||
"webxr-api",
|
||||
]
|
||||
|
@ -591,6 +592,12 @@ version = "0.1.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6da2b592f5a2e590c3d94c44313bab369f2286cfe1e4134c830bf3317814866"
|
||||
|
||||
[[package]]
|
||||
name = "cgl"
|
||||
version = "0.2.3"
|
||||
|
@ -772,6 +779,7 @@ dependencies = [
|
|||
"toml",
|
||||
"webrender",
|
||||
"webrender_api",
|
||||
"webrender_surfman",
|
||||
"webxr",
|
||||
]
|
||||
|
||||
|
@ -3203,11 +3211,12 @@ dependencies = [
|
|||
"sparkle",
|
||||
"style",
|
||||
"style_traits",
|
||||
"surfman 0.1.4",
|
||||
"surfman",
|
||||
"webdriver_server",
|
||||
"webgpu",
|
||||
"webrender",
|
||||
"webrender_api",
|
||||
"webrender_surfman",
|
||||
"webrender_traits",
|
||||
"webxr",
|
||||
"webxr-api",
|
||||
|
@ -3976,11 +3985,6 @@ version = "0.3.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
|
||||
|
||||
[[package]]
|
||||
name = "osmesa-src"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/servo/osmesa-src#1a9519c3675ebc1117cbb18ed6db420b5941cb8b"
|
||||
|
||||
[[package]]
|
||||
name = "osmesa-sys"
|
||||
version = "0.1.2"
|
||||
|
@ -4946,22 +4950,21 @@ dependencies = [
|
|||
"euclid",
|
||||
"getopts",
|
||||
"gleam 0.9.2",
|
||||
"glutin",
|
||||
"image",
|
||||
"keyboard-types",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"libservo",
|
||||
"log",
|
||||
"osmesa-src",
|
||||
"osmesa-sys",
|
||||
"servo-media",
|
||||
"shellwords",
|
||||
"sig",
|
||||
"surfman",
|
||||
"tinyfiledialogs",
|
||||
"webxr",
|
||||
"webxr-api",
|
||||
"winapi",
|
||||
"winit",
|
||||
"winres",
|
||||
]
|
||||
|
||||
|
@ -5025,8 +5028,8 @@ dependencies = [
|
|||
"log",
|
||||
"servo-media",
|
||||
"sparkle",
|
||||
"surfman 0.2.0",
|
||||
"surfman-chains 0.3.0 (git+https://github.com/asajeffrey/surfman-chains?branch=multi)",
|
||||
"surfman",
|
||||
"surfman-chains",
|
||||
"surfman-chains-api",
|
||||
]
|
||||
|
||||
|
@ -5370,6 +5373,7 @@ dependencies = [
|
|||
"libservo",
|
||||
"log",
|
||||
"servo-media",
|
||||
"surfman",
|
||||
"webxr",
|
||||
"webxr-api",
|
||||
"winapi",
|
||||
|
@ -5386,6 +5390,7 @@ dependencies = [
|
|||
"libc",
|
||||
"log",
|
||||
"simpleservo",
|
||||
"surfman",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -5676,47 +5681,20 @@ dependencies = [
|
|||
"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]]
|
||||
name = "surfman"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/pcwalton/surfman?branch=multi#fb782262617e7ca839a4e487b116a5199afaf963"
|
||||
source = "git+https://github.com/servo/surfman#41ac1ee64bc2d1978aeed0f8bf549c57f20ec7c8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg_aliases",
|
||||
"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",
|
||||
"gl_generator 0.13.1",
|
||||
"io-surface",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
|
@ -5734,27 +5712,13 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "surfman-chains"
|
||||
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 = [
|
||||
"euclid",
|
||||
"fnv",
|
||||
"log",
|
||||
"sparkle",
|
||||
"surfman 0.2.0",
|
||||
"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",
|
||||
"surfman-chains-api",
|
||||
]
|
||||
|
||||
|
@ -6591,18 +6555,28 @@ dependencies = [
|
|||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webrender_surfman"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"euclid",
|
||||
"surfman",
|
||||
"surfman-chains",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webrender_traits"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"euclid",
|
||||
"servo_geometry",
|
||||
"webrender_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webxr"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/webxr#373a2fa762a859054070dad921ace05bea9fa712"
|
||||
source = "git+https://github.com/servo/webxr#0d9c83f333920b98d95adf9666b0a365258990a3"
|
||||
dependencies = [
|
||||
"android_injected_glue",
|
||||
"bindgen",
|
||||
|
@ -6615,8 +6589,8 @@ dependencies = [
|
|||
"log",
|
||||
"openxr",
|
||||
"serde",
|
||||
"surfman 0.1.4",
|
||||
"surfman-chains 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"surfman",
|
||||
"surfman-chains",
|
||||
"time",
|
||||
"webxr-api",
|
||||
"winapi",
|
||||
|
@ -6626,7 +6600,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webxr-api"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/webxr#373a2fa762a859054070dad921ace05bea9fa712"
|
||||
source = "git+https://github.com/servo/webxr#0d9c83f333920b98d95adf9666b0a365258990a3"
|
||||
dependencies = [
|
||||
"euclid",
|
||||
"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" }
|
||||
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" }
|
||||
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"
|
||||
webrender = {git = "https://github.com/servo/webrender"}
|
||||
webrender_api = {git = "https://github.com/servo/webrender"}
|
||||
webrender_surfman = {path = "../webrender_surfman"}
|
||||
webrender_traits = {path = "../webrender_traits"}
|
||||
webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]}
|
||||
# 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-api = "0.2"
|
||||
|
|
|
@ -15,19 +15,19 @@ use std::collections::HashMap;
|
|||
use std::default::Default;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use surfman::platform::generic::universal::context::Context;
|
||||
use surfman::platform::generic::universal::device::Device;
|
||||
use surfman::platform::generic::universal::surface::SurfaceTexture;
|
||||
use surfman::Device;
|
||||
use surfman::SurfaceInfo;
|
||||
use surfman::SurfaceTexture;
|
||||
use surfman_chains::SwapChains;
|
||||
use surfman_chains_api::SwapChainAPI;
|
||||
use surfman_chains_api::SwapChainsAPI;
|
||||
use webrender_surfman::WebrenderSurfman;
|
||||
use webrender_traits::{WebrenderExternalImageApi, WebrenderExternalImageRegistry};
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
|
||||
pub struct WebGLComm {
|
||||
pub webgl_threads: WebGLThreads,
|
||||
pub webxr_swap_chains: SwapChains<WebXRSwapChainId>,
|
||||
pub webxr_swap_chains: SwapChains<WebXRSwapChainId, Device>,
|
||||
pub webxr_surface_providers: SurfaceProviders,
|
||||
pub image_handler: Box<dyn WebrenderExternalImageApi>,
|
||||
pub output_handler: Option<Box<dyn webrender_api::OutputImageHandler>>,
|
||||
|
@ -37,8 +37,7 @@ pub struct WebGLComm {
|
|||
impl WebGLComm {
|
||||
/// Creates a new `WebGLComm` object.
|
||||
pub fn new(
|
||||
device: Device,
|
||||
context: Context,
|
||||
surfman: WebrenderSurfman,
|
||||
webrender_gl: Rc<dyn gleam::gl::Gl>,
|
||||
webrender_api_sender: webrender_api::RenderApiSender,
|
||||
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
||||
|
@ -60,8 +59,8 @@ impl WebGLComm {
|
|||
webrender_swap_chains: webrender_swap_chains.clone(),
|
||||
webxr_swap_chains: webxr_swap_chains.clone(),
|
||||
webxr_surface_providers: webxr_surface_providers.clone(),
|
||||
connection: device.connection(),
|
||||
adapter: device.adapter(),
|
||||
connection: surfman.connection(),
|
||||
adapter: surfman.adapter(),
|
||||
api_type,
|
||||
runnable_receiver,
|
||||
};
|
||||
|
@ -72,7 +71,7 @@ impl WebGLComm {
|
|||
None
|
||||
};
|
||||
|
||||
let external = WebGLExternalImages::new(device, context, webrender_swap_chains);
|
||||
let external = WebGLExternalImages::new(surfman, webrender_swap_chains);
|
||||
|
||||
WebGLThread::run_on_own_thread(init);
|
||||
|
||||
|
@ -89,23 +88,15 @@ impl WebGLComm {
|
|||
|
||||
/// Bridge between the webrender::ExternalImage callbacks and the WebGLThreads.
|
||||
struct WebGLExternalImages {
|
||||
device: Device,
|
||||
context: Context,
|
||||
swap_chains: SwapChains<WebGLContextId>,
|
||||
surfman: WebrenderSurfman,
|
||||
swap_chains: SwapChains<WebGLContextId, Device>,
|
||||
locked_front_buffers: FnvHashMap<WebGLContextId, SurfaceTexture>,
|
||||
}
|
||||
|
||||
impl Drop for WebGLExternalImages {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.device.destroy_context(&mut self.context);
|
||||
}
|
||||
}
|
||||
|
||||
impl WebGLExternalImages {
|
||||
fn new(device: Device, context: Context, swap_chains: SwapChains<WebGLContextId>) -> Self {
|
||||
fn new(surfman: WebrenderSurfman, swap_chains: SwapChains<WebGLContextId, Device>) -> Self {
|
||||
Self {
|
||||
device,
|
||||
context,
|
||||
surfman,
|
||||
swap_chains,
|
||||
locked_front_buffers: FnvHashMap::default(),
|
||||
}
|
||||
|
@ -119,13 +110,10 @@ impl WebGLExternalImages {
|
|||
id: front_buffer_id,
|
||||
size,
|
||||
..
|
||||
} = self.device.surface_info(&front_buffer);
|
||||
} = self.surfman.surface_info(&front_buffer);
|
||||
debug!("... getting texture for surface {:?}", front_buffer_id);
|
||||
let front_buffer_texture = self
|
||||
.device
|
||||
.create_surface_texture(&mut self.context, front_buffer)
|
||||
.unwrap();
|
||||
let gl_texture = front_buffer_texture.gl_texture();
|
||||
let front_buffer_texture = self.surfman.create_surface_texture(front_buffer).unwrap();
|
||||
let gl_texture = self.surfman.surface_texture_object(&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<()> {
|
||||
let locked_front_buffer = self.locked_front_buffers.remove(&id)?;
|
||||
let locked_front_buffer = self
|
||||
.device
|
||||
.destroy_surface_texture(&mut self.context, locked_front_buffer)
|
||||
.surfman
|
||||
.destroy_surface_texture(locked_front_buffer)
|
||||
.unwrap();
|
||||
|
||||
debug!("... unlocked chain {:?}", id);
|
||||
|
|
|
@ -47,7 +47,6 @@ use euclid::default::Size2D;
|
|||
use fnv::FnvHashMap;
|
||||
use half::f16;
|
||||
use pixels::{self, PixelFormat};
|
||||
use servo_config::opts;
|
||||
use sparkle::gl;
|
||||
use sparkle::gl::GLint;
|
||||
use sparkle::gl::GLuint;
|
||||
|
@ -59,12 +58,12 @@ use std::slice;
|
|||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use surfman;
|
||||
use surfman::platform::generic::universal::adapter::Adapter;
|
||||
use surfman::platform::generic::universal::connection::Connection;
|
||||
use surfman::platform::generic::universal::context::Context;
|
||||
use surfman::platform::generic::universal::device::Device;
|
||||
use surfman::Adapter;
|
||||
use surfman::Connection;
|
||||
use surfman::Context;
|
||||
use surfman::ContextAttributeFlags;
|
||||
use surfman::ContextAttributes;
|
||||
use surfman::Device;
|
||||
use surfman::GLVersion;
|
||||
use surfman::SurfaceAccess;
|
||||
use surfman::SurfaceInfo;
|
||||
|
@ -87,30 +86,130 @@ struct GLContextData {
|
|||
attributes: GLContextAttributes,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GLState {
|
||||
webgl_version: WebGLVersion,
|
||||
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),
|
||||
scissor_test_enabled: bool,
|
||||
// The WebGL view of the stencil write mask (see comment re `color_write_mask`)
|
||||
stencil_write_mask: (u32, u32),
|
||||
stencil_test_enabled: bool,
|
||||
stencil_clear_value: i32,
|
||||
// The WebGL view of the depth write mask (see comment re `color_write_mask`)
|
||||
depth_write_mask: bool,
|
||||
depth_test_enabled: bool,
|
||||
depth_clear_value: f64,
|
||||
// True when the default framebuffer is bound to DRAW_FRAMEBUFFER
|
||||
drawing_to_default_framebuffer: bool,
|
||||
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 {
|
||||
fn default() -> GLState {
|
||||
GLState {
|
||||
gl_version: GLVersion { major: 1, minor: 0 },
|
||||
webgl_version: WebGLVersion::WebGL1,
|
||||
requested_flags: ContextAttributeFlags::empty(),
|
||||
color_write_mask: [true, true, true, true],
|
||||
clear_color: (0., 0., 0., 0.),
|
||||
scissor_test_enabled: false,
|
||||
// Should these be 0xFFFF_FFFF?
|
||||
stencil_write_mask: (0, 0),
|
||||
stencil_test_enabled: false,
|
||||
stencil_clear_value: 0,
|
||||
depth_write_mask: true,
|
||||
depth_test_enabled: false,
|
||||
depth_clear_value: 1.,
|
||||
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.
|
||||
sender: WebGLSender<WebGLMsg>,
|
||||
/// The swap chains used by webrender
|
||||
webrender_swap_chains: SwapChains<WebGLContextId>,
|
||||
webrender_swap_chains: SwapChains<WebGLContextId, Device>,
|
||||
/// 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.
|
||||
webxr_surface_providers: SurfaceProviders,
|
||||
/// 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 WebGlRunnable = Box<dyn FnOnce() + Send>;
|
||||
pub type WebGlRunnable = Box<dyn FnOnce(&Device) + Send>;
|
||||
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.
|
||||
pub(crate) struct WebGLThreadInit {
|
||||
|
@ -161,8 +260,8 @@ pub(crate) struct WebGLThreadInit {
|
|||
pub external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
||||
pub sender: WebGLSender<WebGLMsg>,
|
||||
pub receiver: WebGLReceiver<WebGLMsg>,
|
||||
pub webrender_swap_chains: SwapChains<WebGLContextId>,
|
||||
pub webxr_swap_chains: SwapChains<WebXRSwapChainId>,
|
||||
pub webrender_swap_chains: SwapChains<WebGLContextId, Device>,
|
||||
pub webxr_swap_chains: SwapChains<WebXRSwapChainId, Device>,
|
||||
pub connection: Connection,
|
||||
pub adapter: Adapter,
|
||||
pub api_type: gl::GlType,
|
||||
|
@ -190,7 +289,9 @@ impl WebGLThread {
|
|||
}: WebGLThreadInit,
|
||||
) -> Self {
|
||||
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(),
|
||||
contexts: Default::default(),
|
||||
cached_context_info: Default::default(),
|
||||
|
@ -236,7 +337,7 @@ impl WebGLThread {
|
|||
}
|
||||
recv(self.runnable_receiver) -> msg => {
|
||||
if let Ok(msg) = msg {
|
||||
msg();
|
||||
msg(&self.device);
|
||||
} else {
|
||||
self.runnable_receiver = crossbeam_channel::never();
|
||||
}
|
||||
|
@ -303,7 +404,7 @@ impl WebGLThread {
|
|||
.unwrap();
|
||||
},
|
||||
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) => {
|
||||
self.remove_webgl_context(ctx_id);
|
||||
|
@ -394,21 +495,35 @@ impl WebGLThread {
|
|||
requested_size: Size2D<u32>,
|
||||
attributes: GLContextAttributes,
|
||||
) -> 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.
|
||||
// Clear it to ensure that make_current() is called in subsequent commands.
|
||||
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 {
|
||||
version: webgl_version.to_surfman_version(),
|
||||
flags: attributes.to_surfman_context_attribute_flags(webgl_version),
|
||||
version: webgl_version.to_surfman_version(self.api_type),
|
||||
flags: flags,
|
||||
};
|
||||
|
||||
let context_descriptor = self
|
||||
.device
|
||||
.create_context_descriptor(&context_attributes)
|
||||
.unwrap();
|
||||
.map_err(|err| format!("Failed to create context descriptor: {:?}", err))?;
|
||||
|
||||
let safe_size = Size2D::new(
|
||||
requested_size.width.min(SAFE_VIEWPORT_DIMS[0]).max(1),
|
||||
|
@ -423,30 +538,30 @@ impl WebGLThread {
|
|||
let mut ctx = self
|
||||
.device
|
||||
.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
|
||||
.device
|
||||
.create_surface(&ctx, surface_access, &surface_type)
|
||||
.expect("Failed to create the initial surface!");
|
||||
.create_surface(&ctx, surface_access, surface_type)
|
||||
.map_err(|err| format!("Failed to create the initial surface: {:?}", err))?;
|
||||
self.device
|
||||
.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
|
||||
self.device
|
||||
.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(
|
||||
self.external_images
|
||||
.lock()
|
||||
.unwrap()
|
||||
.expect("Lock poisoned?")
|
||||
.next_id(WebrenderImageHandlerType::WebGL)
|
||||
.0,
|
||||
);
|
||||
|
||||
self.webrender_swap_chains
|
||||
.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
|
||||
.webrender_swap_chains
|
||||
|
@ -456,7 +571,7 @@ impl WebGLThread {
|
|||
debug!(
|
||||
"Created webgl context {:?}/{:?}",
|
||||
id,
|
||||
self.device.context_id(&ctx)
|
||||
self.device.context_id(&ctx),
|
||||
);
|
||||
|
||||
let gl = match self.api_type {
|
||||
|
@ -475,34 +590,33 @@ impl WebGLThread {
|
|||
debug!("Resizing swap chain from {} to {}", safe_size, size);
|
||||
swap_chain
|
||||
.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();
|
||||
let framebuffer = self
|
||||
.device
|
||||
.context_surface_info(&ctx)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.map_err(|err| format!("Failed to get context surface info: {:?}", err))?
|
||||
.ok_or_else(|| format!("Failed to get context surface info"))?
|
||||
.framebuffer_object;
|
||||
|
||||
gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer);
|
||||
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.clear_color(0., 0., 0., 0.);
|
||||
gl.clear_color(0., 0., 0., !has_alpha as u32 as f32);
|
||||
gl.clear_depth(1.);
|
||||
gl.clear_stencil(0);
|
||||
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);
|
||||
|
||||
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 default_vao = if let Some(vao) =
|
||||
WebGLImpl::create_vertex_array(&gl, use_apple_vertex_array, webgl_version)
|
||||
|
@ -517,9 +631,15 @@ impl WebGLThread {
|
|||
let state = GLState {
|
||||
gl_version,
|
||||
webgl_version,
|
||||
requested_flags,
|
||||
default_vao,
|
||||
..Default::default()
|
||||
};
|
||||
debug!("Created state {:?}", state);
|
||||
|
||||
state.restore_invariant(&*gl);
|
||||
debug_assert_eq!(gl.get_error(), gl::NO_ERROR);
|
||||
|
||||
self.contexts.insert(
|
||||
id,
|
||||
GLContextData {
|
||||
|
@ -549,8 +669,7 @@ impl WebGLThread {
|
|||
&mut self,
|
||||
context_id: WebGLContextId,
|
||||
requested_size: Size2D<u32>,
|
||||
sender: WebGLSender<Result<(), String>>,
|
||||
) {
|
||||
) -> Result<(), String> {
|
||||
let data = Self::make_current_if_needed_mut(
|
||||
&self.device,
|
||||
context_id,
|
||||
|
@ -568,16 +687,17 @@ impl WebGLThread {
|
|||
|
||||
// Resize the swap chains
|
||||
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
|
||||
.resize(&mut self.device, &mut data.ctx, size.to_i32())
|
||||
.expect("Failed to resize swap chain");
|
||||
// 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");
|
||||
.map_err(|err| format!("Failed to resize swap chain: {:?}", err))?;
|
||||
swap_chain
|
||||
.clear_surface(&mut self.device, &mut data.ctx, &*data.gl)
|
||||
.expect("Failed to clear resized swap chain");
|
||||
.clear_surface(&mut self.device, &mut data.ctx, &*data.gl, clear_color)
|
||||
.map_err(|err| format!("Failed to clear resized swap chain: {:?}", err))?;
|
||||
} else {
|
||||
error!("Failed to find swap chain");
|
||||
}
|
||||
|
@ -587,11 +707,9 @@ impl WebGLThread {
|
|||
|
||||
// Update WR image if needed.
|
||||
let info = self.cached_context_info.get_mut(&context_id).unwrap();
|
||||
let context_descriptor = self.device.context_descriptor(&data.ctx);
|
||||
let has_alpha = self
|
||||
.device
|
||||
.context_descriptor_attributes(&context_descriptor)
|
||||
.flags
|
||||
let has_alpha = data
|
||||
.state
|
||||
.requested_flags
|
||||
.contains(ContextAttributeFlags::ALPHA);
|
||||
let texture_target = current_wr_texture_target(&self.device);
|
||||
Self::update_wr_external_image(
|
||||
|
@ -605,7 +723,7 @@ impl WebGLThread {
|
|||
|
||||
debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR);
|
||||
|
||||
sender.send(Ok(())).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 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
|
||||
// https://github.com/servo/servo/issues/24604
|
||||
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
|
||||
.clear_surface(&mut self.device, &mut data.ctx, &*data.gl)
|
||||
.clear_surface(&mut self.device, &mut data.ctx, &*data.gl, clear_color)
|
||||
.unwrap();
|
||||
debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR);
|
||||
|
||||
|
@ -1084,7 +1207,10 @@ impl WebGLImpl {
|
|||
state.stencil_clear_value = 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(
|
||||
target,
|
||||
level,
|
||||
|
@ -1109,22 +1235,40 @@ impl WebGLImpl {
|
|||
WebGLCommand::DepthFunc(func) => gl.depth_func(func),
|
||||
WebGLCommand::DepthMask(flag) => {
|
||||
state.depth_write_mask = flag;
|
||||
gl.depth_mask(flag);
|
||||
state.restore_depth_invariant(gl);
|
||||
},
|
||||
WebGLCommand::DepthRange(near, far) => {
|
||||
gl.depth_range(near.max(0.).min(1.) as f64, far.max(0.).min(1.) as f64)
|
||||
},
|
||||
WebGLCommand::Disable(cap) => {
|
||||
if cap == gl::SCISSOR_TEST {
|
||||
WebGLCommand::Disable(cap) => match cap {
|
||||
gl::SCISSOR_TEST => {
|
||||
state.scissor_test_enabled = false;
|
||||
}
|
||||
gl.disable(cap);
|
||||
state.restore_scissor_invariant(gl);
|
||||
},
|
||||
WebGLCommand::Enable(cap) => {
|
||||
if cap == gl::SCISSOR_TEST {
|
||||
gl::DEPTH_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;
|
||||
}
|
||||
gl.enable(cap);
|
||||
state.restore_scissor_invariant(gl);
|
||||
},
|
||||
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) => {
|
||||
let attach = |attachment| {
|
||||
|
@ -1221,7 +1365,7 @@ impl WebGLImpl {
|
|||
},
|
||||
WebGLCommand::StencilMask(mask) => {
|
||||
state.stencil_write_mask = (mask, mask);
|
||||
gl.stencil_mask(mask);
|
||||
state.restore_stencil_invariant(gl);
|
||||
},
|
||||
WebGLCommand::StencilMaskSeparate(face, mask) => {
|
||||
if face == gl::FRONT {
|
||||
|
@ -1229,7 +1373,7 @@ impl WebGLImpl {
|
|||
} else {
|
||||
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::StencilOpSeparate(face, fail, zfail, zpass) => {
|
||||
|
@ -1321,7 +1465,7 @@ impl WebGLImpl {
|
|||
gl.bind_buffer(target, id.map_or(0, WebGLBufferId::get))
|
||||
},
|
||||
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) => {
|
||||
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);
|
||||
},
|
||||
WebGLCommand::GetParameterBool(param, ref sender) => {
|
||||
let value = match param {
|
||||
webgl::ParameterBool::DepthWritemask => state.depth_write_mask,
|
||||
_ => unsafe {
|
||||
let mut value = [0];
|
||||
unsafe {
|
||||
gl.get_boolean_v(param as u32, &mut value);
|
||||
}
|
||||
sender.send(value[0] != 0).unwrap()
|
||||
value[0] != 0
|
||||
},
|
||||
};
|
||||
sender.send(value).unwrap()
|
||||
},
|
||||
WebGLCommand::FenceSync(ref sender) => {
|
||||
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 _);
|
||||
},
|
||||
WebGLCommand::GetParameterBool4(param, ref sender) => {
|
||||
let mut value = [0; 4];
|
||||
unsafe {
|
||||
gl.get_boolean_v(param as u32, &mut value);
|
||||
}
|
||||
let value = [value[0] != 0, value[1] != 0, value[2] != 0, value[3] != 0];
|
||||
let value = match param {
|
||||
webgl::ParameterBool4::ColorWritemask => state.color_write_mask,
|
||||
};
|
||||
sender.send(value).unwrap()
|
||||
},
|
||||
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];
|
||||
unsafe {
|
||||
gl.get_integer_v(param as u32, &mut value);
|
||||
}
|
||||
sender.send(value[0]).unwrap()
|
||||
value[0]
|
||||
},
|
||||
};
|
||||
sender.send(value).unwrap()
|
||||
},
|
||||
WebGLCommand::GetParameterInt2(param, ref sender) => {
|
||||
let mut value = [0; 2];
|
||||
|
@ -1978,15 +2132,25 @@ impl WebGLImpl {
|
|||
sender.send(value).unwrap();
|
||||
},
|
||||
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) => {
|
||||
gl.clear_buffer_fv(buffer, draw_buffer, value)
|
||||
},
|
||||
|
@ -2065,47 +2229,17 @@ impl WebGLImpl {
|
|||
bits | if enabled { bit } else { 0 }
|
||||
});
|
||||
|
||||
if state.scissor_test_enabled {
|
||||
gl.disable(gl::SCISSOR_TEST);
|
||||
}
|
||||
|
||||
if color {
|
||||
gl.color_mask(true, true, true, true);
|
||||
gl.clear_color(0., 0., 0., 0.);
|
||||
}
|
||||
|
||||
if depth {
|
||||
gl.depth_mask(true);
|
||||
gl.clear_depth(1.);
|
||||
}
|
||||
|
||||
if stencil {
|
||||
gl.stencil_mask_separate(gl::FRONT, 0xFFFFFFFF);
|
||||
gl.stencil_mask_separate(gl::BACK, 0xFFFFFFFF);
|
||||
gl.clear_stencil(0);
|
||||
}
|
||||
|
||||
gl.clear(bits);
|
||||
|
||||
if state.scissor_test_enabled {
|
||||
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);
|
||||
}
|
||||
state.restore_invariant(gl);
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
@ -2213,6 +2347,7 @@ impl WebGLImpl {
|
|||
&mut transform_feedback_mode,
|
||||
);
|
||||
}
|
||||
|
||||
ProgramLinkInfo {
|
||||
linked: true,
|
||||
active_attribs,
|
||||
|
@ -2243,7 +2378,7 @@ impl WebGLImpl {
|
|||
// array object functions, but support a set of APPLE extension functions that
|
||||
// provide VAO support instead.
|
||||
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)]
|
||||
|
@ -2427,8 +2562,8 @@ impl WebGLImpl {
|
|||
/// Updates the swap buffers if the context surface needs to be changed
|
||||
fn attach_surface(
|
||||
context_id: WebGLContextId,
|
||||
webrender_swap_chains: &SwapChains<WebGLContextId>,
|
||||
webxr_swap_chains: &SwapChains<WebXRSwapChainId>,
|
||||
webrender_swap_chains: &SwapChains<WebGLContextId, Device>,
|
||||
webxr_swap_chains: &SwapChains<WebXRSwapChainId, Device>,
|
||||
request: WebGLFramebufferBindingRequest,
|
||||
ctx: &mut Context,
|
||||
device: &mut Device,
|
||||
|
@ -2479,6 +2614,7 @@ impl WebGLImpl {
|
|||
request: WebGLFramebufferBindingRequest,
|
||||
ctx: &Context,
|
||||
device: &Device,
|
||||
state: &mut GLState,
|
||||
) {
|
||||
let id = match request {
|
||||
WebGLFramebufferBindingRequest::Explicit(WebGLFramebufferId::Transparent(id)) => {
|
||||
|
@ -2496,6 +2632,12 @@ impl WebGLImpl {
|
|||
|
||||
debug!("WebGLImpl::bind_framebuffer: {:?}", 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]
|
||||
|
@ -2885,27 +3027,41 @@ fn flip_pixels_y(
|
|||
|
||||
// Clamp a size to the current GL context's max viewport
|
||||
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)]
|
||||
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);
|
||||
}
|
||||
Size2D::new(
|
||||
size.width.min(max_size[0] as u32).max(1),
|
||||
size.height.min(max_size[1] as u32).max(1),
|
||||
size.width
|
||||
.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 {
|
||||
fn to_surfman_version(self) -> GLVersion;
|
||||
fn to_surfman_version(self, api_type: gl::GlType) -> GLVersion;
|
||||
}
|
||||
|
||||
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 {
|
||||
WebGLVersion::WebGL1 => GLVersion::new(2, 0),
|
||||
WebGLVersion::WebGL2 => GLVersion::new(3, 0),
|
||||
// We make use of GL_PACK_PIXEL_BUFFER, which needs at least GL2.1
|
||||
// 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(
|
||||
&self,
|
||||
webgl_version: WebGLVersion,
|
||||
api_type: gl::GlType,
|
||||
) -> ContextAttributeFlags;
|
||||
}
|
||||
|
||||
|
@ -2921,12 +3078,13 @@ impl SurfmanContextAttributeFlagsConvert for GLContextAttributes {
|
|||
fn to_surfman_context_attribute_flags(
|
||||
&self,
|
||||
webgl_version: WebGLVersion,
|
||||
api_type: gl::GlType,
|
||||
) -> ContextAttributeFlags {
|
||||
let mut flags = ContextAttributeFlags::empty();
|
||||
flags.set(ContextAttributeFlags::ALPHA, self.alpha);
|
||||
flags.set(ContextAttributeFlags::DEPTH, self.depth);
|
||||
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
|
||||
|
|
|
@ -667,7 +667,7 @@ pub enum WebGLFramebufferId {
|
|||
Opaque(WebGLOpaqueFramebufferId),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub enum WebGLFramebufferBindingRequest {
|
||||
Explicit(WebGLFramebufferId),
|
||||
Default,
|
||||
|
|
|
@ -40,6 +40,7 @@ style_traits = {path = "../style_traits"}
|
|||
time = "0.1.17"
|
||||
webrender = {git = "https://github.com/servo/webrender", features = ["capture"]}
|
||||
webrender_api = {git = "https://github.com/servo/webrender"}
|
||||
webrender_surfman = {path = "../webrender_surfman"}
|
||||
webxr = {git = "https://github.com/servo/webxr"}
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
@ -19,6 +19,7 @@ use gfx_traits::Epoch;
|
|||
use image::{DynamicImage, ImageFormat};
|
||||
use ipc_channel::ipc;
|
||||
use libc::c_void;
|
||||
use log::warn;
|
||||
use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId};
|
||||
use net_traits::image::base::Image;
|
||||
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 webrender_api::units::{DeviceIntPoint, DeviceIntSize, DevicePoint, LayoutVector2D};
|
||||
use webrender_api::{self, HitTestFlags, HitTestResult, ScrollLocation};
|
||||
use webrender_surfman::WebrenderSurfman;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum UnableToComposite {
|
||||
|
@ -178,6 +180,12 @@ pub struct IOCompositor<Window: WindowMethods + ?Sized> {
|
|||
/// The webrender interface, if enabled.
|
||||
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.
|
||||
pub webxr_main_thread: webxr::MainThreadRegistry,
|
||||
|
||||
|
@ -316,6 +324,8 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
webrender: state.webrender,
|
||||
webrender_document: state.webrender_document,
|
||||
webrender_api: state.webrender_api,
|
||||
webrender_surfman: state.webrender_surfman,
|
||||
webrender_gl: state.webrender_gl,
|
||||
webxr_main_thread: state.webxr_main_thread,
|
||||
pending_paint_metrics: HashMap::new(),
|
||||
cursor: Cursor::None,
|
||||
|
@ -345,6 +355,9 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
convert_mouse_to_touch,
|
||||
);
|
||||
|
||||
// Make sure the GL state is OK
|
||||
compositor.assert_gl_framebuffer_complete();
|
||||
|
||||
// Set the size of the root layer.
|
||||
compositor.update_zoom_transform();
|
||||
|
||||
|
@ -352,7 +365,9 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -1238,7 +1253,22 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
) -> Result<Option<Image>, UnableToComposite> {
|
||||
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();
|
||||
|
||||
let wait_for_stable_image = match target {
|
||||
|
@ -1266,7 +1296,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
CompositeTarget::Window => gl::RenderTargetInfo::default(),
|
||||
#[cfg(feature = "gl")]
|
||||
CompositeTarget::WindowAndPng | CompositeTarget::PngFile => gl::initialize_png(
|
||||
&*self.window.gl(),
|
||||
&*self.webrender_gl,
|
||||
FramebufferUintLength::new(size.width),
|
||||
FramebufferUintLength::new(size.height),
|
||||
),
|
||||
|
@ -1347,7 +1377,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
#[cfg(feature = "gl")]
|
||||
CompositeTarget::WindowAndPng => {
|
||||
let img = gl::draw_img(
|
||||
&*self.window.gl(),
|
||||
&*self.webrender_gl,
|
||||
rt_info,
|
||||
x,
|
||||
y,
|
||||
|
@ -1365,7 +1395,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
},
|
||||
#[cfg(feature = "gl")]
|
||||
CompositeTarget::PngFile => {
|
||||
let gl = &*self.window.gl();
|
||||
let gl = &*self.webrender_gl;
|
||||
profile(
|
||||
ProfilerCategory::ImageSaving,
|
||||
None,
|
||||
|
@ -1399,7 +1429,9 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
};
|
||||
|
||||
// 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();
|
||||
|
||||
|
@ -1426,11 +1458,13 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
}
|
||||
|
||||
fn clear_background(&self) {
|
||||
let gl = self.window.gl();
|
||||
let gl = &self.webrender_gl;
|
||||
self.assert_gl_framebuffer_complete();
|
||||
|
||||
// Make framebuffer fully transparent.
|
||||
gl.clear_color(0.0, 0.0, 0.0, 0.0);
|
||||
gl.clear(gleam::gl::COLOR_BUFFER_BIT);
|
||||
self.assert_gl_framebuffer_complete();
|
||||
|
||||
// Make the viewport white.
|
||||
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.clear(gleam::gl::COLOR_BUFFER_BIT);
|
||||
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> {
|
||||
|
|
|
@ -17,12 +17,14 @@ use profile_traits::mem;
|
|||
use profile_traits::time;
|
||||
use script_traits::{AnimationState, EventResult, MouseButton, MouseEventType};
|
||||
use std::fmt::{Debug, Error, Formatter};
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
use style_traits::viewport::ViewportConstraints;
|
||||
use style_traits::CSSPixel;
|
||||
use webrender_api;
|
||||
use webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
||||
use webrender_surfman::WebrenderSurfman;
|
||||
|
||||
/// Sends messages to the compositor.
|
||||
pub struct CompositorProxy {
|
||||
|
@ -166,6 +168,8 @@ pub struct InitialCompositorState {
|
|||
pub webrender: webrender::Renderer,
|
||||
pub webrender_document: webrender_api::DocumentId,
|
||||
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 pending_wr_frame: Arc<AtomicBool>,
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![feature(track_caller)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
use canvas::{SurfaceProviders, WebGlExecutor};
|
||||
use embedder_traits::{EmbedderProxy, EventLoopWaker};
|
||||
use euclid::Scale;
|
||||
#[cfg(feature = "gl")]
|
||||
use gleam::gl;
|
||||
use keyboard_types::KeyboardEvent;
|
||||
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId, TraversalDirection};
|
||||
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_url::ServoUrl;
|
||||
use std::fmt::{Debug, Error, Formatter};
|
||||
#[cfg(feature = "gl")]
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
use style_traits::DevicePixel;
|
||||
|
||||
use webrender_api::units::DevicePoint;
|
||||
use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use webrender_api::ScrollLocation;
|
||||
use webrender_surfman::WebrenderSurfman;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum MouseWindowEvent {
|
||||
|
@ -148,14 +145,10 @@ pub enum AnimationState {
|
|||
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 {
|
||||
/// 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.
|
||||
fn get_coordinates(&self) -> EmbedderCoordinates;
|
||||
/// Set whether the application is currently animating.
|
||||
|
@ -163,12 +156,14 @@ pub trait WindowMethods {
|
|||
/// will want to avoid blocking on UI events, and just
|
||||
/// run the event loop at the vsync interval.
|
||||
fn set_animation_state(&self, _state: AnimationState);
|
||||
/// Get the GL context
|
||||
/// Get the media GL context
|
||||
fn get_gl_context(&self) -> GlContext;
|
||||
/// Get the native display
|
||||
/// Get the media native display
|
||||
fn get_native_display(&self) -> NativeDisplay;
|
||||
/// Get the GL api
|
||||
fn get_gl_api(&self) -> GlApi;
|
||||
/// Get the webrender surfman instance
|
||||
fn webrender_surfman(&self) -> WebrenderSurfman;
|
||||
}
|
||||
|
||||
pub trait EmbedderMethods {
|
||||
|
|
|
@ -321,7 +321,11 @@ mod gen {
|
|||
subpixel_text_antialiasing: {
|
||||
#[serde(rename = "gfx.subpixel-text-antialiasing.enabled")]
|
||||
enabled: bool,
|
||||
}
|
||||
},
|
||||
texture_swizzling: {
|
||||
#[serde(rename = "gfx.texture-swizzling.enabled")]
|
||||
enabled: bool,
|
||||
},
|
||||
},
|
||||
js: {
|
||||
asmjs: {
|
||||
|
|
|
@ -52,12 +52,24 @@ const DEFAULT_DISABLED_GET_PARAMETER_NAMES_WEBGL1: [GLenum; 3] = [
|
|||
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
|
||||
// but must trigger a InvalidEnum error until the related WebGL Extensions are enabled.
|
||||
// Example: https://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/
|
||||
const DEFAULT_DISABLED_GET_TEX_PARAMETER_NAMES_WEBGL1: [GLenum; 1] =
|
||||
[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
|
||||
// but must trigger a InvalidEnum error until the related WebGL Extensions are enabled.
|
||||
// Example: https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
|
||||
|
@ -116,8 +128,14 @@ impl WebGLExtensionFeatures {
|
|||
),
|
||||
WebGLVersion::WebGL2 => (
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
DEFAULT_DISABLED_GET_PARAMETER_NAMES_WEBGL2
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect(),
|
||||
DEFAULT_DISABLED_GET_TEX_PARAMETER_NAMES_WEBGL2
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect(),
|
||||
Default::default(),
|
||||
true,
|
||||
true,
|
||||
|
|
|
@ -233,7 +233,7 @@ impl WebGLRenderbuffer {
|
|||
),
|
||||
);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -277,8 +277,49 @@ impl WebGLShader {
|
|||
},
|
||||
};
|
||||
|
||||
match validator.compile_and_translate(&[&source]) {
|
||||
Ok(translated_source) => {
|
||||
// Replicating
|
||||
// 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);
|
||||
// NOTE: At this point we should be pretty sure that the compilation in the paint thread
|
||||
// will succeed.
|
||||
|
|
|
@ -81,11 +81,12 @@ style_traits = {path = "../style_traits", features = ["servo"]}
|
|||
webgpu = {path = "../webgpu"}
|
||||
webrender = {git = "https://github.com/servo/webrender"}
|
||||
webrender_api = {git = "https://github.com/servo/webrender"}
|
||||
webrender_surfman = {path = "../webrender_surfman"}
|
||||
webrender_traits = {path = "../webrender_traits"}
|
||||
webdriver_server = {path = "../webdriver_server", optional = true}
|
||||
webxr-api = {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 }
|
||||
|
||||
[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 webgpu;
|
||||
pub use webrender_api;
|
||||
pub use webrender_surfman;
|
||||
pub use webrender_traits;
|
||||
|
||||
#[cfg(feature = "webdriver")]
|
||||
|
@ -116,14 +117,9 @@ use std::path::PathBuf;
|
|||
use std::rc::Rc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Mutex};
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
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 surfman::GLApi;
|
||||
use webrender::{RendererKind, ShaderPrecacheFlags};
|
||||
use webrender_surfman::WebrenderSurfman;
|
||||
use webrender_traits::WebrenderImageHandlerType;
|
||||
use webrender_traits::{WebrenderExternalImageHandlers, WebrenderExternalImageRegistry};
|
||||
|
||||
|
@ -353,8 +349,28 @@ where
|
|||
.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.
|
||||
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.
|
||||
PipelineNamespace::install(PipelineNamespaceId(0));
|
||||
|
@ -407,7 +423,7 @@ where
|
|||
let window_size = Size2D::from_untyped(viewport_size.to_i32().to_untyped());
|
||||
|
||||
webrender::Renderer::new(
|
||||
window.gl(),
|
||||
webrender_gl.clone(),
|
||||
render_notifier,
|
||||
webrender::RendererOptions {
|
||||
device_pixel_ratio,
|
||||
|
@ -422,6 +438,7 @@ where
|
|||
},
|
||||
renderer_kind: renderer_kind,
|
||||
enable_subpixel_aa: opts.enable_subpixel_text_antialiasing,
|
||||
allow_texture_swizzling: pref!(gfx.texture_swizzling.enabled),
|
||||
clear_color: None,
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -451,7 +468,8 @@ where
|
|||
.expect("Failed to create WebXR device registry");
|
||||
|
||||
let (webgl_threads, webgl_extras) = create_webgl_threads(
|
||||
&*window,
|
||||
webrender_surfman.clone(),
|
||||
webrender_gl.clone(),
|
||||
&mut webrender,
|
||||
webrender_api_sender.clone(),
|
||||
&mut webxr_main_thread,
|
||||
|
@ -542,6 +560,8 @@ where
|
|||
webrender,
|
||||
webrender_document,
|
||||
webrender_api,
|
||||
webrender_surfman,
|
||||
webrender_gl,
|
||||
webxr_main_thread,
|
||||
pending_wr_frame,
|
||||
},
|
||||
|
@ -806,6 +826,10 @@ where
|
|||
log::set_max_level(filter);
|
||||
}
|
||||
|
||||
pub fn window(&self) -> &Window {
|
||||
&self.compositor.window
|
||||
}
|
||||
|
||||
pub fn deinit(self) {
|
||||
self.compositor.deinit();
|
||||
}
|
||||
|
@ -1030,8 +1054,9 @@ fn create_sandbox() {
|
|||
}
|
||||
|
||||
// Initializes the WebGL thread.
|
||||
fn create_webgl_threads<W>(
|
||||
window: &W,
|
||||
fn create_webgl_threads(
|
||||
webrender_surfman: WebrenderSurfman,
|
||||
webrender_gl: Rc<dyn gl::Gl>,
|
||||
webrender: &mut webrender::Renderer,
|
||||
webrender_api_sender: webrender_api::RenderApiSender,
|
||||
webxr_main_thread: &mut webxr::MainThreadRegistry,
|
||||
|
@ -1040,45 +1065,8 @@ fn create_webgl_threads<W>(
|
|||
) -> (
|
||||
Option<WebGLThreads>,
|
||||
Option<(SurfaceProviders, WebGlExecutor)>,
|
||||
)
|
||||
where
|
||||
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() {
|
||||
) {
|
||||
let gl_type = match webrender_gl.get_type() {
|
||||
gleam::gl::GlType::Gl => sparkle::gl::GlType::Gl,
|
||||
gleam::gl::GlType::Gles => sparkle::gl::GlType::Gles,
|
||||
};
|
||||
|
@ -1091,9 +1079,8 @@ where
|
|||
output_handler,
|
||||
webgl_executor,
|
||||
} = WebGLComm::new(
|
||||
device,
|
||||
context,
|
||||
window.gl(),
|
||||
webrender_surfman,
|
||||
webrender_gl,
|
||||
webrender_api_sender,
|
||||
external_images,
|
||||
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]
|
||||
euclid = "0.20"
|
||||
servo_geometry = {path = "../geometry"}
|
||||
webrender_api = {git = "https://github.com/servo/webrender"}
|
||||
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
#![deny(unsafe_code)]
|
||||
|
||||
use euclid::default::Size2D;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use webrender_api::units::TexelRect;
|
||||
|
||||
/// 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",
|
||||
"tar -czf target.tar.gz" +
|
||||
" target/release/servo" +
|
||||
" target/release/build/osmesa-src-*/output" +
|
||||
" target/release/build/osmesa-src-*/out/src/gallium/targets/osmesa/.libs" +
|
||||
" target/release/build/osmesa-src-*/out/src/mapi/shared-glapi/.libs",
|
||||
" resources",
|
||||
]))
|
||||
.with_artifacts("repo/target.tar.gz")
|
||||
.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
|
||||
tar -czf /target.tar.gz \
|
||||
target/release/servo \
|
||||
target/release/build/osmesa-src-*/output \
|
||||
target/release/build/osmesa-src-*/out/lib/gallium
|
||||
resources
|
||||
sccache --show-stats
|
||||
""" % build_args)
|
||||
.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
|
||||
name_prefix = "Layout 2020 "
|
||||
job_id_prefix = "2020-"
|
||||
args = "--layout-2020"
|
||||
args = ["--layout-2020"]
|
||||
else:
|
||||
start = 0
|
||||
name_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":
|
||||
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),
|
||||
THIS_CHUNK=str(this_chunk),
|
||||
PROCESSES=str(processes),
|
||||
WPT_ARGS=args,
|
||||
WPT_ARGS=" ".join(args),
|
||||
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
|
||||
if this_chunk == 0:
|
||||
task.with_script("""
|
||||
./mach test-wpt-failure
|
||||
time python2 ./mach test-wpt --release --binary-arg=--multiprocess \
|
||||
--processes $PROCESSES \
|
||||
--log-raw test-wpt-mp.log \
|
||||
|
|
|
@ -53,7 +53,6 @@ clipboard = "0.5"
|
|||
euclid = "0.20"
|
||||
getopts = "0.2.11"
|
||||
gleam = "0.9"
|
||||
glutin = "0.21.0"
|
||||
keyboard-types = "0.4.3"
|
||||
lazy_static = "1"
|
||||
libservo = {path = "../../components/servo"}
|
||||
|
@ -61,19 +60,17 @@ libc = "0.2"
|
|||
log = "0.4"
|
||||
servo-media = {git = "https://github.com/servo/media"}
|
||||
shellwords = "1.0.0"
|
||||
surfman = { version = "0.2", features = ["sm-winit", "sm-x11"] }
|
||||
tinyfiledialogs = "3.0"
|
||||
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
|
||||
webxr = { git = "https://github.com/servo/webxr", features = ["ipc", "glwindow", "headless"] }
|
||||
winit = "0.19"
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies]
|
||||
image = "0.23"
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
|
||||
osmesa-sys = "0.1.2"
|
||||
sig = "1.0"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
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::window_trait::WindowPortsMethods;
|
||||
use crate::{headed_window, headless_window};
|
||||
use glutin::WindowId;
|
||||
use winit::WindowId;
|
||||
use servo::compositing::windowing::WindowEvent;
|
||||
use servo::config::opts::{self, parse_url_or_filename};
|
||||
use servo::servo_config::pref;
|
||||
|
@ -20,6 +20,7 @@ use std::collections::HashMap;
|
|||
use std::env;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use webxr::glwindow::GlWindowDiscovery;
|
||||
|
||||
thread_local! {
|
||||
pub static WINDOWS: RefCell<HashMap<WindowId, Rc<dyn WindowPortsMethods>>> = RefCell::new(HashMap::new());
|
||||
|
@ -35,9 +36,6 @@ pub struct App {
|
|||
|
||||
impl App {
|
||||
pub fn run(
|
||||
angle: bool,
|
||||
enable_vsync: bool,
|
||||
use_msaa: bool,
|
||||
no_native_titlebar: bool,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
user_agent: Option<String>,
|
||||
|
@ -50,21 +48,31 @@ impl App {
|
|||
} else {
|
||||
Rc::new(headed_window::Window::new(
|
||||
opts::get().initial_window_size,
|
||||
None,
|
||||
events_loop.clone(),
|
||||
angle,
|
||||
enable_vsync,
|
||||
use_msaa,
|
||||
no_native_titlebar,
|
||||
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.
|
||||
let embedder = Box::new(EmbedderCallbacks::new(
|
||||
window.clone(),
|
||||
events_loop.clone(),
|
||||
window.gl(),
|
||||
xr_discovery,
|
||||
));
|
||||
|
||||
// Handle browser state.
|
||||
|
@ -93,36 +101,36 @@ impl App {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
// App level events
|
||||
glutin::Event::Suspended(suspended) => {
|
||||
winit::Event::Suspended(suspended) => {
|
||||
self.suspended.set(suspended);
|
||||
if !suspended {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Idle);
|
||||
}
|
||||
},
|
||||
glutin::Event::Awakened => {
|
||||
winit::Event::Awakened => {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Idle);
|
||||
},
|
||||
glutin::Event::DeviceEvent { .. } => {},
|
||||
winit::Event::DeviceEvent { .. } => {},
|
||||
|
||||
// Window level events
|
||||
glutin::Event::WindowEvent {
|
||||
winit::Event::WindowEvent {
|
||||
window_id, event, ..
|
||||
} => {
|
||||
return WINDOWS.with(|windows| {
|
||||
match windows.borrow().get(&window_id) {
|
||||
None => {
|
||||
warn!("Got an event from unknown window");
|
||||
glutin::ControlFlow::Break
|
||||
winit::ControlFlow::Break
|
||||
},
|
||||
Some(window) => {
|
||||
// Resize events need to be handled during run_forever
|
||||
let cont = if let glutin::WindowEvent::Resized(_) = event {
|
||||
glutin::ControlFlow::Continue
|
||||
let cont = if let winit::WindowEvent::Resized(_) = event {
|
||||
winit::ControlFlow::Continue
|
||||
} else {
|
||||
glutin::ControlFlow::Break
|
||||
winit::ControlFlow::Break
|
||||
};
|
||||
window.winit_event_to_servo_event(event);
|
||||
return cont;
|
||||
|
@ -131,7 +139,7 @@ impl App {
|
|||
});
|
||||
},
|
||||
}
|
||||
glutin::ControlFlow::Break
|
||||
winit::ControlFlow::Break
|
||||
}
|
||||
|
||||
fn run_loop(self) {
|
||||
|
@ -146,7 +154,7 @@ impl App {
|
|||
// If there's no animations running then we block on the window event loop.
|
||||
self.events_loop.borrow_mut().run_forever(|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
|
||||
// that are handled during run_forever aren't re-entrant,
|
||||
// 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);
|
||||
});
|
||||
}
|
||||
|
||||
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).
|
||||
|
||||
use crate::events_loop::EventsLoop;
|
||||
use crate::window_trait::WindowPortsMethods;
|
||||
use gleam::gl;
|
||||
use servo::canvas::{SurfaceProviders, WebGlExecutor};
|
||||
use servo::compositing::windowing::EmbedderMethods;
|
||||
use servo::embedder_traits::{EmbedderProxy, EventLoopWaker};
|
||||
use servo::servo_config::{opts, pref};
|
||||
use servo::servo_config::pref;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use webxr::glwindow::GlWindowDiscovery;
|
||||
|
||||
pub struct EmbedderCallbacks {
|
||||
window: Rc<dyn WindowPortsMethods>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
gl: Rc<dyn gl::Gl>,
|
||||
xr_discovery: Option<GlWindowDiscovery>,
|
||||
}
|
||||
|
||||
impl EmbedderCallbacks {
|
||||
pub fn new(
|
||||
window: Rc<dyn WindowPortsMethods>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
gl: Rc<dyn gl::Gl>,
|
||||
xr_discovery: Option<GlWindowDiscovery>,
|
||||
) -> EmbedderCallbacks {
|
||||
EmbedderCallbacks {
|
||||
window,
|
||||
events_loop,
|
||||
gl,
|
||||
xr_discovery,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,13 +44,8 @@ impl EmbedderMethods for EmbedderCallbacks {
|
|||
) {
|
||||
if pref!(dom.webxr.test) {
|
||||
xr.register_mock(webxr::headless::HeadlessMockDiscovery::new());
|
||||
} else if !opts::get().headless && pref!(dom.webxr.glwindow) {
|
||||
warn!("Creating test XR device");
|
||||
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);
|
||||
} else if let Some(xr_discovery) = self.xr_discovery.take() {
|
||||
xr.register(xr_discovery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! An event loop implementation that works in headless mode.
|
||||
|
||||
|
||||
use glutin;
|
||||
use winit;
|
||||
use servo::embedder_traits::EventLoopWaker;
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
use std::rc::Rc;
|
||||
|
@ -14,8 +14,8 @@ use std::time;
|
|||
|
||||
#[allow(dead_code)]
|
||||
enum EventLoop {
|
||||
/// A real Glutin windowing event loop.
|
||||
Glutin(Option<glutin::EventsLoop>),
|
||||
/// A real Winit windowing event loop.
|
||||
Winit(Option<winit::EventsLoop>),
|
||||
/// A fake event loop which contains a signalling flag used to ensure
|
||||
/// that pending events get processed in a timely fashion, and a condition
|
||||
/// 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.
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
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")]
|
||||
pub fn new(headless: bool) -> Rc<RefCell<EventsLoop>> {
|
||||
let events_loop = if headless {
|
||||
EventLoop::Headless(Arc::new((Mutex::new(false), Condvar::new())))
|
||||
} else {
|
||||
EventLoop::Glutin(Some(glutin::EventsLoop::new()))
|
||||
EventLoop::Winit(Some(winit::EventsLoop::new()))
|
||||
};
|
||||
Rc::new(RefCell::new(EventsLoop(events_loop)))
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ impl EventsLoop {
|
|||
impl EventsLoop {
|
||||
pub fn create_event_loop_waker(&self) -> Box<dyn EventLoopWaker> {
|
||||
match self.0 {
|
||||
EventLoop::Glutin(ref events_loop) => {
|
||||
EventLoop::Winit(ref events_loop) => {
|
||||
let events_loop = events_loop
|
||||
.as_ref()
|
||||
.expect("Can't create waker for unavailable event loop.");
|
||||
|
@ -55,17 +55,18 @@ impl EventsLoop {
|
|||
Box::new(HeadlessEventLoopWaker(data.clone())),
|
||||
}
|
||||
}
|
||||
pub fn as_winit(&self) -> &glutin::EventsLoop {
|
||||
pub fn as_winit(&self) -> &winit::EventsLoop {
|
||||
match self.0 {
|
||||
EventLoop::Glutin(Some(ref event_loop)) => event_loop,
|
||||
EventLoop::Glutin(None) | EventLoop::Headless(..) =>
|
||||
EventLoop::Winit(Some(ref event_loop)) => event_loop,
|
||||
EventLoop::Winit(None) | EventLoop::Headless(..) =>
|
||||
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 {
|
||||
EventLoop::Glutin(Some(ref mut events_loop)) => events_loop.poll_events(callback),
|
||||
EventLoop::Glutin(None) => (),
|
||||
EventLoop::Winit(Some(ref mut events_loop)) => events_loop.poll_events(callback),
|
||||
EventLoop::Winit(None) => (),
|
||||
EventLoop::Headless(ref data) => {
|
||||
// This is subtle - the use of the event loop in App::run_loop
|
||||
// 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 {
|
||||
EventLoop::Glutin(ref mut events_loop) => {
|
||||
EventLoop::Winit(ref mut events_loop) => {
|
||||
let events_loop = events_loop
|
||||
.as_mut()
|
||||
.expect("Can't run an unavailable event loop.");
|
||||
|
@ -92,7 +93,7 @@ impl EventsLoop {
|
|||
let &(ref flag, ref condvar) = &**data;
|
||||
while !*flag.lock().unwrap() {
|
||||
self.sleep(flag, condvar);
|
||||
if callback(glutin::Event::Awakened) == glutin::ControlFlow::Break {
|
||||
if callback(winit::Event::Awakened) == winit::ControlFlow::Break {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -115,10 +116,10 @@ impl EventsLoop {
|
|||
}
|
||||
|
||||
struct HeadedEventLoopWaker {
|
||||
proxy: Arc<glutin::EventsLoopProxy>,
|
||||
proxy: Arc<winit::EventsLoopProxy>,
|
||||
}
|
||||
impl HeadedEventLoopWaker {
|
||||
fn new(events_loop: &glutin::EventsLoop) -> HeadedEventLoopWaker {
|
||||
fn new(events_loop: &winit::EventsLoop) -> HeadedEventLoopWaker {
|
||||
let proxy = Arc::new(events_loop.create_proxy());
|
||||
HeadedEventLoopWaker { proxy }
|
||||
}
|
||||
|
|
|
@ -2,27 +2,21 @@
|
|||
* 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/. */
|
||||
|
||||
//! A glutin window implementation.
|
||||
//! A winit window implementation.
|
||||
|
||||
use crate::app;
|
||||
use crate::context::GlContext;
|
||||
use crate::events_loop::EventsLoop;
|
||||
use crate::keyutils::keyboard_event_from_winit;
|
||||
use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT};
|
||||
use euclid::{
|
||||
Angle, default::Size2D as UntypedSize2D, Point2D, Rotation3D, Scale, Size2D, UnknownUnit,
|
||||
Angle, Point2D, Rotation3D, Scale, Size2D, UnknownUnit,
|
||||
Vector2D, Vector3D,
|
||||
};
|
||||
use gleam::gl;
|
||||
use glutin::dpi::{LogicalPosition, LogicalSize, PhysicalSize};
|
||||
use winit::dpi::{LogicalPosition, LogicalSize, PhysicalSize};
|
||||
#[cfg(target_os = "macos")]
|
||||
use glutin::os::macos::{ActivationPolicy, WindowBuilderExt};
|
||||
#[cfg(target_os = "linux")]
|
||||
use glutin::os::unix::WindowExt;
|
||||
use glutin::Api;
|
||||
use winit::os::macos::{ActivationPolicy, WindowBuilderExt};
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
use glutin::Icon;
|
||||
use glutin::{ElementState, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode};
|
||||
use winit::Icon;
|
||||
use winit::{ElementState, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode};
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
use image;
|
||||
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::embedder_traits::Cursor;
|
||||
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::style_traits::DevicePixel;
|
||||
use servo::webrender_api::ScrollLocation;
|
||||
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use servo::webrender_surfman::WebrenderSurfman;
|
||||
use servo_media::player::context::{GlApi, GlContext as PlayerGLContext, NativeDisplay};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::mem;
|
||||
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")]
|
||||
use winapi;
|
||||
|
||||
const MULTISAMPLES: u16 = 16;
|
||||
|
||||
#[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() {
|
||||
// Prevent the window from showing in Dock.app, stealing focus,
|
||||
// when generating an output file.
|
||||
|
@ -55,31 +59,25 @@ fn builder_with_platform_options(mut builder: glutin::WindowBuilder) -> glutin::
|
|||
}
|
||||
|
||||
#[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
|
||||
}
|
||||
|
||||
pub struct Window {
|
||||
gl_context: RefCell<GlContext>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
winit_window: winit::Window,
|
||||
webrender_surfman: WebrenderSurfman,
|
||||
screen_size: 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>>,
|
||||
primary_monitor: glutin::MonitorId,
|
||||
primary_monitor: winit::MonitorId,
|
||||
event_queue: RefCell<Vec<WindowEvent>>,
|
||||
mouse_pos: Cell<Point2D<i32, DevicePixel>>,
|
||||
last_pressed: Cell<Option<KeyboardEvent>>,
|
||||
animation_state: Cell<AnimationState>,
|
||||
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>,
|
||||
xr_window_poses: RefCell<Vec<Rc<XRWindowPose>>>,
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
|
@ -97,11 +95,7 @@ fn window_creation_scale_factor() -> Scale<f32, DeviceIndependentPixel, DevicePi
|
|||
impl Window {
|
||||
pub fn new(
|
||||
win_size: Size2D<u32, DeviceIndependentPixel>,
|
||||
sharing: Option<&Window>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
angle: bool,
|
||||
enable_vsync: bool,
|
||||
use_msaa: bool,
|
||||
no_native_titlebar: bool,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
) -> Window {
|
||||
|
@ -117,7 +111,7 @@ impl Window {
|
|||
let width = win_size.to_untyped().width;
|
||||
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_decorations(!no_native_titlebar)
|
||||
.with_transparency(no_native_titlebar)
|
||||
|
@ -127,39 +121,14 @@ impl Window {
|
|||
|
||||
window_builder = builder_with_platform_options(window_builder);
|
||||
|
||||
let mut context_builder = glutin::ContextBuilder::new()
|
||||
.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.");
|
||||
let winit_window = window_builder.build(events_loop.borrow().as_winit()).expect("Failed to create window.");
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
{
|
||||
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 PhysicalSize {
|
||||
|
@ -168,59 +137,43 @@ impl Window {
|
|||
} = primary_monitor.get_dimensions();
|
||||
let screen_size = Size2D::new(screen_width as u32, screen_height as u32);
|
||||
// TODO(ajeffrey): can this fail?
|
||||
let LogicalSize { width, height } = context
|
||||
.window()
|
||||
let LogicalSize { width, height } = winit_window
|
||||
.get_inner_size()
|
||||
.expect("Failed to get window inner size.");
|
||||
let inner_size = Size2D::new(width as u32, height as u32);
|
||||
|
||||
context.window().show();
|
||||
winit_window.show();
|
||||
|
||||
let gl = if let Some(sharing) = sharing {
|
||||
sharing.gl.clone()
|
||||
} else { match context.get_api() {
|
||||
Api::OpenGl => unsafe {
|
||||
gl::GlFns::load_with(|s| context.get_proc_address(s) as *const _)
|
||||
},
|
||||
Api::OpenGlEs => unsafe {
|
||||
gl::GlesFns::load_with(|s| context.get_proc_address(s) as *const _)
|
||||
},
|
||||
Api::WebGl => unreachable!("webgl is unsupported"),
|
||||
} };
|
||||
// Initialize surfman
|
||||
let connection = Connection::from_winit_window(&winit_window).expect("Failed to create connection");
|
||||
let adapter = connection.create_adapter().expect("Failed to create adapter");
|
||||
let native_widget = connection
|
||||
.create_native_widget_from_winit_window(&winit_window)
|
||||
.expect("Failed to create native widget");
|
||||
let surface_type = SurfaceType::Widget { native_widget };
|
||||
let webrender_surfman = WebrenderSurfman::create(
|
||||
&connection,
|
||||
&adapter,
|
||||
surface_type,
|
||||
).expect("Failed to create WR surfman");
|
||||
|
||||
gl.clear_color(0.6, 0.6, 0.6, 1.0);
|
||||
gl.clear(gl::COLOR_BUFFER_BIT);
|
||||
gl.finish();
|
||||
|
||||
let context = GlContext::Current(context);
|
||||
|
||||
debug!("Created window {:?}", context.window().id());
|
||||
let window = Window {
|
||||
gl_context: RefCell::new(context),
|
||||
events_loop,
|
||||
debug!("Created window {:?}", winit_window.id());
|
||||
Window {
|
||||
winit_window,
|
||||
webrender_surfman,
|
||||
event_queue: RefCell::new(vec![]),
|
||||
mouse_down_button: Cell::new(None),
|
||||
mouse_down_point: Cell::new(Point2D::new(0, 0)),
|
||||
mouse_pos: Cell::new(Point2D::new(0, 0)),
|
||||
last_pressed: Cell::new(None),
|
||||
gl: gl.clone(),
|
||||
animation_state: Cell::new(AnimationState::Idle),
|
||||
fullscreen: Cell::new(false),
|
||||
inner_size: Cell::new(inner_size),
|
||||
primary_monitor,
|
||||
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,
|
||||
};
|
||||
|
||||
window.present();
|
||||
|
||||
window
|
||||
xr_window_poses: RefCell::new(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_received_character(&self, mut ch: char) {
|
||||
|
@ -245,7 +198,10 @@ impl Window {
|
|||
KeyboardEvent::default()
|
||||
};
|
||||
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
|
||||
.borrow_mut()
|
||||
.push(WindowEvent::Keyboard(event));
|
||||
|
@ -258,68 +214,21 @@ impl Window {
|
|||
self.last_pressed.set(Some(event));
|
||||
} else if event.key != Key::Unidentified {
|
||||
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
|
||||
.borrow_mut()
|
||||
.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
|
||||
fn handle_mouse(
|
||||
&self,
|
||||
button: glutin::MouseButton,
|
||||
action: glutin::ElementState,
|
||||
button: winit::MouseButton,
|
||||
action: winit::ElementState,
|
||||
coords: Point2D<i32, DevicePixel>,
|
||||
) {
|
||||
use servo::script_traits::MouseButton;
|
||||
|
@ -359,7 +268,7 @@ impl Window {
|
|||
}
|
||||
|
||||
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> {
|
||||
|
@ -385,33 +294,31 @@ impl WindowPortsMethods for Window {
|
|||
fn page_height(&self) -> f32 {
|
||||
let dpr = self.servo_hidpi_factor();
|
||||
let size = self
|
||||
.gl_context
|
||||
.borrow()
|
||||
.window()
|
||||
.winit_window
|
||||
.get_inner_size()
|
||||
.expect("Failed to get window inner size.");
|
||||
size.height as f32 * dpr.get()
|
||||
}
|
||||
|
||||
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) {
|
||||
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()))
|
||||
}
|
||||
|
||||
fn set_position(&self, point: DeviceIntPoint) {
|
||||
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()))
|
||||
}
|
||||
|
||||
fn set_fullscreen(&self, state: bool) {
|
||||
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 });
|
||||
}
|
||||
self.fullscreen.set(state);
|
||||
|
@ -422,7 +329,7 @@ impl WindowPortsMethods for Window {
|
|||
}
|
||||
|
||||
fn set_cursor(&self, cursor: Cursor) {
|
||||
use glutin::MouseCursor;
|
||||
use winit::MouseCursor;
|
||||
|
||||
let winit_cursor = match cursor {
|
||||
Cursor::Default => MouseCursor::Default,
|
||||
|
@ -461,27 +368,27 @@ impl WindowPortsMethods for Window {
|
|||
Cursor::ZoomOut => MouseCursor::ZoomOut,
|
||||
_ => MouseCursor::Default,
|
||||
};
|
||||
self.gl_context.borrow_mut().window().set_cursor(winit_cursor);
|
||||
self.winit_window.set_cursor(winit_cursor);
|
||||
}
|
||||
|
||||
fn is_animating(&self) -> bool {
|
||||
self.animation_state.get() == AnimationState::Animating
|
||||
}
|
||||
|
||||
fn id(&self) -> glutin::WindowId {
|
||||
self.gl_context.borrow().window().id()
|
||||
fn id(&self) -> winit::WindowId {
|
||||
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 {
|
||||
glutin::WindowEvent::ReceivedCharacter(ch) => self.handle_received_character(ch),
|
||||
glutin::WindowEvent::KeyboardInput { input, .. } => self.handle_keyboard_input(input),
|
||||
glutin::WindowEvent::MouseInput { state, button, .. } => {
|
||||
winit::WindowEvent::ReceivedCharacter(ch) => self.handle_received_character(ch),
|
||||
winit::WindowEvent::KeyboardInput { input, .. } => self.handle_keyboard_input(input),
|
||||
winit::WindowEvent::MouseInput { state, button, .. } => {
|
||||
if button == MouseButton::Left || button == MouseButton::Right {
|
||||
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 (x, y): (i32, i32) = pos.into();
|
||||
self.mouse_pos.set(Point2D::new(x, y));
|
||||
|
@ -491,7 +398,7 @@ impl WindowPortsMethods for Window {
|
|||
x as f32, y as f32,
|
||||
)));
|
||||
},
|
||||
glutin::WindowEvent::MouseWheel { delta, phase, .. } => {
|
||||
winit::WindowEvent::MouseWheel { delta, phase, .. } => {
|
||||
let (mut dx, mut dy, mode) = match delta {
|
||||
MouseScrollDelta::LineDelta(dx, dy) => (dx as f64, (dy * LINE_HEIGHT) as f64,
|
||||
WheelMode::DeltaLine),
|
||||
|
@ -524,7 +431,7 @@ impl WindowPortsMethods for Window {
|
|||
self.event_queue.borrow_mut().push(wheel_event);
|
||||
self.event_queue.borrow_mut().push(scroll_event);
|
||||
},
|
||||
glutin::WindowEvent::Touch(touch) => {
|
||||
winit::WindowEvent::Touch(touch) => {
|
||||
use servo::script_traits::TouchId;
|
||||
|
||||
let phase = winit_phase_to_touch_event_type(touch.phase);
|
||||
|
@ -537,19 +444,19 @@ impl WindowPortsMethods for Window {
|
|||
.borrow_mut()
|
||||
.push(WindowEvent::Touch(phase, id, point));
|
||||
},
|
||||
glutin::WindowEvent::Refresh => {
|
||||
winit::WindowEvent::Refresh => {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Refresh);
|
||||
},
|
||||
glutin::WindowEvent::CloseRequested => {
|
||||
winit::WindowEvent::CloseRequested => {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Quit);
|
||||
},
|
||||
glutin::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.
|
||||
winit::WindowEvent::Resized(size) => {
|
||||
let (width, height) = size.into();
|
||||
let new_size = Size2D::new(width, height);
|
||||
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.event_queue.borrow_mut().push(WindowEvent::Resize);
|
||||
}
|
||||
|
@ -557,75 +464,40 @@ impl WindowPortsMethods for Window {
|
|||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl webxr::glwindow::GlWindow for Window {
|
||||
fn make_current(&self) {
|
||||
debug!("Making window {:?} current", self.gl_context.borrow().window().id());
|
||||
self.gl_context.borrow_mut().make_current();
|
||||
}
|
||||
fn new_glwindow(&self, events_loop: &EventsLoop) -> Box<dyn webxr::glwindow::GlWindow> {
|
||||
let size = self.winit_window.get_outer_size()
|
||||
.expect("Failed to get window outer size");
|
||||
|
||||
fn swap_buffers(&self) {
|
||||
debug!("Swapping buffers on window {:?}", self.gl_context.borrow().window().id());
|
||||
self.gl_context.borrow().swap_buffers();
|
||||
self.gl_context.borrow_mut().make_not_current();
|
||||
}
|
||||
let mut window_builder = winit::WindowBuilder::new()
|
||||
.with_title("Servo XR".to_string())
|
||||
.with_dimensions(size)
|
||||
.with_visibility(true);
|
||||
|
||||
fn size(&self) -> UntypedSize2D<gl::GLsizei> {
|
||||
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)
|
||||
}
|
||||
window_builder = builder_with_platform_options(window_builder);
|
||||
|
||||
fn get_rotation(&self) -> Rotation3D<f32, UnknownUnit, UnknownUnit> {
|
||||
self.xr_rotation.get().clone()
|
||||
}
|
||||
let winit_window = window_builder.build(events_loop.as_winit())
|
||||
.expect("Failed to create window.");
|
||||
|
||||
fn get_translation(&self) -> Vector3D<f32, UnknownUnit> {
|
||||
self.xr_translation.get().clone()
|
||||
}
|
||||
|
||||
fn new_window(&self) -> Result<Rc<dyn webxr::glwindow::GlWindow>, ()> {
|
||||
let window = Rc::new(Window::new(
|
||||
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)
|
||||
let pose = Rc::new(XRWindowPose {
|
||||
xr_rotation: Cell::new(Rotation3D::identity()),
|
||||
xr_translation: Cell::new(Vector3D::zero()),
|
||||
});
|
||||
self.xr_window_poses.borrow_mut().push(pose.clone());
|
||||
Box::new(XRWindow { winit_window, pose })
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowMethods for Window {
|
||||
fn gl(&self) -> Rc<dyn gl::Gl> {
|
||||
self.gl.clone()
|
||||
}
|
||||
|
||||
fn get_coordinates(&self) -> EmbedderCoordinates {
|
||||
// TODO(ajeffrey): can this fail?
|
||||
let dpr = self.device_hidpi_factor();
|
||||
let LogicalSize { width, height } = self
|
||||
.gl_context
|
||||
.borrow()
|
||||
.window()
|
||||
.winit_window
|
||||
.get_outer_size()
|
||||
.expect("Failed to get window outer size.");
|
||||
let LogicalPosition { x, y } = self
|
||||
.gl_context
|
||||
.borrow()
|
||||
.window()
|
||||
.winit_window
|
||||
.get_position()
|
||||
.unwrap_or(LogicalPosition::new(0., 0.));
|
||||
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 LogicalSize { width, height } = self
|
||||
.gl_context
|
||||
.borrow()
|
||||
.window()
|
||||
.winit_window
|
||||
.get_inner_size()
|
||||
.expect("Failed to get window inner size.");
|
||||
let inner_size = (Size2D::new(width as f32, height as f32) * dpr).to_i32();
|
||||
let viewport = DeviceIntRect::new(Point2D::zero(), inner_size);
|
||||
let framebuffer = DeviceIntSize::from_untyped(viewport.size.to_untyped());
|
||||
|
||||
EmbedderCoordinates {
|
||||
viewport,
|
||||
framebuffer,
|
||||
window: (win_size, win_origin),
|
||||
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,
|
||||
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) {
|
||||
self.animation_state.set(state);
|
||||
}
|
||||
|
||||
fn make_gl_context_current(&self) {
|
||||
self.gl_context.borrow_mut().make_current();
|
||||
fn webrender_surfman(&self) -> WebrenderSurfman {
|
||||
self.webrender_surfman.clone()
|
||||
}
|
||||
|
||||
fn get_gl_context(&self) -> PlayerGLContext {
|
||||
if pref!(media.glvideo.enabled) {
|
||||
return self.gl_context.borrow().raw_context();
|
||||
if !pref!(media.glvideo.enabled) {
|
||||
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 {
|
||||
|
@ -679,48 +564,41 @@ impl WindowMethods for Window {
|
|||
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")]
|
||||
{
|
||||
if let Some(display) = self.gl_context.borrow().window().get_wayland_display() {
|
||||
return NativeDisplay::Wayland(display as usize);
|
||||
} else if let Some(display) =
|
||||
self.gl_context.borrow().window().get_xlib_display()
|
||||
{
|
||||
return NativeDisplay::X11(display as usize);
|
||||
}
|
||||
}
|
||||
return match native_connection {
|
||||
NativeConnection::Default(NativeConnection::Default(conn)) =>
|
||||
NativeDisplay::Egl(conn.0 as usize),
|
||||
NativeConnection::Default(NativeConnection::Alternate(conn)) =>
|
||||
NativeDisplay::X11(conn.x11_display as usize),
|
||||
NativeConnection::Alternate(_) => unimplemented!(),
|
||||
};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
{
|
||||
if let Some(display) = self.gl_context.borrow().egl_display() {
|
||||
return NativeDisplay::Egl(display as usize);
|
||||
}
|
||||
}
|
||||
// @TODO(victor): https://github.com/servo/media/pull/315
|
||||
#[cfg(target_os = "macos")]
|
||||
#[allow(unreachable_code)]
|
||||
return unimplemented!();
|
||||
|
||||
NativeDisplay::Unknown
|
||||
#[cfg(not(any(target_os = "linux", target_os = "windows", target_os = "macos")))]
|
||||
return unimplemented!();
|
||||
}
|
||||
|
||||
fn get_gl_api(&self) -> GlApi {
|
||||
let api = self.gl_context.borrow().get_api();
|
||||
|
||||
let version = self.gl.get_string(gl::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);
|
||||
|
||||
let api = self.webrender_surfman.connection().gl_api();
|
||||
let attributes = self.webrender_surfman.context_attributes();
|
||||
let GLVersion { major, minor } = attributes.version;
|
||||
match api {
|
||||
glutin::Api::OpenGl if major >= 3 && minor >= 2 => GlApi::OpenGL3,
|
||||
glutin::Api::OpenGl => GlApi::OpenGL,
|
||||
glutin::Api::OpenGlEs if major > 1 => GlApi::Gles2,
|
||||
glutin::Api::OpenGlEs => GlApi::Gles1,
|
||||
_ => GlApi::None,
|
||||
GLApi::GL if major >= 3 && minor >= 2 => GlApi::OpenGL3,
|
||||
GLApi::GL => GlApi::OpenGL,
|
||||
GLApi::GLES if major > 1 => GlApi::Gles2,
|
||||
GLApi::GLES => GlApi::Gles1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
use crate::events_loop::EventsLoop;
|
||||
use crate::window_trait::WindowPortsMethods;
|
||||
use euclid::{default::Size2D as UntypedSize2D, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
|
||||
use gleam::gl;
|
||||
use glutin;
|
||||
use euclid::{Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
|
||||
use winit;
|
||||
use servo::compositing::windowing::{AnimationState, WindowEvent};
|
||||
use servo::compositing::windowing::{EmbedderCoordinates, WindowMethods};
|
||||
use servo::servo_geometry::DeviceIndependentPixel;
|
||||
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::webrender_surfman::WebrenderSurfman;
|
||||
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;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
struct HeadlessContext {
|
||||
width: u32,
|
||||
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 _
|
||||
}
|
||||
}
|
||||
use surfman::Connection;
|
||||
use surfman::Device;
|
||||
use surfman::NativeWidget;
|
||||
use surfman::SurfaceType;
|
||||
|
||||
pub struct Window {
|
||||
context: HeadlessContext,
|
||||
webrender_surfman: WebrenderSurfman,
|
||||
animation_state: Cell<AnimationState>,
|
||||
fullscreen: Cell<bool>,
|
||||
gl: Rc<dyn gl::Gl>,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
}
|
||||
|
||||
|
@ -99,18 +34,19 @@ impl Window {
|
|||
size: Size2D<u32, DeviceIndependentPixel>,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
) -> Rc<dyn WindowPortsMethods> {
|
||||
let context = HeadlessContext::new(size.width, size.height, None);
|
||||
let gl = unsafe { gl::GlFns::load_with(|s| HeadlessContext::get_proc_address(s)) };
|
||||
|
||||
// Print some information about the headless renderer that
|
||||
// can be useful in diagnosing CI failures on build machines.
|
||||
println!("{}", gl.get_string(gl::VENDOR));
|
||||
println!("{}", gl.get_string(gl::RENDERER));
|
||||
println!("{}", gl.get_string(gl::VERSION));
|
||||
// Initialize surfman
|
||||
let connection = Connection::new().expect("Failed to create connection");
|
||||
let adapter = connection.create_software_adapter().expect("Failed to create adapter");
|
||||
let size = size.to_untyped().to_i32();
|
||||
let surface_type = SurfaceType::Generic { size };
|
||||
let webrender_surfman = WebrenderSurfman::create(
|
||||
&connection,
|
||||
&adapter,
|
||||
surface_type,
|
||||
).expect("Failed to create WR surfman");
|
||||
|
||||
let window = Window {
|
||||
context,
|
||||
gl,
|
||||
webrender_surfman,
|
||||
animation_state: Cell::new(AnimationState::Idle),
|
||||
fullscreen: Cell::new(false),
|
||||
device_pixels_per_px,
|
||||
|
@ -136,13 +72,18 @@ impl WindowPortsMethods for Window {
|
|||
false
|
||||
}
|
||||
|
||||
fn id(&self) -> glutin::WindowId {
|
||||
unsafe { glutin::WindowId::dummy() }
|
||||
fn id(&self) -> winit::WindowId {
|
||||
unsafe { winit::WindowId::dummy() }
|
||||
}
|
||||
|
||||
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();
|
||||
self.context.height as f32 * dpr.get()
|
||||
height as f32 * dpr.get()
|
||||
}
|
||||
|
||||
fn set_fullscreen(&self, state: bool) {
|
||||
|
@ -157,24 +98,27 @@ impl WindowPortsMethods for Window {
|
|||
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.
|
||||
}
|
||||
|
||||
fn new_glwindow(&self, _events_loop: &EventsLoop) -> Box<dyn webxr::glwindow::GlWindow> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowMethods for Window {
|
||||
fn gl(&self) -> Rc<dyn gl::Gl> {
|
||||
self.gl.clone()
|
||||
}
|
||||
|
||||
fn get_coordinates(&self) -> EmbedderCoordinates {
|
||||
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 framebuffer = DeviceIntSize::from_untyped(size.to_untyped());
|
||||
EmbedderCoordinates {
|
||||
viewport,
|
||||
framebuffer,
|
||||
framebuffer: size,
|
||||
window: (size, Point2D::zero()),
|
||||
screen: size,
|
||||
screen_avail: size,
|
||||
|
@ -182,30 +126,10 @@ impl WindowMethods for Window {
|
|||
}
|
||||
}
|
||||
|
||||
fn present(&self) {}
|
||||
|
||||
fn set_animation_state(&self, state: AnimationState) {
|
||||
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 {
|
||||
MediaPlayerCtxt::GlContext::Unknown
|
||||
}
|
||||
|
@ -217,32 +141,17 @@ impl WindowMethods for Window {
|
|||
fn get_gl_api(&self) -> MediaPlayerCtxt::GlApi {
|
||||
MediaPlayerCtxt::GlApi::None
|
||||
}
|
||||
|
||||
fn webrender_surfman(&self) -> WebrenderSurfman {
|
||||
self.webrender_surfman.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl webxr::glwindow::GlWindow for Window {
|
||||
fn make_current(&self) {}
|
||||
fn swap_buffers(&self) {}
|
||||
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_native_widget(&self, _device: &Device) -> NativeWidget {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_rotation(&self) -> Rotation3D<f32, UnknownUnit, UnknownUnit> {
|
||||
Rotation3D::identity()
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode};
|
||||
use winit::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode};
|
||||
use keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers};
|
||||
|
||||
// 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;
|
||||
|
||||
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: map the remaining keys if possible
|
||||
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 {
|
||||
use glutin::VirtualKeyCode::*;
|
||||
use winit::VirtualKeyCode::*;
|
||||
// TODO: add more numpad keys
|
||||
let key = if let Some(key) = key {
|
||||
key
|
||||
|
|
|
@ -13,7 +13,6 @@ extern crate sig;
|
|||
mod app;
|
||||
mod backtrace;
|
||||
mod browser;
|
||||
mod context;
|
||||
mod embedder;
|
||||
mod events_loop;
|
||||
mod headed_window;
|
||||
|
@ -95,12 +94,6 @@ pub fn main() {
|
|||
"clean-shutdown",
|
||||
"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.optopt("", "device-pixel-ratio", "Device pixels per px", "");
|
||||
opts.optopt(
|
||||
|
@ -170,28 +163,19 @@ pub fn main() {
|
|||
process::exit(0);
|
||||
}
|
||||
|
||||
let angle = opts_matches.opt_present("angle");
|
||||
let clean_shutdown = opts_matches.opt_present("clean-shutdown");
|
||||
let do_not_use_native_titlebar =
|
||||
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| {
|
||||
dppx_str.parse().unwrap_or_else(|err| {
|
||||
error!("Error parsing option: --device-pixel-ratio ({})", err);
|
||||
process::exit(1);
|
||||
})
|
||||
});
|
||||
|
||||
let user_agent = opts_matches.opt_str("u");
|
||||
|
||||
App::run(
|
||||
angle,
|
||||
enable_vsync,
|
||||
use_msaa,
|
||||
do_not_use_native_titlebar,
|
||||
device_pixels_per_px,
|
||||
user_agent,
|
||||
);
|
||||
App::run(do_not_use_native_titlebar, device_pixels_per_px, user_agent);
|
||||
|
||||
platform::deinit(clean_shutdown)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
//! Definition of Window.
|
||||
//! Implemented by headless and headed windows.
|
||||
|
||||
use glutin;
|
||||
use crate::events_loop::EventsLoop;
|
||||
use winit;
|
||||
use servo::compositing::windowing::{WindowEvent, WindowMethods};
|
||||
use servo::embedder_traits::Cursor;
|
||||
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)
|
||||
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 id(&self) -> glutin::WindowId;
|
||||
fn id(&self) -> winit::WindowId;
|
||||
fn has_events(&self) -> bool;
|
||||
fn page_height(&self) -> f32;
|
||||
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 set_title(&self, _title: &str) {}
|
||||
fn set_inner_size(&self, _size: DeviceIntSize) {}
|
||||
fn set_position(&self, _point: DeviceIntPoint) {}
|
||||
fn set_fullscreen(&self, _state: bool) {}
|
||||
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"}
|
||||
servo-media = {git = "https://github.com/servo/media"}
|
||||
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 = { git = "https://github.com/asajeffrey/surfman-chains", branch = "multi" }
|
||||
surfman-chains = { git = "https://github.com/asajeffrey/surfman-chains" }
|
||||
|
||||
[build-dependencies]
|
||||
gst-plugin-version-helper = "0.1"
|
||||
|
|
|
@ -76,35 +76,20 @@ use servo::embedder_traits::EventLoopWaker;
|
|||
use servo::msg::constellation_msg::TopLevelBrowsingContextId;
|
||||
use servo::servo_url::ServoUrl;
|
||||
use servo::webrender_api::units::DevicePixel;
|
||||
use servo::webrender_surfman::WebrenderSurfman;
|
||||
use servo::Servo;
|
||||
|
||||
use sparkle::gl;
|
||||
use sparkle::gl::types::GLuint;
|
||||
use sparkle::gl::Gl;
|
||||
|
||||
use surfman::connection::Connection as ConnectionAPI;
|
||||
use surfman::device::Device as DeviceAPI;
|
||||
use surfman::ContextAttributeFlags;
|
||||
use surfman::ContextAttributes;
|
||||
use surfman::GLApi;
|
||||
use surfman::GLVersion;
|
||||
use surfman::SurfaceAccess;
|
||||
use surfman::Connection;
|
||||
use surfman::Context;
|
||||
use surfman::Device;
|
||||
use surfman::SurfaceType;
|
||||
use surfman_chains::SurfmanProvider;
|
||||
use surfman_chains::SwapChain;
|
||||
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::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
|
@ -165,7 +150,7 @@ impl std::fmt::Debug for ConnectionWhichImplementsDebug {
|
|||
|
||||
#[derive(Debug)]
|
||||
enum ServoWebSrcMsg {
|
||||
Start(ConnectionWhichImplementsDebug, GLVersion, ServoUrl),
|
||||
Start(ConnectionWhichImplementsDebug, ServoUrl),
|
||||
GetSwapChain(Sender<SwapChain<Device>>),
|
||||
Resize(Size2D<i32, DevicePixel>),
|
||||
Heartbeat,
|
||||
|
@ -180,41 +165,25 @@ const DEFAULT_FRAME_DURATION: Duration = Duration::from_micros(16_667);
|
|||
|
||||
struct ServoThread {
|
||||
receiver: Receiver<ServoWebSrcMsg>,
|
||||
swap_chain: SwapChain<Device>,
|
||||
gfx: Rc<RefCell<ServoThreadGfx>>,
|
||||
servo: Servo<ServoWebSrcWindow>,
|
||||
}
|
||||
|
||||
struct ServoThreadGfx {
|
||||
device: Device,
|
||||
context: Context,
|
||||
gl: Rc<Gl>,
|
||||
}
|
||||
|
||||
impl ServoThread {
|
||||
fn new(receiver: Receiver<ServoWebSrcMsg>) -> Self {
|
||||
let (connection, version, url) = match receiver.recv() {
|
||||
Ok(ServoWebSrcMsg::Start(connection, version, url)) => (connection.0, version, url),
|
||||
let (connection, url) = match receiver.recv() {
|
||||
Ok(ServoWebSrcMsg::Start(connection, url)) => (connection.0, url),
|
||||
e => panic!("Failed to start ({:?})", e),
|
||||
};
|
||||
info!(
|
||||
"Created new servo thread (GL v{}.{} for {})",
|
||||
version.major, version.minor, url
|
||||
);
|
||||
info!("Created new servo thread for {}", url);
|
||||
let embedder = Box::new(ServoWebSrcEmbedder);
|
||||
let window = Rc::new(ServoWebSrcWindow::new(connection, version));
|
||||
let swap_chain = window.swap_chain.clone();
|
||||
let gfx = window.gfx.clone();
|
||||
let window = Rc::new(ServoWebSrcWindow::new(connection));
|
||||
|
||||
let mut servo = Servo::new(embedder, window, None);
|
||||
|
||||
let id = TopLevelBrowsingContextId::new();
|
||||
servo.handle_events(vec![WindowEvent::NewBrowser(url, id)]);
|
||||
|
||||
Self {
|
||||
receiver,
|
||||
swap_chain,
|
||||
gfx,
|
||||
servo,
|
||||
}
|
||||
Self { receiver, servo }
|
||||
}
|
||||
|
||||
fn run(&mut self) {
|
||||
|
@ -222,9 +191,7 @@ impl ServoThread {
|
|||
debug!("Servo thread handling message {:?}", msg);
|
||||
match msg {
|
||||
ServoWebSrcMsg::Start(..) => error!("Already started"),
|
||||
ServoWebSrcMsg::GetSwapChain(sender) => sender
|
||||
.send(self.swap_chain.clone())
|
||||
.expect("Failed to send swap chain"),
|
||||
ServoWebSrcMsg::GetSwapChain(sender) => self.send_swap_chain(sender),
|
||||
ServoWebSrcMsg::Resize(size) => self.resize(size),
|
||||
ServoWebSrcMsg::Heartbeat => self.servo.handle_events(vec![]),
|
||||
ServoWebSrcMsg::Stop => break,
|
||||
|
@ -233,43 +200,24 @@ impl ServoThread {
|
|||
self.servo.handle_events(vec![WindowEvent::Quit]);
|
||||
}
|
||||
|
||||
fn resize(&mut self, size: Size2D<i32, DevicePixel>) {
|
||||
{
|
||||
let mut gfx = self.gfx.borrow_mut();
|
||||
let gfx = &mut *gfx;
|
||||
self.swap_chain
|
||||
.resize(&mut gfx.device, &mut gfx.context, size.to_untyped())
|
||||
.expect("Failed to resize");
|
||||
gfx.gl.viewport(0, 0, size.width, size.height);
|
||||
let fbo = gfx
|
||||
.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]);
|
||||
}
|
||||
fn send_swap_chain(&mut self, sender: Sender<SwapChain<Device>>) {
|
||||
let swap_chain = self
|
||||
.servo
|
||||
.window()
|
||||
.webrender_surfman
|
||||
.swap_chain()
|
||||
.expect("Failed to get swap chain")
|
||||
.clone();
|
||||
sender.send(swap_chain).expect("Failed to send swap chain");
|
||||
}
|
||||
|
||||
impl Drop for ServoThread {
|
||||
fn drop(&mut self) {
|
||||
let mut gfx = self.gfx.borrow_mut();
|
||||
let gfx = &mut *gfx;
|
||||
self.swap_chain
|
||||
.destroy(&mut gfx.device, &mut gfx.context)
|
||||
.expect("Failed to destroy swap chain")
|
||||
fn resize(&mut self, size: Size2D<i32, DevicePixel>) {
|
||||
let _ = self
|
||||
.servo
|
||||
.window()
|
||||
.webrender_surfman
|
||||
.resize(size.to_untyped());
|
||||
self.servo.handle_events(vec![WindowEvent::Resize]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,154 +238,35 @@ impl EventLoopWaker for ServoWebSrcEmbedder {
|
|||
}
|
||||
|
||||
struct ServoWebSrcWindow {
|
||||
swap_chain: SwapChain<Device>,
|
||||
gfx: Rc<RefCell<ServoThreadGfx>>,
|
||||
gl: Rc<dyn gleam::gl::Gl>,
|
||||
webrender_surfman: WebrenderSurfman,
|
||||
}
|
||||
|
||||
impl ServoWebSrcWindow {
|
||||
fn new(connection: Connection, version: GLVersion) -> Self {
|
||||
let flags = ContextAttributeFlags::DEPTH |
|
||||
ContextAttributeFlags::STENCIL |
|
||||
ContextAttributeFlags::ALPHA;
|
||||
let attributes = ContextAttributes { version, flags };
|
||||
|
||||
fn new(connection: Connection) -> Self {
|
||||
let adapter = connection
|
||||
.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 surface_type = SurfaceType::Generic { size };
|
||||
let surface = device
|
||||
.create_surface(&mut context, access, surface_type)
|
||||
.expect("Failed to create surface");
|
||||
let webrender_surfman = WebrenderSurfman::create(&connection, &adapter, surface_type)
|
||||
.expect("Failed to create surfman");
|
||||
|
||||
device
|
||||
.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,
|
||||
}
|
||||
Self { webrender_surfman }
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowMethods for ServoWebSrcWindow {
|
||||
fn present(&self) {
|
||||
debug!("EMBEDDER present");
|
||||
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 webrender_surfman(&self) -> WebrenderSurfman {
|
||||
self.webrender_surfman.clone()
|
||||
}
|
||||
|
||||
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);
|
||||
let origin = Point2D::origin();
|
||||
EmbedderCoordinates {
|
||||
|
@ -658,11 +487,6 @@ impl BaseSrcImpl for ServoWebSrc {
|
|||
));
|
||||
}
|
||||
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
|
||||
let mut task = BootstrapSurfmanOnGLThread {
|
||||
|
@ -683,7 +507,6 @@ impl BaseSrcImpl for ServoWebSrc {
|
|||
// Inform servo we're starting
|
||||
let _ = self.sender.send(ServoWebSrcMsg::Start(
|
||||
ConnectionWhichImplementsDebug(connection),
|
||||
version,
|
||||
url,
|
||||
));
|
||||
Ok(())
|
||||
|
@ -784,6 +607,26 @@ impl ServoWebSrc {
|
|||
gl_context
|
||||
.activate(true)
|
||||
.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 =
|
||||
NativeConnection::current().expect("Failed to bootstrap native connection");
|
||||
let connection = unsafe { Connection::from_native_connection(native_connection) }
|
||||
|
@ -791,6 +634,7 @@ impl ServoWebSrc {
|
|||
Some(connection)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FillOnGLThread<'a> {
|
||||
servo_web_src: &'a ServoWebSrc,
|
||||
|
@ -840,8 +684,21 @@ impl ServoWebSrc {
|
|||
let device = connection
|
||||
.create_device(&adapter)
|
||||
.expect("Failed to bootstrap surfman device");
|
||||
let native_context =
|
||||
NativeContext::current().expect("Failed to bootstrap native context");
|
||||
#[cfg(target_os = "linux")]
|
||||
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 {
|
||||
device
|
||||
.create_context_from_native_context(native_context)
|
||||
|
@ -995,5 +852,3 @@ impl ServoWebSrc {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement that trait for more platforms
|
||||
|
|
|
@ -12,6 +12,7 @@ ipc-channel = "0.14"
|
|||
libservo = { path = "../../../components/servo" }
|
||||
log = "0.4"
|
||||
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 = { git = "https://github.com/servo/webxr"}
|
||||
|
|
|
@ -32,6 +32,7 @@ use servo::servo_config::{pref, set_pref};
|
|||
use servo::servo_url::ServoUrl;
|
||||
use servo::webrender_api::units::DevicePixel;
|
||||
use servo::webrender_api::ScrollLocation;
|
||||
use servo::webrender_surfman::WebrenderSurfman;
|
||||
use servo::{self, gl, BrowserId, Servo};
|
||||
use servo_media::player::context as MediaPlayerContext;
|
||||
use std::cell::RefCell;
|
||||
|
@ -39,6 +40,8 @@ use std::mem;
|
|||
use std::os::raw::c_void;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use surfman::Connection;
|
||||
use surfman::SurfaceType;
|
||||
|
||||
thread_local! {
|
||||
pub static SERVO: RefCell<Option<ServoGlue>> = RefCell::new(None);
|
||||
|
@ -58,6 +61,7 @@ pub struct InitOptions {
|
|||
pub enable_subpixel_text_antialiasing: bool,
|
||||
pub gl_context_pointer: Option<*const c_void>,
|
||||
pub native_display_pointer: Option<*const c_void>,
|
||||
pub native_widget: *mut c_void,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -84,12 +88,6 @@ impl Coordinates {
|
|||
|
||||
/// Callbacks. Implemented by embedder. Called by Servo.
|
||||
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.
|
||||
fn prompt_alert(&self, msg: String, trusted: bool);
|
||||
/// Ask Yes/No question.
|
||||
|
@ -211,13 +209,28 @@ pub fn init(
|
|||
gl.clear(gl::COLOR_BUFFER_BIT);
|
||||
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 {
|
||||
host_callbacks: callbacks,
|
||||
gl: gl.clone(),
|
||||
coordinates: RefCell::new(init_opts.coordinates),
|
||||
density: init_opts.density,
|
||||
gl_context_pointer: init_opts.gl_context_pointer,
|
||||
native_display_pointer: init_opts.native_display_pointer,
|
||||
webrender_surfman,
|
||||
});
|
||||
|
||||
let embedder_callbacks = Box::new(ServoEmbedderCallbacks {
|
||||
|
@ -723,12 +736,12 @@ struct ServoEmbedderCallbacks {
|
|||
}
|
||||
|
||||
struct ServoWindowCallbacks {
|
||||
gl: Rc<dyn gl::Gl>,
|
||||
host_callbacks: Box<dyn HostTrait>,
|
||||
coordinates: RefCell<Coordinates>,
|
||||
density: f32,
|
||||
gl_context_pointer: Option<*const c_void>,
|
||||
native_display_pointer: Option<*const c_void>,
|
||||
webrender_surfman: WebrenderSurfman,
|
||||
}
|
||||
|
||||
impl EmbedderMethods for ServoEmbedderCallbacks {
|
||||
|
@ -798,7 +811,7 @@ impl EmbedderMethods for ServoEmbedderCallbacks {
|
|||
|
||||
struct GlThread(WebGlExecutor);
|
||||
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);
|
||||
}
|
||||
fn clone(&self) -> Box<dyn webxr::openxr::GlThread> {
|
||||
|
@ -835,19 +848,8 @@ impl EmbedderMethods for ServoEmbedderCallbacks {
|
|||
}
|
||||
|
||||
impl WindowMethods for ServoWindowCallbacks {
|
||||
fn make_gl_context_current(&self) {
|
||||
debug!("WindowMethods::prepare_for_composite");
|
||||
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 webrender_surfman(&self) -> WebrenderSurfman {
|
||||
self.webrender_surfman.clone()
|
||||
}
|
||||
|
||||
fn set_animation_state(&self, state: AnimationState) {
|
||||
|
|
|
@ -18,6 +18,7 @@ log = "0.4"
|
|||
lazy_static = "1"
|
||||
env_logger = "0.7"
|
||||
backtrace = "0.3"
|
||||
surfman = "0.2"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
libc = "0.2"
|
||||
|
|
|
@ -203,8 +203,6 @@ where
|
|||
/// Callback used by Servo internals
|
||||
#[repr(C)]
|
||||
pub struct CHostCallbacks {
|
||||
pub flush: extern "C" fn(),
|
||||
pub make_current: extern "C" fn(),
|
||||
pub on_load_started: extern "C" fn(),
|
||||
pub on_load_ended: extern "C" fn(),
|
||||
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 vslogger_mod_list: *const *const c_char,
|
||||
pub vslogger_mod_size: u32,
|
||||
pub native_widget: *mut c_void,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -442,6 +441,7 @@ unsafe fn init(
|
|||
enable_subpixel_text_antialiasing: opts.enable_subpixel_text_antialiasing,
|
||||
gl_context_pointer: gl_context,
|
||||
native_display_pointer: display,
|
||||
native_widget: opts.native_widget,
|
||||
};
|
||||
|
||||
let wakeup = Box::new(WakeupCallback::new(wakeup));
|
||||
|
@ -750,16 +750,6 @@ impl 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) {
|
||||
debug!("on_load_started");
|
||||
(self.0.on_load_started)();
|
||||
|
|
|
@ -223,34 +223,6 @@ def append_to_path_env(string, env, name):
|
|||
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):
|
||||
if is_windows():
|
||||
arch = {
|
||||
|
|
|
@ -24,7 +24,7 @@ from mach.decorators import (
|
|||
from servo.command_base import (
|
||||
CommandBase,
|
||||
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)]
|
||||
|
||||
if headless:
|
||||
set_osmesa_env(args[0], env, debugger is not None)
|
||||
args.append('-z')
|
||||
|
||||
if software:
|
||||
|
|
|
@ -33,8 +33,8 @@ from mach.decorators import (
|
|||
)
|
||||
|
||||
from servo.command_base import (
|
||||
BuildNotFound, CommandBase,
|
||||
call, check_call, check_output, set_osmesa_env,
|
||||
CommandBase,
|
||||
call, check_call, check_output,
|
||||
)
|
||||
from servo.util import host_triple
|
||||
|
||||
|
@ -197,8 +197,6 @@ class MachCommands(CommandBase):
|
|||
@CommandArgument('--submit', '-a', default=False, action="store_true",
|
||||
help="submit the data to perfherder")
|
||||
def test_perf(self, base=None, date=None, submit=False):
|
||||
self.set_software_rendering_env(True, False)
|
||||
|
||||
env = self.build_env()
|
||||
cmd = ["bash", "test_perf.sh"]
|
||||
if base:
|
||||
|
@ -441,8 +439,6 @@ class MachCommands(CommandBase):
|
|||
|
||||
# Helper for test_css and test_wpt:
|
||||
def wptrunner(self, run_file, **kwargs):
|
||||
self.set_software_rendering_env(kwargs['release'], kwargs['debugger'])
|
||||
|
||||
# By default, Rayon selects the number of worker threads
|
||||
# based on the available CPU count. This doesn't work very
|
||||
# well when running tests on CI, since we run so many
|
||||
|
@ -753,18 +749,6 @@ class MachCommands(CommandBase):
|
|||
return check_call(
|
||||
[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):
|
||||
cmd = "clang-format.exe" if sys.platform == "win32" else "clang-format"
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
"dom.webxr.test": false,
|
||||
"dom.worklet.timeout_ms": 10,
|
||||
"gfx.subpixel-text-antialiasing.enabled": true,
|
||||
"gfx.texture-swizzling.enabled": true,
|
||||
"js.asmjs.enabled": true,
|
||||
"js.asyncstack.enabled": false,
|
||||
"js.baseline.enabled": true,
|
||||
|
|
|
@ -48,10 +48,6 @@ packages = [
|
|||
"quote",
|
||||
"unicode-xid",
|
||||
|
||||
# These can be removed once servo is updated to surfman 0.2
|
||||
"surfman",
|
||||
"surfman-chains",
|
||||
|
||||
# https://github.com/servo/servo/pull/25518
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
|
|
|
@ -947,7 +947,7 @@
|
|||
<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\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>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<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\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\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>
|
||||
</Project>
|
||||
|
|
|
@ -187,51 +187,3 @@ void OpenGLES::Reset() {
|
|||
Cleanup();
|
||||
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();
|
||||
|
||||
EGLSurface
|
||||
CreateSurface(winrt::Windows::UI::Xaml::Controls::SwapChainPanel const &,
|
||||
EGLNativeWindowType
|
||||
GetNativeWindow(winrt::Windows::UI::Xaml::Controls::SwapChainPanel const &,
|
||||
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();
|
||||
|
||||
private:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "pch.h"
|
||||
#include "Servo.h"
|
||||
#include <EGL/egl.h>
|
||||
|
||||
namespace winrt::servo {
|
||||
|
||||
|
@ -21,10 +22,6 @@ void on_url_changed(const char *url) {
|
|||
sServo->Delegate().OnServoURLChanged(char2hstring(url));
|
||||
}
|
||||
|
||||
void flush() { sServo->Delegate().Flush(); }
|
||||
|
||||
void make_current() { sServo->Delegate().MakeCurrent(); }
|
||||
|
||||
void wakeup() { sServo->Delegate().WakeUp(); }
|
||||
|
||||
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,
|
||||
float dpi, ServoDelegate &aDelegate)
|
||||
EGLNativeWindowType eglNativeWindow, float dpi,
|
||||
ServoDelegate &aDelegate)
|
||||
: mWindowHeight(height), mWindowWidth(width), mDelegate(aDelegate) {
|
||||
SetEnvironmentVariableA("PreviewRuntimeEnabled", "1");
|
||||
|
||||
|
@ -119,6 +117,7 @@ Servo::Servo(hstring url, hstring args, GLsizei width, GLsizei height,
|
|||
o.height = mWindowHeight;
|
||||
o.density = dpi;
|
||||
o.enable_subpixel_text_antialiasing = false;
|
||||
o.native_widget = eglNativeWindow;
|
||||
|
||||
// Note about logs:
|
||||
// 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;
|
||||
|
||||
capi::CHostCallbacks c;
|
||||
c.flush = &flush;
|
||||
c.make_current = &make_current;
|
||||
c.on_load_started = &on_load_started;
|
||||
c.on_load_ended = &on_load_ended;
|
||||
c.on_title_changed = &on_title_changed;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
#include <EGL/egl.h>
|
||||
#include "logs.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -23,7 +24,8 @@ class ServoDelegate;
|
|||
|
||||
class Servo {
|
||||
public:
|
||||
Servo(hstring, hstring, GLsizei, GLsizei, float, ServoDelegate &);
|
||||
Servo(hstring, hstring, GLsizei, GLsizei, EGLNativeWindowType, float,
|
||||
ServoDelegate &);
|
||||
~Servo();
|
||||
ServoDelegate &Delegate() { return mDelegate; }
|
||||
|
||||
|
@ -100,8 +102,6 @@ public:
|
|||
virtual void OnServoAnimatingChanged(bool) = 0;
|
||||
virtual void OnServoIMEStateChanged(bool) = 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 OnServoMediaSessionPlaybackStateChange(int) = 0;
|
||||
virtual void OnServoPromptAlert(hstring, bool) = 0;
|
||||
|
|
|
@ -72,7 +72,7 @@ void ServoControl::OnLoaded(IInspectable const &, RoutedEventArgs const &) {
|
|||
InitializeCriticalSection(&mGLLock);
|
||||
InitializeConditionVariable(&mDialogCondVar);
|
||||
InitializeCriticalSection(&mDialogLock);
|
||||
CreateRenderSurface();
|
||||
CreateNativeWindow();
|
||||
StartRenderLoop();
|
||||
}
|
||||
|
||||
|
@ -80,22 +80,26 @@ Controls::SwapChainPanel ServoControl::Panel() {
|
|||
return GetTemplateChild(L"swapChainPanel").as<Controls::SwapChainPanel>();
|
||||
}
|
||||
|
||||
void ServoControl::CreateRenderSurface() {
|
||||
if (mRenderSurface == EGL_NO_SURFACE) {
|
||||
mRenderSurface = mOpenGLES.CreateSurface(Panel(), mDPI);
|
||||
}
|
||||
void ServoControl::CreateNativeWindow() {
|
||||
mPanelWidth = Panel().ActualWidth() * 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() {
|
||||
mOpenGLES.DestroySurface(mRenderSurface);
|
||||
mRenderSurface = EGL_NO_SURFACE;
|
||||
EGLNativeWindowType ServoControl::GetNativeWindow() {
|
||||
EGLNativeWindowType win =
|
||||
static_cast<EGLNativeWindowType>(winrt::get_abi(mNativeWindowProperties));
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
void ServoControl::RecoverFromLostDevice() {
|
||||
StopRenderLoop();
|
||||
DestroyRenderSurface();
|
||||
mOpenGLES.Reset();
|
||||
CreateRenderSurface();
|
||||
StartRenderLoop();
|
||||
}
|
||||
|
||||
|
@ -311,18 +315,12 @@ void ServoControl::RunOnGLThread(std::function<void()> task) {
|
|||
void ServoControl::Loop() {
|
||||
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) {
|
||||
log("Entering loop");
|
||||
ServoDelegate *sd = static_cast<ServoDelegate *>(this);
|
||||
mServo = std::make_unique<Servo>(mInitialURL, mArgs, panelWidth,
|
||||
panelHeight, mDPI, *sd);
|
||||
EGLNativeWindowType win = GetNativeWindow();
|
||||
mServo = std::make_unique<Servo>(mInitialURL, mArgs, mPanelWidth,
|
||||
mPanelHeight, win, mDPI, *sd);
|
||||
} else {
|
||||
// FIXME: this will fail since create_task didn't pick the thread
|
||||
// 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() {
|
||||
RunOnGLThread([=] {});
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "Servo.h"
|
||||
#include "DefaultUrl.h"
|
||||
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
|
||||
namespace winrt::ServoApp::implementation {
|
||||
struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
|
||||
|
||||
|
@ -108,8 +110,6 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
|
|||
virtual void OnServoShutdownComplete();
|
||||
virtual void OnServoTitleChanged(winrt::hstring);
|
||||
virtual void OnServoURLChanged(winrt::hstring);
|
||||
virtual void Flush();
|
||||
virtual void MakeCurrent();
|
||||
virtual bool OnServoAllowNavigation(winrt::hstring);
|
||||
virtual void OnServoAnimatingChanged(bool);
|
||||
virtual void OnServoIMEStateChanged(bool);
|
||||
|
@ -150,14 +150,16 @@ private:
|
|||
std::optional<hstring> secondaryButton,
|
||||
std::optional<hstring> input);
|
||||
|
||||
int mPanelHeight = 0;
|
||||
int mPanelWidth = 0;
|
||||
float mDPI = 1;
|
||||
hstring mInitialURL = DEFAULT_URL;
|
||||
hstring mCurrentUrl = L"";
|
||||
bool mTransient = false;
|
||||
|
||||
Windows::UI::Xaml::Controls::SwapChainPanel ServoControl::Panel();
|
||||
void CreateRenderSurface();
|
||||
void DestroyRenderSurface();
|
||||
void CreateNativeWindow();
|
||||
EGLNativeWindowType GetNativeWindow();
|
||||
void RecoverFromLostDevice();
|
||||
|
||||
void StartRenderLoop();
|
||||
|
@ -204,7 +206,7 @@ private:
|
|||
void TryLoadUri(hstring);
|
||||
|
||||
std::unique_ptr<servo::Servo> mServo;
|
||||
EGLSurface mRenderSurface{EGL_NO_SURFACE};
|
||||
PropertySet mNativeWindowProperties;
|
||||
OpenGLES mOpenGLES;
|
||||
bool mAnimating = false;
|
||||
bool mLooping = false;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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="OpenXR.Loader" version="1.0.3" targetFramework="native" />
|
||||
</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": [
|
||||
"8a7fd1a4201883e63af071122cd5003120dfb23e",
|
||||
"d289bbeabb9b2db31cb6ba50df97d63ccce7d5c6",
|
||||
[
|
||||
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]
|
||||
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)]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,41 +1,72 @@
|
|||
[shader-varying-packing-restrictions.html]
|
||||
bug: https://github.com/servo/servo/issues/20601
|
||||
[WebGL test #2: [unexpected link status\] shaders with varying array of float with 33 elements (one past maximum) accessing last element should fail]
|
||||
[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]
|
||||
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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
[out-of-bounds-uniform-array-access.html]
|
||||
expected: TIMEOUT
|
||||
expected:
|
||||
if os == "linux": TIMEOUT
|
||||
[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]
|
||||
expected:
|
||||
if os == "mac": TIMEOUT
|
||||
[WebGL test #45: getError expected: NO_ERROR. Was INVALID_ENUM : ]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
[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.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
[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).]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
[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]
|
||||
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]
|
||||
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]
|
||||
[WebGL test #2: Framebuffer incomplete.]
|
||||
expected: FAIL
|
||||
expected:
|
||||
if os =="mac": ERROR
|
||||
|
||||
[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]
|
||||
[WebGL test #1: framebuffer not complete]
|
||||
[WebGL test #4: framebuffer not complete]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #2: framebuffer not complete]
|
||||
[WebGL test #1: framebuffer not complete]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #3: framebuffer not complete]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #4: framebuffer not complete]
|
||||
[WebGL test #2: framebuffer not complete]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
[blitframebuffer-scissor-enabled.html]
|
||||
[WebGL test #1: Framebuffer incomplete.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #2: Framebuffer incomplete.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #3: Framebuffer incomplete.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #4: Framebuffer incomplete.]
|
||||
[WebGL test #8: Framebuffer incomplete.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #5: Framebuffer incomplete.]
|
||||
[WebGL test #1: Framebuffer incomplete.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #4: Framebuffer incomplete.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #6: Framebuffer incomplete.]
|
||||
|
@ -20,6 +20,6 @@
|
|||
[WebGL test #7: Framebuffer incomplete.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #8: Framebuffer incomplete.]
|
||||
[WebGL test #5: Framebuffer incomplete.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,31 @@
|
|||
[clear-func-buffer-type-match.html]
|
||||
expected: TIMEOUT
|
||||
[WebGL test #1: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
[WebGL test #18: getError expected: INVALID_OPERATION. Was NO_ERROR : clearBufferiv and RGBA8 buffer]
|
||||
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
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
[framebuffer-unsupported.html]
|
||||
expected: ERROR
|
||||
[WebGL test #4: checkFramebufferStatus expects [FRAMEBUFFER_UNSUPPORTED\], was FRAMEBUFFER_COMPLETE]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #7: checkFramebufferStatus expects [FRAMEBUFFER_UNSUPPORTED\], was FRAMEBUFFER_COMPLETE]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #8: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
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]
|
||||
expected: TIMEOUT
|
||||
[WebGL test #2: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
[WebGL test #2: Framebuffer incomplete.]
|
||||
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
|
||||
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
[line-rendering-quality.html]
|
||||
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]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,10 +1,25 @@
|
|||
[rgb-format-support.html]
|
||||
[WebGL test #15: getError expected: NO_ERROR. Was INVALID_FRAMEBUFFER_OPERATION : should be no errors from clear()]
|
||||
expected: FAIL
|
||||
[WebGL test #24: getError expected: NO_ERROR. Was INVALID_FRAMEBUFFER_OPERATION : should be no errors from clear()]
|
||||
expected:
|
||||
if os == "linux": FAIL
|
||||
|
||||
[WebGL test #14: framebuffer with texture is incomplete]
|
||||
expected: FAIL
|
||||
[WebGL test #23: framebuffer with texture is incomplete]
|
||||
expected:
|
||||
if os == "linux": FAIL
|
||||
|
||||
[WebGL test #13: getError expected: NO_ERROR. Was INVALID_ENUM : should be no errors from texture setup]
|
||||
expected: FAIL
|
||||
[WebGL test #22: getError expected: NO_ERROR. Was INVALID_ENUM : should be no errors from texture setup]
|
||||
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]
|
||||
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).]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -104,3 +108,5 @@
|
|||
[WebGL test #183: getRenderbufferParameter did not generate INVALID_ENUM for invalid parameter enum: NO_ERROR]
|
||||
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]
|
||||
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),
|
||||
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",
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ PATCHES = [
|
|||
("timeout.patch", None),
|
||||
("set-zero-timeout.patch", "js/webgl-test-utils.js"),
|
||||
("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'
|
||||
|
|
|
@ -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