a=release IGNORE BAD COMMIT MESSAGES
This commit is contained in:
Wes Kocher 2017-05-19 15:18:51 -07:00
Родитель 24b1d128db 15edcfd962
Коммит 8b07ba2a07
290 изменённых файлов: 6952 добавлений и 6304 удалений

Просмотреть файл

@ -62,7 +62,6 @@ DEFAULT_NO_CONNECTIONS_PREFS = {
'browser.safebrowsing.provider.google.gethashURL': 'http://localhost/safebrowsing-dummy/gethash',
'browser.safebrowsing.provider.google4.updateURL': 'http://localhost/safebrowsing4-dummy/update',
'browser.safebrowsing.provider.google4.gethashURL': 'http://localhost/safebrowsing4-dummy/gethash',
'browser.selfsupport.url': 'https://localhost/selfsupport-dummy',
'browser.safebrowsing.provider.mozilla.gethashURL': 'http://localhost/safebrowsing-dummy/gethash',
'browser.safebrowsing.provider.mozilla.updateURL': 'http://localhost/safebrowsing-dummy/update',

Просмотреть файл

@ -5,7 +5,6 @@
const { Cu, Ci } = require("chrome");
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
const { SelfSupportBackend } = Cu.import("resource:///modules/SelfSupportBackend.jsm", {});
const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
// Adapted from the SpecialPowers.exactGC() code. We don't have a
@ -38,11 +37,6 @@ function gc() {
// object then it will be unloaded after the memory measurements.
exports.asyncWindowLeakTest = function*(assert, asyncTestFunc) {
// SelfSupportBackend periodically tries to open windows. This can
// mess up our window leak detection below, so turn it off.
if (SelfSupportBackend._log)
SelfSupportBackend.uninit();
// Wait for the browser to finish loading.
yield Startup.onceInitialized;

Просмотреть файл

@ -24,7 +24,6 @@
"browser.safebrowsing.provider.google4.updateURL": "http://localhost/safebrowsing4-dummy/update",
"browser.safebrowsing.provider.google4.gethashURL": "http://localhost/safebrowsing4-dummy/gethash",
"browser.safebrowsing.provider.google4.reportURL": "http://localhost/safebrowsing4-dummy/malwarereport",
"browser.selfsupport.url": "https://localhost/selfsupport-dummy",
"browser.safebrowsing.provider.mozilla.gethashURL": "http://localhost/safebrowsing-dummy/gethash",
"browser.safebrowsing.provider.mozilla.updateURL": "http://localhost/safebrowsing-dummy/update",
"browser.newtabpage.directory.source": "data:application/json,{'jetpack':1}",

Просмотреть файл

@ -8,7 +8,6 @@
# UITour
origin uitour 1 https://www.mozilla.org
origin uitour 1 https://self-repair.mozilla.org
origin uitour 1 https://support.mozilla.org
origin uitour 1 https://addons.mozilla.org
origin uitour 1 https://discovery.addons.mozilla.org

Просмотреть файл

@ -822,8 +822,6 @@ pref("browser.rights.3.shown", false);
pref("browser.rights.override", true);
#endif
pref("browser.selfsupport.url", "https://self-repair.mozilla.org/%LOCALE%/repair");
pref("browser.sessionstore.resume_from_crash", true);
pref("browser.sessionstore.resume_session_once", false);

Просмотреть файл

@ -145,7 +145,8 @@
noautofocus="true"
hidden="true"
overflowpadding="4"
norolluponanchor="true" />
norolluponanchor="true"
nomaxresults="true" />
<!-- for search with one-off buttons -->
<panel type="autocomplete" id="PopupSearchAutoComplete" noautofocus="true" hidden="true"/>
@ -320,7 +321,7 @@
<observes element="viewTabsSidebar" attribute="checked"/>
</toolbarbutton>
<toolbarseparator/>
<toolbarbutton label="&sidebarCloseButton.tooltip;"
<toolbarbutton label="&sidebarMenuClose.label;"
class="subviewbutton"
oncommand="SidebarUI.hide()"/>
</panel>

Просмотреть файл

@ -1000,11 +1000,15 @@
var newTitle = "";
var docElement = this.ownerDocument.documentElement;
var sep = docElement.getAttribute("titlemenuseparator");
let tab = this.getTabForBrowser(aBrowser);
let docTitle;
// Strip out any null bytes in the content title, since the
// underlying widget implementations of nsWindow::SetTitle pass
// null-terminated strings to system APIs.
var docTitle = aBrowser.contentTitle.replace(/\0/g, "");
if (tab._labelIsContentTitle) {
// Strip out any null bytes in the content title, since the
// underlying widget implementations of nsWindow::SetTitle pass
// null-terminated strings to system APIs.
docTitle = tab.getAttribute("label").replace(/\0/g, "");
}
if (!docTitle)
docTitle = docElement.getAttribute("titledefault");
@ -1412,13 +1416,14 @@
<method name="setInitialTabTitle">
<parameter name="aTab"/>
<parameter name="aTitle"/>
<parameter name="aOptions"/>
<body><![CDATA[
if (aTitle) {
aTab.setAttribute("label", aTitle);
// Don't replace the set label with the empty tab label or the URL
// while the tab is loading.
aTab._suppressTransientPlaceholderLabel = true;
this._setTabLabel(aTab, aTitle, aOptions);
}
]]></body>
</method>
@ -1437,7 +1442,10 @@
delete aTab._suppressTransientPlaceholderLabel;
}
if (!title) {
let isContentTitle = false;
if (title) {
isContentTitle = true;
} else {
if (browser.currentURI.spec) {
try {
title = this.mURIFixup.createExposableURI(browser.currentURI).spec;
@ -1465,14 +1473,33 @@
title = this.mStringBundle.getString("tabs.emptyTabTitle");
}
if (aTab.label == title)
return this._setTabLabel(aTab, title, { isContentTitle });
]]>
</body>
</method>
<method name="_setTabLabel">
<parameter name="aTab"/>
<parameter name="aLabel"/>
<parameter name="aOptions"/>
<body>
<![CDATA[
if (!aLabel || aTab.getAttribute("label") == aLabel) {
return false;
}
aTab.label = title;
this._tabAttrModified(aTab, ["label"]);
aTab.setAttribute("label", aLabel);
aTab._labelIsContentTitle = aOptions && aOptions.isContentTitle;
if (aTab.selected)
// Dispatch TabAttrModified event unless we're setting the label
// before the TabOpen event was dispatched.
if (!aOptions || !aOptions.beforeTabOpen) {
this._tabAttrModified(aTab, ["label"]);
}
if (aTab.selected) {
this.updateTitlebar();
}
return true;
]]>
@ -2313,7 +2340,7 @@
t.setAttribute("label", this.mStringBundle.getString("tabs.emptyTabTitle"));
} else {
// Set URL as label so that the tab isn't empty initially.
this.setInitialTabTitle(t, aURI);
this.setInitialTabTitle(t, aURI, { beforeTabOpen: true });
}
}

Просмотреть файл

@ -7,7 +7,7 @@ async function wait_for_tab_playing_event(tab, expectPlaying) {
ok(true, "The tab should " + (expectPlaying ? "" : "not ") + "be playing");
return true;
}
return await BrowserTestUtils.waitForEvent(tab, "TabAttrModified", false, (event) => {
return BrowserTestUtils.waitForEvent(tab, "TabAttrModified", false, (event) => {
if (event.detail.changed.includes("soundplaying")) {
is(tab.hasAttribute("soundplaying"), expectPlaying, "The tab should " + (expectPlaying ? "" : "not ") + "be playing");
is(tab.soundPlaying, expectPlaying, "The tab should " + (expectPlaying ? "" : "not ") + "be playing");
@ -53,8 +53,6 @@ async function pause(tab, options) {
let browser = tab.linkedBrowser;
let awaitDOMAudioPlaybackStopped =
BrowserTestUtils.waitForEvent(browser, "DOMAudioPlaybackStopped", "DOMAudioPlaybackStopped event should get fired after pause");
let awaitTabPausedAttrModified =
wait_for_tab_playing_event(tab, false);
await ContentTask.spawn(browser, {}, async function() {
let audio = content.document.querySelector("audio");
audio.pause();
@ -73,7 +71,7 @@ async function pause(tab, options) {
ok(tab.hasAttribute("soundplaying"), "The tab should still have the soundplaying attribute immediately after DOMAudioPlaybackStopped");
}
await awaitTabPausedAttrModified;
await wait_for_tab_playing_event(tab, false);
ok(!tab.hasAttribute("soundplaying"), "The tab should not have the soundplaying attribute after the timeout has resolved");
} finally {
// Make sure other tests don't timeout if an exception gets thrown above.

Просмотреть файл

@ -34,7 +34,7 @@ XPCOMUtils.defineLazyGetter(this, "WeaveService", () =>
PageThumbs:false, PdfJs:false, PermissionUI:false, PlacesBackups:false,
PlacesUtils:false, PluralForm:false, PrivateBrowsingUtils:false,
ProcessHangMonitor:false, ReaderParent:false, RecentWindow:false,
RemotePrompt:false, SelfSupportBackend:false, SessionStore:false,
RemotePrompt:false, SessionStore:false,
ShellService:false, SimpleServiceDiscovery:false, TabCrashHandler:false,
Task:false, UITour:false, WebChannel:false,
WindowsRegistry:false, webrtcUI:false, UserAgentOverrides: false */
@ -83,7 +83,6 @@ let initializedModules = {};
["ReaderParent", "resource:///modules/ReaderParent.jsm"],
["RecentWindow", "resource:///modules/RecentWindow.jsm"],
["RemotePrompt", "resource:///modules/RemotePrompt.jsm"],
["SelfSupportBackend", "resource:///modules/SelfSupportBackend.jsm", "init"],
["SessionStore", "resource:///modules/sessionstore/SessionStore.jsm"],
["ShellService", "resource:///modules/ShellService.jsm"],
["SimpleServiceDiscovery", "resource://gre/modules/SimpleServiceDiscovery.jsm"],
@ -126,10 +125,6 @@ XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() {
const global = this;
const listeners = {
observers: {
"sessionstore-windows-restored": ["SelfSupportBackend"],
},
ppmm: {
// PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN ContentPrefServiceParent.init
"ContentPrefs:FunctionCall": ["ContentPrefServiceParent"],
@ -171,16 +166,6 @@ const listeners = {
"webrtc:UpdateBrowserIndicators": ["webrtcUI"],
},
observe(subject, topic, data) {
for (let module of this.observers[topic]) {
try {
this[module].observe(subject, topic, data);
} catch (e) {
Cu.reportError(e);
}
}
},
receiveMessage(modules, data) {
let val;
for (let module of modules[data.name]) {
@ -194,10 +179,6 @@ const listeners = {
},
init() {
for (let observer of Object.keys(this.observers)) {
Services.obs.addObserver(this, observer);
}
let receiveMessageMM = this.receiveMessage.bind(this, this.mm);
for (let message of Object.keys(this.mm)) {
Services.mm.addMessageListener(message, receiveMessageMM);

Просмотреть файл

@ -2646,7 +2646,7 @@ var SessionStoreInternal = {
// If the page has a title, set it.
if (activePageData) {
if (activePageData.title) {
win.gBrowser.setInitialTabTitle(tab, activePageData.title);
win.gBrowser.setInitialTabTitle(tab, activePageData.title, { isContentTitle: true });
} else if (activePageData.url != "about:blank") {
win.gBrowser.setInitialTabTitle(tab, activePageData.url);
}

Просмотреть файл

@ -51,6 +51,7 @@ add_task(async function() {
isnot(CONTENT_TITLE.length, 0, "content title isn't empty");
isnot(CONTENT_TITLE, TEST_URL, "content title is different from the URL");
is(firstTab.label, CONTENT_TITLE, "first tab displays content title");
ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
ok(secondTab.hasAttribute("pending"), "second tab is pending");
is(secondTab.label, TEST_URL, "second tab displays URL as its title");
@ -60,7 +61,8 @@ add_task(async function() {
gBrowser.selectedTab = secondTab;
await browserLoadedPromise;
ok(!secondTab.hasAttribute("pending"), "second tab isn't pending anymore");
is(gBrowser.selectedTab.label, CONTENT_TITLE, "second tab displays content title");
is(secondTab.label, CONTENT_TITLE, "second tab displays content title");
ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
checkLabelChangeCount(1);
info("restoring the modified browser state");
@ -68,6 +70,7 @@ add_task(async function() {
await promiseBrowserState(SessionStore.getBrowserState());
[firstTab, secondTab] = gBrowser.tabs;
is(secondTab, gBrowser.selectedTab, "second tab is selected after restoring");
ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
ok(firstTab.hasAttribute("pending"), "first tab is pending after restoring");
is(firstTab.label, CONTENT_TITLE, "first tab displays content title in pending state");
@ -75,6 +78,7 @@ add_task(async function() {
checkLabelChangeCount = observeLabelChanges(firstTab);
let tabContentRestored = TestUtils.topicObserved("sessionstore-debug-tab-restored");
gBrowser.selectedTab = firstTab;
ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
await tabContentRestored;
ok(!firstTab.hasAttribute("pending"), "first tab isn't pending anymore");
checkLabelChangeCount(0);

Просмотреть файл

@ -666,7 +666,8 @@ you can use these alternative items. Otherwise, their values should be empty. -
<!ENTITY fullZoom.label "Zoom">
<!ENTITY fullZoom.accesskey "Z">
<!ENTITY sidebarCloseButton.tooltip "Close Sidebar">
<!ENTITY sidebarCloseButton.tooltip "Close sidebar">
<!ENTITY sidebarMenuClose.label "Close Sidebar">
<!ENTITY quitApplicationCmdWin2.label "Exit">
<!ENTITY quitApplicationCmdWin2.accesskey "x">

Просмотреть файл

@ -1,353 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = ["SelfSupportBackend"];
const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Timer.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "HiddenFrame",
"resource://gre/modules/HiddenFrame.jsm");
// Enables or disables the Self Support.
const PREF_ENABLED = "browser.selfsupport.enabled";
// Url to open in the Self Support browser, in the urlFormatter service format.
const PREF_URL = "browser.selfsupport.url";
// Unified Telemetry status.
const PREF_TELEMETRY_UNIFIED = "toolkit.telemetry.unified";
// UITour status.
const PREF_UITOUR_ENABLED = "browser.uitour.enabled";
// Controls the interval at which the self support page tries to reload in case of
// errors.
const RETRY_INTERVAL_MS = 30000;
// Maximum number of SelfSupport page load attempts in case of failure.
const MAX_RETRIES = 5;
// The delay after which to load the self-support, at startup.
const STARTUP_DELAY_MS = 5000;
const LOGGER_NAME = "Browser.SelfSupportBackend";
const PREF_BRANCH_LOG = "browser.selfsupport.log.";
const PREF_LOG_LEVEL = PREF_BRANCH_LOG + "level";
const PREF_LOG_DUMP = PREF_BRANCH_LOG + "dump";
const HTML_NS = "http://www.w3.org/1999/xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const UITOUR_FRAME_SCRIPT = "chrome://browser/content/content-UITour.js";
// Whether the FHR/Telemetry unification features are enabled.
// Changing this pref requires a restart.
const IS_UNIFIED_TELEMETRY = Services.prefs.getBoolPref(PREF_TELEMETRY_UNIFIED, false);
var gLogAppenderDump = null;
this.SelfSupportBackend = Object.freeze({
init() {
SelfSupportBackendInternal.init();
},
uninit() {
SelfSupportBackendInternal.uninit();
},
});
var SelfSupportBackendInternal = {
// The browser element that will load the SelfSupport page.
_browser: null,
// The Id of the timer triggering delayed SelfSupport page load.
_delayedLoadTimerId: null,
// The HiddenFrame holding the _browser element.
_frame: null,
_log: null,
_progressListener: null,
// Whether we're invited to let test code talk to our frame.
_testing: false,
// Whether self-support is enabled, and we want to continue lazy UI
// startup after the session has been restored.
_lazyStartupEnabled: false,
/**
* Initializes the self support backend.
*/
init() {
this._configureLogging();
this._log.trace("init");
Services.prefs.addObserver(PREF_BRANCH_LOG, this);
// Only allow to use SelfSupport if Unified Telemetry is enabled.
let reportingEnabled = IS_UNIFIED_TELEMETRY;
if (!reportingEnabled) {
this._log.config("init - Disabling SelfSupport because FHR and Unified Telemetry are disabled.");
return;
}
// Make sure UITour is enabled.
let uiTourEnabled = Services.prefs.getBoolPref(PREF_UITOUR_ENABLED, false);
if (!uiTourEnabled) {
this._log.config("init - Disabling SelfSupport because UITour is disabled.");
return;
}
// Check the preferences to see if we want this to be active.
if (!Services.prefs.getBoolPref(PREF_ENABLED, true)) {
this._log.config("init - SelfSupport is disabled.");
return;
}
this._lazyStartupEnabled = true;
},
/**
* Shut down the self support backend, if active.
*/
uninit() {
if (!this._log) {
// We haven't been initialized yet, so just return.
return;
}
this._log.trace("uninit");
Services.prefs.removeObserver(PREF_BRANCH_LOG, this);
// Cancel delayed loading, if still active, when shutting down.
clearTimeout(this._delayedLoadTimerId);
// Dispose of the hidden browser.
if (this._browser !== null) {
if (this._browser.contentWindow) {
this._browser.contentWindow.removeEventListener("DOMWindowClose", this, true);
}
if (this._progressListener) {
this._browser.removeProgressListener(this._progressListener);
this._progressListener.destroy();
this._progressListener = null;
}
this._browser.remove();
this._browser = null;
}
if (this._frame) {
this._frame.destroy();
this._frame = null;
}
if (this._testing) {
Services.obs.notifyObservers(this._browser, "self-support-browser-destroyed");
}
},
/**
* Handle notifications. Once all windows are created, we wait a little bit more
* since tabs might still be loading. Then, we open the self support.
*/
// Observers are added in nsBrowserGlue.js
observe(aSubject, aTopic, aData) {
this._log.trace("observe - Topic " + aTopic);
if (aTopic === "sessionstore-windows-restored") {
if (this._lazyStartupEnabled) {
this._delayedLoadTimerId = setTimeout(this._loadSelfSupport.bind(this), STARTUP_DELAY_MS);
this._lazyStartupEnabled = false;
}
} else if (aTopic === "nsPref:changed") {
this._configureLogging();
}
},
/**
* Configure the logger based on the preferences.
*/
_configureLogging() {
if (!this._log) {
this._log = Log.repository.getLogger(LOGGER_NAME);
// Log messages need to go to the browser console.
let consoleAppender = new Log.ConsoleAppender(new Log.BasicFormatter());
this._log.addAppender(consoleAppender);
}
// Make sure the logger keeps up with the logging level preference.
this._log.level = Log.Level[Services.prefs.getStringPref(PREF_LOG_LEVEL, "Warn")];
// If enabled in the preferences, add a dump appender.
let logDumping = Services.prefs.getBoolPref(PREF_LOG_DUMP, false);
if (logDumping != !!gLogAppenderDump) {
if (logDumping) {
gLogAppenderDump = new Log.DumpAppender(new Log.BasicFormatter());
this._log.addAppender(gLogAppenderDump);
} else {
this._log.removeAppender(gLogAppenderDump);
gLogAppenderDump = null;
}
}
},
/**
* Create an hidden frame to host our |browser|, then load the SelfSupport page in it.
* @param aURL The URL to load in the browser.
*/
_makeHiddenBrowser(aURL) {
this._frame = new HiddenFrame();
return this._frame.get().then(aFrame => {
let doc = aFrame.document;
this._browser = doc.createElementNS(XUL_NS, "browser");
this._browser.setAttribute("type", "content");
this._browser.setAttribute("disableglobalhistory", "true");
this._browser.setAttribute("src", aURL);
if (this._testing) {
Services.obs.notifyObservers(this._browser, "self-support-browser-created");
}
doc.documentElement.appendChild(this._browser);
});
},
handleEvent(aEvent) {
this._log.trace("handleEvent - aEvent.type " + aEvent.type + ", Trusted " + aEvent.isTrusted);
if (aEvent.type === "DOMWindowClose") {
let window = this._browser.contentDocument.defaultView;
let target = aEvent.target;
if (target == window) {
// preventDefault stops the default window.close(). We need to do that to prevent
// Services.appShell.hiddenDOMWindow from being destroyed.
aEvent.preventDefault();
this.uninit();
}
}
},
/**
* Called when the self support page correctly loads.
*/
_pageSuccessCallback() {
this._log.debug("_pageSuccessCallback - Page correctly loaded.");
this._browser.removeProgressListener(this._progressListener);
this._progressListener.destroy();
this._progressListener = null;
// Allow SelfSupportBackend to catch |window.close()| issued by the content.
this._browser.contentWindow.addEventListener("DOMWindowClose", this, true);
},
/**
* Called when the self support page fails to load.
*/
_pageLoadErrorCallback() {
this._log.info("_pageLoadErrorCallback - Too many failed load attempts. Giving up.");
this.uninit();
},
/**
* Create a browser and attach it to an hidden window. The browser will contain the
* self support page and attempt to load the page content. If loading fails, try again
* after an interval.
*/
_loadSelfSupport() {
// Fetch the Self Support URL from the preferences.
let unformattedURL = Services.prefs.getStringPref(PREF_URL, "");
let url = Services.urlFormatter.formatURL(unformattedURL);
if (!url.startsWith("https:")) {
this._log.error("_loadSelfSupport - Non HTTPS URL provided: " + url);
return;
}
this._log.config("_loadSelfSupport - URL " + url);
// Create the hidden browser.
this._makeHiddenBrowser(url).then(() => {
// Load UITour frame script.
this._browser.messageManager.loadFrameScript(UITOUR_FRAME_SCRIPT, true);
// We need to watch for load errors as well and, in case, try to reload
// the self support page.
const webFlags = Ci.nsIWebProgress.NOTIFY_STATE_WINDOW |
Ci.nsIWebProgress.NOTIFY_STATE_REQUEST |
Ci.nsIWebProgress.NOTIFY_LOCATION;
this._progressListener = new ProgressListener(() => this._pageLoadErrorCallback(),
() => this._pageSuccessCallback());
this._browser.addProgressListener(this._progressListener, webFlags);
});
}
};
/**
* A progress listener object which notifies of page load error and load success
* through callbacks. When the page fails to load, the progress listener tries to
* reload it up to MAX_RETRIES times. The page is not loaded again immediately, but
* after a timeout.
*
* @param aLoadErrorCallback Called when a page failed to load MAX_RETRIES times.
* @param aLoadSuccessCallback Called when a page correctly loads.
*/
function ProgressListener(aLoadErrorCallback, aLoadSuccessCallback) {
this._loadErrorCallback = aLoadErrorCallback;
this._loadSuccessCallback = aLoadSuccessCallback;
// The number of page loads attempted.
this._loadAttempts = 0;
this._log = Log.repository.getLogger(LOGGER_NAME);
// The Id of the timer which triggers page load again in case of errors.
this._reloadTimerId = null;
}
ProgressListener.prototype = {
onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) {
this._log.warn("onLocationChange - There was a problem fetching the SelfSupport URL (attempt " +
this._loadAttempts + ").");
// Increase the number of attempts and bail out if we failed too many times.
this._loadAttempts++;
if (this._loadAttempts > MAX_RETRIES) {
this._loadErrorCallback();
return;
}
// Reload the page after the retry interval expires. The interval is multiplied
// by the number of attempted loads, so that it takes a bit more to try to reload
// when frequently failing.
this._reloadTimerId = setTimeout(() => {
this._log.debug("onLocationChange - Reloading SelfSupport URL in the hidden browser.");
aWebProgress.DOMWindow.location.reload();
}, RETRY_INTERVAL_MS * this._loadAttempts);
}
},
onStateChange(aWebProgress, aRequest, aFlags, aStatus) {
if (aFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW &&
Components.isSuccessCode(aStatus)) {
this._loadSuccessCallback();
}
},
destroy() {
// Make sure we don't try to reload self support when shutting down.
clearTimeout(this._reloadTimerId);
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference]),
};

Просмотреть файл

@ -16,9 +16,6 @@ with Files("test/browser/*ContentSearch*"):
with Files("test/browser/*PermissionUI*"):
BUG_COMPONENT = ("Firefox", "Site Identity and Permission Panels")
with Files("test/browser/browser_SelfSupportBackend.js"):
BUG_COMPONENT = ("Toolkit", "Telemetry")
with Files("test/browser/*SitePermissions*"):
BUG_COMPONENT = ("Firefox", "Site Identity and Permission Panels")
@ -97,9 +94,6 @@ with Files("ReaderParent.jsm"):
with Files("Sanitizer.jsm"):
BUG_COMPONENT = ("Firefox", "Preferences")
with Files("SelfSupportBackend.jsm"):
BUG_COMPONENT = ("Toolkit", "Telemetry")
with Files("SitePermissions.jsm"):
BUG_COMPONENT = ("Firefox", "Site Identity and Permission Panels")
@ -160,7 +154,6 @@ EXTRA_JS_MODULES += [
'RecentWindow.jsm',
'RemotePrompt.jsm',
'Sanitizer.jsm',
'SelfSupportBackend.jsm',
'SitePermissions.jsm',
'Social.jsm',
'SocialService.jsm',

Просмотреть файл

@ -19,10 +19,6 @@ support-files =
[browser_PermissionUI_prompts.js]
[browser_ProcessHangNotifications.js]
skip-if = !e10s
[browser_SelfSupportBackend.js]
support-files =
../../../components/uitour/test/uitour.html
../../../components/uitour/UITour-lib.js
[browser_SitePermissions.js]
[browser_SitePermissions_combinations.js]
[browser_SitePermissions_expiry.js]

Просмотреть файл

@ -1,172 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// Pass an empty scope object to the import to prevent "leaked window property"
// errors in tests.
var Preferences = Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
var PromiseUtils = Cu.import("resource://gre/modules/PromiseUtils.jsm", {}).PromiseUtils;
var SelfSupportBackend =
Cu.import("resource:///modules/SelfSupportBackend.jsm", {}).SelfSupportBackend;
const PREF_SELFSUPPORT_ENABLED = "browser.selfsupport.enabled";
const PREF_SELFSUPPORT_URL = "browser.selfsupport.url";
const PREF_UITOUR_ENABLED = "browser.uitour.enabled";
const TEST_WAIT_RETRIES = 60;
const TEST_PAGE_URL = getRootDirectory(gTestPath) + "uitour.html";
const TEST_PAGE_URL_HTTPS = TEST_PAGE_URL.replace("chrome://mochitests/content/", "https://example.com/");
function sendSessionRestoredNotification() {
let selfSupportBackendImpl =
Cu.import("resource:///modules/SelfSupportBackend.jsm", {}).SelfSupportBackendInternal;
selfSupportBackendImpl.observe(null, "sessionstore-windows-restored", null);
}
function toggleSelfSupportTestMode(testing) {
let selfSupportBackendImpl =
Cu.import("resource:///modules/SelfSupportBackend.jsm", {}).SelfSupportBackendInternal;
selfSupportBackendImpl._testing = testing;
}
/**
* Wait for self support page to load.
*
* @param aURL The URL to look for to identify the browser.
*
* @returns {Promise} Return a promise which is resolved when SelfSupport page is fully
* loaded.
*/
function promiseSelfSupportLoad(aURL) {
return new Promise((resolve, reject) => {
// Find the SelfSupport browser.
let browser = null;
let browserPromise = TestUtils.topicObserved("self-support-browser-created",
(subject, topic) => {
let url = subject.getAttribute("src");
Cu.reportError("Got browser with src: " + url);
if (url == aURL) {
browser = subject;
}
return url == aURL;
});
// Once found, append a "load" listener to catch page loads.
browserPromise.then(() => {
if (browser.contentDocument.readyState === "complete") {
resolve(browser);
} else {
let handler = () => {
browser.removeEventListener("load", handler, true);
resolve(browser);
};
browser.addEventListener("load", handler, true);
}
}, reject);
});
}
/**
* Prepare the test environment.
*/
add_task(async function setupEnvironment() {
// We always run the SelfSupportBackend in tests to check for weird behaviours.
// Disable it to test its start-up.
SelfSupportBackend.uninit();
// Testing prefs are set via |user_pref|, so we need to get their value in order
// to restore them.
let selfSupportEnabled = Preferences.get(PREF_SELFSUPPORT_ENABLED, true);
let uitourEnabled = Preferences.get(PREF_UITOUR_ENABLED, false);
let selfSupportURL = Preferences.get(PREF_SELFSUPPORT_URL, "");
// Enable the SelfSupport backend and set the page URL. We also make sure UITour
// is enabled.
Preferences.set(PREF_SELFSUPPORT_ENABLED, true);
Preferences.set(PREF_UITOUR_ENABLED, true);
Preferences.set(PREF_SELFSUPPORT_URL, TEST_PAGE_URL_HTTPS);
// Whitelist the HTTPS page to use UITour.
let pageURI = Services.io.newURI(TEST_PAGE_URL_HTTPS);
Services.perms.add(pageURI, "uitour", Services.perms.ALLOW_ACTION);
registerCleanupFunction(() => {
Services.perms.remove(pageURI, "uitour");
Preferences.set(PREF_SELFSUPPORT_ENABLED, selfSupportEnabled);
Preferences.set(PREF_UITOUR_ENABLED, uitourEnabled);
Preferences.set(PREF_SELFSUPPORT_URL, selfSupportURL);
});
});
/**
* Test that the self support page can use the UITour API and close itself.
*/
add_task(async function test_selfSupport() {
toggleSelfSupportTestMode(true);
registerCleanupFunction(toggleSelfSupportTestMode.bind(null, false));
// Initialise the SelfSupport backend and trigger the load.
SelfSupportBackend.init();
// Wait for the SelfSupport page to load.
let selfSupportBrowserPromise = promiseSelfSupportLoad(TEST_PAGE_URL_HTTPS);
// SelfSupportBackend waits for "sessionstore-windows-restored" to start loading. Send it.
info("Sending sessionstore-windows-restored");
sendSessionRestoredNotification();
// Wait for the SelfSupport page to load.
info("Waiting for the SelfSupport local page to load.");
let selfSupportBrowser = await selfSupportBrowserPromise;
Assert.ok(!!selfSupportBrowser, "SelfSupport browser must exist.");
// Get a reference to the UITour API.
info("Testing access to the UITour API.");
let contentWindow =
Cu.waiveXrays(selfSupportBrowser.contentDocument.defaultView);
let uitourAPI = contentWindow.Mozilla.UITour;
// Test the UITour API with a ping.
let pingPromise = new Promise((resolve) => {
uitourAPI.ping(resolve);
});
await pingPromise;
info("Ping succeeded");
let observePromise = ContentTask.spawn(selfSupportBrowser, null, async function checkObserve() {
await new Promise(resolve => {
let win = Cu.waiveXrays(content);
win.Mozilla.UITour.observe((event, data) => {
if (event != "Heartbeat:Engaged") {
return;
}
Assert.equal(data.flowId, "myFlowID", "Check flowId");
Assert.ok(!!data.timestamp, "Check timestamp");
resolve(data);
}, () => {});
});
});
info("Notifying Heartbeat:Engaged");
UITour.notify("Heartbeat:Engaged", {
flowId: "myFlowID",
timestamp: Date.now(),
});
await observePromise;
info("Observed in the hidden frame");
let selfSupportClosed = TestUtils.topicObserved("self-support-browser-destroyed");
// Close SelfSupport from content.
contentWindow.close();
await selfSupportClosed;
Assert.ok(!selfSupportBrowser.parentNode, "SelfSupport browser must have been removed.");
// We shouldn't need this, but let's keep it to make sure closing SelfSupport twice
// doesn't create any problem.
SelfSupportBackend.uninit();
});

Просмотреть файл

@ -30,6 +30,7 @@ function SourceMapURLService(target, sourceMapService) {
* Reset the service. This flushes the internal cache.
*/
SourceMapURLService.prototype.reset = function () {
this._sourceMapService.clearSourceMaps();
this._urls.clear();
};

Просмотреть файл

@ -11,10 +11,17 @@ support-files =
code_binary_search.coffee
code_binary_search.js
code_binary_search.map
code_bundle_reload_1.js
code_bundle_reload_1.js.map
code_bundle_reload_2.js
code_bundle_reload_2.js.map
code_inline_bundle.js
code_inline_original.js
code_math.js
code_reload_1.js
code_reload_2.js
doc_empty-tab-01.html
doc_reload.html
head.js
shared-head.js
shared-redux-head.js
@ -24,6 +31,8 @@ support-files =
browser_toolbox_options_enable_serviceworkers_testing_frame_script.js
browser_toolbox_options_enable_serviceworkers_testing.html
serviceworker.js
sjs_code_reload.sjs
sjs_code_bundle_reload_map.sjs
test_browser_toolbox_debugger.js
[browser_browser_toolbox.js]
@ -39,6 +48,7 @@ support-files =
[browser_new_activation_workflow.js]
[browser_source_map-01.js]
[browser_source_map-inline.js]
[browser_source_map-reload.js]
[browser_target_from_url.js]
[browser_target_events.js]
[browser_target_remote.js]

Просмотреть файл

@ -0,0 +1,48 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that reloading re-reads the source maps.
"use strict";
const INITIAL_URL = URL_ROOT + "doc_empty-tab-01.html";
const PAGE_URL = URL_ROOT + "doc_reload.html";
const JS_URL = URL_ROOT + "sjs_code_reload.sjs";
const ORIGINAL_URL_1 = "webpack:///code_reload_1.js";
const ORIGINAL_URL_2 = "webpack:///code_reload_2.js";
const GENERATED_LINE = 86;
const ORIGINAL_LINE = 13;
add_task(function* () {
// Start with the empty page, then navigate, so that we can properly
// listen for new sources arriving.
const toolbox = yield openNewTabAndToolbox(INITIAL_URL, "webconsole");
const service = toolbox.sourceMapURLService;
const tab = toolbox.target.tab;
let sourceSeen = waitForSourceLoad(toolbox, JS_URL);
tab.linkedBrowser.loadURI(PAGE_URL);
yield sourceSeen;
info(`checking original location for ${JS_URL}:${GENERATED_LINE}`);
let newLoc = yield service.originalPositionFor(JS_URL, GENERATED_LINE);
is(newLoc.sourceUrl, ORIGINAL_URL_1, "check mapped URL");
is(newLoc.line, ORIGINAL_LINE, "check mapped line number");
// Reload the page. The sjs ensures that a different source file
// will be loaded.
sourceSeen = waitForSourceLoad(toolbox, JS_URL);
yield refreshTab(tab);
yield sourceSeen;
info(`checking post-reload original location for ${JS_URL}:${GENERATED_LINE}`);
newLoc = yield service.originalPositionFor(JS_URL, GENERATED_LINE);
is(newLoc.sourceUrl, ORIGINAL_URL_2, "check post-reload mapped URL");
is(newLoc.line, ORIGINAL_LINE, "check post-reload mapped line number");
yield toolbox.destroy();
gBrowser.removeCurrentTab();
finish();
});

Просмотреть файл

@ -0,0 +1,94 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Original source code for the inline source map test.
// The generated file was made with
// webpack --devtool source-map code_reload_1.js code_bundle_reload_1.js
// perl -pi -e 's/sjs_code_bundle_reload_map.sjs/sjs_code_bundle_reload_map.sjs/' \
// code_bundle_reload_1.js
function f() {
console.log("The first version of the script");
}
f();
/***/ })
/******/ ]);
//# sourceMappingURL=sjs_code_bundle_reload_map.sjs

Просмотреть файл

@ -0,0 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap 59857d9393d4518a63ff","webpack:///./code_reload_1.js"],"names":[],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA,mDAA2C,cAAc;;AAEzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;AChEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA","file":"code_bundle_reload_1.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 59857d9393d4518a63ff","/* Any copyright is dedicated to the Public Domain.\n http://creativecommons.org/publicdomain/zero/1.0/ */\n\n// Original source code for the inline source map test.\n// The generated file was made with\n// webpack --devtool source-map code_reload_1.js code_bundle_reload_1.js\n// perl -pi -e 's/code_bundle_reload_1.js.map/sjs_code_bundle_reload_map.sjs/' \\\n// code_bundle_reload_1.js\n\n\"use strict\";\n\nfunction f() {\n console.log(\"The first version of the script\");\n}\n\nf();\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./code_reload_1.js\n// module id = 0\n// module chunks = 0"],"sourceRoot":""}

Просмотреть файл

@ -0,0 +1,94 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Original source code for the inline source map test.
// The generated file was made with
// webpack --devtool source-map code_reload_2.js code_bundle_reload_2.js
// perl -pi -e 's/sjs_code_bundle_reload_map.sjs/sjs_code_bundle_reload_map.sjs/' \
// code_bundle_reload_2.js
function f() {
console.log("The second version of the script");
}
f();
/***/ })
/******/ ]);
//# sourceMappingURL=sjs_code_bundle_reload_map.sjs

Просмотреть файл

@ -0,0 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap 9497621dfe5d6f67322e","webpack:///./code_reload_2.js"],"names":[],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA,mDAA2C,cAAc;;AAEzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;AChEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA","file":"code_bundle_reload_2.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 9497621dfe5d6f67322e","/* Any copyright is dedicated to the Public Domain.\n http://creativecommons.org/publicdomain/zero/1.0/ */\n\n// Original source code for the inline source map test.\n// The generated file was made with\n// webpack --devtool source-map code_reload_2.js code_bundle_reload_2.js\n// perl -pi -e 's/code_bundle_reload_2.js.map/sjs_code_bundle_reload_map.sjs/' \\\n// code_bundle_reload_2.js\n\n\"use strict\";\n\nfunction f() {\n console.log(\"The second version of the script\");\n}\n\nf();\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./code_reload_2.js\n// module id = 0\n// module chunks = 0"],"sourceRoot":""}

Просмотреть файл

@ -0,0 +1,16 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Original source code for the inline source map test.
// The generated file was made with
// webpack --devtool source-map code_reload_1.js code_bundle_reload_1.js
// perl -pi -e 's/code_bundle_reload_1.js.map/sjs_code_bundle_reload_map.sjs/' \
// code_bundle_reload_1.js
"use strict";
function f() {
console.log("The first version of the script");
}
f();

Просмотреть файл

@ -0,0 +1,16 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Original source code for the inline source map test.
// The generated file was made with
// webpack --devtool source-map code_reload_2.js code_bundle_reload_2.js
// perl -pi -e 's/code_bundle_reload_2.js.map/sjs_code_bundle_reload_map.sjs/' \
// code_bundle_reload_2.js
"use strict";
function f() {
console.log("The second version of the script");
}
f();

Просмотреть файл

@ -0,0 +1,15 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<script src="sjs_code_reload.sjs"></script>
<head>
<meta charset="utf-8"/>
<title>Empty test page 1</title>
</head>
<body>
</body>
</html>

Просмотреть файл

@ -0,0 +1,26 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/* globals getState, setState */
/* exported handleRequest */
"use strict";
function handleRequest(request, response) {
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "0");
response.setHeader("Access-Control-Allow-Origin", "*", false);
// Redirect to a different file each time.
let counter = 1 + +getState("counter");
let index = request.path.lastIndexOf("/");
let newPath = request.path.substr(0, index + 1) +
"code_bundle_reload_" + counter + ".js.map";
let newUrl = request.scheme + "://" + request.host + newPath;
response.setStatusLine(request.httpVersion, 302, "Found");
response.setHeader("Location", newUrl);
setState("counter", "" + counter);
}

Просмотреть файл

@ -0,0 +1,26 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/* globals getState, setState */
/* exported handleRequest */
"use strict";
function handleRequest(request, response) {
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "0");
response.setHeader("Access-Control-Allow-Origin", "*", false);
// Redirect to a different file each time.
let counter = 1 + +getState("counter");
let index = request.path.lastIndexOf("/");
let newPath = request.path.substr(0, index + 1) +
"code_bundle_reload_" + counter + ".js";
let newUrl = request.scheme + "://" + request.host + newPath;
response.setStatusLine(request.httpVersion, 302, "Found");
response.setHeader("Location", newUrl);
setState("counter", "" + counter);
}

Просмотреть файл

@ -164,9 +164,10 @@ using namespace mozilla::dom;
// that the error message actually displays the sizes.
//
// We need different numbers on debug and opt to deal with the owning thread
// pointer that comes with the non-threadsafe refcount on FragmentOrElement.
#if defined(DEBUG) || defined(MOZ_ASAN)
// We need different numbers on certain build types to deal with the owning
// thread pointer that comes with the non-threadsafe refcount on
// FragmentOrElement.
#ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
#define EXTRA_DOM_ELEMENT_BYTES 8
#else
#define EXTRA_DOM_ELEMENT_BYTES 0

Просмотреть файл

@ -338,6 +338,7 @@ nsDOMWindowUtils::UpdateLayerTree()
if (view) {
presShell->Paint(view, view->GetBounds(),
nsIPresShell::PAINT_LAYERS | nsIPresShell::PAINT_SYNC_DECODE_IMAGES);
presShell->GetLayerManager()->WaitOnTransactionProcessed();
}
}
return NS_OK;

Просмотреть файл

@ -61,6 +61,7 @@ support-files = ../file_bug357450.js
[test_bug1063837.xul]
[test_bug1139964.xul]
[test_bug1209621.xul]
[test_bug1346936.html]
[test_cpows.xul]
[test_registerElement_content.xul]
[test_registerElement_ep.xul]

Просмотреть файл

@ -0,0 +1,3 @@
<!DOCTYPE HTML>
<html>
</html>

Просмотреть файл

@ -0,0 +1,4 @@
//# sourceMappingURL=bar.js.map
// Define a single function to prevent script source from being gc'd
function foo() {}

Просмотреть файл

@ -0,0 +1 @@
SourceMap: foo.js.map

Просмотреть файл

@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1346936
-->
<head>
<title>Test for Bug 1346936</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1346936">Mozilla Bug 1346936</a>
<style type="text/css">
#link1 a { -moz-user-select:none; }
</style>
<div id="link1"><a href="http://www.mozilla.org/">link1</a></div>
<div id="link2"><a href="http://www.mozilla.org/">link2</a></div>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 1346936 **/
Components.utils.import("resource://gre/modules/jsdebugger.jsm");
addDebuggerToGlobal(this);
window.onload = function () {
SimpleTest.waitForExplicitFinish();
var iframe = document.createElement("iframe");
iframe.src = "http://mochi.test:8888/tests/dom/base/test/chrome/nochrome_bug1346936.html";
iframe.onload = function () {
var script = iframe.contentWindow.document.createElement("script");
script.src = "http://mochi.test:8888/tests/dom/base/test/chrome/nochrome_bug1346936.js";
script.onload = function () {
var dbg = new Debugger(iframe.contentWindow);
ok(dbg, "Should be able to create debugger");
var scripts = dbg.findScripts({
url: "http://mochi.test:8888/tests/dom/base/test/chrome/nochrome_bug1346936.js"
});
ok(scripts.length > 0, "Should be able to find script");
is(scripts[0].source.sourceMapURL, "foo.js.map");
SimpleTest.finish();
}
iframe.contentWindow.document.body.appendChild(script);
};
document.body.appendChild(iframe);
};
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -31,6 +31,9 @@ TEST_DIRS += [
TEST_HARNESS_FILES.testing.mochitest.tests.dom.base.test.chrome += [
'chrome/bug421622-referer.sjs',
'chrome/bug884693.sjs',
'chrome/nochrome_bug1346936.html',
'chrome/nochrome_bug1346936.js',
'chrome/nochrome_bug1346936.js^headers^',
'chrome/nochrome_bug765993.html',
'chrome/nochrome_bug765993.js',
'chrome/nochrome_bug765993.js^headers^',

Просмотреть файл

@ -41,6 +41,7 @@
#include "mozilla/Preferences.h"
#include "nsTextNode.h"
#include "nsIController.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/TextEvents.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/HTMLInputElement.h"
@ -992,15 +993,22 @@ nsTextInputListener::HandleEvent(nsIDOMEvent* aEvent)
mTxtCtrlElement->IsTextArea() ?
nsIWidget::NativeKeyBindingsForMultiLineEditor :
nsIWidget::NativeKeyBindingsForSingleLineEditor;
nsIWidget* widget = keyEvent->mWidget;
// If the event is created by chrome script, the widget is nullptr.
if (!widget) {
widget = mFrame->GetNearestWidget();
NS_ENSURE_TRUE(widget, NS_OK);
}
if (widget->ExecuteNativeKeyBinding(nativeKeyBindingsType,
*keyEvent, DoCommandCallback, mFrame)) {
// WidgetKeyboardEvent::ExecuteEditCommands() requires non-nullptr mWidget.
// If the event is created by chrome script, it is nullptr but we need to
// execute native key bindings. Therefore, we need to set widget to
// WidgetEvent::mWidget temporarily.
AutoRestore<nsCOMPtr<nsIWidget>> saveWidget(keyEvent->mWidget);
keyEvent->mWidget = widget;
if (keyEvent->ExecuteEditCommands(nativeKeyBindingsType,
DoCommandCallback, mFrame)) {
aEvent->PreventDefault();
}
return NS_OK;

Просмотреть файл

@ -87,19 +87,6 @@ using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/IPCTypes.h";
namespace mozilla {
namespace dom {
struct NativeKeyBinding
{
CommandInt[] singleLineCommands;
CommandInt[] multiLineCommands;
CommandInt[] richTextCommands;
};
union MaybeNativeKeyBinding
{
NativeKeyBinding;
void_t;
};
struct ShowInfo
{
nsString name;
@ -511,8 +498,17 @@ parent:
async ReplyKeyEvent(WidgetKeyboardEvent event);
sync RequestNativeKeyBindings(WidgetKeyboardEvent event)
returns (MaybeNativeKeyBinding bindings);
/**
* Retrieves edit commands for the key combination represented by aEvent.
*
* @param aType One of nsIWidget::NativeKeyBindingsType.
* @param aEvent KeyboardEvent which represents a key combination.
* Note that this must be a trusted event.
* @return Array of edit commands which should be executed in
* editor of native applications.
*/
sync RequestNativeKeyBindings(uint32_t aType, WidgetKeyboardEvent aEvent)
returns (CommandInt[] commands);
async SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
int32_t aNativeKeyCode,
@ -691,7 +687,7 @@ child:
*/
async SynthMouseMoveEvent(WidgetMouseEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
async RealMouseButtonEvent(WidgetMouseEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
async RealKeyEvent(WidgetKeyboardEvent event, MaybeNativeKeyBinding keyBinding);
async RealKeyEvent(WidgetKeyboardEvent event);
async MouseWheelEvent(WidgetWheelEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
async RealTouchEvent(WidgetTouchEvent aEvent,
ScrollableLayerGuid aGuid,

Просмотреть файл

@ -1878,22 +1878,27 @@ TabChild::RecvPluginEvent(const WidgetPluginEvent& aEvent)
}
void
TabChild::RequestNativeKeyBindings(AutoCacheNativeKeyCommands* aAutoCache,
const WidgetKeyboardEvent* aEvent)
TabChild::RequestEditCommands(nsIWidget::NativeKeyBindingsType aType,
const WidgetKeyboardEvent& aEvent,
nsTArray<CommandInt>& aCommands)
{
MaybeNativeKeyBinding maybeBindings;
if (!SendRequestNativeKeyBindings(*aEvent, &maybeBindings)) {
MOZ_ASSERT(aCommands.IsEmpty());
if (NS_WARN_IF(aEvent.IsEditCommandsInitialized(aType))) {
aCommands = aEvent.EditCommandsConstRef(aType);
return;
}
if (maybeBindings.type() == MaybeNativeKeyBinding::TNativeKeyBinding) {
const NativeKeyBinding& bindings = maybeBindings;
aAutoCache->Cache(bindings.singleLineCommands(),
bindings.multiLineCommands(),
bindings.richTextCommands());
} else {
aAutoCache->CacheNoCommands();
switch (aType) {
case nsIWidget::NativeKeyBindingsForSingleLineEditor:
case nsIWidget::NativeKeyBindingsForMultiLineEditor:
case nsIWidget::NativeKeyBindingsForRichTextEditor:
break;
default:
MOZ_ASSERT_UNREACHABLE("Invalid native key bindings type");
}
SendRequestNativeKeyBindings(aType, aEvent, &aCommands);
}
mozilla::ipc::IPCResult
@ -1944,29 +1949,20 @@ TabChild::UpdateRepeatedKeyEventEndTime(const WidgetKeyboardEvent& aEvent)
}
mozilla::ipc::IPCResult
TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& aEvent,
const MaybeNativeKeyBinding& aBindings)
TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& aEvent)
{
if (SkipRepeatedKeyEvent(aEvent)) {
return IPC_OK();
}
AutoCacheNativeKeyCommands autoCache(mPuppetWidget);
MOZ_ASSERT(aEvent.mMessage != eKeyPress ||
aEvent.AreAllEditCommandsInitialized(),
"eKeyPress event should have native key binding information");
if (aEvent.mMessage == eKeyPress) {
// If content code called preventDefault() on a keydown event, then we don't
// want to process any following keypress events.
if (mIgnoreKeyPressEvent) {
return IPC_OK();
}
if (aBindings.type() == MaybeNativeKeyBinding::TNativeKeyBinding) {
const NativeKeyBinding& bindings = aBindings;
autoCache.Cache(bindings.singleLineCommands(),
bindings.multiLineCommands(),
bindings.richTextCommands());
} else {
autoCache.CacheNoCommands();
}
// If content code called preventDefault() on a keydown event, then we don't
// want to process any following keypress events.
if (aEvent.mMessage == eKeyPress && mIgnoreKeyPressEvent) {
return IPC_OK();
}
WidgetKeyboardEvent localEvent(aEvent);

Просмотреть файл

@ -389,8 +389,7 @@ public:
const uint32_t& aDropEffect) override;
virtual mozilla::ipc::IPCResult
RecvRealKeyEvent(const mozilla::WidgetKeyboardEvent& aEvent,
const MaybeNativeKeyBinding& aBindings) override;
RecvRealKeyEvent(const mozilla::WidgetKeyboardEvent& aEvent) override;
virtual mozilla::ipc::IPCResult RecvMouseWheelEvent(const mozilla::WidgetWheelEvent& aEvent,
const ScrollableLayerGuid& aGuid,
@ -512,8 +511,9 @@ public:
void NotifyPainted();
void RequestNativeKeyBindings(mozilla::widget::AutoCacheNativeKeyCommands* aAutoCache,
const WidgetKeyboardEvent* aEvent);
void RequestEditCommands(nsIWidget::NativeKeyBindingsType aType,
const WidgetKeyboardEvent& aEvent,
nsTArray<CommandInt>& aCommands);
/**
* Signal to this TabChild that it should be made visible:

Просмотреть файл

@ -1214,22 +1214,24 @@ TabParent::RecvDispatchKeyboardEvent(const mozilla::WidgetKeyboardEvent& aEvent)
return IPC_OK();
}
static void
DoCommandCallback(mozilla::Command aCommand, void* aData)
{
static_cast<InfallibleTArray<mozilla::CommandInt>*>(aData)->
AppendElement(aCommand);
}
mozilla::ipc::IPCResult
TabParent::RecvRequestNativeKeyBindings(const WidgetKeyboardEvent& aEvent,
MaybeNativeKeyBinding* aBindings)
TabParent::RecvRequestNativeKeyBindings(const uint32_t& aType,
const WidgetKeyboardEvent& aEvent,
nsTArray<CommandInt>* aCommands)
{
AutoTArray<mozilla::CommandInt, 4> singleLine;
AutoTArray<mozilla::CommandInt, 4> multiLine;
AutoTArray<mozilla::CommandInt, 4> richText;
MOZ_ASSERT(aCommands);
MOZ_ASSERT(aCommands->IsEmpty());
*aBindings = mozilla::void_t();
nsIWidget::NativeKeyBindingsType keyBindingsType =
static_cast<nsIWidget::NativeKeyBindingsType>(aType);
switch (keyBindingsType) {
case nsIWidget::NativeKeyBindingsForSingleLineEditor:
case nsIWidget::NativeKeyBindingsForMultiLineEditor:
case nsIWidget::NativeKeyBindingsForRichTextEditor:
break;
default:
return IPC_FAIL(this, "Invalid aType value");
}
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
@ -1237,24 +1239,14 @@ TabParent::RecvRequestNativeKeyBindings(const WidgetKeyboardEvent& aEvent,
}
WidgetKeyboardEvent localEvent(aEvent);
localEvent.mWidget = widget;
if (NS_FAILED(widget->AttachNativeKeyEvent(localEvent))) {
return IPC_OK();
}
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForSingleLineEditor,
localEvent, DoCommandCallback, &singleLine);
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForMultiLineEditor,
localEvent, DoCommandCallback, &multiLine);
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForRichTextEditor,
localEvent, DoCommandCallback, &richText);
if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) {
*aBindings = NativeKeyBinding(singleLine, multiLine, richText);
}
localEvent.InitEditCommandsFor(keyBindingsType);
*aCommands = localEvent.EditCommandsConstRef(keyBindingsType);
return IPC_OK();
}
@ -1444,31 +1436,15 @@ TabParent::SendRealKeyEvent(WidgetKeyboardEvent& aEvent)
}
aEvent.mRefPoint += GetChildProcessOffset();
MaybeNativeKeyBinding bindings;
bindings = void_t();
if (aEvent.mMessage == eKeyPress) {
nsCOMPtr<nsIWidget> widget = GetWidget();
AutoTArray<mozilla::CommandInt, 4> singleLine;
AutoTArray<mozilla::CommandInt, 4> multiLine;
AutoTArray<mozilla::CommandInt, 4> richText;
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForSingleLineEditor,
aEvent, DoCommandCallback, &singleLine);
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForMultiLineEditor,
aEvent, DoCommandCallback, &multiLine);
widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForRichTextEditor,
aEvent, DoCommandCallback, &richText);
if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) {
bindings = NativeKeyBinding(singleLine, multiLine, richText);
}
// XXX Should we do this only when input context indicates an editor having
// focus and the key event won't cause inputting text?
aEvent.InitAllEditCommands();
} else {
aEvent.PreventNativeKeyBindings();
}
return PBrowserParent::SendRealKeyEvent(aEvent, bindings);
return PBrowserParent::SendRealKeyEvent(aEvent);
}
bool

Просмотреть файл

@ -393,8 +393,10 @@ public:
LayoutDeviceToCSSScale GetLayoutDeviceToCSSScale();
virtual mozilla::ipc::IPCResult
RecvRequestNativeKeyBindings(const mozilla::WidgetKeyboardEvent& aEvent,
MaybeNativeKeyBinding* aBindings) override;
RecvRequestNativeKeyBindings(
const uint32_t& aType,
const mozilla::WidgetKeyboardEvent& aEvent,
nsTArray<mozilla::CommandInt>* aCommands) override;
virtual mozilla::ipc::IPCResult
RecvSynthesizeNativeKeyEvent(const int32_t& aNativeKeyboardLayout,

Просмотреть файл

@ -2736,7 +2736,10 @@ ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
}
nsAutoCString sourceMapURL;
rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-SourceMap"), sourceMapURL);
rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("SourceMap"), sourceMapURL);
if (NS_FAILED(rv)) {
rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-SourceMap"), sourceMapURL);
}
if (NS_SUCCEEDED(rv)) {
aRequest->mHasSourceMapURL = true;
aRequest->mSourceMapURL = NS_ConvertUTF8toUTF16(sourceMapURL);

Просмотреть файл

@ -3,47 +3,29 @@ const URL =
"window.focus();" +
"var down = 0; var press = 0;" +
"onkeydown = function(e) {" +
" var startTime = Date.now();" +
" document.body.setAttribute('data-down', ++down);" +
" if (e.keyCode == 'D') while (Date.now() - startTime < 500) {}" +
" if (e.keyCode == KeyboardEvent.DOM_VK_D) while (Date.now() - startTime < 500) {}" +
"};" +
"onkeypress = function(e) {" +
" var startTime = Date.now();" +
" document.body.setAttribute('data-press', ++press);" +
" if (e.charCode == 'P') while (Date.now() - startTime < 500) {}" +
" if (e.charCode == 'p'.charCodeAt(0)) while (Date.now() - startTime < 500) {}" +
"};" +
"</script>";
function createKeyEvent(type, id, repeated) {
var code = id.charCodeAt(0);
return new KeyboardEvent(type, { keyCode: code, charCode: code, bubbles: true, repeat: repeated });
}
add_task(function* () {
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
let browser = tab.linkedBrowser;
// Need to dispatch a DOM Event explicitly via PresShell to get KeyEvent with .repeat = true to
// be handled by EventStateManager, which then forwards the event to the child process.
var utils = EventUtils._getDOMWindowUtils(window);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "D", false), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "D", false), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "D", true), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "D", true), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "D", true), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "D", true), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keyup", "D", true), true);
EventUtils.synthesizeKey("d", { code: "KeyD", repeat: 3 });
yield ContentTask.spawn(browser, null, function* () {
is(content.document.body.getAttribute("data-down"), "2", "Correct number of events");
is(content.document.body.getAttribute("data-press"), "2", "Correct number of events");
});
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "P", false), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "P", false), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "P", true), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "P", true), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "P", true), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "P", true), true);
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keyup", "P", true), true);
EventUtils.synthesizeKey("p", { code: "KeyP", repeat: 3 });
yield ContentTask.spawn(browser, null, function* () {
is(content.document.body.getAttribute("data-down"), "4", "Correct number of events");

Просмотреть файл

@ -627,10 +627,16 @@ EditorEventListener::KeyPress(WidgetKeyboardEvent* aKeyboardEvent)
}
nsCOMPtr<nsIDocument> doc = editorBase->GetDocument();
bool handled = widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForRichTextEditor,
*aKeyboardEvent, DoCommandCallback, doc);
if (handled) {
// WidgetKeyboardEvent::ExecuteEditCommands() requires non-nullptr mWidget.
// If the event is created by chrome script, it is nullptr but we need to
// execute native key bindings. Therefore, we need to set widget to
// WidgetEvent::mWidget temporarily.
AutoRestore<nsCOMPtr<nsIWidget>> saveWidget(aKeyboardEvent->mWidget);
aKeyboardEvent->mWidget = widget;
if (aKeyboardEvent->ExecuteEditCommands(
nsIWidget::NativeKeyBindingsForRichTextEditor,
DoCommandCallback, doc)) {
aKeyboardEvent->PreventDefault();
}
return NS_OK;

Просмотреть файл

@ -204,6 +204,7 @@ DrawTargetCaptureImpl::ContainsOnlyColoredGlyphs(RefPtr<ScaledFont>& aScaledFont
{
uint8_t* start = &mDrawCommandStorage.front();
uint8_t* current = start;
bool result = false;
while (current < start + mDrawCommandStorage.size()) {
DrawingCommand* command =
@ -251,8 +252,9 @@ DrawTargetCaptureImpl::ContainsOnlyColoredGlyphs(RefPtr<ScaledFont>& aScaledFont
aGlyphs.insert(aGlyphs.end(),
fillGlyphs->mGlyphs.begin(),
fillGlyphs->mGlyphs.end());
result = true;
}
return true;
return result;
}
} // namespace gfx

Просмотреть файл

@ -11,6 +11,7 @@
#include "mozilla/RefPtr.h"
#include "mozilla/Assertions.h"
#include "GLConsts.h"
#include "GLContextCGL.h"
using namespace mozilla;
// IOSurface signatures
@ -510,9 +511,13 @@ MacIOSurface::GetReadFormat()
}
CGLError
MacIOSurface::CGLTexImageIOSurface2D(CGLContextObj ctx, size_t plane)
MacIOSurface::CGLTexImageIOSurface2D(mozilla::gl::GLContext* aGL,
CGLContextObj ctx,
size_t plane,
mozilla::gfx::SurfaceFormat* aOutReadFormat)
{
MOZ_ASSERT(plane >= 0);
bool isCompatibilityProfile = aGL->IsCompatibilityProfile();
OSType pixelFormat = GetPixelFormat();
GLenum internalFormat;
@ -522,34 +527,65 @@ MacIOSurface::CGLTexImageIOSurface2D(CGLContextObj ctx, size_t plane)
MOZ_ASSERT(GetPlaneCount() == 2);
MOZ_ASSERT(plane < 2);
// The LOCAL_GL_LUMINANCE and LOCAL_GL_LUMINANCE_ALPHA are the deprecated
// format. So, use LOCAL_GL_RED and LOCAL_GL_RB if we use core profile.
// https://www.khronos.org/opengl/wiki/Image_Format#Legacy_Image_Formats
if (plane == 0) {
internalFormat = format = GL_LUMINANCE;
internalFormat = format = (isCompatibilityProfile) ? (LOCAL_GL_LUMINANCE)
: (LOCAL_GL_RED);
} else {
internalFormat = format = GL_LUMINANCE_ALPHA;
internalFormat = format = (isCompatibilityProfile) ? (LOCAL_GL_LUMINANCE_ALPHA)
: (LOCAL_GL_RG);
}
type = LOCAL_GL_UNSIGNED_BYTE;
if (aOutReadFormat) {
*aOutReadFormat = mozilla::gfx::SurfaceFormat::NV12;
}
type = GL_UNSIGNED_BYTE;
} else if (pixelFormat == '2vuy') {
MOZ_ASSERT(plane == 0);
internalFormat = GL_RGB;
format = LOCAL_GL_YCBCR_422_APPLE;
type = GL_UNSIGNED_SHORT_8_8_APPLE;
// The YCBCR_422_APPLE ext is only available in compatibility profile. So,
// we should use RGB_422_APPLE for core profile. The difference between
// YCBCR_422_APPLE and RGB_422_APPLE is that the YCBCR_422_APPLE converts
// the YCbCr value to RGB with REC 601 conversion. But the RGB_422_APPLE
// doesn't contain color conversion. You should do the color conversion by
// yourself for RGB_422_APPLE.
//
// https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_ycbcr_422.txt
// https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_rgb_422.txt
if (isCompatibilityProfile) {
format = LOCAL_GL_YCBCR_422_APPLE;
if (aOutReadFormat) {
*aOutReadFormat = mozilla::gfx::SurfaceFormat::R8G8B8X8;
}
} else {
format = LOCAL_GL_RGB_422_APPLE;
if (aOutReadFormat) {
*aOutReadFormat = mozilla::gfx::SurfaceFormat::YUV422;
}
}
internalFormat = LOCAL_GL_RGB;
type = LOCAL_GL_UNSIGNED_SHORT_8_8_APPLE;
} else {
MOZ_ASSERT(plane == 0);
internalFormat = HasAlpha() ? GL_RGBA : GL_RGB;
format = GL_BGRA;
type = GL_UNSIGNED_INT_8_8_8_8_REV;
internalFormat = HasAlpha() ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
format = LOCAL_GL_BGRA;
type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
if (aOutReadFormat) {
*aOutReadFormat = HasAlpha() ? mozilla::gfx::SurfaceFormat::R8G8B8A8
: mozilla::gfx::SurfaceFormat::R8G8B8X8;
}
}
CGLError temp = MacIOSurfaceLib::CGLTexImageIOSurface2D(ctx,
GL_TEXTURE_RECTANGLE_ARB,
internalFormat,
GetDevicePixelWidth(plane),
GetDevicePixelHeight(plane),
format,
type,
mIOSurfacePtr, plane);
return temp;
return MacIOSurfaceLib::CGLTexImageIOSurface2D(ctx,
LOCAL_GL_TEXTURE_RECTANGLE_ARB,
internalFormat,
GetDevicePixelWidth(plane),
GetDevicePixelHeight(plane),
format,
type,
mIOSurfacePtr,
plane);
}
static
@ -596,7 +632,6 @@ already_AddRefed<MacIOSurface> MacIOSurface::IOSurfaceContextGetSurface(CGContex
return ioSurface.forget();
}
CGContextType GetContextType(CGContextRef ref)
{
if (!MacIOSurfaceLib::isInit() || !MacIOSurfaceLib::sCGContextGetTypePtr)
@ -611,5 +646,3 @@ CGContextType GetContextType(CGContextRef ref)
return CG_CONTEXT_TYPE_UNKNOWN;
}
}

Просмотреть файл

@ -11,6 +11,12 @@
#include <CoreVideo/CoreVideo.h>
#include <dlfcn.h>
namespace mozilla {
namespace gl {
class GLContext;
}
}
struct _CGLContextObject;
typedef _CGLContextObject* CGLContextObj;
@ -120,7 +126,10 @@ public:
// We would like to forward declare NSOpenGLContext, but it is an @interface
// and this file is also used from c++, so we use a void *.
CGLError CGLTexImageIOSurface2D(CGLContextObj ctxt, size_t plane = 0);
CGLError CGLTexImageIOSurface2D(mozilla::gl::GLContext* aGL,
CGLContextObj ctxt,
size_t plane,
mozilla::gfx::SurfaceFormat* aOutReadFormat = nullptr);
already_AddRefed<SourceSurface> GetAsSurface();
CGContextRef CreateIOSurfaceContext();

Просмотреть файл

@ -212,6 +212,13 @@ ScaledFontBase::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBu
cairoPath->AppendPathToBuilder(builder);
return;
}
if (backendType == BackendType::RECORDING) {
SkPath skPath = GetSkiaPathForGlyphs(aBuffer);
RefPtr<Path> path = MakeAndAddRef<PathSkia>(skPath, FillRule::FILL_WINDING);
path->StreamToSink(aBuilder);
return;
}
MOZ_ASSERT(false, "Path not being copied");
#endif
}

Просмотреть файл

@ -56,6 +56,8 @@ enum class SurfaceFormat : int8_t {
// This one is a single-byte, so endianness isn't an issue.
A8,
R8G8,
// These ones are their own special cases.
YUV,
NV12,

Просмотреть файл

@ -79,4 +79,4 @@ to make sure that mozjs_sys also has its Cargo.lock file updated if needed, henc
the need to run the cargo update command in js/src as well. Hopefully this will
be resolved soon.
Latest Commit: 8516d6c04235e684d9bf9c783ba4fc99dab3bf02
Latest Commit: 102603520d52f335f152ab74b6bcfdae061b6bc8

Просмотреть файл

@ -778,14 +778,18 @@ GLBlitHelper::BlitMacIOSurfaceImage(layers::MacIOSurfaceImage* ioImage)
mGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, textures[0]);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
surf->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(mGL)->GetCGLContext(), 0);
surf->CGLTexImageIOSurface2D(mGL,
gl::GLContextCGL::Cast(mGL)->GetCGLContext(),
0);
mGL->fUniform2f(mYTexScaleLoc, surf->GetWidth(0), surf->GetHeight(0));
mGL->fActiveTexture(LOCAL_GL_TEXTURE1);
mGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, textures[1]);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
surf->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(mGL)->GetCGLContext(), 1);
surf->CGLTexImageIOSurface2D(mGL,
gl::GLContextCGL::Cast(mGL)->GetCGLContext(),
1);
mGL->fUniform2f(mCbCrTexScaleLoc, surf->GetWidth(1), surf->GetHeight(1));
mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);

Просмотреть файл

@ -142,7 +142,7 @@ BackTextureWithIOSurf(GLContext* gl, GLuint tex, MacIOSurface* ioSurf)
CGLContextObj cgl = GLContextCGL::Cast(gl)->GetCGLContext();
MOZ_ASSERT(cgl);
ioSurf->CGLTexImageIOSurface2D(cgl);
ioSurf->CGLTexImageIOSurface2D(gl, cgl, 0);
}
SharedSurface_IOSurface::SharedSurface_IOSurface(const RefPtr<MacIOSurface>& ioSurf,

Просмотреть файл

@ -596,6 +596,11 @@ public:
*/
virtual void FlushRendering() { }
/**
* Make sure that the previous transaction has been
* received. This will synchronsly wait on a remote compositor. */
virtual void WaitOnTransactionProcessed() { }
virtual void SendInvalidRegion(const nsIntRegion& aRegion) {}
/**

Просмотреть файл

@ -28,6 +28,7 @@
#include "mozilla/TouchEvents.h"
#include "mozilla/Preferences.h" // for Preferences
#include "mozilla/EventStateManager.h" // for WheelPrefs
#include "mozilla/webrender/WebRenderAPI.h"
#include "nsDebug.h" // for NS_WARNING
#include "nsPoint.h" // for nsIntPoint
#include "nsThreadUtils.h" // for NS_IsMainThread
@ -364,6 +365,60 @@ APZCTreeManager::UpdateHitTestingTree(uint64_t aRootLayerTreeId,
aOriginatingLayersId, aPaintSequenceNumber);
}
bool
APZCTreeManager::PushStateToWR(wr::WebRenderAPI* aWrApi,
const TimeStamp& aSampleTime)
{
APZThreadUtils::AssertOnCompositorThread();
MOZ_ASSERT(aWrApi);
MutexAutoLock lock(mTreeLock);
bool activeAnimations = false;
uint64_t lastLayersId = -1;
WrPipelineId lastPipelineId;
// We iterate backwards here because the HitTestingTreeNode is optimized
// for backwards iteration. The equivalent code in AsyncCompositionManager
// iterates forwards, but the direction shouldn't really matter in practice
// so we do what's faster. In the future, if we need to start doing the
// equivalent of AlignFixedAndStickyLayers here, then the order will become
// important and we'll need to take that into consideration.
ForEachNode<ReverseIterator>(mRootNode.get(),
[&](HitTestingTreeNode* aNode)
{
if (!aNode->IsPrimaryHolder()) {
return;
}
AsyncPanZoomController* apzc = aNode->GetApzc();
MOZ_ASSERT(apzc);
if (aNode->GetLayersId() != lastLayersId) {
// If we walked into or out of a subtree, we need to get the new
// pipeline id.
lastLayersId = aNode->GetLayersId();
const LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(lastLayersId);
MOZ_ASSERT(state && state->mWrBridge);
lastPipelineId = state->mWrBridge->PipelineId();
}
ParentLayerPoint layerTranslation = apzc->GetCurrentAsyncTransform(
AsyncPanZoomController::RESPECT_FORCE_DISABLE).mTranslation;
// The positive translation means the painted content is supposed to
// move down (or to the right), and that corresponds to a reduction in
// the scroll offset. Since we are effectively giving WR the async
// scroll delta here, we want to negate the translation.
ParentLayerPoint asyncScrollDelta = -layerTranslation;
aWrApi->UpdateScrollPosition(lastPipelineId, apzc->GetGuid().mScrollId,
wr::ToWrPoint(asyncScrollDelta));
apzc->ReportCheckerboard(aSampleTime);
activeAnimations |= apzc->AdvanceAnimations(aSampleTime);
});
return activeAnimations;
}
// Compute the clip region to be used for a layer with an APZC. This function
// is only called for layers which actually have scrollable metrics and an APZC.
template<class ScrollNode> static ParentLayerIntRegion

Просмотреть файл

@ -27,6 +27,10 @@
namespace mozilla {
class MultiTouchInput;
namespace wr {
class WebRenderAPI;
}
namespace layers {
class Layer;
@ -144,6 +148,18 @@ public:
uint64_t aOriginatingLayersId,
uint32_t aPaintSequenceNumber);
/**
* Called when webrender is enabled, from the compositor thread. This function
* walks through the tree of APZC instances and tells webrender about the
* async scroll position. It also advances APZ animations to the specified
* sample time. In effect it is the webrender equivalent of (part of) the
* code in AsyncCompositionManager.
* Returns true if any APZ animations are in progress and we need to keep
* compositing.
*/
bool PushStateToWR(wr::WebRenderAPI* aWrApi,
const TimeStamp& aSampleTime);
/**
* Walk the tree of APZCs and flushes the repaint requests for all the APZCS
* corresponding to the given layers id. Finally, sends a flush complete

Просмотреть файл

@ -656,6 +656,14 @@ ClientLayerManager::FlushRendering()
}
}
void
ClientLayerManager::WaitOnTransactionProcessed()
{
CompositorBridgeChild* remoteRenderer = GetCompositorBridgeChild();
if (remoteRenderer) {
remoteRenderer->SendWaitOnTransactionProcessed();
}
}
void
ClientLayerManager::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier,
uint64_t aDeviceResetSeqNo)

Просмотреть файл

@ -114,6 +114,7 @@ public:
}
virtual void FlushRendering() override;
virtual void WaitOnTransactionProcessed() override;
virtual void SendInvalidRegion(const nsIntRegion& aRegion) override;
virtual uint32_t StartFrameTimeRecording(int32_t aBufferSize) override;

Просмотреть файл

@ -22,6 +22,7 @@
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/GPUVideoTextureHost.h"
#include "mozilla/layers/WebRenderTextureHost.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "nsAString.h"
#include "mozilla/RefPtr.h" // for nsRefPtr
#include "nsPrintfCString.h" // for nsPrintfCString
@ -555,6 +556,33 @@ BufferTextureHost::Unlock()
mLocked = false;
}
void
BufferTextureHost::AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{
MOZ_ASSERT(aImageKeys.length() == 1);
// XXX handling YUV
gfx::SurfaceFormat wrFormat =
(GetFormat() == gfx::SurfaceFormat::YUV) ? gfx::SurfaceFormat::B8G8R8A8
: GetFormat();
gfx::SurfaceFormat format = GetFormat();
uint32_t wrStride = 0;
if (format == gfx::SurfaceFormat::YUV) {
// XXX this stride is used until yuv image rendering by webrender is used.
// Software converted RGB buffers strides are aliened to 16
wrStride = gfx::GetAlignedStride<16>(GetSize().width, BytesPerPixel(gfx::SurfaceFormat::B8G8R8A8));
} else {
wrStride = ImageDataSerializer::ComputeRGBStride(format, GetSize().width);
}
wr::ImageDescriptor descriptor(GetSize(), wrStride, wrFormat);
aAPI->AddExternalImageBuffer(aImageKeys[0],
descriptor,
aExtID);
}
void
TextureHost::DeserializeReadLock(const ReadLockDescriptor& aDesc,
ISurfaceAllocator* aAllocator)

Просмотреть файл

@ -20,6 +20,7 @@
#include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc
#include "mozilla/layers/LayersSurfaces.h"
#include "mozilla/mozalloc.h" // for operator delete
#include "mozilla/Range.h"
#include "mozilla/UniquePtr.h" // for UniquePtr
#include "mozilla/webrender/WebRenderTypes.h"
#include "nsCOMPtr.h" // for already_AddRefed
@ -36,6 +37,10 @@ namespace ipc {
class Shmem;
} // namespace ipc
namespace wr {
class WebRenderAPI;
}
namespace layers {
class BufferDescriptor;
@ -591,6 +596,15 @@ public:
virtual MacIOSurfaceTextureHostOGL* AsMacIOSurfaceTextureHost() { return nullptr; }
virtual WebRenderTextureHost* AsWebRenderTextureHost() { return nullptr; }
// Add all necessary textureHost informations to WebrenderAPI. Then, WR could
// use these informations to compose this textureHost.
virtual void AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{
MOZ_ASSERT_UNREACHABLE("No AddWRImage() implementation for this TextureHost type.");
}
protected:
void ReadUnlock();
@ -678,6 +692,10 @@ public:
const BufferDescriptor& GetBufferDescriptor() const { return mDescriptor; }
virtual void AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) override;
protected:
bool Upload(nsIntRegion *aRegion = nullptr);
bool MaybeUpload(nsIntRegion *aRegion = nullptr);

Просмотреть файл

@ -14,6 +14,7 @@
#include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/webrender/WebRenderAPI.h"
namespace mozilla {
@ -854,6 +855,14 @@ DXGITextureHostD3D11::BindTextureSource(CompositableTextureSourceRef& aTexture)
return !!aTexture;
}
void
DXGITextureHostD3D11::AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{
MOZ_ASSERT_UNREACHABLE("No AddWRImage() implementation for this DXGITextureHostD3D11 type.");
}
DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,
const SurfaceDescriptorDXGIYCbCr& aDescriptor)
: TextureHost(aFlags)
@ -987,6 +996,14 @@ DXGIYCbCrTextureHostD3D11::BindTextureSource(CompositableTextureSourceRef& aText
return !!aTexture;
}
void
DXGIYCbCrTextureHostD3D11::AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{
MOZ_ASSERT_UNREACHABLE("No AddWRImage() implementation for this DXGIYCbCrTextureHostD3D11 type.");
}
bool
DataTextureSourceD3D11::Update(DataSourceSurface* aSurface,
nsIntRegion* aDestRegion,

Просмотреть файл

@ -325,6 +325,10 @@ public:
return nullptr;
}
virtual void AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) override;
protected:
bool LockInternal();
void UnlockInternal();
@ -370,6 +374,10 @@ public:
return nullptr;
}
virtual void AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) override;
protected:
RefPtr<ID3D11Device> GetDevice();

Просмотреть файл

@ -1177,7 +1177,7 @@ CompositorBridgeChild::GetNextExternalImageId()
MOZ_RELEASE_ASSERT(sNextID != UINT32_MAX);
uint64_t imageId = mNamespace;
imageId = imageId << 32 | sNextID;
imageId = (imageId << 32) | sNextID;
return Some(wr::ToExternalImageId(imageId));
}

Просмотреть файл

@ -523,6 +523,12 @@ CompositorBridgeParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
return IPC_OK();
}
mozilla::ipc::IPCResult
CompositorBridgeParent::RecvWaitOnTransactionProcessed()
{
return IPC_OK();
}
mozilla::ipc::IPCResult
CompositorBridgeParent::RecvFlushRendering()
{
@ -1595,7 +1601,8 @@ CompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::PipelineId& aPipel
RefPtr<widget::CompositorWidget> widget = mWidget;
RefPtr<wr::WebRenderAPI> api = wr::WebRenderAPI::Create(
gfxPrefs::WebRenderProfilerEnabled(), this, Move(widget), aSize);
RefPtr<WebRenderCompositableHolder> holder = new WebRenderCompositableHolder();
RefPtr<WebRenderCompositableHolder> holder =
new WebRenderCompositableHolder(WebRenderBridgeParent::AllocIdNameSpace());
MOZ_ASSERT(api); // TODO have a fallback
api->SetRootPipeline(aPipelineId);
mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, nullptr, Move(api), Move(holder));
@ -1631,6 +1638,12 @@ CompositorBridgeParent::DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aA
return true;
}
RefPtr<WebRenderBridgeParent>
CompositorBridgeParent::GetWebRenderBridgeParent() const
{
return mWrBridge;
}
void
CompositorBridgeParent::SetWebRenderProfilerEnabled(bool aEnabled)
{
@ -1834,12 +1847,14 @@ CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart,
void
CompositorBridgeParent::NotifyDidCompositeToPipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd)
{
if (!mWrBridge) {
return;
}
mWrBridge->CompositableHolder()->Update(aPipelineId, aEpoch);
if (mPaused) {
return;
}
MOZ_ASSERT(mWrBridge);
mWrBridge->CompositableHolder()->Update(aPipelineId, aEpoch);
if (mWrBridge->PipelineId() == aPipelineId) {
uint64_t transactionId = mWrBridge->FlushTransactionIdsForEpoch(aEpoch);

Просмотреть файл

@ -199,6 +199,7 @@ public:
const gfx::IntRect& aRect) override;
virtual mozilla::ipc::IPCResult RecvFlushRendering() override;
virtual mozilla::ipc::IPCResult RecvFlushRenderingAsync() override;
virtual mozilla::ipc::IPCResult RecvWaitOnTransactionProcessed() override;
virtual mozilla::ipc::IPCResult RecvForcePresent() override;
virtual mozilla::ipc::IPCResult RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override;
@ -447,11 +448,18 @@ public:
return mOptions;
}
TimeDuration GetVsyncInterval() const {
// the variable is called "rate" but really it's an interval
return mVsyncRate;
}
PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
const LayoutDeviceIntSize& aSize,
TextureFactoryIdentifier* aTextureFactoryIdentifier,
uint32_t* aIdNamespace) override;
bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
RefPtr<WebRenderBridgeParent> GetWebRenderBridgeParent() const;
static void SetWebRenderProfilerEnabled(bool aEnabled);
static CompositorBridgeParent* GetCompositorBridgeParentFromLayersId(const uint64_t& aLayersId);

Просмотреть файл

@ -60,6 +60,7 @@ public:
virtual mozilla::ipc::IPCResult RecvFlushRendering() override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvFlushRenderingAsync() override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvForcePresent() override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvWaitOnTransactionProcessed() override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray<float>* intervals) override { return IPC_OK(); }

Просмотреть файл

@ -194,6 +194,9 @@ parent:
// synchronous repaints on resize.
async FlushRenderingAsync();
// Make sure any pending composites have been received.
sync WaitOnTransactionProcessed();
// Force an additional frame presentation to be executed. This is used to
// work around a windows presentation bug (See Bug 1232042)
async ForcePresent();

Просмотреть файл

@ -21,7 +21,7 @@ using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h";
using mozilla::wr::ImageKey from "mozilla/webrender/WebRenderTypes.h";
using mozilla::wr::FontKey from "mozilla/webrender/WebRenderTypes.h";
using WrBuiltDisplayListDescriptor from "mozilla/webrender/webrender_ffi.h";
using WrAuxiliaryListsDescriptor from "mozilla/webrender/webrender_ffi.h";
using WrSize from "mozilla/webrender/webrender_ffi.h";
using mozilla::layers::WebRenderScrollData from "mozilla/layers/WebRenderScrollData.h";
namespace mozilla {
@ -53,10 +53,10 @@ parent:
async DeleteFont(FontKey aFontKey);
async DPBegin(IntSize aSize);
async DPEnd(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
ByteBuffer aDL, WrBuiltDisplayListDescriptor aDLDesc, ByteBuffer aAux, WrAuxiliaryListsDescriptor aAuxDesc,
WrSize aContentSize, ByteBuffer aDL, WrBuiltDisplayListDescriptor aDLDesc,
WebRenderScrollData aScrollData);
sync DPSyncEnd(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
ByteBuffer aDL, WrBuiltDisplayListDescriptor aDLDesc, ByteBuffer aAux, WrAuxiliaryListsDescriptor aAuxDesc,
WrSize aContentSize, ByteBuffer aDL, WrBuiltDisplayListDescriptor aDLDesc,
WebRenderScrollData aScrollData);
sync DPGetSnapshot(PTexture texture);
async AddExternalImageId(ExternalImageId aImageId, CompositableHandle aHandle);

Просмотреть файл

@ -31,6 +31,11 @@ struct OpAddExternalImage {
ImageKey key;
};
struct OpAddExternalVideoImage {
ExternalImageId externalImageId;
ImageKey[] keys;
};
struct OpAddCompositorAnimations {
CompositorAnimations data;
OptionalTransform transform;
@ -39,6 +44,7 @@ struct OpAddCompositorAnimations {
union WebRenderParentCommand {
OpAddExternalImage;
OpAddExternalVideoImage;
CompositableOperation;
OpAddCompositorAnimations;
};

Просмотреть файл

@ -202,6 +202,7 @@ EXPORTS.mozilla.layers += [
'TextureWrapperImage.h',
'TransactionIdAllocator.h',
'UpdateImageHelper.h',
'wr/ScrollingLayersHelper.h',
'wr/StackingContextHelper.h',
'wr/WebRenderBridgeChild.h',
'wr/WebRenderBridgeParent.h',
@ -397,6 +398,7 @@ UNIFIED_SOURCES += [
'SourceSurfaceVolatileData.cpp',
'TextureSourceProvider.cpp',
'TextureWrapperImage.cpp',
'wr/ScrollingLayersHelper.cpp',
'wr/StackingContextHelper.cpp',
'wr/WebRenderBridgeChild.cpp',
'wr/WebRenderBridgeParent.cpp',

Просмотреть файл

@ -5,6 +5,7 @@
#include "MacIOSurfaceTextureHostOGL.h"
#include "mozilla/gfx/MacIOSurface.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "GLContextCGL.h"
namespace mozilla {
@ -35,7 +36,13 @@ MacIOSurfaceTextureHostOGL::CreateTextureSourceForPlane(size_t aPlane)
gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
mSurface->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(gl)->GetCGLContext(), aPlane);
gfx::SurfaceFormat readFormat = gfx::SurfaceFormat::UNKNOWN;
mSurface->CGLTexImageIOSurface2D(gl,
gl::GLContextCGL::Cast(gl)->GetCGLContext(),
aPlane,
&readFormat);
// With compositorOGL, we doesn't support the yuv interleaving format yet.
MOZ_ASSERT(readFormat != gfx::SurfaceFormat::YUV422);
return new GLTextureSource(mProvider, textureHandle, LOCAL_GL_TEXTURE_RECTANGLE_ARB,
gfx::IntSize(mSurface->GetDevicePixelWidth(aPlane),
@ -107,70 +114,64 @@ MacIOSurfaceTextureHostOGL::gl() const
return mProvider ? mProvider->GetGLContext() : nullptr;
}
MacIOSurfaceTextureSourceOGL::MacIOSurfaceTextureSourceOGL(
CompositorOGL* aCompositor,
MacIOSurface* aSurface)
: mCompositor(aCompositor)
, mSurface(aSurface)
{
MOZ_ASSERT(aCompositor);
MOZ_COUNT_CTOR(MacIOSurfaceTextureSourceOGL);
}
MacIOSurfaceTextureSourceOGL::~MacIOSurfaceTextureSourceOGL()
{
MOZ_COUNT_DTOR(MacIOSurfaceTextureSourceOGL);
}
gfx::IntSize
MacIOSurfaceTextureSourceOGL::GetSize() const
{
return gfx::IntSize(mSurface->GetDevicePixelWidth(),
mSurface->GetDevicePixelHeight());
}
gfx::SurfaceFormat
MacIOSurfaceTextureSourceOGL::GetFormat() const
{
return mSurface->HasAlpha() ? gfx::SurfaceFormat::R8G8B8A8
: gfx::SurfaceFormat::R8G8B8X8;
}
void
MacIOSurfaceTextureSourceOGL::BindTexture(GLenum aTextureUnit,
gfx::SamplingFilter aSamplingFilter)
MacIOSurfaceTextureHostOGL::AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{
gl::GLContext* gl = this->gl();
if (!gl || !gl->MakeCurrent()) {
NS_WARNING("Trying to bind a texture without a working GLContext");
return;
MOZ_ASSERT(mSurface);
switch (GetFormat()) {
case gfx::SurfaceFormat::R8G8B8X8:
case gfx::SurfaceFormat::R8G8B8A8: {
MOZ_ASSERT(aImageKeys.length() == 1);
MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
wr::ImageDescriptor descriptor(GetSize(), GetFormat());
aAPI->AddExternalImage(aImageKeys[0],
descriptor,
aExtID,
WrExternalImageBufferType::TextureRectHandle,
0);
break;
}
case gfx::SurfaceFormat::YUV422: {
// This is the special buffer format. The buffer contents could be a
// converted RGB interleaving data or a YCbCr interleaving data depending
// on the different platform setting. (e.g. It will be RGB at OpenGL 2.1
// and YCbCr at OpenGL 3.1)
MOZ_ASSERT(aImageKeys.length() == 1);
MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
wr::ImageDescriptor descriptor(GetSize(), gfx::SurfaceFormat::R8G8B8X8);
aAPI->AddExternalImage(aImageKeys[0],
descriptor,
aExtID,
WrExternalImageBufferType::TextureRectHandle,
0);
break;
}
case gfx::SurfaceFormat::NV12: {
MOZ_ASSERT(aImageKeys.length() == 2);
MOZ_ASSERT(mSurface->GetPlaneCount() == 2);
wr::ImageDescriptor descriptor0(gfx::IntSize(mSurface->GetDevicePixelWidth(0), mSurface->GetDevicePixelHeight(0)),
gfx::SurfaceFormat::A8);
wr::ImageDescriptor descriptor1(gfx::IntSize(mSurface->GetDevicePixelWidth(1), mSurface->GetDevicePixelHeight(1)),
gfx::SurfaceFormat::R8G8);
aAPI->AddExternalImage(aImageKeys[0],
descriptor0,
aExtID,
WrExternalImageBufferType::TextureRectHandle,
0);
aAPI->AddExternalImage(aImageKeys[1],
descriptor1,
aExtID,
WrExternalImageBufferType::TextureRectHandle,
1);
break;
}
default: {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
}
}
GLuint tex = mCompositor->GetTemporaryTexture(GetTextureTarget(), aTextureUnit);
gl->fActiveTexture(aTextureUnit);
gl->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, tex);
mSurface->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(gl)->GetCGLContext());
ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, LOCAL_GL_TEXTURE_RECTANGLE_ARB);
}
void
MacIOSurfaceTextureSourceOGL::SetTextureSourceProvider(TextureSourceProvider* aProvider)
{
CompositorOGL* ogl = nullptr;
if (Compositor* compositor = aProvider->AsCompositor()) {
ogl = compositor->AsCompositorOGL();
}
mCompositor = ogl;
if (mCompositor && mNextSibling) {
mNextSibling->SetTextureSourceProvider(aProvider);
}
}
gl::GLContext*
MacIOSurfaceTextureSourceOGL::gl() const
{
return mCompositor ? mCompositor->gl() : nullptr;
}
} // namespace layers

Просмотреть файл

@ -14,49 +14,6 @@ class MacIOSurface;
namespace mozilla {
namespace layers {
/**
* A texture source meant for use with MacIOSurfaceTextureHostOGL.
*
* It does not own any GL texture, and attaches its shared handle to one of
* the compositor's temporary textures when binding.
*/
class MacIOSurfaceTextureSourceOGL : public TextureSource
, public TextureSourceOGL
{
public:
MacIOSurfaceTextureSourceOGL(CompositorOGL* aCompositor,
MacIOSurface* aSurface);
virtual ~MacIOSurfaceTextureSourceOGL();
virtual const char* Name() const override { return "MacIOSurfaceTextureSourceOGL"; }
virtual TextureSourceOGL* AsSourceOGL() override { return this; }
virtual void BindTexture(GLenum activetex,
gfx::SamplingFilter aSamplingFilter) override;
virtual bool IsValid() const override { return !!gl(); }
virtual gfx::IntSize GetSize() const override;
virtual gfx::SurfaceFormat GetFormat() const override;
virtual GLenum GetTextureTarget() const override { return LOCAL_GL_TEXTURE_RECTANGLE_ARB; }
virtual GLenum GetWrapMode() const override { return LOCAL_GL_CLAMP_TO_EDGE; }
// MacIOSurfaceTextureSourceOGL doesn't own any gl texture
virtual void DeallocateDeviceData() override {}
virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
gl::GLContext* gl() const;
protected:
RefPtr<CompositorOGL> mCompositor;
RefPtr<MacIOSurface> mSurface;
};
/**
* A TextureHost for shared MacIOSurface
*
@ -105,6 +62,10 @@ public:
return mSurface;
}
virtual void AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) override;
protected:
GLTextureSource* CreateTextureSourceForPlane(size_t aPlane);

Просмотреть файл

@ -0,0 +1,64 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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/. */
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "FrameMetrics.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/WebRenderLayer.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "UnitTransforms.h"
namespace mozilla {
namespace layers {
ScrollingLayersHelper::ScrollingLayersHelper(WebRenderLayer* aLayer,
wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aStackingContext)
: mLayer(aLayer)
, mBuilder(&aBuilder)
{
if (!mLayer->WrManager()->AsyncPanZoomEnabled()) {
// If APZ is disabled then we don't need to push the scrolling clips
return;
}
Layer* layer = mLayer->GetLayer();
for (uint32_t i = layer->GetScrollMetadataCount(); i > 0; i--) {
const FrameMetrics& fm = layer->GetFrameMetrics(i - 1);
if (!fm.IsScrollable()) {
return;
}
LayoutDeviceRect contentRect = fm.GetExpandedScrollableRect()
* fm.GetDevPixelsPerCSSPixel();
// TODO: check coordinate systems are sane here
LayerRect clipBounds = ViewAs<LayerPixel>(
fm.GetCompositionBounds(),
PixelCastJustification::MovingDownToChildren);
mBuilder->PushScrollLayer(fm.GetScrollId(),
aStackingContext.ToRelativeWrRect(contentRect),
aStackingContext.ToRelativeWrRect(clipBounds));
}
}
ScrollingLayersHelper::~ScrollingLayersHelper()
{
if (!mLayer->WrManager()->AsyncPanZoomEnabled()) {
return;
}
Layer* layer = mLayer->GetLayer();
for (int32_t i = layer->GetScrollMetadataCount(); i > 0; i--) {
const FrameMetrics& fm = layer->GetFrameMetrics(i - 1);
if (!fm.IsScrollable()) {
return;
}
mBuilder->PopScrollLayer();
}
}
} // namespace layers
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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_SCROLLINGLAYERSHELPER_H
#define GFX_SCROLLINGLAYERSHELPER_H
#include "mozilla/Attributes.h"
namespace mozilla {
namespace wr {
class DisplayListBuilder;
}
namespace layers {
class StackingContextHelper;
class WebRenderLayer;
class MOZ_RAII ScrollingLayersHelper
{
public:
ScrollingLayersHelper(WebRenderLayer* aLayer,
wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc);
~ScrollingLayersHelper();
private:
WebRenderLayer* mLayer;
wr::DisplayListBuilder* mBuilder;
};
} // namespace layers
} // namespace mozilla
#endif

Просмотреть файл

@ -24,8 +24,6 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
: mBuilder(&aBuilder)
{
WrRect scBounds = aParentSC.ToRelativeWrRect(aLayer->BoundsForStackingContext());
mOffsetToParent.x = scBounds.x;
mOffsetToParent.y = scBounds.y;
Layer* layer = aLayer->GetLayer();
mTransform = aTransform.valueOr(layer->GetTransform());
mBuilder->PushStackingContext(scBounds,
@ -44,8 +42,6 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
: mBuilder(&aBuilder)
{
WrRect scBounds = aParentSC.ToRelativeWrRect(aLayer->BoundsForStackingContext());
mOffsetToParent.x = scBounds.x;
mOffsetToParent.y = scBounds.y;
if (aTransformPtr) {
mTransform = *aTransformPtr;
}
@ -89,10 +85,10 @@ StackingContextHelper::ToRelativeWrRectRounded(const LayoutDeviceRect& aRect) co
}
gfx::Matrix4x4
StackingContextHelper::TransformToParentSC() const
StackingContextHelper::TransformToRoot() const
{
gfx::Matrix4x4 inv = mTransform.Inverse();
inv.PostTranslate(-mOffsetToParent.x, -mOffsetToParent.y, 0);
inv.PostTranslate(-mOrigin.x, -mOrigin.y, 0);
return inv;
}

Просмотреть файл

@ -65,13 +65,12 @@ public:
WrRect ToRelativeWrRectRounded(const LayoutDeviceRect& aRect) const;
// Produce a transform that converts points from the coordinate space of this
// stacking context to the coordinate space of the parent stacking context.
gfx::Matrix4x4 TransformToParentSC() const;
// stacking context to the coordinate space of the root of the layer tree.
gfx::Matrix4x4 TransformToRoot() const;
private:
wr::DisplayListBuilder* mBuilder;
LayerPoint mOrigin;
WrPoint mOffsetToParent;
gfx::Matrix4x4 mTransform;
};

Просмотреть файл

@ -17,6 +17,8 @@
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
WebRenderBridgeChild::WebRenderBridgeChild(const wr::PipelineId& aPipelineId)
: mReadLockSequenceNumber(0)
, mIsInTransaction(false)
@ -100,16 +102,17 @@ WebRenderBridgeChild::DPEnd(wr::DisplayListBuilder &aBuilder,
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(mIsInTransaction);
wr::BuiltDisplayList dl = aBuilder.Finalize();
wr::BuiltDisplayList dl;
WrSize contentSize;
aBuilder.Finalize(contentSize, dl);
ByteBuffer dlData(Move(dl.dl));
ByteBuffer auxData(Move(dl.aux));
if (aIsSync) {
this->SendDPSyncEnd(aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId,
dlData, dl.dl_desc, auxData, dl.aux_desc, aScrollData);
contentSize, dlData, dl.dl_desc, aScrollData);
} else {
this->SendDPEnd(aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId,
dlData, dl.dl_desc, auxData, dl.aux_desc, aScrollData);
contentSize, dlData, dl.dl_desc, aScrollData);
}
mParentCommands.Clear();
@ -188,8 +191,6 @@ WebRenderBridgeChild::PushGlyphs(wr::DisplayListBuilder& aBuilder, const nsTArra
WrFontKey key = GetFontKeyForScaledFont(aFont);
MOZ_ASSERT(key.mNamespace && key.mHandle);
WrClipRegion clipRegion = aBuilder.BuildClipRegion(aSc.ToRelativeWrRect(aClip));
for (size_t i = 0; i < aGlyphs.Length(); i++) {
GlyphArray glyph_array = aGlyphs[i];
nsTArray<gfx::Glyph>& glyphs = glyph_array.glyphs();
@ -202,6 +203,8 @@ WebRenderBridgeChild::PushGlyphs(wr::DisplayListBuilder& aBuilder, const nsTArra
wr_glyph_instances[j].point = aSc.ToRelativeWrPoint(
LayerPoint::FromUnknownPoint(glyphs[j].mPosition));
}
WrClipRegionToken clipRegion = aBuilder.PushClipRegion(aSc.ToRelativeWrRect(aClip));
aBuilder.PushText(aSc.ToRelativeWrRect(aBounds),
clipRegion,
glyph_array.color().value(),
@ -323,6 +326,11 @@ WebRenderBridgeChild::AddOpDestroy(const OpDestroy& aOp)
void
WebRenderBridgeChild::ReleaseCompositable(const CompositableHandle& aHandle)
{
if (!IPCOpen()) {
// This can happen if the IPC connection was torn down, because, e.g.
// the GPU process died.
return;
}
if (!DestroyInTransaction(aHandle)) {
SendReleaseCompositable(aHandle);
}

Просмотреть файл

@ -119,9 +119,10 @@ WebRenderBridgeParent::WebRenderBridgeParent(CompositorBridgeParentBase* aCompos
, mChildLayerObserverEpoch(0)
, mParentLayerObserverEpoch(0)
, mWrEpoch(0)
, mIdNameSpace(++sIdNameSpace)
, mIdNameSpace(AllocIdNameSpace())
, mPaused(false)
, mDestroyed(false)
, mIsSnapshotting(false)
{
MOZ_ASSERT(mCompositableHolder);
mCompositableHolder->AddPipeline(mPipelineId);
@ -157,12 +158,10 @@ WebRenderBridgeParent::RecvCreate(const gfx::IntSize& aSize)
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvShutdown()
{
if (mDestroyed) {
return IPC_OK();
}
Destroy();
IProtocol* mgr = Manager();
if (!Send__delete__(this)) {
return IPC_FAIL_NO_REASON(this);
return IPC_FAIL_NO_REASON(mgr);
}
return IPC_OK();
}
@ -304,10 +303,9 @@ WebRenderBridgeParent::HandleDPEnd(const gfx::IntSize& aSize,
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const WrSize& aContentSize,
const ByteBuffer& dl,
const WrBuiltDisplayListDescriptor& dlDesc,
const ByteBuffer& aux,
const WrAuxiliaryListsDescriptor& auxDesc,
const WebRenderScrollData& aScrollData)
{
UpdateFwdTransactionId(aFwdTransactionId);
@ -325,45 +323,45 @@ WebRenderBridgeParent::HandleDPEnd(const gfx::IntSize& aSize,
++mWrEpoch; // Update webrender epoch
ProcessWebRenderCommands(aSize, aCommands, wr::NewEpoch(mWrEpoch),
dl, dlDesc, aux, auxDesc);
aContentSize, dl, dlDesc);
HoldPendingTransactionId(mWrEpoch, aTransactionId);
mScrollData = aScrollData;
UpdateAPZ();
}
void
WebRenderBridgeParent::UpdateAPZ()
CompositorBridgeParent*
WebRenderBridgeParent::GetRootCompositorBridgeParent() const
{
if (!mCompositorBridge) {
return;
return nullptr;
}
CompositorBridgeParent* cbp;
uint64_t rootLayersId;
WebRenderBridgeParent* rootWrbp;
if (mWidget) {
// This WebRenderBridgeParent is attached to the root
// CompositorBridgeParent.
cbp = static_cast<CompositorBridgeParent*>(mCompositorBridge);
rootLayersId = wr::AsUint64(mPipelineId);
rootWrbp = this;
} else {
// This WebRenderBridgeParent is attached to a
// CrossProcessCompositorBridgeParent so we have an extra level of
// indirection to unravel.
uint64_t layersId = wr::AsUint64(mPipelineId);
CompositorBridgeParent::LayerTreeState* lts =
CompositorBridgeParent::GetIndirectShadowTree(layersId);
MOZ_ASSERT(lts);
cbp = lts->mParent;
rootLayersId = cbp->RootLayerTreeId();
lts = CompositorBridgeParent::GetIndirectShadowTree(rootLayersId);
MOZ_ASSERT(lts);
rootWrbp = lts->mWrBridge.get();
return static_cast<CompositorBridgeParent*>(mCompositorBridge);
}
MOZ_ASSERT(cbp);
// Otherwise, this WebRenderBridgeParent is attached to a
// CrossProcessCompositorBridgeParent so we have an extra level of
// indirection to unravel.
uint64_t layersId = wr::AsUint64(mPipelineId);
CompositorBridgeParent::LayerTreeState* lts =
CompositorBridgeParent::GetIndirectShadowTree(layersId);
MOZ_ASSERT(lts);
return lts->mParent;
}
void
WebRenderBridgeParent::UpdateAPZ()
{
CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
if (!cbp) {
return;
}
uint64_t rootLayersId = cbp->RootLayerTreeId();
RefPtr<WebRenderBridgeParent> rootWrbp = cbp->GetWebRenderBridgeParent();
if (!rootWrbp) {
return;
}
@ -374,6 +372,26 @@ WebRenderBridgeParent::UpdateAPZ()
}
}
bool
WebRenderBridgeParent::PushAPZStateToWR()
{
CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
if (!cbp) {
return false;
}
if (RefPtr<APZCTreeManager> apzc = cbp->GetAPZCTreeManager()) {
TimeStamp animationTime = mCompositorScheduler->GetLastComposeTime();
TimeDuration frameInterval = cbp->GetVsyncInterval();
// As with the non-webrender codepath in AsyncCompositionManager, we want to
// use the timestamp for the next vsync when advancing animations.
if (frameInterval != TimeDuration::Forever()) {
animationTime += frameInterval;
}
return apzc->PushStateToWR(mApi, animationTime);
}
return false;
}
const WebRenderScrollData&
WebRenderBridgeParent::GetScrollData() const
{
@ -387,14 +405,13 @@ WebRenderBridgeParent::RecvDPEnd(const gfx::IntSize& aSize,
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const WrSize& aContentSize,
const ByteBuffer& dl,
const WrBuiltDisplayListDescriptor& dlDesc,
const ByteBuffer& aux,
const WrAuxiliaryListsDescriptor& auxDesc,
const WebRenderScrollData& aScrollData)
{
HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
dl, dlDesc, aux, auxDesc, aScrollData);
aContentSize, dl, dlDesc, aScrollData);
return IPC_OK();
}
@ -404,24 +421,21 @@ WebRenderBridgeParent::RecvDPSyncEnd(const gfx::IntSize &aSize,
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const WrSize& aContentSize,
const ByteBuffer& dl,
const WrBuiltDisplayListDescriptor& dlDesc,
const ByteBuffer& aux,
const WrAuxiliaryListsDescriptor& auxDesc,
const WebRenderScrollData& aScrollData)
{
HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
dl, dlDesc, aux, auxDesc, aScrollData);
aContentSize, dl, dlDesc, aScrollData);
return IPC_OK();
}
void
WebRenderBridgeParent::ProcessWebRenderCommands(const gfx::IntSize &aSize,
InfallibleTArray<WebRenderParentCommand>& aCommands, const wr::Epoch& aEpoch,
const ByteBuffer& dl,
const WrBuiltDisplayListDescriptor& dlDesc,
const ByteBuffer& aux,
const WrAuxiliaryListsDescriptor& auxDesc)
const WrSize& aContentSize, const ByteBuffer& dl,
const WrBuiltDisplayListDescriptor& dlDesc)
{
mCompositableHolder->SetCompositionTime(TimeStamp::Now());
@ -430,10 +444,10 @@ WebRenderBridgeParent::ProcessWebRenderCommands(const gfx::IntSize &aSize,
switch (cmd.type()) {
case WebRenderParentCommand::TOpAddExternalImage: {
const OpAddExternalImage& op = cmd.get_OpAddExternalImage();
wr::ImageKey key = op.key();
Range<const wr::ImageKey> keys(&op.key(), 1);
MOZ_ASSERT(mExternalImageIds.Get(wr::AsUint64(op.externalImageId())).get());
MOZ_ASSERT(!mActiveKeys.Get(wr::AsUint64(key), nullptr));
mActiveKeys.Put(wr::AsUint64(key), key);
MOZ_ASSERT(!mActiveKeys.Get(wr::AsUint64(keys[0]), nullptr));
mActiveKeys.Put(wr::AsUint64(keys[0]), keys[0]);
RefPtr<WebRenderImageHost> host = mExternalImageIds.Get(wr::AsUint64(op.externalImageId()));
if (!host) {
@ -448,25 +462,7 @@ WebRenderBridgeParent::ProcessWebRenderCommands(const gfx::IntSize &aSize,
}
WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost();
if (wrTexture) {
if (wrTexture->IsWrappingNativeHandle()) {
// XXX only for MacIOSurface right now.
// XXX remove the redundant codes for both native handle and yuv case.
wr::ImageDescriptor descriptor(wrTexture->GetSize(), wrTexture->GetReadFormat());
mApi->AddExternalImageHandle(key,
descriptor,
wrTexture->GetExternalImageKey());
mCompositableHolder->HoldExternalImage(mPipelineId, aEpoch, texture->AsWebRenderTextureHost());
} else {
// XXX handling YUV
gfx::SurfaceFormat format =
wrTexture->GetFormat() == SurfaceFormat::YUV ? SurfaceFormat::B8G8R8A8 : wrTexture->GetFormat();
wr::ImageDescriptor descriptor(wrTexture->GetSize(), wrTexture->GetRGBStride(), format);
mApi->AddExternalImageBuffer(key,
descriptor,
wrTexture->GetExternalImageKey());
mCompositableHolder->HoldExternalImage(mPipelineId, aEpoch, texture->AsWebRenderTextureHost());
}
wrTexture->AddWRImage(mApi, keys, wrTexture->GetExternalImageKey());
break;
}
RefPtr<DataSourceSurface> dSurf = host->GetAsSurface();
@ -482,7 +478,52 @@ WebRenderBridgeParent::ProcessWebRenderCommands(const gfx::IntSize &aSize,
IntSize size = dSurf->GetSize();
wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
mApi->AddImage(key, descriptor, slice);
mApi->AddImage(keys[0], descriptor, slice);
dSurf->Unmap();
break;
}
case WebRenderParentCommand::TOpAddExternalVideoImage: {
const OpAddExternalVideoImage& op = cmd.get_OpAddExternalVideoImage();
MOZ_ASSERT(mExternalImageIds.Get(wr::AsUint64(op.externalImageId())).get());
MOZ_ASSERT(op.keys().Length() > 0);
Range<const wr::ImageKey> keys(&(op.keys())[0], op.keys().Length());
for (auto key : keys) {
MOZ_ASSERT(!mActiveKeys.Get(wr::AsUint64(key), nullptr));
mActiveKeys.Put(wr::AsUint64(key), key);
}
RefPtr<WebRenderImageHost> host = mExternalImageIds.Get(wr::AsUint64(op.externalImageId()));
if (!host) {
NS_ERROR("CompositableHost does not exist");
break;
}
// XXX select Texture for video in CompositeToTarget().
TextureHost* texture = host->GetAsTextureHostForComposite();
if (!texture) {
NS_ERROR("TextureHost does not exist");
break;
}
WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost();
if (wrTexture) {
wrTexture->AddWRImage(mApi, keys, wrTexture->GetExternalImageKey());
break;
}
MOZ_ASSERT(keys.length() == 1);
RefPtr<DataSourceSurface> dSurf = host->GetAsSurface();
if (!dSurf) {
break;
}
DataSourceSurface::MappedSurface map;
if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
break;
}
IntSize size = dSurf->GetSize();
wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
mApi->AddImage(keys[0], descriptor, slice);
dSurf->Unmap();
break;
@ -526,9 +567,8 @@ WebRenderBridgeParent::ProcessWebRenderCommands(const gfx::IntSize &aSize,
mApi->SetWindowParameters(size);
}
mApi->SetRootDisplayList(gfx::Color(0.3f, 0.f, 0.f, 1.f), aEpoch, LayerSize(aSize.width, aSize.height),
mPipelineId,
dlDesc, dl.mData, dl.mLength,
auxDesc, aux.mData, aux.mLength);
mPipelineId, aContentSize,
dlDesc, dl.mData, dl.mLength);
ScheduleComposition();
DeleteOldImages();
@ -577,6 +617,8 @@ WebRenderBridgeParent::RecvDPGetSnapshot(PTextureParent* aTexture)
// Assert the stride of the buffer is what webrender expects
MOZ_ASSERT((uint32_t)(size.width * 4) == stride);
mIsSnapshotting = true;
if (mCompositorScheduler->NeedsComposite()) {
mCompositorScheduler->CancelCurrentCompositeTask();
mCompositorScheduler->ForceComposeToTarget(nullptr, nullptr);
@ -584,6 +626,8 @@ WebRenderBridgeParent::RecvDPGetSnapshot(PTextureParent* aTexture)
mApi->Readback(size, buffer, buffer_size);
mIsSnapshotting = false;
return IPC_OK();
}
@ -613,7 +657,7 @@ WebRenderBridgeParent::RecvAddExternalImageId(const ExternalImageId& aImageId,
return IPC_OK();
}
wrHost->SetWrCompositableHolder(mCompositableHolder);
wrHost->SetWrBridge(this);
mExternalImageIds.Put(wr::AsUint64(aImageId), wrHost);
return IPC_OK();
@ -636,7 +680,7 @@ WebRenderBridgeParent::RecvAddExternalImageIdForCompositable(const ExternalImage
return IPC_OK();
}
wrHost->SetWrCompositableHolder(mCompositableHolder);
wrHost->SetWrBridge(this);
mExternalImageIds.Put(wr::AsUint64(aImageId), wrHost);
return IPC_OK();
@ -651,7 +695,7 @@ WebRenderBridgeParent::RecvRemoveExternalImageId(const ExternalImageId& aImageId
MOZ_ASSERT(mExternalImageIds.Get(wr::AsUint64(aImageId)).get());
WebRenderImageHost* wrHost = mExternalImageIds.Get(wr::AsUint64(aImageId)).get();
if (wrHost) {
wrHost->SetWrCompositableHolder(nullptr);
wrHost->ClearWrBridge();
}
mExternalImageIds.Remove(wr::AsUint64(aImageId));
@ -723,6 +767,19 @@ WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::In
return;
}
const uint32_t maxPendingFrameCount = 2;
if (!mIsSnapshotting &&
wr::RenderThread::Get()->GetPendingFrameCount(mApi->GetId()) > maxPendingFrameCount) {
// Render thread is busy, try next time.
ScheduleComposition();
return;
}
if (PushAPZStateToWR()) {
ScheduleComposition();
}
if (gfxPrefs::WebRenderOMTAEnabled()) {
nsTArray<WrOpacityProperty> opacityArray;
nsTArray<WrTransformProperty> transformArray;
@ -847,26 +904,26 @@ WebRenderBridgeParent::Resume()
void
WebRenderBridgeParent::ClearResources()
{
if (mApi) {
++mWrEpoch; // Update webrender epoch
mApi->ClearRootDisplayList(wr::NewEpoch(mWrEpoch), mPipelineId);
for (auto iter = mActiveKeys.Iter(); !iter.Done(); iter.Next()) {
mKeysToDelete.push_back(iter.Data());
iter.Remove();
}
if (!mKeysToDelete.empty()) {
// XXX Sync wait.
mApi->WaitFlushed();
DeleteOldImages();
}
if (!mApi) {
return;
}
mCompositableHolder->RemovePipeline(mPipelineId);
++mWrEpoch; // Update webrender epoch
mApi->ClearRootDisplayList(wr::NewEpoch(mWrEpoch), mPipelineId);
// Schedule composition to clean up Pipeline
mCompositorScheduler->ScheduleComposition();
for (auto iter = mActiveKeys.Iter(); !iter.Done(); iter.Next()) {
mKeysToDelete.push_back(iter.Data());
iter.Remove();
}
DeleteOldImages();
for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
iter.Data()->SetWrCompositableHolder(nullptr);
iter.Data()->ClearWrBridge();
}
mExternalImageIds.Clear();
mCompositableHolder->RemovePipeline(mPipelineId, wr::NewEpoch(mWrEpoch));
if (mWidget && mCompositorScheduler) {
if (mWidget) {
mCompositorScheduler->Destroy();
}
mCompositorScheduler = nullptr;

Просмотреть файл

@ -53,6 +53,7 @@ public:
wr::PipelineId PipelineId() { return mPipelineId; }
wr::WebRenderAPI* GetWebRenderAPI() { return mApi; }
wr::Epoch WrEpoch() { return wr::NewEpoch(mWrEpoch); }
WebRenderCompositableHolder* CompositableHolder() { return mCompositableHolder; }
CompositorVsyncScheduler* CompositorScheduler() { return mCompositorScheduler.get(); }
@ -90,20 +91,18 @@ public:
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const WrSize& aContentSize,
const ByteBuffer& dl,
const WrBuiltDisplayListDescriptor& dlDesc,
const ByteBuffer& aux,
const WrAuxiliaryListsDescriptor& auxDesc,
const WebRenderScrollData& aScrollData) override;
mozilla::ipc::IPCResult RecvDPSyncEnd(const gfx::IntSize& aSize,
InfallibleTArray<WebRenderParentCommand>&& aCommands,
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const WrSize& aContentSize,
const ByteBuffer& dl,
const WrBuiltDisplayListDescriptor& dlDesc,
const ByteBuffer& aux,
const WrAuxiliaryListsDescriptor& auxDesc,
const WebRenderScrollData& aScrollData) override;
mozilla::ipc::IPCResult RecvDPGetSnapshot(PTextureParent* aTexture) override;
@ -165,15 +164,20 @@ public:
void UpdateAPZ();
const WebRenderScrollData& GetScrollData() const;
static uint32_t AllocIdNameSpace() {
return ++sIdNameSpace;
}
private:
virtual ~WebRenderBridgeParent();
void DeleteOldImages();
void ProcessWebRenderCommands(const gfx::IntSize &aSize, InfallibleTArray<WebRenderParentCommand>& commands, const wr::Epoch& aEpoch,
const ByteBuffer& dl,
const WrBuiltDisplayListDescriptor& dlDesc,
const ByteBuffer& aux,
const WrAuxiliaryListsDescriptor& auxDesc);
void ProcessWebRenderCommands(const gfx::IntSize &aSize,
InfallibleTArray<WebRenderParentCommand>& commands,
const wr::Epoch& aEpoch,
const WrSize& aContentSize,
const ByteBuffer& dl,
const WrBuiltDisplayListDescriptor& dlDesc);
void ScheduleComposition();
void ClearResources();
uint64_t GetChildLayerObserverEpoch() const { return mChildLayerObserverEpoch; }
@ -183,15 +187,20 @@ private:
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const WrSize& aContentSize,
const ByteBuffer& dl,
const WrBuiltDisplayListDescriptor& dlDesc,
const ByteBuffer& aux,
const WrAuxiliaryListsDescriptor& auxDesc,
const WebRenderScrollData& aScrollData);
void SampleAnimations(nsTArray<WrOpacityProperty>& aOpacityArray,
nsTArray<WrTransformProperty>& aTransformArray);
CompositorBridgeParent* GetRootCompositorBridgeParent() const;
// Have APZ push the async scroll state to WR. Returns true if an APZ
// animation is in effect and we need to schedule another composition.
bool PushAPZStateToWR();
private:
struct PendingTransactionId {
PendingTransactionId(wr::Epoch aEpoch, uint64_t aId)
@ -227,6 +236,7 @@ private:
bool mPaused;
bool mDestroyed;
bool mIsSnapshotting;
// Can only be accessed on the compositor thread.
WebRenderScrollData mScrollData;

Просмотреть файл

@ -12,6 +12,7 @@
#include "GLScreenBuffer.h"
#include "LayersLogging.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
@ -62,6 +63,7 @@ WebRenderCanvasLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
transform = Some(GetTransform().PreTranslate(0, mBounds.height, 0).PreScale(1, -1, 1));
}
ScrollingLayersHelper scroller(this, aBuilder, aSc);
StackingContextHelper sc(aSc, aBuilder, this, transform);
LayerRect rect(0, 0, mBounds.width, mBounds.height);
@ -69,7 +71,7 @@ WebRenderCanvasLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
LayerRect clipRect = ClipRect().valueOr(rect);
Maybe<WrImageMask> mask = BuildWrMaskLayer(&sc);
WrClipRegion clip = aBuilder.BuildClipRegion(
WrClipRegionToken clip = aBuilder.PushClipRegion(
sc.ToRelativeWrRect(clipRect),
mask.ptrOr(nullptr));

Просмотреть файл

@ -9,6 +9,7 @@
#include "LayersLogging.h"
#include "mozilla/webrender/webrender_ffi.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
@ -21,6 +22,7 @@ void
WebRenderColorLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc)
{
ScrollingLayersHelper scroller(this, aBuilder, aSc);
StackingContextHelper sc(aSc, aBuilder, this);
LayerRect rect = Bounds();
@ -28,7 +30,7 @@ WebRenderColorLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
LayerRect clipRect = ClipRect().valueOr(rect);
Maybe<WrImageMask> mask = BuildWrMaskLayer(&sc);
WrClipRegion clip = aBuilder.BuildClipRegion(
WrClipRegionToken clip = aBuilder.PushClipRegion(
sc.ToRelativeWrRect(clipRect),
mask.ptrOr(nullptr));

Просмотреть файл

@ -8,6 +8,7 @@
#include "CompositableHost.h"
#include "mozilla/layers/WebRenderImageHost.h"
#include "mozilla/layers/WebRenderTextureHost.h"
#include "mozilla/webrender/WebRenderAPI.h"
namespace mozilla {
@ -15,7 +16,9 @@ using namespace gfx;
namespace layers {
WebRenderCompositableHolder::WebRenderCompositableHolder()
WebRenderCompositableHolder::WebRenderCompositableHolder(uint32_t aIdNamespace)
: mIdNamespace(aIdNamespace)
, mResourceId(0)
{
MOZ_COUNT_CTOR(WebRenderCompositableHolder);
}
@ -23,7 +26,6 @@ WebRenderCompositableHolder::WebRenderCompositableHolder()
WebRenderCompositableHolder::~WebRenderCompositableHolder()
{
MOZ_COUNT_DTOR(WebRenderCompositableHolder);
MOZ_ASSERT(mPipelineTexturesHolders.IsEmpty());
}
void
@ -37,18 +39,22 @@ WebRenderCompositableHolder::AddPipeline(const wr::PipelineId& aPipelineId)
}
void
WebRenderCompositableHolder::RemovePipeline(const wr::PipelineId& aPipelineId)
WebRenderCompositableHolder::RemovePipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch)
{
uint64_t id = wr::AsUint64(aPipelineId);
if (mPipelineTexturesHolders.Get(id)) {
mPipelineTexturesHolders.Remove(id);
PipelineTexturesHolder* holder = mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
MOZ_ASSERT(holder);
if (!holder) {
return;
}
MOZ_ASSERT(holder->mDestroyedEpoch.isNothing());
holder->mDestroyedEpoch = Some(aEpoch);
}
void
WebRenderCompositableHolder::HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture)
{
MOZ_ASSERT(aTexture);
PipelineTexturesHolder* holder = mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
MOZ_ASSERT(holder);
if (!holder) {
@ -62,10 +68,17 @@ void
WebRenderCompositableHolder::Update(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch)
{
PipelineTexturesHolder* holder = mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
if (!holder || holder->mTextureHosts.empty()) {
if (!holder) {
return;
}
// Remove Pipeline
if (holder->mDestroyedEpoch.isSome() && holder->mDestroyedEpoch.ref() <= aEpoch) {
mPipelineTexturesHolders.Remove(wr::AsUint64(aPipelineId));
return;
}
// Release TextureHosts based on Epoch
while (!holder->mTextureHosts.empty()) {
if (aEpoch <= holder->mTextureHosts.front().mEpoch) {
break;

Просмотреть файл

@ -9,6 +9,7 @@
#include <queue>
#include "mozilla/layers/TextureHost.h"
#include "mozilla/Maybe.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "nsClassHashtable.h"
@ -28,14 +29,14 @@ class WebRenderCompositableHolder final
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderCompositableHolder)
explicit WebRenderCompositableHolder();
explicit WebRenderCompositableHolder(uint32_t aIdNamespace);
protected:
~WebRenderCompositableHolder();
public:
void AddPipeline(const wr::PipelineId& aPipelineId);
void RemovePipeline(const wr::PipelineId& aPipelineId);
void RemovePipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch);
void HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture);
void Update(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch);
@ -59,6 +60,16 @@ public:
return mCompositeUntilTime;
}
uint32_t GetNextResourceId() { return ++mResourceId; }
uint32_t GetNamespace() { return mIdNamespace; }
wr::ImageKey GetImageKey()
{
wr::ImageKey key;
key.mNamespace = GetNamespace();
key.mHandle = GetNextResourceId();
return key;
}
private:
struct ForwardingTextureHost {
@ -73,8 +84,11 @@ private:
struct PipelineTexturesHolder {
// Holds forwarding WebRenderTextureHosts.
std::queue<ForwardingTextureHost> mTextureHosts;
Maybe<wr::Epoch> mDestroyedEpoch;
};
uint32_t mIdNamespace;
uint32_t mResourceId;
nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder> mPipelineTexturesHolders;
// Render time for the current composition.

Просмотреть файл

@ -8,6 +8,7 @@
#include <inttypes.h>
#include "gfxPrefs.h"
#include "LayersLogging.h"
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/webrender/WebRenderTypes.h"
@ -89,6 +90,7 @@ WebRenderContainerLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
WrBridge()->AddWebRenderParentCommand(anim);
}
ScrollingLayersHelper scroller(this, aBuilder, aSc);
StackingContextHelper sc(aSc, aBuilder, this, animationsId, opacityForSC, transformForSC);
LayerRect rect = Bounds();
@ -110,6 +112,8 @@ void
WebRenderRefLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc)
{
ScrollingLayersHelper scroller(this, aBuilder, aSc);
ParentLayerRect bounds = GetLocalTransformTyped().TransformBounds(Bounds());
// As with WebRenderTextLayer, because we don't push a stacking context for
// this layer, WR doesn't know about the transform on this layer. Therefore
@ -121,7 +125,7 @@ WebRenderRefLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
PixelCastJustification::MovingDownToChildren);
DumpLayerInfo("RefLayer", rect);
WrClipRegion clipRegion = aBuilder.BuildClipRegion(aSc.ToRelativeWrRect(rect));
WrClipRegionToken clipRegion = aBuilder.PushClipRegion(aSc.ToRelativeWrRect(rect));
aBuilder.PushIFrame(aSc.ToRelativeWrRect(rect), clipRegion, wr::AsPipelineId(mId));
}

Просмотреть файл

@ -8,6 +8,7 @@
#include "LayersLogging.h"
#include "mozilla/webrender/webrender_ffi.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "nsDisplayList.h"
@ -37,35 +38,41 @@ WebRenderDisplayItemLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
return;
}
ScrollingLayersHelper scroller(this, aBuilder, aSc);
Maybe<WrImageMask> mask = BuildWrMaskLayer(nullptr);
WrImageMask* imageMask = mask.ptrOr(nullptr);
if (imageMask) {
ParentLayerRect clip = GetLocalTransformTyped().TransformBounds(Bounds());
// As with WebRenderTextLayer, I'm not 100% sure this is correct, but I
// think it is. Because we don't push a stacking context for this layer,
// WR doesn't know about the transform on this layer. The display items
// that we push as part of this layer already take the transform into
// account. When we set the clip rect we also need to explicitly apply
// the transform to make sure it gets taken into account.
// In a sense this is the opposite of what WebRenderLayer::ClipRect() does,
// because there we remove the transform from the clip rect to bring it
// into the coordinate space of the local stacking context, but here we
// need to apply the transform to the bounds to take it into the coordinate
// space of the enclosing stacking context.
// The conversion from ParentLayerPixel to LayerPixel below is a result of
// changing the reference layer from "this layer" to the "the layer that
// created aSc".
LayerRect clipInParentLayerSpace = ViewAs<LayerPixel>(clip,
PixelCastJustification::MovingDownToChildren);
aBuilder.PushClip(aSc.ToRelativeWrRect(clipInParentLayerSpace), imageMask);
ParentLayerRect clip = GetLocalTransformTyped().TransformBounds(Bounds());
if (GetClipRect()) {
clip = ParentLayerRect(GetClipRect().ref());
}
// As with WebRenderTextLayer, I'm not 100% sure this is correct, but I
// think it is. Because we don't push a stacking context for this layer,
// WR doesn't know about the transform on this layer. The display items
// that we push as part of this layer already take the transform into
// account. When we set the clip rect we also need to explicitly apply
// the transform to make sure it gets taken into account.
// In a sense this is the opposite of what WebRenderLayer::ClipRect() does,
// because there we remove the transform from the clip rect to bring it
// into the coordinate space of the local stacking context, but here we
// need to apply the transform to the bounds to take it into the coordinate
// space of the enclosing stacking context.
// The conversion from ParentLayerPixel to LayerPixel below is a result of
// changing the reference layer from "this layer" to the "the layer that
// created aSc".
LayerRect clipInParentLayerSpace = ViewAs<LayerPixel>(clip,
PixelCastJustification::MovingDownToChildren);
aBuilder.PushClip(aSc.ToRelativeWrRect(clipInParentLayerSpace), imageMask);
if (mItem) {
wr::DisplayListBuilder builder(WrBridge()->GetPipeline());
WrSize contentSize; // this won't actually be used by anything
wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
// We might have recycled this layer. Throw away the old commands.
mParentCommands.Clear();
mItem->CreateWebRenderCommands(builder, aSc, mParentCommands, this);
mBuiltDisplayList = builder.Finalize();
builder.Finalize(contentSize, mBuiltDisplayList);
} else {
// else we have an empty transaction and just use the
// old commands.
@ -83,9 +90,7 @@ WebRenderDisplayItemLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
aBuilder.PushBuiltDisplayList(Move(mBuiltDisplayList));
WrBridge()->AddWebRenderParentCommands(mParentCommands);
if (imageMask) {
aBuilder.PopClip();
}
aBuilder.PopClip();
}
Maybe<wr::ImageKey>
@ -166,7 +171,7 @@ WebRenderDisplayItemLayer::PushItemAsBlobImage(wr::DisplayListBuilder& aBuilder,
MOZ_ASSERT(ok);
WrRect dest = aSc.ToRelativeWrRect(imageRect + offset);
WrClipRegion clipRegion = aBuilder.BuildClipRegion(dest);
WrClipRegionToken clipRegion = aBuilder.PushClipRegion(dest);
WrImageKey key = GetImageKey();
WrBridge()->SendAddBlobImage(key, imageSize.ToUnknownSize(), imageSize.width * 4, dt->GetFormat(), bytes);
WrManager()->AddImageKeyForDiscard(key);

Просмотреть файл

@ -9,6 +9,7 @@
#include "mozilla/layers/Compositor.h" // for Compositor
#include "mozilla/layers/Effects.h" // for TexturedEffect, Effect, etc
#include "mozilla/layers/LayerManagerComposite.h" // for TexturedEffect, Effect, etc
#include "mozilla/layers/WebRenderBridgeParent.h"
#include "mozilla/layers/WebRenderCompositableHolder.h"
#include "nsAString.h"
#include "nsDebug.h" // for NS_WARNING, NS_ASSERTION
@ -26,12 +27,13 @@ class ISurfaceAllocator;
WebRenderImageHost::WebRenderImageHost(const TextureInfo& aTextureInfo)
: CompositableHost(aTextureInfo)
, ImageComposite()
, mWrCompositableHolder(nullptr)
, mWrBridge(nullptr)
, mWrBridgeBindings(0)
{}
WebRenderImageHost::~WebRenderImageHost()
{
MOZ_ASSERT(!mWrCompositableHolder);
MOZ_ASSERT(!mWrBridge);
}
void
@ -70,12 +72,13 @@ WebRenderImageHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
// slightly different timestamps in order to sync with the audio clock. This
// means that any CompositeUntil() call we made in Composite() may no longer
// guarantee that we'll composite until the next frame is ready. Fix that here.
if (mWrCompositableHolder && mLastFrameID >= 0) {
if (mWrBridge && mLastFrameID >= 0) {
MOZ_ASSERT(mWrBridge->CompositableHolder());
for (size_t i = 0; i < mImages.Length(); ++i) {
bool frameComesAfter = mImages[i].mFrameID > mLastFrameID ||
mImages[i].mProducerID != mLastProducerID;
if (frameComesAfter && !mImages[i].mTimeStamp.IsNull()) {
mWrCompositableHolder->CompositeUntil(mImages[i].mTimeStamp +
mWrBridge->CompositableHolder()->CompositeUntil(mImages[i].mTimeStamp +
TimeDuration::FromMilliseconds(BIAS_TIME_MS));
break;
}
@ -96,6 +99,7 @@ WebRenderImageHost::CleanupResources()
nsTArray<TimedImage> newImages;
mImages.SwapElements(newImages);
newImages.Clear();
SetCurrentTextureHost(nullptr);
}
void
@ -115,8 +119,9 @@ TimeStamp
WebRenderImageHost::GetCompositionTime() const
{
TimeStamp time;
if (mWrCompositableHolder) {
time = mWrCompositableHolder->GetCompositionTime();
if (mWrBridge) {
MOZ_ASSERT(mWrBridge->CompositableHolder());
time = mWrBridge->CompositableHolder()->GetCompositionTime();
}
return time;
}
@ -136,11 +141,13 @@ WebRenderImageHost::GetAsTextureHostForComposite()
{
int imageIndex = ChooseImageIndex();
if (imageIndex < 0) {
SetCurrentTextureHost(nullptr);
return nullptr;
}
if (mWrCompositableHolder && uint32_t(imageIndex) + 1 < mImages.Length()) {
mWrCompositableHolder->CompositeUntil(mImages[imageIndex + 1].mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS));
if (mWrBridge && uint32_t(imageIndex) + 1 < mImages.Length()) {
MOZ_ASSERT(mWrBridge->CompositableHolder());
mWrBridge->CompositableHolder()->CompositeUntil(mImages[imageIndex + 1].mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS));
}
TimedImage* img = &mImages[imageIndex];
@ -149,7 +156,31 @@ WebRenderImageHost::GetAsTextureHostForComposite()
mLastFrameID = img->mFrameID;
mLastProducerID = img->mProducerID;
}
return img->mTextureHost;
SetCurrentTextureHost(img->mTextureHost);
return mCurrentTextureHost;
}
void
WebRenderImageHost::SetCurrentTextureHost(TextureHost* aTexture)
{
if (aTexture == mCurrentTextureHost.get()) {
return;
}
if (mWrBridge &&
!!mCurrentTextureHost &&
mCurrentTextureHost != aTexture &&
mCurrentTextureHost->AsWebRenderTextureHost()) {
MOZ_ASSERT(mWrBridge->CompositableHolder());
wr::PipelineId piplineId = mWrBridge->PipelineId();
wr::Epoch epoch = mWrBridge->WrEpoch();
mWrBridge->CompositableHolder()->HoldExternalImage(
piplineId,
epoch,
mCurrentTextureHost->AsWebRenderTextureHost());
}
mCurrentTextureHost = aTexture;
}
void WebRenderImageHost::Attach(Layer* aLayer,
@ -246,5 +277,29 @@ WebRenderImageHost::GetImageSize() const
return IntSize();
}
void
WebRenderImageHost::SetWrBridge(WebRenderBridgeParent* aWrBridge)
{
// For image hosts created through ImageBridgeParent, there may be multiple
// references to it due to the order of creation and freeing of layers by
// the layer tree. However this should be limited to things such as video
// which will not be reused across different WebRenderBridgeParent objects.
MOZ_ASSERT(aWrBridge);
MOZ_ASSERT(!mWrBridge || mWrBridge == aWrBridge);
mWrBridge = aWrBridge;
++mWrBridgeBindings;
}
void
WebRenderImageHost::ClearWrBridge()
{
MOZ_ASSERT(mWrBridgeBindings > 0);
--mWrBridgeBindings;
if (mWrBridgeBindings == 0) {
SetCurrentTextureHost(nullptr);
mWrBridge = nullptr;
}
}
} // namespace layers
} // namespace mozilla

Просмотреть файл

@ -12,7 +12,7 @@
namespace mozilla {
namespace layers {
class WebRenderCompositableHolder;
class WebRenderBridgeParent;
/**
* ImageHost. Works with ImageClientSingle and ImageClientBuffered
@ -69,16 +69,21 @@ public:
TextureHost* GetAsTextureHostForComposite();
void SetWrCompositableHolder(WebRenderCompositableHolder* aWrCompositableHolder)
{
mWrCompositableHolder = aWrCompositableHolder;
}
void SetWrBridge(WebRenderBridgeParent* aWrBridge);
void ClearWrBridge();
protected:
// ImageComposite
virtual TimeStamp GetCompositionTime() const override;
WebRenderCompositableHolder* MOZ_NON_OWNING_REF mWrCompositableHolder;
void SetCurrentTextureHost(TextureHost* aTexture);
WebRenderBridgeParent* MOZ_NON_OWNING_REF mWrBridge;
uint32_t mWrBridgeBindings;
CompositableTextureHostRef mCurrentTextureHost;
};
} // namespace layers

Просмотреть файл

@ -7,7 +7,9 @@
#include "gfxPrefs.h"
#include "LayersLogging.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/ImageClient.h"
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/TextureClientRecycleAllocator.h"
#include "mozilla/layers/TextureWrapperImage.h"
@ -30,9 +32,14 @@ WebRenderImageLayer::~WebRenderImageLayer()
{
MOZ_COUNT_DTOR(WebRenderImageLayer);
mPipelineIdRequest.DisconnectIfExists();
for (auto key : mVideoKeys) {
WrManager()->AddImageKeyForDiscard(key);
}
if (mKey.isSome()) {
WrManager()->AddImageKeyForDiscard(mKey.value());
}
if (mExternalImageId.isSome()) {
WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
}
@ -83,6 +90,17 @@ WebRenderImageLayer::ClearCachedResources()
}
}
void
WebRenderImageLayer::AddWRVideoImage(size_t aChannelNumber)
{
for (size_t i = 0; i < aChannelNumber; ++i) {
WrImageKey key = GetImageKey();
WrManager()->AddImageKeyForDiscard(key);
mVideoKeys.AppendElement(key);
}
WrBridge()->AddWebRenderParentCommand(OpAddExternalVideoImage(mExternalImageId.value(), mVideoKeys));
}
void
WebRenderImageLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc)
@ -146,25 +164,43 @@ WebRenderImageLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
}
gfx::IntSize size = image->GetSize();
if (GetImageClientType() == CompositableType::IMAGE_BRIDGE) {
// Always allocate key
WrImageKey key = GetImageKey();
WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId.value(), key));
WrManager()->AddImageKeyForDiscard(key);
mKey = Some(key);
} else {
if (GetImageClientType() != CompositableType::IMAGE_BRIDGE) {
// Handle CompositableType::IMAGE case
MOZ_ASSERT(mImageClient->AsImageClientSingle());
mKey = UpdateImageKey(mImageClient->AsImageClientSingle(),
mContainer,
mKey,
mExternalImageId.ref());
if (mKey.isNothing()) {
return;
}
} else {
// Always allocate key.
mVideoKeys.Clear();
// XXX (Jerry): Remove the hardcode image format setting.
#if defined(XP_WIN)
// Use libyuv to convert the buffer to rgba format. So, use 1 image key here.
AddWRVideoImage(1);
#elif defined(XP_MACOSX)
if (gfx::gfxVars::CanUseHardwareVideoDecoding()) {
// Use the hardware MacIOSurface with YCbCr interleaved format. It uses 1
// image key.
AddWRVideoImage(1);
} else {
// Use libyuv.
AddWRVideoImage(1);
}
#elif defined(MOZ_WIDGET_GTK)
// Use libyuv.
AddWRVideoImage(1);
#elif defined(ANDROID)
// Use libyuv.
AddWRVideoImage(1);
#endif
}
if (mKey.isNothing()) {
return;
}
ScrollingLayersHelper scroller(this, aBuilder, aSc);
StackingContextHelper sc(aSc, aBuilder, this);
LayerRect rect(0, 0, size.width, size.height);
@ -176,7 +212,7 @@ WebRenderImageLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
LayerRect clipRect = ClipRect().valueOr(rect);
Maybe<WrImageMask> mask = BuildWrMaskLayer(&sc);
WrClipRegion clip = aBuilder.BuildClipRegion(
WrClipRegionToken clip = aBuilder.PushClipRegion(
sc.ToRelativeWrRect(clipRect),
mask.ptrOr(nullptr));
@ -189,7 +225,36 @@ WebRenderImageLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
Stringify(filter).c_str());
}
aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mKey.value());
if (GetImageClientType() != CompositableType::IMAGE_BRIDGE) {
aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mKey.value());
} else {
// XXX (Jerry): Remove the hardcode image format setting. The format of
// textureClient could change from time to time. So, we just set the most
// usable format here.
#if defined(XP_WIN)
// Use libyuv to convert the buffer to rgba format.
MOZ_ASSERT(mVideoKeys.Length() == 1);
aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mVideoKeys[0]);
#elif defined(XP_MACOSX)
if (gfx::gfxVars::CanUseHardwareVideoDecoding()) {
// Use the hardware MacIOSurface with YCbCr interleaved format.
MOZ_ASSERT(mVideoKeys.Length() == 1);
aBuilder.PushYCbCrInterleavedImage(sc.ToRelativeWrRect(rect), clip, mVideoKeys[0], WrYuvColorSpace::Rec601);
} else {
// Use libyuv to convert the buffer to rgba format.
MOZ_ASSERT(mVideoKeys.Length() == 1);
aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mVideoKeys[0]);
}
#elif defined(MOZ_WIDGET_GTK)
// Use libyuv to convert the buffer to rgba format.
MOZ_ASSERT(mVideoKeys.Length() == 1);
aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mVideoKeys[0]);
#elif defined(ANDROID)
// Use libyuv to convert the buffer to rgba format.
MOZ_ASSERT(mVideoKeys.Length() == 1);
aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mVideoKeys[0]);
#endif
}
}
Maybe<WrImageMask>

Просмотреть файл

@ -36,6 +36,8 @@ public:
protected:
CompositableType GetImageClientType();
void AddWRVideoImage(size_t aChannelNumber);
class Holder {
public:
explicit Holder(WebRenderImageLayer* aLayer)
@ -47,6 +49,9 @@ protected:
};
wr::MaybeExternalImageId mExternalImageId;
// Some video image format contains multiple channel data.
nsTArray<wr::ImageKey> mVideoKeys;
// The regular single channel image.
Maybe<wr::ImageKey> mKey;
RefPtr<ImageClient> mImageClient;
CompositableType mImageClientTypeContainer;

Просмотреть файл

@ -52,7 +52,7 @@ WebRenderLayer::BuildWrMaskLayer(const StackingContextHelper* aUnapplySc)
// context.
gfx::Matrix4x4 transform = maskLayer->GetLayer()->GetTransform();
if (aUnapplySc) {
transform = transform * aUnapplySc->TransformToParentSC();
transform = transform * aUnapplySc->TransformToRoot();
}
return maskLayer->RenderMaskLayer(transform);

Просмотреть файл

@ -107,7 +107,7 @@ WebRenderLayerManager::~WebRenderLayerManager()
CompositorBridgeChild*
WebRenderLayerManager::GetCompositorBridgeChild()
{
return mWidget ? mWidget->GetRemoteRenderer() : nullptr;
return WrBridge()->GetCompositorBridgeChild();
}
int32_t
@ -192,7 +192,8 @@ WebRenderLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback
mRoot->StartPendingAnimations(mAnimationReadyTime);
StackingContextHelper sc;
wr::DisplayListBuilder builder(WrBridge()->GetPipeline());
WrSize contentSize { (float)size.width, (float)size.height };
wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder, sc);
WrBridge()->ClearReadLocks();
@ -205,7 +206,7 @@ WebRenderLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback
}
WebRenderScrollData scrollData;
if (mWidget->AsyncPanZoomEnabled()) {
if (AsyncPanZoomEnabled()) {
if (mIsFirstPaint) {
scrollData.SetIsFirstPaint();
mIsFirstPaint = false;
@ -233,6 +234,12 @@ WebRenderLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback
return true;
}
bool
WebRenderLayerManager::AsyncPanZoomEnabled() const
{
return mWidget->AsyncPanZoomEnabled();
}
void
WebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSize aSize)
{
@ -304,7 +311,7 @@ WebRenderLayerManager::AddImageKeyForDiscard(wr::ImageKey key)
void
WebRenderLayerManager::DiscardImages()
{
if (!WrBridge()->IsDestroyed()) {
if (WrBridge()->IPCOpen()) {
for (auto key : mImageKeys) {
WrBridge()->SendDeleteImage(key);
}
@ -321,11 +328,11 @@ WebRenderLayerManager::AddCompositorAnimationsIdForDiscard(uint64_t aId)
void
WebRenderLayerManager::DiscardCompositorAnimations()
{
if (!mDiscardedCompositorAnimationsIds.IsEmpty()) {
if (WrBridge()->IPCOpen() && !mDiscardedCompositorAnimationsIds.IsEmpty()) {
WrBridge()->
SendDeleteCompositorAnimations(mDiscardedCompositorAnimationsIds);
mDiscardedCompositorAnimationsIds.Clear();
}
mDiscardedCompositorAnimationsIds.Clear();
}
void
@ -465,6 +472,15 @@ WebRenderLayerManager::FlushRendering()
}
}
void
WebRenderLayerManager::WaitOnTransactionProcessed()
{
CompositorBridgeChild* bridge = GetCompositorBridgeChild();
if (bridge) {
bridge->SendWaitOnTransactionProcessed();
}
}
void
WebRenderLayerManager::SendInvalidRegion(const nsIntRegion& aRegion)
{

Просмотреть файл

@ -88,6 +88,7 @@ public:
virtual void RemoveDidCompositeObserver(DidCompositeObserver* aObserver) override;
virtual void FlushRendering() override;
virtual void WaitOnTransactionProcessed() override;
virtual void SendInvalidRegion(const nsIntRegion& aRegion) override;
@ -100,6 +101,8 @@ public:
virtual bool NeedsComposite() const override { return mNeedsComposite; }
virtual void SetIsFirstPaint() override { mIsFirstPaint = true; }
bool AsyncPanZoomEnabled() const override;
DrawPaintedLayerCallback GetPaintedLayerCallback() const
{ return mPaintedLayerCallback; }

Просмотреть файл

@ -192,28 +192,6 @@ struct ParamTraits<WrBuiltDisplayListDescriptor>
}
};
template<>
struct ParamTraits<WrAuxiliaryListsDescriptor>
{
static void
Write(Message* aMsg, const WrAuxiliaryListsDescriptor& aParam)
{
WriteParam(aMsg, aParam.gradient_stops_size);
WriteParam(aMsg, aParam.complex_clip_regions_size);
WriteParam(aMsg, aParam.filters_size);
WriteParam(aMsg, aParam.glyph_instances_size);
}
static bool
Read(const Message* aMsg, PickleIterator* aIter, WrAuxiliaryListsDescriptor* aResult)
{
return ReadParam(aMsg, aIter, &aResult->gradient_stops_size)
&& ReadParam(aMsg, aIter, &aResult->complex_clip_regions_size)
&& ReadParam(aMsg, aIter, &aResult->filters_size)
&& ReadParam(aMsg, aIter, &aResult->glyph_instances_size);
}
};
} // namespace IPC
#endif // GFX_WEBRENDERMESSAGEUTILS_H

Просмотреть файл

@ -7,6 +7,7 @@
#include "LayersLogging.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/UpdateImageHelper.h"
@ -92,6 +93,7 @@ void
WebRenderPaintedLayer::CreateWebRenderDisplayList(wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc)
{
ScrollingLayersHelper scroller(this, aBuilder, aSc);
StackingContextHelper sc(aSc, aBuilder, this);
LayerRect rect = Bounds();
@ -99,7 +101,7 @@ WebRenderPaintedLayer::CreateWebRenderDisplayList(wr::DisplayListBuilder& aBuild
LayerRect clipRect = ClipRect().valueOr(rect);
Maybe<WrImageMask> mask = BuildWrMaskLayer(&sc);
WrClipRegion clip = aBuilder.BuildClipRegion(
WrClipRegionToken clip = aBuilder.PushClipRegion(
sc.ToRelativeWrRect(clipRect),
mask.ptrOr(nullptr));

Просмотреть файл

@ -10,6 +10,7 @@
#include "LayersLogging.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/gfx/DrawEventRecorder.h"
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/UpdateImageHelper.h"
@ -46,11 +47,11 @@ WebRenderPaintedLayerBlob::RenderLayer(wr::DisplayListBuilder& aBuilder,
}
IntSize imageSize(size.ToUnknownSize());
RefPtr<gfx::DrawEventRecorderMemory> recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>();
RefPtr<gfx::DrawTarget> dummyDt = gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, imageSize, gfx::SurfaceFormat::B8G8R8X8);
RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt);
if (!regionToPaint.IsEmpty() && WrManager()->GetPaintedLayerCallback()) {
RefPtr<gfx::DrawEventRecorderMemory> recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>();
RefPtr<gfx::DrawTarget> dummyDt = gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, imageSize, gfx::SurfaceFormat::B8G8R8X8);
RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt);
dt->ClearRect(Rect(0, 0, imageSize.width, imageSize.height));
dt->SetTransform(Matrix().PreTranslate(-bounds.x, -bounds.y));
RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(dt);
@ -66,33 +67,34 @@ WebRenderPaintedLayerBlob::RenderLayer(wr::DisplayListBuilder& aBuilder,
dt->FillRect(Rect(0, 0, imageSize.width, imageSize.height), ColorPattern(Color(1.0, 0.0, 0.0, 0.5)));
}
wr::ByteBuffer bytes;
bytes.Allocate(recorder->RecordingSize());
DebugOnly<bool> ok = recorder->CopyRecording((char*)bytes.AsSlice().begin().get(), bytes.AsSlice().length());
MOZ_ASSERT(ok);
//XXX: We should switch to updating the blob image instead of adding a new one
// That will get rid of this discard bit
if (mImageKey.isSome()) {
WrManager()->AddImageKeyForDiscard(mImageKey.value());
}
mImageKey = Some(GetImageKey());
WrBridge()->SendAddBlobImage(mImageKey.value(), imageSize, size.width * 4, dt->GetFormat(), bytes);
} else {
// we need to reuse the blob image
MOZ_ASSERT(mExternalImageId);
MOZ_ASSERT(mImageContainer->HasCurrentImage());
MOZ_ASSERT(GetInvalidRegion().IsEmpty());
}
wr::ByteBuffer bytes;
bytes.Allocate(recorder->RecordingSize());
DebugOnly<bool> ok = recorder->CopyRecording((char*)bytes.AsSlice().begin().get(), bytes.AsSlice().length());
MOZ_ASSERT(ok);
ScrollingLayersHelper scroller(this, aBuilder, aSc);
StackingContextHelper sc(aSc, aBuilder, this);
LayerRect rect = Bounds();
DumpLayerInfo("PaintedLayer", rect);
LayerRect clipRect = ClipRect().valueOr(rect);
Maybe<WrImageMask> mask = BuildWrMaskLayer(&sc);
WrClipRegion clip = aBuilder.BuildClipRegion(
WrClipRegionToken clip = aBuilder.PushClipRegion(
sc.ToRelativeWrRect(clipRect),
mask.ptrOr(nullptr));
WrImageKey key = GetImageKey();
WrBridge()->SendAddBlobImage(key, imageSize, size.width * 4, dt->GetFormat(), bytes);
WrManager()->AddImageKeyForDiscard(key);
aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, wr::ImageRendering::Auto, key);
aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, wr::ImageRendering::Auto, mImageKey.value());
}
} // namespace layers

Просмотреть файл

@ -35,6 +35,9 @@ protected:
if (mExternalImageId.isSome()) {
WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
}
if (mImageKey.isSome()) {
WrManager()->AddImageKeyForDiscard(mImageKey.value());
}
}
wr::MaybeExternalImageId mExternalImageId;
@ -52,7 +55,7 @@ public:
private:
RefPtr<ImageContainer> mImageContainer;
RefPtr<ImageClient> mImageClient;
Maybe<WrImageKey> mImageKey;
};
} // namespace layers

Просмотреть файл

@ -8,6 +8,7 @@
#include "gfxPrefs.h"
#include "LayersLogging.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/gfx/2D.h"
@ -25,6 +26,8 @@ WebRenderTextLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
return;
}
ScrollingLayersHelper scroller(this, aBuilder, aSc);
LayerRect rect = LayerRect::FromUnknownRect(
// I am not 100% sure this is correct, but it probably is. Because:
// the bounds are in layer space, and when gecko composites layers it

Просмотреть файл

@ -156,5 +156,16 @@ WebRenderTextureHost::GetRGBStride()
return ImageDataSerializer::ComputeRGBStride(format, GetSize().width);
}
void
WebRenderTextureHost::AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{
MOZ_ASSERT(mWrappedTextureHost);
MOZ_ASSERT(mExternalImageId == aExtID);
mWrappedTextureHost->AddWRImage(aAPI, aImageKeys, aExtID);
}
} // namespace layers
} // namespace mozilla

Просмотреть файл

@ -65,6 +65,10 @@ public:
bool IsWrappingNativeHandle() { return mIsWrappingNativeHandle; }
virtual void AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) override;
protected:
void CreateRenderTextureHost(const SurfaceDescriptor& aDesc, TextureHost* aTexture);

Просмотреть файл

@ -311,3 +311,8 @@ bool gfxPrefs::OverrideBase_WebRender()
{
return gfx::gfxVars::UseWebRender();
}
bool gfxPrefs::OverrideBase_WebRendest()
{
return gfx::gfxVars::UseWebRender() && gfxPrefs::WebRendestEnabled();
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше