Merge mozilla-central to mozilla-inbound. a=merge
|
@ -8,8 +8,8 @@ const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
var EXPORTED_SYMBOLS = ["BlockedSiteChild"];
|
||||
|
||||
const {ActorChild} = ChromeUtils.import("resource://gre/modules/ActorChild.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "Utils",
|
||||
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "E10SUtils",
|
||||
"resource://gre/modules/E10SUtils.jsm");
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "SafeBrowsing",
|
||||
"resource://gre/modules/SafeBrowsing.jsm");
|
||||
|
@ -31,7 +31,7 @@ function getSiteBlockedErrorDetails(docShell) {
|
|||
.finalize();
|
||||
}
|
||||
|
||||
let triggeringPrincipal = docShell.failedChannel.loadInfo ? Utils.serializePrincipal(docShell.failedChannel.loadInfo.triggeringPrincipal) : null;
|
||||
let triggeringPrincipal = docShell.failedChannel.loadInfo ? E10SUtils.serializePrincipal(docShell.failedChannel.loadInfo.triggeringPrincipal) : null;
|
||||
blockedInfo = { list: classifiedChannel.matchedList,
|
||||
triggeringPrincipal,
|
||||
provider: classifiedChannel.matchedProvider,
|
||||
|
|
|
@ -483,6 +483,9 @@ pref("browser.tabs.newanimations", false);
|
|||
pref("browser.tabs.remote.separatePrivilegedContentProcess", true);
|
||||
#endif
|
||||
|
||||
// Turn on HTTP response process selection.
|
||||
pref("browser.tabs.remote.useHTTPResponseProcessSelection", true);
|
||||
|
||||
pref("browser.ctrlTab.recentlyUsedOrder", true);
|
||||
|
||||
// By default, do not export HTML at shutdown.
|
||||
|
@ -1759,7 +1762,7 @@ pref("app.normandy.first_run", true);
|
|||
pref("app.normandy.logging.level", 50); // Warn
|
||||
pref("app.normandy.run_interval_seconds", 21600); // 6 hours
|
||||
pref("app.normandy.shieldLearnMoreUrl", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/shield");
|
||||
pref("app.normandy.remotesettings.enabled", false);
|
||||
pref("features.normandy-remote-settings.enabled", false);
|
||||
#ifdef MOZ_DATA_REPORTING
|
||||
pref("app.shield.optoutstudies.enabled", true);
|
||||
#else
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
var Fingerprinting = {
|
||||
PREF_ENABLED: "privacy.trackingprotection.fingerprinting.enabled",
|
||||
telemetryIdentifier: "fp",
|
||||
|
||||
strings: {
|
||||
get subViewBlocked() {
|
||||
|
@ -114,6 +115,7 @@ var Fingerprinting = {
|
|||
|
||||
var Cryptomining = {
|
||||
PREF_ENABLED: "privacy.trackingprotection.cryptomining.enabled",
|
||||
telemetryIdentifier: "cm",
|
||||
|
||||
strings: {
|
||||
get subViewBlocked() {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
class="menuitem-iconic"
|
||||
tooltip="dynamic-shortcut-tooltip"
|
||||
aria-label="&reloadCmd.label;"
|
||||
oncommand="gContextMenu.reload(event);"
|
||||
command="Browser:ReloadOrDuplicate"
|
||||
accesskey="&reloadCmd.accesskey;"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-stop"
|
||||
|
|
|
@ -69,7 +69,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
UrlbarTokenizer: "resource:///modules/UrlbarTokenizer.jsm",
|
||||
UrlbarUtils: "resource:///modules/UrlbarUtils.jsm",
|
||||
UrlbarValueFormatter: "resource:///modules/UrlbarValueFormatter.jsm",
|
||||
Utils: "resource://gre/modules/sessionstore/Utils.jsm",
|
||||
Weave: "resource://services-sync/main.js",
|
||||
WebNavigationFrames: "resource://gre/modules/WebNavigationFrames.jsm",
|
||||
fxAccounts: "resource://gre/modules/FxAccounts.jsm",
|
||||
|
@ -2060,6 +2059,8 @@ function HandleAppCommandEvent(evt) {
|
|||
}
|
||||
|
||||
function gotoHistoryIndex(aEvent) {
|
||||
aEvent = getRootEvent(aEvent);
|
||||
|
||||
let index = aEvent.target.getAttribute("index");
|
||||
if (!index)
|
||||
return false;
|
||||
|
@ -2136,6 +2137,7 @@ function BrowserStop() {
|
|||
}
|
||||
|
||||
function BrowserReloadOrDuplicate(aEvent) {
|
||||
aEvent = getRootEvent(aEvent);
|
||||
let metaKeyPressed = AppConstants.platform == "macosx"
|
||||
? aEvent.metaKey
|
||||
: aEvent.ctrlKey;
|
||||
|
@ -2174,7 +2176,7 @@ function BrowserHome(aEvent) {
|
|||
aEvent.button == 2) // right-click: do nothing
|
||||
return;
|
||||
|
||||
var homePage = HomePage.get();
|
||||
var homePage = HomePage.get(window);
|
||||
var where = whereToOpenLink(aEvent, false, true);
|
||||
var urls;
|
||||
var notifyObservers;
|
||||
|
@ -3105,7 +3107,7 @@ var BrowserOnClick = {
|
|||
},
|
||||
|
||||
ignoreWarningLink(reason, blockedInfo) {
|
||||
let triggeringPrincipal = Utils.deserializePrincipal(blockedInfo.triggeringPrincipal) || _createNullPrincipalFromTabUserContextId();
|
||||
let triggeringPrincipal = E10SUtils.deserializePrincipal(blockedInfo.triggeringPrincipal) || _createNullPrincipalFromTabUserContextId();
|
||||
// Allow users to override and continue through to the site,
|
||||
// but add a notify bar as a reminder, so that they don't lose
|
||||
// track after, e.g., tab switching.
|
||||
|
|
|
@ -880,10 +880,6 @@ nsContextMenu.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
reload(event) {
|
||||
BrowserReloadOrDuplicate(event);
|
||||
},
|
||||
|
||||
// View Partial Source
|
||||
viewPartialSource() {
|
||||
let {browser} = this;
|
||||
|
|
|
@ -2554,7 +2554,7 @@ window._gBrowser = {
|
|||
entries: [{
|
||||
url: lazyBrowserURI ? lazyBrowserURI.spec : "about:blank",
|
||||
title: lazyTabTitle,
|
||||
triggeringPrincipal_base64: Utils.serializePrincipal(triggeringPrincipal),
|
||||
triggeringPrincipal_base64: E10SUtils.serializePrincipal(triggeringPrincipal),
|
||||
}],
|
||||
});
|
||||
} else {
|
||||
|
@ -5599,7 +5599,7 @@ var TabContextMenu = {
|
|||
// from SessionStore
|
||||
let tabState = JSON.parse(SessionStore.getTabState(tab));
|
||||
try {
|
||||
triggeringPrincipal = Utils.deserializePrincipal(tabState.triggeringPrincipal_base64);
|
||||
triggeringPrincipal = E10SUtils.deserializePrincipal(tabState.triggeringPrincipal_base64);
|
||||
} catch (ex) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ skip-if = (os == "linux" && (debug || asan))
|
|||
skip-if = (os == "linux" && (debug || asan))
|
||||
[browser_popupNotification_keyboard.js]
|
||||
skip-if = (os == "linux" && (debug || asan))
|
||||
[browser_popupNotification_learnmore.js]
|
||||
skip-if = (os == "linux" && (debug || asan))
|
||||
[browser_popupNotification_no_anchors.js]
|
||||
skip-if = (os == "linux" && (debug || asan))
|
||||
[browser_reshow_in_background.js]
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/* 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/. */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
ok(PopupNotifications, "PopupNotifications object exists");
|
||||
ok(PopupNotifications.panel, "PopupNotifications panel exists");
|
||||
|
||||
setup();
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test checkbox being checked by default
|
||||
{ id: "without_learn_more",
|
||||
run() {
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
showNotification(this.notifyObj);
|
||||
},
|
||||
onShown(popup) {
|
||||
checkPopup(popup, this.notifyObj);
|
||||
let notification = popup.children[0];
|
||||
let link = notification.querySelector(".popup-notification-learnmore-link");
|
||||
ok(!link.href, "no href");
|
||||
is(window.getComputedStyle(link).getPropertyValue("display"), "none", "link hidden");
|
||||
dismissNotification(popup);
|
||||
},
|
||||
onHidden() { },
|
||||
},
|
||||
|
||||
// Test that passing the learnMoreURL field sets up the link.
|
||||
{ id: "with_learn_more",
|
||||
run() {
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
this.notifyObj.options.learnMoreURL = "https://mozilla.org";
|
||||
showNotification(this.notifyObj);
|
||||
},
|
||||
onShown(popup) {
|
||||
checkPopup(popup, this.notifyObj);
|
||||
let notification = popup.children[0];
|
||||
let link = notification.querySelector(".popup-notification-learnmore-link");
|
||||
is(link.textContent, "Learn more…", "correct label");
|
||||
is(link.href, "https://mozilla.org", "correct href");
|
||||
isnot(window.getComputedStyle(link).getPropertyValue("display"), "none", "link not hidden");
|
||||
dismissNotification(popup);
|
||||
},
|
||||
onHidden() { },
|
||||
},
|
||||
];
|
|
@ -69,10 +69,8 @@ var whitelist = [
|
|||
// See bug 1339424 for why this is hard to fix.
|
||||
{file: "chrome://global/locale/fallbackMenubar.properties",
|
||||
platforms: ["linux", "win"]},
|
||||
{file: "chrome://global/locale/printPageSetup.dtd", platforms: ["linux", "macosx"]},
|
||||
{file: "chrome://global/locale/printPreviewProgress.dtd",
|
||||
{file: "resource://gre/localization/en-US/toolkit/printing/printDialogs.ftl",
|
||||
platforms: ["macosx"]},
|
||||
{file: "chrome://global/locale/printProgress.dtd", platforms: ["macosx"]},
|
||||
|
||||
// toolkit/content/aboutRights-unbranded.xhtml doesn't use aboutRights.css
|
||||
{file: "chrome://global/skin/aboutRights.css", skipUnofficial: true},
|
||||
|
|
|
@ -69,21 +69,21 @@ add_task(async function testLazyTabs() {
|
|||
}
|
||||
|
||||
let tabsMoved = new Promise(resolve => {
|
||||
// Tab tabs in the new window will be about:blank before swapping the docshells.
|
||||
// The "EndSwapDocShells" event is not dispatched for lazy tabs, so listen for
|
||||
// "TabClose" instead and await a tick.
|
||||
let numTabsMoved = 0;
|
||||
window.addEventListener("TabClose", async function listener(event) {
|
||||
let tab = event.target;
|
||||
let i = oldTabs.indexOf(tab);
|
||||
let oldTab = event.target;
|
||||
let i = oldTabs.indexOf(oldTab);
|
||||
if (i == 0) {
|
||||
isnot(tab.linkedPanel, "", `Old tab ${i} should continue not being lazy`);
|
||||
isnot(oldTab.linkedPanel, "", `Old tab ${i} should continue not being lazy`);
|
||||
} else if (i > 0) {
|
||||
is(tab.linkedPanel, "", `Old tab ${i} should continue being lazy`);
|
||||
is(oldTab.linkedPanel, "", `Old tab ${i} should continue being lazy`);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
await Promise.resolve();
|
||||
let newTab = event.detail.adoptedBy;
|
||||
await TestUtils.waitForCondition(() => {
|
||||
return newTab.linkedBrowser.currentURI.spec != "about:blank";
|
||||
}, `Wait for the new tab to finish the adoption of the old tab`);
|
||||
if (++numTabsMoved == numTabs) {
|
||||
window.removeEventListener("TabClose", listener);
|
||||
resolve();
|
||||
|
|
|
@ -6,9 +6,10 @@ ChromeUtils.defineModuleGetter(this, "SessionStore",
|
|||
"resource:///modules/sessionstore/SessionStore.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "TabStateFlusher",
|
||||
"resource:///modules/sessionstore/TabStateFlusher.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "E10SUtils",
|
||||
"resource://gre/modules/E10SUtils.jsm");
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm", this);
|
||||
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
|
||||
function promiseBrowserStateRestored(state) {
|
||||
if (typeof state != "string") {
|
||||
|
|
|
@ -24,10 +24,19 @@ XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
|
|||
Object.defineProperty(this, "BROWSER_NEW_TAB_URL", {
|
||||
enumerable: true,
|
||||
get() {
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(window) &&
|
||||
!PrivateBrowsingUtils.permanentPrivateBrowsing &&
|
||||
!aboutNewTabService.overridden) {
|
||||
return "about:privatebrowsing";
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
|
||||
if (!PrivateBrowsingUtils.permanentPrivateBrowsing &&
|
||||
!aboutNewTabService.overridden) {
|
||||
return "about:privatebrowsing";
|
||||
}
|
||||
// If the extension does not have private browsing permission,
|
||||
// use about:privatebrowsing.
|
||||
if (aboutNewTabService.newTabURL.startsWith("moz-extension")) {
|
||||
let url = new URL(aboutNewTabService.newTabURL);
|
||||
if (!WebExtensionPolicy.getByHostname(url.hostname).privateBrowsingAllowed) {
|
||||
return "about:privatebrowsing";
|
||||
}
|
||||
}
|
||||
}
|
||||
return aboutNewTabService.newTabURL;
|
||||
},
|
||||
|
@ -86,6 +95,7 @@ function doGetProtocolFlags(aURI) {
|
|||
*/
|
||||
function openUILink(url, event, aIgnoreButton, aIgnoreAlt, aAllowThirdPartyFixup,
|
||||
aPostData, aReferrerURI) {
|
||||
event = getRootEvent(event);
|
||||
let params;
|
||||
|
||||
if (aIgnoreButton && typeof aIgnoreButton == "object") {
|
||||
|
@ -115,6 +125,26 @@ function openUILink(url, event, aIgnoreButton, aIgnoreAlt, aAllowThirdPartyFixup
|
|||
}
|
||||
|
||||
|
||||
// Utility function to check command events for potential middle-click events
|
||||
// from checkForMiddleClick and unwrap them.
|
||||
function getRootEvent(aEvent) {
|
||||
// Part of the fix for Bug 1523813.
|
||||
// Middle-click events arrive here wrapped in different numbers (1-2) of
|
||||
// command events, depending on the button originally clicked.
|
||||
if (!aEvent) {
|
||||
return aEvent;
|
||||
}
|
||||
let tempEvent = aEvent;
|
||||
while (tempEvent.sourceEvent) {
|
||||
if (tempEvent.sourceEvent.button == 1) {
|
||||
aEvent = tempEvent.sourceEvent;
|
||||
break;
|
||||
}
|
||||
tempEvent = tempEvent.sourceEvent;
|
||||
}
|
||||
return aEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* whereToOpenLink() looks at an event to decide where to open a link.
|
||||
*
|
||||
|
@ -147,6 +177,8 @@ function whereToOpenLink(e, ignoreButton, ignoreAlt) {
|
|||
if (!e)
|
||||
return "current";
|
||||
|
||||
e = getRootEvent(e);
|
||||
|
||||
var shift = e.shiftKey;
|
||||
var ctrl = e.ctrlKey;
|
||||
var meta = e.metaKey;
|
||||
|
@ -592,13 +624,13 @@ function checkForMiddleClick(node, event) {
|
|||
|
||||
if (event.button == 1) {
|
||||
/* Execute the node's oncommand or command.
|
||||
*
|
||||
* XXX: we should use node.oncommand(event) once bug 246720 is fixed.
|
||||
*/
|
||||
var target = node.hasAttribute("oncommand") ? node :
|
||||
node.ownerDocument.getElementById(node.getAttribute("command"));
|
||||
var fn = new Function("event", target.getAttribute("oncommand"));
|
||||
fn.call(target, event);
|
||||
|
||||
let cmdEvent = document.createEvent("xulcommandevent");
|
||||
cmdEvent.initCommandEvent("command", true, true, window, 0,
|
||||
event.ctrlKey, event.altKey, event.shiftKey,
|
||||
event.metaKey, event, event.mozInputSource);
|
||||
node.dispatchEvent(cmdEvent);
|
||||
|
||||
// If the middle-click was on part of a menu, close the menu.
|
||||
// (Menus close automatically with left-click but not with middle-click.)
|
||||
|
|
|
@ -209,7 +209,7 @@ function openBrowserWindow(cmdLine, triggeringPrincipal, urlOrUrlList, postData
|
|||
let args;
|
||||
if (!urlOrUrlList) {
|
||||
// Just pass in the defaultArgs directly. We'll use system principal on the other end.
|
||||
args = [gBrowserContentHandler.defaultArgs];
|
||||
args = [gBrowserContentHandler.getDefaultArgs(forcePrivate)];
|
||||
} else {
|
||||
let pService = Cc["@mozilla.org/toolkit/profile-service;1"].
|
||||
getService(Ci.nsIToolkitProfileService);
|
||||
|
@ -518,7 +518,7 @@ nsBrowserContentHandler.prototype = {
|
|||
|
||||
/* nsIBrowserHandler */
|
||||
|
||||
get defaultArgs() {
|
||||
getDefaultArgs(forcePrivate = false) {
|
||||
var prefb = Services.prefs;
|
||||
|
||||
if (!gFirstWindow) {
|
||||
|
@ -603,7 +603,7 @@ nsBrowserContentHandler.prototype = {
|
|||
try {
|
||||
var choice = prefb.getIntPref("browser.startup.page");
|
||||
if (choice == 1 || choice == 3)
|
||||
startPage = HomePage.get();
|
||||
startPage = forcePrivate ? HomePage.getPrivate() : HomePage.get();
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
@ -621,6 +621,10 @@ nsBrowserContentHandler.prototype = {
|
|||
return overridePage || startPage || "about:blank";
|
||||
},
|
||||
|
||||
get defaultArgs() {
|
||||
return this.getDefaultArgs(PrivateBrowsingUtils.permanentPrivateBrowsing);
|
||||
},
|
||||
|
||||
mFeatures: null,
|
||||
|
||||
getFeatures: function bch_features(cmdLine) {
|
||||
|
|
|
@ -1406,6 +1406,12 @@ BrowserGlue.prototype = {
|
|||
}
|
||||
}
|
||||
Services.telemetry.scalarSet("contentblocking.exceptions", exceptions);
|
||||
|
||||
let fpEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.fingerprinting.enabled");
|
||||
let cmEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.cryptomining.enabled");
|
||||
|
||||
Services.telemetry.scalarSet("contentblocking.fingerprinting_blocking_enabled", fpEnabled);
|
||||
Services.telemetry.scalarSet("contentblocking.cryptomining_blocking_enabled", cmEnabled);
|
||||
},
|
||||
|
||||
_sendMediaTelemetry() {
|
||||
|
|
|
@ -328,6 +328,7 @@ var Policies = {
|
|||
onBeforeAddons(manager, param) {
|
||||
if (param) {
|
||||
manager.disallowFeature("Shield");
|
||||
setAndLockPref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr", false);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -682,6 +683,7 @@ var Policies = {
|
|||
setAndLockPref("xpinstall.enabled", param.Default);
|
||||
if (!param.Default) {
|
||||
blockAboutPage(manager, "about:debugging");
|
||||
setAndLockPref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr", false);
|
||||
manager.disallowFeature("xpinstall");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,6 +151,7 @@ const POLICIES_TESTS = [
|
|||
},
|
||||
lockedPrefs: {
|
||||
"xpinstall.enabled": false,
|
||||
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr": false,
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -255,6 +256,16 @@ const POLICIES_TESTS = [
|
|||
"extensions.update.enabled": false,
|
||||
},
|
||||
},
|
||||
|
||||
// POLICY: DisableShield
|
||||
{
|
||||
policies: {
|
||||
"DisableFirefoxStudies": true,
|
||||
},
|
||||
lockedPrefs: {
|
||||
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr": false,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
add_task(async function test_policy_remember_passwords() {
|
||||
|
|
|
@ -31,6 +31,8 @@ ChromeUtils.defineModuleGetter(this, "CustomizableUI",
|
|||
"resource:///modules/CustomizableUI.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
|
||||
"resource://gre/modules/ExtensionSettingsStore.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
let {
|
||||
makeWidgetId,
|
||||
|
@ -195,6 +197,12 @@ class ExtensionControlledPopup {
|
|||
extensionId = item && item.id;
|
||||
}
|
||||
|
||||
let win = targetWindow || this.topWindow;
|
||||
let isPrivate = PrivateBrowsingUtils.isWindowPrivate(win);
|
||||
if (isPrivate && extensionId && !WebExtensionPolicy.getByID(extensionId).privateBrowsingAllowed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The item should have an extension and the user shouldn't have confirmed
|
||||
// the change here, but just to be sure check that it is still controlled
|
||||
// and the user hasn't already confirmed the change.
|
||||
|
@ -203,7 +211,6 @@ class ExtensionControlledPopup {
|
|||
return;
|
||||
}
|
||||
|
||||
let win = targetWindow || this.topWindow;
|
||||
// If the window closes while waiting for focus, this might reject/throw,
|
||||
// and we should stop trying to show the popup.
|
||||
try {
|
||||
|
|
|
@ -191,8 +191,13 @@ this.windows = class extends ExtensionAPI {
|
|||
args.appendElement(mkstr(createData.url));
|
||||
}
|
||||
} else {
|
||||
let url = createData.incognito && !PrivateBrowsingUtils.permanentPrivateBrowsing ?
|
||||
"about:privatebrowsing" : HomePage.get().split("|", 1)[0];
|
||||
let url;
|
||||
if (createData.incognito) {
|
||||
url = PrivateBrowsingUtils.permanentPrivateBrowsing ?
|
||||
HomePage.getPrivate().split("|", 1)[0] : "about:privatebrowsing";
|
||||
} else {
|
||||
url = HomePage.get().split("|", 1)[0];
|
||||
}
|
||||
args.appendElement(mkstr(url));
|
||||
|
||||
if (url.startsWith("about:") &&
|
||||
|
|
|
@ -422,3 +422,127 @@ add_task(async function test_doorhanger_new_window() {
|
|||
|
||||
ok(!isConfirmed(ext1Id), "The confirmation is cleaned up on uninstall");
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_home_page_incognito_not_allowed() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
chrome_settings_overrides: {"homepage": "home.html"},
|
||||
name: "extension",
|
||||
},
|
||||
background() {
|
||||
browser.test.sendMessage("url", browser.runtime.getURL("home.html"));
|
||||
},
|
||||
files: {"home.html": "<h1>1</h1>"},
|
||||
useAddonManager: "temporary",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
let url = await extension.awaitMessage("url");
|
||||
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow({url});
|
||||
let win = OpenBrowserWindow();
|
||||
await windowOpenedPromise;
|
||||
let doc = win.document;
|
||||
let description = doc.getElementById("extension-homepage-notification-description");
|
||||
let panel = doc.getElementById("extension-notification-panel");
|
||||
await promisePopupShown(panel);
|
||||
|
||||
let popupnotification = description.closest("popupnotification");
|
||||
is(description.textContent,
|
||||
"An extension, extension, changed what you see when you open your homepage and new windows.Learn more",
|
||||
"The extension name is in the popup");
|
||||
is(popupnotification.hidden, false, "The expected popup notification is visible");
|
||||
|
||||
ok(win.gURLBar.value.endsWith("home.html"), "extension is in control");
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
|
||||
// Verify a private window does not open the extension page.
|
||||
windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
win.BrowserHome();
|
||||
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
|
||||
|
||||
is(win.gURLBar.value, "", "home page not used in private window");
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_home_page_incognito_not_allowed_bypass() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
name: "extension",
|
||||
},
|
||||
background() {
|
||||
browser.test.sendMessage("url", browser.runtime.getURL("home.html"));
|
||||
},
|
||||
files: {"home.html": "<h1>1</h1>"},
|
||||
useAddonManager: "temporary",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
let url = await extension.awaitMessage("url");
|
||||
|
||||
// Verify manually setting the pref to the extension page does not work.
|
||||
let changed = promisePrefChangeObserved(HOMEPAGE_URL_PREF);
|
||||
Services.prefs.setStringPref(HOMEPAGE_URL_PREF, url);
|
||||
await changed;
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
win.BrowserHome();
|
||||
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
|
||||
|
||||
is(win.gURLBar.value, "", "home page not used in private window");
|
||||
changed = promisePrefChangeObserved(HOMEPAGE_URL_PREF);
|
||||
Services.prefs.clearUserPref(HOMEPAGE_URL_PREF);
|
||||
await changed;
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_home_page_incognito_spanning() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
chrome_settings_overrides: {"homepage": "home.html"},
|
||||
name: "private extension",
|
||||
applications: {
|
||||
gecko: {id: "@spanning-home"},
|
||||
},
|
||||
},
|
||||
files: {"home.html": "<h1>1</h1>"},
|
||||
useAddonManager: "permanent",
|
||||
incognitoOverride: "spanning",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
let doc = win.document;
|
||||
let panel = doc.getElementById("extension-notification-panel");
|
||||
|
||||
let popupShown = promisePopupShown(panel);
|
||||
win.BrowserHome();
|
||||
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
|
||||
await popupShown;
|
||||
|
||||
ok(getHomePageURL().endsWith("home.html"), "The homepage is set");
|
||||
ok(win.gURLBar.value.endsWith("home.html"), "extension is in control in private window");
|
||||
|
||||
let popupHidden = promisePopupHidden(panel);
|
||||
panel.hidePopup();
|
||||
await popupHidden;
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
/* global gBrowser SessionStore */
|
||||
"use strict";
|
||||
|
||||
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
|
||||
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
|
||||
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
|
||||
let lazyTabState = {entries: [{url: "http://example.com/", triggeringPrincipal_base64, title: "Example Domain"}]};
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ ChromeUtils.defineModuleGetter(this, "SessionStore",
|
|||
"resource:///modules/sessionstore/SessionStore.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "TabStateFlusher",
|
||||
"resource:///modules/sessionstore/TabStateFlusher.jsm");
|
||||
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
|
||||
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
|
||||
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
|
||||
async function doorhangerTest(testFn) {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
|
||||
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
|
||||
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
|
||||
const SESSION = {
|
||||
windows: [{
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
|
||||
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
|
||||
"resource://gre/modules/ExtensionSettingsStore.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
|
||||
"@mozilla.org/browser/aboutnewtab-service;1",
|
||||
"nsIAboutNewTabService");
|
||||
|
||||
const NEWTAB_URI_1 = "webext-newtab-1.html";
|
||||
|
||||
|
@ -522,3 +525,189 @@ add_task(async function dontTemporarilyShowAboutExtensionPath() {
|
|||
BrowserTestUtils.removeTab(tab);
|
||||
await extension.unload();
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_newtab_incognito_not_allowed() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let panel = getNewTabDoorhanger().closest("panel");
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
chrome_url_overrides: {"newtab": "newtab.html"},
|
||||
name: "extension",
|
||||
applications: {
|
||||
gecko: {id: "@not-allowed-newtab"},
|
||||
},
|
||||
},
|
||||
files: {
|
||||
"newtab.html": `
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8"/></head>
|
||||
<html>
|
||||
<body>
|
||||
<script src="newtab.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
|
||||
"newtab.js": function() {
|
||||
window.onload = () => {
|
||||
browser.test.sendMessage("from-newtab-page", window.location.href);
|
||||
};
|
||||
},
|
||||
},
|
||||
useAddonManager: "permanent",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
let popupShown = promisePopupShown(panel);
|
||||
BrowserOpenTab();
|
||||
await popupShown;
|
||||
|
||||
let url = await extension.awaitMessage("from-newtab-page");
|
||||
ok(url.endsWith("newtab.html"),
|
||||
"Newtab url is overridden by the extension.");
|
||||
|
||||
// This will show a confirmation doorhanger, make sure we don't leave it open.
|
||||
let popupHidden = promisePopupHidden(panel);
|
||||
panel.hidePopup();
|
||||
await popupHidden;
|
||||
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
||||
// Verify a private window does not open the extension page. We would
|
||||
// get an extra notification that we don't listen for if it gets loaded.
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
|
||||
let newTabOpened = waitForNewTab();
|
||||
win.BrowserOpenTab();
|
||||
await newTabOpened;
|
||||
|
||||
is(win.gURLBar.value, "", "newtab not used in private window");
|
||||
|
||||
// Verify setting the pref directly doesn't bypass permissions.
|
||||
let origUrl = aboutNewTabService.newTabURL;
|
||||
aboutNewTabService.newTabURL = url;
|
||||
newTabOpened = waitForNewTab();
|
||||
win.BrowserOpenTab();
|
||||
await newTabOpened;
|
||||
|
||||
is(win.gURLBar.value, "", "directly set newtab not used in private window");
|
||||
|
||||
aboutNewTabService.newTabURL = origUrl;
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_newtab_incognito_not_allowed_bypass() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
name: "extension",
|
||||
applications: {
|
||||
gecko: {id: "@not-allowed-newtab"},
|
||||
},
|
||||
},
|
||||
background() {
|
||||
browser.test.sendMessage("url", browser.runtime.getURL("newtab.html"));
|
||||
},
|
||||
files: {
|
||||
"newtab.html": `
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8"/></head>
|
||||
<html>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
},
|
||||
useAddonManager: "permanent",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
let url = await extension.awaitMessage("url");
|
||||
|
||||
// Verify setting the pref directly doesn't bypass permissions.
|
||||
let origUrl = aboutNewTabService.newTabURL;
|
||||
aboutNewTabService.newTabURL = url;
|
||||
|
||||
// Verify a private window does not open the extension page. We would
|
||||
// get an extra notification that we don't listen for if it gets loaded.
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
|
||||
let newTabOpened = waitForNewTab();
|
||||
win.BrowserOpenTab();
|
||||
await newTabOpened;
|
||||
|
||||
is(win.gURLBar.value, "", "directly set newtab not used in private window");
|
||||
|
||||
aboutNewTabService.newTabURL = origUrl;
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_newtab_incognito_spanning() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
chrome_url_overrides: {"newtab": "newtab.html"},
|
||||
name: "extension",
|
||||
applications: {
|
||||
gecko: {id: "@spanning-newtab"},
|
||||
},
|
||||
},
|
||||
files: {
|
||||
"newtab.html": `
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8"/></head>
|
||||
<html>
|
||||
<body>
|
||||
<script src="newtab.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
|
||||
"newtab.js": function() {
|
||||
window.onload = () => {
|
||||
browser.test.sendMessage("from-newtab-page", window.location.href);
|
||||
};
|
||||
},
|
||||
},
|
||||
useAddonManager: "permanent",
|
||||
incognitoOverride: "spanning",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
let panel = win.document.getElementById("extension-new-tab-notification").closest("panel");
|
||||
let popupShown = promisePopupShown(panel);
|
||||
win.BrowserOpenTab();
|
||||
await popupShown;
|
||||
|
||||
let url = await extension.awaitMessage("from-newtab-page");
|
||||
ok(url.endsWith("newtab.html"),
|
||||
"Newtab url is overridden by the extension.");
|
||||
|
||||
// This will show a confirmation doorhanger, make sure we don't leave it open.
|
||||
let popupHidden = promisePopupHidden(panel);
|
||||
panel.hidePopup();
|
||||
await popupHidden;
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
|
|
@ -1937,6 +1937,7 @@ this.PlacesPanelview = class extends PlacesViewBase {
|
|||
}
|
||||
|
||||
_onCommand(event) {
|
||||
event = getRootEvent(event);
|
||||
let button = event.originalTarget;
|
||||
if (!button._placesNode)
|
||||
return;
|
||||
|
|
|
@ -33,10 +33,10 @@ skip-if = (os == 'win' && processor == "x86_64") # Bug 1480314
|
|||
[browser_bug1018066_resetScrollPosition.js]
|
||||
[browser_bug1020245_openPreferences_to_paneContent.js]
|
||||
[browser_bug1184989_prevent_scrolling_when_preferences_flipped.js]
|
||||
[browser_cert_export.js]
|
||||
[browser_engines.js]
|
||||
support-files =
|
||||
browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul
|
||||
[browser_cert_export.js]
|
||||
[browser_engines.js]
|
||||
[browser_change_app_handler.js]
|
||||
skip-if = os != "win" # Windows-specific handler application selection dialog
|
||||
[browser_checkspelling.js]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
|
||||
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
|
||||
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
|
||||
add_task(async function() {
|
||||
waitForExplicitFinish();
|
||||
|
|
|
@ -212,9 +212,9 @@ ContentRestoreInternal.prototype = {
|
|||
referrerInfo = new ReferrerInfo(referrerPolicy, true, referrer);
|
||||
}
|
||||
let postData = loadArguments.postData ?
|
||||
Utils.makeInputStream(loadArguments.postData) : null;
|
||||
E10SUtils.makeInputStream(loadArguments.postData) : null;
|
||||
let triggeringPrincipal = loadArguments.triggeringPrincipal
|
||||
? Utils.deserializePrincipal(loadArguments.triggeringPrincipal)
|
||||
? E10SUtils.deserializePrincipal(loadArguments.triggeringPrincipal)
|
||||
: Services.scriptSecurityManager.createNullPrincipal({});
|
||||
|
||||
if (loadArguments.userContextId) {
|
||||
|
|
|
@ -9,8 +9,8 @@ var EXPORTED_SYMBOLS = ["SessionMigration"];
|
|||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
||||
ChromeUtils.import("resource://gre/modules/osfile.jsm", this);
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "Utils",
|
||||
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "E10SUtils",
|
||||
"resource://gre/modules/E10SUtils.jsm");
|
||||
|
||||
// An encoder to UTF-8.
|
||||
XPCOMUtils.defineLazyGetter(this, "gEncoder", function() {
|
||||
|
@ -63,7 +63,7 @@ var SessionMigrationInternal = {
|
|||
});
|
||||
let url = "about:welcomeback";
|
||||
let formdata = {id: {sessionData: state}, url};
|
||||
let entry = { url, triggeringPrincipal_base64: Utils.SERIALIZED_SYSTEMPRINCIPAL };
|
||||
let entry = { url, triggeringPrincipal_base64: E10SUtils.SERIALIZED_SYSTEMPRINCIPAL };
|
||||
return { windows: [{ tabs: [{ entries: [ entry ], formdata}]}]};
|
||||
},
|
||||
/**
|
||||
|
|
|
@ -682,14 +682,14 @@ var SessionStoreInternal = {
|
|||
// replace the crashed session with a restore-page-only session
|
||||
let url = "about:sessionrestore";
|
||||
let formdata = {id: {sessionData: state}, url};
|
||||
let entry = {url, triggeringPrincipal_base64: Utils.SERIALIZED_SYSTEMPRINCIPAL };
|
||||
let entry = {url, triggeringPrincipal_base64: E10SUtils.SERIALIZED_SYSTEMPRINCIPAL };
|
||||
state = { windows: [{ tabs: [{ entries: [entry], formdata }] }] };
|
||||
} else if (this._hasSingleTabWithURL(state.windows,
|
||||
"about:welcomeback")) {
|
||||
// On a single about:welcomeback URL that crashed, replace about:welcomeback
|
||||
// with about:sessionrestore, to make clear to the user that we crashed.
|
||||
state.windows[0].tabs[0].entries[0].url = "about:sessionrestore";
|
||||
state.windows[0].tabs[0].entries[0].triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
state.windows[0].tabs[0].entries[0].triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3345,7 +3345,7 @@ var SessionStoreInternal = {
|
|||
let tabbrowser = aWindow.gBrowser;
|
||||
let startupPref = this._prefBranch.getIntPref("startup.page");
|
||||
if (startupPref == 1)
|
||||
homePages = homePages.concat(HomePage.get().split("|"));
|
||||
homePages = homePages.concat(HomePage.get(aWindow).split("|"));
|
||||
|
||||
for (let i = tabbrowser._numPinnedTabs; i < tabbrowser.tabs.length; i++) {
|
||||
let tab = tabbrowser.tabs[i];
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* 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/. */
|
||||
|
||||
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
|
||||
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
|
||||
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
|
||||
const TAB_STATE_NEEDS_RESTORE = 1;
|
||||
const TAB_STATE_RESTORING = 2;
|
||||
|
|
|
@ -251,8 +251,12 @@ class UrlbarInput {
|
|||
if (selectedOneOff) {
|
||||
// If there's a selected one-off button then load a search using
|
||||
// the button's engine.
|
||||
let result = this._resultForCurrentValue;
|
||||
let searchString =
|
||||
(result && (result.payload.suggestion || result.payload.query)) ||
|
||||
this._lastSearchString;
|
||||
[url, openParams.postData] = UrlbarUtils.getSearchQueryUrl(
|
||||
selectedOneOff.engine, this._lastSearchString);
|
||||
selectedOneOff.engine, searchString);
|
||||
this._recordSearch(selectedOneOff.engine, event);
|
||||
} else {
|
||||
// Use the current value if we don't have a UrlbarResult e.g. because the
|
||||
|
|
|
@ -97,7 +97,6 @@ subsuite = clipboard
|
|||
support-files = empty.xul
|
||||
[browser_UrlbarLoadRace.js]
|
||||
[browser_urlbarOneOffs_searchSuggestions.js]
|
||||
skip-if = true # Bug 1528024 - Need to correctly handle suggestions and one-offs.
|
||||
support-files =
|
||||
../browser/searchSuggestionEngine.xml
|
||||
../browser/searchSuggestionEngine.sjs
|
||||
|
|
|
@ -97,12 +97,12 @@ add_task(async function overridden_engine_not_reused() {
|
|||
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
|
||||
let label = result.displayed.action;
|
||||
// Run again the query, check the label has been replaced.
|
||||
await UrlbarTestUtils.promisePopupClose(window);
|
||||
await promiseAutocompleteResultPopup(typedValue, window, true);
|
||||
await promiseSuggestionsPresent();
|
||||
assertState(0, -1, "foo");
|
||||
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
|
||||
Assert.notEqual(result.displayed.action, label, "The label should have been updated");
|
||||
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
|
@ -111,11 +111,7 @@ function assertState(result, oneOff, textValue = undefined) {
|
|||
"Expected result should be selected");
|
||||
Assert.equal(UrlbarTestUtils.getOneOffSearchButtons(window).selectedButtonIndex,
|
||||
oneOff, "Expected one-off should be selected");
|
||||
// TODO Bug 1527946: Fix textValue differences for QuantumBar
|
||||
if (UrlbarPrefs.get("quantumbar")) {
|
||||
return;
|
||||
}
|
||||
if (textValue !== undefined) {
|
||||
Assert.equal(gURLBar.textValue, textValue, "Expected textValue");
|
||||
}
|
||||
if (textValue !== undefined) {
|
||||
Assert.equal(gURLBar.textValue, textValue, "Expected textValue");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
var EXPORTED_SYMBOLS = ["HomePage"];
|
||||
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
const kPrefName = "browser.startup.homepage";
|
||||
|
||||
|
@ -43,7 +45,11 @@ function getHomepagePref(useDefault) {
|
|||
}
|
||||
|
||||
let HomePage = {
|
||||
get() {
|
||||
get(aWindow) {
|
||||
if (PrivateBrowsingUtils.permanentPrivateBrowsing ||
|
||||
(aWindow && PrivateBrowsingUtils.isWindowPrivate(aWindow))) {
|
||||
return this.getPrivate();
|
||||
}
|
||||
return getHomepagePref();
|
||||
},
|
||||
|
||||
|
@ -51,6 +57,24 @@ let HomePage = {
|
|||
return getHomepagePref(true);
|
||||
},
|
||||
|
||||
getPrivate() {
|
||||
let homePages = getHomepagePref();
|
||||
if (!homePages.includes("moz-extension")) {
|
||||
return homePages;
|
||||
}
|
||||
// Verify private access and build a new list.
|
||||
let privateHomePages = homePages.split("|").filter(page => {
|
||||
let url = new URL(page);
|
||||
if (url.protocol !== "moz-extension:") {
|
||||
return true;
|
||||
}
|
||||
let policy = WebExtensionPolicy.getByHostname(url.hostname);
|
||||
return policy && policy.privateBrowsingAllowed;
|
||||
});
|
||||
// Extensions may not be ready on startup, fallback to defaults.
|
||||
return privateHomePages.join("|") || this.getDefault();
|
||||
},
|
||||
|
||||
get overridden() {
|
||||
return Services.prefs.prefHasUserValue(kPrefName);
|
||||
},
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
|
||||
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
|
||||
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
|
||||
const MAX_CONCURRENT_TABS = "browser.engagement.max_concurrent_tab_count";
|
||||
const TAB_EVENT_COUNT = "browser.engagement.tab_open_event_count";
|
||||
|
|
|
@ -56,7 +56,6 @@ ignored_js_src_dirs = [
|
|||
# We ignore #includes of these files, because they don't follow the usual rules.
|
||||
included_inclnames_to_ignore = set([
|
||||
'ffi.h', # generated in ctypes/libffi/
|
||||
'devtools/sharkctl.h', # we ignore devtools/ in general
|
||||
'devtools/Instruments.h', # we ignore devtools/ in general
|
||||
'double-conversion/double-conversion.h', # strange MFBT case
|
||||
'javascript-trace.h', # generated in $OBJDIR if HAVE_DTRACE is defined
|
||||
|
|
|
@ -92,6 +92,10 @@ storage.popupMenu.deleteLabel=Delete “%S”
|
|||
# Label of popup menu action to add an item.
|
||||
storage.popupMenu.addItemLabel=Add Item
|
||||
|
||||
# LOCALIZATION NOTE (storage.popupMenu.refreshItemLabel):
|
||||
# Label of popup menu action to refresh an item.
|
||||
storage.popupMenu.refreshItemLabel=Refresh Items
|
||||
|
||||
# LOCALIZATION NOTE (storage.popupMenu.deleteAllFromLabel):
|
||||
# Label of popup menu action to delete all storage items.
|
||||
storage.popupMenu.deleteAllFromLabel=Delete All From “%S”
|
||||
|
|
|
@ -8,9 +8,8 @@ const { Cc, Ci, Cu, Cr } = require("chrome");
|
|||
const ChromeUtils = require("ChromeUtils");
|
||||
const Services = require("Services");
|
||||
const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
|
||||
const { Utils } = require("resource://gre/modules/sessionstore/Utils.jsm");
|
||||
const Telemetry = require("devtools/client/shared/telemetry");
|
||||
const { E10SUtils } = require("resource://gre/modules/E10SUtils.jsm");
|
||||
const Telemetry = require("devtools/client/shared/telemetry");
|
||||
|
||||
const telemetry = new Telemetry();
|
||||
|
||||
|
@ -83,7 +82,7 @@ BrowserElementWebNavigation.prototype = {
|
|||
postData: postData ? readInputStreamToString(postData) : null,
|
||||
headers: headers ? readInputStreamToString(headers) : null,
|
||||
baseURI: baseURI ? baseURI.spec : null,
|
||||
triggeringPrincipal: Utils.serializePrincipal(
|
||||
triggeringPrincipal: E10SUtils.serializePrincipal(
|
||||
triggeringPrincipal ||
|
||||
Services.scriptSecurityManager.createNullPrincipal({})),
|
||||
requestTime: telemetry.msSystemNow(),
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
|
||||
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
|
||||
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
|
||||
const testState = {
|
||||
windows: [{
|
||||
|
|
|
@ -48,12 +48,11 @@ const {
|
|||
|
||||
const { OS } = Services.appinfo;
|
||||
|
||||
// CM_SCRIPTS and CM_IFRAME represent the HTML and JavaScript that is
|
||||
// CM_BUNDLE and CM_IFRAME represent the HTML and JavaScript that is
|
||||
// injected into an iframe in order to initialize a CodeMirror instance.
|
||||
|
||||
const CM_SCRIPTS = [
|
||||
"chrome://devtools/content/shared/sourceeditor/codemirror/codemirror.bundle.js",
|
||||
];
|
||||
const CM_BUNDLE =
|
||||
"chrome://devtools/content/shared/sourceeditor/codemirror/codemirror.bundle.js";
|
||||
|
||||
const CM_IFRAME = "chrome://devtools/content/shared/sourceeditor/codemirror/cmiframe.html";
|
||||
|
||||
|
@ -217,11 +216,6 @@ function Editor(config) {
|
|||
cm.replaceSelection(" ".repeat(num), "end", "+input");
|
||||
};
|
||||
|
||||
// Allow add-ons to inject scripts for their editor instances
|
||||
if (!this.config.externalScripts) {
|
||||
this.config.externalScripts = [];
|
||||
}
|
||||
|
||||
if (this.config.cssProperties) {
|
||||
// Ensure that autocompletion has cssProperties if it's passed in via the options.
|
||||
this.config.autocompleteOpts.cssProperties = this.config.cssProperties;
|
||||
|
@ -326,12 +320,7 @@ Editor.prototype = {
|
|||
doc = doc || el.ownerDocument;
|
||||
const win = el.ownerDocument.defaultView;
|
||||
|
||||
const scriptsToInject = CM_SCRIPTS.concat(this.config.externalScripts);
|
||||
scriptsToInject.forEach(url => {
|
||||
if (url.startsWith("chrome://")) {
|
||||
Services.scriptloader.loadSubScript(url, win);
|
||||
}
|
||||
});
|
||||
Services.scriptloader.loadSubScript(CM_BUNDLE, win);
|
||||
|
||||
// Replace the propertyKeywords, colorKeywords and valueKeywords
|
||||
// properties of the CSS MIME type with the values provided by the CSS properties
|
||||
|
|
|
@ -40,7 +40,6 @@ support-files =
|
|||
[browser_editor_markers.js]
|
||||
[browser_editor_movelines.js]
|
||||
[browser_editor_prefs.js]
|
||||
[browser_editor_script_injection.js]
|
||||
[browser_editor_addons.js]
|
||||
[browser_codemirror.js]
|
||||
[browser_css_autocompletion.js]
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test the externalScripts option, which allows custom language modes or
|
||||
// other scripts to be injected into the editor window. See Bug 1089428.
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function() {
|
||||
await runTest();
|
||||
});
|
||||
|
||||
async function runTest() {
|
||||
const baseURL =
|
||||
"chrome://mochitests/content/browser/devtools/client/shared/sourceeditor/test";
|
||||
const injectedText = "Script successfully injected!";
|
||||
|
||||
const {ed, win} = await setup({
|
||||
mode: "ruby",
|
||||
externalScripts: [`${baseURL}/cm_script_injection_test.js`,
|
||||
`${baseURL}/cm_mode_ruby.js`],
|
||||
});
|
||||
|
||||
is(ed.getText(), injectedText, "The text has been injected");
|
||||
is(ed.getOption("mode"), "ruby", "The ruby mode is correctly set");
|
||||
teardown(ed, win);
|
||||
}
|
|
@ -191,6 +191,8 @@ class StorageUI {
|
|||
|
||||
this._refreshButton = this._panelDoc.getElementById("refresh-button");
|
||||
this._refreshButton.addEventListener("command", this.onRefreshTable);
|
||||
this._refreshButton.setAttribute("tooltiptext",
|
||||
L10N.getFormatStr("storage.popupMenu.refreshItemLabel"));
|
||||
|
||||
this._addButton = this._panelDoc.getElementById("add-button");
|
||||
this._addButton.addEventListener("command", this.onAddItem);
|
||||
|
|
|
@ -1227,6 +1227,8 @@ Document::Document(const char* aContentType)
|
|||
mInUnlinkOrDeletion(false),
|
||||
mHasHadScriptHandlingObject(false),
|
||||
mIsBeingUsedAsImage(false),
|
||||
mDocURISchemeIsChrome(false),
|
||||
mInChromeDocShell(false),
|
||||
mIsSyntheticDocument(false),
|
||||
mHasLinksToUpdateRunnable(false),
|
||||
mFlushingPendingLinkUpdates(false),
|
||||
|
@ -2835,6 +2837,8 @@ void Document::SetDocumentURI(nsIURI* aURI) {
|
|||
mDocumentURI = aURI;
|
||||
nsIURI* newBase = GetDocBaseURI();
|
||||
|
||||
mDocURISchemeIsChrome = aURI && IsChromeURI(aURI);
|
||||
|
||||
bool equalBases = false;
|
||||
// Changing just the ref of a URI does not change how relative URIs would
|
||||
// resolve wrt to it, so we can treat the bases as equal as long as they're
|
||||
|
@ -4301,6 +4305,9 @@ void Document::SetContainer(nsDocShell* aContainer) {
|
|||
mDocumentContainer = WeakPtr<nsDocShell>();
|
||||
}
|
||||
|
||||
mInChromeDocShell =
|
||||
aContainer && aContainer->ItemType() == nsIDocShellTreeItem::typeChrome;
|
||||
|
||||
EnumerateActivityObservers(NotifyActivityChanged, nullptr);
|
||||
|
||||
// IsTopLevelWindowInactive depends on the docshell, so
|
||||
|
|
|
@ -2474,6 +2474,16 @@ class Document : public nsINode,
|
|||
return !mParentDocument && !mDisplayDocument;
|
||||
}
|
||||
|
||||
bool IsDocumentURISchemeChrome() const { return mDocURISchemeIsChrome; }
|
||||
|
||||
bool IsInChromeDocShell() const {
|
||||
const Document* root = this;
|
||||
while (const Document* displayDoc = root->GetDisplayDocument()) {
|
||||
root = displayDoc;
|
||||
}
|
||||
return root->mInChromeDocShell;
|
||||
}
|
||||
|
||||
bool IsBeingUsedAsImage() const { return mIsBeingUsedAsImage; }
|
||||
|
||||
void SetIsBeingUsedAsImage() { mIsBeingUsedAsImage = true; }
|
||||
|
@ -4007,6 +4017,12 @@ class Document : public nsINode,
|
|||
// True if we're an SVG document being used as an image.
|
||||
bool mIsBeingUsedAsImage : 1;
|
||||
|
||||
// True if our current document URI's scheme is chrome://
|
||||
bool mDocURISchemeIsChrome : 1;
|
||||
|
||||
// True if we're loaded in a chrome docshell.
|
||||
bool mInChromeDocShell : 1;
|
||||
|
||||
// True is this document is synthetic : stand alone image, video, audio
|
||||
// file, etc.
|
||||
bool mIsSyntheticDocument : 1;
|
||||
|
|
|
@ -3851,10 +3851,6 @@ void nsContentUtils::LogMessageToConsole(const char* aMsg) {
|
|||
sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
|
||||
}
|
||||
|
||||
bool nsContentUtils::IsChromeDoc(const Document* aDocument) {
|
||||
return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
|
||||
}
|
||||
|
||||
bool nsContentUtils::IsChildOfSameType(Document* aDoc) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(aDoc->GetDocShell());
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
|
||||
|
@ -3888,24 +3884,6 @@ bool nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType) {
|
|||
aContentType.EqualsLiteral(TEXT_VTT);
|
||||
}
|
||||
|
||||
// static
|
||||
bool nsContentUtils::IsInChromeDocshell(Document* aDocument) {
|
||||
if (!aDocument) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aDocument->GetDisplayDocument()) {
|
||||
return IsInChromeDocshell(aDocument->GetDisplayDocument());
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShell = aDocument->GetDocShell();
|
||||
if (!docShell) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return docShell->ItemType() == nsIDocShellTreeItem::typeChrome;
|
||||
}
|
||||
|
||||
// static
|
||||
nsIContentPolicy* nsContentUtils::GetContentPolicy() {
|
||||
if (!sTriedToGetContentPolicy) {
|
||||
|
|
|
@ -1227,7 +1227,9 @@ class nsContentUtils {
|
|||
/**
|
||||
* Returns true if aDocument is a chrome document
|
||||
*/
|
||||
static bool IsChromeDoc(const Document* aDocument);
|
||||
static bool IsChromeDoc(const Document* aDocument) {
|
||||
return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if aDocument is in a docshell whose parent is the same type
|
||||
|
@ -1250,7 +1252,9 @@ class nsContentUtils {
|
|||
* display purposes. Returns false for null documents or documents
|
||||
* which do not belong to a docshell.
|
||||
*/
|
||||
static bool IsInChromeDocshell(Document* aDocument);
|
||||
static bool IsInChromeDocshell(const Document* aDocument) {
|
||||
return aDocument && aDocument->IsInChromeDocShell();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content policy service
|
||||
|
|
|
@ -40,6 +40,7 @@ EXPORTS += [
|
|||
'LayersTypes.h',
|
||||
'LayerTreeInvalidation.h',
|
||||
'LayerUserData.h',
|
||||
'opengl/OGLShaderConfig.h',
|
||||
'opengl/OGLShaderProgram.h',
|
||||
'protobuf/LayerScopePacket.pb.h',
|
||||
'ReadbackLayer.h',
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "nsRect.h" // for mozilla::gfx::IntRect
|
||||
#include "nsServiceManagerUtils.h" // for do_GetService
|
||||
#include "nsString.h" // for nsString, nsAutoCString, etc
|
||||
#include "OGLShaderProgram.h" // for ShaderProgramOGL, etc
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "GLReadTexImageHelper.h"
|
||||
#include "GLBlitTextureImageHelper.h"
|
||||
|
@ -152,6 +153,12 @@ bool AsyncReadbackBufferOGL::MapAndCopyInto(DataSourceSurface* aSurface,
|
|||
return true;
|
||||
}
|
||||
|
||||
PerUnitTexturePoolOGL::PerUnitTexturePoolOGL(gl::GLContext* aGL)
|
||||
: mTextureTarget(0), // zero is never a valid texture target
|
||||
mGL(aGL) {}
|
||||
|
||||
PerUnitTexturePoolOGL::~PerUnitTexturePoolOGL() { DestroyTextures(); }
|
||||
|
||||
static void BindMaskForProgram(ShaderProgramOGL* aProgram,
|
||||
TextureSourceOGL* aSourceMask, GLenum aTexUnit,
|
||||
const gfx::Matrix4x4& aTransform) {
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
#ifndef MOZILLA_GFX_COMPOSITOROGL_H
|
||||
#define MOZILLA_GFX_COMPOSITOROGL_H
|
||||
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "gfx2DGlue.h"
|
||||
#include "GLContextTypes.h" // for GLContext, etc
|
||||
#include "GLDefs.h" // for GLuint, LOCAL_GL_TEXTURE_2D, etc
|
||||
#include "OGLShaderProgram.h" // for ShaderProgramOGL, etc
|
||||
#include "OGLShaderConfig.h" // for ShaderConfigOGL
|
||||
#include "Units.h" // for ScreenPoint
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/Attributes.h" // for override, final
|
||||
|
@ -45,6 +46,7 @@ class CompositingRenderTarget;
|
|||
class CompositingRenderTargetOGL;
|
||||
class DataTextureSource;
|
||||
class GLManagerCompositor;
|
||||
class ShaderProgramOGL;
|
||||
class TextureSource;
|
||||
class TextureSourceOGL;
|
||||
class BufferTextureHost;
|
||||
|
@ -81,12 +83,8 @@ class CompositorTexturePoolOGL {
|
|||
*/
|
||||
class PerUnitTexturePoolOGL : public CompositorTexturePoolOGL {
|
||||
public:
|
||||
explicit PerUnitTexturePoolOGL(gl::GLContext* aGL)
|
||||
: mTextureTarget(0) // zero is never a valid texture target
|
||||
,
|
||||
mGL(aGL) {}
|
||||
|
||||
virtual ~PerUnitTexturePoolOGL() { DestroyTextures(); }
|
||||
explicit PerUnitTexturePoolOGL(gl::GLContext* aGL);
|
||||
virtual ~PerUnitTexturePoolOGL();
|
||||
|
||||
virtual void Clear() override { DestroyTextures(); }
|
||||
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "GLManager.h"
|
||||
#include "CompositorOGL.h" // for CompositorOGL
|
||||
#include "GLContext.h" // for GLContext
|
||||
#include "CompositorOGL.h" // for CompositorOGL
|
||||
#include "GLContext.h" // for GLContext
|
||||
#include "OGLShaderProgram.h"
|
||||
#include "mozilla/Attributes.h" // for override
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/layers/Compositor.h" // for Compositor
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define MOZILLA_GFX_GLMANAGER_H
|
||||
|
||||
#include "mozilla/gfx/Types.h" // for SurfaceFormat
|
||||
#include "OGLShaderProgram.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
@ -18,6 +17,7 @@ class GLContext;
|
|||
namespace layers {
|
||||
|
||||
class LayerManagerComposite;
|
||||
class ShaderProgramOGL;
|
||||
|
||||
/**
|
||||
* Minimal interface to allow widgets to draw using OpenGL. Abstracts
|
||||
|
|
|
@ -0,0 +1,266 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef GFX_OGLSHADERCONFIG_H
|
||||
#define GFX_OGLSHADERCONFIG_H
|
||||
|
||||
#include "gfxTypes.h"
|
||||
#include "ImageTypes.h"
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/Pair.h" // for Pair
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
|
||||
#include "mozilla/gfx/Rect.h" // for Rect
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "nsDebug.h" // for NS_ASSERTION
|
||||
#include "nsPoint.h" // for nsIntPoint
|
||||
#include "nsTArray.h" // for nsTArray
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
enum ShaderFeatures {
|
||||
ENABLE_RENDER_COLOR = 0x01,
|
||||
ENABLE_TEXTURE_RECT = 0x02,
|
||||
ENABLE_TEXTURE_EXTERNAL = 0x04,
|
||||
ENABLE_TEXTURE_YCBCR = 0x08,
|
||||
ENABLE_TEXTURE_NV12 = 0x10,
|
||||
ENABLE_TEXTURE_COMPONENT_ALPHA = 0x20,
|
||||
ENABLE_TEXTURE_NO_ALPHA = 0x40,
|
||||
ENABLE_TEXTURE_RB_SWAP = 0x80,
|
||||
ENABLE_OPACITY = 0x100,
|
||||
ENABLE_BLUR = 0x200,
|
||||
ENABLE_COLOR_MATRIX = 0x400,
|
||||
ENABLE_MASK = 0x800,
|
||||
ENABLE_NO_PREMUL_ALPHA = 0x1000,
|
||||
ENABLE_DEAA = 0x2000,
|
||||
ENABLE_DYNAMIC_GEOMETRY = 0x4000,
|
||||
ENABLE_MASK_TEXTURE_RECT = 0x8000,
|
||||
};
|
||||
|
||||
class KnownUniform {
|
||||
public:
|
||||
// this needs to be kept in sync with strings in 'AddUniforms'
|
||||
enum KnownUniformName {
|
||||
NotAKnownUniform = -1,
|
||||
|
||||
LayerTransform = 0,
|
||||
LayerTransformInverse,
|
||||
MaskTransform,
|
||||
BackdropTransform,
|
||||
LayerRects,
|
||||
MatrixProj,
|
||||
TextureTransform,
|
||||
TextureRects,
|
||||
RenderTargetOffset,
|
||||
LayerOpacity,
|
||||
Texture,
|
||||
YTexture,
|
||||
CbTexture,
|
||||
CrTexture,
|
||||
BlackTexture,
|
||||
WhiteTexture,
|
||||
MaskTexture,
|
||||
BackdropTexture,
|
||||
RenderColor,
|
||||
TexCoordMultiplier,
|
||||
CbCrTexCoordMultiplier,
|
||||
MaskCoordMultiplier,
|
||||
TexturePass2,
|
||||
ColorMatrix,
|
||||
ColorMatrixVector,
|
||||
BlurRadius,
|
||||
BlurOffset,
|
||||
BlurAlpha,
|
||||
BlurGaussianKernel,
|
||||
SSEdges,
|
||||
ViewportSize,
|
||||
VisibleCenter,
|
||||
YuvColorMatrix,
|
||||
|
||||
KnownUniformCount
|
||||
};
|
||||
|
||||
KnownUniform() {
|
||||
mName = NotAKnownUniform;
|
||||
mNameString = nullptr;
|
||||
mLocation = -1;
|
||||
memset(&mValue, 0, sizeof(mValue));
|
||||
}
|
||||
|
||||
bool UpdateUniform(int32_t i1) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.i1 != i1) {
|
||||
mValue.i1 = i1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(float f1) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.f1 != f1) {
|
||||
mValue.f1 = f1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(float f1, float f2) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.f16v[0] != f1 || mValue.f16v[1] != f2) {
|
||||
mValue.f16v[0] = f1;
|
||||
mValue.f16v[1] = f2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(float f1, float f2, float f3, float f4) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.f16v[0] != f1 || mValue.f16v[1] != f2 || mValue.f16v[2] != f3 ||
|
||||
mValue.f16v[3] != f4) {
|
||||
mValue.f16v[0] = f1;
|
||||
mValue.f16v[1] = f2;
|
||||
mValue.f16v[2] = f3;
|
||||
mValue.f16v[3] = f4;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(int cnt, const float* fp) {
|
||||
if (mLocation == -1) return false;
|
||||
switch (cnt) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 9:
|
||||
case 16:
|
||||
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt) != 0) {
|
||||
memcpy(mValue.f16v, fp, sizeof(float) * cnt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("cnt must be 1 2 3 4 9 or 16");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateArrayUniform(int cnt, const float* fp) {
|
||||
if (mLocation == -1) return false;
|
||||
if (cnt > 16) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt) != 0) {
|
||||
memcpy(mValue.f16v, fp, sizeof(float) * cnt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateArrayUniform(int cnt, const gfx::Point3D* points) {
|
||||
if (mLocation == -1) return false;
|
||||
if (cnt > 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float fp[12];
|
||||
float* d = fp;
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
// Note: Do not want to make assumptions about .x, .y, .z member packing.
|
||||
// If gfx::Point3D is updated to make this guarantee, SIMD optimizations
|
||||
// may be possible
|
||||
*d++ = points[i].x;
|
||||
*d++ = points[i].y;
|
||||
*d++ = points[i].z;
|
||||
}
|
||||
|
||||
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt * 3) != 0) {
|
||||
memcpy(mValue.f16v, fp, sizeof(float) * cnt * 3);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
KnownUniformName mName;
|
||||
const char* mNameString;
|
||||
int32_t mLocation;
|
||||
|
||||
union {
|
||||
int i1;
|
||||
float f1;
|
||||
float f16v[16];
|
||||
} mValue;
|
||||
};
|
||||
|
||||
class ShaderConfigOGL {
|
||||
public:
|
||||
ShaderConfigOGL()
|
||||
: mFeatures(0),
|
||||
mMultiplier(1),
|
||||
mCompositionOp(gfx::CompositionOp::OP_OVER) {}
|
||||
|
||||
void SetRenderColor(bool aEnabled);
|
||||
void SetTextureTarget(GLenum aTarget);
|
||||
void SetMaskTextureTarget(GLenum aTarget);
|
||||
void SetRBSwap(bool aEnabled);
|
||||
void SetNoAlpha(bool aEnabled);
|
||||
void SetOpacity(bool aEnabled);
|
||||
void SetYCbCr(bool aEnabled);
|
||||
void SetNV12(bool aEnabled);
|
||||
void SetComponentAlpha(bool aEnabled);
|
||||
void SetColorMatrix(bool aEnabled);
|
||||
void SetBlur(bool aEnabled);
|
||||
void SetMask(bool aEnabled);
|
||||
void SetDEAA(bool aEnabled);
|
||||
void SetCompositionOp(gfx::CompositionOp aOp);
|
||||
void SetNoPremultipliedAlpha();
|
||||
void SetDynamicGeometry(bool aEnabled);
|
||||
void SetColorMultiplier(uint32_t aMultiplier);
|
||||
|
||||
bool operator<(const ShaderConfigOGL& other) const {
|
||||
return mFeatures < other.mFeatures ||
|
||||
(mFeatures == other.mFeatures &&
|
||||
(int)mCompositionOp < (int)other.mCompositionOp) ||
|
||||
(mFeatures == other.mFeatures &&
|
||||
(int)mCompositionOp == (int)other.mCompositionOp &&
|
||||
mMultiplier < other.mMultiplier);
|
||||
}
|
||||
|
||||
public:
|
||||
void SetFeature(int aBitmask, bool aState) {
|
||||
if (aState)
|
||||
mFeatures |= aBitmask;
|
||||
else
|
||||
mFeatures &= (~aBitmask);
|
||||
}
|
||||
|
||||
int mFeatures;
|
||||
uint32_t mMultiplier;
|
||||
gfx::CompositionOp mCompositionOp;
|
||||
};
|
||||
|
||||
static inline ShaderConfigOGL ShaderConfigFromTargetAndFormat(
|
||||
GLenum aTarget, gfx::SurfaceFormat aFormat) {
|
||||
ShaderConfigOGL config;
|
||||
config.SetTextureTarget(aTarget);
|
||||
config.SetRBSwap(aFormat == gfx::SurfaceFormat::B8G8R8A8 ||
|
||||
aFormat == gfx::SurfaceFormat::B8G8R8X8);
|
||||
config.SetNoAlpha(aFormat == gfx::SurfaceFormat::B8G8R8X8 ||
|
||||
aFormat == gfx::SurfaceFormat::R8G8B8X8 ||
|
||||
aFormat == gfx::SurfaceFormat::R5G6B5_UINT16);
|
||||
return config;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GFX_OGLSHADERCONFIG_H
|
|
@ -5,6 +5,7 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "OGLShaderProgram.h"
|
||||
|
||||
#include <stdint.h> // for uint32_t
|
||||
#include <sstream> // for ostringstream
|
||||
#include "gfxEnv.h"
|
||||
|
|
|
@ -8,262 +8,27 @@
|
|||
#define GFX_OGLSHADERPROGRAM_H
|
||||
|
||||
#include "GLContext.h" // for fast inlines of glUniform*
|
||||
#include "gfxTypes.h"
|
||||
#include "ImageTypes.h"
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/Pair.h" // for Pair
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
|
||||
#include "mozilla/gfx/Rect.h" // for Rect
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "nsDebug.h" // for NS_ASSERTION
|
||||
#include "nsPoint.h" // for nsIntPoint
|
||||
#include "nsTArray.h" // for nsTArray
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
#include "OGLShaderConfig.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class Layer;
|
||||
|
||||
enum ShaderFeatures {
|
||||
ENABLE_RENDER_COLOR = 0x01,
|
||||
ENABLE_TEXTURE_RECT = 0x02,
|
||||
ENABLE_TEXTURE_EXTERNAL = 0x04,
|
||||
ENABLE_TEXTURE_YCBCR = 0x08,
|
||||
ENABLE_TEXTURE_NV12 = 0x10,
|
||||
ENABLE_TEXTURE_COMPONENT_ALPHA = 0x20,
|
||||
ENABLE_TEXTURE_NO_ALPHA = 0x40,
|
||||
ENABLE_TEXTURE_RB_SWAP = 0x80,
|
||||
ENABLE_OPACITY = 0x100,
|
||||
ENABLE_BLUR = 0x200,
|
||||
ENABLE_COLOR_MATRIX = 0x400,
|
||||
ENABLE_MASK = 0x800,
|
||||
ENABLE_NO_PREMUL_ALPHA = 0x1000,
|
||||
ENABLE_DEAA = 0x2000,
|
||||
ENABLE_DYNAMIC_GEOMETRY = 0x4000,
|
||||
ENABLE_MASK_TEXTURE_RECT = 0x8000,
|
||||
};
|
||||
|
||||
class KnownUniform {
|
||||
public:
|
||||
// this needs to be kept in sync with strings in 'AddUniforms'
|
||||
enum KnownUniformName {
|
||||
NotAKnownUniform = -1,
|
||||
|
||||
LayerTransform = 0,
|
||||
LayerTransformInverse,
|
||||
MaskTransform,
|
||||
BackdropTransform,
|
||||
LayerRects,
|
||||
MatrixProj,
|
||||
TextureTransform,
|
||||
TextureRects,
|
||||
RenderTargetOffset,
|
||||
LayerOpacity,
|
||||
Texture,
|
||||
YTexture,
|
||||
CbTexture,
|
||||
CrTexture,
|
||||
BlackTexture,
|
||||
WhiteTexture,
|
||||
MaskTexture,
|
||||
BackdropTexture,
|
||||
RenderColor,
|
||||
TexCoordMultiplier,
|
||||
CbCrTexCoordMultiplier,
|
||||
MaskCoordMultiplier,
|
||||
TexturePass2,
|
||||
ColorMatrix,
|
||||
ColorMatrixVector,
|
||||
BlurRadius,
|
||||
BlurOffset,
|
||||
BlurAlpha,
|
||||
BlurGaussianKernel,
|
||||
SSEdges,
|
||||
ViewportSize,
|
||||
VisibleCenter,
|
||||
YuvColorMatrix,
|
||||
|
||||
KnownUniformCount
|
||||
};
|
||||
|
||||
KnownUniform() {
|
||||
mName = NotAKnownUniform;
|
||||
mNameString = nullptr;
|
||||
mLocation = -1;
|
||||
memset(&mValue, 0, sizeof(mValue));
|
||||
}
|
||||
|
||||
bool UpdateUniform(int32_t i1) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.i1 != i1) {
|
||||
mValue.i1 = i1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(float f1) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.f1 != f1) {
|
||||
mValue.f1 = f1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(float f1, float f2) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.f16v[0] != f1 || mValue.f16v[1] != f2) {
|
||||
mValue.f16v[0] = f1;
|
||||
mValue.f16v[1] = f2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(float f1, float f2, float f3, float f4) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.f16v[0] != f1 || mValue.f16v[1] != f2 || mValue.f16v[2] != f3 ||
|
||||
mValue.f16v[3] != f4) {
|
||||
mValue.f16v[0] = f1;
|
||||
mValue.f16v[1] = f2;
|
||||
mValue.f16v[2] = f3;
|
||||
mValue.f16v[3] = f4;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(int cnt, const float* fp) {
|
||||
if (mLocation == -1) return false;
|
||||
switch (cnt) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 9:
|
||||
case 16:
|
||||
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt) != 0) {
|
||||
memcpy(mValue.f16v, fp, sizeof(float) * cnt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("cnt must be 1 2 3 4 9 or 16");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateArrayUniform(int cnt, const float* fp) {
|
||||
if (mLocation == -1) return false;
|
||||
if (cnt > 16) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt) != 0) {
|
||||
memcpy(mValue.f16v, fp, sizeof(float) * cnt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateArrayUniform(int cnt, const gfx::Point3D* points) {
|
||||
if (mLocation == -1) return false;
|
||||
if (cnt > 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float fp[12];
|
||||
float* d = fp;
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
// Note: Do not want to make assumptions about .x, .y, .z member packing.
|
||||
// If gfx::Point3D is updated to make this guarantee, SIMD optimizations
|
||||
// may be possible
|
||||
*d++ = points[i].x;
|
||||
*d++ = points[i].y;
|
||||
*d++ = points[i].z;
|
||||
}
|
||||
|
||||
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt * 3) != 0) {
|
||||
memcpy(mValue.f16v, fp, sizeof(float) * cnt * 3);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
KnownUniformName mName;
|
||||
const char* mNameString;
|
||||
int32_t mLocation;
|
||||
|
||||
union {
|
||||
int i1;
|
||||
float f1;
|
||||
float f16v[16];
|
||||
} mValue;
|
||||
};
|
||||
|
||||
class ShaderConfigOGL {
|
||||
public:
|
||||
ShaderConfigOGL()
|
||||
: mFeatures(0),
|
||||
mMultiplier(1),
|
||||
mCompositionOp(gfx::CompositionOp::OP_OVER) {}
|
||||
|
||||
void SetRenderColor(bool aEnabled);
|
||||
void SetTextureTarget(GLenum aTarget);
|
||||
void SetMaskTextureTarget(GLenum aTarget);
|
||||
void SetRBSwap(bool aEnabled);
|
||||
void SetNoAlpha(bool aEnabled);
|
||||
void SetOpacity(bool aEnabled);
|
||||
void SetYCbCr(bool aEnabled);
|
||||
void SetNV12(bool aEnabled);
|
||||
void SetComponentAlpha(bool aEnabled);
|
||||
void SetColorMatrix(bool aEnabled);
|
||||
void SetBlur(bool aEnabled);
|
||||
void SetMask(bool aEnabled);
|
||||
void SetDEAA(bool aEnabled);
|
||||
void SetCompositionOp(gfx::CompositionOp aOp);
|
||||
void SetNoPremultipliedAlpha();
|
||||
void SetDynamicGeometry(bool aEnabled);
|
||||
void SetColorMultiplier(uint32_t aMultiplier);
|
||||
|
||||
bool operator<(const ShaderConfigOGL& other) const {
|
||||
return mFeatures < other.mFeatures ||
|
||||
(mFeatures == other.mFeatures &&
|
||||
(int)mCompositionOp < (int)other.mCompositionOp) ||
|
||||
(mFeatures == other.mFeatures &&
|
||||
(int)mCompositionOp == (int)other.mCompositionOp &&
|
||||
mMultiplier < other.mMultiplier);
|
||||
}
|
||||
|
||||
public:
|
||||
void SetFeature(int aBitmask, bool aState) {
|
||||
if (aState)
|
||||
mFeatures |= aBitmask;
|
||||
else
|
||||
mFeatures &= (~aBitmask);
|
||||
}
|
||||
|
||||
int mFeatures;
|
||||
uint32_t mMultiplier;
|
||||
gfx::CompositionOp mCompositionOp;
|
||||
};
|
||||
|
||||
static inline ShaderConfigOGL ShaderConfigFromTargetAndFormat(
|
||||
GLenum aTarget, gfx::SurfaceFormat aFormat) {
|
||||
ShaderConfigOGL config;
|
||||
config.SetTextureTarget(aTarget);
|
||||
config.SetRBSwap(aFormat == gfx::SurfaceFormat::B8G8R8A8 ||
|
||||
aFormat == gfx::SurfaceFormat::B8G8R8X8);
|
||||
config.SetNoAlpha(aFormat == gfx::SurfaceFormat::B8G8R8X8 ||
|
||||
aFormat == gfx::SurfaceFormat::R8G8B8X8 ||
|
||||
aFormat == gfx::SurfaceFormat::R5G6B5_UINT16);
|
||||
return config;
|
||||
}
|
||||
#if defined(DEBUG)
|
||||
# define CHECK_CURRENT_PROGRAM 1
|
||||
# define ASSERT_THIS_PROGRAM \
|
||||
do { \
|
||||
GLuint currentProgram; \
|
||||
mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, ¤tProgram); \
|
||||
MOZ_ASSERT(currentProgram == mProgram, \
|
||||
"SetUniform with wrong program active!"); \
|
||||
} while (0)
|
||||
#else
|
||||
# define ASSERT_THIS_PROGRAM \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This struct represents the shaders that make up a program and the uniform
|
||||
|
@ -296,21 +61,6 @@ struct ProgramProfileOGL {
|
|||
std::ostringstream& fs);
|
||||
};
|
||||
|
||||
#if defined(DEBUG)
|
||||
# define CHECK_CURRENT_PROGRAM 1
|
||||
# define ASSERT_THIS_PROGRAM \
|
||||
do { \
|
||||
GLuint currentProgram; \
|
||||
mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, ¤tProgram); \
|
||||
MOZ_ASSERT(currentProgram == mProgram, \
|
||||
"SetUniform with wrong program active!"); \
|
||||
} while (0)
|
||||
#else
|
||||
# define ASSERT_THIS_PROGRAM \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Represents an OGL shader program. The details of a program are represented
|
||||
* by a ProgramProfileOGL
|
||||
|
@ -645,4 +395,4 @@ class ShaderProgramOGL {
|
|||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GFX_OGLSHADERPROGRAM_H */
|
||||
#endif // GFX_OGLSHADERPROGRAM_H
|
||||
|
|
|
@ -39,6 +39,17 @@ namespace layers {
|
|||
|
||||
class Compositor;
|
||||
|
||||
void ApplySamplingFilterToBoundTexture(gl::GLContext* aGL,
|
||||
gfx::SamplingFilter aSamplingFilter,
|
||||
GLuint aTarget) {
|
||||
GLenum filter =
|
||||
(aSamplingFilter == gfx::SamplingFilter::POINT ? LOCAL_GL_NEAREST
|
||||
: LOCAL_GL_LINEAR);
|
||||
|
||||
aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MIN_FILTER, filter);
|
||||
aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MAG_FILTER, filter);
|
||||
}
|
||||
|
||||
already_AddRefed<TextureHost> CreateTextureHostOGL(
|
||||
const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator,
|
||||
LayersBackend aBackend, TextureFlags aFlags) {
|
||||
|
|
|
@ -27,11 +27,10 @@
|
|||
#include "mozilla/layers/TextureHost.h" // for TextureHost, etc
|
||||
#include "mozilla/mozalloc.h" // for operator delete, etc
|
||||
#include "mozilla/webrender/RenderThread.h"
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsDebug.h" // for NS_WARNING
|
||||
#include "nsISupportsImpl.h" // for TextureImage::Release, etc
|
||||
#include "nsRegionFwd.h" // for nsIntRegion
|
||||
#include "OGLShaderProgram.h" // for ShaderProgramType, etc
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsDebug.h" // for NS_WARNING
|
||||
#include "nsISupportsImpl.h" // for TextureImage::Release, etc
|
||||
#include "nsRegionFwd.h" // for nsIntRegion
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
# include "GeneratedJNIWrappers.h"
|
||||
|
@ -50,16 +49,9 @@ class CompositorOGL;
|
|||
class TextureImageTextureSourceOGL;
|
||||
class GLTextureSource;
|
||||
|
||||
inline void ApplySamplingFilterToBoundTexture(
|
||||
gl::GLContext* aGL, gfx::SamplingFilter aSamplingFilter,
|
||||
GLuint aTarget = LOCAL_GL_TEXTURE_2D) {
|
||||
GLenum filter =
|
||||
(aSamplingFilter == gfx::SamplingFilter::POINT ? LOCAL_GL_NEAREST
|
||||
: LOCAL_GL_LINEAR);
|
||||
|
||||
aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MIN_FILTER, filter);
|
||||
aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MAG_FILTER, filter);
|
||||
}
|
||||
void ApplySamplingFilterToBoundTexture(gl::GLContext* aGL,
|
||||
gfx::SamplingFilter aSamplingFilter,
|
||||
GLuint aTarget = LOCAL_GL_TEXTURE_2D);
|
||||
|
||||
/*
|
||||
* TextureHost implementations for the OpenGL backend.
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "X11TextureSourceOGL.h"
|
||||
#include "gfxXlibSurface.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "GLContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "RenderAndroidSurfaceTextureHostOGL.h"
|
||||
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "GLContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace wr {
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "mozilla/layers/SynchronousTask.h"
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/VsyncDispatcher.h"
|
||||
|
||||
#include <list>
|
||||
|
@ -28,6 +27,9 @@
|
|||
#include <unordered_map>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
} // namespace gl
|
||||
namespace wr {
|
||||
|
||||
typedef MozPromise<MemoryReport, bool, true> MemoryReportPromise;
|
||||
|
|
|
@ -161,14 +161,13 @@ VertexInfo write_text_vertex(RectWithSize local_clip_rect,
|
|||
|
||||
void main(void) {
|
||||
int prim_header_address = aData.x;
|
||||
int glyph_index = aData.y;
|
||||
int glyph_index = aData.y & 0xffff;
|
||||
int raster_space = aData.y >> 16;
|
||||
int resource_address = aData.z;
|
||||
int subpx_dir = aData.w >> 16;
|
||||
int color_mode = aData.w & 0xffff;
|
||||
|
||||
PrimitiveHeader ph = fetch_prim_header(prim_header_address);
|
||||
int raster_space = ph.user_data.z;
|
||||
|
||||
Transform transform = fetch_transform(ph.transform_id);
|
||||
ClipArea clip_area = fetch_clip_area(ph.clip_task_index);
|
||||
PictureTask task = fetch_picture_task(ph.render_task_index);
|
||||
|
@ -193,8 +192,10 @@ void main(void) {
|
|||
RectWithSize glyph_rect = RectWithSize(res.offset + glyph_transform * (text_offset + glyph.offset),
|
||||
res.uv_rect.zw - res.uv_rect.xy);
|
||||
#else
|
||||
float inverse_raster_scale = float(ph.user_data.z) / 65535.0;
|
||||
|
||||
// Scale from glyph space to local space.
|
||||
float scale = res.scale / task.device_pixel_scale;
|
||||
float scale = inverse_raster_scale * res.scale / task.device_pixel_scale;
|
||||
|
||||
// Compute the glyph rect in local space.
|
||||
RectWithSize glyph_rect = RectWithSize(scale * res.offset + text_offset + glyph.offset,
|
||||
|
|
|
@ -851,7 +851,7 @@ impl AlphaBatchBuilder {
|
|||
[
|
||||
(run.reference_frame_relative_offset.x * 256.0) as i32,
|
||||
(run.reference_frame_relative_offset.y * 256.0) as i32,
|
||||
run.raster_space as i32,
|
||||
(run.inverse_raster_scale * 65535.0).round() as i32,
|
||||
],
|
||||
);
|
||||
let key = BatchKey::new(kind, blend_mode, textures);
|
||||
|
@ -866,7 +866,8 @@ impl AlphaBatchBuilder {
|
|||
|
||||
for glyph in glyphs {
|
||||
batch.push(base_instance.build(
|
||||
glyph.index_in_text_run,
|
||||
glyph.index_in_text_run |
|
||||
(run.raster_space as i32) << 16,
|
||||
glyph.uv_rect_address.as_int(),
|
||||
(subpx_dir as u32 as i32) << 16 |
|
||||
(color_mode as u32 as i32),
|
||||
|
@ -2539,12 +2540,11 @@ pub fn resolve_image(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Batcher managing draw calls into the clip mask (in the RT cache).
|
||||
/// A list of clip instances to be drawn into a target.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct ClipBatcher {
|
||||
pub struct ClipBatchList {
|
||||
/// Rectangle draws fill up the rectangles with rounded corners.
|
||||
pub rectangles: Vec<ClipMaskInstance>,
|
||||
/// Image draws apply the image masking.
|
||||
|
@ -2552,14 +2552,42 @@ pub struct ClipBatcher {
|
|||
pub box_shadows: FastHashMap<TextureSource, Vec<ClipMaskInstance>>,
|
||||
}
|
||||
|
||||
impl ClipBatcher {
|
||||
pub fn new() -> Self {
|
||||
ClipBatcher {
|
||||
impl ClipBatchList {
|
||||
fn new() -> Self {
|
||||
ClipBatchList {
|
||||
rectangles: Vec::new(),
|
||||
images: FastHashMap::default(),
|
||||
box_shadows: FastHashMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Batcher managing draw calls into the clip mask (in the RT cache).
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct ClipBatcher {
|
||||
/// The first clip in each clip task. This will overwrite all pixels
|
||||
/// in the clip region, so we can skip doing a clear and write with
|
||||
/// blending disabled, which is a big performance win on Intel GPUs.
|
||||
pub primary_clips: ClipBatchList,
|
||||
/// Any subsequent clip masks (rare) for a clip task get drawn in
|
||||
/// a second pass with multiplicative blending enabled.
|
||||
pub secondary_clips: ClipBatchList,
|
||||
|
||||
gpu_supports_fast_clears: bool,
|
||||
}
|
||||
|
||||
impl ClipBatcher {
|
||||
pub fn new(
|
||||
gpu_supports_fast_clears: bool,
|
||||
) -> Self {
|
||||
ClipBatcher {
|
||||
primary_clips: ClipBatchList::new(),
|
||||
secondary_clips: ClipBatchList::new(),
|
||||
gpu_supports_fast_clears,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_clip_region(
|
||||
&mut self,
|
||||
|
@ -2580,7 +2608,7 @@ impl ClipBatcher {
|
|||
snap_offsets: SnapOffsets::empty(),
|
||||
};
|
||||
|
||||
self.rectangles.push(instance);
|
||||
self.primary_clips.rectangles.push(instance);
|
||||
}
|
||||
|
||||
/// Where appropriate, draw a clip rectangle as a small series of tiles,
|
||||
|
@ -2595,6 +2623,7 @@ impl ClipBatcher {
|
|||
device_pixel_scale: DevicePixelScale,
|
||||
gpu_address: GpuCacheAddress,
|
||||
instance: &ClipMaskInstance,
|
||||
clip_node_index: u32,
|
||||
) -> bool {
|
||||
// Only try to draw in tiles if the clip mark is big enough.
|
||||
if mask_screen_rect.area() < CLIP_RECTANGLE_AREA_THRESHOLD {
|
||||
|
@ -2636,6 +2665,7 @@ impl ClipBatcher {
|
|||
// and only for rectangles (not rounded etc), the world_device_rect is not conservative - we know
|
||||
// that there is no inner_rect, and the world_device_rect should be the real, axis-aligned clip rect.
|
||||
let mask_origin = mask_screen_rect.origin.to_f32().to_vector();
|
||||
let clip_list = self.get_batch_list(clip_node_index);
|
||||
|
||||
for y in 0 .. y_tiles {
|
||||
for x in 0 .. x_tiles {
|
||||
|
@ -2660,7 +2690,7 @@ impl ClipBatcher {
|
|||
// these pixels would be redundant - since this clip can't possibly
|
||||
// affect the pixels in this tile, skip them!
|
||||
if !world_device_rect.contains_rect(&world_sub_rect) {
|
||||
self.rectangles.push(ClipMaskInstance {
|
||||
clip_list.rectangles.push(ClipMaskInstance {
|
||||
clip_data_address: gpu_address,
|
||||
sub_rect: normalized_sub_rect,
|
||||
..*instance
|
||||
|
@ -2672,6 +2702,19 @@ impl ClipBatcher {
|
|||
true
|
||||
}
|
||||
|
||||
/// Retrieve the correct clip batch list to append to, depending
|
||||
/// on whether this is the first clip mask for a clip task.
|
||||
fn get_batch_list(
|
||||
&mut self,
|
||||
item_index: u32,
|
||||
) -> &mut ClipBatchList {
|
||||
if item_index == 0 && !self.gpu_supports_fast_clears {
|
||||
&mut self.primary_clips
|
||||
} else {
|
||||
&mut self.secondary_clips
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(
|
||||
&mut self,
|
||||
task_address: RenderTaskAddress,
|
||||
|
@ -2739,7 +2782,9 @@ impl ClipBatcher {
|
|||
return;
|
||||
}
|
||||
};
|
||||
self.images
|
||||
|
||||
self.get_batch_list(i)
|
||||
.images
|
||||
.entry(cache_item.texture_id)
|
||||
.or_insert(Vec::new())
|
||||
.push(ClipMaskInstance {
|
||||
|
@ -2778,7 +2823,8 @@ impl ClipBatcher {
|
|||
.get_texture_cache_item(&rt_cache_entry.handle);
|
||||
debug_assert_ne!(cache_item.texture_id, TextureSource::Invalid);
|
||||
|
||||
self.box_shadows
|
||||
self.get_batch_list(i)
|
||||
.box_shadows
|
||||
.entry(cache_item.texture_id)
|
||||
.or_insert(Vec::new())
|
||||
.push(ClipMaskInstance {
|
||||
|
@ -2790,10 +2836,12 @@ impl ClipBatcher {
|
|||
ClipItem::Rectangle(_, ClipMode::ClipOut) => {
|
||||
let gpu_address =
|
||||
gpu_cache.get_address(&clip_node.gpu_cache_handle);
|
||||
self.rectangles.push(ClipMaskInstance {
|
||||
clip_data_address: gpu_address,
|
||||
..instance
|
||||
});
|
||||
self.get_batch_list(i)
|
||||
.rectangles
|
||||
.push(ClipMaskInstance {
|
||||
clip_data_address: gpu_address,
|
||||
..instance
|
||||
});
|
||||
}
|
||||
ClipItem::Rectangle(clip_rect_size, ClipMode::Clip) => {
|
||||
if !clip_instance.flags.contains(ClipNodeFlags::SAME_COORD_SYSTEM) {
|
||||
|
@ -2808,21 +2856,26 @@ impl ClipBatcher {
|
|||
device_pixel_scale,
|
||||
gpu_address,
|
||||
&instance,
|
||||
i,
|
||||
) {
|
||||
self.rectangles.push(ClipMaskInstance {
|
||||
clip_data_address: gpu_address,
|
||||
..instance
|
||||
});
|
||||
self.get_batch_list(i)
|
||||
.rectangles
|
||||
.push(ClipMaskInstance {
|
||||
clip_data_address: gpu_address,
|
||||
..instance
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
ClipItem::RoundedRectangle(..) => {
|
||||
let gpu_address =
|
||||
gpu_cache.get_address(&clip_node.gpu_cache_handle);
|
||||
self.rectangles.push(ClipMaskInstance {
|
||||
clip_data_address: gpu_address,
|
||||
..instance
|
||||
});
|
||||
self.get_batch_list(i)
|
||||
.rectangles
|
||||
.push(ClipMaskInstance {
|
||||
clip_data_address: gpu_address,
|
||||
..instance
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ pub struct FrameBuilderConfig {
|
|||
pub enable_picture_caching: bool,
|
||||
/// True if we're running tests (i.e. via wrench).
|
||||
pub testing: bool,
|
||||
pub gpu_supports_fast_clears: bool,
|
||||
}
|
||||
|
||||
/// A set of common / global resources that are retained between
|
||||
|
@ -138,6 +139,7 @@ pub struct FrameBuildingContext<'a> {
|
|||
pub clip_scroll_tree: &'a ClipScrollTree,
|
||||
pub max_local_clip: LayoutRect,
|
||||
pub debug_flags: DebugFlags,
|
||||
pub fb_config: &'a FrameBuilderConfig,
|
||||
}
|
||||
|
||||
pub struct FrameBuildingState<'a> {
|
||||
|
@ -234,6 +236,7 @@ impl FrameBuilder {
|
|||
chase_primitive: ChasePrimitive::Nothing,
|
||||
enable_picture_caching: false,
|
||||
testing: false,
|
||||
gpu_supports_fast_clears: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -338,6 +341,7 @@ impl FrameBuilder {
|
|||
LayoutSize::new(2.0 * MAX_CLIP_COORD, 2.0 * MAX_CLIP_COORD),
|
||||
),
|
||||
debug_flags,
|
||||
fb_config: &self.config,
|
||||
};
|
||||
|
||||
// Construct a dummy root surface, that represents the
|
||||
|
@ -577,13 +581,14 @@ impl FrameBuilder {
|
|||
|
||||
// Add passes as required for our cached render tasks.
|
||||
if !render_tasks.cacheable_render_tasks.is_empty() {
|
||||
passes.push(RenderPass::new_off_screen(screen_size));
|
||||
passes.push(RenderPass::new_off_screen(screen_size, self.config.gpu_supports_fast_clears));
|
||||
for cacheable_render_task in &render_tasks.cacheable_render_tasks {
|
||||
render_tasks.assign_to_passes(
|
||||
*cacheable_render_task,
|
||||
0,
|
||||
screen_size,
|
||||
&mut passes,
|
||||
self.config.gpu_supports_fast_clears,
|
||||
);
|
||||
}
|
||||
passes.reverse();
|
||||
|
@ -591,12 +596,13 @@ impl FrameBuilder {
|
|||
|
||||
if let Some(main_render_task_id) = main_render_task_id {
|
||||
let passes_start = passes.len();
|
||||
passes.push(RenderPass::new_main_framebuffer(screen_size));
|
||||
passes.push(RenderPass::new_main_framebuffer(screen_size, self.config.gpu_supports_fast_clears));
|
||||
render_tasks.assign_to_passes(
|
||||
main_render_task_id,
|
||||
passes_start,
|
||||
screen_size,
|
||||
&mut passes,
|
||||
self.config.gpu_supports_fast_clears,
|
||||
);
|
||||
passes[passes_start..].reverse();
|
||||
}
|
||||
|
|
|
@ -946,6 +946,7 @@ impl BrushSegment {
|
|||
root_spatial_node_index: SpatialNodeIndex,
|
||||
surface_index: SurfaceIndex,
|
||||
pic_state: &mut PictureState,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
clip_data_store: &mut ClipDataStore,
|
||||
unclipped: &DeviceRect,
|
||||
|
@ -996,6 +997,7 @@ impl BrushSegment {
|
|||
clip_data_store,
|
||||
snap_offsets,
|
||||
device_pixel_scale,
|
||||
frame_context.fb_config,
|
||||
);
|
||||
|
||||
let clip_task_id = frame_state.render_tasks.add(clip_task);
|
||||
|
@ -3297,6 +3299,7 @@ impl PrimitiveInstance {
|
|||
root_spatial_node_index,
|
||||
pic_context.surface_index,
|
||||
pic_state,
|
||||
frame_context,
|
||||
frame_state,
|
||||
&mut data_stores.clip,
|
||||
unclipped,
|
||||
|
@ -3337,6 +3340,7 @@ impl PrimitiveInstance {
|
|||
root_spatial_node_index,
|
||||
pic_context.surface_index,
|
||||
pic_state,
|
||||
frame_context,
|
||||
frame_state,
|
||||
&mut data_stores.clip,
|
||||
unclipped,
|
||||
|
@ -3439,6 +3443,7 @@ impl PrimitiveInstance {
|
|||
&mut data_stores.clip,
|
||||
snap_offsets,
|
||||
device_pixel_scale,
|
||||
frame_context.fb_config,
|
||||
);
|
||||
|
||||
let clip_task_id = frame_state.render_tasks.add(clip_task);
|
||||
|
|
|
@ -68,6 +68,7 @@ impl AsInstanceKind<TextRunDataHandle> for TextRunKey {
|
|||
reference_frame_relative_offset,
|
||||
shadow: self.shadow,
|
||||
raster_space: RasterizationSpace::Screen,
|
||||
inverse_raster_scale: 1.0,
|
||||
});
|
||||
|
||||
PrimitiveInstanceKind::TextRun{ data_handle, run_index }
|
||||
|
@ -214,6 +215,7 @@ pub struct TextRunPrimitive {
|
|||
pub reference_frame_relative_offset: LayoutVector2D,
|
||||
pub shadow: bool,
|
||||
pub raster_space: RasterizationSpace,
|
||||
pub inverse_raster_scale: f32,
|
||||
}
|
||||
|
||||
impl TextRunPrimitive {
|
||||
|
@ -225,8 +227,20 @@ impl TextRunPrimitive {
|
|||
allow_subpixel_aa: bool,
|
||||
raster_space: RasterSpace,
|
||||
) -> bool {
|
||||
// If local raster space is specified, include that in the scale
|
||||
// of the glyphs that get rasterized.
|
||||
// TODO(gw): Once we support proper local space raster modes, this
|
||||
// will implicitly be part of the device pixel ratio for
|
||||
// the (cached) local space surface, and so this code
|
||||
// will no longer be required.
|
||||
let raster_scale = match raster_space {
|
||||
RasterSpace::Screen => 1.0,
|
||||
RasterSpace::Local(scale) => scale.max(0.001),
|
||||
};
|
||||
self.inverse_raster_scale = 1.0 / raster_scale;
|
||||
|
||||
// Get the current font size in device pixels
|
||||
let device_font_size = specified_font.size.scale_by(device_pixel_scale.0);
|
||||
let device_font_size = specified_font.size.scale_by(device_pixel_scale.0 * raster_scale);
|
||||
|
||||
// Determine if rasterizing glyphs in local or screen space.
|
||||
// Only support transforms that can be coerced to simple 2D transforms.
|
||||
|
@ -337,5 +351,5 @@ fn test_struct_sizes() {
|
|||
assert_eq!(mem::size_of::<TextRun>(), 88, "TextRun size changed");
|
||||
assert_eq!(mem::size_of::<TextRunTemplate>(), 104, "TextRunTemplate size changed");
|
||||
assert_eq!(mem::size_of::<TextRunKey>(), 96, "TextRunKey size changed");
|
||||
assert_eq!(mem::size_of::<TextRunPrimitive>(), 96, "TextRunPrimitive size changed");
|
||||
assert_eq!(mem::size_of::<TextRunPrimitive>(), 104, "TextRunPrimitive size changed");
|
||||
}
|
||||
|
|
|
@ -4,16 +4,17 @@
|
|||
|
||||
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceSize, DeviceIntSideOffsets};
|
||||
use api::{DevicePixelScale, ImageDescriptor, ImageFormat, LayoutPoint};
|
||||
use api::{LineStyle, LineOrientation, LayoutSize, DirtyRect};
|
||||
use api::{LineStyle, LineOrientation, LayoutSize, DirtyRect, ClipMode};
|
||||
#[cfg(feature = "pathfinder")]
|
||||
use api::FontRenderMode;
|
||||
use border::BorderSegmentCacheKey;
|
||||
use box_shadow::{BoxShadowCacheKey};
|
||||
use clip::{ClipDataStore, ClipItem, ClipStore, ClipNodeRange};
|
||||
use clip::{ClipDataStore, ClipItem, ClipStore, ClipNodeRange, ClipNodeFlags};
|
||||
use clip_scroll_tree::SpatialNodeIndex;
|
||||
use device::TextureFilter;
|
||||
#[cfg(feature = "pathfinder")]
|
||||
use euclid::{TypedPoint2D, TypedVector2D};
|
||||
use frame_builder::FrameBuilderConfig;
|
||||
use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
|
||||
use glyph_rasterizer::GpuGlyphCacheKey;
|
||||
use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
|
||||
|
@ -146,6 +147,7 @@ impl RenderTaskTree {
|
|||
pass_index: usize,
|
||||
screen_size: DeviceIntSize,
|
||||
passes: &mut Vec<RenderPass>,
|
||||
gpu_supports_fast_clears: bool,
|
||||
) {
|
||||
debug_assert!(pass_index < passes.len());
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -155,10 +157,10 @@ impl RenderTaskTree {
|
|||
if !task.children.is_empty() {
|
||||
let child_index = pass_index + 1;
|
||||
if passes.len() == child_index {
|
||||
passes.push(RenderPass::new_off_screen(screen_size));
|
||||
passes.push(RenderPass::new_off_screen(screen_size, gpu_supports_fast_clears));
|
||||
}
|
||||
for child in &task.children {
|
||||
self.assign_to_passes(*child, child_index, screen_size, passes);
|
||||
self.assign_to_passes(*child, child_index, screen_size, passes, gpu_supports_fast_clears);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -416,6 +418,8 @@ pub enum ClearMode {
|
|||
// Applicable to color and alpha targets.
|
||||
Zero,
|
||||
One,
|
||||
/// This task doesn't care what it is cleared to - it will completely overwrite it.
|
||||
DontCare,
|
||||
|
||||
// Applicable to color targets only.
|
||||
Transparent,
|
||||
|
@ -566,6 +570,7 @@ impl RenderTask {
|
|||
clip_data_store: &mut ClipDataStore,
|
||||
snap_offsets: SnapOffsets,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
fb_config: &FrameBuilderConfig,
|
||||
) -> Self {
|
||||
// Step through the clip sources that make up this mask. If we find
|
||||
// any box-shadow clip sources, request that image from the render
|
||||
|
@ -576,6 +581,8 @@ impl RenderTask {
|
|||
// TODO(gw): If this ever shows up in a profile, we could pre-calculate
|
||||
// whether a ClipSources contains any box-shadows and skip
|
||||
// this iteration for the majority of cases.
|
||||
let mut needs_clear = fb_config.gpu_supports_fast_clears;
|
||||
|
||||
for i in 0 .. clip_node_range.count {
|
||||
let clip_instance = clip_store.get_instance_from_range(&clip_node_range, i);
|
||||
let clip_node = &mut clip_data_store[clip_instance.handle];
|
||||
|
@ -606,6 +613,7 @@ impl RenderTask {
|
|||
clip_data_address,
|
||||
info.minimal_shadow_rect.origin,
|
||||
device_pixel_scale,
|
||||
fb_config,
|
||||
);
|
||||
|
||||
let mask_task_id = render_tasks.add(mask_task);
|
||||
|
@ -623,12 +631,30 @@ impl RenderTask {
|
|||
}
|
||||
));
|
||||
}
|
||||
ClipItem::Rectangle(..) |
|
||||
ClipItem::Rectangle(_, ClipMode::Clip) => {
|
||||
if !clip_instance.flags.contains(ClipNodeFlags::SAME_COORD_SYSTEM) {
|
||||
// This is conservative - it's only the case that we actually need
|
||||
// a clear here if we end up adding this mask via add_tiled_clip_mask,
|
||||
// but for simplicity we will just clear if any of these are encountered,
|
||||
// since they are rare.
|
||||
needs_clear = true;
|
||||
}
|
||||
}
|
||||
ClipItem::Rectangle(_, ClipMode::ClipOut) |
|
||||
ClipItem::RoundedRectangle(..) |
|
||||
ClipItem::Image { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a potentially tiled clip mask, clear the mask area first. Otherwise,
|
||||
// the first (primary) clip mask will overwrite all the clip mask pixels with
|
||||
// blending disabled to set to the initial value.
|
||||
let clear_mode = if needs_clear {
|
||||
ClearMode::One
|
||||
} else {
|
||||
ClearMode::DontCare
|
||||
};
|
||||
|
||||
RenderTask::with_dynamic_location(
|
||||
outer_rect.size,
|
||||
vec![],
|
||||
|
@ -639,7 +665,7 @@ impl RenderTask {
|
|||
snap_offsets,
|
||||
device_pixel_scale,
|
||||
}),
|
||||
ClearMode::One,
|
||||
clear_mode,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -648,7 +674,14 @@ impl RenderTask {
|
|||
clip_data_address: GpuCacheAddress,
|
||||
local_pos: LayoutPoint,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
fb_config: &FrameBuilderConfig,
|
||||
) -> Self {
|
||||
let clear_mode = if fb_config.gpu_supports_fast_clears {
|
||||
ClearMode::One
|
||||
} else {
|
||||
ClearMode::DontCare
|
||||
};
|
||||
|
||||
RenderTask::with_dynamic_location(
|
||||
size,
|
||||
Vec::new(),
|
||||
|
@ -657,7 +690,7 @@ impl RenderTask {
|
|||
local_pos,
|
||||
device_pixel_scale,
|
||||
}),
|
||||
ClearMode::One,
|
||||
clear_mode,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -788,10 +821,7 @@ impl RenderTask {
|
|||
uv_rect_handle: GpuCacheHandle::new(),
|
||||
uv_rect_kind,
|
||||
}),
|
||||
match target_kind {
|
||||
RenderTargetKind::Color => ClearMode::Transparent,
|
||||
RenderTargetKind::Alpha => ClearMode::One,
|
||||
},
|
||||
ClearMode::DontCare,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ use api::{channel};
|
|||
use api::DebugCommand;
|
||||
pub use api::DebugFlags;
|
||||
use api::channel::PayloadReceiverHelperMethods;
|
||||
use batch::{BatchKind, BatchTextures, BrushBatchKind};
|
||||
use batch::{BatchKind, BatchTextures, BrushBatchKind, ClipBatchList};
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
use capture::{CaptureConfig, ExternalCaptureImage, PlainExternalImage};
|
||||
use debug_colors;
|
||||
|
@ -1829,6 +1829,7 @@ impl Renderer {
|
|||
chase_primitive: options.chase_primitive,
|
||||
enable_picture_caching: options.enable_picture_caching,
|
||||
testing: options.testing,
|
||||
gpu_supports_fast_clears: options.gpu_supports_fast_clears,
|
||||
};
|
||||
|
||||
let device_pixel_ratio = options.device_pixel_ratio;
|
||||
|
@ -2256,10 +2257,20 @@ impl Renderer {
|
|||
"Zero Clears",
|
||||
target.zero_clears.len(),
|
||||
);
|
||||
debug_target.add(
|
||||
debug_server::BatchKind::Cache,
|
||||
"One Clears",
|
||||
target.one_clears.len(),
|
||||
);
|
||||
debug_target.add(
|
||||
debug_server::BatchKind::Clip,
|
||||
"BoxShadows",
|
||||
target.clip_batcher.box_shadows.len(),
|
||||
"BoxShadows [p]",
|
||||
target.clip_batcher.primary_clips.box_shadows.len(),
|
||||
);
|
||||
debug_target.add(
|
||||
debug_server::BatchKind::Clip,
|
||||
"BoxShadows [s]",
|
||||
target.clip_batcher.secondary_clips.box_shadows.len(),
|
||||
);
|
||||
debug_target.add(
|
||||
debug_server::BatchKind::Cache,
|
||||
|
@ -2273,11 +2284,19 @@ impl Renderer {
|
|||
);
|
||||
debug_target.add(
|
||||
debug_server::BatchKind::Clip,
|
||||
"Rectangles",
|
||||
target.clip_batcher.rectangles.len(),
|
||||
"Rectangles [p]",
|
||||
target.clip_batcher.primary_clips.rectangles.len(),
|
||||
);
|
||||
for (_, items) in target.clip_batcher.images.iter() {
|
||||
debug_target.add(debug_server::BatchKind::Clip, "Image mask", items.len());
|
||||
debug_target.add(
|
||||
debug_server::BatchKind::Clip,
|
||||
"Rectangles [s]",
|
||||
target.clip_batcher.secondary_clips.rectangles.len(),
|
||||
);
|
||||
for (_, items) in target.clip_batcher.primary_clips.images.iter() {
|
||||
debug_target.add(debug_server::BatchKind::Clip, "Image mask [p]", items.len());
|
||||
}
|
||||
for (_, items) in target.clip_batcher.secondary_clips.images.iter() {
|
||||
debug_target.add(debug_server::BatchKind::Clip, "Image mask [s]", items.len());
|
||||
}
|
||||
|
||||
debug_target
|
||||
|
@ -3265,7 +3284,12 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
self.handle_scaling(&target.scalings, TextureSource::PrevPassColor, projection, stats);
|
||||
self.handle_scaling(
|
||||
&target.scalings,
|
||||
TextureSource::PrevPassColor,
|
||||
projection,
|
||||
stats,
|
||||
);
|
||||
|
||||
// Small helper fn to iterate a regions list, also invoking the closure
|
||||
// if there are no regions.
|
||||
|
@ -3550,6 +3574,69 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
/// Draw all the instances in a clip batcher list to the current target.
|
||||
fn draw_clip_batch_list(
|
||||
&mut self,
|
||||
list: &ClipBatchList,
|
||||
projection: &Transform3D<f32>,
|
||||
stats: &mut RendererStats,
|
||||
) {
|
||||
// draw rounded cornered rectangles
|
||||
if !list.rectangles.is_empty() {
|
||||
let _gm2 = self.gpu_profile.start_marker("clip rectangles");
|
||||
self.shaders.borrow_mut().cs_clip_rectangle.bind(
|
||||
&mut self.device,
|
||||
projection,
|
||||
&mut self.renderer_errors,
|
||||
);
|
||||
self.draw_instanced_batch(
|
||||
&list.rectangles,
|
||||
VertexArrayKind::Clip,
|
||||
&BatchTextures::no_texture(),
|
||||
stats,
|
||||
);
|
||||
}
|
||||
// draw box-shadow clips
|
||||
for (mask_texture_id, items) in list.box_shadows.iter() {
|
||||
let _gm2 = self.gpu_profile.start_marker("box-shadows");
|
||||
let textures = BatchTextures {
|
||||
colors: [
|
||||
mask_texture_id.clone(),
|
||||
TextureSource::Invalid,
|
||||
TextureSource::Invalid,
|
||||
],
|
||||
};
|
||||
self.shaders.borrow_mut().cs_clip_box_shadow
|
||||
.bind(&mut self.device, projection, &mut self.renderer_errors);
|
||||
self.draw_instanced_batch(
|
||||
items,
|
||||
VertexArrayKind::Clip,
|
||||
&textures,
|
||||
stats,
|
||||
);
|
||||
}
|
||||
|
||||
// draw image masks
|
||||
for (mask_texture_id, items) in list.images.iter() {
|
||||
let _gm2 = self.gpu_profile.start_marker("clip images");
|
||||
let textures = BatchTextures {
|
||||
colors: [
|
||||
mask_texture_id.clone(),
|
||||
TextureSource::Invalid,
|
||||
TextureSource::Invalid,
|
||||
],
|
||||
};
|
||||
self.shaders.borrow_mut().cs_clip_image
|
||||
.bind(&mut self.device, projection, &mut self.renderer_errors);
|
||||
self.draw_instanced_batch(
|
||||
items,
|
||||
VertexArrayKind::Clip,
|
||||
&textures,
|
||||
stats,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_alpha_target(
|
||||
&mut self,
|
||||
draw_target: DrawTarget,
|
||||
|
@ -3567,18 +3654,13 @@ impl Renderer {
|
|||
self.device.bind_draw_target(draw_target);
|
||||
self.device.disable_depth();
|
||||
self.device.disable_depth_write();
|
||||
self.set_blend(false, FramebufferKind::Other);
|
||||
|
||||
// TODO(gw): Applying a scissor rect and minimal clear here
|
||||
// is a very large performance win on the Intel and nVidia
|
||||
// GPUs that I have tested with. It's possible it may be a
|
||||
// performance penalty on other GPU types - we should test this
|
||||
// and consider different code paths.
|
||||
let clear_color = [1.0, 1.0, 1.0, 0.0];
|
||||
self.device.clear_target(
|
||||
Some(clear_color),
|
||||
None,
|
||||
Some(target.used_rect()),
|
||||
);
|
||||
|
||||
let zero_color = [0.0, 0.0, 0.0, 0.0];
|
||||
for &task_id in &target.zero_clears {
|
||||
|
@ -3589,6 +3671,16 @@ impl Renderer {
|
|||
Some(rect),
|
||||
);
|
||||
}
|
||||
|
||||
let one_color = [1.0, 1.0, 1.0, 1.0];
|
||||
for &task_id in &target.one_clears {
|
||||
let (rect, _) = render_tasks[task_id].get_target_rect();
|
||||
self.device.clear_target(
|
||||
Some(one_color),
|
||||
None,
|
||||
Some(rect),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw any blurs for this target.
|
||||
|
@ -3600,7 +3692,6 @@ impl Renderer {
|
|||
if !target.vertical_blurs.is_empty() || !target.horizontal_blurs.is_empty() {
|
||||
let _timer = self.gpu_profile.start_timer(GPU_TAG_BLUR);
|
||||
|
||||
self.set_blend(false, FramebufferKind::Other);
|
||||
self.shaders.borrow_mut().cs_blur_a8
|
||||
.bind(&mut self.device, projection, &mut self.renderer_errors);
|
||||
|
||||
|
@ -3623,70 +3714,39 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
self.handle_scaling(&target.scalings, TextureSource::PrevPassAlpha, projection, stats);
|
||||
self.handle_scaling(
|
||||
&target.scalings,
|
||||
TextureSource::PrevPassAlpha,
|
||||
projection,
|
||||
stats,
|
||||
);
|
||||
|
||||
// Draw the clip items into the tiled alpha mask.
|
||||
{
|
||||
let _timer = self.gpu_profile.start_timer(GPU_TAG_CACHE_CLIP);
|
||||
|
||||
// switch to multiplicative blending
|
||||
// TODO(gw): Consider grouping multiple clip masks per shader
|
||||
// invocation here to reduce memory bandwith further?
|
||||
|
||||
// Draw the primary clip mask - since this is the first mask
|
||||
// for the task, we can disable blending, knowing that it will
|
||||
// overwrite every pixel in the mask area.
|
||||
self.set_blend(false, FramebufferKind::Other);
|
||||
self.draw_clip_batch_list(
|
||||
&target.clip_batcher.primary_clips,
|
||||
projection,
|
||||
stats,
|
||||
);
|
||||
|
||||
// switch to multiplicative blending for secondary masks, using
|
||||
// multiplicative blending to accumulate clips into the mask.
|
||||
self.set_blend(true, FramebufferKind::Other);
|
||||
self.set_blend_mode_multiply(FramebufferKind::Other);
|
||||
|
||||
// draw rounded cornered rectangles
|
||||
if !target.clip_batcher.rectangles.is_empty() {
|
||||
let _gm2 = self.gpu_profile.start_marker("clip rectangles");
|
||||
self.shaders.borrow_mut().cs_clip_rectangle.bind(
|
||||
&mut self.device,
|
||||
projection,
|
||||
&mut self.renderer_errors,
|
||||
);
|
||||
self.draw_instanced_batch(
|
||||
&target.clip_batcher.rectangles,
|
||||
VertexArrayKind::Clip,
|
||||
&BatchTextures::no_texture(),
|
||||
stats,
|
||||
);
|
||||
}
|
||||
// draw box-shadow clips
|
||||
for (mask_texture_id, items) in target.clip_batcher.box_shadows.iter() {
|
||||
let _gm2 = self.gpu_profile.start_marker("box-shadows");
|
||||
let textures = BatchTextures {
|
||||
colors: [
|
||||
mask_texture_id.clone(),
|
||||
TextureSource::Invalid,
|
||||
TextureSource::Invalid,
|
||||
],
|
||||
};
|
||||
self.shaders.borrow_mut().cs_clip_box_shadow
|
||||
.bind(&mut self.device, projection, &mut self.renderer_errors);
|
||||
self.draw_instanced_batch(
|
||||
items,
|
||||
VertexArrayKind::Clip,
|
||||
&textures,
|
||||
stats,
|
||||
);
|
||||
}
|
||||
|
||||
// draw image masks
|
||||
for (mask_texture_id, items) in target.clip_batcher.images.iter() {
|
||||
let _gm2 = self.gpu_profile.start_marker("clip images");
|
||||
let textures = BatchTextures {
|
||||
colors: [
|
||||
mask_texture_id.clone(),
|
||||
TextureSource::Invalid,
|
||||
TextureSource::Invalid,
|
||||
],
|
||||
};
|
||||
self.shaders.borrow_mut().cs_clip_image
|
||||
.bind(&mut self.device, projection, &mut self.renderer_errors);
|
||||
self.draw_instanced_batch(
|
||||
items,
|
||||
VertexArrayKind::Clip,
|
||||
&textures,
|
||||
stats,
|
||||
);
|
||||
}
|
||||
self.draw_clip_batch_list(
|
||||
&target.clip_batcher.secondary_clips,
|
||||
projection,
|
||||
stats,
|
||||
);
|
||||
}
|
||||
|
||||
self.gpu_profile.finish_sampler(alpha_sampler);
|
||||
|
@ -4934,6 +4994,11 @@ pub struct RendererOptions {
|
|||
pub namespace_alloc_by_client: bool,
|
||||
pub enable_picture_caching: bool,
|
||||
pub testing: bool,
|
||||
/// Set to true if this GPU supports hardware fast clears as a performance
|
||||
/// optimization. Likely requires benchmarking on various GPUs to see if
|
||||
/// it is a performance win. The default is false, which tends to be best
|
||||
/// performance on lower end / integrated GPUs.
|
||||
pub gpu_supports_fast_clears: bool,
|
||||
}
|
||||
|
||||
impl Default for RendererOptions {
|
||||
|
@ -4972,6 +5037,7 @@ impl Default for RendererOptions {
|
|||
namespace_alloc_by_client: false,
|
||||
enable_picture_caching: false,
|
||||
testing: false,
|
||||
gpu_supports_fast_clears: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,10 @@ pub struct RenderTargetContext<'a, 'rc> {
|
|||
/// and sometimes on its parameters. See `RenderTask::target_kind`.
|
||||
pub trait RenderTarget {
|
||||
/// Creates a new RenderTarget of the given type.
|
||||
fn new(screen_size: DeviceIntSize) -> Self;
|
||||
fn new(
|
||||
screen_size: DeviceIntSize,
|
||||
gpu_supports_fast_clears: bool,
|
||||
) -> Self;
|
||||
|
||||
/// Optional hook to provide additional processing for the target at the
|
||||
/// end of the build phase.
|
||||
|
@ -170,12 +173,14 @@ pub struct RenderTargetList<T> {
|
|||
pub targets: Vec<T>,
|
||||
pub saved_index: Option<SavedTargetIndex>,
|
||||
pub alloc_tracker: ArrayAllocationTracker,
|
||||
gpu_supports_fast_clears: bool,
|
||||
}
|
||||
|
||||
impl<T: RenderTarget> RenderTargetList<T> {
|
||||
fn new(
|
||||
screen_size: DeviceIntSize,
|
||||
format: ImageFormat,
|
||||
gpu_supports_fast_clears: bool,
|
||||
) -> Self {
|
||||
RenderTargetList {
|
||||
screen_size,
|
||||
|
@ -184,6 +189,7 @@ impl<T: RenderTarget> RenderTargetList<T> {
|
|||
targets: Vec::new(),
|
||||
saved_index: None,
|
||||
alloc_tracker: ArrayAllocationTracker::new(),
|
||||
gpu_supports_fast_clears,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,7 +242,7 @@ impl<T: RenderTarget> RenderTargetList<T> {
|
|||
assert!(alloc_size.width <= allocator_dimensions.width &&
|
||||
alloc_size.height <= allocator_dimensions.height);
|
||||
let slice = FreeRectSlice(self.targets.len() as u32);
|
||||
self.targets.push(T::new(self.screen_size));
|
||||
self.targets.push(T::new(self.screen_size, self.gpu_supports_fast_clears));
|
||||
|
||||
self.alloc_tracker.extend(
|
||||
slice,
|
||||
|
@ -250,7 +256,7 @@ impl<T: RenderTarget> RenderTargetList<T> {
|
|||
|
||||
if alloc_size.is_empty_or_negative() && self.targets.is_empty() {
|
||||
// push an unused target here, only if we don't have any
|
||||
self.targets.push(T::new(self.screen_size));
|
||||
self.targets.push(T::new(self.screen_size, self.gpu_supports_fast_clears));
|
||||
}
|
||||
|
||||
self.targets[free_rect_slice.0 as usize]
|
||||
|
@ -356,7 +362,10 @@ pub struct ColorRenderTarget {
|
|||
}
|
||||
|
||||
impl RenderTarget for ColorRenderTarget {
|
||||
fn new(screen_size: DeviceIntSize) -> Self {
|
||||
fn new(
|
||||
screen_size: DeviceIntSize,
|
||||
_: bool,
|
||||
) -> Self {
|
||||
ColorRenderTarget {
|
||||
alpha_batch_containers: Vec::new(),
|
||||
vertical_blurs: Vec::new(),
|
||||
|
@ -391,6 +400,7 @@ impl RenderTarget for ColorRenderTarget {
|
|||
ClearMode::Zero => {
|
||||
panic!("bug: invalid clear mode for color task");
|
||||
}
|
||||
ClearMode::DontCare |
|
||||
ClearMode::Transparent => {}
|
||||
}
|
||||
|
||||
|
@ -578,6 +588,7 @@ pub struct AlphaRenderTarget {
|
|||
pub horizontal_blurs: Vec<BlurInstance>,
|
||||
pub scalings: Vec<ScalingInstance>,
|
||||
pub zero_clears: Vec<RenderTaskId>,
|
||||
pub one_clears: Vec<RenderTaskId>,
|
||||
// Track the used rect of the render target, so that
|
||||
// we can set a scissor rect and only clear to the
|
||||
// used portion of the target as an optimization.
|
||||
|
@ -585,13 +596,17 @@ pub struct AlphaRenderTarget {
|
|||
}
|
||||
|
||||
impl RenderTarget for AlphaRenderTarget {
|
||||
fn new(_screen_size: DeviceIntSize) -> Self {
|
||||
fn new(
|
||||
_screen_size: DeviceIntSize,
|
||||
gpu_supports_fast_clears: bool,
|
||||
) -> Self {
|
||||
AlphaRenderTarget {
|
||||
clip_batcher: ClipBatcher::new(),
|
||||
clip_batcher: ClipBatcher::new(gpu_supports_fast_clears),
|
||||
vertical_blurs: Vec::new(),
|
||||
horizontal_blurs: Vec::new(),
|
||||
scalings: Vec::new(),
|
||||
zero_clears: Vec::new(),
|
||||
one_clears: Vec::new(),
|
||||
used_rect: DeviceIntRect::zero(),
|
||||
}
|
||||
}
|
||||
|
@ -612,7 +627,10 @@ impl RenderTarget for AlphaRenderTarget {
|
|||
ClearMode::Zero => {
|
||||
self.zero_clears.push(task_id);
|
||||
}
|
||||
ClearMode::One => {}
|
||||
ClearMode::One => {
|
||||
self.one_clears.push(task_id);
|
||||
}
|
||||
ClearMode::DontCare => {}
|
||||
ClearMode::Transparent => {
|
||||
panic!("bug: invalid clear mode for alpha task");
|
||||
}
|
||||
|
@ -858,8 +876,11 @@ pub struct RenderPass {
|
|||
impl RenderPass {
|
||||
/// Creates a pass for the main framebuffer. There is only one of these, and
|
||||
/// it is always the last pass.
|
||||
pub fn new_main_framebuffer(screen_size: DeviceIntSize) -> Self {
|
||||
let target = ColorRenderTarget::new(screen_size);
|
||||
pub fn new_main_framebuffer(
|
||||
screen_size: DeviceIntSize,
|
||||
gpu_supports_fast_clears: bool,
|
||||
) -> Self {
|
||||
let target = ColorRenderTarget::new(screen_size, gpu_supports_fast_clears);
|
||||
RenderPass {
|
||||
kind: RenderPassKind::MainFramebuffer(target),
|
||||
tasks: vec![],
|
||||
|
@ -867,11 +888,22 @@ impl RenderPass {
|
|||
}
|
||||
|
||||
/// Creates an intermediate off-screen pass.
|
||||
pub fn new_off_screen(screen_size: DeviceIntSize) -> Self {
|
||||
pub fn new_off_screen(
|
||||
screen_size: DeviceIntSize,
|
||||
gpu_supports_fast_clears: bool,
|
||||
) -> Self {
|
||||
RenderPass {
|
||||
kind: RenderPassKind::OffScreen {
|
||||
color: RenderTargetList::new(screen_size, ImageFormat::BGRA8),
|
||||
alpha: RenderTargetList::new(screen_size, ImageFormat::R8),
|
||||
color: RenderTargetList::new(
|
||||
screen_size,
|
||||
ImageFormat::BGRA8,
|
||||
gpu_supports_fast_clears,
|
||||
),
|
||||
alpha: RenderTargetList::new(
|
||||
screen_size,
|
||||
ImageFormat::R8,
|
||||
gpu_supports_fast_clears,
|
||||
),
|
||||
texture_cache: FastHashMap::default(),
|
||||
},
|
||||
tasks: vec![],
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
# Benchmark to test the cost of clears on a clip mask target that
|
||||
# is large but has low usage.
|
||||
---
|
||||
root:
|
||||
items:
|
||||
-
|
||||
bounds: 0 0 1000 1000
|
||||
type: stacking-context
|
||||
items:
|
||||
- type: clip
|
||||
bounds: [50, 50, 300, 300]
|
||||
complex:
|
||||
- rect: [50, 50, 300, 300]
|
||||
radius: 50
|
||||
items:
|
||||
- type: rect
|
||||
bounds: 50 50 300 300
|
||||
color: red
|
||||
- type: rect
|
||||
bounds: 50 50 300 300
|
||||
color: red
|
||||
- type: rect
|
||||
bounds: 50 50 300 300
|
||||
color: red
|
||||
- type: rect
|
||||
bounds: 50 50 300 300
|
||||
color: red
|
||||
- type: rect
|
||||
bounds: 50 50 300 300
|
||||
color: red
|
||||
- type: rect
|
||||
bounds: 50 50 300 300
|
||||
color: red
|
||||
- type: rect
|
||||
bounds: 50 50 300 300
|
||||
color: red
|
||||
- type: rect
|
||||
bounds: 50 50 300 300
|
||||
color: red
|
||||
- type: rect
|
||||
bounds: 50 50 300 300
|
||||
color: red
|
||||
- type: rect
|
||||
bounds: 50 50 300 300
|
||||
color: red
|
||||
- type: rect
|
||||
bounds: 50 50 300 300
|
||||
color: red
|
Двоичные данные
gfx/wr/wrench/reftests/boxshadow/box-shadow-cache.png
До Ширина: | Высота: | Размер: 35 KiB После Ширина: | Высота: | Размер: 35 KiB |
До Ширина: | Высота: | Размер: 148 KiB После Ширина: | Высота: | Размер: 148 KiB |
До Ширина: | Высота: | Размер: 59 KiB После Ширина: | Высота: | Размер: 59 KiB |
Двоичные данные
gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-x.png
До Ширина: | Высота: | Размер: 16 KiB После Ширина: | Высота: | Размер: 16 KiB |
Двоичные данные
gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-blur.png
До Ширина: | Высота: | Размер: 84 KiB После Ширина: | Высота: | Размер: 84 KiB |
Двоичные данные
gfx/wr/wrench/reftests/boxshadow/inset-mask-region.png
До Ширина: | Высота: | Размер: 24 KiB После Ширина: | Высота: | Размер: 24 KiB |
Двоичные данные
gfx/wr/wrench/reftests/text/raster-space.png
До Ширина: | Высота: | Размер: 44 KiB После Ширина: | Высота: | Размер: 61 KiB |
|
@ -17,3 +17,12 @@ root:
|
|||
origin: 20 50
|
||||
size: 20
|
||||
font: "FreeSans.ttf"
|
||||
- type: stacking-context
|
||||
transform: scale(5.0) rotate(45)
|
||||
transform-origin: -80 240
|
||||
raster-space: local(5.0)
|
||||
items:
|
||||
- text: "Local (scaled)"
|
||||
origin: 20 50
|
||||
size: 10
|
||||
font: "FreeSans.ttf"
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Functions for controlling profilers from within JS: Valgrind, Perf,
|
||||
* Shark, etc.
|
||||
* Functions for controlling profilers from within JS: Valgrind, Perf, etc
|
||||
*/
|
||||
#ifndef builtin_Profilers_h
|
||||
#define builtin_Profilers_h
|
||||
|
|
|
@ -1,190 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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/. */
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
# include "sharkctl.h"
|
||||
# include <stddef.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <unistd.h>
|
||||
|
||||
# include "jsutil.h"
|
||||
|
||||
# define SHARK_MSG_ACQUIRE 0x29a
|
||||
# define SHARK_MSG_RELEASE 0x29b
|
||||
# define SHARK_MSG_STOP 0x29c
|
||||
# define SHARK_MSG_START 0x29d
|
||||
|
||||
# define RECV_SIZEOF(ty) offsetof(ty, out)
|
||||
|
||||
// Private API in libSystem.dylib
|
||||
extern "C" void bootstrap_look_up(mach_port_t special_port, const char* name,
|
||||
mach_port_t* dest_port);
|
||||
|
||||
struct chud_client_acquire_msg {
|
||||
mach_msg_header_t hdr;
|
||||
uint32_t unk0; // always 0
|
||||
uint32_t unk1; // always 1
|
||||
uint32_t pid;
|
||||
uint32_t out[2];
|
||||
};
|
||||
|
||||
struct chud_client_start_msg {
|
||||
mach_msg_header_t hdr;
|
||||
uint32_t unk0; // always 1
|
||||
uint32_t name0;
|
||||
uint32_t arg2; // always 6
|
||||
uint8_t unk1; // always 0
|
||||
uint8_t unk2; // always 1
|
||||
uint8_t unk3; // uninitialized
|
||||
uint8_t unk4; // always 1
|
||||
uint32_t unk5; // always 0
|
||||
uint32_t unk6; // always 1
|
||||
uint32_t name1; // same as name0
|
||||
};
|
||||
|
||||
struct chud_client_stop_msg {
|
||||
mach_msg_header_t hdr;
|
||||
uint32_t out[5];
|
||||
};
|
||||
|
||||
struct chud_client_release_msg {
|
||||
mach_msg_header_t hdr;
|
||||
uint32_t unk0; // always 0
|
||||
uint32_t unk1; // always 1
|
||||
uint32_t pid;
|
||||
uint32_t out[2];
|
||||
};
|
||||
|
||||
static mach_port_t CreatePort(void) {
|
||||
mach_port_t bootstrap_port, shark_port = 0;
|
||||
task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT, &bootstrap_port);
|
||||
bootstrap_look_up(bootstrap_port, "CHUD_IPC", &shark_port);
|
||||
return shark_port;
|
||||
}
|
||||
|
||||
static mach_msg_return_t Connect(mach_port_t shark_port) {
|
||||
mach_port_t reply_port = mig_get_reply_port();
|
||||
|
||||
struct chud_client_acquire_msg msg;
|
||||
msg.hdr.msgh_bits = 0x1513;
|
||||
msg.hdr.msgh_size = sizeof(mach_msg_header_t);
|
||||
msg.hdr.msgh_remote_port = shark_port;
|
||||
msg.hdr.msgh_local_port = reply_port;
|
||||
msg.hdr.msgh_reserved = 0;
|
||||
msg.hdr.msgh_id = SHARK_MSG_ACQUIRE;
|
||||
msg.unk0 = 0;
|
||||
msg.unk1 = 1;
|
||||
msg.pid = getpid();
|
||||
|
||||
MOZ_ASSERT(RECV_SIZEOF(struct chud_client_acquire_msg) == 0x24);
|
||||
MOZ_ASSERT(sizeof(msg) == 0x2c);
|
||||
mach_msg_return_t result =
|
||||
mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
|
||||
RECV_SIZEOF(struct chud_client_acquire_msg), sizeof(msg),
|
||||
reply_port, 0, 0);
|
||||
mig_dealloc_reply_port(reply_port);
|
||||
return result;
|
||||
}
|
||||
|
||||
static mach_msg_return_t Start(mach_port_t shark_port, uint32_t name) {
|
||||
mach_port_t reply_port = mig_get_reply_port();
|
||||
|
||||
struct chud_client_start_msg msg;
|
||||
msg.hdr.msgh_bits = 0x80001513;
|
||||
msg.hdr.msgh_size = sizeof(mach_msg_header_t);
|
||||
msg.hdr.msgh_remote_port = shark_port;
|
||||
msg.hdr.msgh_local_port = reply_port;
|
||||
msg.hdr.msgh_reserved = 0;
|
||||
msg.hdr.msgh_id = SHARK_MSG_START;
|
||||
msg.unk0 = 1;
|
||||
msg.name0 = name;
|
||||
msg.arg2 = 6;
|
||||
msg.unk1 = 0;
|
||||
msg.unk2 = 1;
|
||||
msg.unk3 = 0;
|
||||
msg.unk4 = 1;
|
||||
msg.unk5 = 0;
|
||||
msg.unk6 = 1;
|
||||
msg.name1 = name;
|
||||
|
||||
MOZ_ASSERT(sizeof(msg) == 0x34);
|
||||
mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
|
||||
sizeof(msg), 0x30, reply_port, 0, 0);
|
||||
mig_dealloc_reply_port(reply_port);
|
||||
return result;
|
||||
}
|
||||
|
||||
mach_msg_return_t Stop(mach_port_t shark_port) {
|
||||
mach_port_t reply_port = mig_get_reply_port();
|
||||
|
||||
struct chud_client_stop_msg msg;
|
||||
msg.hdr.msgh_bits = 0x1513;
|
||||
msg.hdr.msgh_size = sizeof(mach_msg_header_t);
|
||||
msg.hdr.msgh_remote_port = shark_port;
|
||||
msg.hdr.msgh_local_port = reply_port;
|
||||
msg.hdr.msgh_reserved = 0;
|
||||
msg.hdr.msgh_id = SHARK_MSG_STOP;
|
||||
|
||||
MOZ_ASSERT(RECV_SIZEOF(struct chud_client_stop_msg) == 0x18);
|
||||
MOZ_ASSERT(sizeof(msg) == 0x2c);
|
||||
mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
|
||||
RECV_SIZEOF(struct chud_client_stop_msg),
|
||||
sizeof(msg), reply_port, 0, 0);
|
||||
mig_dealloc_reply_port(reply_port);
|
||||
return result;
|
||||
}
|
||||
|
||||
static mach_msg_return_t Disconnect(mach_port_t shark_port) {
|
||||
mach_port_t reply_port = mig_get_reply_port();
|
||||
|
||||
struct chud_client_release_msg msg;
|
||||
msg.hdr.msgh_bits = 0x1513;
|
||||
msg.hdr.msgh_size = sizeof(mach_msg_header_t);
|
||||
msg.hdr.msgh_remote_port = shark_port;
|
||||
msg.hdr.msgh_local_port = reply_port;
|
||||
msg.hdr.msgh_reserved = 0;
|
||||
msg.hdr.msgh_id = SHARK_MSG_RELEASE;
|
||||
msg.unk0 = 0;
|
||||
msg.unk1 = 1;
|
||||
msg.pid = getpid();
|
||||
|
||||
MOZ_ASSERT(RECV_SIZEOF(struct chud_client_release_msg) == 0x24);
|
||||
MOZ_ASSERT(sizeof(msg) == 0x2c);
|
||||
mach_msg_return_t result =
|
||||
mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
|
||||
RECV_SIZEOF(struct chud_client_release_msg), sizeof(msg),
|
||||
reply_port, 0, 0);
|
||||
mig_dealloc_reply_port(reply_port);
|
||||
return result;
|
||||
}
|
||||
|
||||
static mach_port_t shark_port = 0;
|
||||
static bool connected = false;
|
||||
static bool running = false;
|
||||
|
||||
namespace Shark {
|
||||
|
||||
bool Start() {
|
||||
if (!shark_port && !(shark_port = CreatePort())) return false;
|
||||
if (!connected && Connect(shark_port)) return false;
|
||||
connected = true;
|
||||
if (!running && ::Start(shark_port, 0xdeadbeef)) return false;
|
||||
return running = true;
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
if (!shark_port || !connected) return;
|
||||
::Stop(shark_port);
|
||||
running = false;
|
||||
Disconnect(shark_port);
|
||||
connected = false;
|
||||
}
|
||||
|
||||
} // namespace Shark
|
||||
|
||||
#endif
|
|
@ -1,24 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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/. */
|
||||
|
||||
#ifndef devtools_sharkctl_h
|
||||
#define devtools_sharkctl_h
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
# include <mach/mach.h>
|
||||
# include <stdint.h>
|
||||
|
||||
namespace Shark {
|
||||
|
||||
bool Start();
|
||||
void Stop();
|
||||
|
||||
} // namespace Shark
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#endif /* devtools_sharkctl_h */
|
|
@ -0,0 +1,11 @@
|
|||
function getarg(x) {
|
||||
return arguments[x]
|
||||
}
|
||||
function f() {
|
||||
var r = 0n;
|
||||
for (var i=0;i<2000;++i) {
|
||||
r += getarg(1+(i & 1), BigInt(0), 1n);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
for (var i=0;i<2;++i) print(f())
|
|
@ -2246,7 +2246,7 @@ void LIRGenerator::visitToString(MToString* ins) {
|
|||
}
|
||||
|
||||
default:
|
||||
// Float32, symbols, and objects are not supported.
|
||||
// Float32, symbols, bigint, and objects are not supported.
|
||||
MOZ_CRASH("unexpected type");
|
||||
}
|
||||
}
|
||||
|
@ -3166,6 +3166,7 @@ void LIRGenerator::visitLoadElementFromState(MLoadElementFromState* ins) {
|
|||
case MIRType::Object:
|
||||
case MIRType::String:
|
||||
case MIRType::Symbol:
|
||||
case MIRType::BigInt:
|
||||
lir->setOperand(1 + BOX_PIECES * i, use(elem));
|
||||
#ifdef JS_NUNBOX32
|
||||
// Bogus second operand.
|
||||
|
|
|
@ -4165,11 +4165,10 @@ class MToString : public MUnaryInstruction, public ToStringPolicy::Data {
|
|||
setResultType(MIRType::String);
|
||||
setMovable();
|
||||
|
||||
// Objects might override toString; Symbol and BigInts throw. We bailout in
|
||||
// those cases and run side-effects in baseline instead.
|
||||
// Objects might override toString; Symbol throws. We bailout in those cases
|
||||
// and run side-effects in baseline instead.
|
||||
if (def->mightBeType(MIRType::Object) ||
|
||||
def->mightBeType(MIRType::Symbol) ||
|
||||
def->mightBeType(MIRType::BigInt)) {
|
||||
def->mightBeType(MIRType::Symbol)) {
|
||||
setGuard();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,7 +219,6 @@ UNIFIED_SOURCES += [
|
|||
'builtin/TypedObject.cpp',
|
||||
'builtin/WeakMapObject.cpp',
|
||||
'builtin/WeakSetObject.cpp',
|
||||
'devtools/sharkctl.cpp',
|
||||
'ds/Bitmap.cpp',
|
||||
'ds/LifoAlloc.cpp',
|
||||
'ds/MemoryProtectionExceptionHandler.cpp',
|
||||
|
|
|
@ -355,10 +355,6 @@ static inline uint32_t FindScopeIndex(mozilla::Span<const GCPtrScope> scopes,
|
|||
MOZ_CRASH("Scope not found");
|
||||
}
|
||||
|
||||
static inline uint32_t FindScopeIndex(JSScript* script, Scope& scope) {
|
||||
return FindScopeIndex(script->scopes(), scope);
|
||||
}
|
||||
|
||||
template <XDRMode mode>
|
||||
static XDRResult XDRInnerObject(XDRState<mode>* xdr,
|
||||
js::PrivateScriptData* data,
|
||||
|
@ -3347,19 +3343,6 @@ bool JSScript::initScriptName(JSContext* cx) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline uint8_t* AllocScriptData(JSContext* cx, size_t size) {
|
||||
if (!size) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t* data = cx->pod_calloc<uint8_t>(JS_ROUNDUP(size, sizeof(Value)));
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(size_t(data) % sizeof(Value) == 0);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* static */ bool JSScript::createPrivateScriptData(
|
||||
JSContext* cx, HandleScript script, uint32_t nscopes, uint32_t nconsts,
|
||||
uint32_t nobjects, uint32_t ntrynotes, uint32_t nscopenotes,
|
||||
|
@ -3997,33 +3980,18 @@ static JSObject* CloneInnerInterpretedFunction(
|
|||
return clone;
|
||||
}
|
||||
|
||||
bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
|
||||
MutableHandle<GCVector<Scope*>> scopes) {
|
||||
// We don't copy the HideScriptFromDebugger flag and it's not clear what
|
||||
// should happen if it's set on the source script.
|
||||
MOZ_ASSERT(!src->hideScriptFromDebugger());
|
||||
|
||||
if (src->treatAsRunOnce() && !src->functionNonDelazifying()) {
|
||||
JS_ReportErrorASCII(cx, "No cloning toplevel run-once scripts");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* NB: Keep this in sync with XDRScript. */
|
||||
|
||||
/* Some embeddings are not careful to use ExposeObjectToActiveJS as needed. */
|
||||
JS::AssertObjectIsNotGray(src->sourceObject());
|
||||
|
||||
uint32_t nscopes = src->scopes().size();
|
||||
uint32_t nconsts = src->hasConsts() ? src->consts().size() : 0;
|
||||
uint32_t nobjects = src->hasObjects() ? src->objects().size() : 0;
|
||||
|
||||
/* Script data */
|
||||
|
||||
size_t size = src->dataSize();
|
||||
UniquePtr<uint8_t, JS::FreePolicy> data(AllocScriptData(cx, size));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
/* static */ bool PrivateScriptData::Clone(
|
||||
JSContext* cx, HandleScript src, HandleScript dst,
|
||||
MutableHandle<GCVector<Scope*>> scopes) {
|
||||
PrivateScriptData* srcData = src->data_;
|
||||
uint32_t nscopes = srcData->scopes().size();
|
||||
uint32_t nconsts = srcData->hasConsts() ? srcData->consts().size() : 0;
|
||||
uint32_t nobjects = srcData->hasObjects() ? srcData->objects().size() : 0;
|
||||
uint32_t ntrynotes = srcData->hasTryNotes() ? srcData->tryNotes().size() : 0;
|
||||
uint32_t nscopenotes =
|
||||
srcData->hasScopeNotes() ? srcData->scopeNotes().size() : 0;
|
||||
uint32_t nresumeoffsets =
|
||||
srcData->hasResumeOffsets() ? srcData->resumeOffsets().size() : 0;
|
||||
|
||||
/* Scopes */
|
||||
|
||||
|
@ -4036,10 +4004,11 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
|
|||
MOZ_ASSERT(src->bodyScopeIndex() + 1 == scopes.length());
|
||||
RootedScope original(cx);
|
||||
RootedScope clone(cx);
|
||||
for (const GCPtrScope& elem : src->scopes().From(scopes.length())) {
|
||||
for (const GCPtrScope& elem : srcData->scopes().From(scopes.length())) {
|
||||
original = elem.get();
|
||||
clone = Scope::clone(cx, original,
|
||||
scopes[FindScopeIndex(src, *original->enclosing())]);
|
||||
uint32_t scopeIndex =
|
||||
FindScopeIndex(srcData->scopes(), *original->enclosing());
|
||||
clone = Scope::clone(cx, original, scopes[scopeIndex]);
|
||||
if (!clone || !scopes.append(clone)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -4052,7 +4021,7 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
|
|||
if (nconsts != 0) {
|
||||
RootedValue val(cx);
|
||||
RootedValue clone(cx);
|
||||
for (const GCPtrValue& elem : src->consts()) {
|
||||
for (const GCPtrValue& elem : srcData->consts()) {
|
||||
val = elem.get();
|
||||
if (val.isDouble()) {
|
||||
clone = val;
|
||||
|
@ -4084,7 +4053,7 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
|
|||
RootedObject obj(cx);
|
||||
RootedObject clone(cx);
|
||||
Rooted<ScriptSourceObject*> sourceObject(cx, dst->sourceObject());
|
||||
for (const GCPtrObject& elem : src->objects()) {
|
||||
for (const GCPtrObject& elem : srcData->objects()) {
|
||||
obj = elem.get();
|
||||
clone = nullptr;
|
||||
if (obj->is<RegExpObject>()) {
|
||||
|
@ -4108,8 +4077,8 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
|
|||
}
|
||||
|
||||
Scope* enclosing = innerFun->nonLazyScript()->enclosingScope();
|
||||
RootedScope enclosingClone(cx,
|
||||
scopes[FindScopeIndex(src, *enclosing)]);
|
||||
uint32_t scopeIndex = FindScopeIndex(srcData->scopes(), *enclosing);
|
||||
RootedScope enclosingClone(cx, scopes[scopeIndex]);
|
||||
clone = CloneInnerInterpretedFunction(cx, enclosingClone, innerFun,
|
||||
sourceObject);
|
||||
}
|
||||
|
@ -4123,74 +4092,110 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
|
|||
}
|
||||
}
|
||||
|
||||
dst->data_ = reinterpret_cast<js::PrivateScriptData*>(data.release());
|
||||
dst->dataSize_ = size;
|
||||
memcpy(dst->data_, src->data_, size);
|
||||
|
||||
if (cx->zone() != src->zoneFromAnyThread()) {
|
||||
for (size_t i = 0; i < src->scriptData()->natoms(); i++) {
|
||||
cx->markAtom(src->scriptData()->atoms()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Script filenames, bytecodes and atoms are runtime-wide. */
|
||||
dst->setScriptData(src->scriptData());
|
||||
|
||||
dst->lineno_ = src->lineno();
|
||||
dst->mainOffset_ = src->mainOffset();
|
||||
dst->nfixed_ = src->nfixed();
|
||||
dst->nslots_ = src->nslots();
|
||||
dst->bodyScopeIndex_ = src->bodyScopeIndex_;
|
||||
dst->funLength_ = src->funLength();
|
||||
dst->numBytecodeTypeSets_ = src->numBytecodeTypeSets();
|
||||
|
||||
dst->immutableFlags_ = src->immutableFlags_;
|
||||
dst->setFlag(JSScript::ImmutableFlags::HasNonSyntacticScope,
|
||||
scopes[0]->hasOnChain(ScopeKind::NonSyntactic));
|
||||
|
||||
if (src->argumentsHasVarBinding()) {
|
||||
dst->setArgumentsHasVarBinding();
|
||||
if (src->analyzedArgsUsage()) {
|
||||
dst->setNeedsArgsObj(src->needsArgsObj());
|
||||
}
|
||||
// Create the new PrivateScriptData on |dst| and fill it in.
|
||||
if (!JSScript::createPrivateScriptData(cx, dst, nscopes, nconsts, nobjects,
|
||||
ntrynotes, nscopenotes,
|
||||
nresumeoffsets)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PrivateScriptData* dstData = dst->data_;
|
||||
{
|
||||
auto array = dst->data_->scopes();
|
||||
auto array = dstData->scopes();
|
||||
for (uint32_t i = 0; i < nscopes; ++i) {
|
||||
array[i].init(scopes[i]);
|
||||
}
|
||||
}
|
||||
if (nconsts) {
|
||||
auto array = dst->data_->consts();
|
||||
auto array = dstData->consts();
|
||||
for (unsigned i = 0; i < nconsts; ++i) {
|
||||
array[i].init(consts[i]);
|
||||
}
|
||||
}
|
||||
if (nobjects) {
|
||||
auto array = dst->data_->objects();
|
||||
auto array = dstData->objects();
|
||||
for (unsigned i = 0; i < nobjects; ++i) {
|
||||
array[i].init(objects[i]);
|
||||
}
|
||||
}
|
||||
if (ntrynotes) {
|
||||
std::copy_n(srcData->tryNotes().begin(), ntrynotes,
|
||||
dstData->tryNotes().begin());
|
||||
}
|
||||
if (nscopenotes) {
|
||||
std::copy_n(srcData->scopeNotes().begin(), nscopenotes,
|
||||
dstData->scopeNotes().begin());
|
||||
}
|
||||
if (nresumeoffsets) {
|
||||
std::copy_n(srcData->resumeOffsets().begin(), nresumeoffsets,
|
||||
dstData->resumeOffsets().begin());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSScript* CreateEmptyScriptForClone(
|
||||
JSContext* cx, HandleScript src, Handle<ScriptSourceObject*> sourceObject) {
|
||||
MOZ_ASSERT(cx->compartment() == sourceObject->compartment());
|
||||
MOZ_ASSERT_IF(src->realm()->isSelfHostingRealm(),
|
||||
sourceObject == cx->realm()->selfHostingScriptSource);
|
||||
JSScript* js::detail::CopyScript(JSContext* cx, HandleScript src,
|
||||
HandleScriptSourceObject sourceObject,
|
||||
MutableHandle<GCVector<Scope*>> scopes) {
|
||||
// We don't copy the HideScriptFromDebugger flag and it's not clear what
|
||||
// should happen if it's set on the source script.
|
||||
MOZ_ASSERT(!src->hideScriptFromDebugger());
|
||||
|
||||
if (src->treatAsRunOnce() && !src->functionNonDelazifying()) {
|
||||
JS_ReportErrorASCII(cx, "No cloning toplevel run-once scripts");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* NB: Keep this in sync with XDRScript. */
|
||||
|
||||
// Some embeddings are not careful to use ExposeObjectToActiveJS as needed.
|
||||
JS::AssertObjectIsNotGray(sourceObject);
|
||||
|
||||
CompileOptions options(cx);
|
||||
options.setMutedErrors(src->mutedErrors())
|
||||
.setSelfHostingMode(src->selfHosted())
|
||||
.setNoScriptRval(src->noScriptRval());
|
||||
|
||||
return JSScript::Create(cx, options, sourceObject, src->sourceStart(),
|
||||
src->sourceEnd(), src->toStringStart(),
|
||||
src->toStringEnd());
|
||||
// Create a new JSScript to fill in
|
||||
RootedScript dst(
|
||||
cx, JSScript::Create(cx, options, sourceObject, src->sourceStart(),
|
||||
src->sourceEnd(), src->toStringStart(),
|
||||
src->toStringEnd()));
|
||||
if (!dst) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Copy POD fields
|
||||
dst->lineno_ = src->lineno();
|
||||
dst->column_ = src->column();
|
||||
dst->mainOffset_ = src->mainOffset();
|
||||
dst->nfixed_ = src->nfixed();
|
||||
dst->nslots_ = src->nslots();
|
||||
dst->bodyScopeIndex_ = src->bodyScopeIndex();
|
||||
dst->immutableFlags_ = src->immutableFlags_;
|
||||
dst->funLength_ = src->funLength();
|
||||
dst->numBytecodeTypeSets_ = src->numBytecodeTypeSets();
|
||||
|
||||
dst->setFlag(JSScript::ImmutableFlags::HasNonSyntacticScope,
|
||||
scopes[0]->hasOnChain(ScopeKind::NonSyntactic));
|
||||
|
||||
if (src->argumentsHasVarBinding()) {
|
||||
dst->setArgumentsHasVarBinding();
|
||||
}
|
||||
|
||||
// Clone the PrivateScriptData into dst
|
||||
if (!PrivateScriptData::Clone(cx, src, dst, scopes)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The SharedScriptData can be reused by any zone in the Runtime as long as
|
||||
// we make sure to mark first (to sync Atom pointers).
|
||||
if (cx->zone() != src->zoneFromAnyThread()) {
|
||||
src->scriptData()->markForCrossZone(cx);
|
||||
}
|
||||
dst->setScriptData(src->scriptData());
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
JSScript* js::CloneGlobalScript(JSContext* cx, ScopeKind scopeKind,
|
||||
|
@ -4206,11 +4211,6 @@ JSScript* js::CloneGlobalScript(JSContext* cx, ScopeKind scopeKind,
|
|||
}
|
||||
}
|
||||
|
||||
RootedScript dst(cx, CreateEmptyScriptForClone(cx, src, sourceObject));
|
||||
if (!dst) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(src->bodyScopeIndex() == 0);
|
||||
Rooted<GCVector<Scope*>> scopes(cx, GCVector<Scope*>(cx));
|
||||
Rooted<GlobalScope*> original(cx, &src->bodyScope()->as<GlobalScope>());
|
||||
|
@ -4219,11 +4219,7 @@ JSScript* js::CloneGlobalScript(JSContext* cx, ScopeKind scopeKind,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (!detail::CopyScript(cx, src, dst, &scopes)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dst;
|
||||
return detail::CopyScript(cx, src, sourceObject, &scopes);
|
||||
}
|
||||
|
||||
JSScript* js::CloneScriptIntoFunction(
|
||||
|
@ -4232,11 +4228,6 @@ JSScript* js::CloneScriptIntoFunction(
|
|||
MOZ_ASSERT(fun->isInterpreted());
|
||||
MOZ_ASSERT(!fun->hasScript() || fun->hasUncompletedScript());
|
||||
|
||||
RootedScript dst(cx, CreateEmptyScriptForClone(cx, src, sourceObject));
|
||||
if (!dst) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Clone the non-intra-body scopes.
|
||||
Rooted<GCVector<Scope*>> scopes(cx, GCVector<Scope*>(cx));
|
||||
RootedScope original(cx);
|
||||
|
@ -4266,7 +4257,8 @@ JSScript* js::CloneScriptIntoFunction(
|
|||
|
||||
// Save flags in case we need to undo the early mutations.
|
||||
const int preservedFlags = fun->flags();
|
||||
if (!detail::CopyScript(cx, src, dst, &scopes)) {
|
||||
RootedScript dst(cx, detail::CopyScript(cx, src, sourceObject, &scopes));
|
||||
if (!dst) {
|
||||
fun->setFlags(preservedFlags);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -4473,6 +4465,12 @@ void SharedScriptData::traceChildren(JSTracer* trc) {
|
|||
}
|
||||
}
|
||||
|
||||
void SharedScriptData::markForCrossZone(JSContext* cx) {
|
||||
for (uint32_t i = 0; i < natoms(); ++i) {
|
||||
cx->markAtom(atoms()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void JSScript::traceChildren(JSTracer* trc) {
|
||||
// NOTE: this JSScript may be partially initialized at this point. E.g. we
|
||||
// may have created it and partially initialized it with
|
||||
|
|
|
@ -85,8 +85,9 @@ namespace detail {
|
|||
|
||||
// Do not call this directly! It is exposed for the friend declarations in
|
||||
// this file.
|
||||
bool CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
|
||||
MutableHandle<GCVector<Scope*>> scopes);
|
||||
JSScript* CopyScript(JSContext* cx, HandleScript src,
|
||||
HandleScriptSourceObject sourceObject,
|
||||
MutableHandle<GCVector<Scope*>> scopes);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
@ -1426,6 +1427,10 @@ class alignas(JS::Value) PrivateScriptData final {
|
|||
js::HandleScope scriptEnclosingScope,
|
||||
js::HandleFunction fun);
|
||||
|
||||
// Clone src script data into dst script.
|
||||
static bool Clone(JSContext* cx, js::HandleScript src, js::HandleScript dst,
|
||||
js::MutableHandle<JS::GCVector<js::Scope*>> scopes);
|
||||
|
||||
void traceChildren(JSTracer* trc);
|
||||
};
|
||||
|
||||
|
@ -1499,6 +1504,9 @@ class SharedScriptData {
|
|||
static MOZ_MUST_USE XDRResult XDR(js::XDRState<mode>* xdr,
|
||||
js::HandleScript script);
|
||||
|
||||
// Mark this SharedScriptData for use in a new zone
|
||||
void markForCrossZone(JSContext* cx);
|
||||
|
||||
private:
|
||||
SharedScriptData() = delete;
|
||||
SharedScriptData(const SharedScriptData&) = delete;
|
||||
|
@ -1836,10 +1844,15 @@ class JSScript : public js::gc::TenuredCell {
|
|||
js::HandleScriptSourceObject sourceObject,
|
||||
js::HandleScope scriptEnclosingScope, js::HandleFunction fun);
|
||||
|
||||
friend bool js::detail::CopyScript(
|
||||
friend bool js::PrivateScriptData::Clone(
|
||||
JSContext* cx, js::HandleScript src, js::HandleScript dst,
|
||||
js::MutableHandle<JS::GCVector<js::Scope*>> scopes);
|
||||
|
||||
friend JSScript* js::detail::CopyScript(
|
||||
JSContext* cx, js::HandleScript src,
|
||||
js::HandleScriptSourceObject sourceObject,
|
||||
js::MutableHandle<JS::GCVector<js::Scope*>> scopes);
|
||||
|
||||
private:
|
||||
JSScript(JS::Realm* realm, uint8_t* stubEntry,
|
||||
js::HandleScriptSourceObject sourceObject, uint32_t sourceStart,
|
||||
|
|
|
@ -689,9 +689,6 @@ nsresult nsDocumentViewer::SyncParentSubDocMap() {
|
|||
NS_IMETHODIMP
|
||||
nsDocumentViewer::SetContainer(nsIDocShell* aContainer) {
|
||||
mContainer = static_cast<nsDocShell*>(aContainer);
|
||||
if (mPresContext) {
|
||||
mPresContext->SetContainer(mContainer);
|
||||
}
|
||||
|
||||
// We're loading a new document into the window where this document
|
||||
// viewer lives, sync the parent document's frame element -> sub
|
||||
|
@ -953,8 +950,6 @@ nsresult nsDocumentViewer::InitInternal(nsIWidget* aParentWidget,
|
|||
nsCOMPtr<nsILinkHandler> linkHandler;
|
||||
requestor->GetInterface(NS_GET_IID(nsILinkHandler),
|
||||
getter_AddRefs(linkHandler));
|
||||
|
||||
mPresContext->SetContainer(mContainer);
|
||||
mPresContext->SetLinkHandler(linkHandler);
|
||||
}
|
||||
|
||||
|
@ -1476,7 +1471,6 @@ static void AttachContainerRecurse(nsIDocShell* aShell) {
|
|||
}
|
||||
RefPtr<nsPresContext> pc = viewer->GetPresContext();
|
||||
if (pc) {
|
||||
pc->SetContainer(static_cast<nsDocShell*>(aShell));
|
||||
nsCOMPtr<nsILinkHandler> handler = do_QueryInterface(aShell);
|
||||
pc->SetLinkHandler(handler);
|
||||
}
|
||||
|
@ -1501,7 +1495,9 @@ NS_IMETHODIMP
|
|||
nsDocumentViewer::Open(nsISupports* aState, nsISHEntry* aSHEntry) {
|
||||
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
if (mDocument) mDocument->SetContainer(mContainer);
|
||||
if (mDocument) {
|
||||
mDocument->SetContainer(mContainer);
|
||||
}
|
||||
|
||||
nsresult rv = InitInternal(mParentWidget, aState, mBounds, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -2171,8 +2167,6 @@ nsDocumentViewer::Show(void) {
|
|||
if (linkHandler) {
|
||||
mPresContext->SetLinkHandler(linkHandler);
|
||||
}
|
||||
|
||||
mPresContext->SetContainer(mContainer);
|
||||
}
|
||||
|
||||
if (mPresContext) {
|
||||
|
|
|
@ -9718,26 +9718,6 @@ already_AddRefed<nsFontMetrics> nsLayoutUtils::GetMetricsFor(
|
|||
return style.get();
|
||||
}
|
||||
|
||||
static float ResolveTransformOrigin(
|
||||
const nsStyleCoord& aCoord, TransformReferenceBox& aRefBox,
|
||||
TransformReferenceBox::DimensionGetter aGetter) {
|
||||
float result = 0.0;
|
||||
const float scale = mozilla::AppUnitsPerCSSPixel();
|
||||
if (aCoord.GetUnit() == eStyleUnit_Calc) {
|
||||
const nsStyleCoord::Calc* calc = aCoord.GetCalcValue();
|
||||
result =
|
||||
NSAppUnitsToFloatPixels((aRefBox.*aGetter)(), scale) * calc->mPercent +
|
||||
NSAppUnitsToFloatPixels(calc->mLength, scale);
|
||||
} else if (aCoord.GetUnit() == eStyleUnit_Percent) {
|
||||
result = NSAppUnitsToFloatPixels((aRefBox.*aGetter)(), scale) *
|
||||
aCoord.GetPercentValue();
|
||||
} else {
|
||||
MOZ_ASSERT(aCoord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
|
||||
result = NSAppUnitsToFloatPixels(aCoord.GetCoordValue(), scale);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* static */ Maybe<MotionPathData> nsLayoutUtils::ResolveMotionPath(
|
||||
const nsIFrame* aFrame) {
|
||||
MOZ_ASSERT(aFrame);
|
||||
|
@ -9791,11 +9771,10 @@ static float ResolveTransformOrigin(
|
|||
// We need to resolve transform-origin here to calculate the correct path
|
||||
// translate. (i.e. Center transform-origin on the path.)
|
||||
TransformReferenceBox refBox(aFrame);
|
||||
Point origin(ResolveTransformOrigin(display->mTransformOrigin[0], refBox,
|
||||
&TransformReferenceBox::Width),
|
||||
ResolveTransformOrigin(display->mTransformOrigin[1], refBox,
|
||||
&TransformReferenceBox::Height));
|
||||
auto& transformOrigin = display->mTransformOrigin;
|
||||
CSSPoint origin = nsStyleTransformMatrix::Convert2DPosition(
|
||||
transformOrigin.horizontal, transformOrigin.vertical, refBox);
|
||||
// Bug 1186329: the translate parameters will be adjusted more after we
|
||||
// implement offset-position and offset-anchor.
|
||||
return Some(MotionPathData{point - origin, angle});
|
||||
return Some(MotionPathData{point - origin.ToUnknownPoint(), angle});
|
||||
}
|
||||
|
|
|
@ -222,14 +222,11 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType)
|
|||
mFontFeatureValuesDirty(true),
|
||||
mSuppressResizeReflow(false),
|
||||
mIsVisual(false),
|
||||
mIsChrome(false),
|
||||
mIsChromeOriginImage(false),
|
||||
mPaintFlashing(false),
|
||||
mPaintFlashingInitialized(false),
|
||||
mHasWarnedAboutPositionedTableParts(false),
|
||||
mHasWarnedAboutTooLargeDashedOrDottedRadius(false),
|
||||
mQuirkSheetAdded(false),
|
||||
mNeedsPrefUpdate(false),
|
||||
mHadNonBlankPaint(false),
|
||||
mHadContentfulPaint(false),
|
||||
mHadContentfulPaintComposite(false)
|
||||
|
@ -359,6 +356,15 @@ static bool sLookAndFeelChanged;
|
|||
// one prescontext.
|
||||
static bool sThemeChanged;
|
||||
|
||||
bool nsPresContext::IsChrome() const {
|
||||
return Document()->IsInChromeDocShell();
|
||||
}
|
||||
|
||||
bool nsPresContext::IsChromeOriginImage() const {
|
||||
return Document()->IsBeingUsedAsImage() &&
|
||||
Document()->IsDocumentURISchemeChrome();
|
||||
}
|
||||
|
||||
void nsPresContext::GetDocumentColorPreferences() {
|
||||
// Make sure the preferences are initialized. In the normal run,
|
||||
// they would already be, because gfxPlatform would have been created,
|
||||
|
@ -367,7 +373,6 @@ void nsPresContext::GetDocumentColorPreferences() {
|
|||
|
||||
int32_t useAccessibilityTheme = 0;
|
||||
bool usePrefColors = true;
|
||||
bool isChromeDocShell = false;
|
||||
static int32_t sDocumentColorsSetting;
|
||||
static bool sDocumentColorsSettingPrefCached = false;
|
||||
if (!sDocumentColorsSettingPrefCached) {
|
||||
|
@ -376,22 +381,7 @@ void nsPresContext::GetDocumentColorPreferences() {
|
|||
"browser.display.document_color_use", 0);
|
||||
}
|
||||
|
||||
dom::Document* doc = mDocument->GetDisplayDocument();
|
||||
if (doc && doc->GetDocShell()) {
|
||||
isChromeDocShell =
|
||||
nsIDocShellTreeItem::typeChrome == doc->GetDocShell()->ItemType();
|
||||
} else {
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShell(mContainer);
|
||||
if (docShell) {
|
||||
isChromeDocShell =
|
||||
nsIDocShellTreeItem::typeChrome == docShell->ItemType();
|
||||
}
|
||||
}
|
||||
|
||||
mIsChromeOriginImage = mDocument->IsBeingUsedAsImage() &&
|
||||
IsChromeURI(mDocument->GetDocumentURI());
|
||||
|
||||
if (isChromeDocShell || mIsChromeOriginImage) {
|
||||
if (IsChrome() || IsChromeOriginImage()) {
|
||||
usePrefColors = false;
|
||||
} else {
|
||||
useAccessibilityTheme =
|
||||
|
@ -441,11 +431,10 @@ void nsPresContext::GetDocumentColorPreferences() {
|
|||
if (sDocumentColorsSetting == 1 || mDocument->IsBeingUsedAsImage()) {
|
||||
mUseDocumentColors = true;
|
||||
} else if (sDocumentColorsSetting == 2) {
|
||||
mUseDocumentColors = isChromeDocShell || mIsChromeOriginImage;
|
||||
mUseDocumentColors = IsChrome() || IsChromeOriginImage();
|
||||
} else {
|
||||
MOZ_ASSERT(
|
||||
!useAccessibilityTheme || !(isChromeDocShell || mIsChromeOriginImage),
|
||||
"The accessibility theme should only be on for non-chrome");
|
||||
MOZ_ASSERT(!useAccessibilityTheme || !(IsChrome() || IsChromeOriginImage()),
|
||||
"The accessibility theme should only be on for non-chrome");
|
||||
mUseDocumentColors = !useAccessibilityTheme;
|
||||
}
|
||||
}
|
||||
|
@ -678,14 +667,7 @@ void nsPresContext::UpdateAfterPreferencesChanged() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!mContainer) {
|
||||
// Delay updating until there is a container
|
||||
mNeedsPrefUpdate = true;
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShell(mContainer);
|
||||
if (docShell && nsIDocShellTreeItem::typeChrome == docShell->ItemType()) {
|
||||
if (mDocument->IsInChromeDocShell()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -753,7 +735,6 @@ nsresult nsPresContext::Init(nsDeviceContext* aDeviceContext) {
|
|||
"How did we end up with a presshell if our parent doesn't "
|
||||
"have one?");
|
||||
if (parent && parent->GetPresContext()) {
|
||||
// We don't have our container set yet at this point
|
||||
nsCOMPtr<nsIDocShellTreeItem> ourItem = mDocument->GetDocShell();
|
||||
if (ourItem) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
|
@ -812,32 +793,28 @@ void nsPresContext::AttachShell(nsIPresShell* aShell) {
|
|||
mCounterStyleManager = new mozilla::CounterStyleManager(this);
|
||||
|
||||
dom::Document* doc = mShell->GetDocument();
|
||||
NS_ASSERTION(doc, "expect document here");
|
||||
if (doc) {
|
||||
// Have to update PresContext's mDocument before calling any other methods.
|
||||
mDocument = doc;
|
||||
}
|
||||
MOZ_ASSERT(doc);
|
||||
// Have to update PresContext's mDocument before calling any other methods.
|
||||
mDocument = doc;
|
||||
// Initialize our state from the user preferences, now that we
|
||||
// have a presshell, and hence a document.
|
||||
GetUserPreferences();
|
||||
|
||||
if (doc) {
|
||||
nsIURI* docURI = doc->GetDocumentURI();
|
||||
nsIURI* docURI = doc->GetDocumentURI();
|
||||
|
||||
if (IsDynamic() && docURI) {
|
||||
bool isChrome = false;
|
||||
bool isRes = false;
|
||||
docURI->SchemeIs("chrome", &isChrome);
|
||||
docURI->SchemeIs("resource", &isRes);
|
||||
if (IsDynamic() && docURI) {
|
||||
bool isChrome = false;
|
||||
bool isRes = false;
|
||||
docURI->SchemeIs("chrome", &isChrome);
|
||||
docURI->SchemeIs("resource", &isRes);
|
||||
|
||||
if (!isChrome && !isRes)
|
||||
mImageAnimationMode = mImageAnimationModePref;
|
||||
else
|
||||
mImageAnimationMode = imgIContainer::kNormalAnimMode;
|
||||
}
|
||||
|
||||
UpdateCharSet(doc->GetDocumentCharacterSet());
|
||||
if (!isChrome && !isRes)
|
||||
mImageAnimationMode = mImageAnimationModePref;
|
||||
else
|
||||
mImageAnimationMode = imgIContainer::kNormalAnimMode;
|
||||
}
|
||||
|
||||
UpdateCharSet(doc->GetDocumentCharacterSet());
|
||||
}
|
||||
|
||||
void nsPresContext::DetachShell() {
|
||||
|
@ -1302,45 +1279,17 @@ bool nsPresContext::ElementWouldPropagateScrollStyles(const Element& aElement) {
|
|||
return GetPropagatedScrollStylesForViewport(this, &dummy) == &aElement;
|
||||
}
|
||||
|
||||
void nsPresContext::SetContainer(nsIDocShell* aDocShell) {
|
||||
if (aDocShell) {
|
||||
NS_ASSERTION(!(mContainer && mNeedsPrefUpdate),
|
||||
"Should only need pref update if mContainer is null.");
|
||||
mContainer = static_cast<nsDocShell*>(aDocShell);
|
||||
if (mNeedsPrefUpdate) {
|
||||
DispatchPrefChangedRunnableIfNeeded();
|
||||
mNeedsPrefUpdate = false;
|
||||
}
|
||||
} else {
|
||||
mContainer = WeakPtr<nsDocShell>();
|
||||
}
|
||||
UpdateIsChrome();
|
||||
if (mContainer) {
|
||||
GetDocumentColorPreferences();
|
||||
}
|
||||
nsISupports* nsPresContext::GetContainerWeak() const { return GetDocShell(); }
|
||||
|
||||
nsIDocShell* nsPresContext::GetDocShell() const {
|
||||
return mDocument->GetDocShell();
|
||||
}
|
||||
|
||||
nsISupports* nsPresContext::GetContainerWeak() const {
|
||||
return static_cast<nsIDocShell*>(mContainer);
|
||||
}
|
||||
|
||||
nsIDocShell* nsPresContext::GetDocShell() const { return mContainer; }
|
||||
|
||||
/* virtual */ void nsPresContext::Detach() {
|
||||
SetContainer(nullptr);
|
||||
SetLinkHandler(nullptr);
|
||||
}
|
||||
/* virtual */ void nsPresContext::Detach() { SetLinkHandler(nullptr); }
|
||||
|
||||
bool nsPresContext::BidiEnabled() const { return Document()->GetBidiEnabled(); }
|
||||
|
||||
void nsPresContext::SetBidiEnabled() const {
|
||||
if (mShell) {
|
||||
dom::Document* doc = mShell->GetDocument();
|
||||
if (doc) {
|
||||
doc->SetBidiEnabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
void nsPresContext::SetBidiEnabled() const { Document()->SetBidiEnabled(); }
|
||||
|
||||
void nsPresContext::SetBidi(uint32_t aSource) {
|
||||
// Don't do all this stuff unless the options have changed.
|
||||
|
@ -1358,10 +1307,7 @@ void nsPresContext::SetBidi(uint32_t aSource) {
|
|||
} else if (IBMBIDI_TEXTTYPE_LOGICAL == GET_BIDI_OPTION_TEXTTYPE(aSource)) {
|
||||
SetVisualMode(false);
|
||||
} else {
|
||||
dom::Document* doc = mShell->GetDocument();
|
||||
if (doc) {
|
||||
SetVisualMode(IsVisualCharset(doc->GetDocumentCharacterSet()));
|
||||
}
|
||||
SetVisualMode(IsVisualCharset(Document()->GetDocumentCharacterSet()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1790,20 +1736,19 @@ void nsPresContext::SetPrintSettings(nsIPrintSettings* aPrintSettings) {
|
|||
}
|
||||
|
||||
bool nsPresContext::EnsureVisible() {
|
||||
nsCOMPtr<nsIDocShell> docShell(mContainer);
|
||||
if (docShell) {
|
||||
nsCOMPtr<nsIContentViewer> cv;
|
||||
docShell->GetContentViewer(getter_AddRefs(cv));
|
||||
// Make sure this is the content viewer we belong with
|
||||
if (cv && cv->GetPresContext() == this) {
|
||||
// OK, this is us. We want to call Show() on the content viewer.
|
||||
nsresult result = cv->Show();
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDocShell> docShell(GetDocShell());
|
||||
if (!docShell) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
nsCOMPtr<nsIContentViewer> cv;
|
||||
docShell->GetContentViewer(getter_AddRefs(cv));
|
||||
// Make sure this is the content viewer we belong with
|
||||
if (!cv || cv->GetPresContext() != this) {
|
||||
return false;
|
||||
}
|
||||
// OK, this is us. We want to call Show() on the content viewer.
|
||||
nsresult result = cv->Show();
|
||||
return NS_SUCCEEDED(result);
|
||||
}
|
||||
|
||||
#ifdef MOZ_REFLOW_PERF
|
||||
|
@ -1814,11 +1759,6 @@ void nsPresContext::CountReflows(const char* aName, nsIFrame* aFrame) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void nsPresContext::UpdateIsChrome() {
|
||||
mIsChrome =
|
||||
mContainer && nsIDocShellTreeItem::typeChrome == mContainer->ItemType();
|
||||
}
|
||||
|
||||
bool nsPresContext::HasAuthorSpecifiedRules(const nsIFrame* aFrame,
|
||||
uint32_t aRuleTypeMask) const {
|
||||
Element* elem = aFrame->GetContent()->AsElement();
|
||||
|
@ -2592,12 +2532,8 @@ nscoord nsPresContext::PhysicalMillimetersToAppUnits(float aMM) const {
|
|||
}
|
||||
|
||||
bool nsPresContext::IsDeviceSizePageSize() {
|
||||
bool isDeviceSizePageSize = false;
|
||||
nsCOMPtr<nsIDocShell> docShell(mContainer);
|
||||
if (docShell) {
|
||||
isDeviceSizePageSize = docShell->GetDeviceSizeIsPageSize();
|
||||
}
|
||||
return isDeviceSizePageSize;
|
||||
nsIDocShell* docShell = GetDocShell();
|
||||
return docShell && docShell->GetDeviceSizeIsPageSize();
|
||||
}
|
||||
|
||||
uint64_t nsPresContext::GetRestyleGeneration() const {
|
||||
|
|
|
@ -413,7 +413,6 @@ class nsPresContext : public nsISupports,
|
|||
bool GetFocusRingOnAnything() const { return mFocusRingOnAnything; }
|
||||
uint8_t GetFocusRingStyle() const { return mFocusRingStyle; }
|
||||
|
||||
void SetContainer(nsIDocShell* aContainer);
|
||||
|
||||
nsISupports* GetContainerWeak() const;
|
||||
|
||||
|
@ -425,7 +424,7 @@ class nsPresContext : public nsISupports,
|
|||
|
||||
/**
|
||||
* Detach this pres context - i.e. cancel relevant timers,
|
||||
* SetLinkHandler(null), SetContainer(null) etc.
|
||||
* SetLinkHandler(null), etc.
|
||||
* Only to be used by the DocumentViewer.
|
||||
*/
|
||||
virtual void Detach();
|
||||
|
@ -871,9 +870,8 @@ class nsPresContext : public nsISupports,
|
|||
}
|
||||
|
||||
// Is this presentation in a chrome docshell?
|
||||
bool IsChrome() const { return mIsChrome; }
|
||||
bool IsChromeOriginImage() const { return mIsChromeOriginImage; }
|
||||
void UpdateIsChrome();
|
||||
bool IsChrome() const;
|
||||
bool IsChromeOriginImage() const;
|
||||
|
||||
// Public API for native theme code to get style internals.
|
||||
bool HasAuthorSpecifiedRules(const nsIFrame* aFrame,
|
||||
|
@ -1195,8 +1193,6 @@ class nsPresContext : public nsISupports,
|
|||
bool mInflationDisabledForShrinkWrap;
|
||||
|
||||
protected:
|
||||
mozilla::WeakPtr<nsDocShell> mContainer;
|
||||
|
||||
float mSystemFontScale; // Internal text zoom factor, defaults to 1.0
|
||||
float mTextZoom; // Text zoom, defaults to 1.0
|
||||
float mEffectiveTextZoom; // Text zoom * system font scale
|
||||
|
@ -1323,9 +1319,6 @@ class nsPresContext : public nsISupports,
|
|||
|
||||
unsigned mIsVisual : 1;
|
||||
|
||||
unsigned mIsChrome : 1;
|
||||
unsigned mIsChromeOriginImage : 1;
|
||||
|
||||
// Should we paint flash in this context? Do not use this variable directly.
|
||||
// Use GetPaintFlashing() method instead.
|
||||
mutable unsigned mPaintFlashing : 1;
|
||||
|
@ -1338,9 +1331,6 @@ class nsPresContext : public nsISupports,
|
|||
// Have we added quirk.css to the style set?
|
||||
unsigned mQuirkSheetAdded : 1;
|
||||
|
||||
// Is there a pref update to process once we have a container?
|
||||
unsigned mNeedsPrefUpdate : 1;
|
||||
|
||||
// Has NotifyNonBlankPaint been called on this PresContext?
|
||||
unsigned mHadNonBlankPaint : 1;
|
||||
// Has NotifyContentfulPaint been called on this PresContext?
|
||||
|
|
|
@ -2388,9 +2388,8 @@ nscoord nsFlexContainerFrame::GetLogicalBaseline(
|
|||
// http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#painting
|
||||
static uint32_t GetDisplayFlagsForFlexItem(nsIFrame* aFrame) {
|
||||
MOZ_ASSERT(aFrame->IsFlexItem(), "Should only be called on flex items");
|
||||
|
||||
const nsStylePosition* pos = aFrame->StylePosition();
|
||||
if (pos->mZIndex.GetUnit() == eStyleUnit_Integer) {
|
||||
if (pos->mZIndex.IsInteger()) {
|
||||
return nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT;
|
||||
}
|
||||
return nsIFrame::DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT;
|
||||
|
@ -3627,7 +3626,7 @@ void FlexboxAxisTracker::InitAxesFromLegacyProps(
|
|||
void FlexboxAxisTracker::InitAxesFromModernProps(
|
||||
const nsFlexContainerFrame* aFlexContainer) {
|
||||
const nsStylePosition* stylePos = aFlexContainer->StylePosition();
|
||||
uint32_t flexDirection = stylePos->mFlexDirection;
|
||||
StyleFlexDirection flexDirection = stylePos->mFlexDirection;
|
||||
|
||||
// Inline dimension ("start-to-end"):
|
||||
// (NOTE: I'm intentionally not calling these "inlineAxis"/"blockAxis", since
|
||||
|
@ -3640,22 +3639,22 @@ void FlexboxAxisTracker::InitAxesFromModernProps(
|
|||
|
||||
// Determine main axis:
|
||||
switch (flexDirection) {
|
||||
case NS_STYLE_FLEX_DIRECTION_ROW:
|
||||
case StyleFlexDirection::Row:
|
||||
mMainAxis = inlineDimension;
|
||||
mIsRowOriented = true;
|
||||
mIsMainAxisReversed = false;
|
||||
break;
|
||||
case NS_STYLE_FLEX_DIRECTION_ROW_REVERSE:
|
||||
case StyleFlexDirection::RowReverse:
|
||||
mMainAxis = GetReverseAxis(inlineDimension);
|
||||
mIsRowOriented = true;
|
||||
mIsMainAxisReversed = true;
|
||||
break;
|
||||
case NS_STYLE_FLEX_DIRECTION_COLUMN:
|
||||
case StyleFlexDirection::Column:
|
||||
mMainAxis = blockDimension;
|
||||
mIsRowOriented = false;
|
||||
mIsMainAxisReversed = false;
|
||||
break;
|
||||
case NS_STYLE_FLEX_DIRECTION_COLUMN_REVERSE:
|
||||
case StyleFlexDirection::ColumnReverse:
|
||||
mMainAxis = GetReverseAxis(blockDimension);
|
||||
mIsRowOriented = false;
|
||||
mIsMainAxisReversed = true;
|
||||
|
@ -3667,8 +3666,8 @@ void FlexboxAxisTracker::InitAxesFromModernProps(
|
|||
// Determine cross axis:
|
||||
// (This is set up so that a bogus |flexDirection| value will
|
||||
// give us blockDimension.
|
||||
if (flexDirection == NS_STYLE_FLEX_DIRECTION_COLUMN ||
|
||||
flexDirection == NS_STYLE_FLEX_DIRECTION_COLUMN_REVERSE) {
|
||||
if (flexDirection == StyleFlexDirection::Column ||
|
||||
flexDirection == StyleFlexDirection::ColumnReverse) {
|
||||
mCrossAxis = inlineDimension;
|
||||
} else {
|
||||
mCrossAxis = blockDimension;
|
||||
|
@ -4447,8 +4446,8 @@ bool nsFlexContainerFrame::IsItemInlineAxisMainAxis(nsIFrame* aFrame) {
|
|||
// whether the flex container's main axis is its inline axis.)
|
||||
auto flexDirection = flexContainer->StylePosition()->mFlexDirection;
|
||||
bool flexContainerIsRowOriented =
|
||||
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW ||
|
||||
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW_REVERSE;
|
||||
flexDirection == StyleFlexDirection::Row ||
|
||||
flexDirection == StyleFlexDirection::RowReverse;
|
||||
|
||||
// aFrame's inline axis is its flex container's main axis IFF the above
|
||||
// questions have the same answer.
|
||||
|
|
|
@ -1286,9 +1286,10 @@ void nsIFrame::SyncFrameViewProperties(nsView* aView) {
|
|||
// Make sure z-index is correct
|
||||
ComputedStyle* sc = Style();
|
||||
const nsStylePosition* position = sc->StylePosition();
|
||||
if (position->mZIndex.GetUnit() == eStyleUnit_Integer) {
|
||||
zIndex = position->mZIndex.GetIntValue();
|
||||
} else if (position->mZIndex.GetUnit() == eStyleUnit_Auto) {
|
||||
if (position->mZIndex.IsInteger()) {
|
||||
zIndex = position->mZIndex.integer._0;
|
||||
} else {
|
||||
MOZ_ASSERT(position->mZIndex.IsAuto());
|
||||
autoZIndex = true;
|
||||
}
|
||||
} else {
|
||||
|
@ -10448,7 +10449,7 @@ bool nsIFrame::IsStackingContext(const nsStyleDisplay* aStyleDisplay,
|
|||
nsSVGIntegrationUtils::UsingEffectsForFrame(this) ||
|
||||
(aIsPositioned &&
|
||||
(aStyleDisplay->IsPositionForcingStackingContext() ||
|
||||
aStylePosition->mZIndex.GetUnit() == eStyleUnit_Integer)) ||
|
||||
aStylePosition->mZIndex.IsInteger())) ||
|
||||
(aStyleDisplay->mWillChangeBitField &
|
||||
NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) ||
|
||||
aStyleDisplay->mIsolation != NS_STYLE_ISOLATION_AUTO;
|
||||
|
@ -10526,8 +10527,9 @@ gfx::Matrix nsIFrame::ComputeWidgetTransform() {
|
|||
float(appUnitsPerDevPixel));
|
||||
|
||||
// Apply the -moz-window-transform-origin translation to the matrix.
|
||||
const StyleTransformOrigin& origin = uiReset->mWindowTransformOrigin;
|
||||
Point transformOrigin = nsStyleTransformMatrix::Convert2DPosition(
|
||||
uiReset->mWindowTransformOrigin, refBox, appUnitsPerDevPixel);
|
||||
origin.horizontal, origin.vertical, refBox, appUnitsPerDevPixel);
|
||||
matrix.ChangeBasis(Point3D(transformOrigin.x, transformOrigin.y, 0));
|
||||
|
||||
gfx::Matrix result2d;
|
||||
|
|
|
@ -2939,10 +2939,14 @@ static Maybe<int32_t> MaxZIndexInList(nsDisplayList* aList,
|
|||
Maybe<int32_t> maxZIndex = Nothing();
|
||||
for (nsDisplayItem* item = aList->GetBottom(); item;
|
||||
item = item->GetAbove()) {
|
||||
int32_t zIndex = item->ZIndex();
|
||||
if (zIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
if (!maxZIndex) {
|
||||
maxZIndex = Some(item->ZIndex());
|
||||
maxZIndex = Some(zIndex);
|
||||
} else {
|
||||
maxZIndex = Some(std::max(maxZIndex.value(), item->ZIndex()));
|
||||
maxZIndex = Some(std::max(maxZIndex.value(), zIndex));
|
||||
}
|
||||
}
|
||||
return maxZIndex;
|
||||
|
@ -3001,9 +3005,8 @@ static void AppendToTop(nsDisplayListBuilder* aBuilder,
|
|||
zIndex = Some(INT32_MAX);
|
||||
} else if (aFlags & APPEND_OVERLAY) {
|
||||
zIndex = MaxZIndexInList(aLists.PositionedDescendants(), aBuilder);
|
||||
} else if (aSourceFrame->StylePosition()->mZIndex.GetUnit() ==
|
||||
eStyleUnit_Integer) {
|
||||
zIndex = Some(aSourceFrame->StylePosition()->mZIndex.GetIntValue());
|
||||
} else if (aSourceFrame->StylePosition()->mZIndex.IsInteger()) {
|
||||
zIndex = Some(aSourceFrame->StylePosition()->mZIndex.integer._0);
|
||||
}
|
||||
AppendInternalItemToTop(aLists, newItem, zIndex);
|
||||
} else {
|
||||
|
|
|
@ -2323,7 +2323,7 @@ void nsGridContainerFrame::GridReflowInput::CalculateTrackSizes(
|
|||
*/
|
||||
static uint32_t GetDisplayFlagsForGridItem(nsIFrame* aFrame) {
|
||||
const nsStylePosition* pos = aFrame->StylePosition();
|
||||
if (pos->mZIndex.GetUnit() == eStyleUnit_Integer) {
|
||||
if (pos->mZIndex.IsInteger()) {
|
||||
return nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT;
|
||||
}
|
||||
return nsIFrame::DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT;
|
||||
|
|
|
@ -3081,9 +3081,9 @@ static int32_t ZIndexForFrame(nsIFrame* aFrame) {
|
|||
return 0;
|
||||
|
||||
const nsStylePosition* position = aFrame->StylePosition();
|
||||
if (position->mZIndex.GetUnit() == eStyleUnit_Integer)
|
||||
return position->mZIndex.GetIntValue();
|
||||
|
||||
if (position->mZIndex.IsInteger())
|
||||
return position->mZIndex.integer._0;
|
||||
MOZ_ASSERT(position->mZIndex.IsAuto());
|
||||
// sort the auto and 0 elements together
|
||||
return 0;
|
||||
}
|
||||
|
@ -7376,49 +7376,21 @@ bool nsDisplayTransform::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
|
|||
refBox.Init(aFrame);
|
||||
}
|
||||
|
||||
/* Allows us to access dimension getters by index. */
|
||||
float transformOrigin[2];
|
||||
TransformReferenceBox::DimensionGetter dimensionGetter[] = {
|
||||
&TransformReferenceBox::Width, &TransformReferenceBox::Height};
|
||||
TransformReferenceBox::DimensionGetter offsetGetter[] = {
|
||||
&TransformReferenceBox::X, &TransformReferenceBox::Y};
|
||||
const StyleTransformOrigin& transformOrigin = display->mTransformOrigin;
|
||||
CSSPoint origin = nsStyleTransformMatrix::Convert2DPosition(
|
||||
transformOrigin.horizontal, transformOrigin.vertical, refBox);
|
||||
|
||||
for (uint8_t index = 0; index < 2; ++index) {
|
||||
/* If the transform-origin specifies a percentage, take the percentage
|
||||
* of the size of the box.
|
||||
*/
|
||||
const nsStyleCoord& originValue = display->mTransformOrigin[index];
|
||||
if (originValue.GetUnit() == eStyleUnit_Calc) {
|
||||
const nsStyleCoord::Calc* calc = originValue.GetCalcValue();
|
||||
transformOrigin[index] =
|
||||
NSAppUnitsToFloatPixels((refBox.*dimensionGetter[index])(),
|
||||
aAppUnitsPerPixel) *
|
||||
calc->mPercent +
|
||||
NSAppUnitsToFloatPixels(calc->mLength, aAppUnitsPerPixel);
|
||||
} else if (originValue.GetUnit() == eStyleUnit_Percent) {
|
||||
transformOrigin[index] =
|
||||
NSAppUnitsToFloatPixels((refBox.*dimensionGetter[index])(),
|
||||
aAppUnitsPerPixel) *
|
||||
originValue.GetPercentValue();
|
||||
} else {
|
||||
MOZ_ASSERT(originValue.GetUnit() == eStyleUnit_Coord, "unexpected unit");
|
||||
transformOrigin[index] = NSAppUnitsToFloatPixels(
|
||||
originValue.GetCoordValue(), aAppUnitsPerPixel);
|
||||
}
|
||||
|
||||
if (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
|
||||
// SVG frames (unlike other frames) have a reference box that can be (and
|
||||
// typically is) offset from the TopLeft() of the frame. We need to
|
||||
// account for that here.
|
||||
transformOrigin[index] += NSAppUnitsToFloatPixels(
|
||||
(refBox.*offsetGetter[index])(), aAppUnitsPerPixel);
|
||||
}
|
||||
if (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
|
||||
// SVG frames (unlike other frames) have a reference box that can be (and
|
||||
// typically is) offset from the TopLeft() of the frame. We need to account
|
||||
// for that here.
|
||||
origin.x += CSSPixel::FromAppUnits(refBox.X());
|
||||
origin.y += CSSPixel::FromAppUnits(refBox.Y());
|
||||
}
|
||||
|
||||
return Point3D(
|
||||
transformOrigin[0], transformOrigin[1],
|
||||
NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(),
|
||||
aAppUnitsPerPixel));
|
||||
float scale = mozilla::AppUnitsPerCSSPixel() / float(aAppUnitsPerPixel);
|
||||
float z = transformOrigin.depth._0;
|
||||
return Point3D(origin.x * scale, origin.y * scale, z * scale);
|
||||
}
|
||||
|
||||
/* static */ bool nsDisplayTransform::ComputePerspectiveMatrix(
|
||||
|
@ -7446,12 +7418,15 @@ bool nsDisplayTransform::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
|
|||
}
|
||||
|
||||
/* Grab the values for perspective and perspective-origin (if present) */
|
||||
|
||||
const nsStyleDisplay* cbDisplay = cbFrame->StyleDisplay();
|
||||
if (cbDisplay->mChildPerspective.GetUnit() != eStyleUnit_Coord) {
|
||||
if (cbDisplay->mChildPerspective.IsNone()) {
|
||||
return false;
|
||||
}
|
||||
nscoord perspective = cbDisplay->mChildPerspective.GetCoordValue();
|
||||
|
||||
MOZ_ASSERT(cbDisplay->mChildPerspective.IsLength());
|
||||
// TODO(emilio): Seems quite silly to go through app units just to convert to
|
||||
// float pixels below.
|
||||
nscoord perspective = cbDisplay->mChildPerspective.length._0.ToAppUnits();
|
||||
if (perspective < std::numeric_limits<Float>::epsilon()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -7459,7 +7434,8 @@ bool nsDisplayTransform::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
|
|||
TransformReferenceBox refBox(cbFrame);
|
||||
|
||||
Point perspectiveOrigin = nsStyleTransformMatrix::Convert2DPosition(
|
||||
cbDisplay->mPerspectiveOrigin, refBox, aAppUnitsPerPixel);
|
||||
cbDisplay->mPerspectiveOrigin.horizontal,
|
||||
cbDisplay->mPerspectiveOrigin.vertical, refBox, aAppUnitsPerPixel);
|
||||
|
||||
/* GetOffsetTo computes the offset required to move from 0,0 in cbFrame to 0,0
|
||||
* in aFrame. Although we actually want the inverse of this, it's faster to
|
||||
|
|
|
@ -61,7 +61,7 @@ nsImageRenderer::nsImageRenderer(nsIFrame* aForFrame,
|
|||
mSize(0, 0),
|
||||
mFlags(aFlags),
|
||||
mExtendMode(ExtendMode::CLAMP),
|
||||
mMaskOp(NS_STYLE_MASK_MODE_MATCH_SOURCE) {}
|
||||
mMaskOp(StyleMaskMode::MatchSource) {}
|
||||
|
||||
static bool ShouldTreatAsCompleteDueToSyncDecode(const nsStyleImage* aImage,
|
||||
uint32_t aFlags) {
|
||||
|
@ -428,7 +428,7 @@ ImgDrawResult nsImageRenderer::Draw(nsPresContext* aPresContext,
|
|||
IntRect tmpDTRect;
|
||||
|
||||
if (ctx->CurrentOp() != CompositionOp::OP_OVER ||
|
||||
mMaskOp == NS_STYLE_MASK_MODE_LUMINANCE) {
|
||||
mMaskOp == StyleMaskMode::Luminance) {
|
||||
gfxRect clipRect = ctx->GetClipExtents(gfxContext::eDeviceSpace);
|
||||
tmpDTRect = RoundedOut(ToRect(clipRect));
|
||||
if (tmpDTRect.IsEmpty()) {
|
||||
|
@ -493,7 +493,7 @@ ImgDrawResult nsImageRenderer::Draw(nsPresContext* aPresContext,
|
|||
DrawTarget* dt = aRenderingContext.GetDrawTarget();
|
||||
Matrix oldTransform = dt->GetTransform();
|
||||
dt->SetTransform(Matrix());
|
||||
if (mMaskOp == NS_STYLE_MASK_MODE_LUMINANCE) {
|
||||
if (mMaskOp == StyleMaskMode::Luminance) {
|
||||
RefPtr<SourceSurface> surf = ctx->GetDrawTarget()->IntoLuminanceSource(
|
||||
LuminanceType::LUMINANCE, 1.0f);
|
||||
dt->MaskSurface(ColorPattern(Color(0, 0, 0, 1.0f)), surf,
|
||||
|
|
|
@ -249,7 +249,7 @@ class nsImageRenderer {
|
|||
bool IsReady() const { return mPrepareResult == ImgDrawResult::SUCCESS; }
|
||||
ImgDrawResult PrepareResult() const { return mPrepareResult; }
|
||||
void SetExtendMode(mozilla::gfx::ExtendMode aMode) { mExtendMode = aMode; }
|
||||
void SetMaskOp(uint8_t aMaskOp) { mMaskOp = aMaskOp; }
|
||||
void SetMaskOp(mozilla::StyleMaskMode aMaskOp) { mMaskOp = aMaskOp; }
|
||||
void PurgeCacheForViewportChange(
|
||||
const mozilla::Maybe<nsSize>& aSVGViewportSize, const bool aHasRatio);
|
||||
nsStyleImageType GetType() const { return mType; }
|
||||
|
@ -305,7 +305,7 @@ class nsImageRenderer {
|
|||
nsSize mSize; // unscaled size of the image, in app units
|
||||
uint32_t mFlags;
|
||||
mozilla::gfx::ExtendMode mExtendMode;
|
||||
uint8_t mMaskOp;
|
||||
mozilla::StyleMaskMode mMaskOp;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -2270,10 +2270,6 @@ nsresult nsPrintJob::ReflowPrintObject(const UniquePtr<nsPrintObject>& aPO) {
|
|||
aPO.get(), aPO->mPresShell.get(), gFrameTypesStr[aPO->mFrameType],
|
||||
adjSize.width, adjSize.height));
|
||||
|
||||
// This docshell stuff is weird; will go away when we stop having multiple
|
||||
// presentations per document
|
||||
aPO->mPresContext->SetContainer(aPO->mDocShell);
|
||||
|
||||
aPO->mPresShell->BeginObservingDocument();
|
||||
|
||||
aPO->mPresContext->SetPageSize(adjSize);
|
||||
|
|
|
@ -134,6 +134,7 @@ rusty-enums = [
|
|||
"mozilla::StyleWhiteSpace",
|
||||
"mozilla::StyleTextRendering",
|
||||
"mozilla::StyleColorAdjust",
|
||||
"mozilla::StyleFlexDirection",
|
||||
"nsStyleImageType",
|
||||
"nsStyleSVGPaintType",
|
||||
"nsStyleSVGFallbackType",
|
||||
|
@ -144,6 +145,7 @@ rusty-enums = [
|
|||
"nsStyleTransformMatrix::MatrixTransformOperator",
|
||||
"mozilla::StyleGeometryBox",
|
||||
"mozilla::SystemColor",
|
||||
"mozilla::StyleMaskMode",
|
||||
]
|
||||
whitelist-vars = [
|
||||
"NS_AUTHOR_SPECIFIED_.*",
|
||||
|
@ -436,7 +438,12 @@ cbindgen-types = [
|
|||
{ gecko = "StyleCSSPixelLength", servo = "values::computed::length::CSSPixelLength" },
|
||||
{ gecko = "StyleNonNegativeLength", servo = "values::computed::NonNegativeLength" },
|
||||
{ gecko = "StyleNonNegativeNumber", servo = "values::computed::NonNegativeNumber" },
|
||||
{ gecko = "StylePercentage", servo = "values::computed::Percentage" }
|
||||
{ gecko = "StylePercentage", servo = "values::computed::Percentage" },
|
||||
{ gecko = "StylePerspective", servo = "values::computed::Perspective" },
|
||||
{ gecko = "StyleGenericPerspective", servo = "values::generics::box_::Perspective" },
|
||||
{ gecko = "StyleZIndex", servo = "values::computed::ZIndex" },
|
||||
{ gecko = "StyleGenericZIndex", servo = "values::generics::position::ZIndex" },
|
||||
{ gecko = "StyleTransformOrigin", servo = "values::computed::TransformOrigin" },
|
||||
]
|
||||
|
||||
mapped-generic-types = [
|
||||
|
|