Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed scaling artefacts in paint worklets caused by zoom and hidpi #17499

Merged
merged 1 commit into from Jul 21, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Fixed scaling artefacts in paint worklets caused by zoom and hidpi.

  • Loading branch information
asajeffrey committed Jul 20, 2017
commit caa35852197cd96e6c6ece42d346c45b36ff14f2

Some generated files are not rendered by default. Learn more.

@@ -16,7 +16,7 @@ use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId, Tra
use net_traits::image::base::{Image, PixelFormat};
use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg};
use script_traits::{ConstellationMsg, DevicePixel, LayoutControlMsg, LoadData, MouseButton};
use script_traits::{ConstellationMsg, LayoutControlMsg, LoadData, MouseButton};
use script_traits::{MouseEventType, ScrollState};
use script_traits::{TouchpadPressurePhase, TouchEventType, TouchId, WindowSizeData, WindowSizeType};
use script_traits::CompositorEvent::{self, MouseMoveEvent, MouseButtonEvent, TouchEvent, TouchpadPressureEvent};
@@ -29,7 +29,7 @@ use std::fs::File;
use std::rc::Rc;
use std::sync::mpsc::Sender;
use std::time::{Duration, Instant};
use style_traits::{CSSPixel, PinchZoomFactor};
use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
use style_traits::viewport::ViewportConstraints;
use time::{precise_time_ns, precise_time_s};
use touch::{TouchHandler, TouchAction};
@@ -4,8 +4,9 @@

use euclid::{TypedPoint2D, TypedVector2D};
use euclid::ScaleFactor;
use script_traits::{DevicePixel, EventResult, TouchId};
use script_traits::{EventResult, TouchId};
use self::TouchState::*;
use style_traits::DevicePixel;

/// Minimum number of `DeviceIndependentPixel` to begin touch scrolling.
const TOUCH_PAN_MIN_SCREEN_PX: f32 = 20.0;
@@ -11,11 +11,12 @@ use gleam::gl;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{Key, KeyModifiers, KeyState, TraversalDirection};
use net_traits::net_error_list::NetError;
use script_traits::{DevicePixel, LoadData, MouseButton, TouchEventType, TouchId, TouchpadPressurePhase};
use script_traits::{LoadData, MouseButton, TouchEventType, TouchId, TouchpadPressurePhase};
use servo_geometry::DeviceIndependentPixel;
use servo_url::ServoUrl;
use std::fmt::{Debug, Error, Formatter};
use std::rc::Rc;
use style_traits::DevicePixel;
use style_traits::cursor::Cursor;
use webrender_api::ScrollLocation;

@@ -21,7 +21,7 @@ use net_traits::{IpcSend, ResourceThreads};
use net_traits::image_cache::ImageCache;
use profile_traits::mem as profile_mem;
use profile_traits::time;
use script_traits::{ConstellationControlMsg, DevicePixel, DiscardBrowsingContext};
use script_traits::{ConstellationControlMsg, DiscardBrowsingContext};
use script_traits::{DocumentActivity, InitialScriptState};
use script_traits::{LayoutControlMsg, LayoutMsg, LoadData, MozBrowserEvent};
use script_traits::{NewLayoutInfo, SWManagerMsg, SWManagerSenders, ScriptMsg};
@@ -38,6 +38,7 @@ use std::rc::Rc;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use style_traits::CSSPixel;
use style_traits::DevicePixel;
use webrender_api;
use webvr_traits::WebVRMsg;

@@ -1170,7 +1170,10 @@ impl FragmentDisplayListBuilding for Fragment {
// including padding, but not border or margin, so we follow suit.
// https://github.com/w3c/css-houdini-drafts/issues/417
let unbordered_box = self.border_box - style.logical_border_width();
let size = unbordered_box.size.to_physical(style.writing_mode);
let device_pixel_ratio = state.layout_context.style_context.device_pixel_ratio();
let size_in_au = unbordered_box.size.to_physical(style.writing_mode);
let size_in_px = TypedSize2D::new(size_in_au.width.to_f32_px(), size_in_au.height.to_f32_px());
let size_in_dpx = size_in_px * device_pixel_ratio;
let name = paint_worklet.name.clone();

// Get the painter, and the computed values for its properties.
@@ -1188,17 +1191,17 @@ impl FragmentDisplayListBuilding for Fragment {

// TODO: add a one-place cache to avoid drawing the paint image every time.
// https://github.com/servo/servo/issues/17369
debug!("Drawing a paint image {}({},{}).", name, size.width.to_px(), size.height.to_px());
debug!("Drawing a paint image {}({},{}).", name, size_in_px.width, size_in_px.height);
let (sender, receiver) = ipc::channel().unwrap();
painter.draw_a_paint_image(size, properties, sender);
painter.draw_a_paint_image(size_in_px, device_pixel_ratio, properties, sender);

// TODO: timeout
let webrender_image = match receiver.recv() {
Ok(CanvasData::Image(canvas_data)) => {
WebRenderImageInfo {
// TODO: it would be nice to get this data back from the canvas
width: size.width.to_px().abs() as u32,
height: size.height.to_px().abs() as u32,
width: size_in_dpx.width as u32,
height: size_in_dpx.height as u32,
format: PixelFormat::BGRA8,
key: Some(canvas_data.image_key),
}
@@ -462,9 +462,12 @@ impl LayoutThread {
layout_threads: usize,
paint_time_metrics: PaintTimeMetrics)
-> LayoutThread {
// The device pixel ratio is incorrect (it does not have the hidpi value),
// but it will be set correctly when the initial reflow takes place.
let device = Device::new(
MediaType::Screen,
opts::get().initial_window_size.to_f32() * ScaleFactor::new(1.0));
opts::get().initial_window_size.to_f32() * ScaleFactor::new(1.0),
ScaleFactor::new(opts::get().device_pixels_per_px.unwrap_or(1.0)));

let configuration =
rayon::Configuration::new().num_threads(layout_threads);
@@ -1125,6 +1128,7 @@ impl LayoutThread {
trace!("{:?}", ShowSubtree(element.as_node()));

let initial_viewport = data.window_size.initial_viewport;
let device_pixel_ratio = data.window_size.device_pixel_ratio;
let old_viewport_size = self.viewport_size;
let current_screen_size = Size2D::new(Au::from_f32_px(initial_viewport.width),
Au::from_f32_px(initial_viewport.height));
@@ -1134,7 +1138,7 @@ impl LayoutThread {
let document_shared_lock = document.style_shared_lock();
self.document_shared_lock = Some(document_shared_lock.clone());
let author_guard = document_shared_lock.read();
let device = Device::new(MediaType::Screen, initial_viewport);
let device = Device::new(MediaType::Screen, initial_viewport, device_pixel_ratio);
self.stylist.set_device(device, &author_guard, &data.document_stylesheets);

self.viewport_size =
@@ -43,7 +43,7 @@ use dom::bindings::str::{DOMString, USVString};
use dom::bindings::utils::WindowProxyHandler;
use dom::document::PendingRestyle;
use encoding::types::EncodingRef;
use euclid::{Transform2D, Transform3D, Point2D, Vector2D, Rect, Size2D};
use euclid::{Transform2D, Transform3D, Point2D, Vector2D, Rect, Size2D, ScaleFactor};
use euclid::Length as EuclidLength;
use html5ever::{Prefix, LocalName, Namespace, QualName};
use html5ever::buffer_queue::BufferQueue;
@@ -484,6 +484,13 @@ unsafe impl JSTraceable for Point2D<f32> {
}
}

unsafe impl<T, U> JSTraceable for ScaleFactor<f32, T, U> {
#[inline]
unsafe fn trace(&self, _trc: *mut JSTracer) {
// Do nothing
}
}

unsafe impl JSTraceable for Vector2D<f32> {
#[inline]
unsafe fn trace(&self, _trc: *mut JSTracer) {
@@ -76,7 +76,8 @@ impl MediaQueryList {
pub fn evaluate(&self) -> bool {
if let Some(window_size) = self.document.window().window_size() {
let viewport_size = window_size.initial_viewport;
let device = Device::new(MediaType::Screen, viewport_size);
let device_pixel_ratio = window_size.device_pixel_ratio;
let device = Device::new(MediaType::Screen, viewport_size, device_pixel_ratio);
self.media_query_list.evaluate(&device, self.document.quirks_mode())
} else {
false
@@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use canvas_traits::CanvasData;
use canvas_traits::CanvasMsg;
use canvas_traits::FromLayoutMsg;
@@ -26,19 +25,26 @@ use dom::canvaspattern::CanvasPattern;
use dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
use dom::paintworkletglobalscope::PaintWorkletGlobalScope;
use dom_struct::dom_struct;
use euclid::ScaleFactor;
use euclid::Size2D;
use euclid::TypedSize2D;
use ipc_channel::ipc::IpcSender;
use std::cell::Cell;
use style_traits::CSSPixel;
use style_traits::DevicePixel;

#[dom_struct]
pub struct PaintRenderingContext2D {
context: CanvasRenderingContext2D,
device_pixel_ratio: Cell<ScaleFactor<f32, CSSPixel, DevicePixel>>,
}

impl PaintRenderingContext2D {
fn new_inherited(global: &PaintWorkletGlobalScope) -> PaintRenderingContext2D {
let size = Size2D::zero();
PaintRenderingContext2D {
context: CanvasRenderingContext2D::new_inherited(global.upcast(), None, size),
device_pixel_ratio: Cell::new(ScaleFactor::new(1.0)),
}
}

@@ -53,9 +59,21 @@ impl PaintRenderingContext2D {
let _ = self.context.ipc_renderer().send(msg);
}

pub fn set_bitmap_dimensions(&self, size: Size2D<Au>) {
let size = Size2D::new(size.width.to_px(), size.height.to_px());
self.context.set_bitmap_dimensions(size);
pub fn set_bitmap_dimensions(&self,
size: TypedSize2D<f32, CSSPixel>,
device_pixel_ratio: ScaleFactor<f32, CSSPixel, DevicePixel>)
{
let size = size * device_pixel_ratio;
self.device_pixel_ratio.set(device_pixel_ratio);
self.context.set_bitmap_dimensions(size.to_untyped().to_i32());
self.scale_by_device_pixel_ratio();
}

fn scale_by_device_pixel_ratio(&self) {
let device_pixel_ratio = self.device_pixel_ratio.get().get() as f64;
if device_pixel_ratio != 1.0 {
self.Scale(device_pixel_ratio, device_pixel_ratio);
}
}
}

@@ -92,12 +110,14 @@ impl PaintRenderingContext2DMethods for PaintRenderingContext2D {

// https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform
fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
self.context.SetTransform(a, b, c, d, e, f)
self.context.SetTransform(a, b, c, d, e, f);
self.scale_by_device_pixel_ratio();
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform
fn ResetTransform(&self) {
self.context.ResetTransform()
self.context.ResetTransform();
self.scale_by_device_pixel_ratio();
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha
@@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use dom::bindings::codegen::Bindings::PaintSizeBinding;
use dom::bindings::codegen::Bindings::PaintSizeBinding::PaintSizeMethods;
use dom::bindings::js::Root;
@@ -11,7 +10,8 @@ use dom::bindings::reflector::Reflector;
use dom::bindings::reflector::reflect_dom_object;
use dom::paintworkletglobalscope::PaintWorkletGlobalScope;
use dom_struct::dom_struct;
use euclid::Size2D;
use euclid::TypedSize2D;
use style_traits::CSSPixel;

#[dom_struct]
pub struct PaintSize {
@@ -21,15 +21,15 @@ pub struct PaintSize {
}

impl PaintSize {
fn new_inherited(size: Size2D<Au>) -> PaintSize {
fn new_inherited(size: TypedSize2D<f32, CSSPixel>) -> PaintSize {
PaintSize {
reflector: Reflector::new(),
width: Finite::wrap(size.width.to_px().abs() as f64),
height: Finite::wrap(size.height.to_px().abs() as f64),
width: Finite::wrap(size.width as f64),
height: Finite::wrap(size.height as f64),
}
}

pub fn new(global: &PaintWorkletGlobalScope, size: Size2D<Au>) -> Root<PaintSize> {
pub fn new(global: &PaintWorkletGlobalScope, size: TypedSize2D<f32, CSSPixel>) -> Root<PaintSize> {
reflect_dom_object(box PaintSize::new_inherited(size), global, PaintSizeBinding::Wrap)
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.