Merge mozilla-central and mozilla-inbound
@ -1,165 +0,0 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* Command Updater
|
||||
*/
|
||||
let CommandUpdater = {
|
||||
/**
|
||||
* Gets a controller that can handle a particular command.
|
||||
* @param {string} command
|
||||
* A command to locate a controller for, preferring controllers that
|
||||
* show the command as enabled.
|
||||
* @return {object} In this order of precedence:
|
||||
* - the first controller supporting the specified command
|
||||
* associated with the focused element that advertises the
|
||||
* command as ENABLED.
|
||||
* - the first controller supporting the specified command
|
||||
* associated with the global window that advertises the
|
||||
* command as ENABLED.
|
||||
* - the first controller supporting the specified command
|
||||
* associated with the focused element.
|
||||
* - the first controller supporting the specified command
|
||||
* associated with the global window.
|
||||
*/
|
||||
_getControllerForCommand: function(command) {
|
||||
try {
|
||||
let commandDispatcher = top.document.commandDispatcher;
|
||||
let controller = commandDispatcher.getControllerForCommand(command);
|
||||
if (controller && controller.isCommandEnabled(command))
|
||||
return controller;
|
||||
}
|
||||
catch (e) { }
|
||||
|
||||
let controllerCount = window.controllers.getControllerCount();
|
||||
for (let i = 0; i < controllerCount; ++i) {
|
||||
let current = window.controllers.getControllerAt(i);
|
||||
try {
|
||||
if (current.supportsCommand(command) &&
|
||||
current.isCommandEnabled(command))
|
||||
return current;
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
return controller || window.controllers.getControllerForCommand(command);
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the state of a XUL <command> element for the specified command
|
||||
* depending on its state.
|
||||
* @param {string} command
|
||||
* The name of the command to update the XUL <command> element for.
|
||||
*/
|
||||
updateCommand: function(command) {
|
||||
let enabled = false;
|
||||
try {
|
||||
let controller = this._getControllerForCommand(command);
|
||||
if (controller) {
|
||||
enabled = controller.isCommandEnabled(command);
|
||||
}
|
||||
}
|
||||
catch (ex) { }
|
||||
|
||||
this.enableCommand(command, enabled);
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the state of a XUL <command> element for the specified command
|
||||
* depending on its state.
|
||||
* @param {string} command
|
||||
* The name of the command to update the XUL <command> element for.
|
||||
*/
|
||||
updateCommands: function(_commands) {
|
||||
let commands = _commands.split(',');
|
||||
for (let command in commands) {
|
||||
this.updateCommand(commands[command]);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables or disables a XUL <command> element.
|
||||
* @param {string} command
|
||||
* The name of the command to enable or disable.
|
||||
* @param {bool} enabled
|
||||
* true if the command should be enabled, false otherwise.
|
||||
*/
|
||||
enableCommand: function(command, enabled) {
|
||||
let element = document.getElementById(command);
|
||||
if (!element)
|
||||
return;
|
||||
|
||||
if (enabled)
|
||||
element.removeAttribute('disabled');
|
||||
else
|
||||
element.setAttribute('disabled', 'true');
|
||||
},
|
||||
|
||||
/**
|
||||
* Performs the action associated with a specified command using the most
|
||||
* relevant controller.
|
||||
* @param {string} command
|
||||
* The command to perform.
|
||||
*/
|
||||
doCommand: function(command) {
|
||||
let controller = this._getControllerForCommand(command);
|
||||
if (!controller)
|
||||
return;
|
||||
controller.doCommand(command);
|
||||
},
|
||||
|
||||
/**
|
||||
* Changes the label attribute for the specified command.
|
||||
* @param {string} command
|
||||
* The command to update.
|
||||
* @param {string} labelAttribute
|
||||
* The label value to use.
|
||||
*/
|
||||
setMenuValue: function(command, labelAttribute) {
|
||||
let commandNode = top.document.getElementById(command);
|
||||
if (commandNode) {
|
||||
let label = commandNode.getAttribute(labelAttribute);
|
||||
if (label)
|
||||
commandNode.setAttribute('label', label);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Changes the accesskey attribute for the specified command.
|
||||
* @param {string} command
|
||||
* The command to update.
|
||||
* @param {string} valueAttribute
|
||||
* The value attribute to use.
|
||||
*/
|
||||
setAccessKey: function(command, valueAttribute) {
|
||||
let commandNode = top.document.getElementById(command);
|
||||
if (commandNode) {
|
||||
let value = commandNode.getAttribute(valueAttribute);
|
||||
if (value)
|
||||
commandNode.setAttribute('accesskey', value);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Inform all the controllers attached to a node that an event has occurred
|
||||
* (e.g. the tree controllers need to be informed of blur events so that they
|
||||
* can change some of the menu items back to their default values)
|
||||
* @param {node} node
|
||||
* The node receiving the event.
|
||||
* @param {event} event
|
||||
* The event.
|
||||
*/
|
||||
onEvent: function(node, event) {
|
||||
let numControllers = node.controllers.getControllerCount();
|
||||
let controller;
|
||||
|
||||
for (let i = 0; i < numControllers; i++) {
|
||||
controller = node.controllers.getControllerAt(i);
|
||||
if (controller)
|
||||
controller.onEvent(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -33,11 +33,15 @@ XPCOMUtils.defineLazyGetter(Services, 'idle', function() {
|
||||
.getService(Ci.nsIIdleService);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'fm', function(){
|
||||
return Cc['@mozilla.org/focus-managr;1']
|
||||
.getService(Ci.nsFocusManager);
|
||||
XPCOMUtils.defineLazyGetter(Services, 'audioManager', function() {
|
||||
return Cc['@mozilla.org/telephony/audiomanager;1']
|
||||
.getService(Ci.nsIAudioManager);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'fm', function() {
|
||||
return Cc['@mozilla.org/focus-manager;1']
|
||||
.getService(Ci.nsFocusManager);
|
||||
});
|
||||
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
// In order to use http:// scheme instead of file:// scheme
|
||||
@ -74,9 +78,6 @@ function addPermissions(urls) {
|
||||
}
|
||||
|
||||
var shell = {
|
||||
// FIXME/bug 678695: this should be a system setting
|
||||
preferredScreenBrightness: 1.0,
|
||||
|
||||
isDebug: false,
|
||||
|
||||
get contentBrowser() {
|
||||
@ -111,13 +112,23 @@ var shell = {
|
||||
return alert(msg);
|
||||
}
|
||||
|
||||
window.controllers.appendController(this);
|
||||
window.addEventListener('keypress', this);
|
||||
['keydown', 'keypress', 'keyup'].forEach((function listenKey(type) {
|
||||
window.addEventListener(type, this, false, true);
|
||||
window.addEventListener(type, this, true, true);
|
||||
}).bind(this));
|
||||
|
||||
window.addEventListener('MozApplicationManifest', this);
|
||||
window.addEventListener("AppCommand", this);
|
||||
window.addEventListener('mozfullscreenchange', this);
|
||||
this.contentBrowser.addEventListener('load', this, true);
|
||||
|
||||
// Until the volume can be set from the content side, set it to a
|
||||
// a specific value when the device starts. This way the front-end
|
||||
// can display a notification when the volume change and show a volume
|
||||
// level modified from this point.
|
||||
try {
|
||||
Services.audioManager.masterVolume = 0.5;
|
||||
} catch(e) {}
|
||||
|
||||
try {
|
||||
Services.io.offline = false;
|
||||
|
||||
@ -159,35 +170,8 @@ var shell = {
|
||||
},
|
||||
|
||||
stop: function shell_stop() {
|
||||
window.controllers.removeController(this);
|
||||
window.removeEventListener('keypress', this);
|
||||
window.removeEventListener('MozApplicationManifest', this);
|
||||
window.removeEventListener('AppCommand', this);
|
||||
},
|
||||
|
||||
supportsCommand: function shell_supportsCommand(cmd) {
|
||||
let isSupported = false;
|
||||
switch (cmd) {
|
||||
case 'cmd_close':
|
||||
isSupported = true;
|
||||
break;
|
||||
default:
|
||||
isSupported = false;
|
||||
break;
|
||||
}
|
||||
return isSupported;
|
||||
},
|
||||
|
||||
isCommandEnabled: function shell_isCommandEnabled(cmd) {
|
||||
return true;
|
||||
},
|
||||
|
||||
doCommand: function shell_doCommand(cmd) {
|
||||
switch (cmd) {
|
||||
case 'cmd_close':
|
||||
content.postMessage('appclose', '*');
|
||||
break;
|
||||
}
|
||||
window.removeEventListener('mozfullscreenchange', this);
|
||||
},
|
||||
|
||||
toggleDebug: function shell_toggleDebug() {
|
||||
@ -202,9 +186,7 @@ var shell = {
|
||||
}
|
||||
},
|
||||
|
||||
changeVolume: function shell_changeVolume(aDelta) {
|
||||
let audioManager = Cc["@mozilla.org/telephony/audiomanager;1"].getService(Ci.nsIAudioManager);
|
||||
|
||||
changeVolume: function shell_changeVolume(delta) {
|
||||
let steps = 10;
|
||||
try {
|
||||
steps = Services.prefs.getIntPref("media.volume.steps");
|
||||
@ -212,7 +194,11 @@ var shell = {
|
||||
steps = 1;
|
||||
} catch(e) {}
|
||||
|
||||
let volume = audioManager.masterVolume + aDelta / steps;
|
||||
let audioManager = Services.audioManager;
|
||||
if (!audioManager)
|
||||
return;
|
||||
|
||||
let volume = audioManager.masterVolume + delta / steps;
|
||||
if (volume > 1)
|
||||
volume = 1;
|
||||
if (volume < 0)
|
||||
@ -220,44 +206,58 @@ var shell = {
|
||||
audioManager.masterVolume = volume;
|
||||
},
|
||||
|
||||
forwardKeyToHomescreen: function shell_forwardKeyToHomescreen(evt) {
|
||||
let generatedEvent = content.document.createEvent('KeyboardEvent');
|
||||
generatedEvent.initKeyEvent(evt.type, true, true, evt.view, evt.ctrlKey,
|
||||
evt.altKey, evt.shiftKey, evt.metaKey,
|
||||
evt.keyCode, evt.charCode);
|
||||
|
||||
content.dispatchEvent(generatedEvent);
|
||||
},
|
||||
|
||||
handleEvent: function shell_handleEvent(evt) {
|
||||
switch (evt.type) {
|
||||
case 'keydown':
|
||||
case 'keyup':
|
||||
case 'keypress':
|
||||
switch (evt.keyCode) {
|
||||
case evt.DOM_VK_HOME:
|
||||
this.sendEvent(content, 'home');
|
||||
break;
|
||||
case evt.DOM_VK_SLEEP:
|
||||
this.toggleScreen();
|
||||
|
||||
let details = {
|
||||
'enabled': screen.mozEnabled
|
||||
};
|
||||
this.sendEvent(content, 'sleep', details);
|
||||
break;
|
||||
case evt.DOM_VK_ESCAPE:
|
||||
if (evt.defaultPrevented)
|
||||
return;
|
||||
this.doCommand('cmd_close');
|
||||
break;
|
||||
// If the home key is pressed, always forward it to the homescreen
|
||||
if (evt.eventPhase == evt.CAPTURING_PHASE) {
|
||||
if (evt.keyCode == evt.VK_DOM_HOME) {
|
||||
window.setTimeout(this.forwardKeyToHomescreen, 0, evt);
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'AppCommand':
|
||||
switch (evt.command) {
|
||||
case 'Menu':
|
||||
if (Services.prefs.getBoolPref('b2g.keys.menu.enabled'))
|
||||
this.sendEvent(content, 'menu');
|
||||
break;
|
||||
case 'Search':
|
||||
if (Services.prefs.getBoolPref('b2g.keys.search.enabled'))
|
||||
this.toggleDebug();
|
||||
break;
|
||||
case 'VolumeUp':
|
||||
this.changeVolume(1);
|
||||
break;
|
||||
case 'VolumeDown':
|
||||
this.changeVolume(-1);
|
||||
break;
|
||||
|
||||
// If one of the other keys is used in an application and is
|
||||
// cancelled via preventDefault, do nothing.
|
||||
let homescreen = (evt.target.ownerDocument.defaultView == content);
|
||||
if (!homescreen && evt.defaultPrevented)
|
||||
return;
|
||||
|
||||
// If one of the other keys is used in an application and is
|
||||
// not used forward it to the homescreen
|
||||
if (!homescreen)
|
||||
window.setTimeout(this.forwardKeyToHomescreen, 0, evt);
|
||||
|
||||
// For debug purposes and because some of the APIs are not yet exposed
|
||||
// to the content, let's react on some of the keyup events.
|
||||
if (evt.type == 'keyup') {
|
||||
switch (evt.keyCode) {
|
||||
case evt.DOM_VK_F5:
|
||||
if (Services.prefs.getBoolPref('b2g.keys.search.enabled'))
|
||||
this.toggleDebug();
|
||||
break;
|
||||
|
||||
case evt.DOM_VK_PAGE_DOWN:
|
||||
this.changeVolume(-1);
|
||||
break;
|
||||
|
||||
case evt.DOM_VK_PAGE_UP:
|
||||
this.changeVolume(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -270,7 +270,6 @@ var shell = {
|
||||
break;
|
||||
case 'load':
|
||||
this.contentBrowser.removeEventListener('load', this, true);
|
||||
this.turnScreenOn();
|
||||
|
||||
let chromeWindow = window.QueryInterface(Ci.nsIDOMChromeWindow);
|
||||
chromeWindow.browserDOMWindow = new nsBrowserAccess();
|
||||
@ -317,20 +316,6 @@ var shell = {
|
||||
let event = content.document.createEvent('CustomEvent');
|
||||
event.initCustomEvent(type, true, true, details ? details : {});
|
||||
content.dispatchEvent(event);
|
||||
},
|
||||
toggleScreen: function shell_toggleScreen() {
|
||||
if (screen.mozEnabled)
|
||||
this.turnScreenOff();
|
||||
else
|
||||
this.turnScreenOn();
|
||||
},
|
||||
turnScreenOff: function shell_turnScreenOff() {
|
||||
screen.mozEnabled = false;
|
||||
screen.mozBrightness = 0.0;
|
||||
},
|
||||
turnScreenOn: function shell_turnScreenOn() {
|
||||
screen.mozEnabled = true;
|
||||
screen.mozBrightness = this.preferredScreenBrightness;
|
||||
}
|
||||
};
|
||||
|
||||
@ -339,7 +324,7 @@ var shell = {
|
||||
observe: function(subject, topic, time) {
|
||||
if (topic === "idle") {
|
||||
// TODO: Check wakelock status. See bug 697132.
|
||||
shell.turnScreenOff();
|
||||
screen.mozEnabled = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
onload="shell.start();"
|
||||
onunload="shell.stop();">
|
||||
|
||||
<script type="application/javascript" src="chrome://browser/content/commandUtil.js"/>
|
||||
<script type="application/javascript" src="chrome://browser/content/shell.js"/>
|
||||
#ifndef MOZ_TOUCH
|
||||
<script type="application/javascript" src="chrome://browser/content/touch.js"/>
|
||||
@ -24,10 +23,6 @@
|
||||
<script type="application/javascript" src="chrome://browser/content/httpd.js"/>
|
||||
#endif
|
||||
|
||||
<commandset id="mainCommandSet">
|
||||
<command id="cmd_close" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
</commandset>
|
||||
|
||||
<browser id="homescreen"
|
||||
type="content-primary"
|
||||
flex="1"
|
||||
|
@ -9,7 +9,6 @@ chrome.jar:
|
||||
#ifndef MOZ_TOUCH
|
||||
content/touch.js (content/touch.js)
|
||||
#endif
|
||||
content/commandUtil.js (content/commandUtil.js)
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
content/httpd.js (content/httpd.js)
|
||||
#endif
|
||||
@ -22,4 +21,4 @@ chrome.jar:
|
||||
content/netError.css (content/netError.css)
|
||||
content/images/errorpage-larry-black.png (content/images/errorpage-larry-black.png)
|
||||
content/images/errorpage-larry-white.png (content/images/errorpage-larry-white.png)
|
||||
content/images/errorpage-warning.png (content/images/errorpage-warning.png)
|
||||
content/images/errorpage-warning.png (content/images/errorpage-warning.png)
|
||||
|
@ -320,6 +320,8 @@ pref("browser.urlbar.default.behavior", 0);
|
||||
pref("browser.urlbar.formatting.enabled", true);
|
||||
pref("browser.urlbar.trimURLs", true);
|
||||
|
||||
pref("browser.altClickSave", false);
|
||||
|
||||
// Number of milliseconds to wait for the http headers (and thus
|
||||
// the Content-Disposition filename) before giving up and falling back to
|
||||
// picking a filename without that info in hand so that the user sees some
|
||||
|
@ -48,6 +48,9 @@
|
||||
<!ENTITY % syncSetupDTD
|
||||
SYSTEM "chrome://browser/locale/syncSetup.dtd">
|
||||
%syncSetupDTD;
|
||||
<!ENTITY % globalDTD
|
||||
SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
@ -63,7 +66,7 @@
|
||||
<script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/sync/progress.js"/>
|
||||
</head>
|
||||
<body onload="onLoad(event)" onunload="onUnload(event)">
|
||||
<body onload="onLoad(event)" onunload="onUnload(event)" dir="&locale.dir;">
|
||||
<title>&setup.successPage.title;</title>
|
||||
<div id="floatingBox" class="main-content">
|
||||
<div id="title">
|
||||
|
@ -93,7 +93,6 @@ endif
|
||||
# browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
|
||||
|
||||
# browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
|
||||
# browser_urlbarAutoFillTrimURLs.js is disabled till bug 720792 is fixed
|
||||
|
||||
_BROWSER_FILES = \
|
||||
head.js \
|
||||
@ -223,6 +222,7 @@ _BROWSER_FILES = \
|
||||
browser_tabfocus.js \
|
||||
browser_tabs_isActive.js \
|
||||
browser_tabs_owner.js \
|
||||
browser_urlbarAutoFillTrimURLs.js \
|
||||
browser_urlbarCopying.js \
|
||||
browser_urlbarEnter.js \
|
||||
browser_urlbarRevert.js \
|
||||
|
@ -73,8 +73,12 @@ let gTests = [
|
||||
// just be like Alt click.
|
||||
{
|
||||
desc: "Shift+Alt left click",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
setup: function() {
|
||||
gPrefService.setBoolPref("browser.altClickSave", true);
|
||||
},
|
||||
clean: function() {
|
||||
gPrefService.clearUserPref("browser.altClickSave");
|
||||
},
|
||||
event: { shiftKey: true,
|
||||
altKey: true },
|
||||
targets: [ "commonlink", "maplink" ],
|
||||
@ -84,8 +88,12 @@ let gTests = [
|
||||
|
||||
{
|
||||
desc: "Shift+Alt left click on XLinks",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
setup: function() {
|
||||
gPrefService.setBoolPref("browser.altClickSave", true);
|
||||
},
|
||||
clean: function() {
|
||||
gPrefService.clearUserPref("browser.altClickSave");
|
||||
},
|
||||
event: { shiftKey: true,
|
||||
altKey: true },
|
||||
targets: [ "mathxlink", "svgxlink"],
|
||||
@ -105,8 +113,12 @@ let gTests = [
|
||||
|
||||
{
|
||||
desc: "Alt click",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
setup: function() {
|
||||
gPrefService.setBoolPref("browser.altClickSave", true);
|
||||
},
|
||||
clean: function() {
|
||||
gPrefService.clearUserPref("browser.altClickSave");
|
||||
},
|
||||
event: { altKey: true },
|
||||
targets: [ "commonlink", "maplink" ],
|
||||
expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ],
|
||||
@ -115,8 +127,12 @@ let gTests = [
|
||||
|
||||
{
|
||||
desc: "Alt click on XLinks",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
setup: function() {
|
||||
gPrefService.setBoolPref("browser.altClickSave", true);
|
||||
},
|
||||
clean: function() {
|
||||
gPrefService.clearUserPref("browser.altClickSave");
|
||||
},
|
||||
event: { altKey: true },
|
||||
targets: [ "mathxlink", "svgxlink" ],
|
||||
expectedInvokedMethods: [ "saveURL" ],
|
||||
@ -149,9 +165,7 @@ let gTests = [
|
||||
gPrefService.setBoolPref("browser.tabs.opentabfor.middleclick", false);
|
||||
},
|
||||
clean: function() {
|
||||
try {
|
||||
gPrefService.clearUserPref("browser.tabs.opentabfor.middleclick");
|
||||
} catch(ex) {}
|
||||
gPrefService.clearUserPref("browser.tabs.opentabfor.middleclick");
|
||||
},
|
||||
event: { button: 1 },
|
||||
targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
|
||||
@ -166,12 +180,8 @@ let gTests = [
|
||||
gPrefService.setBoolPref("general.autoScroll", false);
|
||||
},
|
||||
clean: function() {
|
||||
try {
|
||||
gPrefService.clearUserPref("middlemouse.contentLoadURL");
|
||||
} catch(ex) {}
|
||||
try {
|
||||
gPrefService.clearUserPref("general.autoScroll");
|
||||
} catch(ex) {}
|
||||
gPrefService.clearUserPref("middlemouse.contentLoadURL");
|
||||
gPrefService.clearUserPref("general.autoScroll");
|
||||
},
|
||||
event: { button: 1 },
|
||||
targets: [ "emptylink" ],
|
||||
|
@ -9,6 +9,12 @@ let gFocusManager = Cc["@mozilla.org/focus-manager;1"].
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref("browser.altClickSave");
|
||||
});
|
||||
Services.prefs.setBoolPref("browser.altClickSave", true);
|
||||
|
||||
runAltLeftClickTest();
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ function whereToOpenLink( e, ignoreButton, ignoreAlt )
|
||||
#endif
|
||||
return shift ? "tabshifted" : "tab";
|
||||
|
||||
if (alt)
|
||||
if (alt && getBoolPref("browser.altClickSave", false))
|
||||
return "save";
|
||||
|
||||
if (shift || (middle && !middleUsesTabs))
|
||||
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 445 B After Width: | Height: | Size: 237 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 926 B |
@ -3,8 +3,13 @@ dnl disabling frame pointers in this architecture based on the configure
|
||||
dnl options
|
||||
|
||||
AC_DEFUN([MOZ_SET_FRAMEPTR_FLAGS], [
|
||||
case "$target" in
|
||||
*android*)
|
||||
unwind_tables="-funwind-tables"
|
||||
;;
|
||||
esac
|
||||
if test "$GNU_CC"; then
|
||||
MOZ_ENABLE_FRAME_PTR="-fno-omit-frame-pointer"
|
||||
MOZ_ENABLE_FRAME_PTR="-fno-omit-frame-pointer $unwind_tables"
|
||||
MOZ_DISABLE_FRAME_PTR="-fomit-frame-pointer"
|
||||
else
|
||||
case "$target" in
|
||||
|
@ -913,6 +913,7 @@ sechash.h
|
||||
secoidt.h
|
||||
certdb.h
|
||||
secerr.h
|
||||
nssutil.h
|
||||
nssb64.h
|
||||
secasn1.h
|
||||
secder.h
|
||||
|
@ -5157,10 +5157,10 @@ incorrect])
|
||||
else
|
||||
AC_CHECK_LIB(QtSensors, main, [
|
||||
MOZ_ENABLE_QTMOBILITY=1
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtMobility"
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtSensors"
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtFeedback"
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtLocation"
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtMobility"
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtSensors"
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtFeedback"
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtLocation"
|
||||
MOZ_QT_LIBS="$MOZ_QT_LIBS -lQtSensors -lQtFeedback -lQtLocation"
|
||||
])
|
||||
fi
|
||||
|
@ -422,8 +422,8 @@ public:
|
||||
/**
|
||||
* Returns true if aChar is of class Ps, Pi, Po, Pf, or Pe.
|
||||
*/
|
||||
static bool IsPunctuationMark(PRUint32 aChar);
|
||||
static bool IsPunctuationMarkAt(const nsTextFragment* aFrag, PRUint32 aOffset);
|
||||
static bool IsFirstLetterPunctuation(PRUint32 aChar);
|
||||
static bool IsFirstLetterPunctuationAt(const nsTextFragment* aFrag, PRUint32 aOffset);
|
||||
|
||||
/**
|
||||
* Returns true if aChar is of class Lu, Ll, Lt, Lm, Lo, Nd, Nl or No
|
||||
|
@ -210,6 +210,7 @@ INCLUDES += \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
||||
DEFINES += -DHB_DONT_DEFINE_STDINT
|
||||
|
||||
# gcc requires -msse2 for this file since it uses SSE2 intrinsics. (See bug
|
||||
# 585538 comment 12.)
|
||||
|
@ -123,6 +123,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
||||
#include "nsILineBreaker.h"
|
||||
#include "nsIWordBreaker.h"
|
||||
#include "nsUnicodeProperties.h"
|
||||
#include "harfbuzz/hb-common.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsIDOMDocumentXBL.h"
|
||||
@ -1117,34 +1118,38 @@ nsContentUtils::CopyNewlineNormalizedUnicodeTo(nsReadingIterator<PRUnichar>& aSr
|
||||
return normalizer.GetCharsWritten();
|
||||
}
|
||||
|
||||
// Replaced by precompiled CCMap (see bug 180266). To update the list
|
||||
// of characters, see one of files included below. As for the way
|
||||
// the original list of characters was obtained by Frank Tang, see bug 54467.
|
||||
// Updated to fix the regression (bug 263411). The list contains
|
||||
// characters of the following Unicode character classes : Ps, Pi, Po, Pf, Pe.
|
||||
// (ref.: http://www.w3.org/TR/2004/CR-CSS21-20040225/selector.html#first-letter)
|
||||
#include "punct_marks.x-ccmap"
|
||||
DEFINE_X_CCMAP(gPuncCharsCCMapExt, const);
|
||||
/**
|
||||
* This is used to determine whether a character is in one of the punctuation
|
||||
* mark classes which CSS says should be part of the first-letter.
|
||||
* See http://www.w3.org/TR/CSS2/selector.html#first-letter and
|
||||
* http://www.w3.org/TR/selectors/#first-letter
|
||||
*/
|
||||
|
||||
// static
|
||||
bool
|
||||
nsContentUtils::IsPunctuationMark(PRUint32 aChar)
|
||||
nsContentUtils::IsFirstLetterPunctuation(PRUint32 aChar)
|
||||
{
|
||||
return CCMAP_HAS_CHAR_EXT(gPuncCharsCCMapExt, aChar);
|
||||
PRUint8 cat = mozilla::unicode::GetGeneralCategory(aChar);
|
||||
|
||||
return (cat == HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION || // Ps
|
||||
cat == HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION || // Pe
|
||||
cat == HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION || // Pi
|
||||
cat == HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION || // Pf
|
||||
cat == HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION); // Po
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsContentUtils::IsPunctuationMarkAt(const nsTextFragment* aFrag, PRUint32 aOffset)
|
||||
nsContentUtils::IsFirstLetterPunctuationAt(const nsTextFragment* aFrag, PRUint32 aOffset)
|
||||
{
|
||||
PRUnichar h = aFrag->CharAt(aOffset);
|
||||
if (!IS_SURROGATE(h)) {
|
||||
return IsPunctuationMark(h);
|
||||
return IsFirstLetterPunctuation(h);
|
||||
}
|
||||
if (NS_IS_HIGH_SURROGATE(h) && aOffset + 1 < aFrag->GetLength()) {
|
||||
PRUnichar l = aFrag->CharAt(aOffset + 1);
|
||||
if (NS_IS_LOW_SURROGATE(l)) {
|
||||
return IsPunctuationMark(SURROGATE_TO_UCS4(h, l));
|
||||
return IsFirstLetterPunctuation(SURROGATE_TO_UCS4(h, l));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -65,7 +65,7 @@ SetupCapitalization(const PRUnichar* aWord, PRUint32 aLength,
|
||||
// The only space character a word can contain is NBSP.
|
||||
bool capitalizeNextChar = true;
|
||||
for (PRUint32 i = 0; i < aLength; ++i) {
|
||||
if (capitalizeNextChar && !nsContentUtils::IsPunctuationMark(aWord[i])) {
|
||||
if (capitalizeNextChar && !nsContentUtils::IsFirstLetterPunctuation(aWord[i])) {
|
||||
aCapitalization[i] = true;
|
||||
capitalizeNextChar = false;
|
||||
}
|
||||
|
@ -467,6 +467,13 @@ public:
|
||||
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace);
|
||||
void SendIdleEvent();
|
||||
|
||||
NPError InitAsyncSurface(NPSize *size, NPImageFormat format,
|
||||
void *initData, NPAsyncSurface *surface)
|
||||
{ return NPERR_GENERIC_ERROR; }
|
||||
|
||||
NPError FinalizeAsyncSurface(NPAsyncSurface *surface) { return NPERR_GENERIC_ERROR; }
|
||||
void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed) { return; }
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsDummyJavaPluginOwner)
|
||||
|
||||
@ -605,6 +612,12 @@ nsDummyJavaPluginOwner::InvalidateRegion(NPRegion invalidRegion)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDummyJavaPluginOwner::RedrawPlugin()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDummyJavaPluginOwner::GetNetscapeWindow(void *value)
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ VPATH = \
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
|
||||
ifeq ($(MOZ_BUILD_APP),b2g)
|
||||
VPATH += $(srcdir)/fallback
|
||||
endif
|
||||
|
||||
@ -19,17 +19,16 @@ MODULE = dom
|
||||
LIBRARY_NAME = jsdomcontacts_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
ContactManager.js \
|
||||
ContactManager.manifest \
|
||||
EXTRA_COMPONENTS = \
|
||||
ContactManager.js \
|
||||
ContactManager.manifest \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
|
||||
EXTRA_JS_MODULES = ContactService.jsm \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES += ContactDB.jsm \
|
||||
$(NULL)
|
||||
ifeq ($(MOZ_BUILD_APP),b2g)
|
||||
EXTRA_JS_MODULES = \
|
||||
ContactService.jsm \
|
||||
ContactDB.jsm \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
|
@ -228,6 +228,33 @@ typedef enum {
|
||||
NPFocusPrevious = 1
|
||||
} NPFocusDirection;
|
||||
|
||||
/* These formats describe the format in the memory byte-order. This means if
|
||||
* a 32-bit value of a pixel is viewed on a little-endian system the layout will
|
||||
* be 0xAARRGGBB. The Alpha channel will be stored in the most significant
|
||||
* bits. */
|
||||
typedef enum {
|
||||
/* 32-bit per pixel 8-bit per channel - premultiplied alpha */
|
||||
NPImageFormatBGRA32 = 0x1,
|
||||
/* 32-bit per pixel 8-bit per channel - 1 unused channel */
|
||||
NPImageFormatBGRX32 = 0x2
|
||||
} NPImageFormat;
|
||||
|
||||
typedef struct _NPAsyncSurface
|
||||
{
|
||||
uint32_t version;
|
||||
NPSize size;
|
||||
NPImageFormat format;
|
||||
union {
|
||||
struct {
|
||||
uint32_t stride;
|
||||
void *data;
|
||||
} bitmap;
|
||||
#if defined(XP_WIN)
|
||||
HANDLE sharedHandle;
|
||||
#endif
|
||||
};
|
||||
} NPAsyncSurface;
|
||||
|
||||
/* Return values for NPP_HandleEvent */
|
||||
#define kNPEventNotHandled 0
|
||||
#define kNPEventHandled 1
|
||||
@ -273,17 +300,26 @@ typedef struct
|
||||
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
typedef enum {
|
||||
#ifndef NP_NO_QUICKDRAW
|
||||
NPDrawingModelQuickDraw = 0,
|
||||
#endif
|
||||
#if defined(XP_MACOSX)
|
||||
NPDrawingModelCoreGraphics = 1,
|
||||
NPDrawingModelOpenGL = 2,
|
||||
NPDrawingModelCoreAnimation = 3,
|
||||
NPDrawingModelInvalidatingCoreAnimation = 4
|
||||
NPDrawingModelInvalidatingCoreAnimation = 4,
|
||||
#endif
|
||||
NPDrawingModelSyncWin = 5,
|
||||
NPDrawingModelSyncX = 6,
|
||||
NPDrawingModelAsyncBitmapSurface = 7
|
||||
#if defined(XP_WIN)
|
||||
, NPDrawingModelAsyncWindowsDXGISurface = 8,
|
||||
NPDrawingModelAsyncWindowsDX9ExSurface = 9
|
||||
#endif
|
||||
} NPDrawingModel;
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
typedef enum {
|
||||
#ifndef NP_NO_CARBON
|
||||
NPEventModelCarbon = 0,
|
||||
@ -370,9 +406,9 @@ typedef enum {
|
||||
|
||||
NPPVpluginUsesDOMForCursorBool = 22
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
/* Used for negotiating drawing models */
|
||||
, NPPVpluginDrawingModel = 1000
|
||||
#if defined(XP_MACOSX)
|
||||
/* Used for negotiating event models */
|
||||
, NPPVpluginEventModel = 1001
|
||||
/* In the NPDrawingModelCoreAnimation drawing model, the browser asks the plug-in for a Core Animation layer. */
|
||||
@ -415,9 +451,9 @@ typedef enum {
|
||||
|
||||
NPNVdocumentOrigin = 22
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
/* Used for negotiating drawing models */
|
||||
, NPNVpluginDrawingModel = 1000
|
||||
#if defined(XP_MACOSX)
|
||||
#ifndef NP_NO_QUICKDRAW
|
||||
, NPNVsupportsQuickDrawBool = 2000
|
||||
#endif
|
||||
@ -425,6 +461,15 @@ typedef enum {
|
||||
, NPNVsupportsOpenGLBool = 2002
|
||||
, NPNVsupportsCoreAnimationBool = 2003
|
||||
, NPNVsupportsInvalidatingCoreAnimationBool = 2004
|
||||
#endif
|
||||
, NPNVsupportsSyncDrawingBool = 2005
|
||||
, NPNVsupportsAsyncBitmapSurfaceBool = 2006
|
||||
#if defined(XP_WIN)
|
||||
, NPNVsupportsAsyncWindowsDXGISurfaceBool = 2007
|
||||
, NPNVsupportsAsyncWindowsDX9ExSurfaceBool = 2008
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
#ifndef NP_NO_CARBON
|
||||
, NPNVsupportsCarbonBool = 3000 /* TRUE if the browser supports the Carbon event model */
|
||||
#endif
|
||||
@ -820,6 +865,7 @@ void NP_LOADDS NPP_LostFocus(NPP instance);
|
||||
void NP_LOADDS NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, void* notifyData);
|
||||
NPError NP_LOADDS NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge);
|
||||
char** NP_LOADDS NPP_GetSitesWithData(void);
|
||||
void NP_LOADDS NPP_DidComposite(NPP instance);
|
||||
|
||||
/* NPN_* functions are provided by the navigator and called by the plugin. */
|
||||
void NP_LOADDS NPN_Version(int* plugin_major, int* plugin_minor,
|
||||
@ -882,6 +928,11 @@ NPBool NP_LOADDS NPN_ConvertPoint(NPP instance, double sourceX, double sour
|
||||
NPBool NP_LOADDS NPN_HandleEvent(NPP instance, void *event, NPBool handled);
|
||||
NPBool NP_LOADDS NPN_UnfocusInstance(NPP instance, NPFocusDirection direction);
|
||||
void NP_LOADDS NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow);
|
||||
NPError NP_LOADDS NPN_InitAsyncSurface(NPP instance, NPSize *size,
|
||||
NPImageFormat format, void *initData,
|
||||
NPAsyncSurface *surface);
|
||||
NPError NP_LOADDS NPN_FinalizeAsyncSurface(NPP instance, NPAsyncSurface *surface);
|
||||
void NP_LOADDS NPN_SetCurrentAsyncSurface(NPP instance, NPAsyncSurface *surface, NPRect *changed);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
|
@ -72,6 +72,7 @@ typedef void (* NP_LOADDS NPP_LostFocusPtr)(NPP instance);
|
||||
typedef void (* NP_LOADDS NPP_URLRedirectNotifyPtr)(NPP instance, const char* url, int32_t status, void* notifyData);
|
||||
typedef NPError (* NP_LOADDS NPP_ClearSiteDataPtr)(const char* site, uint64_t flags, uint64_t maxAge);
|
||||
typedef char** (* NP_LOADDS NPP_GetSitesWithDataPtr)(void);
|
||||
typedef void (* NP_LOADDS NPP_DidCompositePtr)(NPP instance);
|
||||
|
||||
typedef NPError (*NPN_GetValueProcPtr)(NPP instance, NPNVariable variable, void *ret_value);
|
||||
typedef NPError (*NPN_SetValueProcPtr)(NPP instance, NPPVariable variable, void *value);
|
||||
@ -130,6 +131,9 @@ typedef NPBool (*NPN_ConvertPointPtr)(NPP instance, double sourceX, double
|
||||
typedef NPBool (*NPN_HandleEventPtr)(NPP instance, void *event, NPBool handled);
|
||||
typedef NPBool (*NPN_UnfocusInstancePtr)(NPP instance, NPFocusDirection direction);
|
||||
typedef void (*NPN_URLRedirectResponsePtr)(NPP instance, void* notifyData, NPBool allow);
|
||||
typedef NPError (*NPN_InitAsyncSurfacePtr)(NPP instance, NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface);
|
||||
typedef NPError (*NPN_FinalizeAsyncSurfacePtr)(NPP instance, NPAsyncSurface *surface);
|
||||
typedef void (*NPN_SetCurrentAsyncSurfacePtr)(NPP instance, NPAsyncSurface *surface, NPRect *changed);
|
||||
|
||||
typedef struct _NPPluginFuncs {
|
||||
uint16_t size;
|
||||
@ -153,6 +157,7 @@ typedef struct _NPPluginFuncs {
|
||||
NPP_URLRedirectNotifyPtr urlredirectnotify;
|
||||
NPP_ClearSiteDataPtr clearsitedata;
|
||||
NPP_GetSitesWithDataPtr getsiteswithdata;
|
||||
NPP_DidCompositePtr didComposite;
|
||||
} NPPluginFuncs;
|
||||
|
||||
typedef struct _NPNetscapeFuncs {
|
||||
@ -213,6 +218,9 @@ typedef struct _NPNetscapeFuncs {
|
||||
NPN_HandleEventPtr handleevent;
|
||||
NPN_UnfocusInstancePtr unfocusinstance;
|
||||
NPN_URLRedirectResponsePtr urlredirectresponse;
|
||||
NPN_InitAsyncSurfacePtr initasyncsurface;
|
||||
NPN_FinalizeAsyncSurfacePtr finalizeasyncsurface;
|
||||
NPN_SetCurrentAsyncSurfacePtr setcurrentasyncsurface;
|
||||
} NPNetscapeFuncs;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
@ -118,6 +118,11 @@ interface nsIPluginInstanceOwner : nsISupports
|
||||
*/
|
||||
void invalidateRegion(in NPRegion aRegion);
|
||||
|
||||
/**
|
||||
* Have the plugin recomposited.
|
||||
*/
|
||||
void redrawPlugin();
|
||||
|
||||
/**
|
||||
* Get NetscapeWindow, corresponds to NPNVnetscapeWindow
|
||||
*/
|
||||
@ -130,6 +135,10 @@ interface nsIPluginInstanceOwner : nsISupports
|
||||
virtual NPError ShowNativeContextMenu(NPMenu* menu, void* event) = 0;
|
||||
virtual NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace) = 0;
|
||||
virtual NPError InitAsyncSurface(NPSize *size, NPImageFormat format,
|
||||
void *initData, NPAsyncSurface *surface) = 0;
|
||||
virtual NPError FinalizeAsyncSurface(NPAsyncSurface *surface) = 0;
|
||||
virtual void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed) = 0;
|
||||
%}
|
||||
|
||||
void setEventModel(in PRInt32 eventModel);
|
||||
|
@ -220,8 +220,8 @@ static JSClass sNPObjectMemberClass =
|
||||
static void
|
||||
OnWrapperDestroyed();
|
||||
|
||||
static JSBool
|
||||
DelayedReleaseGCCallback(JSContext* cx, JSGCStatus status)
|
||||
static void
|
||||
DelayedReleaseGCCallback(JSRuntime* rt, JSGCStatus status)
|
||||
{
|
||||
if (JSGC_END == status) {
|
||||
// Take ownership of sDelayedReleases and null it out now. The
|
||||
@ -238,7 +238,6 @@ DelayedReleaseGCCallback(JSContext* cx, JSGCStatus status)
|
||||
}
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -200,7 +200,10 @@ static NPNetscapeFuncs sBrowserFuncs = {
|
||||
_convertpoint,
|
||||
NULL, // handleevent, unimplemented
|
||||
NULL, // unfocusinstance, unimplemented
|
||||
_urlredirectresponse
|
||||
_urlredirectresponse,
|
||||
_initasyncsurface,
|
||||
_finalizeasyncsurface,
|
||||
_setcurrentasyncsurface
|
||||
};
|
||||
|
||||
static Mutex *sPluginThreadAsyncCallLock = nsnull;
|
||||
@ -2525,7 +2528,8 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
|
||||
return inst->SetUsesDOMForCursor(useDOMForCursor);
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
// On android, their 'drawing model' uses the same constant!
|
||||
case NPPVpluginDrawingModel: {
|
||||
if (inst) {
|
||||
inst->SetDrawingModel((NPDrawingModel)NS_PTR_TO_INT32(result));
|
||||
@ -2535,7 +2539,9 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
case NPPVpluginEventModel: {
|
||||
if (inst) {
|
||||
inst->SetEventModel((NPEventModel)NS_PTR_TO_INT32(result));
|
||||
@ -2883,6 +2889,36 @@ _popupcontextmenu(NPP instance, NPMenu* menu)
|
||||
return inst->PopUpContextMenu(menu);
|
||||
}
|
||||
|
||||
NPError NP_CALLBACK
|
||||
_initasyncsurface(NPP instance, NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface)
|
||||
{
|
||||
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
|
||||
if (!inst)
|
||||
return NPERR_GENERIC_ERROR;
|
||||
|
||||
return inst->InitAsyncSurface(size, format, initData, surface);
|
||||
}
|
||||
|
||||
NPError NP_CALLBACK
|
||||
_finalizeasyncsurface(NPP instance, NPAsyncSurface *surface)
|
||||
{
|
||||
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
|
||||
if (!inst)
|
||||
return NPERR_GENERIC_ERROR;
|
||||
|
||||
return inst->FinalizeAsyncSurface(surface);
|
||||
}
|
||||
|
||||
void NP_CALLBACK
|
||||
_setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed)
|
||||
{
|
||||
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
|
||||
if (!inst)
|
||||
return;
|
||||
|
||||
inst->SetCurrentAsyncSurface(surface, changed);
|
||||
}
|
||||
|
||||
NPBool NP_CALLBACK
|
||||
_convertpoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace)
|
||||
{
|
||||
|
@ -297,6 +297,15 @@ _unscheduletimer(NPP instance, uint32_t timerID);
|
||||
NPError NP_CALLBACK
|
||||
_popupcontextmenu(NPP instance, NPMenu* menu);
|
||||
|
||||
NPError NP_CALLBACK
|
||||
_initasyncsurface(NPP instance, NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface);
|
||||
|
||||
NPError NP_CALLBACK
|
||||
_finalizeasyncsurface(NPP instance, NPAsyncSurface *surface);
|
||||
|
||||
void NP_CALLBACK
|
||||
_setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed);
|
||||
|
||||
NPBool NP_CALLBACK
|
||||
_convertpoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
|
||||
|
||||
|
@ -80,13 +80,7 @@ NS_IMPL_THREADSAFE_ISUPPORTS0(nsNPAPIPluginInstance)
|
||||
|
||||
nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
|
||||
:
|
||||
#ifdef XP_MACOSX
|
||||
#ifdef NP_NO_QUICKDRAW
|
||||
mDrawingModel(NPDrawingModelCoreGraphics),
|
||||
#else
|
||||
mDrawingModel(NPDrawingModelQuickDraw),
|
||||
#endif
|
||||
#endif
|
||||
mDrawingModel(kDefaultDrawingModel),
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
mSurface(nsnull),
|
||||
mANPDrawingModel(0),
|
||||
@ -704,12 +698,17 @@ nsNPAPIPluginInstance::UsesDOMForCursor()
|
||||
return mUsesDOMForCursor;
|
||||
}
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
void nsNPAPIPluginInstance::SetDrawingModel(NPDrawingModel aModel)
|
||||
{
|
||||
mDrawingModel = aModel;
|
||||
}
|
||||
|
||||
void nsNPAPIPluginInstance::RedrawPlugin()
|
||||
{
|
||||
mOwner->RedrawPlugin();
|
||||
}
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
void nsNPAPIPluginInstance::SetEventModel(NPEventModel aModel)
|
||||
{
|
||||
// the event model needs to be set for the object frame immediately
|
||||
@ -1482,6 +1481,32 @@ nsNPAPIPluginInstance::URLRedirectResponse(void* notifyData, NPBool allow)
|
||||
}
|
||||
}
|
||||
|
||||
NPError
|
||||
nsNPAPIPluginInstance::InitAsyncSurface(NPSize *size, NPImageFormat format,
|
||||
void *initData, NPAsyncSurface *surface)
|
||||
{
|
||||
if (mOwner)
|
||||
return mOwner->InitAsyncSurface(size, format, initData, surface);
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NPError
|
||||
nsNPAPIPluginInstance::FinalizeAsyncSurface(NPAsyncSurface *surface)
|
||||
{
|
||||
if (mOwner)
|
||||
return mOwner->FinalizeAsyncSurface(surface);
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
nsNPAPIPluginInstance::SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed)
|
||||
{
|
||||
if (mOwner)
|
||||
mOwner->SetCurrentAsyncSurface(surface, changed);
|
||||
}
|
||||
|
||||
class CarbonEventModelFailureEvent : public nsRunnable {
|
||||
public:
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
|
@ -64,6 +64,18 @@ class nsIPluginInstanceOwner;
|
||||
class nsIPluginStreamListener;
|
||||
class nsIOutputStream;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
const NPDrawingModel kDefaultDrawingModel = NPDrawingModelSyncWin;
|
||||
#elif defined(MOZ_X11)
|
||||
const NPDrawingModel kDefaultDrawingModel = NPDrawingModelSyncX;
|
||||
#else
|
||||
#ifndef NP_NO_QUICKDRAW
|
||||
const NPDrawingModel kDefaultDrawingModel = NPDrawingModelQuickDraw;
|
||||
#else
|
||||
const NPDrawingModel kDefaultDrawingModel = NPDrawingModelCoreGraphics;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class nsNPAPITimer
|
||||
{
|
||||
public:
|
||||
@ -141,8 +153,9 @@ public:
|
||||
NPError SetUsesDOMForCursor(bool aUsesDOMForCursor);
|
||||
bool UsesDOMForCursor();
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
void SetDrawingModel(NPDrawingModel aModel);
|
||||
void RedrawPlugin();
|
||||
#ifdef XP_MACOSX
|
||||
void SetEventModel(NPEventModel aModel);
|
||||
#endif
|
||||
|
||||
@ -214,6 +227,11 @@ public:
|
||||
|
||||
void URLRedirectResponse(void* notifyData, NPBool allow);
|
||||
|
||||
NPError InitAsyncSurface(NPSize *size, NPImageFormat format,
|
||||
void *initData, NPAsyncSurface *surface);
|
||||
NPError FinalizeAsyncSurface(NPAsyncSurface *surface);
|
||||
void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed);
|
||||
|
||||
// Called when the instance fails to instantiate beceause the Carbon
|
||||
// event model is not supported.
|
||||
void CarbonNPAPIFailure();
|
||||
@ -232,9 +250,7 @@ protected:
|
||||
// the browser.
|
||||
NPP_t mNPP;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
NPDrawingModel mDrawingModel;
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
PRUint32 mANPDrawingModel;
|
||||
|
@ -212,9 +212,10 @@ nsPluginInstanceOwner::GetImageContainer()
|
||||
mInstance->GetImageContainer(getter_AddRefs(container));
|
||||
if (container) {
|
||||
#ifdef XP_MACOSX
|
||||
nsRefPtr<Image> image = container->GetCurrentImage();
|
||||
AutoLockImage autoLock(container);
|
||||
Image* image = autoLock.GetImage();
|
||||
if (image && image->GetFormat() == Image::MAC_IO_SURFACE && mObjectFrame) {
|
||||
MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image.get());
|
||||
MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image);
|
||||
NS_ADDREF_THIS();
|
||||
oglImage->SetUpdateCallback(&DrawPlugin, this);
|
||||
oglImage->SetDestroyCallback(&OnDestroyImage);
|
||||
@ -670,6 +671,15 @@ NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRegion(NPRegion invalidRegion)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginInstanceOwner::RedrawPlugin()
|
||||
{
|
||||
if (mObjectFrame) {
|
||||
mObjectFrame->InvalidateLayer(mObjectFrame->GetContentRectRelativeToSelf(), nsDisplayItem::TYPE_PLUGIN);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
|
||||
{
|
||||
@ -791,6 +801,21 @@ NPBool nsPluginInstanceOwner::ConvertPoint(double sourceX, double sourceY, NPCoo
|
||||
#endif
|
||||
}
|
||||
|
||||
NPError nsPluginInstanceOwner::InitAsyncSurface(NPSize *size, NPImageFormat format,
|
||||
void *initData, NPAsyncSurface *surface)
|
||||
{
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
NPError nsPluginInstanceOwner::FinalizeAsyncSurface(NPAsyncSurface *)
|
||||
{
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
void nsPluginInstanceOwner::SetCurrentAsyncSurface(NPAsyncSurface *, NPRect*)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginInstanceOwner::GetTagType(nsPluginTagType *result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(result);
|
||||
@ -3704,10 +3729,11 @@ void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
|
||||
nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
|
||||
if (container) {
|
||||
#ifdef XP_MACOSX
|
||||
nsRefPtr<Image> image = container->GetCurrentImage();
|
||||
AutoLockImage autoLock(container);
|
||||
Image *image = autoLock.GetImage();
|
||||
if (image && (image->GetFormat() == Image::MAC_IO_SURFACE) && mObjectFrame) {
|
||||
// Undo what we did to the current image in SetCurrentImage().
|
||||
MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image.get());
|
||||
MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image);
|
||||
oglImage->SetUpdateCallback(nsnull, nsnull);
|
||||
oglImage->SetDestroyCallback(nsnull);
|
||||
// If we have a current image here, its destructor hasn't yet been
|
||||
@ -3715,6 +3741,9 @@ void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
|
||||
// to do ourselves what OnDestroyImage() would have done.
|
||||
NS_RELEASE_THIS();
|
||||
}
|
||||
// Important! Unlock here otherwise SetCurrentImage will deadlock with
|
||||
// our lock if we have a RemoteImage.
|
||||
autoLock.Unlock();
|
||||
#endif
|
||||
container->SetCurrentImage(nsnull);
|
||||
}
|
||||
|
@ -128,6 +128,11 @@ public:
|
||||
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace);
|
||||
|
||||
virtual NPError InitAsyncSurface(NPSize *size, NPImageFormat format,
|
||||
void *initData, NPAsyncSurface *surface);
|
||||
virtual NPError FinalizeAsyncSurface(NPAsyncSurface *surface);
|
||||
virtual void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed);
|
||||
|
||||
//nsIPluginTagInfo interface
|
||||
NS_DECL_NSIPLUGINTAGINFO
|
||||
|
||||
|
@ -52,6 +52,7 @@ using NPError;
|
||||
using NPRemoteWindow;
|
||||
using NPRemoteEvent;
|
||||
using NPRect;
|
||||
using NPImageFormat;
|
||||
using NPNURLVariable;
|
||||
using NPCoordinateSpace;
|
||||
using mozilla::plugins::NativeWindowHandle;
|
||||
@ -59,6 +60,8 @@ using mozilla::gfxSurfaceType;
|
||||
using gfxIntSize;
|
||||
using mozilla::null_t;
|
||||
using mozilla::plugins::WindowsSharedMemoryHandle;
|
||||
using mozilla::plugins::DXGISharedSurfaceHandle;
|
||||
using mozilla::CrossProcessMutexHandle;
|
||||
using SurfaceDescriptorX11;
|
||||
using nsIntRect;
|
||||
using nsTextEvent;
|
||||
@ -84,6 +87,26 @@ union SurfaceDescriptor {
|
||||
null_t;
|
||||
};
|
||||
|
||||
union OptionalShmem {
|
||||
Shmem;
|
||||
null_t;
|
||||
};
|
||||
|
||||
union AsyncSurfaceDescriptor {
|
||||
Shmem;
|
||||
DXGISharedSurfaceHandle;
|
||||
};
|
||||
|
||||
struct NPRemoteAsyncSurface
|
||||
{
|
||||
uint32_t version;
|
||||
gfxIntSize size;
|
||||
NPImageFormat format;
|
||||
uint32_t stride;
|
||||
AsyncSurfaceDescriptor data;
|
||||
uintptr_t hostPtr;
|
||||
};
|
||||
|
||||
rpc protocol PPluginInstance
|
||||
{
|
||||
manager PPluginModule;
|
||||
@ -150,6 +173,8 @@ child:
|
||||
rpc HandleKeyEvent(nsKeyEvent event)
|
||||
returns (bool handled);
|
||||
|
||||
async NPP_DidComposite();
|
||||
|
||||
rpc NPP_Destroy()
|
||||
returns (NPError rv);
|
||||
|
||||
@ -176,7 +201,7 @@ parent:
|
||||
rpc NPN_SetValue_NPPVpluginUsesDOMForCursor(bool useDOMForCursor)
|
||||
returns (NPError result);
|
||||
rpc NPN_SetValue_NPPVpluginDrawingModel(int drawingModel)
|
||||
returns (NPError result);
|
||||
returns (OptionalShmem remoteImageData, CrossProcessMutexHandle mutex, NPError result);
|
||||
rpc NPN_SetValue_NPPVpluginEventModel(int eventModel)
|
||||
returns (NPError result);
|
||||
|
||||
@ -232,6 +257,11 @@ parent:
|
||||
NPCoordinateSpace destSpace)
|
||||
returns (double destX, double destY, bool result);
|
||||
|
||||
async RedrawPlugin();
|
||||
|
||||
rpc NPN_InitAsyncSurface(gfxIntSize size, NPImageFormat format)
|
||||
returns (NPRemoteAsyncSurface surfData, bool result);
|
||||
|
||||
// Send notification that a plugin tried to negotiate Carbon NPAPI so that
|
||||
// users can be notified that restarting the browser in i386 mode may allow
|
||||
// them to use the plugin.
|
||||
|
@ -87,7 +87,7 @@ child:
|
||||
rpc NP_GetEntryPoints()
|
||||
returns (NPError rv);
|
||||
|
||||
rpc NP_Initialize()
|
||||
rpc NP_Initialize(uint32_t aFlags)
|
||||
returns (NPError rv);
|
||||
|
||||
rpc PPluginInstance(nsCString aMimeType,
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "PluginProcessChild.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxContext.h"
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#ifdef MOZ_X11
|
||||
#include "gfxXlibSurface.h"
|
||||
#endif
|
||||
@ -74,6 +75,7 @@ using mozilla::gfx::SharedDIBSurface;
|
||||
using namespace mozilla;
|
||||
using mozilla::ipc::ProcessChild;
|
||||
using namespace mozilla::plugins;
|
||||
using namespace std;
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK2
|
||||
|
||||
@ -131,6 +133,10 @@ struct RunnableMethodTraits<PluginInstanceChild>
|
||||
|
||||
PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface)
|
||||
: mPluginIface(aPluginIface)
|
||||
, mDrawingModel(kDefaultDrawingModel)
|
||||
, mCurrentAsyncSurface(0)
|
||||
, mAsyncInvalidateMutex("PluginInstanceChild::mAsyncInvalidateMutex")
|
||||
, mAsyncInvalidateTask(0)
|
||||
, mCachedWindowActor(nsnull)
|
||||
, mCachedElementActor(nsnull)
|
||||
#if defined(OS_WIN)
|
||||
@ -149,7 +155,6 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface)
|
||||
#endif
|
||||
, mShColorSpace(nsnull)
|
||||
, mShContext(nsnull)
|
||||
, mDrawingModel(NPDrawingModelCoreGraphics)
|
||||
, mCGLayer(nsnull)
|
||||
, mCurrentEvent(nsnull)
|
||||
#endif
|
||||
@ -174,6 +179,7 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface)
|
||||
memset(&mWindow, 0, sizeof(mWindow));
|
||||
mData.ndata = (void*) this;
|
||||
mData.pdata = nsnull;
|
||||
mAsyncBitmaps.Init();
|
||||
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
mWindow.ws_info = &mWsInfo;
|
||||
memset(&mWsInfo, 0, sizeof(mWsInfo));
|
||||
@ -414,6 +420,16 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
|
||||
#endif
|
||||
}
|
||||
|
||||
case NPNVsupportsAsyncBitmapSurfaceBool: {
|
||||
#ifdef XP_WIN
|
||||
*((NPBool*)aValue) = PluginModuleChild::current()->AsyncDrawingAllowed();
|
||||
#else
|
||||
// We do not support non-windows yet.
|
||||
*((NPBool*)aValue) = false;
|
||||
#endif
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
case NPNVsupportsCoreGraphicsBool: {
|
||||
*((NPBool*)aValue) = true;
|
||||
@ -519,18 +535,35 @@ PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
case NPPVpluginDrawingModel: {
|
||||
NPError rv;
|
||||
int drawingModel = (int16) (intptr_t) aValue;
|
||||
|
||||
if (!CallNPN_SetValue_NPPVpluginDrawingModel(drawingModel, &rv))
|
||||
if (!PluginModuleChild::current()->AsyncDrawingAllowed() &&
|
||||
IsDrawingModelAsync(drawingModel)) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
CrossProcessMutexHandle handle;
|
||||
OptionalShmem optionalShmem;
|
||||
if (!CallNPN_SetValue_NPPVpluginDrawingModel(drawingModel, &optionalShmem, &handle, &rv))
|
||||
return NPERR_GENERIC_ERROR;
|
||||
|
||||
if (drawingModel == NPDrawingModelAsyncBitmapSurface) {
|
||||
if (optionalShmem.type() != OptionalShmem::TShmem) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
mRemoteImageDataShmem = optionalShmem.get_Shmem();
|
||||
mRemoteImageData = mRemoteImageDataShmem.get<RemoteImageData>();
|
||||
mRemoteImageDataMutex = new CrossProcessMutex(handle);
|
||||
}
|
||||
mDrawingModel = drawingModel;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if (drawingModel == NPDrawingModelCoreAnimation) {
|
||||
mCARefreshTimer = ScheduleTimer(DEFAULT_REFRESH_MS, true, CAUpdate);
|
||||
}
|
||||
#endif
|
||||
|
||||
PLUGIN_LOG_DEBUG((" Plugin requested drawing model id #%i\n",
|
||||
mDrawingModel));
|
||||
@ -538,6 +571,7 @@ PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
case NPPVpluginEventModel: {
|
||||
NPError rv;
|
||||
int eventModel = (int16) (intptr_t) aValue;
|
||||
@ -2061,6 +2095,15 @@ PluginInstanceChild::AnswerUpdateWindow()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::RecvNPP_DidComposite()
|
||||
{
|
||||
if (mPluginIface->didComposite) {
|
||||
mPluginIface->didComposite(GetNPP());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PPluginScriptableObjectChild*
|
||||
PluginInstanceChild::AllocPPluginScriptableObject()
|
||||
{
|
||||
@ -2314,6 +2357,172 @@ PluginInstanceChild::NPN_URLRedirectResponse(void* notifyData, NPBool allow)
|
||||
NS_ASSERTION(false, "Couldn't find stream for redirect response!");
|
||||
}
|
||||
|
||||
NPError
|
||||
PluginInstanceChild::DeallocateAsyncBitmapSurface(NPAsyncSurface *aSurface)
|
||||
{
|
||||
AsyncBitmapData* data;
|
||||
|
||||
if (!mAsyncBitmaps.Get(aSurface, &data)) {
|
||||
return NPERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
DeallocShmem(data->mShmem);
|
||||
aSurface->bitmap.data = nsnull;
|
||||
|
||||
mAsyncBitmaps.Remove(aSurface);
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::IsAsyncDrawing()
|
||||
{
|
||||
return IsDrawingModelAsync(mDrawingModel);
|
||||
}
|
||||
|
||||
NPError
|
||||
PluginInstanceChild::NPN_InitAsyncSurface(NPSize *size, NPImageFormat format,
|
||||
void *initData, NPAsyncSurface *surface)
|
||||
{
|
||||
AssertPluginThread();
|
||||
|
||||
surface->bitmap.data = NULL;
|
||||
|
||||
if (!IsAsyncDrawing()) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
switch (mDrawingModel) {
|
||||
case NPDrawingModelAsyncBitmapSurface: {
|
||||
if (mAsyncBitmaps.Get(surface, nsnull)) {
|
||||
return NPERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (size->width < 0 || size->height < 0) {
|
||||
return NPERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
||||
bool result;
|
||||
NPRemoteAsyncSurface remote;
|
||||
|
||||
if (!CallNPN_InitAsyncSurface(gfxIntSize(size->width, size->height), format, &remote, &result) || !result) {
|
||||
return NPERR_OUT_OF_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
NS_ABORT_IF_FALSE(remote.data().get_Shmem().IsWritable(),
|
||||
"Failed to create writable shared memory.");
|
||||
|
||||
AsyncBitmapData *data = new AsyncBitmapData;
|
||||
mAsyncBitmaps.Put(surface, data);
|
||||
|
||||
data->mRemotePtr = (void*)remote.hostPtr();
|
||||
data->mShmem = remote.data().get_Shmem();
|
||||
|
||||
surface->bitmap.data = data->mShmem.get<unsigned char>();
|
||||
surface->bitmap.stride = remote.stride();
|
||||
surface->format = remote.format();
|
||||
surface->size.width = remote.size().width;
|
||||
surface->size.height = remote.size().height;
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
NPError
|
||||
PluginInstanceChild::NPN_FinalizeAsyncSurface(NPAsyncSurface *surface)
|
||||
{
|
||||
AssertPluginThread();
|
||||
|
||||
if (!IsAsyncDrawing()) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
switch (mDrawingModel) {
|
||||
case NPDrawingModelAsyncBitmapSurface: {
|
||||
AsyncBitmapData *bitmapData;
|
||||
|
||||
if (!mAsyncBitmaps.Get(surface, &bitmapData)) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
{
|
||||
CrossProcessMutexAutoLock autoLock(*mRemoteImageDataMutex);
|
||||
RemoteImageData *data = mRemoteImageData;
|
||||
if (data->mBitmap.mData == bitmapData->mRemotePtr) {
|
||||
data->mBitmap.mData = NULL;
|
||||
data->mSize = gfxIntSize(0, 0);
|
||||
data->mWasUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
return DeallocateAsyncBitmapSurface(surface);
|
||||
}
|
||||
}
|
||||
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::NPN_SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed)
|
||||
{
|
||||
if (!IsAsyncDrawing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RemoteImageData *data = mRemoteImageData;
|
||||
|
||||
if (!surface) {
|
||||
CrossProcessMutexAutoLock autoLock(*mRemoteImageDataMutex);
|
||||
data->mBitmap.mData = NULL;
|
||||
data->mSize = gfxIntSize(0, 0);
|
||||
data->mWasUpdated = true;
|
||||
} else {
|
||||
switch (mDrawingModel) {
|
||||
case NPDrawingModelAsyncBitmapSurface:
|
||||
{
|
||||
AsyncBitmapData *bitmapData;
|
||||
|
||||
if (!mAsyncBitmaps.Get(surface, &bitmapData)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CrossProcessMutexAutoLock autoLock(*mRemoteImageDataMutex);
|
||||
data->mBitmap.mData = (unsigned char*)bitmapData->mRemotePtr;
|
||||
data->mSize = gfxIntSize(surface->size.width, surface->size.height);
|
||||
data->mFormat = surface->format == NPImageFormatBGRX32 ?
|
||||
RemoteImageData::BGRX32 : RemoteImageData::BGRA32;
|
||||
data->mBitmap.mStride = surface->bitmap.stride;
|
||||
data->mWasUpdated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock autoLock(mAsyncInvalidateMutex);
|
||||
if (!mAsyncInvalidateTask) {
|
||||
mAsyncInvalidateTask =
|
||||
NewRunnableMethod<PluginInstanceChild, void (PluginInstanceChild::*)()>
|
||||
(this, &PluginInstanceChild::DoAsyncRedraw);
|
||||
ProcessChild::message_loop()->PostTask(FROM_HERE, mAsyncInvalidateTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::DoAsyncRedraw()
|
||||
{
|
||||
{
|
||||
MutexAutoLock autoLock(mAsyncInvalidateMutex);
|
||||
mAsyncInvalidateTask = NULL;
|
||||
}
|
||||
|
||||
SendRedrawPlugin();
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::RecvAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
||||
const NPRemoteWindow& aWindow)
|
||||
@ -3665,6 +3874,16 @@ PluginInstanceChild::ClearAllSurfaces()
|
||||
#endif
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
PluginInstanceChild::DeleteSurface(NPAsyncSurface* surf, nsAutoPtr<AsyncBitmapData> &data, void* userArg)
|
||||
{
|
||||
PluginInstanceChild *inst = static_cast<PluginInstanceChild*>(userArg);
|
||||
|
||||
inst->DeallocShmem(data->mShmem);
|
||||
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
||||
{
|
||||
@ -3705,6 +3924,13 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
||||
mCurrentAsyncSetWindowTask->Cancel();
|
||||
mCurrentAsyncSetWindowTask = nsnull;
|
||||
}
|
||||
{
|
||||
MutexAutoLock autoLock(mAsyncInvalidateMutex);
|
||||
if (mAsyncInvalidateTask) {
|
||||
mAsyncInvalidateTask->Cancel();
|
||||
mAsyncInvalidateTask = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
ClearAllSurfaces();
|
||||
|
||||
@ -3733,6 +3959,11 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
||||
mPendingAsyncCalls[i]->Cancel();
|
||||
|
||||
mPendingAsyncCalls.Clear();
|
||||
|
||||
if (mAsyncBitmaps.Count()) {
|
||||
NS_ERROR("Not all AsyncBitmaps were finalized by a plugin!");
|
||||
mAsyncBitmaps.Enumerate(DeleteSurface, this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -43,6 +43,8 @@
|
||||
#include "mozilla/plugins/PluginScriptableObjectChild.h"
|
||||
#include "mozilla/plugins/StreamNotifyChild.h"
|
||||
#include "mozilla/plugins/PPluginSurfaceChild.h"
|
||||
#include "mozilla/ipc/CrossProcessMutex.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#if defined(OS_WIN)
|
||||
#include "mozilla/gfx/SharedDIBWin.h"
|
||||
#elif defined(MOZ_WIDGET_COCOA)
|
||||
@ -63,7 +65,14 @@ using namespace mozilla::plugins::PluginUtilsOSX;
|
||||
#include "mozilla/PaintTracker.h"
|
||||
#include "gfxASurface.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace layers {
|
||||
struct RemoteImageData;
|
||||
}
|
||||
|
||||
namespace plugins {
|
||||
|
||||
class PBrowserStreamChild;
|
||||
@ -209,6 +218,9 @@ protected:
|
||||
virtual bool
|
||||
AnswerUpdateWindow();
|
||||
|
||||
virtual bool
|
||||
RecvNPP_DidComposite();
|
||||
|
||||
public:
|
||||
PluginInstanceChild(const NPPluginFuncs* aPluginIface);
|
||||
|
||||
@ -249,6 +261,13 @@ public:
|
||||
|
||||
void NPN_URLRedirectResponse(void* notifyData, NPBool allow);
|
||||
|
||||
NPError NPN_InitAsyncSurface(NPSize *size, NPImageFormat format,
|
||||
void *initData, NPAsyncSurface *surface);
|
||||
NPError NPN_FinalizeAsyncSurface(NPAsyncSurface *surface);
|
||||
|
||||
void NPN_SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed);
|
||||
|
||||
void DoAsyncRedraw();
|
||||
private:
|
||||
friend class PluginModuleChild;
|
||||
|
||||
@ -256,6 +275,10 @@ private:
|
||||
InternalGetNPObjectForValue(NPNVariable aValue,
|
||||
NPObject** aObject);
|
||||
|
||||
bool IsAsyncDrawing();
|
||||
|
||||
NPError DeallocateAsyncBitmapSurface(NPAsyncSurface *aSurface);
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvUpdateBackground(const SurfaceDescriptor& aBackground,
|
||||
const nsIntRect& aRect);
|
||||
@ -360,10 +383,23 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
const NPPluginFuncs* mPluginIface;
|
||||
NPP_t mData;
|
||||
NPWindow mWindow;
|
||||
int16_t mDrawingModel;
|
||||
NPAsyncSurface* mCurrentAsyncSurface;
|
||||
struct AsyncBitmapData {
|
||||
void *mRemotePtr;
|
||||
Shmem mShmem;
|
||||
};
|
||||
|
||||
static PLDHashOperator DeleteSurface(NPAsyncSurface* surf, nsAutoPtr<AsyncBitmapData> &data, void* userArg);
|
||||
nsClassHashtable<nsPtrHashKey<NPAsyncSurface>, AsyncBitmapData> mAsyncBitmaps;
|
||||
Shmem mRemoteImageDataShmem;
|
||||
mozilla::layers::RemoteImageData *mRemoteImageData;
|
||||
nsAutoPtr<CrossProcessMutex> mRemoteImageDataMutex;
|
||||
mozilla::Mutex mAsyncInvalidateMutex;
|
||||
CancelableTask *mAsyncInvalidateTask;
|
||||
|
||||
// Cached scriptable actors to avoid IPC churn
|
||||
PluginScriptableObjectChild* mCachedWindowActor;
|
||||
@ -426,7 +462,6 @@ private:
|
||||
#endif
|
||||
CGColorSpaceRef mShColorSpace;
|
||||
CGContextRef mShContext;
|
||||
int16_t mDrawingModel;
|
||||
nsCARenderer mCARenderer;
|
||||
void *mCGLayer;
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "gfxContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxSharedImageSurface.h"
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#ifdef MOZ_X11
|
||||
#include "gfxXlibSurface.h"
|
||||
#endif
|
||||
@ -91,6 +92,7 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
|
||||
, mNPP(npp)
|
||||
, mNPNIface(npniface)
|
||||
, mWindowType(NPWindowTypeWindow)
|
||||
, mDrawingModel(kDefaultDrawingModel)
|
||||
#if defined(OS_WIN)
|
||||
, mPluginHWND(NULL)
|
||||
, mPluginWndProc(NULL)
|
||||
@ -100,7 +102,6 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
|
||||
, mShWidth(0)
|
||||
, mShHeight(0)
|
||||
, mShColorSpace(nsnull)
|
||||
, mDrawingModel(NPDrawingModelCoreGraphics)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@ -121,6 +122,16 @@ PluginInstanceParent::~PluginInstanceParent()
|
||||
if (mShColorSpace)
|
||||
::CGColorSpaceRelease(mShColorSpace);
|
||||
#endif
|
||||
if (mRemoteImageDataShmem.IsWritable()) {
|
||||
ImageContainer *container =
|
||||
GetImageContainer();
|
||||
|
||||
if (container) {
|
||||
container->SetRemoteImageData(nsnull, nsnull);
|
||||
container->SetCompositionNotifySink(nsnull);
|
||||
DeallocShmem(mRemoteImageDataShmem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@ -281,6 +292,12 @@ PluginInstanceParent::InternalGetValueForNPObject(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceParent::IsAsyncDrawing()
|
||||
{
|
||||
return IsDrawingModelAsync(mDrawingModel);
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceParent::AnswerNPN_GetValue_NPNVWindowNPObject(
|
||||
PPluginScriptableObjectParent** aValue,
|
||||
@ -349,9 +366,20 @@ PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginUsesDOMForCursor(
|
||||
return true;
|
||||
}
|
||||
|
||||
class NotificationSink : public CompositionNotifySink
|
||||
{
|
||||
public:
|
||||
NotificationSink(PluginInstanceParent *aInstance) : mInstance(aInstance)
|
||||
{ }
|
||||
|
||||
virtual void DidComposite() { mInstance->DidComposite(); }
|
||||
private:
|
||||
PluginInstanceParent *mInstance;
|
||||
};
|
||||
|
||||
bool
|
||||
PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginDrawingModel(
|
||||
const int& drawingModel, NPError* result)
|
||||
const int& drawingModel, OptionalShmem *shmem, CrossProcessMutexHandle *mutex, NPError* result)
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
if (drawingModel == NPDrawingModelCoreAnimation ||
|
||||
@ -362,16 +390,68 @@ PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginDrawingModel(
|
||||
mDrawingModel = drawingModel;
|
||||
*result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
|
||||
(void*)NPDrawingModelCoreGraphics);
|
||||
} else {
|
||||
*shmem = null_t();
|
||||
} else
|
||||
#endif
|
||||
if (drawingModel == NPDrawingModelAsyncBitmapSurface) {
|
||||
ImageContainer *container = GetImageContainer();
|
||||
if (!container) {
|
||||
*result = NPERR_GENERIC_ERROR;
|
||||
return true;
|
||||
}
|
||||
|
||||
mDrawingModel = drawingModel;
|
||||
*result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
|
||||
(void*)drawingModel);
|
||||
(void*)drawingModel);
|
||||
|
||||
|
||||
if (*result != NPERR_NO_ERROR) {
|
||||
return true;
|
||||
}
|
||||
|
||||
AllocUnsafeShmem(sizeof(RemoteImageData), SharedMemory::TYPE_BASIC, &mRemoteImageDataShmem);
|
||||
|
||||
*shmem = mRemoteImageDataShmem;
|
||||
|
||||
mRemoteImageDataMutex = new CrossProcessMutex("PluginInstanceParent.mRemoteImageDataMutex");
|
||||
|
||||
*mutex = mRemoteImageDataMutex->ShareToProcess(OtherProcess());
|
||||
container->SetRemoteImageData(mRemoteImageDataShmem.get<RemoteImageData>(), mRemoteImageDataMutex);
|
||||
|
||||
mNotifySink = new NotificationSink(this);
|
||||
|
||||
container->SetCompositionNotifySink(mNotifySink);
|
||||
} else if (drawingModel == NPDrawingModelSyncWin ||
|
||||
#ifdef XP_MACOSX
|
||||
#ifndef NP_NO_QUICKDRAW
|
||||
drawingModel == NPDrawingModelQuickDraw ||
|
||||
#endif
|
||||
drawingModel == NPDrawingModelOpenGL ||
|
||||
drawingModel == NPDrawingModelCoreGraphics ||
|
||||
#endif
|
||||
drawingModel == NPDrawingModelSyncX) {
|
||||
*shmem = null_t();
|
||||
|
||||
ImageContainer *container = GetImageContainer();
|
||||
if (!container) {
|
||||
*result = NPERR_GENERIC_ERROR;
|
||||
return true;
|
||||
}
|
||||
|
||||
mDrawingModel = drawingModel;
|
||||
*result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
|
||||
(void*)drawingModel);
|
||||
|
||||
if (mRemoteImageDataShmem.IsWritable()) {
|
||||
container->SetRemoteImageData(nsnull, nsnull);
|
||||
container->SetCompositionNotifySink(nsnull);
|
||||
DeallocShmem(mRemoteImageDataShmem);
|
||||
mRemoteImageDataMutex = NULL;
|
||||
}
|
||||
} else {
|
||||
*result = NPERR_GENERIC_ERROR;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
*result = NPERR_GENERIC_ERROR;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
@ -647,6 +727,12 @@ PluginInstanceParent::GetImageContainer(ImageContainer** aContainer)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (IsAsyncDrawing()) {
|
||||
NS_IF_ADDREF(container);
|
||||
*aContainer = container;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<Image> image;
|
||||
image = container->CreateImage(&format, 1);
|
||||
if (!image) {
|
||||
@ -1101,6 +1187,12 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
|
||||
|
||||
#if defined(OS_WIN)
|
||||
if (mWindowType == NPWindowTypeDrawable) {
|
||||
if (IsAsyncDrawing()) {
|
||||
if (npevent->event == WM_PAINT || npevent->event == DoublePassRenderingEvent()) {
|
||||
// This plugin maintains its own async drawing.
|
||||
return handled;
|
||||
}
|
||||
}
|
||||
if (DoublePassRenderingEvent() == npevent->event) {
|
||||
CallPaint(npremoteevent, &handled);
|
||||
return handled;
|
||||
@ -1602,15 +1694,58 @@ PluginInstanceParent::AnswerNPN_ConvertPoint(const double& sourceX,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceParent::AnswerNPN_InitAsyncSurface(const gfxIntSize& size,
|
||||
const NPImageFormat& format,
|
||||
NPRemoteAsyncSurface* surfData,
|
||||
bool* result)
|
||||
{
|
||||
if (!IsAsyncDrawing()) {
|
||||
*result = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (mDrawingModel) {
|
||||
case NPDrawingModelAsyncBitmapSurface: {
|
||||
Shmem sharedMem;
|
||||
if (!AllocUnsafeShmem(size.width * size.height * 4, SharedMemory::TYPE_BASIC, &sharedMem)) {
|
||||
*result = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
surfData->size() = size;
|
||||
surfData->hostPtr() = (uintptr_t)sharedMem.get<unsigned char>();
|
||||
surfData->stride() = size.width * 4;
|
||||
surfData->format() = format;
|
||||
surfData->data() = sharedMem;
|
||||
*result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceParent::RecvRedrawPlugin()
|
||||
{
|
||||
nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata);
|
||||
if (!inst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
inst->RedrawPlugin();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceParent::RecvNegotiatedCarbon()
|
||||
{
|
||||
nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata);
|
||||
if (!inst) {
|
||||
return false;
|
||||
}
|
||||
inst->CarbonNPAPIFailure();
|
||||
return true;
|
||||
nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata);
|
||||
if (!inst) {
|
||||
return false;
|
||||
}
|
||||
inst->CarbonNPAPIFailure();
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
@ -144,7 +144,9 @@ public:
|
||||
NPError* result);
|
||||
virtual bool
|
||||
AnswerNPN_SetValue_NPPVpluginDrawingModel(const int& drawingModel,
|
||||
NPError* result);
|
||||
OptionalShmem *remoteImageData,
|
||||
CrossProcessMutexHandle *mutex,
|
||||
NPError* result);
|
||||
virtual bool
|
||||
AnswerNPN_SetValue_NPPVpluginEventModel(const int& eventModel,
|
||||
NPError* result);
|
||||
@ -229,6 +231,15 @@ public:
|
||||
double *destY,
|
||||
bool *result);
|
||||
|
||||
virtual bool
|
||||
AnswerNPN_InitAsyncSurface(const gfxIntSize& size,
|
||||
const NPImageFormat& format,
|
||||
NPRemoteAsyncSurface* surfData,
|
||||
bool* result);
|
||||
|
||||
virtual bool
|
||||
RecvRedrawPlugin();
|
||||
|
||||
NS_OVERRIDE virtual bool
|
||||
RecvNegotiatedCarbon();
|
||||
|
||||
@ -294,6 +305,8 @@ public:
|
||||
nsresult HandleGUIEvent(const nsGUIEvent& anEvent, bool* handled);
|
||||
#endif
|
||||
|
||||
void DidComposite() { SendNPP_DidComposite(); }
|
||||
|
||||
private:
|
||||
// Create an appropriate platform surface for a background of size
|
||||
// |aSize|. Return true if successful.
|
||||
@ -316,11 +329,17 @@ private:
|
||||
PPluginScriptableObjectParent** aValue,
|
||||
NPError* aResult);
|
||||
|
||||
bool IsAsyncDrawing();
|
||||
|
||||
private:
|
||||
PluginModuleParent* mParent;
|
||||
NPP mNPP;
|
||||
const NPNetscapeFuncs* mNPNIface;
|
||||
NPWindowType mWindowType;
|
||||
Shmem mRemoteImageDataShmem;
|
||||
nsAutoPtr<CrossProcessMutex> mRemoteImageDataMutex;
|
||||
int16_t mDrawingModel;
|
||||
nsAutoPtr<mozilla::layers::CompositionNotifySink> mNotifySink;
|
||||
|
||||
nsDataHashtable<nsVoidPtrHashKey, PluginScriptableObjectParent*> mScriptableObjects;
|
||||
|
||||
@ -351,7 +370,6 @@ private:
|
||||
uint16_t mShWidth;
|
||||
uint16_t mShHeight;
|
||||
CGColorSpaceRef mShColorSpace;
|
||||
int16_t mDrawingModel;
|
||||
nsRefPtr<nsIOSurface> mIOSurface;
|
||||
nsRefPtr<nsIOSurface> mFrontIOSurface;
|
||||
#endif // definied(MOZ_WIDGET_COCOA)
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "base/message_loop.h"
|
||||
|
||||
#include "mozilla/ipc/RPCChannel.h"
|
||||
#include "mozilla/ipc/CrossProcessMutex.h"
|
||||
#include "gfxipc/ShadowLayerUtils.h"
|
||||
|
||||
#include "npapi.h"
|
||||
@ -86,6 +87,17 @@ UnmungePluginDsoPath(const std::string& munged);
|
||||
|
||||
extern PRLogModuleInfo* gPluginLog;
|
||||
|
||||
const uint32_t kAllowAsyncDrawing = 0x1;
|
||||
|
||||
inline bool IsDrawingModelAsync(int16_t aModel) {
|
||||
return aModel == NPDrawingModelAsyncBitmapSurface
|
||||
#ifdef XP_WIN
|
||||
|| aModel == NPDrawingModelAsyncWindowsDXGISurface
|
||||
|| aModel == NPDrawingModelAsyncWindowsDX9ExSurface
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define FULLFUNCTION __FUNCSIG__
|
||||
#elif (__GNUC__ >= 4)
|
||||
@ -142,8 +154,10 @@ typedef intptr_t NativeWindowHandle; // never actually used, will always be 0
|
||||
|
||||
#ifdef XP_WIN
|
||||
typedef base::SharedMemoryHandle WindowsSharedMemoryHandle;
|
||||
typedef HANDLE DXGISharedSurfaceHandle;
|
||||
#else
|
||||
typedef mozilla::null_t WindowsSharedMemoryHandle;
|
||||
typedef mozilla::null_t DXGISharedSurfaceHandle;
|
||||
#endif
|
||||
|
||||
// XXX maybe not the best place for these. better one?
|
||||
@ -354,6 +368,32 @@ struct ParamTraits<NPWindowType>
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<NPImageFormat>
|
||||
{
|
||||
typedef NPImageFormat paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
aMsg->WriteInt16(int16(aParam));
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
int16 result;
|
||||
if (aMsg->ReadInt16(aIter, &result)) {
|
||||
*aResult = paramType(result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
aLog->append(StringPrintf(L"%d", int16(aParam)));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::NPRemoteWindow>
|
||||
{
|
||||
|
@ -975,6 +975,17 @@ _convertpoint(NPP instance,
|
||||
static void NP_CALLBACK
|
||||
_urlredirectresponse(NPP instance, void* notifyData, NPBool allow);
|
||||
|
||||
static NPError NP_CALLBACK
|
||||
_initasyncsurface(NPP instance, NPSize *size,
|
||||
NPImageFormat format, void *initData,
|
||||
NPAsyncSurface *surface);
|
||||
|
||||
static NPError NP_CALLBACK
|
||||
_finalizeasyncsurface(NPP instance, NPAsyncSurface *surface);
|
||||
|
||||
static void NP_CALLBACK
|
||||
_setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed);
|
||||
|
||||
} /* namespace child */
|
||||
} /* namespace plugins */
|
||||
} /* namespace mozilla */
|
||||
@ -1036,7 +1047,10 @@ const NPNetscapeFuncs PluginModuleChild::sBrowserFuncs = {
|
||||
mozilla::plugins::child::_convertpoint,
|
||||
NULL, // handleevent, unimplemented
|
||||
NULL, // unfocusinstance, unimplemented
|
||||
mozilla::plugins::child::_urlredirectresponse
|
||||
mozilla::plugins::child::_urlredirectresponse,
|
||||
mozilla::plugins::child::_initasyncsurface,
|
||||
mozilla::plugins::child::_finalizeasyncsurface,
|
||||
mozilla::plugins::child::_setcurrentasyncsurface
|
||||
};
|
||||
|
||||
PluginInstanceChild*
|
||||
@ -1809,6 +1823,26 @@ _urlredirectresponse(NPP instance, void* notifyData, NPBool allow)
|
||||
InstCast(instance)->NPN_URLRedirectResponse(notifyData, allow);
|
||||
}
|
||||
|
||||
NPError NP_CALLBACK
|
||||
_initasyncsurface(NPP instance, NPSize *size,
|
||||
NPImageFormat format, void *initData,
|
||||
NPAsyncSurface *surface)
|
||||
{
|
||||
return InstCast(instance)->NPN_InitAsyncSurface(size, format, initData, surface);
|
||||
}
|
||||
|
||||
NPError NP_CALLBACK
|
||||
_finalizeasyncsurface(NPP instance, NPAsyncSurface *surface)
|
||||
{
|
||||
return InstCast(instance)->NPN_FinalizeAsyncSurface(surface);
|
||||
}
|
||||
|
||||
void NP_CALLBACK
|
||||
_setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed)
|
||||
{
|
||||
InstCast(instance)->NPN_SetCurrentAsyncSurface(surface, changed);
|
||||
}
|
||||
|
||||
} /* namespace child */
|
||||
} /* namespace plugins */
|
||||
} /* namespace mozilla */
|
||||
@ -1832,11 +1866,13 @@ PluginModuleChild::AnswerNP_GetEntryPoints(NPError* _retval)
|
||||
}
|
||||
|
||||
bool
|
||||
PluginModuleChild::AnswerNP_Initialize(NPError* _retval)
|
||||
PluginModuleChild::AnswerNP_Initialize(const uint32_t& aFlags, NPError* _retval)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_METHOD;
|
||||
AssertPluginThread();
|
||||
|
||||
mAsyncDrawingAllowed = aFlags & kAllowAsyncDrawing;
|
||||
|
||||
#ifdef OS_WIN
|
||||
SetEventHooks();
|
||||
#endif
|
||||
|
@ -123,7 +123,7 @@ protected:
|
||||
|
||||
// Implement the PPluginModuleChild interface
|
||||
virtual bool AnswerNP_GetEntryPoints(NPError* rv);
|
||||
virtual bool AnswerNP_Initialize(NPError* rv);
|
||||
virtual bool AnswerNP_Initialize(const uint32_t& aFlags, NPError* rv);
|
||||
|
||||
virtual PPluginIdentifierChild*
|
||||
AllocPPluginIdentifier(const nsCString& aString,
|
||||
@ -228,6 +228,8 @@ public:
|
||||
bool NPObjectIsRegistered(NPObject* aObject);
|
||||
#endif
|
||||
|
||||
bool AsyncDrawingAllowed() { return mAsyncDrawingAllowed; }
|
||||
|
||||
/**
|
||||
* The child implementation of NPN_CreateObject.
|
||||
*/
|
||||
@ -357,6 +359,7 @@ private:
|
||||
nsCString mPluginFilename; // UTF8
|
||||
nsCString mUserAgent;
|
||||
int mQuirks;
|
||||
bool mAsyncDrawingAllowed;
|
||||
|
||||
// we get this from the plugin
|
||||
NP_PLUGINSHUTDOWN mShutdownFunc;
|
||||
|
@ -749,7 +749,12 @@ PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!CallNP_Initialize(error)) {
|
||||
uint32_t flags = 0;
|
||||
if (mozilla::Preferences::GetBool("plugin.allow.asyncdrawing", false)) {
|
||||
flags |= kAllowAsyncDrawing;
|
||||
}
|
||||
|
||||
if (!CallNP_Initialize(flags, error)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else if (*error != NPERR_NO_ERROR) {
|
||||
@ -773,7 +778,12 @@ PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!CallNP_Initialize(error))
|
||||
uint32_t flags = 0;
|
||||
if (mozilla::Preferences::GetBool("plugin.allow.asyncdrawing", false)) {
|
||||
flags |= kAllowAsyncDrawing;
|
||||
}
|
||||
|
||||
if (!CallNP_Initialize(flags, error))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
#if defined XP_WIN
|
||||
|
14
dom/plugins/test/reftest/plugin-async-update-ref.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html><head>
|
||||
<title>div boxes</title>
|
||||
<style>
|
||||
div {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="background-color: #00FF00;"></div> <!-- green -->
|
||||
</body></html>
|
10
dom/plugins/test/reftest/plugin-asyncbitmap-sanity.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!doctype html>
|
||||
<html><head>
|
||||
<title>Plugin boxes</title>
|
||||
</head>
|
||||
<body>
|
||||
<embed type="application/x-test" width="400" height="400" drawmode="solid" color="FFFF0000" asyncmodel="bitmap"></embed> <!-- red -->
|
||||
<embed type="application/x-test" width="400" height="400" drawmode="solid" color="FF00FF00" asyncmodel="bitmap"></embed> <!-- green -->
|
||||
<embed type="application/x-test" width="400" height="400" drawmode="solid" color="FF0000FF" asyncmodel="bitmap"></embed> <!-- blue -->
|
||||
<embed type="application/x-test" width="400" height="400" drawmode="solid" color="FF999999" asyncmodel="bitmap"></embed> <!-- gray -->
|
||||
</body></html>
|
24
dom/plugins/test/reftest/plugin-asyncbitmap-update.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!doctype html>
|
||||
<html class="reftest-wait"><head>
|
||||
<title>Plugin boxes</title>
|
||||
</head>
|
||||
<body>
|
||||
<embed type="application/x-test" width="400" height="400" drawmode="solid" color="FFFF0000" id="plugin" asyncmodel="bitmap"></embed> <!-- red -->
|
||||
<script>
|
||||
var prevPaintCount = 0;
|
||||
function doTestWait() {
|
||||
if (window.mozPaintCount != prevPaintCount) {
|
||||
document.documentElement.removeAttribute('class');
|
||||
} else {
|
||||
setTimeout(doTestWait, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
prevPaintCount = window.mozPaintCount;
|
||||
document.getElementById("plugin").setColor("FF00FF00");
|
||||
setTimeout(doTestWait, 0);
|
||||
}
|
||||
window.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
</script>
|
||||
</body></html>
|
@ -1,6 +1,9 @@
|
||||
# basic sanity checking
|
||||
random-if(!haveTestPlugin) != plugin-sanity.html about:blank
|
||||
random-if(!haveTestPlugin) != plugin-asyncbitmap-sanity.html about:blank
|
||||
fails-if(!haveTestPlugin) == plugin-sanity.html div-sanity.html
|
||||
fails-if(!haveTestPlugin) == plugin-asyncbitmap-sanity.html div-sanity.html
|
||||
skip-if(!haveTestPlugin) == plugin-asyncbitmap-update.html plugin-async-update-ref.html
|
||||
fails-if(!haveTestPlugin) == plugin-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) == plugin-alpha-opacity.html div-alpha-opacity.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == windowless-clipping-1.html windowless-clipping-1-ref.html # bug 631832
|
||||
|
@ -540,6 +540,39 @@ DuplicateNPVariant(NPVariant& aDest, const NPVariant& aSrc)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
drawAsyncBitmapColor(InstanceData* instanceData)
|
||||
{
|
||||
NPP npp = instanceData->npp;
|
||||
|
||||
PRUint32 *pixelData = (PRUint32*)instanceData->backBuffer->bitmap.data;
|
||||
|
||||
PRUint32 rgba = instanceData->scriptableObject->drawColor;
|
||||
|
||||
unsigned char subpixels[4];
|
||||
subpixels[0] = rgba & 0xFF;
|
||||
subpixels[1] = (rgba & 0xFF00) >> 8;
|
||||
subpixels[2] = (rgba & 0xFF0000) >> 16;
|
||||
subpixels[3] = (rgba & 0xFF000000) >> 24;
|
||||
|
||||
subpixels[0] = PRUint8(float(subpixels[3] * subpixels[0]) / 0xFF);
|
||||
subpixels[1] = PRUint8(float(subpixels[3] * subpixels[1]) / 0xFF);
|
||||
subpixels[2] = PRUint8(float(subpixels[3] * subpixels[2]) / 0xFF);
|
||||
PRUint32 premultiplied;
|
||||
memcpy(&premultiplied, subpixels, sizeof(premultiplied));
|
||||
|
||||
for (PRUint32* lastPixel = pixelData + instanceData->backBuffer->size.width * instanceData->backBuffer->size.height;
|
||||
pixelData < lastPixel;
|
||||
++pixelData) {
|
||||
*pixelData = premultiplied;
|
||||
}
|
||||
|
||||
NPN_SetCurrentAsyncSurface(npp, instanceData->backBuffer, NULL);
|
||||
NPAsyncSurface *oldFront = instanceData->frontBuffer;
|
||||
instanceData->frontBuffer = instanceData->backBuffer;
|
||||
instanceData->backBuffer = oldFront;
|
||||
}
|
||||
|
||||
//
|
||||
// function signatures
|
||||
//
|
||||
@ -746,6 +779,9 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
|
||||
instanceData->eventModel = 0;
|
||||
instanceData->closeStream = false;
|
||||
instanceData->wantsAllStreams = false;
|
||||
instanceData->asyncDrawing = AD_NONE;
|
||||
instanceData->frontBuffer = NULL;
|
||||
instanceData->backBuffer = NULL;
|
||||
instance->pdata = instanceData;
|
||||
|
||||
TestNPObject* scriptableObject = (TestNPObject*)NPN_CreateObject(instance, &sNPClass);
|
||||
@ -782,6 +818,13 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
|
||||
requestWindow = true;
|
||||
}
|
||||
}
|
||||
else if (strcmp(argn[i], "asyncmodel") == 0) {
|
||||
if (strcmp(argv[i], "bitmap") == 0) {
|
||||
if (pluginSupportsAsyncBitmapDrawing()) {
|
||||
instanceData->asyncDrawing = AD_BITMAP;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strcmp(argn[i], "streammode") == 0) {
|
||||
if (strcmp(argv[i], "normal") == 0) {
|
||||
instanceData->streamMode = NP_NORMAL;
|
||||
@ -884,6 +927,16 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
|
||||
NPN_SetValue(instance, NPPVpluginTransparentBool, (void*)true);
|
||||
}
|
||||
|
||||
if (instanceData->asyncDrawing == AD_BITMAP) {
|
||||
NPBool supportsAsyncBitmap = false;
|
||||
if ((NPN_GetValue(instance, NPNVsupportsAsyncBitmapSurfaceBool, &supportsAsyncBitmap) == NPERR_NO_ERROR) &&
|
||||
supportsAsyncBitmap) {
|
||||
NPN_SetValue(instance, NPPVpluginDrawingModel, (void*)NPDrawingModelAsyncBitmapSurface);
|
||||
} else {
|
||||
instanceData->asyncDrawing = AD_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
instanceData->lastReportedPrivateModeState = false;
|
||||
instanceData->lastMouseX = instanceData->lastMouseY = -1;
|
||||
instanceData->widthAtLastPaint = -1;
|
||||
@ -969,6 +1022,16 @@ NPP_Destroy(NPP instance, NPSavedData** save)
|
||||
currentrange = nextrange;
|
||||
}
|
||||
|
||||
if (instanceData->frontBuffer) {
|
||||
NPN_SetCurrentAsyncSurface(instance, NULL, NULL);
|
||||
NPN_FinalizeAsyncSurface(instance, instanceData->frontBuffer);
|
||||
NPN_MemFree(instanceData->frontBuffer);
|
||||
}
|
||||
if (instanceData->backBuffer) {
|
||||
NPN_FinalizeAsyncSurface(instance, instanceData->backBuffer);
|
||||
NPN_MemFree(instanceData->backBuffer);
|
||||
}
|
||||
|
||||
pluginInstanceShutdown(instanceData);
|
||||
NPN_ReleaseObject(instanceData->scriptableObject);
|
||||
|
||||
@ -1000,6 +1063,35 @@ NPP_SetWindow(NPP instance, NPWindow* window)
|
||||
if (instanceData->hasWidget && oldWindow != instanceData->window.window) {
|
||||
pluginWidgetInit(instanceData, oldWindow);
|
||||
}
|
||||
|
||||
if (instanceData->asyncDrawing == AD_BITMAP) {
|
||||
if (instanceData->frontBuffer &&
|
||||
instanceData->frontBuffer->size.width == window->width &&
|
||||
instanceData->frontBuffer->size.height == window->height) {
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
if (instanceData->frontBuffer) {
|
||||
NPN_FinalizeAsyncSurface(instance, instanceData->frontBuffer);
|
||||
NPN_MemFree(instanceData->frontBuffer);
|
||||
}
|
||||
if (instanceData->backBuffer) {
|
||||
NPN_FinalizeAsyncSurface(instance, instanceData->backBuffer);
|
||||
NPN_MemFree(instanceData->backBuffer);
|
||||
}
|
||||
instanceData->frontBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface));
|
||||
instanceData->backBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface));
|
||||
|
||||
NPSize size;
|
||||
size.width = window->width;
|
||||
size.height = window->height;
|
||||
|
||||
memcpy(instanceData->backBuffer, instanceData->frontBuffer, sizeof(NPAsyncSurface));
|
||||
|
||||
NPN_InitAsyncSurface(instance, &size, NPImageFormatBGRA32, NULL, instanceData->frontBuffer);
|
||||
NPN_InitAsyncSurface(instance, &size, NPImageFormatBGRA32, NULL, instanceData->backBuffer);
|
||||
|
||||
drawAsyncBitmapColor(instanceData);
|
||||
}
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
@ -1751,6 +1843,25 @@ NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow)
|
||||
return sBrowserFuncs->urlredirectresponse(instance, notifyData, allow);
|
||||
}
|
||||
|
||||
NPError
|
||||
NPN_InitAsyncSurface(NPP instance, NPSize *size, NPImageFormat format,
|
||||
void *initData, NPAsyncSurface *surface)
|
||||
{
|
||||
return sBrowserFuncs->initasyncsurface(instance, size, format, initData, surface);
|
||||
}
|
||||
|
||||
NPError
|
||||
NPN_FinalizeAsyncSurface(NPP instance, NPAsyncSurface *surface)
|
||||
{
|
||||
return sBrowserFuncs->finalizeasyncsurface(instance, surface);
|
||||
}
|
||||
|
||||
void
|
||||
NPN_SetCurrentAsyncSurface(NPP instance, NPAsyncSurface *surface, NPRect *changed)
|
||||
{
|
||||
sBrowserFuncs->setcurrentasyncsurface(instance, surface, changed);
|
||||
}
|
||||
|
||||
//
|
||||
// npruntime object functions
|
||||
//
|
||||
@ -2621,7 +2732,11 @@ setColor(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* r
|
||||
r.top = 0;
|
||||
r.right = id->window.width;
|
||||
r.bottom = id->window.height;
|
||||
NPN_InvalidateRect(npp, &r);
|
||||
if (id->asyncDrawing == AD_NONE) {
|
||||
NPN_InvalidateRect(npp, &r);
|
||||
} else if (id->asyncDrawing == AD_BITMAP) {
|
||||
drawAsyncBitmapColor(id);
|
||||
}
|
||||
|
||||
VOID_TO_NPVARIANT(*result);
|
||||
return true;
|
||||
|
@ -61,6 +61,11 @@ typedef enum {
|
||||
FUNCTION_NPP_WRITE_RPC
|
||||
} TestFunction;
|
||||
|
||||
typedef enum {
|
||||
AD_NONE,
|
||||
AD_BITMAP
|
||||
} AsyncDrawing;
|
||||
|
||||
typedef enum {
|
||||
ACTIVATION_STATE_UNKNOWN,
|
||||
ACTIVATION_STATE_ACTIVATED,
|
||||
@ -140,6 +145,9 @@ typedef struct InstanceData {
|
||||
bool closeStream;
|
||||
std::string lastKeyText;
|
||||
bool wantsAllStreams;
|
||||
AsyncDrawing asyncDrawing;
|
||||
NPAsyncSurface *frontBuffer;
|
||||
NPAsyncSurface *backBuffer;
|
||||
} InstanceData;
|
||||
|
||||
void notifyDidPaint(InstanceData* instanceData);
|
||||
|
@ -49,6 +49,12 @@ pluginSupportsWindowlessMode()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
pluginSupportsAsyncBitmapDrawing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NPError
|
||||
pluginInstanceInit(InstanceData* instanceData)
|
||||
{
|
||||
|
@ -70,6 +70,12 @@ pluginSupportsWindowlessMode()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
pluginSupportsAsyncBitmapDrawing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NPError
|
||||
pluginInstanceInit(InstanceData* instanceData)
|
||||
{
|
||||
|
@ -49,6 +49,12 @@ pluginSupportsWindowlessMode()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
pluginSupportsAsyncBitmapDrawing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NPError
|
||||
pluginInstanceInit(InstanceData* instanceData)
|
||||
{
|
||||
|
@ -47,6 +47,12 @@ pluginSupportsWindowlessMode()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
pluginSupportsAsyncBitmapDrawing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NPError
|
||||
pluginInstanceInit(InstanceData* instanceData)
|
||||
{
|
||||
|
@ -48,6 +48,11 @@ bool pluginSupportsWindowMode();
|
||||
*/
|
||||
bool pluginSupportsWindowlessMode();
|
||||
|
||||
/**
|
||||
* Returns true if the plugin supports async bitmap drawing.
|
||||
*/
|
||||
bool pluginSupportsAsyncBitmapDrawing();
|
||||
|
||||
/**
|
||||
* Initialize the plugin instance. Returning an error here will cause the
|
||||
* plugin instantiation to fail.
|
||||
|
@ -57,6 +57,12 @@ pluginSupportsWindowlessMode()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
pluginSupportsAsyncBitmapDrawing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NPError
|
||||
pluginInstanceInit(InstanceData* instanceData)
|
||||
{
|
||||
|
@ -60,14 +60,22 @@ pluginSupportsWindowlessMode()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
pluginSupportsAsyncBitmapDrawing()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
NPError
|
||||
pluginInstanceInit(InstanceData* instanceData)
|
||||
{
|
||||
NPP npp = instanceData->npp;
|
||||
|
||||
instanceData->platformData = static_cast<PlatformData*>
|
||||
(NPN_MemAlloc(sizeof(PlatformData)));
|
||||
if (!instanceData->platformData)
|
||||
return NPERR_OUT_OF_MEMORY_ERROR;
|
||||
|
||||
|
||||
instanceData->platformData->childWindow = NULL;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
@ -83,6 +91,7 @@ void
|
||||
pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow)
|
||||
{
|
||||
instanceData->window = *newWindow;
|
||||
NPP npp = instanceData->npp;
|
||||
}
|
||||
|
||||
#define CHILD_WIDGET_SIZE 10
|
||||
|
@ -253,6 +253,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
||||
{ (PRFuncPtr*) &mSymbols.fTexParameteri, { "TexParameteri", NULL } },
|
||||
{ (PRFuncPtr*) &mSymbols.fTexParameterf, { "TexParameterf", NULL } },
|
||||
{ (PRFuncPtr*) &mSymbols.fGetString, { "GetString", NULL } },
|
||||
{ (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", NULL } },
|
||||
{ (PRFuncPtr*) &mSymbols.fGetTexParameterfv, { "GetTexParameterfv", NULL } },
|
||||
{ (PRFuncPtr*) &mSymbols.fGetTexParameteriv, { "GetTexParameteriv", NULL } },
|
||||
{ (PRFuncPtr*) &mSymbols.fGetUniformfv, { "GetUniformfv", "GetUniformfvARB", NULL } },
|
||||
@ -494,6 +495,13 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
||||
mInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Load developer symbols, don't fail if we can't find them.
|
||||
SymLoadStruct auxSymbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", NULL } },
|
||||
{ NULL, { NULL } },
|
||||
};
|
||||
LoadSymbols(&auxSymbols[0], trygl, prefix);
|
||||
}
|
||||
|
||||
if (mInitialized) {
|
||||
@ -1598,10 +1606,73 @@ GLContext::MarkDestroyed()
|
||||
mSymbols.Zero();
|
||||
}
|
||||
|
||||
static void SwapRAndBComponents(gfxImageSurface* aSurf)
|
||||
{
|
||||
gfxIntSize size = aSurf->GetSize();
|
||||
for (int j = 0; j < size.height; ++j) {
|
||||
PRUint32 *row = (PRUint32*) (aSurf->Data() + aSurf->Stride() * j);
|
||||
for (int i = 0; i < size.width; ++i) {
|
||||
*row = (*row & 0xff00ff00) | ((*row & 0xff) << 16) | ((*row & 0xff0000) >> 16);
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static already_AddRefed<gfxImageSurface> YInvertImageSurface(gfxImageSurface* aSurf)
|
||||
{
|
||||
gfxIntSize size = aSurf->GetSize();
|
||||
nsRefPtr<gfxImageSurface> temp = new gfxImageSurface(size, aSurf->Format());
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(temp);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->Scale(1.0, -1.0);
|
||||
ctx->Translate(-gfxPoint(0.0, size.height));
|
||||
ctx->SetSource(aSurf);
|
||||
ctx->Paint();
|
||||
return temp.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxImageSurface>
|
||||
GLContext::GetTexImage(GLuint aTexture, bool aYInvert, ShaderProgramType aShader)
|
||||
{
|
||||
MakeCurrent();
|
||||
fFinish();
|
||||
fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
|
||||
|
||||
gfxIntSize size;
|
||||
fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_WIDTH, &size.width);
|
||||
fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_HEIGHT, &size.height);
|
||||
|
||||
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(size, gfxASurface::ImageFormatARGB32);
|
||||
if (!surf || surf->CairoStatus()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PRUint32 currentPackAlignment = 0;
|
||||
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)¤tPackAlignment);
|
||||
if (currentPackAlignment != 4) {
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
|
||||
}
|
||||
fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, surf->Data());
|
||||
if (currentPackAlignment != 4) {
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
|
||||
}
|
||||
|
||||
if (aShader == RGBALayerProgramType || aShader == RGBXLayerProgramType) {
|
||||
SwapRAndBComponents(surf);
|
||||
}
|
||||
|
||||
if (aYInvert) {
|
||||
surf = YInvertImageSurface(surf);
|
||||
}
|
||||
return surf.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxImageSurface>
|
||||
GLContext::ReadTextureImage(GLuint aTexture,
|
||||
const gfxIntSize& aSize,
|
||||
GLenum aTextureFormat)
|
||||
GLenum aTextureFormat,
|
||||
bool aYInvert)
|
||||
{
|
||||
MakeCurrent();
|
||||
|
||||
@ -1664,6 +1735,8 @@ GLContext::ReadTextureImage(GLuint aTexture,
|
||||
fs = fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
|
||||
fShaderSource(vs, 1, (const GLchar**) &vShader, NULL);
|
||||
fShaderSource(fs, 1, (const GLchar**) &fShader, NULL);
|
||||
fCompileShader(vs);
|
||||
fCompileShader(fs);
|
||||
prog = fCreateProgram();
|
||||
fAttachShader(prog, vs);
|
||||
fAttachShader(prog, fs);
|
||||
@ -1707,9 +1780,15 @@ GLContext::ReadTextureImage(GLuint aTexture,
|
||||
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
|
||||
isurf->Data());
|
||||
|
||||
SwapRAndBComponents(isurf);
|
||||
|
||||
if (oldPackAlignment != 4)
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, oldPackAlignment);
|
||||
|
||||
if (aYInvert) {
|
||||
isurf = YInvertImageSurface(isurf);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
// note that deleting 0 has no effect in any of these calls
|
||||
fDeleteRenderbuffers(1, &rb);
|
||||
|
@ -1233,7 +1233,10 @@ public:
|
||||
*/
|
||||
already_AddRefed<gfxImageSurface> ReadTextureImage(GLuint aTexture,
|
||||
const gfxIntSize& aSize,
|
||||
GLenum aTextureFormat);
|
||||
GLenum aTextureFormat,
|
||||
bool aYInvert = false);
|
||||
|
||||
already_AddRefed<gfxImageSurface> GetTexImage(GLuint aTexture, bool aYInvert, ShaderProgramType aShader);
|
||||
|
||||
/**
|
||||
* Call ReadPixels into an existing gfxImageSurface for the given bounds.
|
||||
@ -2122,6 +2125,22 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
void fGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *img) {
|
||||
if (!mSymbols.fGetTexImage) {
|
||||
return;
|
||||
}
|
||||
BEFORE_GL_CALL;
|
||||
mSymbols.fGetTexImage(target, level, format, type, img);
|
||||
AFTER_GL_CALL;
|
||||
};
|
||||
|
||||
void fGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
|
||||
{
|
||||
BEFORE_GL_CALL;
|
||||
mSymbols.fGetTexLevelParameteriv(target, level, pname, params);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void fGetTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) {
|
||||
BEFORE_GL_CALL;
|
||||
mSymbols.fGetTexParameterfv(target, pname, params);
|
||||
|
@ -155,6 +155,10 @@ struct GLContextSymbols
|
||||
PFNGLTEXPARAMETERFPROC fTexParameterf;
|
||||
typedef GLubyte* (GLAPIENTRY * PFNGLGETSTRINGPROC) (GLenum);
|
||||
PFNGLGETSTRINGPROC fGetString;
|
||||
typedef void (GLAPIENTRY * PFNGLGETTEXIMAGEPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLvoid* image);
|
||||
PFNGLGETTEXIMAGEPROC fGetTexImage;
|
||||
typedef void (GLAPIENTRY * PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
|
||||
PFNGLGETTEXLEVELPARAMETERIVPROC fGetTexLevelParameteriv;
|
||||
typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
|
||||
PFNGLGETTEXPARAMETERFVPROC fGetTexParameterfv;
|
||||
typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
|
||||
|
@ -36,6 +36,7 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
#include "mozilla/ipc/CrossProcessMutex.h"
|
||||
#include "ImageLayers.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "yuv_convert.h"
|
||||
@ -119,15 +120,91 @@ ImageContainer::SetCurrentImage(Image *aImage)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (mRemoteData) {
|
||||
NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
|
||||
mRemoteDataMutex->Lock();
|
||||
// This is important since it ensures we won't change the active image
|
||||
// when we currently have a locked image that depends on mRemoteData.
|
||||
}
|
||||
|
||||
mActiveImage = aImage;
|
||||
CurrentImageChanged();
|
||||
|
||||
if (mRemoteData) {
|
||||
mRemoteDataMutex->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ImageContainer::HasCurrentImage()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (mRemoteData) {
|
||||
CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
|
||||
|
||||
EnsureActiveImage();
|
||||
|
||||
return !!mActiveImage.get();
|
||||
}
|
||||
|
||||
return !!mActiveImage.get();
|
||||
}
|
||||
|
||||
already_AddRefed<Image>
|
||||
ImageContainer::LockCurrentImage()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (mRemoteData) {
|
||||
NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
|
||||
mRemoteDataMutex->Lock();
|
||||
}
|
||||
|
||||
EnsureActiveImage();
|
||||
|
||||
nsRefPtr<Image> retval = mActiveImage;
|
||||
return retval.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
ImageContainer::GetCurrentAsSurface(gfxIntSize *aSize)
|
||||
ImageContainer::LockCurrentAsSurface(gfxIntSize *aSize, Image** aCurrentImage)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (mRemoteData) {
|
||||
NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
|
||||
mRemoteDataMutex->Lock();
|
||||
|
||||
EnsureActiveImage();
|
||||
|
||||
if (aCurrentImage) {
|
||||
NS_IF_ADDREF(mActiveImage);
|
||||
*aCurrentImage = mActiveImage.get();
|
||||
}
|
||||
|
||||
if (!mActiveImage) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (mActiveImage->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
|
||||
nsRefPtr<gfxImageSurface> newSurf =
|
||||
new gfxImageSurface(mRemoteData->mBitmap.mData, mRemoteData->mSize, mRemoteData->mBitmap.mStride,
|
||||
mRemoteData->mFormat == RemoteImageData::BGRX32 ?
|
||||
gfxASurface::ImageFormatARGB32 :
|
||||
gfxASurface::ImageFormatRGB24);
|
||||
|
||||
*aSize = newSurf->GetSize();
|
||||
|
||||
return newSurf.forget();
|
||||
}
|
||||
}
|
||||
|
||||
if (aCurrentImage) {
|
||||
NS_IF_ADDREF(mActiveImage);
|
||||
*aCurrentImage = mActiveImage.get();
|
||||
}
|
||||
|
||||
if (!mActiveImage) {
|
||||
return nsnull;
|
||||
}
|
||||
@ -136,11 +213,45 @@ ImageContainer::GetCurrentAsSurface(gfxIntSize *aSize)
|
||||
return mActiveImage->GetAsSurface();
|
||||
}
|
||||
|
||||
void
|
||||
ImageContainer::UnlockCurrentImage()
|
||||
{
|
||||
if (mRemoteData) {
|
||||
NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
|
||||
mRemoteDataMutex->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
ImageContainer::GetCurrentAsSurface(gfxIntSize *aSize)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (mRemoteData) {
|
||||
CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
|
||||
EnsureActiveImage();
|
||||
|
||||
*aSize = mRemoteData->mSize;
|
||||
return mActiveImage ? mActiveImage->GetAsSurface() : nsnull;
|
||||
}
|
||||
|
||||
*aSize = mActiveImage->GetSize();
|
||||
return mActiveImage ? mActiveImage->GetAsSurface() : nsnull;
|
||||
}
|
||||
|
||||
gfxIntSize
|
||||
ImageContainer::GetCurrentSize()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (mRemoteData) {
|
||||
CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
|
||||
|
||||
// We don't need to ensure we have an active image here, as we need to
|
||||
// be in the mutex anyway, and this is easiest to return from there.
|
||||
return mRemoteData->mSize;
|
||||
}
|
||||
|
||||
if (!mActiveImage) {
|
||||
return gfxIntSize(0,0);
|
||||
}
|
||||
@ -148,6 +259,47 @@ ImageContainer::GetCurrentSize()
|
||||
return mActiveImage->GetSize();
|
||||
}
|
||||
|
||||
void
|
||||
ImageContainer::SetRemoteImageData(RemoteImageData *aData, CrossProcessMutex *aMutex)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
NS_ASSERTION(!mActiveImage, "No active image expected when SetRemoteImageData is called.");
|
||||
NS_ASSERTION(!mRemoteData, "No remote data expected when SetRemoteImageData is called.");
|
||||
|
||||
mRemoteData = aData;
|
||||
|
||||
if (aData) {
|
||||
memset(aData, 0, sizeof(RemoteImageData));
|
||||
} else {
|
||||
mActiveImage = nsnull;
|
||||
}
|
||||
|
||||
mRemoteDataMutex = aMutex;
|
||||
}
|
||||
|
||||
void
|
||||
ImageContainer::EnsureActiveImage()
|
||||
{
|
||||
if (mRemoteData) {
|
||||
if (mRemoteData->mWasUpdated) {
|
||||
mActiveImage = nsnull;
|
||||
}
|
||||
|
||||
if (mRemoteData->mType == RemoteImageData::RAW_BITMAP &&
|
||||
mRemoteData->mBitmap.mData && !mActiveImage) {
|
||||
nsRefPtr<RemoteBitmapImage> newImg = new RemoteBitmapImage();
|
||||
|
||||
newImg->mFormat = mRemoteData->mFormat;
|
||||
newImg->mData = mRemoteData->mBitmap.mData;
|
||||
newImg->mSize = mRemoteData->mSize;
|
||||
newImg->mStride = mRemoteData->mBitmap.mStride;
|
||||
mRemoteData->mWasUpdated = false;
|
||||
|
||||
mActiveImage = newImg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlanarYCbCrImage::PlanarYCbCrImage(BufferRecycleBin *aRecycleBin)
|
||||
: Image(nsnull, PLANAR_YCBCR)
|
||||
, mBufferSize(0)
|
||||
@ -270,6 +422,21 @@ MacIOSurfaceImage::Update(ImageContainer* aContainer)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
already_AddRefed<gfxASurface>
|
||||
RemoteBitmapImage::GetAsSurface()
|
||||
{
|
||||
nsRefPtr<gfxImageSurface> newSurf =
|
||||
new gfxImageSurface(mSize,
|
||||
mFormat == RemoteImageData::BGRX32 ? gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32);
|
||||
|
||||
for (int y = 0; y < mSize.height; y++) {
|
||||
memcpy(newSurf->Data() + newSurf->Stride() * y,
|
||||
mData + mStride * y,
|
||||
mSize.width * 4);
|
||||
}
|
||||
|
||||
return newSurf.forget();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,12 @@
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class CrossProcessMutex;
|
||||
namespace ipc {
|
||||
class Shmem;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
||||
enum StereoMode {
|
||||
@ -120,7 +126,12 @@ public:
|
||||
*
|
||||
* It wraps an IOSurface object and binds it directly to a GL texture.
|
||||
*/
|
||||
MAC_IO_SURFACE
|
||||
MAC_IO_SURFACE,
|
||||
|
||||
/**
|
||||
* An bitmap image that can be shared with a remote process.
|
||||
*/
|
||||
REMOTE_IMAGE_BITMAP
|
||||
};
|
||||
|
||||
Format GetFormat() { return mFormat; }
|
||||
@ -194,6 +205,12 @@ FormatInList(const Image::Format* aFormats, PRUint32 aNumFormats,
|
||||
return false;
|
||||
}
|
||||
|
||||
class CompositionNotifySink
|
||||
{
|
||||
public:
|
||||
virtual void DidComposite() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* A class that manages Image creation for a LayerManager. The only reason
|
||||
* we need a separate class here is that LayerMananers aren't threadsafe
|
||||
@ -225,6 +242,46 @@ protected:
|
||||
BufferRecycleBin *aRecycleBin);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This struct is used to store RemoteImages, it is meant to be able to live in
|
||||
* shared memory. Therefor it should not contain a vtable pointer. Remote
|
||||
* users can manipulate the data in this structure to specify what image is to
|
||||
* be drawn by the container. When accessing this data users should make sure
|
||||
* the mutex synchronizing access to the structure is held!
|
||||
*/
|
||||
struct RemoteImageData {
|
||||
enum Type {
|
||||
/**
|
||||
* This is a format that uses raw bitmap data.
|
||||
*/
|
||||
RAW_BITMAP
|
||||
};
|
||||
/* These formats describe the format in the memory byte-order */
|
||||
enum Format {
|
||||
/* 8 bits per channel */
|
||||
BGRA32,
|
||||
/* 8 bits per channel, alpha channel is ignored */
|
||||
BGRX32
|
||||
};
|
||||
|
||||
// This should be set to true if a change was made so that the ImageContainer
|
||||
// knows to throw out any cached RemoteImage objects.
|
||||
bool mWasUpdated;
|
||||
Type mType;
|
||||
Format mFormat;
|
||||
gfxIntSize mSize;
|
||||
union {
|
||||
struct {
|
||||
/* This pointer is set by a remote process, however it will be set to
|
||||
* the container process' address the memory of the raw bitmap resides
|
||||
* at.
|
||||
*/
|
||||
unsigned char *mData;
|
||||
int mStride;
|
||||
} mBitmap;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* A class that manages Images for an ImageLayer. The only reason
|
||||
@ -242,7 +299,10 @@ public:
|
||||
mPaintCount(0),
|
||||
mPreviousImagePainted(false),
|
||||
mImageFactory(new ImageFactory()),
|
||||
mRecycleBin(new BufferRecycleBin())
|
||||
mRecycleBin(new BufferRecycleBin()),
|
||||
mRemoteData(nsnull),
|
||||
mRemoteDataMutex(nsnull),
|
||||
mCompositionNotifySink(nsnull)
|
||||
{}
|
||||
|
||||
~ImageContainer();
|
||||
@ -266,26 +326,37 @@ public:
|
||||
* aImage can be null. While it's null, nothing will be painted.
|
||||
*
|
||||
* The Image data must not be modified after this method is called!
|
||||
*
|
||||
* Implementations must call CurrentImageChanged() while holding
|
||||
* mReentrantMonitor.
|
||||
*/
|
||||
void SetCurrentImage(Image* aImage);
|
||||
|
||||
/**
|
||||
* Get the current Image.
|
||||
* This has to add a reference since otherwise there are race conditions
|
||||
* where the current image is destroyed before the caller can add
|
||||
* a reference.
|
||||
* Returns if the container currently has an image.
|
||||
* Can be called on any thread. This method takes mReentrantMonitor
|
||||
* when accessing thread-shared state.
|
||||
* Implementations must call CurrentImageChanged() while holding
|
||||
* mReentrantMonitor.
|
||||
*/
|
||||
already_AddRefed<Image> GetCurrentImage()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
bool HasCurrentImage();
|
||||
|
||||
nsRefPtr<Image> retval = mActiveImage;
|
||||
return retval.forget();
|
||||
}
|
||||
/**
|
||||
* Lock the current Image.
|
||||
* This has to add a reference since otherwise there are race conditions
|
||||
* where the current image is destroyed before the caller can add
|
||||
* a reference. This lock strictly guarantees the underlying image remains
|
||||
* valid, it does not mean the current image cannot change.
|
||||
* Can be called on any thread. This method will lock the cross-process
|
||||
* mutex to ensure remote processes cannot alter underlying data. This call
|
||||
* -must- be balanced by a call to UnlockCurrentImage and users should avoid
|
||||
* holding the image locked for a long time.
|
||||
*/
|
||||
already_AddRefed<Image> LockCurrentImage();
|
||||
|
||||
/**
|
||||
* This call unlocks the image. For remote images releasing the cross-process
|
||||
* mutex.
|
||||
*/
|
||||
void UnlockCurrentImage();
|
||||
|
||||
/**
|
||||
* Get the current image as a gfxASurface. This is useful for fallback
|
||||
@ -301,9 +372,25 @@ public:
|
||||
* modify it.
|
||||
* Can be called on any thread. This method takes mReentrantMonitor
|
||||
* when accessing thread-shared state.
|
||||
* If the current image is a remote image, that is, if it is an image that
|
||||
* may be shared accross processes, calling this function will make
|
||||
* a copy of the image data while holding the mRemoteDataMutex. If possible,
|
||||
* the lock methods should be used to avoid the copy, however this should be
|
||||
* avoided if the surface is required for a long period of time.
|
||||
*/
|
||||
already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSizeResult);
|
||||
|
||||
/**
|
||||
* This is similar to GetCurrentAsSurface, however this does not make a copy
|
||||
* of the image data and requires the user to call UnlockCurrentImage when
|
||||
* done with the image data. Once UnlockCurrentImage has been called the
|
||||
* surface returned by this function is no longer valid! This works for any
|
||||
* type of image. Optionally a pointer can be passed to receive the current
|
||||
* image.
|
||||
*/
|
||||
already_AddRefed<gfxASurface> LockCurrentAsSurface(gfxIntSize* aSizeResult,
|
||||
Image** aCurrentImage = nsnull);
|
||||
|
||||
/**
|
||||
* Returns the size of the image in pixels.
|
||||
* Can be called on any thread. This method takes mReentrantMonitor when accessing
|
||||
@ -354,7 +441,8 @@ public:
|
||||
*/
|
||||
void NotifyPaintedImage(Image* aPainted) {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
nsRefPtr<Image> current = GetCurrentImage();
|
||||
|
||||
nsRefPtr<Image> current = mActiveImage;
|
||||
if (aPainted == current) {
|
||||
if (mPaintTime.IsNull()) {
|
||||
mPaintTime = TimeStamp::Now();
|
||||
@ -367,11 +455,40 @@ public:
|
||||
mPaintCount++;
|
||||
mPreviousImagePainted = true;
|
||||
}
|
||||
|
||||
if (mCompositionNotifySink) {
|
||||
mCompositionNotifySink->DidComposite();
|
||||
}
|
||||
}
|
||||
|
||||
void SetCompositionNotifySink(CompositionNotifySink *aSink) {
|
||||
mCompositionNotifySink = aSink;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called to tell the ImageContainer where the
|
||||
* (cross-process) segment lives where the shared data about possible
|
||||
* remote images are stored. In addition to this a CrossProcessMutex object
|
||||
* is passed telling the container how to synchronize access to this data.
|
||||
* NOTE: This should be called during setup of the container and not after
|
||||
* usage has started.
|
||||
*/
|
||||
void SetRemoteImageData(RemoteImageData *aRemoteData,
|
||||
CrossProcessMutex *aRemoteDataMutex);
|
||||
/**
|
||||
* This can be used to check if the container has RemoteData set.
|
||||
*/
|
||||
RemoteImageData *GetRemoteImageData() { return mRemoteData; }
|
||||
|
||||
protected:
|
||||
typedef mozilla::ReentrantMonitor ReentrantMonitor;
|
||||
|
||||
// This is called to ensure we have an active image, this may not be true
|
||||
// when we're storing image information in a RemoteImageData structure.
|
||||
// NOTE: If we have remote data mRemoteDataMutex should be locked when
|
||||
// calling this function!
|
||||
void EnsureActiveImage();
|
||||
|
||||
// ReentrantMonitor to protect thread safe access to the "current
|
||||
// image", and any other state which is shared between threads.
|
||||
ReentrantMonitor mReentrantMonitor;
|
||||
@ -407,6 +524,56 @@ protected:
|
||||
gfxIntSize mScaleHint;
|
||||
|
||||
nsRefPtr<BufferRecycleBin> mRecycleBin;
|
||||
|
||||
// This contains the remote image data for this container, if this is NULL
|
||||
// that means the container has no other process that may control its active
|
||||
// image.
|
||||
RemoteImageData *mRemoteData;
|
||||
|
||||
// This cross-process mutex is used to synchronise access to mRemoteData.
|
||||
// When this mutex is held, we will always be inside the mReentrantMonitor
|
||||
// however the same is not true vice versa.
|
||||
CrossProcessMutex *mRemoteDataMutex;
|
||||
|
||||
CompositionNotifySink *mCompositionNotifySink;
|
||||
};
|
||||
|
||||
class AutoLockImage
|
||||
{
|
||||
public:
|
||||
AutoLockImage(ImageContainer *aContainer) : mContainer(aContainer) { mImage = mContainer->LockCurrentImage(); }
|
||||
AutoLockImage(ImageContainer *aContainer, gfxASurface **aSurface) : mContainer(aContainer) {
|
||||
*aSurface = mContainer->LockCurrentAsSurface(&mSize, getter_AddRefs(mImage)).get();
|
||||
}
|
||||
~AutoLockImage() { if (mContainer) { mContainer->UnlockCurrentImage(); } }
|
||||
|
||||
Image* GetImage() { return mImage; }
|
||||
const gfxIntSize &GetSize() { return mSize; }
|
||||
|
||||
void Unlock() {
|
||||
if (mContainer) {
|
||||
mImage = nsnull;
|
||||
mContainer->UnlockCurrentImage();
|
||||
mContainer = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
/** Things get a little tricky here, because our underlying image can -still-
|
||||
* change, and OS X requires a complicated callback mechanism to update this
|
||||
* we need to support staying the lock and getting the new image in a proper
|
||||
* way. This method makes any images retrieved with GetImage invalid!
|
||||
*/
|
||||
void Refresh() {
|
||||
if (mContainer) {
|
||||
mContainer->UnlockCurrentImage();
|
||||
mImage = mContainer->LockCurrentImage();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ImageContainer *mContainer;
|
||||
nsRefPtr<Image> mImage;
|
||||
gfxIntSize mSize;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -676,6 +843,20 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
class RemoteBitmapImage : public Image {
|
||||
public:
|
||||
RemoteBitmapImage() : Image(NULL, REMOTE_IMAGE_BITMAP) {}
|
||||
|
||||
already_AddRefed<gfxASurface> GetAsSurface();
|
||||
|
||||
gfxIntSize GetSize() { return mSize; }
|
||||
|
||||
unsigned char *mData;
|
||||
int mStride;
|
||||
gfxIntSize mSize;
|
||||
RemoteImageData::Format mFormat;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,6 +458,10 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const gfx3DMatrix& aTransformT
|
||||
float opacity = GetEffectiveOpacity();
|
||||
if (opacity != 1.0f && HasMultipleChildren()) {
|
||||
useIntermediateSurface = true;
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
} else if (gfxUtils::sDumpPainting) {
|
||||
useIntermediateSurface = true;
|
||||
#endif
|
||||
} else {
|
||||
useIntermediateSurface = false;
|
||||
gfxMatrix contTransform;
|
||||
@ -552,17 +556,60 @@ LayerManager::StopFrameTimeRecording()
|
||||
|
||||
static nsACString& PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
template <typename T>
|
||||
void WriteSnapshotLinkToDumpFile(T* aObj, FILE* aFile)
|
||||
{
|
||||
nsCString string(aObj->Name());
|
||||
string.Append("-");
|
||||
string.AppendInt((PRUint64)aObj);
|
||||
fprintf(aFile, "href=\"javascript:ViewImage('%s')\"", string.BeginReading());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void WriteSnapshotToDumpFile_internal(T* aObj, gfxASurface* aSurf)
|
||||
{
|
||||
nsCString string(aObj->Name());
|
||||
string.Append("-");
|
||||
string.AppendInt((PRUint64)aObj);
|
||||
fprintf(gfxUtils::sDumpPaintFile, "array[\"%s\"]=\"", string.BeginReading());
|
||||
aSurf->DumpAsDataURL(gfxUtils::sDumpPaintFile);
|
||||
fprintf(gfxUtils::sDumpPaintFile, "\";");
|
||||
}
|
||||
|
||||
void WriteSnapshotToDumpFile(Layer* aLayer, gfxASurface* aSurf)
|
||||
{
|
||||
WriteSnapshotToDumpFile_internal(aLayer, aSurf);
|
||||
}
|
||||
|
||||
void WriteSnapshotToDumpFile(LayerManager* aManager, gfxASurface* aSurf)
|
||||
{
|
||||
WriteSnapshotToDumpFile_internal(aManager, aSurf);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Layer::Dump(FILE* aFile, const char* aPrefix)
|
||||
{
|
||||
fprintf(aFile, "<li><a id=\"%p\" ", this);
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (GetType() == TYPE_CONTAINER || GetType() == TYPE_THEBES) {
|
||||
WriteSnapshotLinkToDumpFile(this, aFile);
|
||||
}
|
||||
#endif
|
||||
fprintf(aFile, ">");
|
||||
DumpSelf(aFile, aPrefix);
|
||||
fprintf(aFile, "</a>");
|
||||
|
||||
if (Layer* kid = GetFirstChild()) {
|
||||
nsCAutoString pfx(aPrefix);
|
||||
pfx += " ";
|
||||
fprintf(aFile, "<ul>");
|
||||
kid->Dump(aFile, pfx.get());
|
||||
fprintf(aFile, "</ul>");
|
||||
}
|
||||
|
||||
fprintf(aFile, "</li>");
|
||||
if (Layer* next = GetNextSibling())
|
||||
next->Dump(aFile, aPrefix);
|
||||
}
|
||||
@ -714,17 +761,27 @@ void
|
||||
LayerManager::Dump(FILE* aFile, const char* aPrefix)
|
||||
{
|
||||
FILE* file = FILEOrDefault(aFile);
|
||||
|
||||
|
||||
fprintf(file, "<ul><li><a ");
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
WriteSnapshotLinkToDumpFile(this, aFile);
|
||||
#endif
|
||||
fprintf(file, ">");
|
||||
DumpSelf(file, aPrefix);
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
fprintf(aFile, "</a>");
|
||||
#endif
|
||||
|
||||
nsCAutoString pfx(aPrefix);
|
||||
pfx += " ";
|
||||
if (!GetRoot()) {
|
||||
fprintf(file, "%s(null)", pfx.get());
|
||||
fprintf(file, "%s(null)</li></ul>", pfx.get());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fprintf(file, "<ul>");
|
||||
GetRoot()->Dump(file, pfx.get());
|
||||
fprintf(file, "</ul></li></ul>");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1345,6 +1345,11 @@ protected:
|
||||
bool mDirty;
|
||||
};
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void WriteSnapshotToDumpFile(Layer* aLayer, gfxASurface* aSurf);
|
||||
void WriteSnapshotToDumpFile(LayerManager* aManager, gfxASurface* aSurf);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -904,9 +904,11 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
|
||||
|
||||
mContainer->SetImageFactory(mManager->IsCompositingCheap() ? nsnull : BasicManager()->GetImageFactory());
|
||||
|
||||
nsRefPtr<Image> image = mContainer->GetCurrentImage();
|
||||
nsRefPtr<gfxASurface> surface;
|
||||
AutoLockImage autoLock(mContainer, getter_AddRefs(surface));
|
||||
Image *image = autoLock.GetImage();
|
||||
mSize = autoLock.GetSize();
|
||||
|
||||
nsRefPtr<gfxASurface> surface = mContainer->GetCurrentAsSurface(&mSize);
|
||||
if (!surface || surface->CairoStatus()) {
|
||||
return nsnull;
|
||||
}
|
||||
@ -2522,13 +2524,16 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext)
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<Image> image = mContainer->GetCurrentImage();
|
||||
AutoLockImage autoLock(mContainer);
|
||||
|
||||
Image *image = autoLock.GetImage();
|
||||
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (image->GetFormat() == Image::PLANAR_YCBCR && BasicManager()->IsCompositingCheap()) {
|
||||
PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(image.get());
|
||||
PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(image);
|
||||
const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
|
||||
NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
|
||||
|
||||
|
@ -44,6 +44,34 @@
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
static already_AddRefed<ID3D10Texture2D>
|
||||
DataToTexture(ID3D10Device *aDevice,
|
||||
unsigned char *data,
|
||||
int stride,
|
||||
const gfxIntSize &aSize)
|
||||
{
|
||||
D3D10_SUBRESOURCE_DATA srdata;
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
1, 1);
|
||||
desc.Usage = D3D10_USAGE_IMMUTABLE;
|
||||
|
||||
srdata.pSysMem = data;
|
||||
srdata.SysMemPitch = stride;
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> texture;
|
||||
HRESULT hr = aDevice->CreateTexture2D(&desc, &srdata, getter_AddRefs(texture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("Failed to create texture for data"),
|
||||
hr);
|
||||
}
|
||||
|
||||
return texture.forget();
|
||||
}
|
||||
|
||||
static already_AddRefed<ID3D10Texture2D>
|
||||
SurfaceToTexture(ID3D10Device *aDevice,
|
||||
@ -78,26 +106,7 @@ SurfaceToTexture(ID3D10Device *aDevice,
|
||||
context->Paint();
|
||||
}
|
||||
|
||||
D3D10_SUBRESOURCE_DATA data;
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
imageSurface->GetSize().width,
|
||||
imageSurface->GetSize().height,
|
||||
1, 1);
|
||||
desc.Usage = D3D10_USAGE_IMMUTABLE;
|
||||
|
||||
data.pSysMem = imageSurface->Data();
|
||||
data.SysMemPitch = imageSurface->Stride();
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> texture;
|
||||
HRESULT hr = aDevice->CreateTexture2D(&desc, &data, getter_AddRefs(texture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("Failed to create texture for image surface"),
|
||||
hr);
|
||||
}
|
||||
|
||||
return texture.forget();
|
||||
return DataToTexture(aDevice, imageSurface->Data(), imageSurface->Stride(), aSize);
|
||||
}
|
||||
|
||||
Layer*
|
||||
@ -109,11 +118,14 @@ ImageLayerD3D10::GetLayer()
|
||||
void
|
||||
ImageLayerD3D10::RenderLayer()
|
||||
{
|
||||
if (!GetContainer()) {
|
||||
ImageContainer *container = GetContainer();
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<Image> image = GetContainer()->GetCurrentImage();
|
||||
AutoLockImage autoLock(container);
|
||||
|
||||
Image *image = autoLock.GetImage();
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
@ -122,27 +134,51 @@ ImageLayerD3D10::RenderLayer()
|
||||
|
||||
ID3D10EffectTechnique *technique;
|
||||
|
||||
if (image->GetFormat() == Image::CAIRO_SURFACE)
|
||||
if (image->GetFormat() == Image::CAIRO_SURFACE || image->GetFormat() == Image::REMOTE_IMAGE_BITMAP)
|
||||
{
|
||||
CairoImage *cairoImage =
|
||||
static_cast<CairoImage*>(image.get());
|
||||
bool hasAlpha = false;
|
||||
gfxIntSize size;
|
||||
|
||||
if (!cairoImage->mSurface) {
|
||||
return;
|
||||
}
|
||||
if (image->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
|
||||
RemoteBitmapImage *remoteImage =
|
||||
static_cast<RemoteBitmapImage*>(image);
|
||||
|
||||
if (!image->GetBackendData(LayerManager::LAYERS_D3D10)) {
|
||||
nsAutoPtr<TextureD3D10BackendData> dat = new TextureD3D10BackendData();
|
||||
dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize);
|
||||
|
||||
if (!cairoImage->GetBackendData(LayerManager::LAYERS_D3D10)) {
|
||||
nsAutoPtr<CairoD3D10BackendData> dat(new CairoD3D10BackendData());
|
||||
dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
|
||||
|
||||
if (dat->mTexture) {
|
||||
device()->CreateShaderResourceView(dat->mTexture, NULL, getter_AddRefs(dat->mSRView));
|
||||
cairoImage->SetBackendData(LayerManager::LAYERS_D3D10, dat.forget());
|
||||
if (dat->mTexture) {
|
||||
device()->CreateShaderResourceView(dat->mTexture, NULL, getter_AddRefs(dat->mSRView));
|
||||
image->SetBackendData(LayerManager::LAYERS_D3D10, dat.forget());
|
||||
}
|
||||
}
|
||||
|
||||
hasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
|
||||
size = remoteImage->mSize;
|
||||
} else {
|
||||
CairoImage *cairoImage =
|
||||
static_cast<CairoImage*>(image);
|
||||
|
||||
if (!cairoImage->mSurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!image->GetBackendData(LayerManager::LAYERS_D3D10)) {
|
||||
nsAutoPtr<TextureD3D10BackendData> dat = new TextureD3D10BackendData();
|
||||
dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
|
||||
|
||||
if (dat->mTexture) {
|
||||
device()->CreateShaderResourceView(dat->mTexture, NULL, getter_AddRefs(dat->mSRView));
|
||||
image->SetBackendData(LayerManager::LAYERS_D3D10, dat.forget());
|
||||
}
|
||||
}
|
||||
|
||||
hasAlpha = cairoImage->mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA;
|
||||
size = cairoImage->mSize;
|
||||
}
|
||||
|
||||
CairoD3D10BackendData *data =
|
||||
static_cast<CairoD3D10BackendData*>(cairoImage->GetBackendData(LayerManager::LAYERS_D3D10));
|
||||
TextureD3D10BackendData *data =
|
||||
static_cast<TextureD3D10BackendData*>(image->GetBackendData(LayerManager::LAYERS_D3D10));
|
||||
|
||||
if (!data) {
|
||||
return;
|
||||
@ -154,7 +190,7 @@ ImageLayerD3D10::RenderLayer()
|
||||
return;
|
||||
}
|
||||
|
||||
if (cairoImage->mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
|
||||
if (hasAlpha) {
|
||||
if (mFilter == gfxPattern::FILTER_NEAREST) {
|
||||
technique = effect()->GetTechniqueByName("RenderRGBALayerPremulPoint");
|
||||
} else {
|
||||
@ -174,12 +210,12 @@ ImageLayerD3D10::RenderLayer()
|
||||
ShaderConstantRectD3D10(
|
||||
(float)0,
|
||||
(float)0,
|
||||
(float)cairoImage->mSize.width,
|
||||
(float)cairoImage->mSize.height)
|
||||
(float)size.width,
|
||||
(float)size.height)
|
||||
);
|
||||
} else if (image->GetFormat() == Image::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImage *yuvImage =
|
||||
static_cast<PlanarYCbCrImage*>(image.get());
|
||||
static_cast<PlanarYCbCrImage*>(image);
|
||||
|
||||
if (!yuvImage->mBufferSize) {
|
||||
return;
|
||||
@ -262,11 +298,15 @@ ImageLayerD3D10::RenderLayer()
|
||||
(float)yuvImage->mData.mPicSize.height / yuvImage->mData.mYSize.height)
|
||||
);
|
||||
}
|
||||
|
||||
bool resetTexCoords = image->GetFormat() == Image::PLANAR_YCBCR;
|
||||
image = nsnull;
|
||||
autoLock.Unlock();
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
device()->Draw(4, 0);
|
||||
|
||||
if (image->GetFormat() == Image::PLANAR_YCBCR) {
|
||||
if (resetTexCoords) {
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ struct PlanarYCbCrD3D10BackendData : public ImageBackendData
|
||||
nsRefPtr<ID3D10ShaderResourceView> mCrView;
|
||||
};
|
||||
|
||||
struct CairoD3D10BackendData : public ImageBackendData
|
||||
struct TextureD3D10BackendData : public ImageBackendData
|
||||
{
|
||||
nsRefPtr<ID3D10Texture2D> mTexture;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mSRView;
|
||||
|
@ -53,23 +53,11 @@ namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
static already_AddRefed<IDirect3DTexture9>
|
||||
SurfaceToTexture(IDirect3DDevice9 *aDevice,
|
||||
gfxASurface *aSurface,
|
||||
const gfxIntSize &aSize)
|
||||
DataToTexture(IDirect3DDevice9 *aDevice,
|
||||
unsigned char *aData,
|
||||
int aStride,
|
||||
const gfxIntSize &aSize)
|
||||
{
|
||||
|
||||
nsRefPtr<gfxImageSurface> imageSurface = aSurface->GetAsImageSurface();
|
||||
|
||||
if (!imageSurface) {
|
||||
imageSurface = new gfxImageSurface(aSize,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
|
||||
context->SetSource(aSurface);
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
context->Paint();
|
||||
}
|
||||
|
||||
nsRefPtr<IDirect3DTexture9> texture;
|
||||
nsRefPtr<IDirect3DDevice9Ex> deviceEx;
|
||||
aDevice->QueryInterface(IID_IDirect3DDevice9Ex,
|
||||
@ -103,7 +91,7 @@ SurfaceToTexture(IDirect3DDevice9 *aDevice,
|
||||
surface->LockRect(&lockedRect, NULL, 0);
|
||||
for (int y = 0; y < aSize.height; y++) {
|
||||
memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y,
|
||||
imageSurface->Data() + imageSurface->Stride() * y,
|
||||
aData + aStride * y,
|
||||
aSize.width * 4);
|
||||
}
|
||||
surface->UnlockRect();
|
||||
@ -127,7 +115,7 @@ SurfaceToTexture(IDirect3DDevice9 *aDevice,
|
||||
// use memcpy
|
||||
for (int y = 0; y < aSize.height; y++) {
|
||||
memcpy((char*)lockrect.pBits + lockrect.Pitch * y,
|
||||
imageSurface->Data() + imageSurface->Stride() * y,
|
||||
aData + aStride * y,
|
||||
aSize.width * 4);
|
||||
}
|
||||
|
||||
@ -137,6 +125,27 @@ SurfaceToTexture(IDirect3DDevice9 *aDevice,
|
||||
return texture.forget();
|
||||
}
|
||||
|
||||
static already_AddRefed<IDirect3DTexture9>
|
||||
SurfaceToTexture(IDirect3DDevice9 *aDevice,
|
||||
gfxASurface *aSurface,
|
||||
const gfxIntSize &aSize)
|
||||
{
|
||||
|
||||
nsRefPtr<gfxImageSurface> imageSurface = aSurface->GetAsImageSurface();
|
||||
|
||||
if (!imageSurface) {
|
||||
imageSurface = new gfxImageSurface(aSize,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
|
||||
context->SetSource(aSurface);
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
context->Paint();
|
||||
}
|
||||
|
||||
return DataToTexture(aDevice, imageSurface->Data(), imageSurface->Stride(), aSize);
|
||||
}
|
||||
|
||||
static void AllocateTexturesYCbCr(PlanarYCbCrImage *aImage,
|
||||
IDirect3DDevice9 *aDevice,
|
||||
LayerManagerD3D9 *aManager)
|
||||
@ -302,37 +311,61 @@ ImageLayerD3D9::GetLayer()
|
||||
void
|
||||
ImageLayerD3D9::RenderLayer()
|
||||
{
|
||||
if (!GetContainer()) {
|
||||
ImageContainer *container = GetContainer();
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<Image> image = GetContainer()->GetCurrentImage();
|
||||
AutoLockImage autoLock(container);
|
||||
|
||||
Image *image = autoLock.GetImage();
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetShaderTransformAndOpacity();
|
||||
|
||||
if (image->GetFormat() == Image::CAIRO_SURFACE)
|
||||
if (image->GetFormat() == Image::CAIRO_SURFACE || image->GetFormat() == Image::REMOTE_IMAGE_BITMAP)
|
||||
{
|
||||
CairoImage *cairoImage =
|
||||
static_cast<CairoImage*>(image.get());
|
||||
bool hasAlpha = false;
|
||||
gfxIntSize size;
|
||||
|
||||
if (!cairoImage->mSurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cairoImage->GetBackendData(LayerManager::LAYERS_D3D9)) {
|
||||
nsAutoPtr<CairoD3D9BackendData> dat(new CairoD3D9BackendData());
|
||||
dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
|
||||
|
||||
if (dat->mTexture) {
|
||||
cairoImage->SetBackendData(LayerManager::LAYERS_D3D9, dat.forget());
|
||||
if (image->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
|
||||
RemoteBitmapImage *remoteImage =
|
||||
static_cast<RemoteBitmapImage*>(image);
|
||||
|
||||
if (!image->GetBackendData(LayerManager::LAYERS_D3D9)) {
|
||||
nsAutoPtr<TextureD3D9BackendData> dat = new TextureD3D9BackendData();
|
||||
dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize);
|
||||
if (dat->mTexture) {
|
||||
image->SetBackendData(LayerManager::LAYERS_D3D9, dat.forget());
|
||||
}
|
||||
}
|
||||
|
||||
hasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
|
||||
size = remoteImage->mSize;
|
||||
} else {
|
||||
CairoImage *cairoImage =
|
||||
static_cast<CairoImage*>(image);
|
||||
|
||||
if (!cairoImage->mSurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!image->GetBackendData(LayerManager::LAYERS_D3D9)) {
|
||||
nsAutoPtr<TextureD3D9BackendData> dat = new TextureD3D9BackendData();
|
||||
dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
|
||||
if (dat->mTexture) {
|
||||
image->SetBackendData(LayerManager::LAYERS_D3D9, dat.forget());
|
||||
}
|
||||
}
|
||||
|
||||
hasAlpha = cairoImage->mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA;
|
||||
size = cairoImage->mSize;
|
||||
}
|
||||
|
||||
CairoD3D9BackendData *data =
|
||||
static_cast<CairoD3D9BackendData*>(cairoImage->GetBackendData(LayerManager::LAYERS_D3D9));
|
||||
TextureD3D9BackendData *data =
|
||||
static_cast<TextureD3D9BackendData*>(image->GetBackendData(LayerManager::LAYERS_D3D9));
|
||||
|
||||
if (!data) {
|
||||
return;
|
||||
@ -344,12 +377,6 @@ ImageLayerD3D9::RenderLayer()
|
||||
return;
|
||||
}
|
||||
|
||||
gfxIntSize size;
|
||||
nsRefPtr<gfxASurface> surface =
|
||||
GetContainer()->GetCurrentAsSurface(&size);
|
||||
nsRefPtr<IDirect3DTexture9> texture =
|
||||
SurfaceToTexture(device(), surface, size);
|
||||
|
||||
device()->SetVertexShaderConstantF(CBvLayerQuad,
|
||||
ShaderConstantRect(0,
|
||||
0,
|
||||
@ -357,7 +384,7 @@ ImageLayerD3D9::RenderLayer()
|
||||
size.height),
|
||||
1);
|
||||
|
||||
if (surface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
|
||||
if (hasAlpha) {
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
|
||||
} else {
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
|
||||
@ -367,7 +394,12 @@ ImageLayerD3D9::RenderLayer()
|
||||
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||
}
|
||||
device()->SetTexture(0, texture);
|
||||
device()->SetTexture(0, data->mTexture);
|
||||
|
||||
image = nsnull;
|
||||
data = nsnull;
|
||||
autoLock.Unlock();
|
||||
|
||||
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
if (mFilter == gfxPattern::FILTER_NEAREST) {
|
||||
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
@ -375,7 +407,7 @@ ImageLayerD3D9::RenderLayer()
|
||||
}
|
||||
} else {
|
||||
PlanarYCbCrImage *yuvImage =
|
||||
static_cast<PlanarYCbCrImage*>(image.get());
|
||||
static_cast<PlanarYCbCrImage*>(image);
|
||||
|
||||
if (!yuvImage->mBufferSize) {
|
||||
return;
|
||||
@ -459,6 +491,10 @@ ImageLayerD3D9::RenderLayer()
|
||||
device()->SetTexture(1, data->mCbTexture);
|
||||
device()->SetTexture(2, data->mCrTexture);
|
||||
|
||||
image = nsnull;
|
||||
data = nsnull;
|
||||
autoLock.Unlock();
|
||||
|
||||
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
|
||||
device()->SetVertexShaderConstantF(CBvTextureCoords,
|
||||
|
@ -71,7 +71,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
struct CairoD3D9BackendData : public ImageBackendData
|
||||
struct TextureD3D9BackendData : public ImageBackendData
|
||||
{
|
||||
nsRefPtr<IDirect3DTexture9> mTexture;
|
||||
};
|
||||
|
@ -256,6 +256,14 @@ ContainerRender(Container* aContainer,
|
||||
|
||||
if (needsFramebuffer) {
|
||||
// Unbind the current framebuffer and rebind the previous one.
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (gfxUtils::sDumpPainting) {
|
||||
nsRefPtr<gfxImageSurface> surf =
|
||||
aContainer->gl()->GetTexImage(containerSurface, true, aManager->GetFBOLayerProgramType());
|
||||
|
||||
WriteSnapshotToDumpFile(aContainer, surf);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Restore the viewport
|
||||
aContainer->gl()->PopViewportRect();
|
||||
|
@ -214,19 +214,26 @@ void
|
||||
ImageLayerOGL::RenderLayer(int,
|
||||
const nsIntPoint& aOffset)
|
||||
{
|
||||
if (!GetContainer())
|
||||
nsRefPtr<ImageContainer> container = GetContainer();
|
||||
|
||||
if (!container)
|
||||
return;
|
||||
|
||||
mOGLManager->MakeCurrent();
|
||||
|
||||
nsRefPtr<Image> image = GetContainer()->GetCurrentImage();
|
||||
AutoLockImage autoLock(container);
|
||||
|
||||
Image *image = autoLock.GetImage();
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(image->GetFormat() != Image::REMOTE_IMAGE_BITMAP,
|
||||
"Remote images aren't handled yet in OGL layers!");
|
||||
|
||||
if (image->GetFormat() == Image::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImage *yuvImage =
|
||||
static_cast<PlanarYCbCrImage*>(image.get());
|
||||
static_cast<PlanarYCbCrImage*>(image);
|
||||
|
||||
if (!yuvImage->mBufferSize) {
|
||||
return;
|
||||
@ -276,7 +283,7 @@ ImageLayerOGL::RenderLayer(int,
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
} else if (image->GetFormat() == Image::CAIRO_SURFACE) {
|
||||
CairoImage *cairoImage =
|
||||
static_cast<CairoImage*>(image.get());
|
||||
static_cast<CairoImage*>(image);
|
||||
|
||||
if (!cairoImage->mSurface) {
|
||||
return;
|
||||
@ -424,16 +431,18 @@ ImageLayerOGL::RenderLayer(int,
|
||||
#ifdef XP_MACOSX
|
||||
} else if (image->GetFormat() == Image::MAC_IO_SURFACE) {
|
||||
MacIOSurfaceImage *ioImage =
|
||||
static_cast<MacIOSurfaceImage*>(image.get());
|
||||
static_cast<MacIOSurfaceImage*>(image);
|
||||
|
||||
if (!mOGLManager->GetThebesLayerCallback()) {
|
||||
// If its an empty transaction we still need to update
|
||||
// the plugin IO Surface and make sure we grab the
|
||||
// new image
|
||||
ioImage->Update(GetContainer());
|
||||
image = GetContainer()->GetCurrentImage();
|
||||
image = nsnull;
|
||||
autoLock.Refresh();
|
||||
image = autoLock.GetImage();
|
||||
gl()->MakeCurrent();
|
||||
ioImage = static_cast<MacIOSurfaceImage*>(image.get());
|
||||
ioImage = static_cast<MacIOSurfaceImage*>(image);
|
||||
}
|
||||
|
||||
if (!ioImage) {
|
||||
|
@ -54,6 +54,8 @@
|
||||
#include "LayerManagerOGLShaders.h"
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "GLContext.h"
|
||||
@ -779,8 +781,20 @@ LayerManagerOGL::Render()
|
||||
|
||||
mWidget->DrawWindowOverlay(this, rect);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (gfxUtils::sDumpPainting) {
|
||||
nsIntRect rect;
|
||||
mWidget->GetBounds(rect);
|
||||
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(rect.Size(), gfxASurface::CONTENT_COLOR_ALPHA);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
|
||||
CopyToTarget(ctx);
|
||||
|
||||
WriteSnapshotToDumpFile(this, surf);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mTarget) {
|
||||
CopyToTarget();
|
||||
CopyToTarget(mTarget);
|
||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
return;
|
||||
}
|
||||
@ -986,7 +1000,7 @@ LayerManagerOGL::SetupBackBuffer(int aWidth, int aHeight)
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::CopyToTarget()
|
||||
LayerManagerOGL::CopyToTarget(gfxContext *aTarget)
|
||||
{
|
||||
nsIntRect rect;
|
||||
mWidget->GetBounds(rect);
|
||||
@ -1050,11 +1064,11 @@ LayerManagerOGL::CopyToTarget()
|
||||
}
|
||||
}
|
||||
|
||||
mTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
mTarget->Scale(1.0, -1.0);
|
||||
mTarget->Translate(-gfxPoint(0.0, height));
|
||||
mTarget->SetSource(imageSurface);
|
||||
mTarget->Paint();
|
||||
aTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
aTarget->Scale(1.0, -1.0);
|
||||
aTarget->Translate(-gfxPoint(0.0, height));
|
||||
aTarget->SetSource(imageSurface);
|
||||
aTarget->Paint();
|
||||
}
|
||||
|
||||
LayerManagerOGL::ProgramType LayerManagerOGL::sLayerProgramTypes[] = {
|
||||
|
@ -236,9 +236,13 @@ public:
|
||||
}
|
||||
|
||||
ColorTextureLayerProgram *GetFBOLayerProgram() {
|
||||
return static_cast<ColorTextureLayerProgram*>(mPrograms[GetFBOLayerProgramType()]);
|
||||
}
|
||||
|
||||
gl::ShaderProgramType GetFBOLayerProgramType() {
|
||||
if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB)
|
||||
return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::RGBARectLayerProgramType]);
|
||||
return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::RGBALayerProgramType]);
|
||||
return gl::RGBARectLayerProgramType;
|
||||
return gl::RGBALayerProgramType;
|
||||
}
|
||||
|
||||
GLContext *gl() const { return mGLContext; }
|
||||
@ -451,7 +455,7 @@ private:
|
||||
/**
|
||||
* Copies the content of our backbuffer to the set transaction target.
|
||||
*/
|
||||
void CopyToTarget();
|
||||
void CopyToTarget(gfxContext *aTarget);
|
||||
|
||||
/**
|
||||
* Updates all layer programs with a new projection matrix.
|
||||
|
@ -145,6 +145,15 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
|
||||
mTexImageOnWhite->EndUpdate();
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (gfxUtils::sDumpPainting) {
|
||||
nsRefPtr<gfxImageSurface> surf =
|
||||
gl()->GetTexImage(mTexImage->GetTextureID(), false, mTexImage->GetShaderProgramType());
|
||||
|
||||
WriteSnapshotToDumpFile(mLayer, surf);
|
||||
}
|
||||
#endif
|
||||
|
||||
PRInt32 passes = mTexImageOnWhite ? 2 : 1;
|
||||
for (PRInt32 pass = 1; pass <= passes; ++pass) {
|
||||
LayerProgram *program;
|
||||
|
@ -716,9 +716,16 @@ gfxASurface::WriteAsPNG(const char* aFile)
|
||||
}
|
||||
|
||||
void
|
||||
gfxASurface::DumpAsDataURL()
|
||||
gfxASurface::DumpAsDataURL(FILE* aOutput)
|
||||
{
|
||||
WriteAsPNG_internal(aOutput, false);
|
||||
}
|
||||
|
||||
void
|
||||
gfxASurface::PrintAsDataURL()
|
||||
{
|
||||
WriteAsPNG_internal(stdout, false);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
@ -776,7 +783,6 @@ gfxASurface::WriteAsPNG_internal(FILE* aFile, bool aBinary)
|
||||
for (PRInt32 x = 0; x < w; ++x) {
|
||||
printf("%x ", reinterpret_cast<PRUint32*>(imgsurf->Data())[y*imgsurf->Stride()+ x]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -846,7 +852,6 @@ gfxASurface::WriteAsPNG_internal(FILE* aFile, bool aBinary)
|
||||
|
||||
if (aFile) {
|
||||
fprintf(aFile, "%s", string.BeginReading());
|
||||
fprintf(aFile, "\n");
|
||||
} else {
|
||||
nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
|
||||
if (clipboard) {
|
||||
|
@ -257,10 +257,15 @@ public:
|
||||
*/
|
||||
void WriteAsPNG(const char* aFile);
|
||||
|
||||
/**
|
||||
* Write as a PNG encoded Data URL to a file.
|
||||
*/
|
||||
void DumpAsDataURL(FILE* aOutput = stdout);
|
||||
|
||||
/**
|
||||
* Write as a PNG encoded Data URL to stdout.
|
||||
*/
|
||||
void DumpAsDataURL();
|
||||
void PrintAsDataURL();
|
||||
|
||||
/**
|
||||
* Copy a PNG encoded Data URL to the clipboard.
|
||||
|
@ -692,4 +692,8 @@ gfxUtils::CopyAsDataURL(DrawTarget* aDT)
|
||||
NS_WARNING("Failed to get Thebes surface!");
|
||||
}
|
||||
}
|
||||
|
||||
bool gfxUtils::sDumpPainting = getenv("MOZ_DUMP_PAINT_LIST") != 0;
|
||||
bool gfxUtils::sDumpPaintingToFile = getenv("MOZ_DUMP_PAINT_TO_FILE") != 0;
|
||||
FILE *gfxUtils::sDumpPaintFile = NULL;
|
||||
#endif
|
||||
|
@ -167,7 +167,12 @@ public:
|
||||
* Copy a PNG encoded Data URL to the clipboard.
|
||||
*/
|
||||
static void CopyAsDataURL(mozilla::gfx::DrawTarget* aDT);
|
||||
|
||||
static bool sDumpPainting;
|
||||
static bool sDumpPaintingToFile;
|
||||
static FILE* sDumpPaintFile;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -137,182 +137,194 @@ static void PrintImageDecoders()
|
||||
#endif
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ImagesMallocSizeOf, "images")
|
||||
|
||||
|
||||
class imgMemoryReporter MOZ_FINAL :
|
||||
public nsIMemoryReporter
|
||||
public nsIMemoryMultiReporter
|
||||
{
|
||||
public:
|
||||
enum ReporterType {
|
||||
CHROME_BIT = PR_BIT(0),
|
||||
USED_BIT = PR_BIT(1),
|
||||
RAW_BIT = PR_BIT(2),
|
||||
HEAP_BIT = PR_BIT(3),
|
||||
|
||||
ChromeUsedRaw = CHROME_BIT | USED_BIT | RAW_BIT | HEAP_BIT,
|
||||
ChromeUsedUncompressedHeap = CHROME_BIT | USED_BIT | HEAP_BIT,
|
||||
ChromeUsedUncompressedNonheap = CHROME_BIT | USED_BIT,
|
||||
ChromeUnusedRaw = CHROME_BIT | RAW_BIT | HEAP_BIT,
|
||||
ChromeUnusedUncompressedHeap = CHROME_BIT | HEAP_BIT,
|
||||
ChromeUnusedUncompressedNonheap = CHROME_BIT,
|
||||
ContentUsedRaw = USED_BIT | RAW_BIT | HEAP_BIT,
|
||||
ContentUsedUncompressedHeap = USED_BIT | HEAP_BIT,
|
||||
ContentUsedUncompressedNonheap = USED_BIT,
|
||||
ContentUnusedRaw = RAW_BIT | HEAP_BIT,
|
||||
ContentUnusedUncompressedHeap = HEAP_BIT,
|
||||
ContentUnusedUncompressedNonheap = 0
|
||||
};
|
||||
|
||||
imgMemoryReporter(ReporterType aType)
|
||||
: mType(aType)
|
||||
imgMemoryReporter()
|
||||
{
|
||||
// If the RAW bit is set, HEAP should also be set, because we don't
|
||||
// currently understand storing compressed image data off the heap.
|
||||
NS_ASSERTION(!(aType & RAW_BIT) || (aType & HEAP_BIT),
|
||||
"RAW bit should imply HEAP bit.");
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD GetProcess(nsACString &process)
|
||||
NS_IMETHOD GetName(nsACString &name)
|
||||
{
|
||||
process.Truncate();
|
||||
name.Assign("images");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetPath(nsACString &path)
|
||||
NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback,
|
||||
nsISupports *closure)
|
||||
{
|
||||
if (mType == ChromeUsedRaw) {
|
||||
path.AssignLiteral("explicit/images/chrome/used/raw");
|
||||
} else if (mType == ChromeUsedUncompressedHeap) {
|
||||
path.AssignLiteral("explicit/images/chrome/used/uncompressed-heap");
|
||||
} else if (mType == ChromeUsedUncompressedNonheap) {
|
||||
path.AssignLiteral("explicit/images/chrome/used/uncompressed-nonheap");
|
||||
} else if (mType == ChromeUnusedRaw) {
|
||||
path.AssignLiteral("explicit/images/chrome/unused/raw");
|
||||
} else if (mType == ChromeUnusedUncompressedHeap) {
|
||||
path.AssignLiteral("explicit/images/chrome/unused/uncompressed-heap");
|
||||
} else if (mType == ChromeUnusedUncompressedNonheap) {
|
||||
path.AssignLiteral("explicit/images/chrome/unused/uncompressed-nonheap");
|
||||
} else if (mType == ContentUsedRaw) {
|
||||
path.AssignLiteral("explicit/images/content/used/raw");
|
||||
} else if (mType == ContentUsedUncompressedHeap) {
|
||||
path.AssignLiteral("explicit/images/content/used/uncompressed-heap");
|
||||
} else if (mType == ContentUsedUncompressedNonheap) {
|
||||
path.AssignLiteral("explicit/images/content/used/uncompressed-nonheap");
|
||||
} else if (mType == ContentUnusedRaw) {
|
||||
path.AssignLiteral("explicit/images/content/unused/raw");
|
||||
} else if (mType == ContentUnusedUncompressedHeap) {
|
||||
path.AssignLiteral("explicit/images/content/unused/uncompressed-heap");
|
||||
} else if (mType == ContentUnusedUncompressedNonheap) {
|
||||
path.AssignLiteral("explicit/images/content/unused/uncompressed-nonheap");
|
||||
AllSizes chrome;
|
||||
AllSizes content;
|
||||
imgLoader::sChromeCache.EnumerateRead(EntryAllSizes, &chrome);
|
||||
imgLoader::sCache.EnumerateRead(EntryAllSizes, &content);
|
||||
|
||||
#define REPORT(_path, _kind, _amount, _desc) \
|
||||
do { \
|
||||
nsresult rv; \
|
||||
rv = callback->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
|
||||
_kind, nsIMemoryReporter::UNITS_BYTES, _amount, \
|
||||
NS_LITERAL_CSTRING(_desc), closure); \
|
||||
NS_ENSURE_SUCCESS(rv, rv); \
|
||||
} while (0)
|
||||
|
||||
REPORT("explicit/images/chrome/used/raw",
|
||||
nsIMemoryReporter::KIND_HEAP, chrome.mUsedRaw,
|
||||
"Memory used by in-use chrome images (compressed data).");
|
||||
|
||||
REPORT("explicit/images/chrome/used/uncompressed-heap",
|
||||
nsIMemoryReporter::KIND_HEAP, chrome.mUsedUncompressedHeap,
|
||||
"Memory used by in-use chrome images (uncompressed data).");
|
||||
|
||||
REPORT("explicit/images/chrome/used/uncompressed-nonheap",
|
||||
nsIMemoryReporter::KIND_NONHEAP, chrome.mUsedUncompressedNonheap,
|
||||
"Memory used by in-use chrome images (uncompressed data).");
|
||||
|
||||
REPORT("explicit/images/chrome/unused/raw",
|
||||
nsIMemoryReporter::KIND_HEAP, chrome.mUnusedRaw,
|
||||
"Memory used by not in-use chrome images (compressed data).");
|
||||
|
||||
REPORT("explicit/images/chrome/unused/uncompressed-heap",
|
||||
nsIMemoryReporter::KIND_HEAP, chrome.mUnusedUncompressedHeap,
|
||||
"Memory used by not in-use chrome images (uncompressed data).");
|
||||
|
||||
REPORT("explicit/images/chrome/unused/uncompressed-nonheap",
|
||||
nsIMemoryReporter::KIND_NONHEAP, chrome.mUnusedUncompressedNonheap,
|
||||
"Memory used by not in-use chrome images (uncompressed data).");
|
||||
|
||||
REPORT("explicit/images/content/used/raw",
|
||||
nsIMemoryReporter::KIND_HEAP, content.mUsedRaw,
|
||||
"Memory used by in-use content images (compressed data).");
|
||||
|
||||
REPORT("explicit/images/content/used/uncompressed-heap",
|
||||
nsIMemoryReporter::KIND_HEAP, content.mUsedUncompressedHeap,
|
||||
"Memory used by in-use content images (uncompressed data).");
|
||||
|
||||
REPORT("explicit/images/content/used/uncompressed-nonheap",
|
||||
nsIMemoryReporter::KIND_NONHEAP, content.mUsedUncompressedNonheap,
|
||||
"Memory used by in-use content images (uncompressed data).");
|
||||
|
||||
REPORT("explicit/images/content/unused/raw",
|
||||
nsIMemoryReporter::KIND_HEAP, content.mUnusedRaw,
|
||||
"Memory used by not in-use content images (compressed data).");
|
||||
|
||||
REPORT("explicit/images/content/unused/uncompressed-heap",
|
||||
nsIMemoryReporter::KIND_HEAP, content.mUnusedUncompressedHeap,
|
||||
"Memory used by not in-use content images (uncompressed data).");
|
||||
|
||||
REPORT("explicit/images/content/unused/uncompressed-nonheap",
|
||||
nsIMemoryReporter::KIND_NONHEAP, content.mUnusedUncompressedNonheap,
|
||||
"Memory used by not in-use content images (uncompressed data).");
|
||||
|
||||
#undef REPORT
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetExplicitNonHeap(PRInt64 *n)
|
||||
{
|
||||
size_t n2 = 0;
|
||||
imgLoader::sChromeCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
|
||||
imgLoader::sCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
|
||||
*n = n2;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static PRInt64 GetImagesContentUsedUncompressed()
|
||||
{
|
||||
size_t n = 0;
|
||||
imgLoader::sCache.EnumerateRead(EntryUsedUncompressedSize, &n);
|
||||
return n;
|
||||
}
|
||||
|
||||
private:
|
||||
struct AllSizes {
|
||||
size_t mUsedRaw;
|
||||
size_t mUsedUncompressedHeap;
|
||||
size_t mUsedUncompressedNonheap;
|
||||
size_t mUnusedRaw;
|
||||
size_t mUnusedUncompressedHeap;
|
||||
size_t mUnusedUncompressedNonheap;
|
||||
|
||||
AllSizes() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetKind(PRInt32 *kind)
|
||||
{
|
||||
if (mType & HEAP_BIT) {
|
||||
*kind = KIND_HEAP;
|
||||
}
|
||||
else {
|
||||
*kind = KIND_MAPPED;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetUnits(PRInt32 *units)
|
||||
{
|
||||
*units = UNITS_BYTES;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct EnumArg {
|
||||
EnumArg(ReporterType aType)
|
||||
: rtype(aType), n(0)
|
||||
{ }
|
||||
|
||||
ReporterType rtype;
|
||||
size_t n;
|
||||
};
|
||||
|
||||
static PLDHashOperator EnumEntries(const nsACString&,
|
||||
imgCacheEntry *entry,
|
||||
void *userArg)
|
||||
static PLDHashOperator EntryAllSizes(const nsACString&,
|
||||
imgCacheEntry *entry,
|
||||
void *userArg)
|
||||
{
|
||||
EnumArg *arg = static_cast<EnumArg*>(userArg);
|
||||
ReporterType rtype = arg->rtype;
|
||||
|
||||
if (rtype & USED_BIT) {
|
||||
if (entry->HasNoProxies())
|
||||
return PL_DHASH_NEXT;
|
||||
} else {
|
||||
if (!entry->HasNoProxies())
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsRefPtr<imgRequest> req = entry->GetRequest();
|
||||
Image *image = static_cast<Image*>(req->mImage.get());
|
||||
if (!image)
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
if (rtype & RAW_BIT) {
|
||||
arg->n += image->HeapSizeOfSourceWithComputedFallback(ImagesMallocSizeOf);
|
||||
} else if (rtype & HEAP_BIT) {
|
||||
arg->n += image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf);
|
||||
} else {
|
||||
arg->n += image->NonHeapSizeOfDecoded();
|
||||
if (image) {
|
||||
AllSizes *sizes = static_cast<AllSizes*>(userArg);
|
||||
if (entry->HasNoProxies()) {
|
||||
sizes->mUnusedRaw +=
|
||||
image->HeapSizeOfSourceWithComputedFallback(ImagesMallocSizeOf);
|
||||
sizes->mUnusedUncompressedHeap +=
|
||||
image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf);
|
||||
sizes->mUnusedUncompressedNonheap += image->NonHeapSizeOfDecoded();
|
||||
} else {
|
||||
sizes->mUsedRaw +=
|
||||
image->HeapSizeOfSourceWithComputedFallback(ImagesMallocSizeOf);
|
||||
sizes->mUsedUncompressedHeap +=
|
||||
image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf);
|
||||
sizes->mUsedUncompressedNonheap += image->NonHeapSizeOfDecoded();
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetAmount(PRInt64 *amount)
|
||||
static PLDHashOperator EntryExplicitNonHeapSize(const nsACString&,
|
||||
imgCacheEntry *entry,
|
||||
void *userArg)
|
||||
{
|
||||
EnumArg arg(mType);
|
||||
if (mType & CHROME_BIT) {
|
||||
imgLoader::sChromeCache.EnumerateRead(EnumEntries, &arg);
|
||||
} else {
|
||||
imgLoader::sCache.EnumerateRead(EnumEntries, &arg);
|
||||
size_t *n = static_cast<size_t*>(userArg);
|
||||
nsRefPtr<imgRequest> req = entry->GetRequest();
|
||||
Image *image = static_cast<Image*>(req->mImage.get());
|
||||
if (image) {
|
||||
*n += image->NonHeapSizeOfDecoded();
|
||||
}
|
||||
|
||||
*amount = arg.n;
|
||||
return NS_OK;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetDescription(nsACString &desc)
|
||||
static PLDHashOperator EntryUsedUncompressedSize(const nsACString&,
|
||||
imgCacheEntry *entry,
|
||||
void *userArg)
|
||||
{
|
||||
if (mType == ChromeUsedRaw) {
|
||||
desc.AssignLiteral("Memory used by in-use chrome images (compressed data).");
|
||||
} else if (mType == ChromeUsedUncompressedHeap) {
|
||||
desc.AssignLiteral("Memory used by in-use chrome images (uncompressed data).");
|
||||
} else if (mType == ChromeUsedUncompressedNonheap) {
|
||||
desc.AssignLiteral("Memory used by in-use chrome images (uncompressed data).");
|
||||
} else if (mType == ChromeUnusedRaw) {
|
||||
desc.AssignLiteral("Memory used by not in-use chrome images (compressed data).");
|
||||
} else if (mType == ChromeUnusedUncompressedHeap) {
|
||||
desc.AssignLiteral("Memory used by not in-use chrome images (uncompressed data).");
|
||||
} else if (mType == ChromeUnusedUncompressedNonheap) {
|
||||
desc.AssignLiteral("Memory used by not in-use chrome images (uncompressed data).");
|
||||
} else if (mType == ContentUsedRaw) {
|
||||
desc.AssignLiteral("Memory used by in-use content images (compressed data).");
|
||||
} else if (mType == ContentUsedUncompressedHeap) {
|
||||
desc.AssignLiteral("Memory used by in-use content images (uncompressed data).");
|
||||
} else if (mType == ContentUsedUncompressedNonheap) {
|
||||
desc.AssignLiteral("Memory used by in-use content images (uncompressed data).");
|
||||
} else if (mType == ContentUnusedRaw) {
|
||||
desc.AssignLiteral("Memory used by not in-use content images (compressed data).");
|
||||
} else if (mType == ContentUnusedUncompressedHeap) {
|
||||
desc.AssignLiteral("Memory used by not in-use content images (uncompressed data).");
|
||||
} else if (mType == ContentUnusedUncompressedNonheap) {
|
||||
desc.AssignLiteral("Memory used by not in-use content images (uncompressed data).");
|
||||
if (!entry->HasNoProxies()) {
|
||||
size_t *n = static_cast<size_t*>(userArg);
|
||||
nsRefPtr<imgRequest> req = entry->GetRequest();
|
||||
Image *image = static_cast<Image*>(req->mImage.get());
|
||||
if (image) {
|
||||
*n += image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf);
|
||||
*n += image->NonHeapSizeOfDecoded();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ReporterType mType;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(imgMemoryReporter, nsIMemoryReporter)
|
||||
// This is used by telemetry.
|
||||
NS_MEMORY_REPORTER_IMPLEMENT(
|
||||
ImagesContentUsedUncompressed,
|
||||
"images-content-used-uncompressed",
|
||||
KIND_OTHER,
|
||||
UNITS_BYTES,
|
||||
imgMemoryReporter::GetImagesContentUsedUncompressed,
|
||||
"This is the sum of the 'explicit/images/content/used/uncompressed-heap' "
|
||||
"and 'explicit/images/content/used/uncompressed-nonheap' numbers. However, "
|
||||
"it is measured at a different time and so may give slightly different "
|
||||
"results.")
|
||||
|
||||
NS_IMPL_ISUPPORTS1(imgMemoryReporter, nsIMemoryMultiReporter)
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsProgressNotificationProxy,
|
||||
nsIProgressEventSink,
|
||||
@ -922,18 +934,8 @@ nsresult imgLoader::InitCache()
|
||||
else
|
||||
sCacheMaxSize = 5 * 1024 * 1024;
|
||||
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUsedRaw));
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUsedUncompressedHeap));
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUsedUncompressedNonheap));
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUnusedRaw));
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUnusedUncompressedHeap));
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUnusedUncompressedNonheap));
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUsedRaw));
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUsedUncompressedHeap));
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUsedUncompressedNonheap));
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUnusedRaw));
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUnusedUncompressedHeap));
|
||||
NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUnusedUncompressedNonheap));
|
||||
NS_RegisterMemoryMultiReporter(new imgMemoryReporter());
|
||||
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(ImagesContentUsedUncompressed));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
133
ipc/glue/CrossProcessMutex.h
Normal file
@ -0,0 +1,133 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_CrossProcessMutex_h
|
||||
#define mozilla_CrossProcessMutex_h
|
||||
|
||||
#include "base/process.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
namespace IPC {
|
||||
template<typename T>
|
||||
struct ParamTraits;
|
||||
}
|
||||
|
||||
//
|
||||
// Provides:
|
||||
//
|
||||
// - CrossProcessMutex, a non-recursive mutex that can be shared across processes
|
||||
// - CrossProcessMutexAutoLock, an RAII class for ensuring that Mutexes are
|
||||
// properly locked and unlocked
|
||||
//
|
||||
// Using CrossProcessMutexAutoLock/CrossProcessMutexAutoUnlock is MUCH
|
||||
// preferred to making bare calls to CrossProcessMutex.Lock and Unlock.
|
||||
//
|
||||
namespace mozilla {
|
||||
#ifdef XP_WIN
|
||||
typedef HANDLE CrossProcessMutexHandle;
|
||||
#else
|
||||
// Stub for other platforms. We can't use uintptr_t here since different
|
||||
// processes could disagree on its size.
|
||||
typedef uintptr_t CrossProcessMutexHandle;
|
||||
#endif
|
||||
|
||||
class NS_COM_GLUE CrossProcessMutex
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* CrossProcessMutex
|
||||
* @param name A name which can reference this lock (currently unused)
|
||||
**/
|
||||
CrossProcessMutex(const char* aName);
|
||||
/**
|
||||
* CrossProcessMutex
|
||||
* @param handle A handle of an existing cross process mutex that can be
|
||||
* opened.
|
||||
*/
|
||||
CrossProcessMutex(CrossProcessMutexHandle aHandle);
|
||||
|
||||
/**
|
||||
* ~CrossProcessMutex
|
||||
**/
|
||||
~CrossProcessMutex();
|
||||
|
||||
/**
|
||||
* Lock
|
||||
* This will lock the mutex. Any other thread in any other process that
|
||||
* has access to this mutex calling lock will block execution until the
|
||||
* initial caller of lock has made a call to Unlock.
|
||||
*
|
||||
* If the owning process is terminated unexpectedly the mutex will be
|
||||
* released.
|
||||
**/
|
||||
void Lock();
|
||||
|
||||
/**
|
||||
* Unlock
|
||||
* This will unlock the mutex. A single thread currently waiting on a lock
|
||||
* call will resume execution and aquire ownership of the lock. No
|
||||
* guarantees are made as to the order in which waiting threads will resume
|
||||
* execution.
|
||||
**/
|
||||
void Unlock();
|
||||
|
||||
/**
|
||||
* ShareToProcess
|
||||
* This function is called to generate a serializable structure that can
|
||||
* be sent to the specified process and opened on the other side.
|
||||
*
|
||||
* @returns A handle that can be shared to another process
|
||||
*/
|
||||
CrossProcessMutexHandle ShareToProcess(base::ProcessHandle aTarget);
|
||||
|
||||
private:
|
||||
friend struct IPC::ParamTraits<CrossProcessMutex>;
|
||||
|
||||
CrossProcessMutex();
|
||||
CrossProcessMutex(const CrossProcessMutex&);
|
||||
CrossProcessMutex &operator=(const CrossProcessMutex&);
|
||||
|
||||
#ifdef XP_WIN
|
||||
HANDLE mMutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef BaseAutoLock<CrossProcessMutex> CrossProcessMutexAutoLock;
|
||||
typedef BaseAutoUnlock<CrossProcessMutex> CrossProcessMutexAutoUnlock;
|
||||
|
||||
}
|
||||
#endif
|
78
ipc/glue/CrossProcessMutex_unimplemented.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "CrossProcessMutex.h"
|
||||
|
||||
#include "nsDebug.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
CrossProcessMutex::CrossProcessMutex(const char*)
|
||||
{
|
||||
NS_RUNTIMEABORT("Cross-process mutices not allowed on this platform.");
|
||||
}
|
||||
|
||||
CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle)
|
||||
{
|
||||
NS_RUNTIMEABORT("Cross-process mutices not allowed on this platform.");
|
||||
}
|
||||
|
||||
CrossProcessMutex::~CrossProcessMutex()
|
||||
{
|
||||
NS_RUNTIMEABORT("Cross-process mutices not allowed on this platform - woah! We should've aborted by now!");
|
||||
}
|
||||
|
||||
void
|
||||
CrossProcessMutex::Lock()
|
||||
{
|
||||
NS_RUNTIMEABORT("Cross-process mutices not allowed on this platform - woah! We should've aborted by now!");
|
||||
}
|
||||
|
||||
void
|
||||
CrossProcessMutex::Unlock()
|
||||
{
|
||||
NS_RUNTIMEABORT("Cross-process mutices not allowed on this platform - woah! We should've aborted by now!");
|
||||
}
|
||||
|
||||
CrossProcessMutexHandle
|
||||
CrossProcessMutex::ShareToProcess(base::ProcessHandle aHandle)
|
||||
{
|
||||
NS_RUNTIMEABORT("Cross-process mutices not allowed on this platform - woah! We should've aborted by now!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
106
ipc/glue/CrossProcessMutex_windows.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "base/process_util.h"
|
||||
#include "CrossProcessMutex.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
using namespace base;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
CrossProcessMutex::CrossProcessMutex(const char*)
|
||||
{
|
||||
// We explicitly share this using DuplicateHandle, we do -not- want this to
|
||||
// be inherited by child processes by default! So no security attributes are
|
||||
// given.
|
||||
mMutex = ::CreateMutexA(NULL, FALSE, NULL);
|
||||
if (!mMutex) {
|
||||
NS_RUNTIMEABORT("This shouldn't happen - failed to create mutex!");
|
||||
}
|
||||
MOZ_COUNT_CTOR(CrossProcessMutex);
|
||||
}
|
||||
|
||||
CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle)
|
||||
{
|
||||
DWORD flags;
|
||||
if (!::GetHandleInformation(aHandle, &flags)) {
|
||||
NS_RUNTIMEABORT("Attempt to construct a mutex from an invalid handle!");
|
||||
}
|
||||
mMutex = aHandle;
|
||||
}
|
||||
|
||||
CrossProcessMutex::~CrossProcessMutex()
|
||||
{
|
||||
NS_ASSERTION(mMutex, "Improper construction of mutex or double free.");
|
||||
::CloseHandle(mMutex);
|
||||
MOZ_COUNT_DTOR(CrossProcessMutex);
|
||||
}
|
||||
|
||||
void
|
||||
CrossProcessMutex::Lock()
|
||||
{
|
||||
NS_ASSERTION(mMutex, "Improper construction of mutex.");
|
||||
::WaitForSingleObject(mMutex, INFINITE);
|
||||
}
|
||||
|
||||
void
|
||||
CrossProcessMutex::Unlock()
|
||||
{
|
||||
NS_ASSERTION(mMutex, "Improper construction of mutex.");
|
||||
::ReleaseMutex(mMutex);
|
||||
}
|
||||
|
||||
CrossProcessMutexHandle
|
||||
CrossProcessMutex::ShareToProcess(ProcessHandle aHandle)
|
||||
{
|
||||
HANDLE newHandle;
|
||||
bool succeeded = ::DuplicateHandle(GetCurrentProcessHandle(),
|
||||
mMutex, aHandle, &newHandle,
|
||||
NULL, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
|
||||
if (!succeeded) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return newHandle;
|
||||
}
|
||||
|
||||
}
|
@ -56,6 +56,7 @@ EXPORTS_IPC = IPCMessageUtils.h
|
||||
EXPORTS_mozilla/ipc = \
|
||||
AsyncChannel.h \
|
||||
BrowserProcessSubThread.h \
|
||||
CrossProcessMutex.h \
|
||||
GeckoChildProcessHost.h \
|
||||
IOThreadChild.h \
|
||||
ProcessChild.h \
|
||||
@ -111,12 +112,14 @@ CPPSRCS += \
|
||||
SharedMemory_windows.cpp \
|
||||
Transport_win.cpp \
|
||||
WindowsMessageLoop.cpp \
|
||||
CrossProcessMutex_windows.cpp \
|
||||
$(NULL)
|
||||
else
|
||||
# POSIX
|
||||
CPPSRCS += \
|
||||
SharedMemory_posix.cpp \
|
||||
Transport_posix.cpp \
|
||||
CrossProcessMutex_unimplemented.cpp \
|
||||
$(NULL)
|
||||
endif #}
|
||||
|
||||
|
@ -507,10 +507,12 @@ DumpHeap(JSContext *cx,
|
||||
}
|
||||
}
|
||||
|
||||
ok = JS_DumpHeap(cx, dumpFile, startThing, startTraceKind, thingToFind,
|
||||
ok = JS_DumpHeap(JS_GetRuntime(cx), dumpFile, startThing, startTraceKind, thingToFind,
|
||||
maxDepth, thingToIgnore);
|
||||
if (dumpFile != stdout)
|
||||
fclose(dumpFile);
|
||||
if (!ok)
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return ok;
|
||||
|
||||
not_traceable_arg:
|
||||
|
@ -2835,7 +2835,7 @@ jsdService::DumpHeap(const nsACString &fileName)
|
||||
rv = NS_ERROR_FAILURE;
|
||||
} else {
|
||||
JSContext *cx = JSD_GetDefaultJSContext (mCx);
|
||||
if (!JS_DumpHeap(cx, file, NULL, JSTRACE_OBJECT, NULL, (size_t)-1, NULL))
|
||||
if (!JS_DumpHeap(JS_GetRuntime(cx), file, NULL, JSTRACE_OBJECT, NULL, (size_t)-1, NULL))
|
||||
rv = NS_ERROR_FAILURE;
|
||||
if (file != stdout)
|
||||
fclose(file);
|
||||
|
@ -1062,7 +1062,7 @@ class HashMap
|
||||
*/
|
||||
typedef typename Impl::Range Range;
|
||||
Range all() const { return impl.all(); }
|
||||
size_t count() const { return impl.count(); }
|
||||
uint32_t count() const { return impl.count(); }
|
||||
size_t capacity() const { return impl.capacity(); }
|
||||
size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const {
|
||||
return impl.sizeOfExcludingThis(mallocSizeOf);
|
||||
@ -1272,7 +1272,7 @@ class HashSet
|
||||
*/
|
||||
typedef typename Impl::Range Range;
|
||||
Range all() const { return impl.all(); }
|
||||
size_t count() const { return impl.count(); }
|
||||
uint32_t count() const { return impl.count(); }
|
||||
size_t capacity() const { return impl.capacity(); }
|
||||
size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const {
|
||||
return impl.sizeOfExcludingThis(mallocSizeOf);
|
||||
|
@ -115,7 +115,7 @@ extern JS_PUBLIC_DATA(uint32_t) OOM_counter; /* data race, who cares. */
|
||||
# define JS_OOM_POSSIBLY_FAIL() \
|
||||
do \
|
||||
{ \
|
||||
if (OOM_counter++ >= OOM_maxAllocations) { \
|
||||
if (++OOM_counter > OOM_maxAllocations) { \
|
||||
return NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
@ -3,8 +3,13 @@ dnl disabling frame pointers in this architecture based on the configure
|
||||
dnl options
|
||||
|
||||
AC_DEFUN([MOZ_SET_FRAMEPTR_FLAGS], [
|
||||
case "$target" in
|
||||
*android*)
|
||||
unwind_tables="-funwind-tables"
|
||||
;;
|
||||
esac
|
||||
if test "$GNU_CC"; then
|
||||
MOZ_ENABLE_FRAME_PTR="-fno-omit-frame-pointer"
|
||||
MOZ_ENABLE_FRAME_PTR="-fno-omit-frame-pointer $unwind_tables"
|
||||
MOZ_DISABLE_FRAME_PTR="-fomit-frame-pointer"
|
||||
else
|
||||
case "$target" in
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsgcmark.h"
|
||||
#include "jsiter.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "vm/GlobalObject.h"
|
||||
@ -62,7 +63,7 @@ InitClass(JSContext *cx, GlobalObject *global, Class *clasp, JSProtoKey key, Nat
|
||||
proto->setPrivate(NULL);
|
||||
|
||||
JSAtom *atom = cx->runtime->atomState.classAtoms[key];
|
||||
JSFunction *ctor = global->createConstructor(cx, construct, clasp, atom, 0);
|
||||
JSFunction *ctor = global->createConstructor(cx, construct, clasp, atom, 1);
|
||||
if (!ctor ||
|
||||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
|
||||
!DefinePropertiesAndBrand(cx, proto, NULL, methods) ||
|
||||
@ -165,6 +166,7 @@ Class MapObject::class_ = {
|
||||
};
|
||||
|
||||
JSFunctionSpec MapObject::methods[] = {
|
||||
JS_FN("size", size, 0, 0),
|
||||
JS_FN("get", get, 1, 0),
|
||||
JS_FN("has", has, 1, 0),
|
||||
JS_FN("set", set, 2, 0),
|
||||
@ -201,6 +203,37 @@ MapObject::finalize(JSContext *cx, JSObject *obj)
|
||||
cx->delete_(map);
|
||||
}
|
||||
|
||||
class AddToMap {
|
||||
private:
|
||||
ValueMap *map;
|
||||
|
||||
public:
|
||||
AddToMap(ValueMap *map) : map(map) {}
|
||||
|
||||
bool operator()(JSContext *cx, const Value &v) {
|
||||
JSObject *pairobj = js_ValueToNonNullObject(cx, v);
|
||||
if (!pairobj)
|
||||
return false;
|
||||
|
||||
Value key;
|
||||
if (!pairobj->getElement(cx, 0, &key))
|
||||
return false;
|
||||
HashableValue hkey;
|
||||
if (!hkey.setValue(cx, key))
|
||||
return false;
|
||||
|
||||
Value val;
|
||||
if (!pairobj->getElement(cx, 1, &val))
|
||||
return false;
|
||||
|
||||
if (!map->put(hkey, val)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
JSBool
|
||||
MapObject::construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
@ -209,11 +242,21 @@ MapObject::construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
return false;
|
||||
|
||||
ValueMap *map = cx->new_<ValueMap>(cx->runtime);
|
||||
if (!map || !map->init())
|
||||
if (!map)
|
||||
return false;
|
||||
if (!map->init()) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
obj->setPrivate(map);
|
||||
|
||||
CallArgsFromVp(argc, vp).rval().setObject(*obj);
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.hasDefined(0)) {
|
||||
if (!ForOf(cx, args[0], AddToMap(map)))
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -240,6 +283,15 @@ MapObject::construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
if (args.length() > 0 && !key.setValue(cx, args[0])) \
|
||||
return false
|
||||
|
||||
JSBool
|
||||
MapObject::size(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
THIS_MAP(get, cx, argc, vp, args, map);
|
||||
JS_STATIC_ASSERT(sizeof map.count() <= sizeof(uint32_t));
|
||||
args.rval().setNumber(map.count());
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
MapObject::get(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
@ -267,7 +319,10 @@ MapObject::set(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
THIS_MAP(set, cx, argc, vp, args, map);
|
||||
ARG0_KEY(cx, args, key);
|
||||
map.put(key, args.length() > 1 ? args[1] : UndefinedValue());
|
||||
if (!map.put(key, args.length() > 1 ? args[1] : UndefinedValue())) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
@ -314,6 +369,7 @@ Class SetObject::class_ = {
|
||||
};
|
||||
|
||||
JSFunctionSpec SetObject::methods[] = {
|
||||
JS_FN("size", size, 0, 0),
|
||||
JS_FN("has", has, 1, 0),
|
||||
JS_FN("add", add, 1, 0),
|
||||
JS_FN("delete", delete_, 1, 0),
|
||||
@ -348,6 +404,25 @@ SetObject::finalize(JSContext *cx, JSObject *obj)
|
||||
cx->delete_(set);
|
||||
}
|
||||
|
||||
class AddToSet {
|
||||
private:
|
||||
ValueSet *set;
|
||||
|
||||
public:
|
||||
AddToSet(ValueSet *set) : set(set) {}
|
||||
|
||||
bool operator()(JSContext *cx, const Value &v) {
|
||||
HashableValue key;
|
||||
if (!key.setValue(cx, v))
|
||||
return false;
|
||||
if (!set->put(key)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
JSBool
|
||||
SetObject::construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
@ -356,17 +431,36 @@ SetObject::construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
return false;
|
||||
|
||||
ValueSet *set = cx->new_<ValueSet>(cx->runtime);
|
||||
if (!set || !set->init())
|
||||
if (!set)
|
||||
return false;
|
||||
if (!set->init()) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
obj->setPrivate(set);
|
||||
|
||||
CallArgsFromVp(argc, vp).rval().setObject(*obj);
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.hasDefined(0)) {
|
||||
if (!ForOf(cx, args[0], AddToSet(set)))
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define THIS_SET(native, cx, argc, vp, args, set) \
|
||||
UNPACK_THIS(SetObject, native, cx, argc, vp, args, set)
|
||||
|
||||
JSBool
|
||||
SetObject::size(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
THIS_SET(has, cx, argc, vp, args, set);
|
||||
JS_STATIC_ASSERT(sizeof set.count() <= sizeof(uint32_t));
|
||||
args.rval().setNumber(set.count());
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
SetObject::has(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
@ -381,8 +475,10 @@ SetObject::add(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
THIS_SET(add, cx, argc, vp, args, set);
|
||||
ARG0_KEY(cx, args, key);
|
||||
if (!set.put(key))
|
||||
if (!set.put(key)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ class MapObject : public JSObject {
|
||||
static void mark(JSTracer *trc, JSObject *obj);
|
||||
static void finalize(JSContext *cx, JSObject *obj);
|
||||
static JSBool construct(JSContext *cx, unsigned argc, Value *vp);
|
||||
static JSBool size(JSContext *cx, unsigned argc, Value *vp);
|
||||
static JSBool get(JSContext *cx, unsigned argc, Value *vp);
|
||||
static JSBool has(JSContext *cx, unsigned argc, Value *vp);
|
||||
static JSBool set(JSContext *cx, unsigned argc, Value *vp);
|
||||
@ -106,6 +107,7 @@ class SetObject : public JSObject {
|
||||
static void mark(JSTracer *trc, JSObject *obj);
|
||||
static void finalize(JSContext *cx, JSObject *obj);
|
||||
static JSBool construct(JSContext *cx, unsigned argc, Value *vp);
|
||||
static JSBool size(JSContext *cx, unsigned argc, Value *vp);
|
||||
static JSBool has(JSContext *cx, unsigned argc, Value *vp);
|
||||
static JSBool add(JSContext *cx, unsigned argc, Value *vp);
|
||||
static JSBool delete_(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
@ -244,7 +244,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
|
||||
*/
|
||||
JSObject &sourceObj = sourceValue.toObject();
|
||||
|
||||
if (args.length() >= 2 && !args[1].isUndefined()) {
|
||||
if (args.hasDefined(1)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEWREGEXP_FLAGGED);
|
||||
return false;
|
||||
}
|
||||
@ -293,7 +293,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
|
||||
}
|
||||
|
||||
RegExpFlag flags = RegExpFlag(0);
|
||||
if (args.length() > 1 && !args[1].isUndefined()) {
|
||||
if (args.hasDefined(1)) {
|
||||
JSString *flagStr = ToString(cx, args[1]);
|
||||
if (!flagStr)
|
||||
return false;
|
||||
@ -343,8 +343,9 @@ regexp_construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
* Otherwise, delegate to the standard constructor.
|
||||
* See ECMAv5 15.10.3.1.
|
||||
*/
|
||||
if (args.length() >= 1 && IsObjectWithClass(args[0], ESClass_RegExp, cx) &&
|
||||
(args.length() == 1 || args[1].isUndefined()))
|
||||
if (args.hasDefined(0) &&
|
||||
IsObjectWithClass(args[0], ESClass_RegExp, cx) &&
|
||||
!args.hasDefined(1))
|
||||
{
|
||||
args.rval() = args[0];
|
||||
return true;
|
||||
|
@ -913,6 +913,7 @@ sechash.h
|
||||
secoidt.h
|
||||
certdb.h
|
||||
secerr.h
|
||||
nssutil.h
|
||||
nssb64.h
|
||||
secasn1.h
|
||||
secder.h
|
||||
|
14
js/src/jit-test/tests/basic/bug730888.js
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
(function() {
|
||||
for (var i = 0; i < 64; ++i) {
|
||||
var name;
|
||||
switch (this) {
|
||||
case 0: name = 'firstAttr'; break;
|
||||
case 1: name = 'secondAttr';
|
||||
case 2: name = 'thirdAttr'; break;
|
||||
}
|
||||
switch (name) {
|
||||
case 'firstAttr': assertEq(result, 'value'); break;
|
||||
}
|
||||
}
|
||||
})();
|
6
js/src/jit-test/tests/basic/bug732087.js
Normal file
@ -0,0 +1,6 @@
|
||||
gczeal(2,1);
|
||||
var count = 0;
|
||||
var a = {__noSuchMethod__: function() { count++; } }
|
||||
for (var i = 0; i < 10; i++) {
|
||||
a.b();
|
||||
}
|
6
js/src/jit-test/tests/collections/Map-constructor-1.js
Normal file
@ -0,0 +1,6 @@
|
||||
// The Map constructor creates an empty Map by default.
|
||||
|
||||
assertEq(Map().size(), 0);
|
||||
assertEq((new Map).size(), 0);
|
||||
assertEq(Map(undefined).size(), 0);
|
||||
assertEq(new Map(undefined).size(), 0);
|
6
js/src/jit-test/tests/collections/Map-constructor-2.js
Normal file
@ -0,0 +1,6 @@
|
||||
// The Map constructor can take an argument that is an array of pairs.
|
||||
|
||||
var arr = [["zero", 0], ["one", 1], ["two", 2]];
|
||||
var m = Map(arr);
|
||||
for (var [k, v] of arr)
|
||||
assertEq(m.get(k), v);
|
9
js/src/jit-test/tests/collections/Map-constructor-3.js
Normal file
@ -0,0 +1,9 @@
|
||||
// Map can take an argument that is an array of singleton arrays.
|
||||
|
||||
var arr = [["a"], ["b"], ["c"]];
|
||||
var m = Map(arr);
|
||||
assertEq(m.size(), 3);
|
||||
for (var [k, _] of arr) {
|
||||
assertEq(m.has(k), true);
|
||||
assertEq(m.get(k), undefined);
|
||||
}
|
6
js/src/jit-test/tests/collections/Map-constructor-4.js
Normal file
@ -0,0 +1,6 @@
|
||||
// Map(x) throws if x is not iterable (unless x is undefined).
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
var nonIterables = [null, true, 1, -0, 3.14, NaN, "", "xyzzy", {}, Math, this];
|
||||
for (let k of nonIterables)
|
||||
assertThrowsInstanceOf(function () { Map(k); }, TypeError);
|
7
js/src/jit-test/tests/collections/Map-constructor-5.js
Normal file
@ -0,0 +1,7 @@
|
||||
// Map(arr) throws if arr contains holes (or undefined values).
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
assertThrowsInstanceOf(function () { Map([undefined]); }, TypeError);
|
||||
assertThrowsInstanceOf(function () { Map([null]); }, TypeError);
|
||||
assertThrowsInstanceOf(function () { Map([[0, 0], [1, 1], , [3, 3]]); }, TypeError);
|
||||
assertThrowsInstanceOf(function () { Map([[0, 0], [1, 1], ,]); }, TypeError);
|
@ -0,0 +1,8 @@
|
||||
// When the argument to Map contains a key multiple times, the last value is retained.
|
||||
|
||||
var arg = [["zero", 7], ["one", 1], ["two", 4], ["zero", 8], ["two", 2], ["zero", 0]];
|
||||
var m = Map(arg);
|
||||
assertEq(m.get("zero"), 0);
|
||||
assertEq(m.get("one"), 1);
|
||||
assertEq(m.get("two"), 2);
|
||||
assertEq(m.size(), 3);
|
@ -0,0 +1,19 @@
|
||||
// The argument to Map can be a generator.
|
||||
|
||||
var done = false;
|
||||
function data(n) {
|
||||
var s = '';
|
||||
for (var i = 0; i < n; i++) {
|
||||
yield [s, i];
|
||||
s += '.';
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
|
||||
var m = Map(data(50));
|
||||
assertEq(done, true); // the constructor consumes the argument
|
||||
assertEq(m.size(), 50);
|
||||
assertEq(m.get(""), 0);
|
||||
assertEq(m.get("....."), 5);
|
||||
assertEq(m.get(Array(49+1).join(".")), 49);
|
||||
assertEq(m.has(undefined), false);
|