Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Margareta Eliza Balazs 2019-01-18 12:31:59 +02:00
commit 9dda825205
197 changed files with 4104 additions and 2200 deletions

View File

@ -38,7 +38,10 @@ tasks:
$if: 'tasks_for == "action"'
then:
name: "Action: ${action.title}"
description: '${action.description}'
description: |
${action.description}
Action triggered by clientID `${clientId}`
else:
name: "Decision Task for cron job ${cron.job_name}"
description: 'Created by a [cron task](https://tools.taskcluster.net/tasks/${cron.task_id})'

View File

@ -6,8 +6,10 @@
#include "ErrorHandler.h"
#if defined(MOZ_LAUNCHER_PROCESS)
#include "mozilla/LauncherRegistryInfo.h"
#include "mozilla/Unused.h"
#endif // defined(MOZ_LAUNCHER_PROCESS)
namespace mozilla {
@ -15,8 +17,10 @@ void HandleLauncherError(const LauncherError& aError) {
// This is a placeholder error handler. We'll add telemetry and a fallback
// error log in future revisions.
#if defined(MOZ_LAUNCHER_PROCESS)
LauncherRegistryInfo regInfo;
Unused << regInfo.DisableDueToFailure();
#endif // defined(MOZ_LAUNCHER_PROCESS)
WindowsError::UniqueString msg = aError.mError.AsString();
if (!msg) {

View File

@ -13,7 +13,6 @@
#include "mozilla/CmdLineAndEnvUtils.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/DynamicallyLinkedFunctionPtr.h"
#include "mozilla/LauncherRegistryInfo.h"
#include "mozilla/LauncherResult.h"
#include "mozilla/Maybe.h"
#include "mozilla/SafeMode.h"
@ -32,6 +31,7 @@
#include "ProcThreadAttributes.h"
#if defined(MOZ_LAUNCHER_PROCESS)
# include "mozilla/LauncherRegistryInfo.h"
# include "SameBinary.h"
#endif // defined(MOZ_LAUNCHER_PROCESS)
@ -175,19 +175,20 @@ static bool DoLauncherProcessChecks(int& argc, wchar_t** argv) {
namespace mozilla {
bool RunAsLauncherProcess(int& argc, wchar_t** argv) {
LauncherRegistryInfo::ProcessType desiredType =
DoLauncherProcessChecks(argc, argv)
? LauncherRegistryInfo::ProcessType::Launcher
: LauncherRegistryInfo::ProcessType::Browser;
bool runAsLauncher = DoLauncherProcessChecks(argc, argv);
// If we're looking at browser, return fast when we're a child process.
if (desiredType == LauncherRegistryInfo::ProcessType::Browser &&
// If we're running as browser, return fast when we're a child process.
if (!runAsLauncher &&
mozilla::CheckArg(argc, argv, L"contentproc",
static_cast<const wchar_t**>(nullptr),
mozilla::CheckArgFlag::None) == mozilla::ARG_FOUND) {
return false;
}
#if defined(MOZ_LAUNCHER_PROCESS)
LauncherRegistryInfo::ProcessType desiredType =
runAsLauncher ? LauncherRegistryInfo::ProcessType::Launcher
: LauncherRegistryInfo::ProcessType::Browser;
LauncherRegistryInfo regInfo;
LauncherResult<LauncherRegistryInfo::ProcessType> runAsType =
regInfo.Check(desiredType);
@ -199,13 +200,17 @@ bool RunAsLauncherProcess(int& argc, wchar_t** argv) {
return false;
}
if (runAsType.unwrap() == LauncherRegistryInfo::ProcessType::Browser) {
runAsLauncher =
runAsType.unwrap() == LauncherRegistryInfo::ProcessType::Launcher;
#endif // defined(MOZ_LAUNCHER_PROCESS)
if (!runAsLauncher) {
// In this case, we will be proceeding to run as the browser.
// We should check MOZ_DEBUG_BROWSER_* env vars.
MaybeBreakForBrowserDebugging();
}
return runAsType.unwrap() == LauncherRegistryInfo::ProcessType::Launcher;
return runAsLauncher;
}
int LauncherMain(int argc, wchar_t* argv[]) {

View File

@ -9,7 +9,6 @@ Library('winlauncher')
FORCE_STATIC_LIB = True
UNIFIED_SOURCES += [
'/toolkit/xre/LauncherRegistryInfo.cpp',
'DllBlocklistWin.cpp',
'ErrorHandler.cpp',
'LauncherProcessWin.cpp',
@ -26,8 +25,12 @@ TEST_DIRS += [
'test',
]
for var in ('MOZ_APP_BASENAME', 'MOZ_APP_VENDOR'):
DEFINES[var] = '"%s"' % CONFIG[var]
if CONFIG['MOZ_LAUNCHER_PROCESS']:
UNIFIED_SOURCES += [
'/toolkit/xre/LauncherRegistryInfo.cpp',
]
for var in ('MOZ_APP_BASENAME', 'MOZ_APP_VENDOR'):
DEFINES[var] = '"%s"' % CONFIG[var]
DisableStlWrapping()

View File

@ -22,10 +22,6 @@ install:
- npm config set spin false
- npm install
before_script:
- bash bin/download-firefox-travis.sh release-linux64-add-on-devel
- export FIREFOX_BIN=./firefox/firefox
script:
- npm test

View File

@ -1,12 +0,0 @@
#!/bin/bash
# Copied and slightly modified from https://github.com/lidel/ipfs-firefox-addon/commit/d656832eec807ebae59543982dde96932ce5bb7c
# Licensed under Creative Commons - CC0 1.0 Universal - https://github.com/lidel/ipfs-firefox-addon/blob/master/LICENSE
BUILD_TYPE=${1:-$FIREFOX_RELEASE}
echo "Looking up latest URL for $BUILD_TYPE"
BUILD_ROOT="/pub/firefox/tinderbox-builds/mozilla-${BUILD_TYPE}/"
ROOT="https://archive.mozilla.org"
LATEST=$(curl -s "$ROOT$BUILD_ROOT" | grep $BUILD_TYPE | grep -Po '<a href=".+">\K[[:digit:]]+' | sort -n | tail -1)
echo "Latest build located at $ROOT$BUILD_ROOT$LATEST"
FILE=$(curl -s "$ROOT$BUILD_ROOT$LATEST/" | grep '.tar.' | grep -Po '<a href="\K[^"]*')
echo "URL: $ROOT$FILE"
wget -O "firefox-${BUILD_TYPE}.tar.bz2" "$ROOT$FILE" && tar xf "firefox-${BUILD_TYPE}.tar.bz2"

View File

@ -49,7 +49,6 @@ for (const type of [
"DISCOVERY_STREAM_SPOCS_UPDATE",
"DOWNLOAD_CHANGED",
"FILL_SEARCH_TERM",
"FOCUS_SEARCH",
"HANDOFF_SEARCH_TO_AWESOMEBAR",
"HIDE_SEARCH",
"INIT",

View File

@ -59,7 +59,7 @@ const INITIAL_STATE = {
spocs: {
spocs_endpoint: "",
lastUpdated: null,
data: [],
data: {}, // {spocs: []}
},
},
Search: {
@ -491,10 +491,8 @@ function Search(prevState = INITIAL_STATE.Search, action) {
switch (action.type) {
case at.HIDE_SEARCH:
return Object.assign({...prevState, hide: true});
case at.FOCUS_SEARCH:
return Object.assign({...prevState, focus: true});
case at.SHOW_SEARCH:
return Object.assign({...prevState, hide: false, focus: false});
return Object.assign({...prevState, hide: false});
default:
return prevState;
}

View File

@ -11,7 +11,7 @@
z-index: 2100;
.ReturnToAMOText {
color: $grey-90-80;
color: $grey-90;
line-height: 32px;
font-size: 23px;
width: 100%;
@ -23,19 +23,19 @@
}
h2 {
color: $grey-60-60;
color: $grey-60;
font-weight: 100;
margin: 0 0 22px;
margin: 0 0 36px;
font-size: 36px;
line-height: 48px;
letter-spacing: 1.2px;
}
p {
color: $grey-90-50;
color: $grey-60;
font-size: 14px;
line-height: 18px;
margin-bottom: 4px;
margin-bottom: 16px;
}
.puffy {
@ -95,17 +95,18 @@
}
.ReturnToAMOContainer {
width: 835px;
width: 960px;
background: $white;
box-shadow: 0 1px 15px 0 $black-30;
border-radius: 4px;
display: flex;
padding: 38px 96px 28px 48px;
padding: 64px 64px 72px;
}
.ReturnToAMOAddonContents {
width: 400px;
margin-top: 42px;
width: 560px;
margin-top: 32px;
margin-inline-end: 24px;
}
.ReturnToAMOIcon {

View File

@ -7,6 +7,7 @@
font-size: 14px;
padding-left: $sidebar-width;
display: flex;
color: var(--newtab-text-primary-color);
.sidebar {
inset-inline-start: 0;
@ -23,9 +24,10 @@
li a {
padding: 10px 34px;
display: block;
color: var(--lwt-sidebar-text-color);
&:hover {
background: $grey-20;
background: var(--newtab-textbox-background-color);
}
}
}
@ -49,7 +51,7 @@
}
.sourceLabel {
background: $grey-20;
background: var(--newtab-textbox-background-color);
padding: 2px 5px;
border-radius: 3px;
@ -136,6 +138,7 @@
display: flex;
background: $yellow-50;
border-radius: 3px;
color: $grey-90;
a {
text-decoration: underline;

View File

@ -2,11 +2,23 @@ import {CardGrid} from "content-src/components/DiscoveryStreamComponents/CardGri
import {connect} from "react-redux";
import {Hero} from "content-src/components/DiscoveryStreamComponents/Hero/Hero";
import {HorizontalRule} from "content-src/components/DiscoveryStreamComponents/HorizontalRule/HorizontalRule";
import {ImpressionStats} from "content-src/components/DiscoveryStreamImpressionStats/ImpressionStats";
import {List} from "content-src/components/DiscoveryStreamComponents/List/List";
import React from "react";
import {SectionTitle} from "content-src/components/DiscoveryStreamComponents/SectionTitle/SectionTitle";
import {selectLayoutRender} from "content-src/lib/selectLayoutRender";
import {TopSites} from "content-src/components/DiscoveryStreamComponents/TopSites/TopSites";
// According to the Pocket API endpoint specs, `component.properties.items` is a required property with following values:
// - Lists 1-5 items
// - Hero 1-5 items
// - CardGrid 1-8 items
// To enforce that, we define various maximium items for individual components as an extra check.
// Note that these values are subject to the future changes of the specs.
const MAX_ROWS_HERO = 5;
// const MAX_ROWS_LISTS = 5;
// const MAX_ROWS_CARDGRID = 8;
export class _DiscoveryStreamBase extends React.PureComponent {
renderComponent(component) {
switch (component.type) {
@ -15,27 +27,45 @@ export class _DiscoveryStreamBase extends React.PureComponent {
case "SectionTitle":
return (<SectionTitle />);
case "CardGrid":
return (<CardGrid feed={component.feed} />);
case "Hero":
return (<Hero
title={component.header.title}
return (<CardGrid
title={component.header && component.header.title}
data={component.data}
feed={component.feed}
style={component.properties.style}
type={component.type}
dispatch={this.props.dispatch}
items={component.properties.items} />);
case "Hero":
const items = Math.min(MAX_ROWS_HERO,
component.properties.items || (component.data ? component.data.recommendations.length : 0));
const rows = component.data ? component.data.recommendations.slice(0, items) : [];
return (
<ImpressionStats rows={rows} dispatch={this.props.dispatch} source={component.type}>
<Hero
title={component.header && component.header.title}
data={component.data}
style={component.properties.style}
type={component.type}
dispatch={this.props.dispatch}
items={items} />
</ImpressionStats>
);
case "HorizontalRule":
return (<HorizontalRule />);
case "List":
return (<List feed={component.feed} />);
return (<List
feed={component.feed}
header={component.header} />);
default:
return (<div>{component.type}</div>);
}
}
render() {
const {layout} = this.props.DiscoveryStream;
const {layoutRender} = this.props.DiscoveryStream;
return (
<div className="discovery-stream ds-layout">
{layout.map((row, rowIndex) => (
{layoutRender.map((row, rowIndex) => (
<div key={`row-${rowIndex}`} className={`ds-column ds-column-${row.width}`}>
{row.components.map((component, componentIndex) => (
<div key={`component-${componentIndex}`}>
@ -49,4 +79,13 @@ export class _DiscoveryStreamBase extends React.PureComponent {
}
}
export const DiscoveryStreamBase = connect(state => ({DiscoveryStream: state.DiscoveryStream}))(_DiscoveryStreamBase);
function transform(state) {
return {
DiscoveryStream: {
...state.DiscoveryStream,
layoutRender: selectLayoutRender(state),
},
};
}
export const DiscoveryStreamBase = connect(transform)(_DiscoveryStreamBase);

View File

@ -1,9 +1,16 @@
.outer-wrapper a {
color: $grey-90;
}
.discovery-stream.ds-layout {
$columns: 12;
display: grid;
grid-template-columns: repeat($columns, 1fr);
grid-column-gap: 48px;
grid-row-gap: 10px;
width: 936px;
margin: 0 auto;
@while $columns > 0 {
.ds-column-#{$columns} {

View File

@ -1,15 +1,40 @@
import {connect} from "react-redux";
import {DSCard} from "../DSCard/DSCard.jsx";
import React from "react";
export class _CardGrid extends React.PureComponent {
export class CardGrid extends React.PureComponent {
render() {
// const feed = this.props.DiscoveryStream.feeds[this.props.feed.url];
const {data} = this.props;
// Handle a render before feed has been fetched by displaying nothing
if (!data) {
return (
<div />
);
}
let cards = data.recommendations.slice(0, this.props.items).map((rec, index) => (
<DSCard
key={`dscard-${index}`}
image_src={rec.image_src}
title={rec.title}
excerpt={rec.title}
url={rec.url}
id={rec.id}
index={index}
type={this.props.type}
dispatch={this.props.dispatch}
source={rec.domain} />
));
return (
<div>
Card Grid
<div className="ds-card-grid">
{cards}
</div>
);
}
}
export const CardGrid = connect(state => ({DiscoveryStream: state.DiscoveryStream}))(_CardGrid);
CardGrid.defaultProps = {
style: `border`,
items: 4, // Number of stories to display
};

View File

@ -0,0 +1,28 @@
.ds-card-grid {
display: grid;
.ds-card {
background: $white;
box-shadow: 0 1px 4px $grey-10-10;
border-radius: 4px;
margin-bottom: 24px;
}
// "2/3 width layout"
.ds-column-5 &,
.ds-column-6 &,
.ds-column-7 &,
.ds-column-8 & {
grid-template-columns: repeat(2, 1fr);
grid-gap: 24px;
}
// "Full width layout"
.ds-column-9 &,
.dscolumn-10 &,
.ds-column-11 &,
.ds-column-12 & {
grid-template-columns: repeat(4, 1fr);
grid-gap: 24px;
}
}

View File

@ -1,16 +1,36 @@
import {actionCreators as ac} from "common/Actions.jsm";
import React from "react";
export class DSCard extends React.PureComponent {
constructor(props) {
super(props);
this.onLinkClick = this.onLinkClick.bind(this);
}
onLinkClick(event) {
this.props.dispatch(ac.UserEvent({
event: "CLICK",
source: this.props.type.toUpperCase(),
action_position: this.props.index,
}));
this.props.dispatch(ac.ImpressionStats({
source: this.props.type.toUpperCase(),
click: 0,
tiles: [{id: this.props.id, pos: this.props.index}],
}));
}
render() {
return (
<a href={this.props.url} className="ds-card">
<a href={this.props.url} className="ds-card" onClick={this.onLinkClick}>
<div className="img-wrapper">
<div className="img" style={{backgroundImage: `url(${this.props.image_src}`}} />
</div>
<div className="meta">
<header>{this.props.title}</header>
<p>{this.props.excerpt}</p>
<p>{this.props.source}</p>
<header className="title">{this.props.title}</header>
<p className="excerpt">{this.props.excerpt}</p>
<p className="source">{this.props.source}</p>
</div>
</a>
);

View File

@ -1,3 +1,9 @@
// Type sizes
$header-font-size: 17;
$header-line-height: 24;
$excerpt-font-size: 13;
$excerpt-line-height: 20;
.ds-card {
border: 5px solid transparent;
@ -11,7 +17,6 @@
width: 100%;
border: 0.5px solid $black-10;
border-radius: 4px;
margin: 0 0 12px;
}
.img {
@ -23,11 +28,21 @@
.meta {
padding: 16px;
.title {
// show only 2 lines of copy
@include limit-visibile-lines(2, $header-line-height, $header-font-size);
}
.excerpt {
// show only 4 lines of copy
@include limit-visibile-lines(4, $excerpt-line-height, $excerpt-font-size);
}
}
header {
line-height: 24px;
font-size: 17px;
line-height: $header-line-height * 1px;
font-size: $header-font-size * 1px;
color: $grey-90;
&:hover {
@ -40,8 +55,8 @@
}
p {
font-size: 13px;
line-height: 20px;
font-size: $excerpt-font-size * 1px;
line-height: $excerpt-line-height * 1px;
color: $grey-50;
margin: 8px 0;
}

View File

@ -1,27 +1,52 @@
import {connect} from "react-redux";
import {actionCreators as ac} from "common/Actions.jsm";
import {DSCard} from "../DSCard/DSCard.jsx";
import React from "react";
export class _Hero extends React.PureComponent {
export class Hero extends React.PureComponent {
constructor(props) {
super(props);
this.onLinkClick = this.onLinkClick.bind(this);
}
onLinkClick(event) {
this.props.dispatch(ac.UserEvent({
event: "CLICK",
source: this.props.type.toUpperCase(),
action_position: 0,
}));
this.props.dispatch(ac.ImpressionStats({
source: this.props.type.toUpperCase(),
click: 0,
tiles: [{id: this.heroRec.id, pos: 0}],
}));
}
render() {
const feed = this.props.DiscoveryStream.feeds[this.props.feed.url];
const {data} = this.props;
// Handle a render before feed has been fetched by displaying nothing
if (!feed) {
if (!data || !data.recommendations) {
return (
<div />
);
}
let [heroRec, ...otherRecs] = feed.data.recommendations;
let [heroRec, ...otherRecs] = data.recommendations.slice(0, this.props.items);
this.heroRec = heroRec;
let truncateText = (text, cap) => `${text.substring(0, cap)}${text.length > cap ? `...` : ``}`;
let cards = otherRecs.slice(1, this.props.items).map((rec, index) => (
// Note that `{index + 1}` is necessary below for telemetry since we treat heroRec as index 0.
let cards = otherRecs.map((rec, index) => (
<DSCard
key={`dscard-${index}`}
image_src={rec.image_src}
title={truncateText(rec.title, 44)}
url={rec.url}
id={rec.id}
index={index + 1}
type={this.props.type}
dispatch={this.props.dispatch}
source={truncateText(`TODO: SOURCE`, 22)} />
));
@ -29,7 +54,7 @@ export class _Hero extends React.PureComponent {
<div>
<div className="ds-header">{this.props.title}</div>
<div className={`ds-hero ds-hero-${this.props.style}`}>
<a href={heroRec.url} className="wrapper">
<a href={heroRec.url} className="wrapper" onClick={this.onLinkClick}>
<div className="img-wrapper">
<div className="img" style={{backgroundImage: `url(${heroRec.image_src})`}} />
</div>
@ -48,9 +73,8 @@ export class _Hero extends React.PureComponent {
}
}
_Hero.defaultProps = {
Hero.defaultProps = {
data: {},
style: `border`,
items: 1, // Number of stories to display
};
export const Hero = connect(state => ({DiscoveryStream: state.DiscoveryStream}))(_Hero);

View File

@ -26,6 +26,10 @@
}
}
.img-wrapper {
margin: 0 0 12px;
}
// "1/3 width layout" (aka "Mobile First")
.wrapper {
color: $grey-50;

View File

@ -1,15 +1,60 @@
import {connect} from "react-redux";
import React from "react";
export class _List extends React.PureComponent {
render() {
// const feed = this.props.DiscoveryStream.feeds[this.props.feed.url];
return (
<div className="ds-list">
List
</div>
);
}
/**
* @note exported for testing only
*/
export function ListItem(props) {
// TODO performance: get feeds to send appropriately sized images rather
// than waiting longer and scaling down on client?
return (
<li className="ds-list-item">
<a className="ds-list-item-link" href={props.url}>
<div className="ds-list-item-text">
<div className="ds-list-item-title">
<b>
{props.title}
</b>
</div>
<div className="ds-list-item-info">
{`${props.domain} · TODO:Topic`}
</div>
</div>
<img className="ds-list-image" src={props.image_src} />
</a>
</li>
);
}
/**
* @note exported for testing only
*/
export function _List(props) {
const feed = props.DiscoveryStream.feeds[props.feed.url];
if (!feed || !feed.data || !feed.data.recommendations) {
return null;
}
const recs = feed.data.recommendations;
let recMarkup = recs.slice(0, props.items).map((rec, index) => (
<ListItem {...rec} key={`ds-list-item-$index`} />)
);
return (
<div>
<h3 className="ds-list-title">{props.header && props.header.title}</h3>
<hr className="ds-list-border" />
<ul className="ds-list">{recMarkup}</ul>
</div>
);
}
_List.defaultProps = {
items: 6, // Number of stories to display. TODO: get from endpoint
};
export const List = connect(state => ({DiscoveryStream: state.DiscoveryStream}))(_List);

View File

@ -0,0 +1,58 @@
.ds-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-row-gap: 10px;
grid-column-gap: 24px;
// reset some stuff from <ul>. Should maybe be hoisted when we have better
// regression detection?
padding-inline-start: 0;
}
.ds-list-item {
// XXX see if we really want absolute units, maybe hoist somewhere central?
line-height: 20px;
font-size: 13px;
// reset some stuff from <li>. Should maybe be hoisted when we have better
// regression detection?
display: block;
text-align: start;
.ds-list-item-link {
mix-blend-mode: normal;
padding-bottom: 16px;
display: flex;
justify-content: space-between;
}
.ds-list-item-info {
color: $grey-50;
overflow: hidden;
text-overflow: ellipsis;
}
.ds-list-item-title {
margin-bottom: 8px;
padding-bottom: 8px;
}
.ds-list-item-text {
display: flex;
justify-content: space-between;
flex-direction: column;
}
.ds-list-image {
width: 72px;
height: 72px;
object-fit: cover;
border: 0.5px solid $black-12;
box-sizing: border-box;
border-radius: 4px;
}
}

View File

@ -10,5 +10,92 @@
.section-top-bar {
display: none;
}
.top-site-outer {
padding: 0 12px;
}
.top-sites-list {
margin: 0 -12px;
}
}
// Only show 6 cards for 2/3 and 1/3
// XXX hide-for-narrow is wrapping a previous functionality, can do better.
.hide-for-narrow {
display: none;
}
}
// Only show 8 cards for the full row.
// XXX hide-for-narrow is wrapping a previous functionality, can do better.
.ds-column-9,
.ds-column-10,
.ds-column-11,
.ds-column-12 {
.ds-top-sites {
.hide-for-narrow {
display: inline-block;
}
}
}
// Size overrides for topsites in the 2/3 view.
.ds-column-5,
.ds-column-6,
.ds-column-7,
.ds-column-8 {
.ds-top-sites {
.top-site-outer {
padding: 0 10px;
}
.top-sites-list {
margin: 0 -10px;
}
.top-site-inner {
--leftPanelIconWidth: 84.67px;
.tile {
width: var(--leftPanelIconWidth);
height: var(--leftPanelIconWidth);
}
.title {
width: var(--leftPanelIconWidth);
}
}
}
}
// Size overrides for topsites in the 1/3 view.
.ds-column-1,
.ds-column-2,
.ds-column-3,
.ds-column-4 {
.ds-top-sites {
.top-site-outer {
padding: 0 8px;
}
.top-sites-list {
margin: 0 -8px;
}
.top-site-inner {
--rightPanelIconWidth: 82.67px;
.tile {
width: var(--rightPanelIconWidth);
height: var(--rightPanelIconWidth);
}
.title {
width: var(--rightPanelIconWidth);
}
}
}
}

View File

@ -0,0 +1,93 @@
import {actionCreators as ac} from "common/Actions.jsm";
import React from "react";
const VISIBLE = "visible";
const VISIBILITY_CHANGE_EVENT = "visibilitychange";
export class ImpressionStats extends React.PureComponent {
// This checks if the given cards are the same as those in the last impression ping.
// If so, it should not send the same impression ping again.
_needsImpressionStats(cards) {
if (!this.impressionCardGuids || (this.impressionCardGuids.length !== cards.length)) {
return true;
}
for (let i = 0; i < cards.length; i++) {
if (cards[i].id !== this.impressionCardGuids[i]) {
return true;
}
}
return false;
}
_dispatchImpressionStats() {
const {props} = this;
const cards = props.rows;
if (this._needsImpressionStats(cards)) {
props.dispatch(ac.ImpressionStats({
source: props.source.toUpperCase(),
tiles: cards.map(link => ({id: link.id})),
}));
this.impressionCardGuids = cards.map(link => link.id);
}
}
// This sends an event when a user sees a set of new content. If content
// changes while the page is hidden (i.e. preloaded or on a hidden tab),
// only send the event if the page becomes visible again.
sendImpressionStatsOrAddListener() {
const {props} = this;
if (!props.dispatch) {
return;
}
if (props.document.visibilityState === VISIBLE) {
this._dispatchImpressionStats();
} else {
// We should only ever send the latest impression stats ping, so remove any
// older listeners.
if (this._onVisibilityChange) {
props.document.removeEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange);
}
this._onVisibilityChange = () => {
if (props.document.visibilityState === VISIBLE) {
this._dispatchImpressionStats();
props.document.removeEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange);
}
};
props.document.addEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange);
}
}
componentDidMount() {
if (this.props.rows.length) {
this.sendImpressionStatsOrAddListener();
}
}
componentDidUpdate(prevProps) {
if (this.props.rows.length && this.props.rows !== prevProps.rows) {
this.sendImpressionStatsOrAddListener();
}
}
componentWillUnmount() {
if (this._onVisibilityChange) {
this.props.document.removeEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange);
}
}
render() {
return this.props.children;
}
}
ImpressionStats.defaultProps = {
document: global.document,
rows: [],
source: "",
};

View File

@ -29,29 +29,35 @@ export class _Search extends React.PureComponent {
window.gContentSearchController.search(event);
}
doSearchHandoff(text) {
this.props.dispatch(ac.OnlyToMain({type: at.HANDOFF_SEARCH_TO_AWESOMEBAR, data: {text}}));
this.props.dispatch(ac.UserEvent({event: "SEARCH_HANDOFF"}));
if (text) {
// We don't hide the in-content search if there is no text (user hit <Enter>)
this.props.dispatch({type: at.HIDE_SEARCH});
}
}
onSearchHandoffClick(event) {
// When search hand-off is enabled, we render a big button that is styled to
// look like a search textbox. If the button is clicked with the mouse, we style
// the button as if it was a focused search box and show a fake cursor but
// really focus the awesomebar without the focus styles.
// look like a search textbox. If the button is clicked with the mouse, we
// focus it. If the user types, transfer focus to awesomebar.
// If the button is clicked from the keyboard, we focus the awesomebar normally.
// This is to minimize confusion with users navigating with the keyboard and
// users using assistive technologoy.
event.preventDefault();
const isKeyboardClick = event.clientX === 0 && event.clientY === 0;
const hiddenFocus = !isKeyboardClick;
this.props.dispatch(ac.OnlyToMain({type: at.HANDOFF_SEARCH_TO_AWESOMEBAR, data: {hiddenFocus}}));
this.props.dispatch({type: at.FOCUS_SEARCH});
// TODO: Send a telemetry ping. BUG 1514732
if (isKeyboardClick) {
this.doSearchHandoff();
} else {
this._searchHandoffButton.focus();
}
}
onSearchHandoffKeyDown(event) {
if (event.key.length === 1 && !event.altKey && !event.ctrlKey && !event.metaKey) {
// We only care about key strokes that will produce a character.
const text = event.key;
this.props.dispatch(ac.OnlyToMain({type: at.HANDOFF_SEARCH_TO_AWESOMEBAR, data: {text}}));
// TODO: Send a telemetry ping. BUG 1514732
this.doSearchHandoff(event.key);
}
}
@ -63,10 +69,7 @@ export class _Search extends React.PureComponent {
return;
}
event.preventDefault();
const text = event.clipboardData.getData("Text");
this.props.dispatch(ac.OnlyToMain({type: at.HANDOFF_SEARCH_TO_AWESOMEBAR, data: {text}}));
// TODO: Send a telemetry ping. BUG 1514732
this.doSearchHandoff(event.clipboardData.getData("Text"));
}
componentWillMount() {
@ -127,7 +130,6 @@ export class _Search extends React.PureComponent {
const wrapperClassName = [
"search-wrapper",
this.props.hide && "search-hidden",
this.props.focus && "search-active",
].filter(v => v).join(" ");
return (<div className={wrapperClassName}>

View File

@ -160,8 +160,7 @@ $glyph-forward: url('chrome://browser/skin/forward.svg');
box-shadow: $shadow-secondary, 0 0 0 1px $black-25;
}
&:focus,
.search-active & {
&:focus {
border: $input-border-active;
box-shadow: var(--newtab-textbox-focus-boxshadow);

View File

@ -0,0 +1,51 @@
import {createSelector} from "reselect";
function calculateSpocs(component, spocs) {
let spocIndex = 0;
return component.spocs.positions.map(position => {
const rickRoll = Math.random();
if (spocs.data.spocs[spocIndex] && rickRoll <= component.spocs.probability) {
return {
...position,
result: spocs.data.spocs[spocIndex++],
};
}
return position;
});
}
export const selectLayoutRender = createSelector(
// Selects layout, feeds, spocs so that we only recompute if
// any of these values change.
[
state => state.DiscoveryStream.layout,
state => state.DiscoveryStream.feeds,
state => state.DiscoveryStream.spocs,
],
// Adds data to each component from feeds. This function only re-runs if one of the inputs change.
// TODO: calculate spocs
function layoutRender(layout, feeds, spocs) {
return layout.map(row => ({
...row,
// Loops through all the components and adds a .data property
// containing data from feeds
components: row.components.map(component => {
if (!component.feed || !feeds[component.feed.url]) {
return component;
}
// Calculate if we should display a spoc or not.
if (component.spocs && spocs.data.spocs && spocs.data.spocs.length) {
component.spocs = {
...component.spocs,
positions: calculateSpocs(component, spocs),
};
}
return {...component, data: feeds[component.feed.url].data};
}),
}));
}
);

View File

@ -2,6 +2,7 @@
@import './variables';
@import './theme';
@import './icons';
@import './mixins';
html {
height: 100%;

View File

@ -0,0 +1,5 @@
// Note: lineHeight and fontSize should be unitless but can be derived from pixel values
@mixin limit-visibile-lines($line-count, $line-height, $font-size) {
max-height: 1em * $line-count * $line-height / $font-size;
overflow: hidden;
}

View File

@ -45,6 +45,7 @@ $grey-90-90: rgba($grey-90, 0.9);
$black: #000;
$black-5: rgba($black, 0.05);
$black-10: rgba($black, 0.1);
$black-12: rgba($black, 0.12);
$black-15: rgba($black, 0.15);
$black-20: rgba($black, 0.2);
$black-25: rgba($black, 0.25);

View File

@ -1066,12 +1066,10 @@ main {
background-position-x: right 12px; }
.search-handoff-button:hover {
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.25); }
.search-handoff-button:focus,
.search-active .search-handoff-button {
.search-handoff-button:focus {
border: 1px solid var(--newtab-textbox-focus-color);
box-shadow: var(--newtab-textbox-focus-boxshadow); }
.search-handoff-button:focus .fake-caret,
.search-active .search-handoff-button .fake-caret {
.search-handoff-button:focus .fake-caret {
display: block; }
.search-hidden .search-handoff-button {
opacity: 0;
@ -1631,7 +1629,8 @@ main {
margin: 0 auto;
font-size: 14px;
padding-left: 240px;
display: flex; }
display: flex;
color: var(--newtab-text-primary-color); }
.asrouter-admin .sidebar {
inset-inline-start: 0;
position: fixed;
@ -1643,9 +1642,10 @@ main {
list-style: none; }
.asrouter-admin .sidebar li a {
padding: 10px 34px;
display: block; }
display: block;
color: var(--lwt-sidebar-text-color); }
.asrouter-admin .sidebar li a:hover {
background: #EDEDF0; }
background: var(--newtab-textbox-background-color); }
.asrouter-admin h1 {
font-weight: 200;
font-size: 32px; }
@ -1658,7 +1658,7 @@ main {
border-collapse: collapse;
width: 100%; }
.asrouter-admin .sourceLabel {
background: #EDEDF0;
background: var(--newtab-textbox-background-color);
padding: 2px 5px;
border-radius: 3px; }
.asrouter-admin .sourceLabel.isDisabled {
@ -1706,7 +1706,8 @@ main {
padding: 10px;
display: flex;
background: #FFE900;
border-radius: 3px; }
border-radius: 3px;
color: #0C0C0D; }
.asrouter-admin .helpLink a {
text-decoration: underline; }
.asrouter-admin .dsEnabled {
@ -1764,11 +1765,16 @@ main {
.more-recommendations:dir(rtl)::after {
transform: scaleX(-1); }
.outer-wrapper a {
color: #0C0C0D; }
.discovery-stream.ds-layout {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-column-gap: 48px;
grid-row-gap: 10px; }
grid-row-gap: 10px;
width: 936px;
margin: 0 auto; }
.discovery-stream.ds-layout .ds-column-12 {
grid-column-start: auto;
grid-column-end: span 12; }
@ -1809,6 +1815,26 @@ main {
display: grid;
grid-row-gap: 10px; }
.ds-card-grid {
display: grid; }
.ds-card-grid .ds-card {
background: #FFF;
box-shadow: 0 1px 4px rgba(249, 249, 250, 0.1);
border-radius: 4px;
margin-bottom: 24px; }
.ds-column-5 .ds-card-grid,
.ds-column-6 .ds-card-grid,
.ds-column-7 .ds-card-grid,
.ds-column-8 .ds-card-grid {
grid-template-columns: repeat(2, 1fr);
grid-gap: 24px; }
.ds-column-9 .ds-card-grid,
.dscolumn-10 .ds-card-grid,
.ds-column-11 .ds-card-grid,
.ds-column-12 .ds-card-grid {
grid-template-columns: repeat(4, 1fr);
grid-gap: 24px; }
.ds-header {
font-size: 17px;
line-height: 24px;
@ -1829,6 +1855,9 @@ main {
.ds-hero .ds-card .meta {
padding: 0; }
.ds-hero .img-wrapper {
margin: 0 0 12px; }
.ds-hero .wrapper {
color: #737373;
margin: 18px 0;
@ -1918,6 +1947,42 @@ main {
grid-template-columns: repeat(4, 1fr);
grid-column-gap: 24px; }
.ds-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-row-gap: 10px;
grid-column-gap: 24px;
padding-inline-start: 0; }
.ds-list-item {
line-height: 20px;
font-size: 13px;
display: block;
text-align: start; }
.ds-list-item .ds-list-item-link {
mix-blend-mode: normal;
padding-bottom: 16px;
display: flex;
justify-content: space-between; }
.ds-list-item .ds-list-item-info {
color: #737373;
overflow: hidden;
text-overflow: ellipsis; }
.ds-list-item .ds-list-item-title {
margin-bottom: 8px;
padding-bottom: 8px; }
.ds-list-item .ds-list-item-text {
display: flex;
justify-content: space-between;
flex-direction: column; }
.ds-list-item .ds-list-image {
width: 72px;
height: 72px;
object-fit: cover;
border: 0.5px solid rgba(0, 0, 0, 0.12);
box-sizing: border-box;
border-radius: 4px; }
.ds-section-title ul {
margin: 0;
padding: 0; }
@ -1944,6 +2009,77 @@ main {
padding: 0; }
.ds-top-sites .top-sites .section-top-bar {
display: none; }
.ds-top-sites .top-sites .top-site-outer {
padding: 0 12px; }
.ds-top-sites .top-sites .top-sites-list {
margin: 0 -12px; }
.ds-top-sites .hide-for-narrow {
display: none; }
.ds-column-9 .ds-top-sites .hide-for-narrow,
.ds-column-10 .ds-top-sites .hide-for-narrow,
.ds-column-11 .ds-top-sites .hide-for-narrow,
.ds-column-12 .ds-top-sites .hide-for-narrow {
display: inline-block; }
.ds-column-5 .ds-top-sites .top-site-outer,
.ds-column-6 .ds-top-sites .top-site-outer,
.ds-column-7 .ds-top-sites .top-site-outer,
.ds-column-8 .ds-top-sites .top-site-outer {
padding: 0 10px; }
.ds-column-5 .ds-top-sites .top-sites-list,
.ds-column-6 .ds-top-sites .top-sites-list,
.ds-column-7 .ds-top-sites .top-sites-list,
.ds-column-8 .ds-top-sites .top-sites-list {
margin: 0 -10px; }
.ds-column-5 .ds-top-sites .top-site-inner,
.ds-column-6 .ds-top-sites .top-site-inner,
.ds-column-7 .ds-top-sites .top-site-inner,
.ds-column-8 .ds-top-sites .top-site-inner {
--leftPanelIconWidth: 84.67px; }
.ds-column-5 .ds-top-sites .top-site-inner .tile,
.ds-column-6 .ds-top-sites .top-site-inner .tile,
.ds-column-7 .ds-top-sites .top-site-inner .tile,
.ds-column-8 .ds-top-sites .top-site-inner .tile {
width: var(--leftPanelIconWidth);
height: var(--leftPanelIconWidth); }
.ds-column-5 .ds-top-sites .top-site-inner .title,
.ds-column-6 .ds-top-sites .top-site-inner .title,
.ds-column-7 .ds-top-sites .top-site-inner .title,
.ds-column-8 .ds-top-sites .top-site-inner .title {
width: var(--leftPanelIconWidth); }
.ds-column-1 .ds-top-sites .top-site-outer,
.ds-column-2 .ds-top-sites .top-site-outer,
.ds-column-3 .ds-top-sites .top-site-outer,
.ds-column-4 .ds-top-sites .top-site-outer {
padding: 0 8px; }
.ds-column-1 .ds-top-sites .top-sites-list,
.ds-column-2 .ds-top-sites .top-sites-list,
.ds-column-3 .ds-top-sites .top-sites-list,
.ds-column-4 .ds-top-sites .top-sites-list {
margin: 0 -8px; }
.ds-column-1 .ds-top-sites .top-site-inner,
.ds-column-2 .ds-top-sites .top-site-inner,
.ds-column-3 .ds-top-sites .top-site-inner,
.ds-column-4 .ds-top-sites .top-site-inner {
--rightPanelIconWidth: 82.67px; }
.ds-column-1 .ds-top-sites .top-site-inner .tile,
.ds-column-2 .ds-top-sites .top-site-inner .tile,
.ds-column-3 .ds-top-sites .top-site-inner .tile,
.ds-column-4 .ds-top-sites .top-site-inner .tile {
width: var(--rightPanelIconWidth);
height: var(--rightPanelIconWidth); }
.ds-column-1 .ds-top-sites .top-site-inner .title,
.ds-column-2 .ds-top-sites .top-site-inner .title,
.ds-column-3 .ds-top-sites .top-site-inner .title,
.ds-column-4 .ds-top-sites .top-site-inner .title {
width: var(--rightPanelIconWidth); }
.ds-card {
border: 5px solid transparent; }
@ -1954,8 +2090,7 @@ main {
.ds-card .img-wrapper {
width: 100%;
border: 0.5px solid rgba(0, 0, 0, 0.1);
border-radius: 4px;
margin: 0 0 12px; }
border-radius: 4px; }
.ds-card .img {
height: 0;
padding-top: 50%;
@ -1963,6 +2098,12 @@ main {
background-size: cover; }
.ds-card .meta {
padding: 16px; }
.ds-card .meta .title {
max-height: 2.82353em;
overflow: hidden; }
.ds-card .meta .excerpt {
max-height: 6.15385em;
overflow: hidden; }
.ds-card header {
line-height: 24px;
font-size: 17px;
@ -2187,7 +2328,7 @@ main {
z-index: 2100; }
.ReturnToAMOOverlay .ReturnToAMOText,
.amo + body.hide-main .ReturnToAMOText {
color: rgba(12, 12, 13, 0.8);
color: #0C0C0D;
line-height: 32px;
font-size: 23px;
width: 100%; }
@ -2197,18 +2338,18 @@ main {
margin-inline-end: 6px; }
.ReturnToAMOOverlay h2,
.amo + body.hide-main h2 {
color: rgba(74, 74, 79, 0.6);
color: #4A4A4F;
font-weight: 100;
margin: 0 0 22px;
margin: 0 0 36px;
font-size: 36px;
line-height: 48px;
letter-spacing: 1.2px; }
.ReturnToAMOOverlay p,
.amo + body.hide-main p {
color: rgba(12, 12, 13, 0.5);
color: #4A4A4F;
font-size: 14px;
line-height: 18px;
margin-bottom: 4px; }
margin-bottom: 16px; }
.ReturnToAMOOverlay .puffy,
.amo + body.hide-main .puffy {
border-radius: 4px;
@ -2256,16 +2397,17 @@ main {
margin-top: 20px; }
.ReturnToAMOOverlay .ReturnToAMOContainer,
.amo + body.hide-main .ReturnToAMOContainer {
width: 835px;
width: 960px;
background: #FFF;
box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.3);
border-radius: 4px;
display: flex;
padding: 38px 96px 28px 48px; }
padding: 64px 64px 72px; }
.ReturnToAMOOverlay .ReturnToAMOAddonContents,
.amo + body.hide-main .ReturnToAMOAddonContents {
width: 400px;
margin-top: 42px; }
width: 560px;
margin-top: 32px;
margin-inline-end: 24px; }
.ReturnToAMOOverlay .ReturnToAMOIcon,
.amo + body.hide-main .ReturnToAMOIcon {
width: 292px;

File diff suppressed because one or more lines are too long

View File

@ -1069,12 +1069,10 @@ main {
background-position-x: right 12px; }
.search-handoff-button:hover {
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.25); }
.search-handoff-button:focus,
.search-active .search-handoff-button {
.search-handoff-button:focus {
border: 1px solid var(--newtab-textbox-focus-color);
box-shadow: var(--newtab-textbox-focus-boxshadow); }
.search-handoff-button:focus .fake-caret,
.search-active .search-handoff-button .fake-caret {
.search-handoff-button:focus .fake-caret {
display: block; }
.search-hidden .search-handoff-button {
opacity: 0;
@ -1634,7 +1632,8 @@ main {
margin: 0 auto;
font-size: 14px;
padding-left: 240px;
display: flex; }
display: flex;
color: var(--newtab-text-primary-color); }
.asrouter-admin .sidebar {
inset-inline-start: 0;
position: fixed;
@ -1646,9 +1645,10 @@ main {
list-style: none; }
.asrouter-admin .sidebar li a {
padding: 10px 34px;
display: block; }
display: block;
color: var(--lwt-sidebar-text-color); }
.asrouter-admin .sidebar li a:hover {
background: #EDEDF0; }
background: var(--newtab-textbox-background-color); }
.asrouter-admin h1 {
font-weight: 200;
font-size: 32px; }
@ -1661,7 +1661,7 @@ main {
border-collapse: collapse;
width: 100%; }
.asrouter-admin .sourceLabel {
background: #EDEDF0;
background: var(--newtab-textbox-background-color);
padding: 2px 5px;
border-radius: 3px; }
.asrouter-admin .sourceLabel.isDisabled {
@ -1709,7 +1709,8 @@ main {
padding: 10px;
display: flex;
background: #FFE900;
border-radius: 3px; }
border-radius: 3px;
color: #0C0C0D; }
.asrouter-admin .helpLink a {
text-decoration: underline; }
.asrouter-admin .dsEnabled {
@ -1767,11 +1768,16 @@ main {
.more-recommendations:dir(rtl)::after {
transform: scaleX(-1); }
.outer-wrapper a {
color: #0C0C0D; }
.discovery-stream.ds-layout {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-column-gap: 48px;
grid-row-gap: 10px; }
grid-row-gap: 10px;
width: 936px;
margin: 0 auto; }
.discovery-stream.ds-layout .ds-column-12 {
grid-column-start: auto;
grid-column-end: span 12; }
@ -1812,6 +1818,26 @@ main {
display: grid;
grid-row-gap: 10px; }
.ds-card-grid {
display: grid; }
.ds-card-grid .ds-card {
background: #FFF;
box-shadow: 0 1px 4px rgba(249, 249, 250, 0.1);
border-radius: 4px;
margin-bottom: 24px; }
.ds-column-5 .ds-card-grid,
.ds-column-6 .ds-card-grid,
.ds-column-7 .ds-card-grid,
.ds-column-8 .ds-card-grid {
grid-template-columns: repeat(2, 1fr);
grid-gap: 24px; }
.ds-column-9 .ds-card-grid,
.dscolumn-10 .ds-card-grid,
.ds-column-11 .ds-card-grid,
.ds-column-12 .ds-card-grid {
grid-template-columns: repeat(4, 1fr);
grid-gap: 24px; }
.ds-header {
font-size: 17px;
line-height: 24px;
@ -1832,6 +1858,9 @@ main {
.ds-hero .ds-card .meta {
padding: 0; }
.ds-hero .img-wrapper {
margin: 0 0 12px; }
.ds-hero .wrapper {
color: #737373;
margin: 18px 0;
@ -1921,6 +1950,42 @@ main {
grid-template-columns: repeat(4, 1fr);
grid-column-gap: 24px; }
.ds-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-row-gap: 10px;
grid-column-gap: 24px;
padding-inline-start: 0; }
.ds-list-item {
line-height: 20px;
font-size: 13px;
display: block;
text-align: start; }
.ds-list-item .ds-list-item-link {
mix-blend-mode: normal;
padding-bottom: 16px;
display: flex;
justify-content: space-between; }
.ds-list-item .ds-list-item-info {
color: #737373;
overflow: hidden;
text-overflow: ellipsis; }
.ds-list-item .ds-list-item-title {
margin-bottom: 8px;
padding-bottom: 8px; }
.ds-list-item .ds-list-item-text {
display: flex;
justify-content: space-between;
flex-direction: column; }
.ds-list-item .ds-list-image {
width: 72px;
height: 72px;
object-fit: cover;
border: 0.5px solid rgba(0, 0, 0, 0.12);
box-sizing: border-box;
border-radius: 4px; }
.ds-section-title ul {
margin: 0;
padding: 0; }
@ -1947,6 +2012,77 @@ main {
padding: 0; }
.ds-top-sites .top-sites .section-top-bar {
display: none; }
.ds-top-sites .top-sites .top-site-outer {
padding: 0 12px; }
.ds-top-sites .top-sites .top-sites-list {
margin: 0 -12px; }
.ds-top-sites .hide-for-narrow {
display: none; }
.ds-column-9 .ds-top-sites .hide-for-narrow,
.ds-column-10 .ds-top-sites .hide-for-narrow,
.ds-column-11 .ds-top-sites .hide-for-narrow,
.ds-column-12 .ds-top-sites .hide-for-narrow {
display: inline-block; }
.ds-column-5 .ds-top-sites .top-site-outer,
.ds-column-6 .ds-top-sites .top-site-outer,
.ds-column-7 .ds-top-sites .top-site-outer,
.ds-column-8 .ds-top-sites .top-site-outer {
padding: 0 10px; }
.ds-column-5 .ds-top-sites .top-sites-list,
.ds-column-6 .ds-top-sites .top-sites-list,
.ds-column-7 .ds-top-sites .top-sites-list,
.ds-column-8 .ds-top-sites .top-sites-list {
margin: 0 -10px; }
.ds-column-5 .ds-top-sites .top-site-inner,
.ds-column-6 .ds-top-sites .top-site-inner,
.ds-column-7 .ds-top-sites .top-site-inner,
.ds-column-8 .ds-top-sites .top-site-inner {
--leftPanelIconWidth: 84.67px; }
.ds-column-5 .ds-top-sites .top-site-inner .tile,
.ds-column-6 .ds-top-sites .top-site-inner .tile,
.ds-column-7 .ds-top-sites .top-site-inner .tile,
.ds-column-8 .ds-top-sites .top-site-inner .tile {
width: var(--leftPanelIconWidth);
height: var(--leftPanelIconWidth); }
.ds-column-5 .ds-top-sites .top-site-inner .title,
.ds-column-6 .ds-top-sites .top-site-inner .title,
.ds-column-7 .ds-top-sites .top-site-inner .title,
.ds-column-8 .ds-top-sites .top-site-inner .title {
width: var(--leftPanelIconWidth); }
.ds-column-1 .ds-top-sites .top-site-outer,
.ds-column-2 .ds-top-sites .top-site-outer,
.ds-column-3 .ds-top-sites .top-site-outer,
.ds-column-4 .ds-top-sites .top-site-outer {
padding: 0 8px; }
.ds-column-1 .ds-top-sites .top-sites-list,
.ds-column-2 .ds-top-sites .top-sites-list,
.ds-column-3 .ds-top-sites .top-sites-list,
.ds-column-4 .ds-top-sites .top-sites-list {
margin: 0 -8px; }
.ds-column-1 .ds-top-sites .top-site-inner,
.ds-column-2 .ds-top-sites .top-site-inner,
.ds-column-3 .ds-top-sites .top-site-inner,
.ds-column-4 .ds-top-sites .top-site-inner {
--rightPanelIconWidth: 82.67px; }
.ds-column-1 .ds-top-sites .top-site-inner .tile,
.ds-column-2 .ds-top-sites .top-site-inner .tile,
.ds-column-3 .ds-top-sites .top-site-inner .tile,
.ds-column-4 .ds-top-sites .top-site-inner .tile {
width: var(--rightPanelIconWidth);
height: var(--rightPanelIconWidth); }
.ds-column-1 .ds-top-sites .top-site-inner .title,
.ds-column-2 .ds-top-sites .top-site-inner .title,
.ds-column-3 .ds-top-sites .top-site-inner .title,
.ds-column-4 .ds-top-sites .top-site-inner .title {
width: var(--rightPanelIconWidth); }
.ds-card {
border: 5px solid transparent; }
@ -1957,8 +2093,7 @@ main {
.ds-card .img-wrapper {
width: 100%;
border: 0.5px solid rgba(0, 0, 0, 0.1);
border-radius: 4px;
margin: 0 0 12px; }
border-radius: 4px; }
.ds-card .img {
height: 0;
padding-top: 50%;
@ -1966,6 +2101,12 @@ main {
background-size: cover; }
.ds-card .meta {
padding: 16px; }
.ds-card .meta .title {
max-height: 2.82353em;
overflow: hidden; }
.ds-card .meta .excerpt {
max-height: 6.15385em;
overflow: hidden; }
.ds-card header {
line-height: 24px;
font-size: 17px;
@ -2190,7 +2331,7 @@ main {
z-index: 2100; }
.ReturnToAMOOverlay .ReturnToAMOText,
.amo + body.hide-main .ReturnToAMOText {
color: rgba(12, 12, 13, 0.8);
color: #0C0C0D;
line-height: 32px;
font-size: 23px;
width: 100%; }
@ -2200,18 +2341,18 @@ main {
margin-inline-end: 6px; }
.ReturnToAMOOverlay h2,
.amo + body.hide-main h2 {
color: rgba(74, 74, 79, 0.6);
color: #4A4A4F;
font-weight: 100;
margin: 0 0 22px;
margin: 0 0 36px;
font-size: 36px;
line-height: 48px;
letter-spacing: 1.2px; }
.ReturnToAMOOverlay p,
.amo + body.hide-main p {
color: rgba(12, 12, 13, 0.5);
color: #4A4A4F;
font-size: 14px;
line-height: 18px;
margin-bottom: 4px; }
margin-bottom: 16px; }
.ReturnToAMOOverlay .puffy,
.amo + body.hide-main .puffy {
border-radius: 4px;
@ -2259,16 +2400,17 @@ main {
margin-top: 20px; }
.ReturnToAMOOverlay .ReturnToAMOContainer,
.amo + body.hide-main .ReturnToAMOContainer {
width: 835px;
width: 960px;
background: #FFF;
box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.3);
border-radius: 4px;
display: flex;
padding: 38px 96px 28px 48px; }
padding: 64px 64px 72px; }
.ReturnToAMOOverlay .ReturnToAMOAddonContents,
.amo + body.hide-main .ReturnToAMOAddonContents {
width: 400px;
margin-top: 42px; }
width: 560px;
margin-top: 32px;
margin-inline-end: 24px; }
.ReturnToAMOOverlay .ReturnToAMOIcon,
.amo + body.hide-main .ReturnToAMOIcon {
width: 292px;

File diff suppressed because one or more lines are too long

View File

@ -1066,12 +1066,10 @@ main {
background-position-x: right 12px; }
.search-handoff-button:hover {
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.25); }
.search-handoff-button:focus,
.search-active .search-handoff-button {
.search-handoff-button:focus {
border: 1px solid var(--newtab-textbox-focus-color);
box-shadow: var(--newtab-textbox-focus-boxshadow); }
.search-handoff-button:focus .fake-caret,
.search-active .search-handoff-button .fake-caret {
.search-handoff-button:focus .fake-caret {
display: block; }
.search-hidden .search-handoff-button {
opacity: 0;
@ -1631,7 +1629,8 @@ main {
margin: 0 auto;
font-size: 14px;
padding-left: 240px;
display: flex; }
display: flex;
color: var(--newtab-text-primary-color); }
.asrouter-admin .sidebar {
inset-inline-start: 0;
position: fixed;
@ -1643,9 +1642,10 @@ main {
list-style: none; }
.asrouter-admin .sidebar li a {
padding: 10px 34px;
display: block; }
display: block;
color: var(--lwt-sidebar-text-color); }
.asrouter-admin .sidebar li a:hover {
background: #EDEDF0; }
background: var(--newtab-textbox-background-color); }
.asrouter-admin h1 {
font-weight: 200;
font-size: 32px; }
@ -1658,7 +1658,7 @@ main {
border-collapse: collapse;
width: 100%; }
.asrouter-admin .sourceLabel {
background: #EDEDF0;
background: var(--newtab-textbox-background-color);
padding: 2px 5px;
border-radius: 3px; }
.asrouter-admin .sourceLabel.isDisabled {
@ -1706,7 +1706,8 @@ main {
padding: 10px;
display: flex;
background: #FFE900;
border-radius: 3px; }
border-radius: 3px;
color: #0C0C0D; }
.asrouter-admin .helpLink a {
text-decoration: underline; }
.asrouter-admin .dsEnabled {
@ -1764,11 +1765,16 @@ main {
.more-recommendations:dir(rtl)::after {
transform: scaleX(-1); }
.outer-wrapper a {
color: #0C0C0D; }
.discovery-stream.ds-layout {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-column-gap: 48px;
grid-row-gap: 10px; }
grid-row-gap: 10px;
width: 936px;
margin: 0 auto; }
.discovery-stream.ds-layout .ds-column-12 {
grid-column-start: auto;
grid-column-end: span 12; }
@ -1809,6 +1815,26 @@ main {
display: grid;
grid-row-gap: 10px; }
.ds-card-grid {
display: grid; }
.ds-card-grid .ds-card {
background: #FFF;
box-shadow: 0 1px 4px rgba(249, 249, 250, 0.1);
border-radius: 4px;
margin-bottom: 24px; }
.ds-column-5 .ds-card-grid,
.ds-column-6 .ds-card-grid,
.ds-column-7 .ds-card-grid,
.ds-column-8 .ds-card-grid {
grid-template-columns: repeat(2, 1fr);
grid-gap: 24px; }
.ds-column-9 .ds-card-grid,
.dscolumn-10 .ds-card-grid,
.ds-column-11 .ds-card-grid,
.ds-column-12 .ds-card-grid {
grid-template-columns: repeat(4, 1fr);
grid-gap: 24px; }
.ds-header {
font-size: 17px;
line-height: 24px;
@ -1829,6 +1855,9 @@ main {
.ds-hero .ds-card .meta {
padding: 0; }
.ds-hero .img-wrapper {
margin: 0 0 12px; }
.ds-hero .wrapper {
color: #737373;
margin: 18px 0;
@ -1918,6 +1947,42 @@ main {
grid-template-columns: repeat(4, 1fr);
grid-column-gap: 24px; }
.ds-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-row-gap: 10px;
grid-column-gap: 24px;
padding-inline-start: 0; }
.ds-list-item {
line-height: 20px;
font-size: 13px;
display: block;
text-align: start; }
.ds-list-item .ds-list-item-link {
mix-blend-mode: normal;
padding-bottom: 16px;
display: flex;
justify-content: space-between; }
.ds-list-item .ds-list-item-info {
color: #737373;
overflow: hidden;
text-overflow: ellipsis; }
.ds-list-item .ds-list-item-title {
margin-bottom: 8px;
padding-bottom: 8px; }
.ds-list-item .ds-list-item-text {
display: flex;
justify-content: space-between;
flex-direction: column; }
.ds-list-item .ds-list-image {
width: 72px;
height: 72px;
object-fit: cover;
border: 0.5px solid rgba(0, 0, 0, 0.12);
box-sizing: border-box;
border-radius: 4px; }
.ds-section-title ul {
margin: 0;
padding: 0; }
@ -1944,6 +2009,77 @@ main {
padding: 0; }
.ds-top-sites .top-sites .section-top-bar {
display: none; }
.ds-top-sites .top-sites .top-site-outer {
padding: 0 12px; }
.ds-top-sites .top-sites .top-sites-list {
margin: 0 -12px; }
.ds-top-sites .hide-for-narrow {
display: none; }
.ds-column-9 .ds-top-sites .hide-for-narrow,
.ds-column-10 .ds-top-sites .hide-for-narrow,
.ds-column-11 .ds-top-sites .hide-for-narrow,
.ds-column-12 .ds-top-sites .hide-for-narrow {
display: inline-block; }
.ds-column-5 .ds-top-sites .top-site-outer,
.ds-column-6 .ds-top-sites .top-site-outer,
.ds-column-7 .ds-top-sites .top-site-outer,
.ds-column-8 .ds-top-sites .top-site-outer {
padding: 0 10px; }
.ds-column-5 .ds-top-sites .top-sites-list,
.ds-column-6 .ds-top-sites .top-sites-list,
.ds-column-7 .ds-top-sites .top-sites-list,
.ds-column-8 .ds-top-sites .top-sites-list {
margin: 0 -10px; }
.ds-column-5 .ds-top-sites .top-site-inner,
.ds-column-6 .ds-top-sites .top-site-inner,
.ds-column-7 .ds-top-sites .top-site-inner,
.ds-column-8 .ds-top-sites .top-site-inner {
--leftPanelIconWidth: 84.67px; }
.ds-column-5 .ds-top-sites .top-site-inner .tile,
.ds-column-6 .ds-top-sites .top-site-inner .tile,
.ds-column-7 .ds-top-sites .top-site-inner .tile,
.ds-column-8 .ds-top-sites .top-site-inner .tile {
width: var(--leftPanelIconWidth);
height: var(--leftPanelIconWidth); }
.ds-column-5 .ds-top-sites .top-site-inner .title,
.ds-column-6 .ds-top-sites .top-site-inner .title,
.ds-column-7 .ds-top-sites .top-site-inner .title,
.ds-column-8 .ds-top-sites .top-site-inner .title {
width: var(--leftPanelIconWidth); }
.ds-column-1 .ds-top-sites .top-site-outer,
.ds-column-2 .ds-top-sites .top-site-outer,
.ds-column-3 .ds-top-sites .top-site-outer,
.ds-column-4 .ds-top-sites .top-site-outer {
padding: 0 8px; }
.ds-column-1 .ds-top-sites .top-sites-list,
.ds-column-2 .ds-top-sites .top-sites-list,
.ds-column-3 .ds-top-sites .top-sites-list,
.ds-column-4 .ds-top-sites .top-sites-list {
margin: 0 -8px; }
.ds-column-1 .ds-top-sites .top-site-inner,
.ds-column-2 .ds-top-sites .top-site-inner,
.ds-column-3 .ds-top-sites .top-site-inner,
.ds-column-4 .ds-top-sites .top-site-inner {
--rightPanelIconWidth: 82.67px; }
.ds-column-1 .ds-top-sites .top-site-inner .tile,
.ds-column-2 .ds-top-sites .top-site-inner .tile,
.ds-column-3 .ds-top-sites .top-site-inner .tile,
.ds-column-4 .ds-top-sites .top-site-inner .tile {
width: var(--rightPanelIconWidth);
height: var(--rightPanelIconWidth); }
.ds-column-1 .ds-top-sites .top-site-inner .title,
.ds-column-2 .ds-top-sites .top-site-inner .title,
.ds-column-3 .ds-top-sites .top-site-inner .title,
.ds-column-4 .ds-top-sites .top-site-inner .title {
width: var(--rightPanelIconWidth); }
.ds-card {
border: 5px solid transparent; }
@ -1954,8 +2090,7 @@ main {
.ds-card .img-wrapper {
width: 100%;
border: 0.5px solid rgba(0, 0, 0, 0.1);
border-radius: 4px;
margin: 0 0 12px; }
border-radius: 4px; }
.ds-card .img {
height: 0;
padding-top: 50%;
@ -1963,6 +2098,12 @@ main {
background-size: cover; }
.ds-card .meta {
padding: 16px; }
.ds-card .meta .title {
max-height: 2.82353em;
overflow: hidden; }
.ds-card .meta .excerpt {
max-height: 6.15385em;
overflow: hidden; }
.ds-card header {
line-height: 24px;
font-size: 17px;
@ -2187,7 +2328,7 @@ main {
z-index: 2100; }
.ReturnToAMOOverlay .ReturnToAMOText,
.amo + body.hide-main .ReturnToAMOText {
color: rgba(12, 12, 13, 0.8);
color: #0C0C0D;
line-height: 32px;
font-size: 23px;
width: 100%; }
@ -2197,18 +2338,18 @@ main {
margin-inline-end: 6px; }
.ReturnToAMOOverlay h2,
.amo + body.hide-main h2 {
color: rgba(74, 74, 79, 0.6);
color: #4A4A4F;
font-weight: 100;
margin: 0 0 22px;
margin: 0 0 36px;
font-size: 36px;
line-height: 48px;
letter-spacing: 1.2px; }
.ReturnToAMOOverlay p,
.amo + body.hide-main p {
color: rgba(12, 12, 13, 0.5);
color: #4A4A4F;
font-size: 14px;
line-height: 18px;
margin-bottom: 4px; }
margin-bottom: 16px; }
.ReturnToAMOOverlay .puffy,
.amo + body.hide-main .puffy {
border-radius: 4px;
@ -2256,16 +2397,17 @@ main {
margin-top: 20px; }
.ReturnToAMOOverlay .ReturnToAMOContainer,
.amo + body.hide-main .ReturnToAMOContainer {
width: 835px;
width: 960px;
background: #FFF;
box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.3);
border-radius: 4px;
display: flex;
padding: 38px 96px 28px 48px; }
padding: 64px 64px 72px; }
.ReturnToAMOOverlay .ReturnToAMOAddonContents,
.amo + body.hide-main .ReturnToAMOAddonContents {
width: 400px;
margin-top: 42px; }
width: 560px;
margin-top: 32px;
margin-inline-end: 24px; }
.ReturnToAMOOverlay .ReturnToAMOIcon,
.amo + body.hide-main .ReturnToAMOIcon {
width: 292px;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -66,7 +66,7 @@ A user event ping includes some basic metadata (tab id, addon version, etc.) as
```js
{
// This indicates the type of interaction
  "event": ["CLICK", "SEARCH", "BLOCK", "DELETE", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "BOOKMARK_DELETE", "BOOKMARK_ADD", "OPEN_NEWTAB_PREFS", "CLOSE_NEWTAB_PREFS"],
  "event": ["CLICK", "SEARCH", "BLOCK", "DELETE", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "BOOKMARK_DELETE", "BOOKMARK_ADD", "OPEN_NEWTAB_PREFS", "CLOSE_NEWTAB_PREFS", "SEARCH_HANDOFF"],
// Optional field indicating the UI component type
"source": "TOP_SITES",
@ -106,6 +106,23 @@ A user event ping includes some basic metadata (tab id, addon version, etc.) as
}
```
#### Performing a search handoff
```js
{
  "event": "SEARCH_HANDOFF",
// Basic metadata
"action": "activity_stream_event",
"page": ["about:newtab" | "about:home" | "about:welcome" | "unknown"],
  "client_id": "26288a14-5cc4-d14f-ae0a-bb01ef45be9c",
"session_id": "005deed0-e3e4-4c02-a041-17405fd703f6",
  "addon_version": "20180710100040",
  "locale": "en-US",
"user_prefs": 7
}
```
#### Clicking a top site item
```js

View File

@ -10,6 +10,8 @@ XPCOMUtils.defineLazyModuleGetters(this, {
AddonManager: "resource://gre/modules/AddonManager.jsm",
UITour: "resource:///modules/UITour.jsm",
FxAccounts: "resource://gre/modules/FxAccounts.jsm",
AppConstants: "resource://gre/modules/AppConstants.jsm",
OS: "resource://gre/modules/osfile.jsm",
});
const {ASRouterActions: ra, actionTypes: at, actionCreators: ac} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm", {});
const {CFRMessageProvider} = ChromeUtils.import("resource://activity-stream/lib/CFRMessageProvider.jsm", {});
@ -948,24 +950,49 @@ class _ASRouter {
}
}
// Windows specific calls to write attribution data
// Used by `forceAttribution` to set required targeting attributes for
// RTAMO messages. This should only be called from within about:newtab#asrouter
/* istanbul ignore next */
async _writeAttributionFile(data) {
let appDir = Services.dirsvc.get("LocalAppData", Ci.nsIFile);
let file = appDir.clone();
file.append(Services.appinfo.vendor || "mozilla");
file.append(AppConstants.MOZ_APP_NAME);
await OS.File.makeDir(file.path,
{from: appDir.path, ignoreExisting: true});
file.append("postSigningData");
await OS.File.writeAtomic(file.path, data);
}
/**
* forceAttribution - this function should only be called from within about:newtab#asrouter.
* It forces the browser attribution to be set to something specified in asrouter admin
* tools, and reloads the providers in order to get messages that are dependant on this
* attribution data (see Return to AMO flow in bug 1475354 for example). Note - only works with OSX
* attribution data (see Return to AMO flow in bug 1475354 for example). Note - OSX and Windows only
* @param {data} Object an object containing the attribtion data that came from asrouter admin page
*/
/* istanbul ignore next */
async forceAttribution(data) {
// Extract the parameters from data that will make up the referrer url
const {source, campaign, content} = data;
let appPath = Services.dirsvc.get("GreD", Ci.nsIFile).parent.parent.path;
let attributionSvc = Cc["@mozilla.org/mac-attribution;1"]
.getService(Ci.nsIMacAttributionService);
if (AppConstants.platform === "win") {
const attributionData = `source=${source}&campaign=${campaign}&content=${content}`;
this._writeAttributionFile(encodeURIComponent(attributionData));
} else if (AppConstants.platform === "macosx") {
let appPath = Services.dirsvc.get("GreD", Ci.nsIFile).parent.parent.path;
let attributionSvc = Cc["@mozilla.org/mac-attribution;1"]
.getService(Ci.nsIMacAttributionService);
let referrer = `https://www.mozilla.org/anything/?utm_campaign=${campaign}&utm_source=${source}&utm_content=${encodeURIComponent(content)}`;
let referrer = `https://www.mozilla.org/anything/?utm_campaign=${campaign}&utm_source=${source}&utm_content=${encodeURIComponent(content)}`;
// This sets the Attribution to be the referrer
attributionSvc.setReferrerUrl(appPath, referrer, true);
// This sets the Attribution to be the referrer
attributionSvc.setReferrerUrl(appPath, referrer, true);
}
// Clear cache call is only possible in a testing environment
let env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
env.set("XPCSHELL_TEST_PROFILE_DIR", "testing");

View File

@ -286,41 +286,28 @@ class PlacesFeed {
handoffSearchToAwesomebar({_target, data, meta}) {
const urlBar = _target.browser.ownerGlobal.gURLBar;
if (!data.hiddenFocus && !data.text) {
// Do a normal focus of awesomebar and reset the in content search (remove fake focus styles).
if (!data.text) {
// Do a normal focus of awesomebar.
urlBar.focus();
this.store.dispatch(ac.OnlyToOneContent({type: at.SHOW_SEARCH}, meta.fromTarget));
// We are done here. return early.
return;
}
if (data.text) {
// Pass the provided text to the awesomebar.
urlBar.search(data.text);
this.store.dispatch(ac.OnlyToOneContent({type: at.HIDE_SEARCH}, meta.fromTarget));
} else {
// Focus the awesomebar without the style changes.
urlBar.hiddenFocus();
}
// Pass the provided text to the awesomebar.
urlBar.search(data.text);
const onKeydown = event => {
// We only care about key strokes that will produce a character.
if (event.key.length === 1 && !event.altKey && !event.ctrlKey && !event.metaKey) {
// Once the user starts typing, we want to hide the in content search box
// and show the focus styles on the awesomebar.
this.store.dispatch(ac.OnlyToOneContent({type: at.HIDE_SEARCH}, meta.fromTarget));
urlBar.removeHiddenFocus();
urlBar.removeEventListener("keydown", onKeydown);
}
};
const onDone = () => {
// When done, let's cleanup everything.
this.store.dispatch(ac.OnlyToOneContent({type: at.SHOW_SEARCH}, meta.fromTarget));
urlBar.removeHiddenFocus();
urlBar.removeEventListener("keydown", onKeydown);
urlBar.removeEventListener("mousedown", onDone);
urlBar.removeEventListener("blur", onDone);
};
const onKeydown = event => {
// If the Esc button is pressed, we are done. Show in-content search and cleanup.
if (event.key === "Escape") {
onDone();
}
};
urlBar.addEventListener("keydown", onKeydown);
urlBar.addEventListener("mousedown", onDone);
urlBar.addEventListener("blur", onDone);

View File

@ -126,7 +126,7 @@ topsites_form_edit_header=Wichtige Seite bearbeiten
topsites_form_title_label=Titel
topsites_form_title_placeholder=Name eingeben
topsites_form_url_label=Adresse
topsites_form_image_url_label=URL von benutzerdefinierter Grafik
topsites_form_image_url_label=Adresse von benutzerdefinierter Grafik
topsites_form_url_placeholder=Eine Adresse eingeben oder einfügen
topsites_form_use_image_link=Eine benutzerdefinierte Grafik verwenden…
# LOCALIZATION NOTE (topsites_form_*_button): These are verbs/actions.
@ -134,8 +134,8 @@ topsites_form_preview_button=Vorschau
topsites_form_add_button=Hinzufügen
topsites_form_save_button=Speichern
topsites_form_cancel_button=Abbrechen
topsites_form_url_validation=Gültige URL erforderlich
topsites_form_image_validation=Grafik konnte nicht geladen werden. Verwenden Sie eine andere URL.
topsites_form_url_validation=Gültige Adresse erforderlich
topsites_form_image_validation=Grafik konnte nicht geladen werden. Verwenden Sie eine andere Adresse.
# LOCALIZATION NOTE (pocket_read_more): This is shown at the bottom of the
# trending stories section and precedes a list of links to popular topics.
@ -144,7 +144,6 @@ pocket_read_more=Beliebte Themen:
# end of the list of popular topic links.
pocket_read_even_more=Weitere Nachrichten ansehen
pocket_more_reccommendations=Mehr Empfehlungen
pocket_learn_more=Weitere Informationen
pocket_how_it_works=Wie es funktioniert
pocket_cta_button=Pocket holen
pocket_cta_text=Speichern Sie Ihre Lieblingstexte in Pocket und gewinnen Sie gedankenreiche Einblicke durch faszinierende Texte.

View File

@ -10159,6 +10159,11 @@
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
"dev": true
},
"reselect": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz",
"integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA=="
},
"resolve": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz",

View File

@ -13,7 +13,8 @@
"react-dom": "16.2.0",
"react-intl": "2.4.0",
"react-redux": "5.1.0",
"redux": "4.0.1"
"redux": "4.0.1",
"reselect": "4.0.0"
},
"devDependencies": {
"@octokit/rest": "15.17.0",

View File

@ -66,15 +66,15 @@ window.gActivityStreamStrings = {
"topsites_form_title_label": "Titel",
"topsites_form_title_placeholder": "Name eingeben",
"topsites_form_url_label": "Adresse",
"topsites_form_image_url_label": "URL von benutzerdefinierter Grafik",
"topsites_form_image_url_label": "Adresse von benutzerdefinierter Grafik",
"topsites_form_url_placeholder": "Eine Adresse eingeben oder einfügen",
"topsites_form_use_image_link": "Eine benutzerdefinierte Grafik verwenden…",
"topsites_form_preview_button": "Vorschau",
"topsites_form_add_button": "Hinzufügen",
"topsites_form_save_button": "Speichern",
"topsites_form_cancel_button": "Abbrechen",
"topsites_form_url_validation": "Gültige URL erforderlich",
"topsites_form_image_validation": "Grafik konnte nicht geladen werden. Verwenden Sie eine andere URL.",
"topsites_form_url_validation": "Gültige Adresse erforderlich",
"topsites_form_image_validation": "Grafik konnte nicht geladen werden. Verwenden Sie eine andere Adresse.",
"pocket_read_more": "Beliebte Themen:",
"pocket_read_even_more": "Weitere Nachrichten ansehen",
"pocket_more_reccommendations": "Mehr Empfehlungen",
@ -110,6 +110,5 @@ window.gActivityStreamStrings = {
"firstrun_privacy_notice": "Datenschutzhinweis",
"firstrun_continue_to_login": "Weiter",
"firstrun_skip_login": "Diesen Schritt überspringen",
"context_menu_title": "Menü öffnen",
"pocket_learn_more": "Weitere Informationen"
"context_menu_title": "Menü öffnen"
};

View File

@ -77,7 +77,7 @@ window.gActivityStreamPrerenderedState = {
"spocs": {
"spocs_endpoint": "",
"lastUpdated": null,
"data": []
"data": {}
}
},
"Search": {

View File

@ -70,6 +70,7 @@ export const UserEventAction = Joi.object().keys({
event: Joi.valid([
"CLICK",
"SEARCH",
"SEARCH_HANDOFF",
"BLOCK",
"DELETE",
"DELETE_CONFIRM",

View File

@ -698,13 +698,8 @@ describe("Reducers", () => {
const nextState = Search(undefined, {type: "HIDE_SEARCH"});
assert.propertyVal(nextState, "hide", true);
});
it("should set focus to true on FOCUS_SEARCH", () => {
const nextState = Search(undefined, {type: "FOCUS_SEARCH"});
assert.propertyVal(nextState, "focus", true);
});
it("should set focus and hide to false on SHOW_SEARCH", () => {
const nextState = Search(undefined, {type: "SHOW_SEARCH"});
assert.propertyVal(nextState, "focus", false);
assert.propertyVal(nextState, "hide", false);
});
});

View File

@ -0,0 +1,137 @@
import {actionTypes as at} from "common/Actions.jsm";
import {ImpressionStats} from "content-src/components/DiscoveryStreamImpressionStats/ImpressionStats";
import React from "react";
import {shallow} from "enzyme";
const SOURCE = "TEST_SOURCE";
describe("<ImpressionStats>", () => {
const DEFAULT_PROPS = {
rows: [{id: 1}, {id: 2}, {id: 3}],
source: SOURCE,
document: {
visibilityState: "visible",
addEventListener: sinon.stub(),
removeEventListener: sinon.stub(),
},
};
const InnerEl = () => (<div>Inner Element</div>);
function renderImpressionStats(props = {}) {
return shallow(<ImpressionStats {...DEFAULT_PROPS} {...props}>
<InnerEl />
</ImpressionStats>);
}
it("should render props.children", () => {
const wrapper = renderImpressionStats();
assert.ok(wrapper.contains(<InnerEl />));
});
it("should send impression with the right stats when the page loads", () => {
const dispatch = sinon.spy();
const props = {dispatch};
renderImpressionStats(props);
assert.calledOnce(dispatch);
const [action] = dispatch.firstCall.args;
assert.equal(action.type, at.TELEMETRY_IMPRESSION_STATS);
assert.equal(action.data.source, SOURCE);
assert.deepEqual(action.data.tiles, [{id: 1}, {id: 2}, {id: 3}]);
});
it("should send 1 impression when the page becomes visibile after loading", () => {
const props = {
document: {
visibilityState: "hidden",
addEventListener: sinon.spy(),
removeEventListener: sinon.spy(),
},
dispatch: sinon.spy(),
};
renderImpressionStats(props);
// Was the event listener added?
assert.calledWith(props.document.addEventListener, "visibilitychange");
// Make sure dispatch wasn't called yet
assert.notCalled(props.dispatch);
// Simulate a visibilityChange event
const [, listener] = props.document.addEventListener.firstCall.args;
props.document.visibilityState = "visible";
listener();
// Did we actually dispatch an event?
assert.calledOnce(props.dispatch);
assert.equal(props.dispatch.firstCall.args[0].type, at.TELEMETRY_IMPRESSION_STATS);
// Did we remove the event listener?
assert.calledWith(props.document.removeEventListener, "visibilitychange", listener);
});
it("should remove visibility change listener when wrapper is removed", () => {
const props = {
dispatch: sinon.spy(),
document: {
visibilityState: "hidden",
addEventListener: sinon.spy(),
removeEventListener: sinon.spy(),
},
};
const wrapper = renderImpressionStats(props);
assert.calledWith(props.document.addEventListener, "visibilitychange");
const [, listener] = props.document.addEventListener.firstCall.args;
wrapper.unmount();
assert.calledWith(props.document.removeEventListener, "visibilitychange", listener);
});
it("should send an impression if props are updated and props.rows are different", () => {
const props = {dispatch: sinon.spy()};
const wrapper = renderImpressionStats(props);
props.dispatch.resetHistory();
// New rows
wrapper.setProps({...DEFAULT_PROPS, ...{rows: [{id: 4}]}});
assert.calledOnce(props.dispatch);
});
it("should not send an impression if props are updated but IDs are the same", () => {
const props = {dispatch: sinon.spy()};
const wrapper = renderImpressionStats(props);
props.dispatch.resetHistory();
wrapper.setProps(DEFAULT_PROPS);
assert.notCalled(props.dispatch);
});
it("should only send the latest impression on a visibility change", () => {
const listeners = new Set();
const props = {
dispatch: sinon.spy(),
document: {
visibilityState: "hidden",
addEventListener: (ev, cb) => listeners.add(cb),
removeEventListener: (ev, cb) => listeners.delete(cb),
},
};
const wrapper = renderImpressionStats(props);
// Update twice
wrapper.setProps({...props, ...{rows: [{id: 123}]}});
wrapper.setProps({...props, ...{rows: [{id: 2432}]}});
assert.notCalled(props.dispatch);
// Simulate listeners getting called
props.document.visibilityState = "visible";
listeners.forEach(l => l());
// Make sure we only sent the latest event
assert.calledOnce(props.dispatch);
const [action] = props.dispatch.firstCall.args;
assert.deepEqual(action.data.tiles, [{id: 2432}]);
});
});

View File

@ -0,0 +1,85 @@
import {_List as List, ListItem} from "content-src/components/DiscoveryStreamComponents/List/List";
import {GlobalOverrider} from "test/unit/utils";
import React from "react";
import {shallow} from "enzyme";
describe("<List> presentation component", () => {
const ValidRecommendations = [{a: 1}, {a: 2}];
const ValidListProps = {
DiscoveryStream: {
feeds: {
fakeFeedUrl: {
data: {
recommendations: ValidRecommendations,
},
},
},
},
feed: {
url: "fakeFeedUrl",
},
header: {
title: "fakeFeedTitle",
},
};
it("should return null if feed.data is falsy", () => {
const ListProps = {
DiscoveryStream: {feeds: {a: "stuff"}},
feed: {url: "a"},
};
const wrapper = shallow(<List {...ListProps} />);
assert.isNull(wrapper.getElement());
});
it("should return something containing a <ul> if props are valid", () => {
const wrapper = shallow(<List {...ValidListProps} />);
const list = wrapper.find("ul");
assert.ok(wrapper.exists());
assert.lengthOf(list, 1);
});
it("should return the right number of ListItems if props are valid", () => {
const wrapper = shallow(<List {...ValidListProps} />);
const listItem = wrapper.find(ListItem);
assert.lengthOf(listItem, ValidRecommendations.length);
});
});
describe("<ListItem> presentation component", () => {
const ValidListItemProps = {
url: "FAKE_URL",
title: "FAKE_TITLE",
domain: "example.com",
image_src: "FAKE_IMAGE_SRC",
};
let globals;
beforeEach(() => {
globals = new GlobalOverrider();
});
afterEach(() => {
globals.sandbox.restore();
});
it("should contain 'a.ds-list-item-link' with the props.url set", () => {
const wrapper = shallow(<ListItem {...ValidListItemProps} />);
const anchors = wrapper.find(
`a.ds-list-item-link[href="${ValidListItemProps.url}"]`);
assert.lengthOf(anchors, 1);
});
it("should include an img with a src of props.image_src", () => {
const wrapper = shallow(<ListItem {...ValidListItemProps} />);
const anchors = wrapper.find(`img[src="${ValidListItemProps.image_src}"]`);
assert.lengthOf(anchors, 1);
});
});

View File

@ -80,37 +80,41 @@ describe("<Search>", () => {
assert.ok(wrapper.exists());
assert.equal(wrapper.find(".search-handoff-button").length, 1);
});
it("should hand-off search when button is clicked with mouse", () => {
it("should focus search hand-off button when clicked with mouse", () => {
const dispatch = sinon.spy();
const wrapper = shallowWithIntl(<Search {...DEFAULT_PROPS} handoffEnabled={true} dispatch={dispatch} />);
wrapper.find(".search-handoff-button").simulate("click", {clientX: 101, clientY: 102});
assert.calledWith(dispatch, {
data: {hiddenFocus: true},
meta: {from: "ActivityStream:Content", skipLocal: true, to: "ActivityStream:Main"},
type: "HANDOFF_SEARCH_TO_AWESOMEBAR",
});
assert.calledWith(dispatch, {type: "FOCUS_SEARCH"});
wrapper.instance()._searchHandoffButton = {focus: sinon.spy()};
wrapper.find(".search-handoff-button").simulate("click", {clientX: 101, clientY: 102, preventDefault: () => {}});
assert.calledOnce(wrapper.instance()._searchHandoffButton.focus);
});
it("should hand-off search when button is clicked with keyboard", () => {
const dispatch = sinon.spy();
const wrapper = shallowWithIntl(<Search {...DEFAULT_PROPS} handoffEnabled={true} dispatch={dispatch} />);
wrapper.find(".search-handoff-button").simulate("click", {clientX: 0, clientY: 0});
wrapper.find(".search-handoff-button").simulate("click", {clientX: 0, clientY: 0, preventDefault: () => {}});
assert.calledTwice(dispatch);
assert.calledWith(dispatch, {
data: {hiddenFocus: false},
data: {text: undefined},
meta: {from: "ActivityStream:Content", skipLocal: true, to: "ActivityStream:Main"},
type: "HANDOFF_SEARCH_TO_AWESOMEBAR",
});
assert.calledWith(dispatch, {type: "FOCUS_SEARCH"});
const [action] = dispatch.secondCall.args;
assert.isUserEventAction(action);
assert.propertyVal(action.data, "event", "SEARCH_HANDOFF");
});
it("should hand-off search when user types", () => {
const dispatch = sinon.spy();
const wrapper = shallowWithIntl(<Search {...DEFAULT_PROPS} handoffEnabled={true} dispatch={dispatch} />);
wrapper.find(".search-handoff-button").simulate("keydown", {key: "f"});
assert.calledThrice(dispatch);
assert.calledWith(dispatch, {
data: {text: "f"},
meta: {from: "ActivityStream:Content", skipLocal: true, to: "ActivityStream:Main"},
type: "HANDOFF_SEARCH_TO_AWESOMEBAR",
});
assert.calledWith(dispatch, {type: "HIDE_SEARCH"});
const [action] = dispatch.secondCall.args;
assert.isUserEventAction(action);
assert.propertyVal(action.data, "event", "SEARCH_HANDOFF");
});
it("should NOT hand-off search when user types with with ctrl pressed", () => {
const dispatch = sinon.spy();
@ -140,11 +144,16 @@ describe("<Search>", () => {
},
preventDefault: () => {},
});
assert.calledThrice(dispatch);
assert.calledWith(dispatch, {
data: {text: "some copied text"},
meta: {from: "ActivityStream:Content", skipLocal: true, to: "ActivityStream:Main"},
type: "HANDOFF_SEARCH_TO_AWESOMEBAR",
});
assert.calledWith(dispatch, {type: "HIDE_SEARCH"});
const [action] = dispatch.secondCall.args;
assert.isUserEventAction(action);
assert.propertyVal(action.data, "event", "SEARCH_HANDOFF");
});
});
});

View File

@ -0,0 +1,83 @@
import {combineReducers, createStore} from "redux";
import {actionTypes as at} from "common/Actions.jsm";
import {GlobalOverrider} from "test/unit/utils";
import {reducers} from "common/Reducers.jsm";
import {selectLayoutRender} from "content-src/lib/selectLayoutRender";
const FAKE_LAYOUT = [{width: 3, components: [{type: "foo", feed: {url: "foo.com"}}]}];
const FAKE_FEEDS = {"foo.com": {data: ["foo", "bar"]}};
describe("selectLayoutRender", () => {
let store;
let globals;
beforeEach(() => {
globals = new GlobalOverrider();
store = createStore(combineReducers(reducers));
});
afterEach(() => {
globals.restore();
});
it("should return an empty array given initial state", () => {
const result = selectLayoutRender(store.getState());
assert.deepEqual(result, []);
});
it("should add .data property from feeds to each compontent in .layout", () => {
store.dispatch({type: at.DISCOVERY_STREAM_LAYOUT_UPDATE, data: {layout: FAKE_LAYOUT}});
store.dispatch({type: at.DISCOVERY_STREAM_FEEDS_UPDATE, data: FAKE_FEEDS});
const result = selectLayoutRender(store.getState());
assert.lengthOf(result, 1);
assert.propertyVal(result[0], "width", 3);
assert.deepEqual(result[0].components[0], {type: "foo", feed: {url: "foo.com"}, data: ["foo", "bar"]});
});
it("should return layout property without data if feed isn't available", () => {
store.dispatch({type: at.DISCOVERY_STREAM_LAYOUT_UPDATE, data: {layout: FAKE_LAYOUT}});
store.dispatch({type: at.DISCOVERY_STREAM_FEEDS_UPDATE, data: {}});
const result = selectLayoutRender(store.getState());
assert.lengthOf(result, 1);
assert.propertyVal(result[0], "width", 3);
assert.deepEqual(result[0].components[0], FAKE_LAYOUT[0].components[0]);
});
it("should return spoc result for rolls below the probability", () => {
const fakeSpocConfig = {positions: [{index: 0}, {index: 1}], probability: 0.5};
const fakeLayout = [{width: 3, components: [{type: "foo", feed: {url: "foo.com"}, spocs: fakeSpocConfig}]}];
const fakeSpocsData = {lastUpdated: 0, spocs: {spocs: ["foo", "bar"]}};
store.dispatch({type: at.DISCOVERY_STREAM_LAYOUT_UPDATE, data: {layout: fakeLayout}});
store.dispatch({type: at.DISCOVERY_STREAM_FEEDS_UPDATE, data: FAKE_FEEDS});
store.dispatch({type: at.DISCOVERY_STREAM_SPOCS_UPDATE, data: fakeSpocsData});
globals.sandbox.stub(global.Math, "random").returns(0.1);
const result = selectLayoutRender(store.getState());
assert.lengthOf(result, 1);
assert.deepEqual(result[0].components[0].spocs.positions[0], {index: 0, result: "foo"});
assert.deepEqual(result[0].components[0].spocs.positions[1], {index: 1, result: "bar"});
});
it("should not return spoc result for rolls above the probability", () => {
const fakeSpocConfig = {positions: [{index: 0}, {index: 1}], probability: 0.5};
const fakeLayout = [{width: 3, components: [{type: "foo", feed: {url: "foo.com"}, spocs: fakeSpocConfig}]}];
const fakeSpocsData = {lastUpdated: 0, spocs: {spocs: ["foo", "bar"]}};
store.dispatch({type: at.DISCOVERY_STREAM_LAYOUT_UPDATE, data: {layout: fakeLayout}});
store.dispatch({type: at.DISCOVERY_STREAM_FEEDS_UPDATE, data: FAKE_FEEDS});
store.dispatch({type: at.DISCOVERY_STREAM_SPOCS_UPDATE, data: fakeSpocsData});
globals.sandbox.stub(global.Math, "random").returns(0.6);
const result = selectLayoutRender(store.getState());
assert.lengthOf(result, 1);
assert.deepEqual(result[0].components[0].spocs.positions[0], {index: 0});
assert.deepEqual(result[0].components[0].spocs.positions[1], {index: 1});
});
});

View File

@ -309,7 +309,7 @@ describe("PlacesFeed", () => {
it("should call handoffSearchToAwesomebar on HANDOFF_SEARCH_TO_AWESOMEBAR", () => {
const action = {
type: at.HANDOFF_SEARCH_TO_AWESOMEBAR,
data: {hiddenFocus: false},
data: {text: "f"},
meta: {fromTarget: {}},
_target: {browser: {ownerGlobal: {gURLBar: {focus: () => {}}}}},
};
@ -336,77 +336,14 @@ describe("PlacesFeed", () => {
};
listeners = {};
});
it("should properly handle hiddenFocus=false", () => {
it("should properly handle normal focus (no text passed in)", () => {
feed.handoffSearchToAwesomebar({
_target: {browser: {ownerGlobal: {gURLBar: fakeUrlBar}}},
data: {hiddenFocus: false},
data: {},
meta: {fromTarget: {}},
});
assert.calledOnce(fakeUrlBar.focus);
assert.notCalled(fakeUrlBar.hiddenFocus);
assert.calledOnce(feed.store.dispatch);
assert.calledWith(feed.store.dispatch, {
meta: {
from: "ActivityStream:Main",
skipMain: true,
to: "ActivityStream:Content",
toTarget: {},
},
type: "SHOW_SEARCH",
});
});
it("should properly handle hiddenFocus=true", () => {
feed.handoffSearchToAwesomebar({
_target: {browser: {ownerGlobal: {gURLBar: fakeUrlBar}}},
data: {hiddenFocus: true},
meta: {fromTarget: {}},
});
assert.calledOnce(fakeUrlBar.hiddenFocus);
assert.notCalled(fakeUrlBar.focus);
assert.notCalled(feed.store.dispatch);
// Now call keydown listener with "Ctrl".
feed.store.dispatch.resetHistory();
listeners.keydown({key: "Ctrl"});
assert.notCalled(fakeUrlBar.removeHiddenFocus);
assert.notCalled(feed.store.dispatch);
// Now call keydown listener with "Ctrl+f".
feed.store.dispatch.resetHistory();
listeners.keydown({key: "f", ctrlKey: true});
assert.notCalled(fakeUrlBar.removeHiddenFocus);
assert.notCalled(feed.store.dispatch);
// Now call keydown listener with "f".
feed.store.dispatch.resetHistory();
listeners.keydown({key: "f"});
assert.calledOnce(fakeUrlBar.removeHiddenFocus);
assert.calledOnce(feed.store.dispatch);
assert.calledWith(feed.store.dispatch, {
meta: {
from: "ActivityStream:Main",
skipMain: true,
to: "ActivityStream:Content",
toTarget: {},
},
type: "HIDE_SEARCH",
});
// And then call blur listener.
fakeUrlBar.removeHiddenFocus.resetHistory();
feed.store.dispatch.resetHistory();
listeners.blur();
assert.calledOnce(fakeUrlBar.removeHiddenFocus);
assert.calledOnce(feed.store.dispatch);
assert.calledWith(feed.store.dispatch, {
meta: {
from: "ActivityStream:Main",
skipMain: true,
to: "ActivityStream:Content",
toTarget: {},
},
type: "SHOW_SEARCH",
});
});
it("should properly handle text data passed in", () => {
feed.handoffSearchToAwesomebar({
@ -416,8 +353,10 @@ describe("PlacesFeed", () => {
});
assert.calledOnce(fakeUrlBar.search);
assert.calledWith(fakeUrlBar.search, "f");
assert.notCalled(fakeUrlBar.hiddenFocus);
assert.notCalled(fakeUrlBar.focus);
// Now call blur listener.
listeners.blur();
assert.calledOnce(feed.store.dispatch);
assert.calledWith(feed.store.dispatch, {
meta: {
@ -426,7 +365,30 @@ describe("PlacesFeed", () => {
to: "ActivityStream:Content",
toTarget: {},
},
type: "HIDE_SEARCH",
type: "SHOW_SEARCH",
});
});
it("should SHOW_SEARCH on ESC keydown", () => {
feed.handoffSearchToAwesomebar({
_target: {browser: {ownerGlobal: {gURLBar: fakeUrlBar}}},
data: {text: "f"},
meta: {fromTarget: {}},
});
assert.calledOnce(fakeUrlBar.search);
assert.calledWith(fakeUrlBar.search, "f");
assert.notCalled(fakeUrlBar.focus);
// Now call ESC keydown.
listeners.keydown({key: "Escape"});
assert.calledOnce(feed.store.dispatch);
assert.calledWith(feed.store.dispatch, {
meta: {
from: "ActivityStream:Main",
skipMain: true,
to: "ActivityStream:Content",
toTarget: {},
},
type: "SHOW_SEARCH",
});
});
});

View File

@ -110,7 +110,6 @@ endif
# and Mac requires some extra care due to cross-compilation.
MOZ_PACKAGER_MINIFY=1
include $(topsrcdir)/toolkit/mozapps/installer/signing.mk
include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
ifeq (bundle, $(MOZ_FS_LAYOUT))

View File

@ -62,7 +62,7 @@ $(CONFIG_DIR)/setup.exe::
--convert-utf8-utf16le \
$(srcdir)/nsis/extensionsLocale.nsh $(CONFIG_DIR)/extensionsLocale.nsh
GARBARGE_DIRS += instgen
GARBAGE_DIRS += instgen
include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/makensis.mk

View File

@ -10,61 +10,42 @@ def moz_jemalloc4(value):
die('MOZ_JEMALLOC4 is deprecated')
option('--enable-jemalloc', env='MOZ_MEMORY',
help='Replace memory allocator with jemalloc')
@depends(target)
def jemalloc_default(target):
return target.kernel in ('Darwin', 'Linux', 'WINNT')
@depends('--enable-jemalloc', target)
def jemalloc(value, target):
if value.origin != 'default':
return bool(value) or None
if target.kernel in ('Darwin', 'Linux', 'WINNT'):
return True
js_option('--enable-jemalloc', env='MOZ_MEMORY', default=jemalloc_default,
help='{Replace|Do not replace} memory allocator with jemalloc')
set_config('MOZ_MEMORY', jemalloc)
set_define('MOZ_MEMORY', jemalloc)
add_old_configure_assignment('MOZ_MEMORY', jemalloc)
set_config('MOZ_MEMORY', True, when='--enable-jemalloc')
set_define('MOZ_MEMORY', True, when='--enable-jemalloc')
add_old_configure_assignment('MOZ_MEMORY', True, when='--enable-jemalloc')
# Because --enable-jemalloc doesn't use a default because of the dependency
# on the target, we can't use a js_option for it to propagate to js/src
# through the old-configure.
@depends(jemalloc)
def jemalloc_for_old_configure(jemalloc):
return '--%s-jemalloc' % ('enable' if jemalloc else 'disable')
add_old_configure_arg(jemalloc_for_old_configure)
option('--enable-replace-malloc',
help='Enable ability to dynamically replace the malloc implementation')
@depends('--enable-replace-malloc', jemalloc, milestone, build_project)
def replace_malloc(value, jemalloc, milestone, build_project):
# Enable on central for the debugging opportunities it adds.
if value and not jemalloc:
die('--enable-replace-malloc requires --enable-jemalloc')
if value.origin != 'default':
return bool(value) or None
@depends(milestone, build_project)
def replace_malloc_default(milestone, build_project):
if build_project == 'memory':
return True
if milestone.is_nightly and jemalloc and build_project != 'js':
if milestone.is_nightly and build_project != 'js':
return True
set_config('MOZ_REPLACE_MALLOC', replace_malloc)
set_define('MOZ_REPLACE_MALLOC', replace_malloc)
js_option('--enable-replace-malloc', default=replace_malloc_default,
when='--enable-jemalloc',
help='{Enable|Disable} ability to dynamically replace the malloc implementation')
@depends(replace_malloc, build_project)
def replace_malloc_static(replace_malloc, build_project):
set_config('MOZ_REPLACE_MALLOC', True, when='--enable-replace-malloc')
set_define('MOZ_REPLACE_MALLOC', True, when='--enable-replace-malloc')
@depends(build_project, when='--enable-replace-malloc')
def replace_malloc_static(build_project):
# Default to statically linking replace-malloc libraries that can be
# statically linked, except when building with --enable-project=memory.
if replace_malloc and build_project != 'memory':
if build_project != 'memory':
return True

View File

@ -309,3 +309,19 @@ def win64_cargo_linker_config(linker, env):
set_config('WIN64_CARGO_LINKER_CONFIG', win64_cargo_linker_config)
@depends(target, c_compiler, rustc)
@imports('os')
def rustc_natvis_ldflags(target, compiler_info, rustc):
if target.kernel == 'WINNT' and compiler_info.type in ('msvc', 'clang-cl'):
sysroot = check_cmd_output(rustc, '--print', 'sysroot').strip()
etc = os.path.join(sysroot, 'lib/rustlib/etc')
ldflags = []
for f in os.listdir(etc):
if f.endswith('.natvis'):
ldflags.append('-NATVIS:' + normsep(os.path.join(etc, f)))
return ldflags
set_config('RUSTC_NATVIS_LDFLAGS', rustc_natvis_ldflags)

View File

@ -79,9 +79,9 @@ BrowserElementWebNavigation.prototype = {
postData: postData ? readInputStreamToString(postData) : null,
headers: headers ? readInputStreamToString(headers) : null,
baseURI: baseURI ? baseURI.spec : null,
triggeringPrincipal: triggeringPrincipal
? Utils.serializePrincipal(triggeringPrincipal)
: Services.scriptSecurityManager.createNullPrincipal({}),
triggeringPrincipal: Utils.serializePrincipal(
triggeringPrincipal ||
Services.scriptSecurityManager.createNullPrincipal({})),
requestTime: telemetry.msSystemNow(),
});
},

View File

@ -115,11 +115,11 @@ const mozilla::Module::CIDEntry kDocShellCIDs[] = {
{ &kNS_ABOUT_REDIRECTOR_MODULE_CID, false, nullptr, nsAboutRedirector::Create },
{ &kNS_URI_LOADER_CID, false, nullptr, nsURILoaderConstructor },
{ &kNS_DOCUMENTLOADER_SERVICE_CID, false, nullptr, nsDocLoaderConstructor },
{ &kNS_EXTERNALHELPERAPPSERVICE_CID, false, nullptr, nsOSHelperAppServiceConstructor },
{ &kNS_EXTERNALHELPERAPPSERVICE_CID, false, nullptr, nsOSHelperAppServiceConstructor, mozilla::Module::ALLOW_IN_SOCKET_PROCESS },
{ &kNS_OSPERMISSIONREQUEST_CID, false, nullptr, nsOSPermissionRequestConstructor },
{ &kNS_CONTENTHANDLERSERVICE_CID, false, nullptr, ContentHandlerServiceConstructor,
mozilla::Module::CONTENT_PROCESS_ONLY },
{ &kNS_EXTERNALPROTOCOLHANDLER_CID, false, nullptr, nsExternalProtocolHandlerConstructor },
{ &kNS_EXTERNALPROTOCOLHANDLER_CID, false, nullptr, nsExternalProtocolHandlerConstructor, mozilla::Module::ALLOW_IN_SOCKET_PROCESS },
{ &kNS_PREFETCHSERVICE_CID, false, nullptr, nsPrefetchServiceConstructor },
{ &kNS_OFFLINECACHEUPDATESERVICE_CID, false, nullptr, nsOfflineCacheUpdateServiceConstructor },
{ &kNS_LOCALHANDLERAPP_CID, false, nullptr, PlatformLocalHandlerApp_tConstructor },
@ -171,9 +171,9 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
{ NS_DOCUMENTLOADER_SERVICE_CONTRACTID, &kNS_DOCUMENTLOADER_SERVICE_CID },
{ NS_HANDLERSERVICE_CONTRACTID, &kNS_CONTENTHANDLERSERVICE_CID, mozilla::Module::CONTENT_PROCESS_ONLY },
{ NS_EXTERNALHELPERAPPSERVICE_CONTRACTID, &kNS_EXTERNALHELPERAPPSERVICE_CID },
{ NS_EXTERNALPROTOCOLSERVICE_CONTRACTID, &kNS_EXTERNALHELPERAPPSERVICE_CID },
{ NS_EXTERNALPROTOCOLSERVICE_CONTRACTID, &kNS_EXTERNALHELPERAPPSERVICE_CID, mozilla::Module::ALLOW_IN_SOCKET_PROCESS },
{ NS_MIMESERVICE_CONTRACTID, &kNS_EXTERNALHELPERAPPSERVICE_CID },
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default", &kNS_EXTERNALPROTOCOLHANDLER_CID },
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default", &kNS_EXTERNALPROTOCOLHANDLER_CID, mozilla::Module::ALLOW_IN_SOCKET_PROCESS },
{ NS_PREFETCHSERVICE_CONTRACTID, &kNS_PREFETCHSERVICE_CID },
{ NS_OFFLINECACHEUPDATESERVICE_CONTRACTID, &kNS_OFFLINECACHEUPDATESERVICE_CID },
{ NS_LOCALHANDLERAPP_CONTRACTID, &kNS_LOCALHANDLERAPP_CID },
@ -195,6 +195,7 @@ static const mozilla::Module kDocShellModule = {mozilla::Module::kVersion,
nullptr,
nullptr,
Initialize,
Shutdown};
Shutdown,
mozilla::Module::ALLOW_IN_SOCKET_PROCESS};
NSMODULE_DEFN(docshell_provider) = &kDocShellModule;

View File

@ -1834,9 +1834,11 @@ waitForAllPaints(() => {
await ensureElementRemoval(div);
});
// Tests that transform animations are not able to run on the compositor due
// to layout restrictions (e.g. animations on a large size frame) doesn't
// flush layout at all.
// Tests that transform animations on a large size frame doesn't flush layout at all.
//
// With WebRender, the large size frame could run on compositor.
// Without WebRender, the large size frame is not able to run on the compositor
// due to layout restrictions.
add_task(async function flush_layout_for_transform_animations() {
// Set layout.animation.prerender.partial to disallow transform animations
// on large frames to be sent to the compositor.
@ -1850,11 +1852,17 @@ waitForAllPaints(() => {
easing: 'step-end' });
const FLUSH_LAYOUT = SpecialPowers.DOMWindowUtils.FLUSH_LAYOUT;
const isWebRender =
SpecialPowers.DOMWindowUtils.layerManagerType == 'WebRender';
ok(SpecialPowers.DOMWindowUtils.needsFlush(FLUSH_LAYOUT),
'Flush layout is needed for the appended div');
await waitForAnimationReadyToRestyle(animation);
ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
if (isWebRender) {
ok(SpecialPowers.wrap(animation).isRunningOnCompositor);
} else {
ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
}
ok(!SpecialPowers.DOMWindowUtils.needsFlush(FLUSH_LAYOUT),
'No further flush layout needed');

View File

@ -1323,7 +1323,6 @@ Document::Document(const char* aContentType)
mNotifiedPageForUseCounter(0),
mUserHasInteracted(false),
mHasUserInteractionTimerScheduled(false),
mUserGestureActivated(false),
mStackRefCnt(0),
mUpdateNestLevel(0),
mViewportType(Unknown),
@ -11717,13 +11716,14 @@ void Document::MaybeNotifyAutoplayBlocked() {
}
void Document::ClearUserGestureActivation() {
Document* doc = this;
while (doc) {
MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug,
("Reset user activation flag for document %p.", this));
doc->mUserGestureActivated = false;
doc = doc->GetSameTypeParentDocument();
if (!HasBeenUserGestureActivated()) {
return;
}
RefPtr<BrowsingContext> bc = GetBrowsingContext();
if (!bc) {
return;
}
bc->NotifyResetUserGestureActivation();
}
void Document::SetDocTreeHadAudibleMedia() {

View File

@ -4250,13 +4250,6 @@ class Document : public nsINode,
// timer is scheduled.
bool mHasUserInteractionTimerScheduled;
// Whether the user has interacted with the document via a restricted
// set of gestures which are likely to be interaction with the document,
// and not events that are fired as a byproduct of the user interacting
// with the browser (events for like scrolling the page, keyboard short
// cuts, etc).
bool mUserGestureActivated;
mozilla::TimeStamp mPageUnloadingEventTimeStamp;
RefPtr<mozilla::dom::DocGroup> mDocGroup;

View File

@ -3196,8 +3196,7 @@ mozilla::ipc::IPCResult ContentChild::RecvGetFilesResponse(
}
PURLClassifierChild* ContentChild::AllocPURLClassifierChild(
const Principal& aPrincipal, const bool& aUseTrackingProtection,
bool* aSuccess) {
const Principal& aPrincipal, bool* aSuccess) {
*aSuccess = true;
return new URLClassifierChild();
}

View File

@ -637,8 +637,7 @@ class ContentChild final : public PContentChild,
// PURLClassifierChild
virtual PURLClassifierChild* AllocPURLClassifierChild(
const Principal& aPrincipal, const bool& aUseTrackingProtection,
bool* aSuccess) override;
const Principal& aPrincipal, bool* aSuccess) override;
virtual bool DeallocPURLClassifierChild(PURLClassifierChild* aActor) override;
// PURLClassifierLocalChild

View File

@ -5341,8 +5341,7 @@ mozilla::ipc::IPCResult ContentParent::RecvRecordDiscardedData(
// PURLClassifierParent
PURLClassifierParent* ContentParent::AllocPURLClassifierParent(
const Principal& aPrincipal, const bool& aUseTrackingProtection,
bool* aSuccess) {
const Principal& aPrincipal, bool* aSuccess) {
MOZ_ASSERT(NS_IsMainThread());
*aSuccess = true;
@ -5351,8 +5350,7 @@ PURLClassifierParent* ContentParent::AllocPURLClassifierParent(
}
mozilla::ipc::IPCResult ContentParent::RecvPURLClassifierConstructor(
PURLClassifierParent* aActor, const Principal& aPrincipal,
const bool& aUseTrackingProtection, bool* aSuccess) {
PURLClassifierParent* aActor, const Principal& aPrincipal, bool* aSuccess) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aActor);
*aSuccess = false;
@ -5363,7 +5361,7 @@ mozilla::ipc::IPCResult ContentParent::RecvPURLClassifierConstructor(
actor->ClassificationFailed();
return IPC_OK();
}
return actor->StartClassify(principal, aUseTrackingProtection, aSuccess);
return actor->StartClassify(principal, aSuccess);
}
bool ContentParent::DeallocPURLClassifierParent(PURLClassifierParent* aActor) {

View File

@ -558,11 +558,10 @@ class ContentParent final : public PContentParent,
// PURLClassifierParent.
virtual PURLClassifierParent* AllocPURLClassifierParent(
const Principal& aPrincipal, const bool& aUseTrackingProtection,
bool* aSuccess) override;
const Principal& aPrincipal, bool* aSuccess) override;
virtual mozilla::ipc::IPCResult RecvPURLClassifierConstructor(
PURLClassifierParent* aActor, const Principal& aPrincipal,
const bool& aUseTrackingProtection, bool* aSuccess) override;
bool* aSuccess) override;
// PURLClassifierLocalParent.
virtual PURLClassifierLocalParent* AllocPURLClassifierLocalParent(

View File

@ -816,7 +816,7 @@ parent:
async CreateAudioIPCConnection() returns (FileDescriptor fd);
sync PURLClassifier(Principal principal, bool useTrackingProtection)
sync PURLClassifier(Principal principal)
returns (bool success);
async PURLClassifierLocal(URIParams uri, IPCURLClassifierFeature[] features);

View File

@ -18,7 +18,7 @@ using namespace mozilla::dom;
NS_IMPL_ISUPPORTS(URLClassifierParent, nsIURIClassifierCallback)
mozilla::ipc::IPCResult URLClassifierParent::StartClassify(
nsIPrincipal* aPrincipal, bool aUseTrackingProtection, bool* aSuccess) {
nsIPrincipal* aPrincipal, bool* aSuccess) {
*aSuccess = false;
nsresult rv = NS_OK;
// Note that in safe mode, the URL classifier service isn't available, so we
@ -26,8 +26,7 @@ mozilla::ipc::IPCResult URLClassifierParent::StartClassify(
nsCOMPtr<nsIURIClassifier> uriClassifier =
do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = uriClassifier->Classify(aPrincipal, nullptr, aUseTrackingProtection,
this, aSuccess);
rv = uriClassifier->Classify(aPrincipal, nullptr, this, aSuccess);
}
if (NS_FAILED(rv) || !*aSuccess) {
// We treat the case where we fail to classify and the case where the

View File

@ -24,7 +24,6 @@ class URLClassifierParent : public nsIURIClassifierCallback,
NS_DECL_THREADSAFE_ISUPPORTS
mozilla::ipc::IPCResult StartClassify(nsIPrincipal* aPrincipal,
bool aUseTrackingProtection,
bool* aSuccess);
// nsIURIClassifierCallback.

View File

@ -403,8 +403,8 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
wr::ToRoundedLayoutRect(aPipeline->mScBounds),
wr::WrStackingContextClip::None(), nullptr, &opacity,
aPipeline->mScTransform.IsIdentity() ? nullptr : &aPipeline->mScTransform,
wr::TransformStyle::Flat, nullptr, aPipeline->mMixBlendMode,
nsTArray<wr::FilterOp>(), true,
wr::TransformStyle::Flat, wr::ReferenceFrameKind::Transform,
aPipeline->mMixBlendMode, nsTArray<wr::FilterOp>(), true,
// This is fine to do unconditionally because we only push images here.
wr::RasterSpace::Screen());

View File

@ -27,7 +27,8 @@ StackingContextHelper::StackingContextHelper(
wr::DisplayListBuilder& aBuilder, const nsTArray<wr::FilterOp>& aFilters,
const LayoutDeviceRect& aBounds, const gfx::Matrix4x4* aBoundTransform,
const wr::WrAnimationProperty* aAnimation, const float* aOpacityPtr,
const gfx::Matrix4x4* aTransformPtr, const gfx::Matrix4x4* aPerspectivePtr,
const gfx::Matrix4x4* aTransformPtr,
wr::ReferenceFrameKind aReferenceFrameKind,
const gfx::CompositionOp& aMixBlendMode, bool aBackfaceVisible,
bool aIsPreserve3D,
const Maybe<nsDisplayTransform*>& aDeferredTransformItem,
@ -41,7 +42,8 @@ StackingContextHelper::StackingContextHelper(
// transformed items
gfx::Matrix transform2d;
if (aBoundTransform && aBoundTransform->CanDraw2D(&transform2d) &&
!aPerspectivePtr && !aParentSC.mIsPreserve3D) {
aReferenceFrameKind != wr::ReferenceFrameKind::Perspective &&
!aParentSC.mIsPreserve3D) {
mInheritedTransform = transform2d * aParentSC.mInheritedTransform;
int32_t apd = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
@ -70,7 +72,7 @@ StackingContextHelper::StackingContextHelper(
mReferenceFrameId = mBuilder->PushStackingContext(
wr::ToLayoutRect(aBounds), aClip, aAnimation, aOpacityPtr, aTransformPtr,
aIsPreserve3D ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat,
aPerspectivePtr, wr::ToMixBlendMode(aMixBlendMode), aFilters,
aReferenceFrameKind, wr::ToMixBlendMode(aMixBlendMode), aFilters,
aBackfaceVisible, rasterSpace);
if (mReferenceFrameId) {

View File

@ -37,7 +37,7 @@ class MOZ_RAII StackingContextHelper {
const wr::WrAnimationProperty* aAnimation = nullptr,
const float* aOpacityPtr = nullptr,
const gfx::Matrix4x4* aTransformPtr = nullptr,
const gfx::Matrix4x4* aPerspectivePtr = nullptr,
const wr::ReferenceFrameKind = wr::ReferenceFrameKind::Transform,
const gfx::CompositionOp& aMixBlendMode = gfx::CompositionOp::OP_OVER,
bool aBackfaceVisible = true, bool aIsPreserve3D = false,
const Maybe<nsDisplayTransform*>& aDeferredTransformItem = Nothing(),

View File

@ -685,12 +685,12 @@ static void FinishAsyncMemoryReport() {
// clang-format off
// (For some reason, clang-format gets the second macro right, but totally mangles the first).
#define REPORT_INTERNER(id) \
helper.Report(aReport.interning.id##_interner, \
helper.Report(aReport.interning.interners.id, \
"interning/" #id "/interners");
// clang-format on
#define REPORT_DATA_STORE(id) \
helper.Report(aReport.interning.id##_data_store, \
helper.Report(aReport.interning.data_stores.id, \
"interning/" #id "/data-stores");
NS_IMPL_ISUPPORTS(WebRenderMemoryReporter, nsIMemoryReporter)

View File

@ -39,7 +39,7 @@ static StaticRefPtr<RenderThread> sRenderThread;
RenderThread::RenderThread(base::Thread* aThread)
: mThread(aThread),
mFrameCountMapLock("RenderThread.mFrameCountMapLock"),
mWindowInfos("RenderThread.mWindowInfos"),
mRenderTextureMapLock("RenderThread.mRenderTextureMapLock"),
mHasShutdown(false),
mHandlingDeviceReset(false) {}
@ -180,8 +180,7 @@ void RenderThread::AddRenderer(wr::WindowId aWindowId,
mRenderers[aWindowId] = std::move(aRenderer);
MutexAutoLock lock(mFrameCountMapLock);
mWindowInfos.emplace(AsUint64(aWindowId), new WindowInfo());
mWindowInfos.Lock()->emplace(AsUint64(aWindowId), new WindowInfo());
}
void RenderThread::RemoveRenderer(wr::WindowId aWindowId) {
@ -197,11 +196,11 @@ void RenderThread::RemoveRenderer(wr::WindowId aWindowId) {
mHandlingDeviceReset = false;
}
MutexAutoLock lock(mFrameCountMapLock);
auto it = mWindowInfos.find(AsUint64(aWindowId));
MOZ_ASSERT(it != mWindowInfos.end());
auto windows = mWindowInfos.Lock();
auto it = windows->find(AsUint64(aWindowId));
MOZ_ASSERT(it != windows->end());
WindowInfo* toDelete = it->second;
mWindowInfos.erase(it);
windows->erase(it);
delete toDelete;
}
@ -248,9 +247,9 @@ void RenderThread::HandleFrame(wr::WindowId aWindowId, bool aRender) {
bool hadSlowFrame;
{ // scope lock
MutexAutoLock lock(mFrameCountMapLock);
auto it = mWindowInfos.find(AsUint64(aWindowId));
MOZ_ASSERT(it != mWindowInfos.end());
auto windows = mWindowInfos.Lock();
auto it = windows->find(AsUint64(aWindowId));
MOZ_ASSERT(it != windows->end());
WindowInfo* info = it->second;
MOZ_ASSERT(info->mPendingCount > 0);
startTime = info->mStartTimes.front();
@ -432,9 +431,9 @@ bool RenderThread::TooManyPendingFrames(wr::WindowId aWindowId) {
// Too many pending frames if pending frames exit more than maxFrameCount
// or if RenderBackend is still processing a frame.
MutexAutoLock lock(mFrameCountMapLock);
auto it = mWindowInfos.find(AsUint64(aWindowId));
if (it == mWindowInfos.end()) {
auto windows = mWindowInfos.Lock();
auto it = windows->find(AsUint64(aWindowId));
if (it == windows->end()) {
MOZ_ASSERT(false);
return true;
}
@ -448,9 +447,9 @@ bool RenderThread::TooManyPendingFrames(wr::WindowId aWindowId) {
}
bool RenderThread::IsDestroyed(wr::WindowId aWindowId) {
MutexAutoLock lock(mFrameCountMapLock);
auto it = mWindowInfos.find(AsUint64(aWindowId));
if (it == mWindowInfos.end()) {
auto windows = mWindowInfos.Lock();
auto it = windows->find(AsUint64(aWindowId));
if (it == windows->end()) {
return true;
}
@ -458,9 +457,9 @@ bool RenderThread::IsDestroyed(wr::WindowId aWindowId) {
}
void RenderThread::SetDestroyed(wr::WindowId aWindowId) {
MutexAutoLock lock(mFrameCountMapLock);
auto it = mWindowInfos.find(AsUint64(aWindowId));
if (it == mWindowInfos.end()) {
auto windows = mWindowInfos.Lock();
auto it = windows->find(AsUint64(aWindowId));
if (it == windows->end()) {
MOZ_ASSERT(false);
return;
}
@ -470,9 +469,9 @@ void RenderThread::SetDestroyed(wr::WindowId aWindowId) {
void RenderThread::IncPendingFrameCount(wr::WindowId aWindowId,
const VsyncId& aStartId,
const TimeStamp& aStartTime) {
MutexAutoLock lock(mFrameCountMapLock);
auto it = mWindowInfos.find(AsUint64(aWindowId));
if (it == mWindowInfos.end()) {
auto windows = mWindowInfos.Lock();
auto it = windows->find(AsUint64(aWindowId));
if (it == windows->end()) {
MOZ_ASSERT(false);
return;
}
@ -482,9 +481,9 @@ void RenderThread::IncPendingFrameCount(wr::WindowId aWindowId,
}
void RenderThread::DecPendingFrameCount(wr::WindowId aWindowId) {
MutexAutoLock lock(mFrameCountMapLock);
auto it = mWindowInfos.find(AsUint64(aWindowId));
if (it == mWindowInfos.end()) {
auto windows = mWindowInfos.Lock();
auto it = windows->find(AsUint64(aWindowId));
if (it == windows->end()) {
MOZ_ASSERT(false);
return;
}
@ -506,9 +505,9 @@ void RenderThread::DecPendingFrameCount(wr::WindowId aWindowId) {
}
void RenderThread::IncRenderingFrameCount(wr::WindowId aWindowId) {
MutexAutoLock lock(mFrameCountMapLock);
auto it = mWindowInfos.find(AsUint64(aWindowId));
if (it == mWindowInfos.end()) {
auto windows = mWindowInfos.Lock();
auto it = windows->find(AsUint64(aWindowId));
if (it == windows->end()) {
MOZ_ASSERT(false);
return;
}
@ -516,9 +515,9 @@ void RenderThread::IncRenderingFrameCount(wr::WindowId aWindowId) {
}
void RenderThread::FrameRenderingComplete(wr::WindowId aWindowId) {
MutexAutoLock lock(mFrameCountMapLock);
auto it = mWindowInfos.find(AsUint64(aWindowId));
if (it == mWindowInfos.end()) {
auto windows = mWindowInfos.Lock();
auto it = windows->find(AsUint64(aWindowId));
if (it == windows->end()) {
MOZ_ASSERT(false);
return;
}
@ -541,9 +540,9 @@ void RenderThread::FrameRenderingComplete(wr::WindowId aWindowId) {
}
void RenderThread::NotifySlowFrame(wr::WindowId aWindowId) {
MutexAutoLock lock(mFrameCountMapLock);
auto it = mWindowInfos.find(AsUint64(aWindowId));
if (it == mWindowInfos.end()) {
auto windows = mWindowInfos.Lock();
auto it = windows->find(AsUint64(aWindowId));
if (it == windows->end()) {
MOZ_ASSERT(false);
return;
}

View File

@ -15,7 +15,7 @@
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/MozPromise.h"
#include "mozilla/Mutex.h"
#include "mozilla/DataMutex.h"
#include "mozilla/webrender/webrender_ffi.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/webrender/WebRenderTypes.h"
@ -272,8 +272,7 @@ class RenderThread final {
bool mHadSlowFrame = false;
};
Mutex mFrameCountMapLock;
std::unordered_map<uint64_t, WindowInfo*> mWindowInfos;
DataMutex<std::unordered_map<uint64_t, WindowInfo*>> mWindowInfos;
Mutex mRenderTextureMapLock;
std::unordered_map<uint64_t, RefPtr<RenderTextureHost>> mRenderTextures;

View File

@ -676,7 +676,7 @@ Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext(
const wr::LayoutRect& aBounds, const wr::WrStackingContextClip& aClip,
const WrAnimationProperty* aAnimation, const float* aOpacity,
const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
const gfx::Matrix4x4* aPerspective, const wr::MixBlendMode& aMixBlendMode,
const wr::ReferenceFrameKind aReferenceFrameKind, const wr::MixBlendMode& aMixBlendMode,
const nsTArray<wr::FilterOp>& aFilters, bool aIsBackfaceVisible,
const wr::RasterSpace& aRasterSpace) {
MOZ_ASSERT(mClipChainLeaf.isNothing(),
@ -687,20 +687,13 @@ Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext(
matrix = ToLayoutTransform(*aTransform);
}
const wr::LayoutTransform* maybeTransform = aTransform ? &matrix : nullptr;
wr::LayoutTransform perspective;
if (aPerspective) {
perspective = ToLayoutTransform(*aPerspective);
}
const wr::LayoutTransform* maybePerspective =
aPerspective ? &perspective : nullptr;
WRDL_LOG("PushStackingContext b=%s t=%s\n", mWrState,
Stringify(aBounds).c_str(),
aTransform ? Stringify(*aTransform).c_str() : "none");
auto spatialId = wr_dp_push_stacking_context(
mWrState, aBounds, mCurrentSpaceAndClipChain.space, &aClip, aAnimation,
aOpacity, maybeTransform, aTransformStyle, maybePerspective,
aOpacity, maybeTransform, aTransformStyle, aReferenceFrameKind,
aMixBlendMode, aFilters.Elements(), aFilters.Length(), aIsBackfaceVisible,
aRasterSpace);

View File

@ -333,7 +333,7 @@ class DisplayListBuilder {
const wr::LayoutRect& aBounds, const wr::WrStackingContextClip& aClip,
const wr::WrAnimationProperty* aAnimation, const float* aOpacity,
const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
const gfx::Matrix4x4* aPerspective, const wr::MixBlendMode& aMixBlendMode,
const wr::ReferenceFrameKind, const wr::MixBlendMode& aMixBlendMode,
const nsTArray<wr::FilterOp>& aFilters, bool aIsBackfaceVisible,
const wr::RasterSpace& aRasterSpace);
void PopStackingContext(bool aIsReferenceFrame);

View File

@ -1904,7 +1904,7 @@ pub extern "C" fn wr_dp_push_stacking_context(
opacity: *const f32,
transform: *const LayoutTransform,
transform_style: TransformStyle,
perspective: *const LayoutTransform,
reference_frame_kind: ReferenceFrameKind,
mix_blend_mode: MixBlendMode,
filters: *const FilterOp,
filter_count: usize,
@ -1955,28 +1955,21 @@ pub extern "C" fn wr_dp_push_stacking_context(
}
}
let perspective_ref = unsafe { perspective.as_ref() };
let perspective = match perspective_ref {
Some(perspective) => Some(perspective.clone()),
None => None,
};
let mut wr_spatial_id = spatial_id.to_webrender(state.pipeline_id);
let wr_clip_id = clip.to_webrender(state.pipeline_id);
let is_reference_frame = transform_binding.is_some() || perspective.is_some();
// Note: 0 has special meaning in WR land, standing for ROOT_REFERENCE_FRAME.
// However, it is never returned by `push_reference_frame`, and we need to return
// an option here across FFI, so we take that 0 value for the None semantics.
// This is resolved into proper `Maybe<WrSpatialId>` inside `WebRenderAPI::PushStackingContext`.
let mut result = WrSpatialId { id: 0 };
if is_reference_frame {
if let Some(transform_binding) = transform_binding {
wr_spatial_id = state.frame_builder.dl_builder.push_reference_frame(
&bounds,
wr_spatial_id,
transform_style,
transform_binding,
perspective,
reference_frame_kind,
);
bounds.origin = LayoutPoint::zero();

View File

@ -54,15 +54,13 @@ namespace mozilla {
namespace wr {
// Because this struct is macro-generated on the Rust side, cbindgen can't see
// it for some reason. Work around that by re-declaring it here.
#define DECLARE_MEMBERS(id) \
uintptr_t id##_interner; \
uintptr_t id##_data_store;
struct InterningMemoryReport {
WEBRENDER_FOR_EACH_INTERNER(DECLARE_MEMBERS)
// it. Work around that by re-declaring it here.
#define DECLARE_MEMBER(id) uintptr_t id;
struct InternerSubReport {
WEBRENDER_FOR_EACH_INTERNER(DECLARE_MEMBER)
};
#undef DECLARE_MEMBERS
#undef DECLARE_MEMBER
struct FontInstanceFlags {
uint32_t bits;

View File

@ -59,8 +59,8 @@ impl App {
&LayoutRect::new(bounds.origin, LayoutSize::zero()),
SpatialId::root_scroll_node(pipeline_id),
TransformStyle::Flat,
Some(PropertyBinding::Binding(property_key, LayoutTransform::identity())),
None,
PropertyBinding::Binding(property_key, LayoutTransform::identity()),
ReferenceFrameKind::Transform,
);
builder.push_stacking_context(

View File

@ -66,8 +66,8 @@ impl Example for App {
&sub_bounds,
space_and_clip.spatial_id,
TransformStyle::Flat,
Some(PropertyBinding::Binding(PropertyBindingKey::new(42), LayoutTransform::identity())),
None,
PropertyBinding::Binding(PropertyBindingKey::new(42), LayoutTransform::identity()),
ReferenceFrameKind::Transform,
);
// And this is for the root pipeline

View File

@ -19,7 +19,7 @@ use prim_store::{DeferredResolve, EdgeAaSegmentMask, PrimitiveInstanceKind, Prim
use prim_store::{VisibleGradientTile, PrimitiveInstance, PrimitiveOpacity, SegmentInstanceIndex};
use prim_store::{BrushSegment, ClipMaskKind, ClipTaskIndex};
use prim_store::image::ImageSource;
use render_backend::FrameResources;
use render_backend::DataStores;
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskTree, TileBlit};
use renderer::{BlendMode, ImageBufferKind, ShaderColorMode};
use renderer::BLOCKS_PER_UV_RECT;
@ -614,7 +614,7 @@ impl AlphaBatchBuilder {
render_tasks,
).unwrap_or(OPAQUE_TASK_ADDRESS);
let prim_common_data = &ctx.resources.as_common_data(&prim_instance);
let prim_common_data = &ctx.data_stores.as_common_data(&prim_instance);
let prim_rect = LayoutRect::new(
prim_instance.prim_origin,
prim_common_data.prim_size,
@ -622,7 +622,7 @@ impl AlphaBatchBuilder {
match prim_instance.kind {
PrimitiveInstanceKind::Clear { data_handle } => {
let prim_data = &ctx.resources.prim_data_store[data_handle];
let prim_data = &ctx.data_stores.prim[data_handle];
let prim_cache_address = gpu_cache.get_address(&prim_data.gpu_cache_handle);
// TODO(gw): We can abstract some of the common code below into
@ -667,7 +667,7 @@ impl AlphaBatchBuilder {
);
}
PrimitiveInstanceKind::NormalBorder { data_handle, ref cache_handles, .. } => {
let prim_data = &ctx.resources.normal_border_data_store[data_handle];
let prim_data = &ctx.data_stores.normal_border[data_handle];
let common_data = &prim_data.common;
let prim_cache_address = gpu_cache.get_address(&common_data.gpu_cache_handle);
let cache_handles = &ctx.scratch.border_cache_handles[*cache_handles];
@ -747,7 +747,7 @@ impl AlphaBatchBuilder {
// The GPU cache data is stored in the template and reused across
// frames and display lists.
let prim_data = &ctx.resources.text_run_data_store[data_handle];
let prim_data = &ctx.data_stores.text_run[data_handle];
let glyph_fetch_buffer = &mut self.glyph_fetch_buffer;
let alpha_batch_list = &mut self.batch_lists.last_mut().unwrap().alpha_batch_list;
let prim_cache_address = gpu_cache.get_address(&prim_data.gpu_cache_handle);
@ -854,7 +854,7 @@ impl AlphaBatchBuilder {
PrimitiveInstanceKind::LineDecoration { data_handle, ref cache_handle, .. } => {
// The GPU cache data is stored in the template and reused across
// frames and display lists.
let common_data = &ctx.resources.line_decoration_data_store[data_handle].common;
let common_data = &ctx.data_stores.line_decoration[data_handle].common;
let prim_cache_address = gpu_cache.get_address(&common_data.gpu_cache_handle);
let (batch_kind, textures, prim_user_data, segment_user_data) = match cache_handle {
@ -1488,7 +1488,7 @@ impl AlphaBatchBuilder {
}
}
PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
let prim_data = &ctx.resources.image_border_data_store[data_handle];
let prim_data = &ctx.data_stores.image_border[data_handle];
let common_data = &prim_data.common;
let border_data = &prim_data.kind;
@ -1557,7 +1557,7 @@ impl AlphaBatchBuilder {
);
}
PrimitiveInstanceKind::Rectangle { data_handle, segment_instance_index, opacity_binding_index, .. } => {
let prim_data = &ctx.resources.prim_data_store[data_handle];
let prim_data = &ctx.data_stores.prim[data_handle];
let specified_blend_mode = BlendMode::PremultipliedAlpha;
let opacity_binding = ctx.prim_store.get_opacity_binding(opacity_binding_index);
@ -1620,7 +1620,7 @@ impl AlphaBatchBuilder {
);
}
PrimitiveInstanceKind::YuvImage { data_handle, segment_instance_index, .. } => {
let yuv_image_data = &ctx.resources.yuv_image_data_store[data_handle].kind;
let yuv_image_data = &ctx.data_stores.yuv_image[data_handle].kind;
let mut textures = BatchTextures::no_texture();
let mut uv_rect_addresses = [0; 3];
@ -1728,8 +1728,8 @@ impl AlphaBatchBuilder {
);
}
PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
let image_data = &ctx.resources.image_data_store[data_handle].kind;
let common_data = &ctx.resources.image_data_store[data_handle].common;
let image_data = &ctx.data_stores.image[data_handle].kind;
let common_data = &ctx.data_stores.image[data_handle].common;
let image_instance = &ctx.prim_store.images[image_instance_index];
let opacity_binding = ctx.prim_store.get_opacity_binding(image_instance.opacity_binding_index);
let specified_blend_mode = match image_data.alpha_type {
@ -1867,7 +1867,7 @@ impl AlphaBatchBuilder {
}
}
PrimitiveInstanceKind::LinearGradient { data_handle, ref visible_tiles_range, .. } => {
let prim_data = &ctx.resources.linear_grad_data_store[data_handle];
let prim_data = &ctx.data_stores.linear_grad[data_handle];
let specified_blend_mode = BlendMode::PremultipliedAlpha;
let mut prim_header = PrimitiveHeader {
@ -1948,7 +1948,7 @@ impl AlphaBatchBuilder {
}
}
PrimitiveInstanceKind::RadialGradient { data_handle, ref visible_tiles_range, .. } => {
let prim_data = &ctx.resources.radial_grad_data_store[data_handle];
let prim_data = &ctx.data_stores.radial_grad[data_handle];
let specified_blend_mode = BlendMode::PremultipliedAlpha;
let mut prim_header = PrimitiveHeader {
@ -2359,17 +2359,17 @@ impl BrushBatchParameters {
impl PrimitiveInstance {
pub fn is_cacheable(
&self,
resources: &FrameResources,
data_stores: &DataStores,
resource_cache: &ResourceCache,
) -> bool {
let image_key = match self.kind {
PrimitiveInstanceKind::Image { data_handle, .. } => {
let image_data = &resources.image_data_store[data_handle].kind;
let image_data = &data_stores.image[data_handle].kind;
image_data.key
}
PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
let yuv_image_data =
&resources.yuv_image_data_store[data_handle].kind;
&data_stores.yuv_image[data_handle].kind;
yuv_image_data.yuv_key[0]
}
PrimitiveInstanceKind::Picture { .. } |

View File

@ -104,15 +104,9 @@ use util::{extract_inner_rect_safe, project_rect, ScaleOffset};
*/
// Type definitions for interning clip nodes.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
pub struct ClipDataMarker;
pub type ClipDataStore = intern::DataStore<ClipItemKey, ClipNode, ClipDataMarker>;
pub type ClipDataHandle = intern::Handle<ClipDataMarker>;
pub type ClipDataUpdateList = intern::UpdateList<ClipItemKey>;
pub type ClipDataInterner = intern::Interner<ClipItemKey, (), ClipDataMarker>;
pub use intern_types::clip::Store as ClipDataStore;
use intern_types::clip::Handle as ClipDataHandle;
// Result of comparing a clip node instance against a local rect.
#[derive(Debug)]
@ -1034,7 +1028,7 @@ impl ClipItem {
// reduce the size of a primitive region. This is typically
// used to eliminate redundant clips, and reduce the size of
// any clip mask that eventually gets drawn.
fn get_local_clip_rect(&self, local_pos: LayoutPoint) -> Option<LayoutRect> {
pub fn get_local_clip_rect(&self, local_pos: LayoutPoint) -> Option<LayoutRect> {
let size = match *self {
ClipItem::Rectangle(size, ClipMode::Clip) => Some(size),
ClipItem::Rectangle(_, ClipMode::ClipOut) => None,

View File

@ -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 http://mozilla.org/MPL/2.0/. */
use api::{ExternalScrollId, LayoutPoint, LayoutRect, LayoutVector2D};
use api::{ExternalScrollId, LayoutPoint, LayoutRect, LayoutVector2D, ReferenceFrameKind};
use api::{PipelineId, ScrollClamping, ScrollNodeState, ScrollLocation, ScrollSensitivity};
use api::{LayoutSize, LayoutTransform, PropertyBinding, TransformStyle, WorldPoint};
use gpu_types::TransformPalette;
@ -352,8 +352,8 @@ impl ClipScrollTree {
&mut self,
parent_index: Option<SpatialNodeIndex>,
transform_style: TransformStyle,
source_transform: Option<PropertyBinding<LayoutTransform>>,
source_perspective: Option<LayoutTransform>,
source_transform: PropertyBinding<LayoutTransform>,
kind: ReferenceFrameKind,
origin_in_parent_reference_frame: LayoutVector2D,
pipeline_id: PipelineId,
) -> SpatialNodeIndex {
@ -361,7 +361,7 @@ impl ClipScrollTree {
parent_index,
transform_style,
source_transform,
source_perspective,
kind,
origin_in_parent_reference_frame,
pipeline_id,
);
@ -456,10 +456,6 @@ impl ClipScrollTree {
match node.node_type {
SpatialNodeType::ReferenceFrame(ref info) => {
if !info.source_perspective.is_identity() {
return false;
}
match info.source_transform {
PropertyBinding::Value(transform) => {
if transform != LayoutTransform::identity() {
@ -508,8 +504,8 @@ fn add_reference_frame(
cst.add_reference_frame(
parent,
TransformStyle::Preserve3D,
Some(PropertyBinding::Value(transform)),
None,
PropertyBinding::Value(transform),
ReferenceFrameKind::Perspective,
origin_in_parent_reference_frame,
PipelineId::dummy(),
)

View File

@ -9,7 +9,7 @@ use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, G
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayoutPoint, ColorDepth};
use api::{LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
use api::{LineOrientation, LineStyle, NinePatchBorderSource, PipelineId};
use api::{PropertyBinding, ReferenceFrame, ScrollFrameDisplayItem, ScrollSensitivity};
use api::{PropertyBinding, ReferenceFrame, ReferenceFrameKind, ScrollFrameDisplayItem, ScrollSensitivity};
use api::{Shadow, SpaceAndClipInfo, SpatialId, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
use api::{ClipMode, TransformStyle, YuvColorSpace, YuvData};
use app_units::Au;
@ -35,7 +35,7 @@ use prim_store::text_run::TextRun;
use render_backend::{DocumentView};
use resource_cache::{FontInstanceMap, ImageRequest};
use scene::{Scene, ScenePipeline, StackingContextHelpers};
use scene_builder::{DocumentResources, InternerMut};
use scene_builder::{InternerMut, Interners};
use spatial_node::{StickyFrameInfo, ScrollFrameKind, SpatialNodeType};
use std::{f32, mem, usize};
use std::collections::vec_deque::VecDeque;
@ -139,9 +139,8 @@ pub struct DisplayListFlattener<'a> {
/// order to determine the default font.
pub config: FrameBuilderConfig,
/// Reference to the document resources, which contains
/// shared (interned) data between display lists.
resources: &'a mut DocumentResources,
/// Reference to the set of data that is interned across display lists.
interners: &'a mut Interners,
/// The root picture index for this flattener. This is the picture
/// to start the culling phase from.
@ -157,7 +156,7 @@ impl<'a> DisplayListFlattener<'a> {
output_pipelines: &FastHashSet<PipelineId>,
frame_builder_config: &FrameBuilderConfig,
new_scene: &mut Scene,
resources: &mut DocumentResources,
interners: &mut Interners,
prim_store_stats: &PrimitiveStoreStats,
) -> FrameBuilder {
// We checked that the root pipeline is available on the render backend.
@ -181,7 +180,7 @@ impl<'a> DisplayListFlattener<'a> {
pipeline_clip_chain_stack: vec![ClipChainId::NONE],
prim_store: PrimitiveStore::new(&prim_store_stats),
clip_store: ClipStore::new(),
resources,
interners,
root_pic_index: PictureIndex(0),
};
@ -326,7 +325,7 @@ impl<'a> DisplayListFlattener<'a> {
let prim_list = PrimitiveList::new(
remaining_prims,
&self.resources,
&self.interners,
);
// Now, create a picture with tile caching enabled that will hold all
@ -339,8 +338,8 @@ impl<'a> DisplayListFlattener<'a> {
},
);
let pic_data_handle = self.resources
.picture_interner
let pic_data_handle = self.interners
.picture
.intern(&pic_key, || {
PrimitiveSceneData {
prim_size: LayoutSize::zero(),
@ -598,7 +597,7 @@ impl<'a> DisplayListFlattener<'a> {
pipeline_id,
reference_frame.transform_style,
reference_frame.transform,
reference_frame.perspective,
reference_frame.kind,
reference_frame_relative_offset + origin.to_vector(),
);
@ -690,8 +689,8 @@ impl<'a> DisplayListFlattener<'a> {
Some(spatial_node_index),
iframe_pipeline_id,
TransformStyle::Flat,
None,
None,
PropertyBinding::Value(LayoutTransform::identity()),
ReferenceFrameKind::Transform,
origin,
);
@ -1028,8 +1027,8 @@ impl<'a> DisplayListFlattener<'a> {
for (local_pos, item) in clip_items {
// Intern this clip item, and store the handle
// in the clip chain node.
let handle = self.resources
.clip_interner
let handle = self.interners
.clip
.intern(&item, || ());
clip_chain_id = self.clip_store.add_clip_chain_node(
@ -1059,12 +1058,12 @@ impl<'a> DisplayListFlattener<'a> {
where
P: Internable<InternData=PrimitiveSceneData>,
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
DocumentResources: InternerMut<P>,
Interners: InternerMut<P>,
{
// Build a primitive key.
let prim_key = prim.build_key(info);
let interner = self.resources.interner_mut();
let interner = self.interners.interner_mut();
let prim_data_handle =
interner
.intern(&prim_key, || {
@ -1134,7 +1133,7 @@ impl<'a> DisplayListFlattener<'a> {
where
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
DocumentResources: InternerMut<P>,
Interners: InternerMut<P>,
{
if prim.is_visible() {
let clip_chain_id = self.build_clip_chain(
@ -1161,7 +1160,7 @@ impl<'a> DisplayListFlattener<'a> {
where
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
DocumentResources: InternerMut<P>,
Interners: InternerMut<P>,
ShadowItem: From<PendingPrimitive<P>>
{
// If a shadow context is not active, then add the primitive
@ -1191,7 +1190,7 @@ impl<'a> DisplayListFlattener<'a> {
where
P: Internable<InternData = PrimitiveSceneData>,
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
DocumentResources: InternerMut<P>,
Interners: InternerMut<P>,
{
let prim_instance = self.create_primitive(
info,
@ -1238,7 +1237,7 @@ impl<'a> DisplayListFlattener<'a> {
// so that the relative order between them and our current SC is preserved.
let extra_instance = sc.cut_flat_item_sequence(
&mut self.prim_store,
&mut self.resources,
&mut self.interners,
&self.clip_store,
);
(sc.is_3d(), extra_instance)
@ -1386,7 +1385,7 @@ impl<'a> DisplayListFlattener<'a> {
stacking_context.requested_raster_space,
PrimitiveList::new(
stacking_context.primitives,
&self.resources,
&self.interners,
),
stacking_context.spatial_node_index,
max_clip,
@ -1405,7 +1404,7 @@ impl<'a> DisplayListFlattener<'a> {
stacking_context.is_backface_visible,
stacking_context.clip_chain_id,
stacking_context.spatial_node_index,
&mut self.resources,
&mut self.interners,
);
if cur_instance.is_chased() {
@ -1433,7 +1432,7 @@ impl<'a> DisplayListFlattener<'a> {
stacking_context.requested_raster_space,
PrimitiveList::new(
prims,
&self.resources,
&self.interners,
),
stacking_context.spatial_node_index,
max_clip,
@ -1448,7 +1447,7 @@ impl<'a> DisplayListFlattener<'a> {
stacking_context.is_backface_visible,
stacking_context.clip_chain_id,
stacking_context.spatial_node_index,
&mut self.resources,
&mut self.interners,
);
}
@ -1468,7 +1467,7 @@ impl<'a> DisplayListFlattener<'a> {
stacking_context.requested_raster_space,
PrimitiveList::new(
vec![cur_instance.clone()],
&self.resources,
&self.interners,
),
stacking_context.spatial_node_index,
max_clip,
@ -1484,7 +1483,7 @@ impl<'a> DisplayListFlattener<'a> {
stacking_context.is_backface_visible,
stacking_context.clip_chain_id,
stacking_context.spatial_node_index,
&mut self.resources,
&mut self.interners,
);
if cur_instance.is_chased() {
@ -1511,7 +1510,7 @@ impl<'a> DisplayListFlattener<'a> {
stacking_context.requested_raster_space,
PrimitiveList::new(
vec![cur_instance.clone()],
&self.resources,
&self.interners,
),
stacking_context.spatial_node_index,
max_clip,
@ -1527,7 +1526,7 @@ impl<'a> DisplayListFlattener<'a> {
stacking_context.is_backface_visible,
stacking_context.clip_chain_id,
stacking_context.spatial_node_index,
&mut self.resources,
&mut self.interners,
);
if cur_instance.is_chased() {
@ -1584,15 +1583,15 @@ impl<'a> DisplayListFlattener<'a> {
parent_index: Option<SpatialNodeIndex>,
pipeline_id: PipelineId,
transform_style: TransformStyle,
source_transform: Option<PropertyBinding<LayoutTransform>>,
source_perspective: Option<LayoutTransform>,
source_transform: PropertyBinding<LayoutTransform>,
kind: ReferenceFrameKind,
origin_in_parent_reference_frame: LayoutVector2D,
) -> SpatialNodeIndex {
let index = self.clip_scroll_tree.add_reference_frame(
parent_index,
transform_style,
source_transform,
source_perspective,
kind,
origin_in_parent_reference_frame,
pipeline_id,
);
@ -1619,8 +1618,8 @@ impl<'a> DisplayListFlattener<'a> {
None,
pipeline_id,
TransformStyle::Flat,
None,
None,
PropertyBinding::Value(LayoutTransform::identity()),
ReferenceFrameKind::Transform,
LayoutVector2D::zero(),
);
@ -1662,8 +1661,8 @@ impl<'a> DisplayListFlattener<'a> {
// Build the clip sources from the supplied region.
let handle = self
.resources
.clip_interner
.interners
.clip
.intern(&ClipItemKey::rectangle(clip_region.main.size, ClipMode::Clip), || ());
parent_clip_chain_index = self
@ -1678,8 +1677,8 @@ impl<'a> DisplayListFlattener<'a> {
if let Some(ref image_mask) = clip_region.image_mask {
let handle = self
.resources
.clip_interner
.interners
.clip
.intern(&ClipItemKey::image_mask(image_mask), || ());
parent_clip_chain_index = self
@ -1695,8 +1694,8 @@ impl<'a> DisplayListFlattener<'a> {
for region in clip_region.complex_clips {
let handle = self
.resources
.clip_interner
.interners
.clip
.intern(&ClipItemKey::rounded_rect(region.rect.size, region.radii, region.mode), || ());
parent_clip_chain_index = self
@ -1847,7 +1846,7 @@ impl<'a> DisplayListFlattener<'a> {
raster_space,
PrimitiveList::new(
prims,
&self.resources,
&self.interners,
),
pending_shadow.clip_and_scroll.spatial_node_index,
max_clip,
@ -1862,8 +1861,8 @@ impl<'a> DisplayListFlattener<'a> {
Picture { composite_mode_key },
);
let shadow_prim_data_handle = self.resources
.picture_interner
let shadow_prim_data_handle = self.interners
.picture
.intern(&shadow_pic_key, || {
PrimitiveSceneData {
prim_size: LayoutSize::zero(),
@ -1919,7 +1918,7 @@ impl<'a> DisplayListFlattener<'a> {
where
P: Internable<InternData=PrimitiveSceneData> + CreateShadow,
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
DocumentResources: InternerMut<P>,
Interners: InternerMut<P>,
{
// Offset the local rect and clip rect by the shadow offset.
let mut info = pending_primitive.info.clone();
@ -1944,7 +1943,7 @@ impl<'a> DisplayListFlattener<'a> {
where
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
DocumentResources: InternerMut<P>,
Interners: InternerMut<P>,
{
// For a normal primitive, if it has alpha > 0, then we add this
// as a normal primitive to the parent picture.
@ -2594,7 +2593,7 @@ impl FlattenedStackingContext {
pub fn cut_flat_item_sequence(
&mut self,
prim_store: &mut PrimitiveStore,
resources: &mut DocumentResources,
interners: &mut Interners,
clip_store: &ClipStore,
) -> Option<PrimitiveInstance> {
if !self.is_3d() || self.primitives.is_empty() {
@ -2619,7 +2618,7 @@ impl FlattenedStackingContext {
self.requested_raster_space,
PrimitiveList::new(
mem::replace(&mut self.primitives, Vec::new()),
resources,
interners,
),
self.spatial_node_index,
LayoutRect::max_rect(),
@ -2634,7 +2633,7 @@ impl FlattenedStackingContext {
self.is_backface_visible,
self.clip_chain_id,
self.spatial_node_index,
resources,
interners,
);
Some(prim_instance)
@ -2702,7 +2701,7 @@ fn create_prim_instance(
is_backface_visible: bool,
clip_chain_id: ClipChainId,
spatial_node_index: SpatialNodeIndex,
resources: &mut DocumentResources,
interners: &mut Interners,
) -> PrimitiveInstance {
let pic_key = PictureKey::new(
is_backface_visible,
@ -2710,8 +2709,8 @@ fn create_prim_instance(
Picture { composite_mode_key },
);
let data_handle = resources
.picture_interner
let data_handle = interners
.picture
.intern(&pic_key, || {
PrimitiveSceneData {
prim_size: LayoutSize::zero(),

View File

@ -18,7 +18,7 @@ use prim_store::{PrimitiveStore, SpaceMapper, PictureIndex, PrimitiveDebugId, Pr
#[cfg(feature = "replay")]
use prim_store::{PrimitiveStoreStats};
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
use render_backend::{FrameResources, FrameStamp};
use render_backend::{DataStores, FrameStamp};
use render_task::{RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree};
use resource_cache::{ResourceCache};
use scene::{ScenePipeline, SceneProperties};
@ -86,7 +86,7 @@ pub struct FrameVisibilityState<'a> {
pub scratch: &'a mut PrimitiveScratchBuffer,
pub tile_cache: Option<TileCache>,
pub retained_tiles: &'a mut RetainedTiles,
pub resources: &'a mut FrameResources,
pub data_stores: &'a mut DataStores,
}
pub struct FrameBuildingContext<'a> {
@ -244,7 +244,7 @@ impl FrameBuilder {
device_pixel_scale: DevicePixelScale,
scene_properties: &SceneProperties,
transform_palette: &mut TransformPalette,
resources: &mut FrameResources,
data_stores: &mut DataStores,
surfaces: &mut Vec<SurfaceInfo>,
scratch: &mut PrimitiveScratchBuffer,
debug_flags: DebugFlags,
@ -305,7 +305,7 @@ impl FrameBuilder {
&mut pic_update_state,
&frame_context,
gpu_cache,
resources,
data_stores,
&self.clip_store,
);
@ -326,7 +326,7 @@ impl FrameBuilder {
scratch,
tile_cache: None,
retained_tiles: &mut retained_tiles,
resources,
data_stores,
};
self.prim_store.update_visibility(
@ -369,7 +369,7 @@ impl FrameBuilder {
&mut pic_state,
&frame_context,
&mut frame_state,
resources,
data_stores,
scratch,
);
@ -417,7 +417,7 @@ impl FrameBuilder {
texture_cache_profile: &mut TextureCacheProfileCounters,
gpu_cache_profile: &mut GpuCacheProfileCounters,
scene_properties: &SceneProperties,
resources: &mut FrameResources,
data_stores: &mut DataStores,
scratch: &mut PrimitiveScratchBuffer,
debug_flags: DebugFlags,
) -> Frame {
@ -458,7 +458,7 @@ impl FrameBuilder {
device_pixel_scale,
scene_properties,
&mut transform_palette,
resources,
data_stores,
&mut surfaces,
scratch,
debug_flags,
@ -512,7 +512,7 @@ impl FrameBuilder {
resource_cache,
use_dual_source_blending,
clip_scroll_tree,
resources,
data_stores,
surfaces: &surfaces,
scratch,
};

View File

@ -0,0 +1,107 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
macro_rules! common {
() => (
use ::intern;
#[allow(unused_imports)]
use ::prim_store::PrimitiveSceneData;
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
pub struct Marker;
pub type Handle = intern::Handle<Marker>;
)
}
pub mod clip {
common!();
use ::clip::{ClipItemKey, ClipNode};
pub type Store = intern::DataStore<ClipItemKey, ClipNode, Marker>;
pub type UpdateList = intern::UpdateList<ClipItemKey>;
pub type Interner = intern::Interner<ClipItemKey, (), Marker>;
}
pub mod prim {
common!();
use ::prim_store::{PrimitiveKey, PrimitiveTemplate};
pub type Store = intern::DataStore<PrimitiveKey, PrimitiveTemplate, Marker>;
pub type UpdateList = intern::UpdateList<PrimitiveKey>;
pub type Interner = intern::Interner<PrimitiveKey, PrimitiveSceneData, Marker>;
}
pub mod normal_border {
common!();
use ::prim_store::borders::{NormalBorderKey, NormalBorderTemplate};
pub type Store = intern::DataStore<NormalBorderKey, NormalBorderTemplate, Marker>;
pub type UpdateList = intern::UpdateList<NormalBorderKey>;
pub type Interner = intern::Interner<NormalBorderKey, PrimitiveSceneData, Marker>;
}
pub mod image_border {
common!();
use ::prim_store::borders::{ImageBorderKey, ImageBorderTemplate};
pub type Store = intern::DataStore<ImageBorderKey, ImageBorderTemplate, Marker>;
pub type UpdateList = intern::UpdateList<ImageBorderKey>;
pub type Interner = intern::Interner<ImageBorderKey, PrimitiveSceneData, Marker>;
}
pub mod image {
common!();
use ::prim_store::image::{ImageKey, ImageTemplate};
pub type Store = intern::DataStore<ImageKey, ImageTemplate, Marker>;
pub type UpdateList = intern::UpdateList<ImageKey>;
pub type Interner = intern::Interner<ImageKey, PrimitiveSceneData, Marker>;
}
pub mod yuv_image {
common!();
use ::prim_store::image::{YuvImageKey, YuvImageTemplate};
pub type Store = intern::DataStore<YuvImageKey, YuvImageTemplate, Marker>;
pub type UpdateList = intern::UpdateList<YuvImageKey>;
pub type Interner = intern::Interner<YuvImageKey, PrimitiveSceneData, Marker>;
}
pub mod line_decoration {
use ::prim_store::line_dec::{LineDecorationKey, LineDecorationTemplate};
common!();
pub type Store = intern::DataStore<LineDecorationKey, LineDecorationTemplate, Marker>;
pub type UpdateList = intern::UpdateList<LineDecorationKey>;
pub type Interner = intern::Interner<LineDecorationKey, PrimitiveSceneData, Marker>;
}
pub mod linear_grad {
common!();
use ::prim_store::gradient::{LinearGradientKey, LinearGradientTemplate};
pub type Store = intern::DataStore<LinearGradientKey, LinearGradientTemplate, Marker>;
pub type UpdateList = intern::UpdateList<LinearGradientKey>;
pub type Interner = intern::Interner<LinearGradientKey, PrimitiveSceneData, Marker>;
}
pub mod radial_grad {
common!();
use ::prim_store::gradient::{RadialGradientKey, RadialGradientTemplate};
pub type Store = intern::DataStore<RadialGradientKey, RadialGradientTemplate, Marker>;
pub type UpdateList = intern::UpdateList<RadialGradientKey>;
pub type Interner = intern::Interner<RadialGradientKey, PrimitiveSceneData, Marker>;
}
pub mod picture {
common!();
use ::prim_store::picture::{PictureKey, PictureTemplate};
pub type Store = intern::DataStore<PictureKey, PictureTemplate, Marker>;
pub type UpdateList = intern::UpdateList<PictureKey>;
pub type Interner = intern::Interner<PictureKey, PrimitiveSceneData, Marker>;
}
pub mod text_run {
common!();
use ::prim_store::text_run::{TextRunKey, TextRunTemplate};
pub type Store = intern::DataStore<TextRunKey, TextRunTemplate, Marker>;
pub type UpdateList = intern::UpdateList<TextRunKey>;
pub type Interner = intern::Interner<TextRunKey, PrimitiveSceneData, Marker>;
}

View File

@ -100,6 +100,7 @@ mod gpu_types;
mod hit_test;
mod image;
mod intern;
mod intern_types;
mod internal_types;
mod picture;
mod prim_store;

View File

@ -16,7 +16,7 @@ use debug_colors;
use device::TextureFilter;
use euclid::{TypedScale, vec3, TypedRect, TypedPoint2D, TypedSize2D};
use euclid::approxeq::ApproxEq;
use frame_builder::FrameVisibilityContext;
use frame_builder::{FrameVisibilityContext, FrameVisibilityState};
use intern::ItemUid;
use internal_types::{FastHashMap, FastHashSet, PlaneSplitter};
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState, PictureContext};
@ -27,12 +27,12 @@ use prim_store::{PictureIndex, PrimitiveInstance, SpaceMapper, VisibleFace, Prim
use prim_store::{get_raster_rects, PrimitiveScratchBuffer, VectorKey, PointKey};
use prim_store::{OpacityBindingStorage, ImageInstanceStorage, OpacityBindingIndex, RectangleKey};
use print_tree::PrintTreePrinter;
use render_backend::FrameResources;
use render_backend::DataStores;
use render_task::{ClearMode, RenderTask, RenderTaskCacheEntryHandle, TileBlit};
use render_task::{RenderTaskCacheKey, RenderTaskCacheKeyKind, RenderTaskId, RenderTaskLocation};
use resource_cache::ResourceCache;
use scene::{FilterOpHelpers, SceneProperties};
use scene_builder::DocumentResources;
use scene_builder::Interners;
use smallvec::SmallVec;
use surface::{SurfaceDescriptor};
use std::{mem, u16};
@ -315,12 +315,26 @@ impl TileDescriptor {
/// as last frame. This doesn't check validity of the
/// tile based on the currently valid regions.
fn is_same_content(&self) -> bool {
self.image_keys.is_valid() &&
self.opacity_bindings.is_valid() &&
self.clip_uids.is_valid() &&
self.clip_vertices.is_valid() &&
self.prims.is_valid() &&
self.transforms.is_valid()
if !self.image_keys.is_valid() {
return false;
}
if !self.opacity_bindings.is_valid() {
return false;
}
if !self.clip_uids.is_valid() {
return false;
}
if !self.clip_vertices.is_valid() {
return false;
}
if !self.prims.is_valid() {
return false;
}
if !self.transforms.is_valid() {
return false;
}
true
}
}
@ -371,6 +385,9 @@ pub struct TileCache {
/// scroll bars in gecko, when the content overflows under the
/// scroll bar).
world_bounding_rect: WorldRect,
/// World space clip rect of the root clipping node. Every primitive
/// has this as the root of the clip chain attached to the primitive.
root_clip_rect: WorldRect,
/// List of reference primitive information used for
/// correlating the position between display lists.
reference_prims: ReferencePrimitiveList,
@ -497,6 +514,7 @@ impl TileCache {
scroll_offset: None,
pending_blits: Vec::new(),
world_bounding_rect: WorldRect::zero(),
root_clip_rect: WorldRect::max_rect(),
reference_prims,
root_clip_chain_id,
}
@ -529,8 +547,7 @@ impl TileCache {
&mut self,
pic_rect: LayoutRect,
frame_context: &FrameVisibilityContext,
resource_cache: &ResourceCache,
retained_tiles: &mut RetainedTiles,
frame_state: &mut FrameVisibilityState,
) {
// Work out the scroll offset to apply to the world reference point.
let scroll_transform = frame_context.clip_scroll_tree.get_relative_transform(
@ -548,11 +565,11 @@ impl TileCache {
self.scroll_offset = Some(scroll_offset);
// Pull any retained tiles from the previous scene.
let world_offset = if retained_tiles.tiles.is_empty() {
let world_offset = if frame_state.retained_tiles.tiles.is_empty() {
None
} else {
assert!(self.tiles.is_empty());
self.tiles = mem::replace(&mut retained_tiles.tiles, Vec::new());
self.tiles = mem::replace(&mut frame_state.retained_tiles.tiles, Vec::new());
// Get the positions of the reference primitives for this
// new display list.
@ -565,7 +582,7 @@ impl TileCache {
// Attempt to correlate them to work out which offset to apply.
correlate_prim_maps(
&retained_tiles.ref_prims,
&frame_state.retained_tiles.ref_prims,
&new_prim_map,
)
}.unwrap_or(WorldVector2D::zero());
@ -735,6 +752,28 @@ impl TileCache {
// detect this and skip the dependency update on scroll frames.
self.needs_update = true;
self.world_bounding_rect = WorldRect::zero();
self.root_clip_rect = WorldRect::max_rect();
// Calculate the world space of the root clip node, that every primitive has
// at the root of its clip chain (this is enforced by the per-pipeline-root
// clip node added implicitly during display list flattening). Doing it once
// here saves doing it for every primitive during update_prim_dependencies.
let root_clip_chain_node = &frame_state
.clip_store
.clip_chain_nodes[self.root_clip_chain_id.0 as usize];
let root_clip_node = &frame_state
.data_stores
.clip[root_clip_chain_node.handle];
if let Some(clip_rect) = root_clip_node.item.get_local_clip_rect(root_clip_chain_node.local_pos) {
self.map_local_to_world.set_target_spatial_node(
root_clip_chain_node.spatial_node_index,
frame_context.clip_scroll_tree,
);
if let Some(world_clip_rect) = self.map_local_to_world.map(&clip_rect) {
self.root_clip_rect = world_clip_rect;
}
}
// Do tile invalidation for any dependencies that we know now.
for tile in &mut self.tiles {
@ -743,7 +782,7 @@ impl TileCache {
// Content has changed if any images have changed
for image_key in tile.descriptor.image_keys.items() {
if resource_cache.is_image_dirty(*image_key) {
if frame_state.resource_cache.is_image_dirty(*image_key) {
tile.is_same_content = false;
break;
}
@ -776,7 +815,7 @@ impl TileCache {
&mut self,
prim_instance: &PrimitiveInstance,
clip_scroll_tree: &ClipScrollTree,
resources: &FrameResources,
data_stores: &DataStores,
clip_chain_nodes: &[ClipChainNode],
pictures: &[PicturePrimitive],
resource_cache: &ResourceCache,
@ -792,7 +831,7 @@ impl TileCache {
clip_scroll_tree,
);
let prim_data = &resources.as_common_data(&prim_instance);
let prim_data = &data_stores.as_common_data(&prim_instance);
let prim_rect = match prim_instance.kind {
PrimitiveInstanceKind::Picture { pic_index, .. } => {
@ -838,7 +877,7 @@ impl TileCache {
// Some primitives can not be cached (e.g. external video images)
let is_cacheable = prim_instance.is_cacheable(
&resources,
&data_stores,
resource_cache,
);
@ -874,7 +913,7 @@ impl TileCache {
true
}
PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
let image_data = &resources.image_data_store[data_handle].kind;
let image_data = &data_stores.image[data_handle].kind;
let image_instance = &image_instances[image_instance_index];
let opacity_binding_index = image_instance.opacity_binding_index;
@ -889,7 +928,7 @@ impl TileCache {
true
}
PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
let yuv_image_data = &resources.yuv_image_data_store[data_handle].kind;
let yuv_image_data = &data_stores.yuv_image[data_handle].kind;
image_keys.extend_from_slice(&yuv_image_data.yuv_key);
true
}
@ -915,7 +954,7 @@ impl TileCache {
let mut current_clip_chain_id = prim_instance.clip_chain_id;
while current_clip_chain_id != ClipChainId::NONE {
let clip_chain_node = &clip_chain_nodes[current_clip_chain_id.0 as usize];
let clip_node = &resources.clip_data_store[clip_chain_node.handle];
let clip_node = &data_stores.clip[clip_chain_node.handle];
// We can skip the root clip node - it will be taken care of by the
// world bounding rect calculated for the cache.
@ -941,12 +980,7 @@ impl TileCache {
size,
);
// If the clip rect is in the same spatial node, it can be handled by the
// local clip rect.
if clip_chain_node.spatial_node_index == prim_instance.spatial_node_index {
culling_rect = culling_rect.intersection(&local_clip_rect).unwrap_or(LayoutRect::zero());
false
} else if clip_spatial_node.coordinate_system_id == CoordinateSystemId(0) {
if clip_spatial_node.coordinate_system_id == CoordinateSystemId(0) {
// Clips that are not in the root coordinate system are not axis-aligned,
// so we need to treat them as normal style clips with vertices.
match self.map_local_to_world.map(&local_clip_rect) {
@ -959,10 +993,16 @@ impl TileCache {
.intersection(&clip_world_rect)
.unwrap_or(WorldRect::zero());
world_clips.push((
clip_world_rect.into(),
clip_chain_node.spatial_node_index,
));
// If the clip rect is in the same spatial node, it can be handled by the
// local clip rect.
if clip_chain_node.spatial_node_index == prim_instance.spatial_node_index {
culling_rect = culling_rect.intersection(&local_clip_rect).unwrap_or(LayoutRect::zero());
} else {
world_clips.push((
clip_world_rect.into(),
clip_chain_node.spatial_node_index,
));
}
false
}
@ -984,7 +1024,12 @@ impl TileCache {
if add_to_clip_deps {
clip_chain_uids.push(clip_chain_node.handle.uid());
clip_spatial_nodes.insert(clip_chain_node.spatial_node_index);
// If the clip has the same spatial node, the relative transform
// will always be the same, so there's no need to depend on it.
if clip_chain_node.spatial_node_index != self.spatial_node_index {
clip_spatial_nodes.insert(clip_chain_node.spatial_node_index);
}
let local_clip_rect = LayoutRect::new(
clip_chain_node.local_pos,
@ -999,7 +1044,11 @@ impl TileCache {
}
if include_clip_rect {
self.world_bounding_rect = self.world_bounding_rect.union(&world_clip_rect);
// Intersect the calculated prim bounds with the root clip rect, to save
// having to process and transform the root clip rect in every primitive.
if let Some(clipped_world_rect) = world_clip_rect.intersection(&self.root_clip_rect) {
self.world_bounding_rect = self.world_bounding_rect.union(&clipped_world_rect);
}
}
self.map_local_to_world.set_target_spatial_node(
@ -1062,7 +1111,12 @@ impl TileCache {
tile.descriptor.clip_vertices.push(clip_vertex.into());
}
tile.transforms.insert(prim_instance.spatial_node_index);
// If the primitive has the same spatial node, the relative transform
// will always be the same, so there's no need to depend on it.
if prim_instance.spatial_node_index != self.spatial_node_index {
tile.transforms.insert(prim_instance.spatial_node_index);
}
for spatial_node_index in &clip_spatial_nodes {
tile.transforms.insert(*spatial_node_index);
}
@ -1193,7 +1247,7 @@ impl TileCache {
_scratch.push_debug_string(
label_pos,
debug_colors::RED,
format!("{:?} {:?}", tile.id, tile.handle),
format!("{:?} {:?} {:?}", tile.id, tile.handle, tile.world_rect),
);
label_pos.y += 20.0;
_scratch.push_debug_string(
@ -1207,6 +1261,16 @@ impl TileCache {
// Add the tile rect to the dirty rect.
dirty_world_rect = dirty_world_rect.union(&visible_rect);
#[cfg(feature = "debug_renderer")]
{
if frame_context.debug_flags.contains(DebugFlags::PICTURE_CACHING_DBG) {
_scratch.push_debug_rect(
visible_rect * frame_context.device_pixel_scale,
debug_colors::RED,
);
}
}
// Only cache tiles that have had the same content for at least two
// frames. This skips caching on pages / benchmarks that are changing
// every frame, which is wasteful.
@ -1258,16 +1322,6 @@ impl TileCache {
} else {
let dirty_device_rect = dirty_world_rect * frame_context.device_pixel_scale;
#[cfg(feature = "debug_renderer")]
{
if frame_context.debug_flags.contains(DebugFlags::PICTURE_CACHING_DBG) {
_scratch.push_debug_rect(
dirty_device_rect,
debug_colors::RED,
);
}
}
Some(DirtyRegion {
dirty_world_rect,
dirty_device_rect: dirty_device_rect.round().to_i32(),
@ -1580,7 +1634,7 @@ impl PrimitiveList {
/// significantly faster.
pub fn new(
mut prim_instances: Vec<PrimitiveInstance>,
resources: &DocumentResources
interners: &Interners
) -> Self {
let mut pictures = SmallVec::new();
let mut clusters_map = FastHashMap::default();
@ -1604,34 +1658,34 @@ impl PrimitiveList {
let prim_data = match prim_instance.kind {
PrimitiveInstanceKind::Rectangle { data_handle, .. } |
PrimitiveInstanceKind::Clear { data_handle, .. } => {
&resources.prim_interner[data_handle]
&interners.prim[data_handle]
}
PrimitiveInstanceKind::Image { data_handle, .. } => {
&resources.image_interner[data_handle]
&interners.image[data_handle]
}
PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
&resources.image_border_interner[data_handle]
&interners.image_border[data_handle]
}
PrimitiveInstanceKind::LineDecoration { data_handle, .. } => {
&resources.line_decoration_interner[data_handle]
&interners.line_decoration[data_handle]
}
PrimitiveInstanceKind::LinearGradient { data_handle, .. } => {
&resources.linear_grad_interner[data_handle]
&interners.linear_grad[data_handle]
}
PrimitiveInstanceKind::NormalBorder { data_handle, .. } => {
&resources.normal_border_interner[data_handle]
&interners.normal_border[data_handle]
}
PrimitiveInstanceKind::Picture { data_handle, .. } => {
&resources.picture_interner[data_handle]
&interners.picture[data_handle]
}
PrimitiveInstanceKind::RadialGradient { data_handle, ..} => {
&resources.radial_grad_interner[data_handle]
&interners.radial_grad[data_handle]
}
PrimitiveInstanceKind::TextRun { data_handle, .. } => {
&resources.text_run_interner[data_handle]
&interners.text_run[data_handle]
}
PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
&resources.yuv_image_interner[data_handle]
&interners.yuv_image[data_handle]
}
};

View File

@ -13,6 +13,7 @@ use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
use frame_builder::{FrameBuildingState};
use gpu_cache::GpuDataRequest;
use intern;
use intern_types;
use prim_store::{
BorderSegmentInfo, BrushSegment, NinePatchDescriptor, PrimKey,
PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
@ -158,18 +159,10 @@ impl From<NormalBorderKey> for NormalBorderTemplate {
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
pub struct NormalBorderDataMarker;
pub type NormalBorderDataStore = intern::DataStore<NormalBorderKey, NormalBorderTemplate, NormalBorderDataMarker>;
pub type NormalBorderDataHandle = intern::Handle<NormalBorderDataMarker>;
pub type NormalBorderDataUpdateList = intern::UpdateList<NormalBorderKey>;
pub type NormalBorderDataInterner = intern::Interner<NormalBorderKey, PrimitiveSceneData, NormalBorderDataMarker>;
pub use intern_types::normal_border::Handle as NormalBorderDataHandle;
impl intern::Internable for NormalBorderPrim {
type Marker = NormalBorderDataMarker;
type Marker = intern_types::normal_border::Marker;
type Source = NormalBorderKey;
type StoreData = NormalBorderTemplate;
type InternData = PrimitiveSceneData;
@ -335,18 +328,10 @@ impl From<ImageBorderKey> for ImageBorderTemplate {
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
pub struct ImageBorderDataMarker;
pub type ImageBorderDataStore = intern::DataStore<ImageBorderKey, ImageBorderTemplate, ImageBorderDataMarker>;
pub type ImageBorderDataHandle = intern::Handle<ImageBorderDataMarker>;
pub type ImageBorderDataUpdateList = intern::UpdateList<ImageBorderKey>;
pub type ImageBorderDataInterner = intern::Interner<ImageBorderKey, PrimitiveSceneData, ImageBorderDataMarker>;
pub use intern_types::image_border::Handle as ImageBorderDataHandle;
impl intern::Internable for ImageBorder {
type Marker = ImageBorderDataMarker;
type Marker = intern_types::image_border::Marker;
type Source = ImageBorderKey;
type StoreData = ImageBorderTemplate;
type InternData = PrimitiveSceneData;

View File

@ -9,7 +9,8 @@ use api::{
use display_list_flattener::{AsInstanceKind, IsVisible};
use frame_builder::FrameBuildingState;
use gpu_cache::{GpuCacheHandle, GpuDataRequest};
use intern::{DataStore, Handle, Internable, InternDebug, Interner, UpdateList};
use intern::{Internable, InternDebug};
use intern_types;
use prim_store::{BrushSegment, GradientTileRange};
use prim_store::{PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData};
use prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore};
@ -225,15 +226,7 @@ impl LinearGradientTemplate {
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
pub struct LinearGradientDataMarker;
pub type LinearGradientDataStore = DataStore<LinearGradientKey, LinearGradientTemplate, LinearGradientDataMarker>;
pub type LinearGradientDataHandle = Handle<LinearGradientDataMarker>;
pub type LinearGradientDataUpdateList = UpdateList<LinearGradientKey>;
pub type LinearGradientDataInterner = Interner<LinearGradientKey, PrimitiveSceneData, LinearGradientDataMarker>;
pub type LinearGradientDataHandle = intern_types::linear_grad::Handle;
pub struct LinearGradient {
pub extend_mode: ExtendMode,
@ -247,7 +240,7 @@ pub struct LinearGradient {
}
impl Internable for LinearGradient {
type Marker = LinearGradientDataMarker;
type Marker = intern_types::linear_grad::Marker;
type Source = LinearGradientKey;
type StoreData = LinearGradientTemplate;
type InternData = PrimitiveSceneData;
@ -452,15 +445,7 @@ impl RadialGradientTemplate {
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
pub struct RadialGradientDataMarker;
pub type RadialGradientDataStore = DataStore<RadialGradientKey, RadialGradientTemplate, RadialGradientDataMarker>;
pub type RadialGradientDataHandle = Handle<RadialGradientDataMarker>;
pub type RadialGradientDataUpdateList = UpdateList<RadialGradientKey>;
pub type RadialGradientDataInterner = Interner<RadialGradientKey, PrimitiveSceneData, RadialGradientDataMarker>;
pub type RadialGradientDataHandle = intern_types::radial_grad::Handle;
pub struct RadialGradient {
pub extend_mode: ExtendMode,
@ -473,7 +458,7 @@ pub struct RadialGradient {
}
impl Internable for RadialGradient {
type Marker = RadialGradientDataMarker;
type Marker = intern_types::radial_grad::Marker;
type Source = RadialGradientKey;
type StoreData = RadialGradientTemplate;
type InternData = PrimitiveSceneData;

View File

@ -11,7 +11,8 @@ use api::ImageKey as ApiImageKey;
use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
use frame_builder::FrameBuildingState;
use gpu_cache::{GpuCacheHandle, GpuDataRequest};
use intern::{DataStore, Handle, Internable, Interner, InternDebug, UpdateList};
use intern::{Internable, InternDebug};
use intern_types;
use prim_store::{
EdgeAaSegmentMask, OpacityBindingIndex, PrimitiveInstanceKind,
PrimitiveOpacity, PrimitiveSceneData, PrimKey, PrimKeyCommonData,
@ -333,18 +334,10 @@ impl From<ImageKey> for ImageTemplate {
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
pub struct ImageDataMarker;
pub type ImageDataStore = DataStore<ImageKey, ImageTemplate, ImageDataMarker>;
pub type ImageDataHandle = Handle<ImageDataMarker>;
pub type ImageDataUpdateList = UpdateList<ImageKey>;
pub type ImageDataInterner = Interner<ImageKey, PrimitiveSceneData, ImageDataMarker>;
pub use intern_types::image::Handle as ImageDataHandle;
impl Internable for Image {
type Marker = ImageDataMarker;
type Marker = intern_types::image::Marker;
type Source = ImageKey;
type StoreData = ImageTemplate;
type InternData = PrimitiveSceneData;
@ -507,18 +500,10 @@ impl From<YuvImageKey> for YuvImageTemplate {
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
pub struct YuvImageDataMarker;
pub type YuvImageDataStore = DataStore<YuvImageKey, YuvImageTemplate, YuvImageDataMarker>;
pub type YuvImageDataHandle = Handle<YuvImageDataMarker>;
pub type YuvImageDataUpdateList = UpdateList<YuvImageKey>;
pub type YuvImageDataInterner = Interner<YuvImageKey, PrimitiveSceneData, YuvImageDataMarker>;
pub use intern_types::yuv_image::Handle as YuvImageDataHandle;
impl Internable for YuvImage {
type Marker = YuvImageDataMarker;
type Marker = intern_types::yuv_image::Marker;
type Source = YuvImageKey;
type StoreData = YuvImageTemplate;
type InternData = PrimitiveSceneData;

View File

@ -11,6 +11,7 @@ use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
use frame_builder::{FrameBuildingState};
use gpu_cache::GpuDataRequest;
use intern;
use intern_types;
use prim_store::{
PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
PrimitiveSceneData, PrimitiveStore,
@ -133,18 +134,10 @@ impl From<LineDecorationKey> for LineDecorationTemplate {
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
pub struct LineDecorationDataMarker;
pub type LineDecorationDataStore = intern::DataStore<LineDecorationKey, LineDecorationTemplate, LineDecorationDataMarker>;
pub type LineDecorationDataHandle = intern::Handle<LineDecorationDataMarker>;
pub type LineDecorationDataUpdateList = intern::UpdateList<LineDecorationKey>;
pub type LineDecorationDataInterner = intern::Interner<LineDecorationKey, PrimitiveSceneData, LineDecorationDataMarker>;
pub use intern_types::line_decoration::Handle as LineDecorationDataHandle;
impl intern::Internable for LineDecoration {
type Marker = LineDecorationDataMarker;
type Marker = intern_types::line_decoration::Marker;
type Source = LineDecorationKey;
type StoreData = LineDecorationTemplate;
type InternData = PrimitiveSceneData;

View File

@ -41,7 +41,7 @@ use prim_store::picture::PictureDataHandle;
use prim_store::text_run::{TextRunDataHandle, TextRunPrimitive};
#[cfg(debug_assertions)]
use render_backend::{FrameId};
use render_backend::FrameResources;
use render_backend::DataStores;
use render_task::{RenderTask, RenderTaskCacheKey, to_cache_size};
use render_task::{RenderTaskCacheKeyKind, RenderTaskId, RenderTaskCacheEntryHandle};
use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
@ -821,14 +821,8 @@ impl PrimitiveTemplate {
}
}
// Type definitions for interning primitives.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
pub struct PrimitiveDataMarker;
impl intern::Internable for PrimitiveKeyKind {
type Marker = PrimitiveDataMarker;
type Marker = ::intern_types::prim::Marker;
type Source = PrimitiveKey;
type StoreData = PrimitiveTemplate;
type InternData = PrimitiveSceneData;
@ -845,10 +839,7 @@ impl intern::Internable for PrimitiveKeyKind {
}
}
pub type PrimitiveDataStore = intern::DataStore<PrimitiveKey, PrimitiveTemplate, PrimitiveDataMarker>;
pub type PrimitiveDataHandle = intern::Handle<PrimitiveDataMarker>;
pub type PrimitiveDataUpdateList = intern::UpdateList<PrimitiveKey>;
pub type PrimitiveDataInterner = intern::Interner<PrimitiveKey, PrimitiveSceneData, PrimitiveDataMarker>;
use intern_types::prim::Handle as PrimitiveDataHandle;
// Maintains a list of opacity bindings that have been collapsed into
// the color of a single primitive. This is an important optimization
@ -1737,7 +1728,7 @@ impl PrimitiveStore {
state: &mut PictureUpdateState,
frame_context: &FrameBuildingContext,
gpu_cache: &mut GpuCache,
resources: &FrameResources,
data_stores: &DataStores,
clip_store: &ClipStore,
) {
if let Some(children) = self.pictures[pic_index.0].pre_update(
@ -1750,7 +1741,7 @@ impl PrimitiveStore {
state,
frame_context,
gpu_cache,
resources,
data_stores,
clip_store,
);
}
@ -1791,8 +1782,7 @@ impl PrimitiveStore {
tile_cache.pre_update(
pic.local_rect,
frame_context,
frame_state.resource_cache,
frame_state.retained_tiles,
frame_state,
);
frame_state.tile_cache = Some(tile_cache);
@ -1878,7 +1868,7 @@ impl PrimitiveStore {
(pic.raster_config.is_none(), pic.local_rect, clip_node_collector)
}
_ => {
let prim_data = &frame_state.resources.as_common_data(&prim_instance);
let prim_data = &frame_state.data_stores.as_common_data(&prim_instance);
let prim_rect = LayoutRect::new(
prim_instance.prim_origin,
@ -1944,14 +1934,14 @@ impl PrimitiveStore {
frame_context.device_pixel_scale,
&frame_context.screen_world_rect,
clip_node_collector.as_ref(),
&mut frame_state.resources.clip_data_store,
&mut frame_state.data_stores.clip,
);
if let Some(ref mut tile_cache) = frame_state.tile_cache {
tile_cache.update_prim_dependencies(
prim_instance,
frame_context.clip_scroll_tree,
frame_state.resources,
frame_state.data_stores,
&frame_state.clip_store.clip_chain_nodes,
&self.pictures,
frame_state.resource_cache,
@ -2192,7 +2182,7 @@ impl PrimitiveStore {
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
plane_split_anchor: usize,
resources: &mut FrameResources,
data_stores: &mut DataStores,
scratch: &mut PrimitiveScratchBuffer,
) -> bool {
// If we have dependencies, we need to prepare them first, in order
@ -2251,7 +2241,7 @@ impl PrimitiveStore {
&mut pic_state_for_children,
frame_context,
frame_state,
resources,
data_stores,
scratch,
);
@ -2283,7 +2273,7 @@ impl PrimitiveStore {
frame_context,
frame_state,
self,
resources,
data_stores,
scratch,
);
@ -2298,7 +2288,7 @@ impl PrimitiveStore {
}
pic_state.is_cacheable &= prim_instance.is_cacheable(
&resources,
&data_stores,
frame_state.resource_cache,
);
@ -2356,7 +2346,7 @@ impl PrimitiveStore {
pic_context,
frame_context,
frame_state,
resources,
data_stores,
scratch,
);
}
@ -2372,7 +2362,7 @@ impl PrimitiveStore {
pic_state: &mut PictureState,
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
resources: &mut FrameResources,
data_stores: &mut DataStores,
scratch: &mut PrimitiveScratchBuffer,
) {
for (plane_split_anchor, prim_instance) in prim_list.prim_instances.iter_mut().enumerate() {
@ -2424,7 +2414,7 @@ impl PrimitiveStore {
frame_context,
frame_state,
plane_split_anchor,
resources,
data_stores,
scratch,
) {
frame_state.profile_counters.visible_primitives.inc();
@ -2442,14 +2432,14 @@ impl PrimitiveStore {
pic_context: &PictureContext,
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
resources: &mut FrameResources,
data_stores: &mut DataStores,
scratch: &mut PrimitiveScratchBuffer,
) {
let is_chased = prim_instance.is_chased();
match &mut prim_instance.kind {
PrimitiveInstanceKind::LineDecoration { data_handle, ref mut cache_handle, .. } => {
let prim_data = &mut resources.line_decoration_data_store[*data_handle];
let prim_data = &mut data_stores.line_decoration[*data_handle];
let common_data = &mut prim_data.common;
let line_dec_data = &mut prim_data.kind;
@ -2498,7 +2488,7 @@ impl PrimitiveStore {
}
}
PrimitiveInstanceKind::TextRun { data_handle, run_index, .. } => {
let prim_data = &mut resources.text_run_data_store[*data_handle];
let prim_data = &mut data_stores.text_run[*data_handle];
// Update the template this instane references, which may refresh the GPU
// cache with any shared template data.
@ -2527,14 +2517,14 @@ impl PrimitiveStore {
);
}
PrimitiveInstanceKind::Clear { data_handle, .. } => {
let prim_data = &mut resources.prim_data_store[*data_handle];
let prim_data = &mut data_stores.prim[*data_handle];
// Update the template this instane references, which may refresh the GPU
// cache with any shared template data.
prim_data.update(frame_state);
}
PrimitiveInstanceKind::NormalBorder { data_handle, ref mut cache_handles, .. } => {
let prim_data = &mut resources.normal_border_data_store[*data_handle];
let prim_data = &mut data_stores.normal_border[*data_handle];
let common_data = &mut prim_data.common;
let border_data = &mut prim_data.kind;
@ -2591,14 +2581,14 @@ impl PrimitiveStore {
.extend(handles);
}
PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
let prim_data = &mut resources.image_border_data_store[*data_handle];
let prim_data = &mut data_stores.image_border[*data_handle];
// Update the template this instane references, which may refresh the GPU
// cache with any shared template data.
prim_data.kind.update(&mut prim_data.common, frame_state);
}
PrimitiveInstanceKind::Rectangle { data_handle, segment_instance_index, opacity_binding_index, .. } => {
let prim_data = &mut resources.prim_data_store[*data_handle];
let prim_data = &mut data_stores.prim[*data_handle];
// Update the template this instane references, which may refresh the GPU
// cache with any shared template data.
@ -2617,7 +2607,7 @@ impl PrimitiveStore {
});
}
PrimitiveInstanceKind::YuvImage { data_handle, segment_instance_index, .. } => {
let yuv_image_data = &mut resources.yuv_image_data_store[*data_handle];
let yuv_image_data = &mut data_stores.yuv_image[*data_handle];
// Update the template this instane references, which may refresh the GPU
// cache with any shared template data.
@ -2628,7 +2618,7 @@ impl PrimitiveStore {
});
}
PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
let prim_data = &mut resources.image_data_store[*data_handle];
let prim_data = &mut data_stores.image[*data_handle];
let common_data = &mut prim_data.common;
let image_data = &mut prim_data.kind;
@ -2742,7 +2732,7 @@ impl PrimitiveStore {
});
}
PrimitiveInstanceKind::LinearGradient { data_handle, ref mut visible_tiles_range, .. } => {
let prim_data = &mut resources.linear_grad_data_store[*data_handle];
let prim_data = &mut data_stores.linear_grad[*data_handle];
// Update the template this instane references, which may refresh the GPU
// cache with any shared template data.
@ -2789,7 +2779,7 @@ impl PrimitiveStore {
// for gradient primitives.
}
PrimitiveInstanceKind::RadialGradient { data_handle, ref mut visible_tiles_range, .. } => {
let prim_data = &mut resources.radial_grad_data_store[*data_handle];
let prim_data = &mut data_stores.radial_grad[*data_handle];
// Update the template this instane references, which may refresh the GPU
// cache with any shared template data.
@ -2972,7 +2962,7 @@ impl<'a> GpuDataRequest<'a> {
clip_chain: &ClipChainInstance,
segment_builder: &mut SegmentBuilder,
clip_store: &ClipStore,
resources: &FrameResources,
data_stores: &DataStores,
) -> bool {
// If the brush is small, we generally want to skip building segments
// and just draw it as a single primitive with clip mask. However,
@ -2997,7 +2987,7 @@ impl<'a> GpuDataRequest<'a> {
for i in 0 .. clip_chain.clips_range.count {
let clip_instance = clip_store
.get_instance_from_range(&clip_chain.clips_range, i);
let clip_node = &resources.clip_data_store[clip_instance.handle];
let clip_node = &data_stores.clip[clip_instance.handle];
// If this clip item is positioned by another positioning node, its relative position
// could change during scrolling. This means that we would need to resegment. Instead
@ -3102,11 +3092,11 @@ impl PrimitiveInstance {
prim_clip_chain: &ClipChainInstance,
frame_state: &mut FrameBuildingState,
prim_store: &mut PrimitiveStore,
resources: &FrameResources,
data_stores: &DataStores,
segments_store: &mut SegmentStorage,
segment_instances_store: &mut SegmentInstanceStorage,
) {
let prim_data = &resources.as_common_data(self);
let prim_data = &data_stores.as_common_data(self);
let prim_local_rect = LayoutRect::new(
self.prim_origin,
prim_data.prim_size,
@ -3118,7 +3108,7 @@ impl PrimitiveInstance {
segment_instance_index
}
PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
let image_data = &resources.image_data_store[data_handle].kind;
let image_data = &data_stores.image[data_handle].kind;
let image_instance = &mut prim_store.images[image_instance_index];
// tiled images don't support segmentation
if frame_state
@ -3153,7 +3143,7 @@ impl PrimitiveInstance {
prim_clip_chain,
&mut frame_state.segment_builder,
frame_state.clip_store,
resources,
data_stores,
) {
frame_state.segment_builder.build(|segment| {
segments.push(
@ -3193,7 +3183,7 @@ impl PrimitiveInstance {
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
prim_store: &PrimitiveStore,
resources: &mut FrameResources,
data_stores: &mut DataStores,
segments_store: &mut SegmentStorage,
segment_instances_store: &mut SegmentInstanceStorage,
clip_mask_instances: &mut Vec<ClipMaskKind>,
@ -3231,21 +3221,21 @@ impl PrimitiveInstance {
&segments_store[segment_instance.segments_range]
}
PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
let border_data = &resources.image_border_data_store[data_handle].kind;
let border_data = &data_stores.image_border[data_handle].kind;
// TODO: This is quite messy - once we remove legacy primitives we
// can change this to be a tuple match on (instance, template)
border_data.brush_segments.as_slice()
}
PrimitiveInstanceKind::NormalBorder { data_handle, .. } => {
let border_data = &resources.normal_border_data_store[data_handle].kind;
let border_data = &data_stores.normal_border[data_handle].kind;
// TODO: This is quite messy - once we remove legacy primitives we
// can change this to be a tuple match on (instance, template)
border_data.brush_segments.as_slice()
}
PrimitiveInstanceKind::LinearGradient { data_handle, .. } => {
let prim_data = &resources.linear_grad_data_store[data_handle];
let prim_data = &data_stores.linear_grad[data_handle];
// TODO: This is quite messy - once we remove legacy primitives we
// can change this to be a tuple match on (instance, template)
@ -3256,7 +3246,7 @@ impl PrimitiveInstance {
prim_data.brush_segments.as_slice()
}
PrimitiveInstanceKind::RadialGradient { data_handle, .. } => {
let prim_data = &resources.radial_grad_data_store[data_handle];
let prim_data = &data_stores.radial_grad[data_handle];
// TODO: This is quite messy - once we remove legacy primitives we
// can change this to be a tuple match on (instance, template)
@ -3292,7 +3282,7 @@ impl PrimitiveInstance {
pic_state,
frame_context,
frame_state,
&mut resources.clip_data_store,
&mut data_stores.clip,
);
clip_mask_instances.push(clip_mask_kind);
} else {
@ -3318,7 +3308,7 @@ impl PrimitiveInstance {
frame_context.device_pixel_scale,
&pic_context.dirty_world_rect,
None,
&mut resources.clip_data_store,
&mut data_stores.clip,
);
let clip_mask_kind = segment.update_clip_task(
@ -3329,7 +3319,7 @@ impl PrimitiveInstance {
pic_state,
frame_context,
frame_state,
&mut resources.clip_data_store,
&mut data_stores.clip,
);
clip_mask_instances.push(clip_mask_kind);
}
@ -3347,7 +3337,7 @@ impl PrimitiveInstance {
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
prim_store: &mut PrimitiveStore,
resources: &mut FrameResources,
data_stores: &mut DataStores,
scratch: &mut PrimitiveScratchBuffer,
) {
let prim_info = &mut scratch.prim_info[self.visibility_info.0 as usize];
@ -3360,7 +3350,7 @@ impl PrimitiveInstance {
&prim_info.clip_chain,
frame_state,
prim_store,
resources,
data_stores,
&mut scratch.segments,
&mut scratch.segment_instances,
);
@ -3375,7 +3365,7 @@ impl PrimitiveInstance {
frame_context,
frame_state,
prim_store,
resources,
data_stores,
&mut scratch.segments,
&mut scratch.segment_instances,
&mut scratch.clip_mask_instances,
@ -3402,7 +3392,7 @@ impl PrimitiveInstance {
frame_state.gpu_cache,
frame_state.resource_cache,
frame_state.render_tasks,
&mut resources.clip_data_store,
&mut data_stores.clip,
);
let clip_task_id = frame_state.render_tasks.add(clip_task);

View File

@ -8,7 +8,8 @@ use api::{
};
use app_units::Au;
use display_list_flattener::{AsInstanceKind, IsVisible};
use intern::{DataStore, Handle, Internable, Interner, InternDebug, UpdateList};
use intern::{Internable, InternDebug};
use intern_types;
use picture::PictureCompositeMode;
use prim_store::{
PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
@ -185,18 +186,10 @@ impl From<PictureKey> for PictureTemplate {
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
pub struct PictureDataMarker;
pub type PictureDataStore = DataStore<PictureKey, PictureTemplate, PictureDataMarker>;
pub type PictureDataHandle = Handle<PictureDataMarker>;
pub type PictureDataUpdateList = UpdateList<PictureKey>;
pub type PictureDataInterner = Interner<PictureKey, PrimitiveSceneData, PictureDataMarker>;
pub use intern_types::picture::Handle as PictureDataHandle;
impl Internable for Picture {
type Marker = PictureDataMarker;
type Marker = intern_types::picture::Marker;
type Source = PictureKey;
type StoreData = PictureTemplate;
type InternData = PrimitiveSceneData;

View File

@ -10,6 +10,7 @@ use frame_builder::{FrameBuildingState, PictureContext};
use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey, FONT_SIZE_LIMIT};
use gpu_cache::GpuCache;
use intern;
use intern_types;
use prim_store::{PrimitiveOpacity, PrimitiveSceneData, PrimitiveScratchBuffer};
use prim_store::{PrimitiveStore, PrimKeyCommonData, PrimTemplateCommonData, VectorKey};
use render_task::{RenderTaskTree};
@ -161,15 +162,7 @@ impl TextRunTemplate {
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
pub struct TextRunDataMarker;
pub type TextRunDataStore = intern::DataStore<TextRunKey, TextRunTemplate, TextRunDataMarker>;
pub type TextRunDataHandle = intern::Handle<TextRunDataMarker>;
pub type TextRunDataUpdateList = intern::UpdateList<TextRunKey>;
pub type TextRunDataInterner = intern::Interner<TextRunKey, PrimitiveSceneData, TextRunDataMarker>;
pub use intern_types::text_run::Handle as TextRunDataHandle;
pub struct TextRun {
pub font: FontInstance,
@ -179,7 +172,7 @@ pub struct TextRun {
}
impl intern::Internable for TextRun {
type Marker = TextRunDataMarker;
type Marker = intern_types::text_run::Marker;
type Source = TextRunKey;
type StoreData = TextRunTemplate;
type InternData = PrimitiveSceneData;

View File

@ -401,21 +401,39 @@ pub struct IpcProfileCounters {
pub display_lists: ResourceProfileCounter,
}
#[derive(Clone)]
pub struct InternProfileCounters {
pub prims: ResourceProfileCounter,
pub images: ResourceProfileCounter,
pub image_borders: ResourceProfileCounter,
pub line_decs: ResourceProfileCounter,
pub linear_gradients: ResourceProfileCounter,
pub normal_borders: ResourceProfileCounter,
pub pictures: ResourceProfileCounter,
pub radial_gradients: ResourceProfileCounter,
pub text_runs: ResourceProfileCounter,
pub yuv_images: ResourceProfileCounter,
pub clips: ResourceProfileCounter,
macro_rules! declare_intern_profile_counters {
( $( $name: ident, )+ ) => {
#[derive(Clone)]
pub struct InternProfileCounters {
$(
pub $name: ResourceProfileCounter,
)+
}
impl InternProfileCounters {
#[cfg(feature = "debug_renderer")]
fn draw(
&self,
debug_renderer: &mut DebugRenderer,
draw_state: &mut DrawState,
) {
Profiler::draw_counters(
&[
$(
&self.$name,
)+
],
debug_renderer,
true,
draw_state,
);
}
}
}
}
enumerate_interners!(declare_intern_profile_counters);
impl IpcProfileCounters {
pub fn set(
&mut self,
@ -455,17 +473,17 @@ impl BackendProfileCounters {
display_lists: ResourceProfileCounter::new("Display Lists Sent"),
},
intern: InternProfileCounters {
prims: ResourceProfileCounter::new("Interned primitives"),
images: ResourceProfileCounter::new("Interned images"),
image_borders: ResourceProfileCounter::new("Interned image borders"),
line_decs: ResourceProfileCounter::new("Interned line decorations"),
linear_gradients: ResourceProfileCounter::new("Interned linear gradients"),
normal_borders: ResourceProfileCounter::new("Interned normal borders"),
pictures: ResourceProfileCounter::new("Interned pictures"),
radial_gradients: ResourceProfileCounter::new("Interned radial gradients"),
text_runs: ResourceProfileCounter::new("Interned text runs"),
yuv_images: ResourceProfileCounter::new("Interned YUV images"),
clips: ResourceProfileCounter::new("Interned clips"),
prim: ResourceProfileCounter::new("Interned primitives"),
image: ResourceProfileCounter::new("Interned images"),
image_border: ResourceProfileCounter::new("Interned image borders"),
line_decoration: ResourceProfileCounter::new("Interned line decorations"),
linear_grad: ResourceProfileCounter::new("Interned linear gradients"),
normal_border: ResourceProfileCounter::new("Interned normal borders"),
picture: ResourceProfileCounter::new("Interned pictures"),
radial_grad: ResourceProfileCounter::new("Interned radial gradients"),
text_run: ResourceProfileCounter::new("Interned text runs"),
yuv_image: ResourceProfileCounter::new("Interned YUV images"),
clip: ResourceProfileCounter::new("Interned clips"),
},
}
}
@ -1111,24 +1129,7 @@ impl Profiler {
&mut self.draw_state
);
Profiler::draw_counters(
&[
&backend_profile.intern.clips,
&backend_profile.intern.prims,
&backend_profile.intern.images,
&backend_profile.intern.image_borders,
&backend_profile.intern.line_decs,
&backend_profile.intern.linear_gradients,
&backend_profile.intern.normal_borders,
&backend_profile.intern.pictures,
&backend_profile.intern.radial_gradients,
&backend_profile.intern.text_runs,
&backend_profile.intern.yuv_images,
],
debug_renderer,
true,
&mut self.draw_state
);
backend_profile.intern.draw(debug_renderer, &mut self.draw_state);
Profiler::draw_counters(
&[

View File

@ -22,24 +22,18 @@ use api::channel::{MsgReceiver, MsgSender, Payload};
use api::CaptureBits;
#[cfg(feature = "replay")]
use api::CapturedDocument;
use clip::ClipDataStore;
use clip_scroll_tree::{SpatialNodeIndex, ClipScrollTree};
#[cfg(feature = "debugger")]
use debug_server;
use frame_builder::{FrameBuilder, FrameBuilderConfig};
use gpu_cache::GpuCache;
use hit_test::{HitTest, HitTester};
use intern_types;
use internal_types::{DebugOutput, FastHashMap, FastHashSet, RenderedDocument, ResultMsg};
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use picture::RetainedTiles;
use prim_store::{PrimitiveDataStore, PrimitiveScratchBuffer, PrimitiveInstance};
use prim_store::{PrimitiveScratchBuffer, PrimitiveInstance};
use prim_store::{PrimitiveInstanceKind, PrimTemplateCommonData};
use prim_store::borders::{ImageBorderDataStore, NormalBorderDataStore};
use prim_store::gradient::{LinearGradientDataStore, RadialGradientDataStore};
use prim_store::image::{ImageDataStore, YuvImageDataStore};
use prim_store::line_dec::LineDecorationDataStore;
use prim_store::picture::PictureDataStore;
use prim_store::text_run::TextRunDataStore;
use profiler::{BackendProfileCounters, IpcProfileCounters, ResourceProfileCounters};
use record::ApiRecordingReceiver;
use renderer::{AsyncPropertySampler, PipelineInfo};
@ -214,33 +208,46 @@ impl FrameStamp {
};
}
macro_rules! declare_frame_resources {
( $( { $x: ident, $y: ty, $datastore_ident: ident, $datastore_type: ty } )+ ) => {
macro_rules! declare_data_stores {
( $( $name: ident, )+ ) => {
/// A collection of resources that are shared by clips, primitives
/// between display lists.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Default)]
pub struct FrameResources {
pub struct DataStores {
$(
pub $datastore_ident: $datastore_type,
pub $name: intern_types::$name::Store,
)+
}
impl FrameResources {
impl DataStores {
/// Reports CPU heap usage.
fn report_memory(&self, ops: &mut MallocSizeOfOps, r: &mut MemoryReport) {
$(
r.interning.$datastore_ident += self.$datastore_ident.size_of(ops);
r.interning.data_stores.$name += self.$name.size_of(ops);
)+
}
fn apply_updates(
&mut self,
updates: InternerUpdates,
profile_counters: &mut BackendProfileCounters,
) {
$(
self.$name.apply_updates(
updates.$name,
&mut profile_counters.intern.$name,
);
)+
}
}
}
}
enumerate_interners!(declare_frame_resources);
enumerate_interners!(declare_data_stores);
impl FrameResources {
impl DataStores {
pub fn as_common_data(
&self,
prim_inst: &PrimitiveInstance
@ -248,43 +255,43 @@ impl FrameResources {
match prim_inst.kind {
PrimitiveInstanceKind::Rectangle { data_handle, .. } |
PrimitiveInstanceKind::Clear { data_handle, .. } => {
let prim_data = &self.prim_data_store[data_handle];
let prim_data = &self.prim[data_handle];
&prim_data.common
}
PrimitiveInstanceKind::Image { data_handle, .. } => {
let prim_data = &self.image_data_store[data_handle];
let prim_data = &self.image[data_handle];
&prim_data.common
}
PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
let prim_data = &self.image_border_data_store[data_handle];
let prim_data = &self.image_border[data_handle];
&prim_data.common
}
PrimitiveInstanceKind::LineDecoration { data_handle, .. } => {
let prim_data = &self.line_decoration_data_store[data_handle];
let prim_data = &self.line_decoration[data_handle];
&prim_data.common
}
PrimitiveInstanceKind::LinearGradient { data_handle, .. } => {
let prim_data = &self.linear_grad_data_store[data_handle];
let prim_data = &self.linear_grad[data_handle];
&prim_data.common
}
PrimitiveInstanceKind::NormalBorder { data_handle, .. } => {
let prim_data = &self.normal_border_data_store[data_handle];
let prim_data = &self.normal_border[data_handle];
&prim_data.common
}
PrimitiveInstanceKind::Picture { data_handle, .. } => {
let prim_data = &self.picture_data_store[data_handle];
let prim_data = &self.picture[data_handle];
&prim_data.common
}
PrimitiveInstanceKind::RadialGradient { data_handle, .. } => {
let prim_data = &self.radial_grad_data_store[data_handle];
let prim_data = &self.radial_grad[data_handle];
&prim_data.common
}
PrimitiveInstanceKind::TextRun { data_handle, .. } => {
let prim_data = &self.text_run_data_store[data_handle];
let prim_data = &self.text_run[data_handle];
&prim_data.common
}
PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
let prim_data = &self.yuv_image_data_store[data_handle];
let prim_data = &self.yuv_image[data_handle];
&prim_data.common
}
}
@ -333,7 +340,7 @@ struct Document {
// renderer.
has_built_scene: bool,
resources: FrameResources,
data_stores: DataStores,
/// Contains various vecs of data that is used only during frame building,
/// where we want to recycle the memory each new display list, to avoid constantly
@ -370,7 +377,7 @@ impl Document {
hit_tester_is_valid: false,
rendered_frame_is_valid: false,
has_built_scene: false,
resources: FrameResources::default(),
data_stores: DataStores::default(),
scratch: PrimitiveScratchBuffer::new(),
}
}
@ -512,13 +519,13 @@ impl Document {
&mut resource_profile.texture_cache,
&mut resource_profile.gpu_cache,
&self.dynamic_properties,
&mut self.resources,
&mut self.data_stores,
&mut self.scratch,
debug_flags,
);
self.hit_tester = Some(frame_builder.create_hit_tester(
&self.clip_scroll_tree,
&self.resources.clip_data_store,
&self.data_stores.clip,
));
frame
};
@ -548,7 +555,7 @@ impl Document {
self.hit_tester = Some(frame_builder.create_hit_tester(
&self.clip_scroll_tree,
&self.resources.clip_data_store,
&self.data_stores.clip,
));
self.hit_tester_is_valid = true;
}
@ -886,7 +893,7 @@ impl RenderBackend {
self.update_document(
txn.document_id,
replace(&mut txn.resource_updates, Vec::new()),
txn.doc_resource_updates.take(),
txn.interner_updates.take(),
replace(&mut txn.frame_ops, Vec::new()),
replace(&mut txn.notifications, Vec::new()),
txn.render_frame,
@ -1270,7 +1277,7 @@ impl RenderBackend {
&mut self,
document_id: DocumentId,
resource_updates: Vec<ResourceUpdate>,
doc_resource_updates: Option<DocumentResourceUpdates>,
interner_updates: Option<InternerUpdates>,
mut frame_ops: Vec<FrameMsg>,
mut notifications: Vec<NotificationRequest>,
mut render_frame: bool,
@ -1297,51 +1304,8 @@ impl RenderBackend {
// If there are any additions or removals of clip modes
// during the scene build, apply them to the data store now.
if let Some(updates) = doc_resource_updates {
doc.resources.clip_data_store.apply_updates(
updates.clip_updates,
&mut profile_counters.intern.clips,
);
doc.resources.prim_data_store.apply_updates(
updates.prim_updates,
&mut profile_counters.intern.prims,
);
doc.resources.image_data_store.apply_updates(
updates.image_updates,
&mut profile_counters.intern.images,
);
doc.resources.image_border_data_store.apply_updates(
updates.image_border_updates,
&mut profile_counters.intern.image_borders,
);
doc.resources.line_decoration_data_store.apply_updates(
updates.line_decoration_updates,
&mut profile_counters.intern.line_decs,
);
doc.resources.linear_grad_data_store.apply_updates(
updates.linear_grad_updates,
&mut profile_counters.intern.linear_gradients,
);
doc.resources.normal_border_data_store.apply_updates(
updates.normal_border_updates,
&mut profile_counters.intern.normal_borders,
);
doc.resources.picture_data_store.apply_updates(
updates.picture_updates,
&mut profile_counters.intern.pictures,
);
doc.resources.radial_grad_data_store.apply_updates(
updates.radial_grad_updates,
&mut profile_counters.intern.radial_gradients,
);
doc.resources.text_run_data_store.apply_updates(
updates.text_run_updates,
&mut profile_counters.intern.text_runs,
);
doc.resources.yuv_image_data_store.apply_updates(
updates.yuv_image_updates,
&mut profile_counters.intern.yuv_images,
);
if let Some(updates) = interner_updates {
doc.data_stores.apply_updates(updates, profile_counters);
}
// TODO: this scroll variable doesn't necessarily mean we scrolled. It is only used
@ -1564,7 +1528,7 @@ impl RenderBackend {
}
report.hit_testers += doc.hit_tester.size_of(ops);
doc.resources.report_memory(ops, &mut report)
doc.data_stores.report_memory(ops, &mut report)
}
report += self.resource_cache.report_memory(op);
@ -1673,8 +1637,8 @@ impl RenderBackend {
config.serialize_tree(&doc.clip_scroll_tree, file_name);
}
let frame_resources_name = format!("frame-resources-{}-{}", (id.0).0, id.1);
config.serialize(&doc.resources, frame_resources_name);
let data_stores_name = format!("data-stores-{}-{}", (id.0).0, id.1);
config.serialize(&doc.data_stores, data_stores_name);
}
debug!("\tscene builder");
@ -1758,13 +1722,13 @@ impl RenderBackend {
let scene = CaptureConfig::deserialize::<Scene, _>(root, &scene_name)
.expect(&format!("Unable to open {}.ron", scene_name));
let doc_resources_name = format!("doc-resources-{}-{}", (id.0).0, id.1);
let doc_resources = CaptureConfig::deserialize::<DocumentResources, _>(root, &doc_resources_name)
.expect(&format!("Unable to open {}.ron", doc_resources_name));
let interners_name = format!("interners-{}-{}", (id.0).0, id.1);
let interners = CaptureConfig::deserialize::<Interners, _>(root, &interners_name)
.expect(&format!("Unable to open {}.ron", interners_name));
let frame_resources_name = format!("frame-resources-{}-{}", (id.0).0, id.1);
let frame_resources = CaptureConfig::deserialize::<FrameResources, _>(root, &frame_resources_name)
.expect(&format!("Unable to open {}.ron", frame_resources_name));
let data_stores_name = format!("data-stores-{}-{}", (id.0).0, id.1);
let data_stores = CaptureConfig::deserialize::<DataStores, _>(root, &data_stores_name)
.expect(&format!("Unable to open {}.ron", data_stores_name));
let mut doc = Document {
scene: scene.clone(),
@ -1780,7 +1744,7 @@ impl RenderBackend {
hit_tester_is_valid: false,
rendered_frame_is_valid: false,
has_built_scene: false,
resources: frame_resources,
data_stores,
scratch: PrimitiveScratchBuffer::new(),
};
@ -1819,7 +1783,7 @@ impl RenderBackend {
output_pipelines: doc.output_pipelines.clone(),
font_instances: self.resource_cache.get_font_instances(),
build_frame,
doc_resources,
interners,
});
self.documents.insert(id, doc);

View File

@ -4251,7 +4251,7 @@ impl Renderer {
for item in items {
match item {
DebugItem::Rect { rect, color } => {
let inner_color = color.scale_alpha(0.1).into();
let inner_color = color.scale_alpha(0.5).into();
let outer_color = (*color).into();
debug_renderer.add_quad(

View File

@ -10,31 +10,20 @@ use api::channel::MsgSender;
#[cfg(feature = "capture")]
use capture::CaptureConfig;
use frame_builder::{FrameBuilderConfig, FrameBuilder};
use clip::{ClipDataInterner, ClipDataUpdateList};
use clip_scroll_tree::ClipScrollTree;
use display_list_flattener::DisplayListFlattener;
use intern::{Internable, Interner};
use intern_types;
use internal_types::{FastHashMap, FastHashSet};
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use prim_store::{PrimitiveDataInterner, PrimitiveDataUpdateList, PrimitiveKeyKind};
use prim_store::{PrimitiveKeyKind};
use prim_store::PrimitiveStoreStats;
use prim_store::borders::{
ImageBorder, ImageBorderDataInterner, ImageBorderDataUpdateList,
NormalBorderPrim, NormalBorderDataInterner, NormalBorderDataUpdateList
};
use prim_store::gradient::{
LinearGradient, LinearGradientDataInterner, LinearGradientDataUpdateList,
RadialGradient, RadialGradientDataInterner, RadialGradientDataUpdateList
};
use prim_store::image::{
Image, ImageDataInterner, ImageDataUpdateList,
YuvImage, YuvImageDataInterner, YuvImageDataUpdateList,
};
use prim_store::line_dec::{
LineDecoration, LineDecorationDataInterner, LineDecorationDataUpdateList
};
use prim_store::picture::{PictureDataInterner, Picture, PictureDataUpdateList};
use prim_store::text_run::{TextRunDataInterner, TextRun, TextRunDataUpdateList};
use prim_store::borders::{ImageBorder, NormalBorderPrim};
use prim_store::gradient::{LinearGradient, RadialGradient};
use prim_store::image::{Image, YuvImage};
use prim_store::line_dec::LineDecoration;
use prim_store::picture::Picture;
use prim_store::text_run::TextRun;
use resource_cache::{AsyncBlobImageInfo, FontInstanceMap};
use render_backend::DocumentView;
use renderer::{PipelineInfo, SceneBuilderHooks};
@ -46,20 +35,6 @@ use util::drain_filter;
use std::thread;
use std::time::Duration;
pub struct DocumentResourceUpdates {
pub clip_updates: ClipDataUpdateList,
pub prim_updates: PrimitiveDataUpdateList,
pub image_updates: ImageDataUpdateList,
pub image_border_updates: ImageBorderDataUpdateList,
pub line_decoration_updates: LineDecorationDataUpdateList,
pub linear_grad_updates: LinearGradientDataUpdateList,
pub normal_border_updates: NormalBorderDataUpdateList,
pub picture_updates: PictureDataUpdateList,
pub radial_grad_updates: RadialGradientDataUpdateList,
pub text_run_updates: TextRunDataUpdateList,
pub yuv_image_updates: YuvImageDataUpdateList,
}
/// Represents the work associated to a transaction before scene building.
pub struct Transaction {
pub document_id: DocumentId,
@ -117,7 +92,7 @@ pub struct BuiltTransaction {
pub frame_ops: Vec<FrameMsg>,
pub removed_pipelines: Vec<PipelineId>,
pub notifications: Vec<NotificationRequest>,
pub doc_resource_updates: Option<DocumentResourceUpdates>,
pub interner_updates: Option<InternerUpdates>,
pub scene_build_start_time: u64,
pub scene_build_end_time: u64,
pub render_frame: bool,
@ -149,7 +124,7 @@ pub struct LoadScene {
pub view: DocumentView,
pub config: FrameBuilderConfig,
pub build_frame: bool,
pub doc_resources: DocumentResources,
pub interners: Interners,
}
pub struct BuiltScene {
@ -194,8 +169,8 @@ pub enum SceneSwapResult {
Aborted,
}
macro_rules! declare_document_resources {
( $( { $interner_ident: ident, $interner_type: ty, $x: ident, $y: ty } )+ ) => {
macro_rules! declare_interners {
( $( $name: ident, )+ ) => {
/// This struct contains all items that can be shared between
/// display lists. We want to intern and share the same clips,
/// primitives and other things between display lists so that:
@ -205,13 +180,19 @@ macro_rules! declare_document_resources {
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Default)]
pub struct DocumentResources {
pub struct Interners {
$(
pub $interner_ident: $interner_type,
pub $name: intern_types::$name::Interner,
)+
}
impl DocumentResources {
pub struct InternerUpdates {
$(
pub $name: intern_types::$name::UpdateList,
)+
}
impl Interners {
/// Reports CPU heap memory used by the interners.
fn report_memory(
&self,
@ -219,24 +200,32 @@ macro_rules! declare_document_resources {
r: &mut MemoryReport,
) {
$(
r.interning.$interner_ident += self.$interner_ident.size_of(ops);
r.interning.interners.$name += self.$name.size_of(ops);
)+
}
fn end_frame_and_get_pending_updates(&mut self) -> InternerUpdates {
InternerUpdates {
$(
$name: self.$name.end_frame_and_get_pending_updates(),
)+
}
}
}
}
}
enumerate_interners!(declare_document_resources);
enumerate_interners!(declare_interners);
// Access to `DocumentResources` interners by `Internable`
// Access to `Interners` interners by `Internable`
pub trait InternerMut<I: Internable>
{
fn interner_mut(&mut self) -> &mut Interner<I::Source, I::InternData, I::Marker>;
}
macro_rules! impl_internet_mut {
macro_rules! impl_interner_mut {
($($ty:ident: $mem:ident,)*) => {
$(impl InternerMut<$ty> for DocumentResources {
$(impl InternerMut<$ty> for Interners {
fn interner_mut(&mut self) -> &mut Interner<
<$ty as Internable>::Source,
<$ty as Internable>::InternData,
@ -248,17 +237,17 @@ macro_rules! impl_internet_mut {
}
}
impl_internet_mut! {
Image: image_interner,
ImageBorder: image_border_interner,
LineDecoration: line_decoration_interner,
LinearGradient: linear_grad_interner,
NormalBorderPrim: normal_border_interner,
Picture: picture_interner,
PrimitiveKeyKind: prim_interner,
RadialGradient: radial_grad_interner,
TextRun: text_run_interner,
YuvImage: yuv_image_interner,
impl_interner_mut! {
Image: image,
ImageBorder: image_border,
LineDecoration: line_decoration,
LinearGradient: linear_grad,
NormalBorderPrim: normal_border,
Picture: picture,
PrimitiveKeyKind: prim,
RadialGradient: radial_grad,
TextRun: text_run,
YuvImage: yuv_image,
}
// A document in the scene builder contains the current scene,
@ -267,7 +256,7 @@ impl_internet_mut! {
// display lists.
struct Document {
scene: Scene,
resources: DocumentResources,
interners: Interners,
prim_store_stats: PrimitiveStoreStats,
}
@ -275,7 +264,7 @@ impl Document {
fn new(scene: Scene) -> Self {
Document {
scene,
resources: DocumentResources::default(),
interners: Interners::default(),
prim_store_stats: PrimitiveStoreStats::empty(),
}
}
@ -395,8 +384,8 @@ impl SceneBuilder {
#[cfg(feature = "capture")]
fn save_scene(&mut self, config: CaptureConfig) {
for (id, doc) in &self.documents {
let doc_resources_name = format!("doc-resources-{}-{}", (id.0).0, id.1);
config.serialize(&doc.resources, doc_resources_name);
let interners_name = format!("interners-{}-{}", (id.0).0, id.1);
config.serialize(&doc.interners, interners_name);
}
}
@ -408,7 +397,7 @@ impl SceneBuilder {
let scene_build_start_time = precise_time_ns();
let mut built_scene = None;
let mut doc_resource_updates = None;
let mut interner_updates = None;
if item.scene.has_root_pipeline() {
let mut clip_scroll_tree = ClipScrollTree::new();
@ -422,81 +411,12 @@ impl SceneBuilder {
&item.output_pipelines,
&self.config,
&mut new_scene,
&mut item.doc_resources,
&mut item.interners,
&PrimitiveStoreStats::empty(),
);
// TODO(djg): Can we do better than this? Use a #[derive] to
// write the code for us, or unify updates into one enum/list?
let clip_updates = item
.doc_resources
.clip_interner
.end_frame_and_get_pending_updates();
let prim_updates = item
.doc_resources
.prim_interner
.end_frame_and_get_pending_updates();
let image_updates = item
.doc_resources
.image_interner
.end_frame_and_get_pending_updates();
let image_border_updates = item
.doc_resources
.image_border_interner
.end_frame_and_get_pending_updates();
let line_decoration_updates = item
.doc_resources
.line_decoration_interner
.end_frame_and_get_pending_updates();
let linear_grad_updates = item
.doc_resources
.linear_grad_interner
.end_frame_and_get_pending_updates();
let normal_border_updates = item
.doc_resources
.normal_border_interner
.end_frame_and_get_pending_updates();
let picture_updates = item
.doc_resources
.picture_interner
.end_frame_and_get_pending_updates();
let radial_grad_updates = item
.doc_resources
.radial_grad_interner
.end_frame_and_get_pending_updates();
let text_run_updates = item
.doc_resources
.text_run_interner
.end_frame_and_get_pending_updates();
let yuv_image_updates = item
.doc_resources
.yuv_image_interner
.end_frame_and_get_pending_updates();
doc_resource_updates = Some(
DocumentResourceUpdates {
clip_updates,
prim_updates,
image_updates,
image_border_updates,
line_decoration_updates,
linear_grad_updates,
normal_border_updates,
picture_updates,
radial_grad_updates,
text_run_updates,
yuv_image_updates,
}
interner_updates = Some(
item.interners.end_frame_and_get_pending_updates()
);
built_scene = Some(BuiltScene {
@ -510,7 +430,7 @@ impl SceneBuilder {
item.document_id,
Document {
scene: item.scene,
resources: item.doc_resources,
interners: item.interners,
prim_store_stats: PrimitiveStoreStats::empty(),
},
);
@ -528,7 +448,7 @@ impl SceneBuilder {
notifications: Vec::new(),
scene_build_start_time,
scene_build_end_time: precise_time_ns(),
doc_resource_updates,
interner_updates,
});
self.forward_built_transaction(txn);
@ -572,7 +492,7 @@ impl SceneBuilder {
}
let mut built_scene = None;
let mut doc_resource_updates = None;
let mut interner_updates = None;
if scene.has_root_pipeline() {
if let Some(request) = txn.request_scene_build.take() {
let mut clip_scroll_tree = ClipScrollTree::new();
@ -586,7 +506,7 @@ impl SceneBuilder {
&request.output_pipelines,
&self.config,
&mut new_scene,
&mut doc.resources,
&mut doc.interners,
&doc.prim_store_stats,
);
@ -594,75 +514,8 @@ impl SceneBuilder {
doc.prim_store_stats = frame_builder.prim_store.get_stats();
// Retrieve the list of updates from the clip interner.
let clip_updates = doc
.resources
.clip_interner
.end_frame_and_get_pending_updates();
let prim_updates = doc
.resources
.prim_interner
.end_frame_and_get_pending_updates();
let image_updates = doc
.resources
.image_interner
.end_frame_and_get_pending_updates();
let image_border_updates = doc
.resources
.image_border_interner
.end_frame_and_get_pending_updates();
let line_decoration_updates = doc
.resources
.line_decoration_interner
.end_frame_and_get_pending_updates();
let linear_grad_updates = doc
.resources
.linear_grad_interner
.end_frame_and_get_pending_updates();
let normal_border_updates = doc
.resources
.normal_border_interner
.end_frame_and_get_pending_updates();
let picture_updates = doc
.resources
.picture_interner
.end_frame_and_get_pending_updates();
let radial_grad_updates = doc
.resources
.radial_grad_interner
.end_frame_and_get_pending_updates();
let text_run_updates = doc
.resources
.text_run_interner
.end_frame_and_get_pending_updates();
let yuv_image_updates = doc
.resources
.yuv_image_interner
.end_frame_and_get_pending_updates();
doc_resource_updates = Some(
DocumentResourceUpdates {
clip_updates,
prim_updates,
image_updates,
image_border_updates,
line_decoration_updates,
linear_grad_updates,
normal_border_updates,
picture_updates,
radial_grad_updates,
text_run_updates,
yuv_image_updates,
}
interner_updates = Some(
doc.interners.end_frame_and_get_pending_updates()
);
built_scene = Some(BuiltScene {
@ -697,7 +550,7 @@ impl SceneBuilder {
frame_ops: replace(&mut txn.frame_ops, Vec::new()),
removed_pipelines: replace(&mut txn.removed_pipelines, Vec::new()),
notifications: replace(&mut txn.notifications, Vec::new()),
doc_resource_updates,
interner_updates,
scene_build_start_time,
scene_build_end_time: precise_time_ns(),
})
@ -760,7 +613,7 @@ impl SceneBuilder {
let ops = self.size_of_ops.as_mut().unwrap();
let mut report = MemoryReport::default();
for doc in self.documents.values() {
doc.resources.report_memory(ops, &mut report);
doc.interners.report_memory(ops, &mut report);
}
report

View File

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{ExternalScrollId, LayoutPixel, LayoutPoint, LayoutRect, LayoutSize, LayoutTransform};
use api::{LayoutVector2D, PipelineId, PropertyBinding, ScrollClamping, ScrollLocation};
use api::{LayoutVector2D, PipelineId, PropertyBinding, ReferenceFrameKind, ScrollClamping, ScrollLocation};
use api::{TransformStyle, ScrollSensitivity, StickyOffsetBounds};
use clip_scroll_tree::{CoordinateSystem, CoordinateSystemId, SpatialNodeIndex, TransformUpdateState};
use euclid::SideOffsets2D;
@ -116,18 +116,15 @@ impl SpatialNode {
pub fn new_reference_frame(
parent_index: Option<SpatialNodeIndex>,
transform_style: TransformStyle,
source_transform: Option<PropertyBinding<LayoutTransform>>,
source_perspective: Option<LayoutTransform>,
source_transform: PropertyBinding<LayoutTransform>,
kind: ReferenceFrameKind,
origin_in_parent_reference_frame: LayoutVector2D,
pipeline_id: PipelineId,
) -> Self {
let identity = LayoutTransform::identity();
let source_perspective = source_perspective.map_or_else(
LayoutFastTransform::identity, |perspective| perspective.into());
let info = ReferenceFrameInfo {
transform_style,
source_transform: source_transform.unwrap_or(PropertyBinding::Value(identity)),
source_perspective,
source_transform,
kind,
origin_in_parent_reference_frame,
invertible: true,
};
@ -142,7 +139,6 @@ impl SpatialNode {
Self::new(pipeline_id, Some(parent_index), SpatialNodeType::StickyFrame(sticky_frame_info))
}
pub fn add_child(&mut self, child: SpatialNodeIndex) {
self.children.push(child);
}
@ -257,17 +253,26 @@ impl SpatialNode {
match self.node_type {
SpatialNodeType::ReferenceFrame(ref mut info) => {
// Resolve the transform against any property bindings.
let source_transform = scene_properties.resolve_layout_transform(&info.source_transform);
let source_transform = LayoutFastTransform::from(
scene_properties.resolve_layout_transform(&info.source_transform)
);
// Do a change-basis operation on the perspective matrix using
// the scroll offset.
let scrolled_perspective = info.source_perspective
.pre_translate(&state.parent_accumulated_scroll_offset)
.post_translate(-state.parent_accumulated_scroll_offset);
let source_transform = match info.kind {
ReferenceFrameKind::Perspective => {
// Do a change-basis operation on the perspective matrix
// using the scroll offset.
source_transform
.pre_translate(&state.parent_accumulated_scroll_offset)
.post_translate(-state.parent_accumulated_scroll_offset)
}
ReferenceFrameKind::Transform => source_transform,
};
let resolved_transform =
LayoutFastTransform::with_vector(info.origin_in_parent_reference_frame)
.pre_mul(&source_transform.into())
.pre_mul(&scrolled_perspective);
.pre_mul(&source_transform);
// The transformation for this viewport in world coordinates is the transformation for
// our parent reference frame, plus any accumulated scrolling offsets from nodes
@ -494,8 +499,8 @@ impl SpatialNode {
state.parent_reference_frame_transform = self.world_viewport_transform;
let should_flatten =
info.transform_style == TransformStyle::Flat &&
info.source_perspective.is_identity();
info.kind == ReferenceFrameKind::Transform &&
info.transform_style == TransformStyle::Flat;
if should_flatten {
state.parent_reference_frame_transform = state.parent_reference_frame_transform.project_to_2d();
@ -661,7 +666,7 @@ pub struct ReferenceFrameInfo {
/// frame.
pub source_transform: PropertyBinding<LayoutTransform>,
pub transform_style: TransformStyle,
pub source_perspective: LayoutFastTransform,
pub kind: ReferenceFrameKind,
/// The original, not including the transform and relative to the parent reference frame,
/// origin of this reference frame. This is already rolled into the `transform' property, but

View File

@ -22,7 +22,7 @@ use pathfinder_partitioner::mesh::Mesh;
use picture::SurfaceInfo;
use prim_store::{PrimitiveStore, DeferredResolve, PrimitiveScratchBuffer};
use profiler::FrameProfileCounters;
use render_backend::{FrameId, FrameResources};
use render_backend::{DataStores, FrameId};
use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
use render_task::{BlurTask, ClearMode, GlyphTask, RenderTaskLocation, RenderTaskTree, ScalingTask};
use resource_cache::ResourceCache;
@ -55,7 +55,7 @@ pub struct RenderTargetContext<'a, 'rc> {
pub resource_cache: &'rc mut ResourceCache,
pub use_dual_source_blending: bool,
pub clip_scroll_tree: &'a ClipScrollTree,
pub resources: &'a FrameResources,
pub data_stores: &'a DataStores,
pub surfaces: &'a [SurfaceInfo],
pub scratch: &'a PrimitiveScratchBuffer,
}
@ -658,7 +658,7 @@ impl RenderTarget for AlphaRenderTarget {
clip_store,
ctx.clip_scroll_tree,
transforms,
&ctx.resources.clip_data_store,
&ctx.data_stores.clip,
);
}
RenderTaskKind::ClipRegion(ref task) => {

Some files were not shown because too many files have changed in this diff Show More