diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 8a413a57b3d..fffb9ad3f7a 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -42,8 +42,7 @@ use style_traits::viewport::ViewportConstraints; use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor}; use time::{now, precise_time_ns, precise_time_s}; use webrender_api::{ - self, DeviceIntPoint, DevicePoint, FramebufferIntRect, FramebufferIntSize, HitTestFlags, - HitTestResult, + self, DeviceIntPoint, DevicePoint, FramebufferIntSize, HitTestFlags, HitTestResult, }; use webrender_api::{LayoutVector2D, ScrollLocation}; use webvr_traits::WebVRMainThreadHeartbeat; @@ -578,16 +577,9 @@ impl IOCompositor { fn send_window_size(&self, size_type: WindowSizeType) { let dppx = self.page_zoom * self.embedder_coordinates.hidpi_factor; - let flipped_viewport = { - let fb_height = self.embedder_coordinates.framebuffer.height; - let mut view = self.embedder_coordinates.viewport.clone(); - view.origin.y = fb_height - view.origin.y - view.size.height; - FramebufferIntRect::from_untyped(&view.to_untyped()) - }; - self.webrender_api.set_document_view( self.webrender_document, - flipped_viewport, + self.embedder_coordinates.get_flipped_viewport(), self.embedder_coordinates.hidpi_factor.get(), ); @@ -1214,8 +1206,19 @@ impl IOCompositor { &self.embedder_coordinates.framebuffer.to_untyped(), ); - self.window.gl().clear_color(1.0, 1.0, 1.0, 0.0); + self.window.gl().clear_color(0.0, 0.0, 0.0, 0.0); self.window.gl().clear(gleam::gl::COLOR_BUFFER_BIT); + let viewport = self.embedder_coordinates.get_flipped_viewport(); + self.window.gl().scissor( + viewport.origin.x, + viewport.origin.y, + viewport.size.width, + viewport.size.height, + ); + self.window.gl().clear_color(1.0, 1.0, 1.0, 1.0); + self.window.gl().enable(gleam::gl::SCISSOR_TEST); + self.window.gl().clear(gleam::gl::COLOR_BUFFER_BIT); + self.window.gl().disable(gleam::gl::SCISSOR_TEST); // Paint the scene. // TODO(gw): Take notice of any errors the renderer returns! diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 66fc50b7dc2..cb15eeb581f 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -18,7 +18,8 @@ use std::fmt::{Debug, Error, Formatter}; use std::rc::Rc; use style_traits::DevicePixel; use webrender_api::{ - DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePoint, FramebufferIntSize, ScrollLocation, + DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePoint, FramebufferIntRect, + FramebufferIntSize, ScrollLocation, }; use webvr::VRServiceManager; use webvr_traits::WebVRMainThreadHeartbeat; @@ -173,3 +174,12 @@ pub struct EmbedderCoordinates { /// Coordinates of the document within the framebuffer. pub viewport: DeviceIntRect, } + +impl EmbedderCoordinates { + pub fn get_flipped_viewport(&self) -> FramebufferIntRect { + let fb_height = self.framebuffer.height; + let mut view = self.viewport.clone(); + view.origin.y = fb_height - view.origin.y - view.size.height; + FramebufferIntRect::from_untyped(&view.to_untyped()) + } +} diff --git a/ports/libmlservo/src/lib.rs b/ports/libmlservo/src/lib.rs index 25035ba9aa7..3af71da4b99 100644 --- a/ports/libmlservo/src/lib.rs +++ b/ports/libmlservo/src/lib.rs @@ -16,7 +16,8 @@ use servo::webrender_api::DevicePixel; use servo::webrender_api::DevicePoint; use servo::webrender_api::LayoutPixel; use simpleservo::{ - self, deinit, gl_glue, EventLoopWaker, HostTrait, InitOptions, MouseButton, ServoGlue, SERVO, + self, deinit, gl_glue, Coordinates, EventLoopWaker, HostTrait, InitOptions, MouseButton, + ServoGlue, SERVO, }; use smallvec::SmallVec; use std::cell::Cell; @@ -114,14 +115,21 @@ pub unsafe extern "C" fn init_servo( let gl = gl_glue::egl::init().expect("EGL initialization failure"); let url = CStr::from_ptr(url).to_str().unwrap_or("about:blank"); + let coordinates = Coordinates::new( + 0, + 0, + width as i32, + height as i32, + width as i32, + height as i32, + ); let opts = InitOptions { args: None, url: Some(url.to_string()), - width: width, - height: height, density: hidpi, enable_subpixel_text_antialiasing: false, vr_pointer: None, + coordinates, }; let wakeup = Box::new(EventLoopWakerInstance); let shut_down_complete = Rc::new(Cell::new(false)); diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs index 6cfc6ec1b9e..ab2528b1775 100644 --- a/ports/libsimpleservo/api/src/lib.rs +++ b/ports/libsimpleservo/api/src/lib.rs @@ -14,16 +14,17 @@ use servo::compositing::windowing::{ }; use servo::embedder_traits::resources::{self, Resource, ResourceReaderMethods}; use servo::embedder_traits::EmbedderMsg; -use servo::euclid::{TypedPoint2D, TypedScale, TypedSize2D, TypedVector2D}; +use servo::euclid::{TypedPoint2D, TypedRect, TypedScale, TypedSize2D, TypedVector2D}; use servo::keyboard_types::{Key, KeyState, KeyboardEvent}; use servo::msg::constellation_msg::TraversalDirection; use servo::script_traits::{TouchEventType, TouchId}; use servo::servo_config::opts; use servo::servo_config::{pref, set_pref}; use servo::servo_url::ServoUrl; +use servo::webrender_api::{DevicePixel, FramebufferPixel, ScrollLocation}; use servo::webvr::{VRExternalShmemPtr, VRMainThreadHeartbeat, VRServiceManager}; -use servo::{self, gl, webrender_api, BrowserId, Servo}; -use std::cell::{Cell, RefCell}; +use servo::{self, gl, BrowserId, Servo}; +use std::cell::RefCell; use std::mem; use std::os::raw::c_void; use std::path::PathBuf; @@ -41,13 +42,34 @@ pub use servo::embedder_traits::EventLoopWaker; pub struct InitOptions { pub args: Option, pub url: Option, - pub width: u32, - pub height: u32, + pub coordinates: Coordinates, pub density: f32, pub vr_pointer: Option<*mut c_void>, pub enable_subpixel_text_antialiasing: bool, } +#[derive(Clone, Debug)] +pub struct Coordinates { + pub viewport: TypedRect, + pub framebuffer: TypedSize2D, +} + +impl Coordinates { + pub fn new( + x: i32, + y: i32, + width: i32, + height: i32, + fb_width: i32, + fb_height: i32, + ) -> Coordinates { + Coordinates { + viewport: TypedRect::new(TypedPoint2D::new(x, y), TypedSize2D::new(width, height)), + framebuffer: TypedSize2D::new(fb_width, fb_height), + } + } +} + /// Callbacks. Implemented by embedder. Called by Servo. pub trait HostTrait { /// Will be called from the thread used for the init call. @@ -150,8 +172,7 @@ pub fn init( let callbacks = Rc::new(ServoCallbacks { gl: gl.clone(), host_callbacks: callbacks, - width: Cell::new(init_opts.width), - height: Cell::new(init_opts.height), + coordinates: RefCell::new(init_opts.coordinates), density: init_opts.density, vr_pointer: init_opts.vr_pointer, waker, @@ -270,10 +291,9 @@ impl ServoGlue { } /// Let Servo know that the window has been resized. - pub fn resize(&mut self, width: u32, height: u32) -> Result<(), &'static str> { + pub fn resize(&mut self, coordinates: Coordinates) -> Result<(), &'static str> { info!("resize"); - self.callbacks.width.set(width); - self.callbacks.height.set(height); + *self.callbacks.coordinates.borrow_mut() = coordinates; self.process_event(WindowEvent::Resize) } @@ -282,7 +302,7 @@ impl ServoGlue { /// dx/dy are scroll deltas. pub fn scroll_start(&mut self, dx: f32, dy: f32, x: i32, y: i32) -> Result<(), &'static str> { let delta = TypedVector2D::new(dx, dy); - let scroll_location = webrender_api::ScrollLocation::Delta(delta); + let scroll_location = ScrollLocation::Delta(delta); let event = WindowEvent::Scroll( scroll_location, TypedPoint2D::new(x, y), @@ -296,7 +316,7 @@ impl ServoGlue { /// dx/dy are scroll deltas. pub fn scroll(&mut self, dx: f32, dy: f32, x: i32, y: i32) -> Result<(), &'static str> { let delta = TypedVector2D::new(dx, dy); - let scroll_location = webrender_api::ScrollLocation::Delta(delta); + let scroll_location = ScrollLocation::Delta(delta); let event = WindowEvent::Scroll( scroll_location, TypedPoint2D::new(x, y), @@ -310,7 +330,7 @@ impl ServoGlue { /// dx/dy are scroll deltas. pub fn scroll_end(&mut self, dx: f32, dy: f32, x: i32, y: i32) -> Result<(), &'static str> { let delta = TypedVector2D::new(dx, dy); - let scroll_location = webrender_api::ScrollLocation::Delta(delta); + let scroll_location = ScrollLocation::Delta(delta); let event = WindowEvent::Scroll(scroll_location, TypedPoint2D::new(x, y), TouchEventType::Up); self.process_event(event) @@ -529,8 +549,7 @@ struct ServoCallbacks { waker: Box, gl: Rc, host_callbacks: Box, - width: Cell, - height: Cell, + coordinates: RefCell, density: f32, vr_pointer: Option<*mut c_void>, } @@ -564,15 +583,13 @@ impl WindowMethods for ServoCallbacks { } fn get_coordinates(&self) -> EmbedderCoordinates { - let fb_size = TypedSize2D::new(self.width.get() as i32, self.height.get() as i32); - let pixel_size = TypedSize2D::new(self.width.get() as i32, self.height.get() as i32); - let viewport = webrender_api::DeviceIntRect::new(TypedPoint2D::zero(), pixel_size); + let coords = self.coordinates.borrow(); EmbedderCoordinates { - viewport, - framebuffer: fb_size, - window: (pixel_size, TypedPoint2D::new(0, 0)), - screen: pixel_size, - screen_avail: pixel_size, + viewport: coords.viewport, + framebuffer: coords.framebuffer, + window: (coords.viewport.size, TypedPoint2D::new(0, 0)), + screen: coords.viewport.size, + screen_avail: coords.viewport.size, hidpi_factor: TypedScale::new(self.density), } } diff --git a/ports/libsimpleservo/capi/src/lib.rs b/ports/libsimpleservo/capi/src/lib.rs index acbf2b0c440..aa23dfda602 100644 --- a/ports/libsimpleservo/capi/src/lib.rs +++ b/ports/libsimpleservo/capi/src/lib.rs @@ -6,7 +6,9 @@ extern crate log; use env_logger; -use simpleservo::{self, gl_glue, EventLoopWaker, HostTrait, InitOptions, ServoGlue, SERVO}; +use simpleservo::{ + self, gl_glue, Coordinates, EventLoopWaker, HostTrait, InitOptions, ServoGlue, SERVO, +}; use std::ffi::{CStr, CString}; use std::mem; use std::os::raw::{c_char, c_void}; @@ -48,8 +50,8 @@ pub struct CHostCallbacks { pub struct CInitOptions { pub args: *const c_char, pub url: *const c_char, - pub width: u32, - pub height: u32, + pub width: i32, + pub height: i32, pub density: f32, pub vr_pointer: *mut c_void, pub enable_subpixel_text_antialiasing: bool, @@ -79,11 +81,12 @@ fn init( let url = unsafe { CStr::from_ptr(opts.url) }; let url = url.to_str().map(|s| s.to_string()).ok(); + let coordinates = Coordinates::new(0, 0, opts.width, opts.height, opts.width, opts.height); + let opts = InitOptions { args, url, - width: opts.width, - height: opts.height, + coordinates, density: opts.density, vr_pointer: if opts.vr_pointer.is_null() { None @@ -140,9 +143,12 @@ pub extern "C" fn set_batch_mode(batch: bool) { } #[no_mangle] -pub extern "C" fn resize(width: u32, height: u32) { +pub extern "C" fn resize(width: i32, height: i32) { debug!("resize {}/{}", width, height); - call(|s| s.resize(width, height)); + call(|s| { + let coordinates = Coordinates::new(0, 0, width, height, width, height); + s.resize(coordinates) + }); } #[no_mangle] diff --git a/ports/libsimpleservo/jniapi/src/lib.rs b/ports/libsimpleservo/jniapi/src/lib.rs index 7f287485677..99210c7a0bb 100644 --- a/ports/libsimpleservo/jniapi/src/lib.rs +++ b/ports/libsimpleservo/jniapi/src/lib.rs @@ -13,7 +13,9 @@ use jni::sys::{jboolean, jfloat, jint, jstring, JNI_TRUE}; use jni::{errors, JNIEnv, JavaVM}; use libc::{dup2, pipe, read}; use log::Level; -use simpleservo::{self, gl_glue, EventLoopWaker, HostTrait, InitOptions, ServoGlue, SERVO}; +use simpleservo::{ + self, gl_glue, Coordinates, EventLoopWaker, HostTrait, InitOptions, ServoGlue, SERVO, +}; use std::os::raw::{c_char, c_int, c_void}; use std::sync::Arc; use std::thread; @@ -129,14 +131,13 @@ pub fn Java_org_mozilla_servoview_JNIServo_deinit(_env: JNIEnv, _class: JClass) } #[no_mangle] -pub fn Java_org_mozilla_servoview_JNIServo_resize( - env: JNIEnv, - _: JClass, - width: jint, - height: jint, -) { - debug!("resize {}/{}", width, height); - call(&env, |s| s.resize(width as u32, height as u32)); +pub fn Java_org_mozilla_servoview_JNIServo_resize(env: JNIEnv, _: JClass, coordinates: JObject) { + let coords = jni_coords_to_rust_coords(&env, coordinates); + debug!("resize {:#?}", coords); + match coords { + Ok(coords) => call(&env, |s| s.resize(coords.clone())), + Err(error) => throw(&env, &error), + } } #[no_mangle] @@ -587,6 +588,28 @@ fn new_string(env: &JNIEnv, s: &str) -> Result { } } +fn jni_coords_to_rust_coords(env: &JNIEnv, obj: JObject) -> Result { + let x = get_non_null_field(env, obj, "x", "I")? + .i() + .map_err(|_| "x not an int")? as i32; + let y = get_non_null_field(env, obj, "y", "I")? + .i() + .map_err(|_| "y not an int")? as i32; + let width = get_non_null_field(env, obj, "width", "I")? + .i() + .map_err(|_| "width not an int")? as i32; + let height = get_non_null_field(env, obj, "height", "I")? + .i() + .map_err(|_| "height not an int")? as i32; + let fb_width = get_non_null_field(env, obj, "fb_width", "I")? + .i() + .map_err(|_| "fb_width not an int")? as i32; + let fb_height = get_non_null_field(env, obj, "fb_height", "I")? + .i() + .map_err(|_| "fb_height not an int")? as i32; + Ok(Coordinates::new(x, y, width, height, fb_width, fb_height)) +} + fn get_field<'a>( env: &'a JNIEnv, obj: JObject, @@ -638,12 +661,6 @@ fn get_options(env: &JNIEnv, opts: JObject) -> Result<(InitOptions, bool, Option let args = get_string(env, opts, "args")?; let url = get_string(env, opts, "url")?; let log_str = get_string(env, opts, "logStr")?; - let width = get_non_null_field(env, opts, "width", "I")? - .i() - .map_err(|_| "width not an int")? as u32; - let height = get_non_null_field(env, opts, "height", "I")? - .i() - .map_err(|_| "height not an int")? as u32; let density = get_non_null_field(env, opts, "density", "F")? .f() .map_err(|_| "densitiy not a float")? as f32; @@ -657,11 +674,19 @@ fn get_options(env: &JNIEnv, opts: JObject) -> Result<(InitOptions, bool, Option let vr_pointer = get_non_null_field(env, opts, "VRExternalContext", "J")? .j() .map_err(|_| "VRExternalContext is not a long")? as *mut c_void; + let coordinates = get_non_null_field( + env, + opts, + "coordinates", + "Lorg/mozilla/servoview/JNIServo$ServoCoordinates;", + )? + .l() + .map_err(|_| "coordinates is not an object")?; + let coordinates = jni_coords_to_rust_coords(&env, coordinates)?; let opts = InitOptions { args, url, - width, - height, + coordinates, density, enable_subpixel_text_antialiasing, vr_pointer: if vr_pointer.is_null() { diff --git a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/JNIServo.java b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/JNIServo.java index 2079eccb705..f2c3bad3873 100644 --- a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/JNIServo.java +++ b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/JNIServo.java @@ -30,7 +30,7 @@ public class JNIServo { public native void performUpdates(); - public native void resize(int width, int height); + public native void resize(ServoCoordinates coords); public native void reload(); @@ -69,8 +69,7 @@ public class JNIServo { public static class ServoOptions { public String args; public String url; - public int width = 0; - public int height = 0; + public ServoCoordinates coordinates; public float density = 1; public boolean enableSubpixelTextAntialiasing = true; public long VRExternalContext = 0; @@ -78,6 +77,15 @@ public class JNIServo { public boolean enableLogs = false; } + public static class ServoCoordinates { + public int x = 0; + public int y = 0; + public int width = 0; + public int height = 0; + public int fb_width = 0; + public int fb_height = 0; + } + public interface Callbacks { void wakeup(); diff --git a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/Servo.java b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/Servo.java index 05a210dfa53..13c177c1236 100644 --- a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/Servo.java +++ b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/Servo.java @@ -13,6 +13,7 @@ import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; import org.freedesktop.gstreamer.GStreamer; +import org.mozilla.servoview.JNIServo.ServoCoordinates; import org.mozilla.servoview.JNIServo.ServoOptions; public class Servo { @@ -91,8 +92,8 @@ public class Servo { mRunCallback.inGLThread(() -> mJNI.setBatchMode(mode)); } - public void resize(int width, int height) { - mRunCallback.inGLThread(() -> mJNI.resize(width, height)); + public void resize(ServoCoordinates coords) { + mRunCallback.inGLThread(() -> mJNI.resize(coords)); } public void refresh() { diff --git a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoSurface.java b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoSurface.java index 239891952f7..93691f0fbae 100644 --- a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoSurface.java +++ b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoSurface.java @@ -18,6 +18,7 @@ import android.os.Looper; import android.util.Log; import android.view.Surface; +import org.mozilla.servoview.JNIServo.ServoCoordinates; import org.mozilla.servoview.JNIServo.ServoOptions; import org.mozilla.servoview.Servo.Client; import org.mozilla.servoview.Servo.GfxCallbacks; @@ -34,6 +35,7 @@ public class ServoSurface { private final Handler mMainLooperHandler; private Handler mGLLooperHandler; private Surface mASurface; + private int mPadding; private int mWidth; private int mHeight; private long mVRExternalContext; @@ -44,7 +46,8 @@ public class ServoSurface { private String mInitialUri; private Activity mActivity; - public ServoSurface(Surface surface, int width, int height) { + public ServoSurface(Surface surface, int width, int height, int padding) { + mPadding = padding; mWidth = width; mHeight = height; mASurface = surface; @@ -136,7 +139,18 @@ public class ServoSurface { } public void onSurfaceResized(int width, int height) { - mServo.resize(width, height); + mWidth = width; + mHeight = height; + + ServoCoordinates coords = new ServoCoordinates(); + coords.x = mPadding; + coords.y = mPadding; + coords.width = width - 2 * mPadding; + coords.height = height - 2 * mPadding; + coords.fb_width = width; + coords.fb_height = height; + + mServo.resize(coords); } static class GLSurface implements GfxCallbacks { @@ -261,10 +275,17 @@ public class ServoSurface { mGLLooperHandler = new Handler(); inUIThread(() -> { + ServoCoordinates coords = new ServoCoordinates(); + coords.x = mPadding; + coords.y = mPadding; + coords.width = mWidth - 2 * mPadding; + coords.height = mHeight - 2 * mPadding; + coords.fb_width = mWidth; + coords.fb_height = mHeight; + ServoOptions options = new ServoOptions(); + options.coordinates = coords; options.args = mServoArgs; - options.width = mWidth; - options.height = mHeight; options.density = 1; options.url = mInitialUri; options.logStr = mServoLog; diff --git a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoView.java b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoView.java index e9ee9dee37d..8d9c0b21383 100644 --- a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoView.java +++ b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoView.java @@ -19,6 +19,7 @@ import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.widget.OverScroller; +import org.mozilla.servoview.JNIServo.ServoCoordinates; import org.mozilla.servoview.JNIServo.ServoOptions; import org.mozilla.servoview.Servo.Client; import org.mozilla.servoview.Servo.GfxCallbacks; @@ -112,7 +113,13 @@ public class ServoView extends GLSurfaceView public void onSurfaceInvalidated(int width, int height) { if (mServo != null) { - mServo.resize(width, height); + ServoCoordinates coords = new ServoCoordinates(); + coords.width = width; + coords.height = height; + coords.fb_width = width; + coords.fb_height = height; + + mServo.resize(coords); mServo.refresh(); } } @@ -150,12 +157,18 @@ public class ServoView extends GLSurfaceView } public void onGLReady() { + ServoCoordinates coords = new ServoCoordinates(); + coords.width = getWidth(); + coords.height = getHeight(); + coords.fb_width = getWidth(); + coords.fb_height = getHeight(); + ServoOptions options = new ServoOptions(); options.args = mServoArgs; - options.width = getWidth(); - options.height = getHeight(); + options.coordinates = coords; options.enableLogs = true; options.enableSubpixelTextAntialiasing = true; + DisplayMetrics metrics = new DisplayMetrics(); mActivity.getWindowManager().getDefaultDisplay().getMetrics(metrics); options.density = metrics.density;