mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 09:49:14 +00:00
Merge mozilla-central to tabcandy-central.
This commit is contained in:
commit
8f0189e0d4
@ -83,13 +83,9 @@ toolbar[printpreview="true"] {
|
||||
}
|
||||
|
||||
%ifdef MENUBAR_CAN_AUTOHIDE
|
||||
#main-window[inFullscreen] > #titlebar {
|
||||
#main-window[inFullscreen] > #appmenu-button-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#titlebar {
|
||||
-moz-binding: url("chrome://global/content/bindings/general.xml#windowdragbox");
|
||||
}
|
||||
%endif
|
||||
|
||||
toolbarpaletteitem[place="palette"] > toolbaritem > hbox[type="places"] {
|
||||
@ -326,6 +322,7 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
|
||||
notifications are */
|
||||
.notification-anchor-icon {
|
||||
display: none;
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
#notification-popup-box[anchorid="geo-notification-icon"] > #geo-notification-icon,
|
||||
|
@ -159,9 +159,13 @@ XPCOMUtils.defineLazyGetter(this, "Weave", function() {
|
||||
XPCOMUtils.defineLazyGetter(this, "PopupNotifications", function () {
|
||||
let tmp = {};
|
||||
Cu.import("resource://gre/modules/PopupNotifications.jsm", tmp);
|
||||
return new tmp.PopupNotifications(gBrowser,
|
||||
document.getElementById("notification-popup"),
|
||||
document.getElementById("notification-popup-box"));
|
||||
try {
|
||||
return new tmp.PopupNotifications(gBrowser,
|
||||
document.getElementById("notification-popup"),
|
||||
document.getElementById("notification-popup-box"));
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
});
|
||||
|
||||
let gInitialPages = [
|
||||
@ -1317,15 +1321,6 @@ function prepareForStartup() {
|
||||
|
||||
// setup simple gestures support
|
||||
gGestureSupport.init(true);
|
||||
|
||||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
// update the visibility of the titlebar buttons after the window is
|
||||
// displayed. (required by theme code.)
|
||||
window.addEventListener("MozAfterPaint", function () {
|
||||
window.removeEventListener("MozAfterPaint", arguments.callee, false);
|
||||
document.getElementById("titlebar-buttonbox").collapsed = false;
|
||||
}, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
function delayedStartup(isLoadingBlank, mustLoadSidebar) {
|
||||
@ -4770,20 +4765,13 @@ function updateAppButtonDisplay() {
|
||||
window.menubar.visible &&
|
||||
document.getElementById("toolbar-menubar").getAttribute("autohide") == "true";
|
||||
|
||||
document.getElementById("titlebar").hidden = !displayAppButton;
|
||||
document.getElementById("appmenu-button-container").hidden = !displayAppButton;
|
||||
|
||||
if (displayAppButton)
|
||||
document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
|
||||
else
|
||||
document.documentElement.removeAttribute("chromemargin");
|
||||
}
|
||||
|
||||
function onTitlebarMaxClick() {
|
||||
if (window.windowState == window.STATE_MAXIMIZED)
|
||||
window.restore();
|
||||
else
|
||||
window.maximize();
|
||||
}
|
||||
#endif
|
||||
|
||||
function displaySecurityInfo()
|
||||
|
@ -452,9 +452,7 @@
|
||||
</popupset>
|
||||
|
||||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
<vbox id="titlebar">
|
||||
<hbox id="titlebar-content">
|
||||
<hbox id="appmenu-button-container" align="start">
|
||||
<hbox id="appmenu-button-container">
|
||||
<button id="appmenu-button"
|
||||
type="menu"
|
||||
label="&brandShortName;"
|
||||
@ -594,15 +592,7 @@
|
||||
command="cmd_quitApplication"/>
|
||||
</menupopup>
|
||||
</button>
|
||||
</hbox>
|
||||
<spacer id="titlebar-spacer" flex="1"/>
|
||||
<hbox id="titlebar-buttonbox" collapsed="true">
|
||||
<toolbarbutton id="titlebar-min" onclick="window.minimize();"/>
|
||||
<toolbarbutton id="titlebar-max" onclick="onTitlebarMaxClick();"/>
|
||||
<toolbarbutton id="titlebar-close" onclick="window.close();"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
#endif
|
||||
|
||||
<toolbox id="navigator-toolbox"
|
||||
@ -720,8 +710,8 @@
|
||||
onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
|
||||
onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);">
|
||||
<box id="notification-popup-box" hidden="true" align="center">
|
||||
<image id="geo-notification-icon" class="notification-anchor-icon"/>
|
||||
<image id="addons-notification-icon" class="notification-anchor-icon"/>
|
||||
<image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
</box>
|
||||
<!-- Use onclick instead of normal popup= syntax since the popup
|
||||
code fires onmousedown, and hence eats our favicon drag events.
|
||||
|
@ -296,7 +296,7 @@ var tests = [
|
||||
this.firstNotification = showNotification(this.notifyObj);
|
||||
this.notifyObj2 = new basicNotification();
|
||||
this.notifyObj2.id += "-2";
|
||||
this.notifyObj2.anchorID = "urlbar";
|
||||
this.notifyObj2.anchorID = "addons-notification-icon";
|
||||
// Second showNotification() overrides the first
|
||||
this.secondNotification = showNotification(this.notifyObj2);
|
||||
},
|
||||
@ -485,15 +485,17 @@ function triggerSecondaryCommand(popup, index) {
|
||||
}
|
||||
|
||||
function loadURI(uri, callback) {
|
||||
gBrowser.addEventListener("load", function() {
|
||||
// Ignore the about:blank load
|
||||
if (gBrowser.currentURI.spec != uri)
|
||||
return;
|
||||
if (callback) {
|
||||
gBrowser.addEventListener("load", function() {
|
||||
// Ignore the about:blank load
|
||||
if (gBrowser.currentURI.spec != uri)
|
||||
return;
|
||||
|
||||
gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
callback();
|
||||
}, true);
|
||||
callback();
|
||||
}, true);
|
||||
}
|
||||
gBrowser.loadURI(uri);
|
||||
}
|
||||
|
||||
@ -502,4 +504,4 @@ function dismissNotification(popup) {
|
||||
executeSoon(function () {
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
});
|
||||
}
|
||||
}
|
@ -36,6 +36,20 @@ function closeContextMenu() {
|
||||
contextMenu.hidePopup();
|
||||
}
|
||||
|
||||
function executeCopyCommand(command, expectedValue)
|
||||
{
|
||||
// Just execute the command directly rather than simulating a context menu
|
||||
// press to avoid having to deal with its asynchronous nature
|
||||
subwindow.controllers.getControllerForCommand(command).doCommand(command);
|
||||
|
||||
// The easiest way to check the clipboard is to paste the contents into a
|
||||
// textbox
|
||||
input.focus();
|
||||
input.value = "";
|
||||
input.controllers.getControllerForCommand("cmd_paste").doCommand("cmd_paste");
|
||||
is(input.value, expectedValue, "paste for command " + command);
|
||||
}
|
||||
|
||||
function getVisibleMenuItems(aMenu) {
|
||||
var items = [];
|
||||
var accessKeys = {};
|
||||
@ -391,6 +405,13 @@ function runTest(testNum) {
|
||||
"spell-add-dictionaries", true], null]);
|
||||
|
||||
closeContextMenu();
|
||||
openContextMenuFor(link); // Invoke context menu for next test.
|
||||
break;
|
||||
|
||||
case 15:
|
||||
executeCopyCommand("cmd_copyLink", "http://mozilla.com/");
|
||||
closeContextMenu();
|
||||
|
||||
subwindow.close();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
|
@ -52,6 +52,11 @@ const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
return NetUtil;
|
||||
});
|
||||
|
||||
const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
|
||||
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
|
||||
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
|
||||
@ -840,16 +845,18 @@ BrowserGlue.prototype = {
|
||||
var dirService = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
|
||||
var bookmarksFile = null;
|
||||
var bookmarksURI = null;
|
||||
if (restoreDefaultBookmarks) {
|
||||
// User wants to restore bookmarks.html file from default profile folder
|
||||
bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
|
||||
bookmarksFile.append("bookmarks.html");
|
||||
bookmarksURI = NetUtil.newURI("resource:///defaults/profile/bookmarks.html");
|
||||
}
|
||||
else {
|
||||
var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
|
||||
if (bookmarksFile.exists())
|
||||
bookmarksURI = NetUtil.newURI(bookmarksFile);
|
||||
}
|
||||
else
|
||||
bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
|
||||
|
||||
if (bookmarksFile.exists()) {
|
||||
if (bookmarksURI) {
|
||||
// Add an import observer. It will ensure that smart bookmarks are
|
||||
// created once the operation is complete.
|
||||
Services.obs.addObserver(this, "bookmarks-restore-success", false);
|
||||
@ -859,7 +866,7 @@ BrowserGlue.prototype = {
|
||||
try {
|
||||
var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
|
||||
getService(Ci.nsIPlacesImportExportService);
|
||||
importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
|
||||
importer.importHTMLFromURI(bookmarksURI, true /* overwrite existing */);
|
||||
} catch (err) {
|
||||
// Report the error, but ignore it.
|
||||
Cu.reportError("Bookmarks.html file could be corrupt. " + err);
|
||||
|
@ -50,7 +50,7 @@ const RELOAD_ACTION_NOTHING = 0;
|
||||
const RELOAD_ACTION_INSERT = 1;
|
||||
// Removing items from the view, select the first item after the last selected
|
||||
const RELOAD_ACTION_REMOVE = 2;
|
||||
// Moving items within a view, don't treat the dropped items as additional
|
||||
// Moving items within a view, don't treat the dropped items as additional
|
||||
// rows.
|
||||
const RELOAD_ACTION_MOVE = 3;
|
||||
|
||||
@ -67,7 +67,7 @@ const REMOVE_PAGES_MAX_SINGLEREMOVES = 10;
|
||||
|
||||
/**
|
||||
* Represents an insertion point within a container where we can insert
|
||||
* items.
|
||||
* items.
|
||||
* @param aItemId
|
||||
* The identifier of the parent container
|
||||
* @param aIndex
|
||||
@ -139,7 +139,7 @@ PlacesController.prototype = {
|
||||
return true;
|
||||
}
|
||||
|
||||
// All other Places Commands are prefixed with "placesCmd_" ... this
|
||||
// All other Places Commands are prefixed with "placesCmd_" ... this
|
||||
// filters out other commands that we do _not_ support (see 329587).
|
||||
const CMD_PREFIX = "placesCmd_";
|
||||
return (aCommand.substr(0, CMD_PREFIX.length) == CMD_PREFIX);
|
||||
@ -178,7 +178,7 @@ PlacesController.prototype = {
|
||||
if (this._view.selType != "single") {
|
||||
let rootNode = this._view.result.root;
|
||||
if (rootNode.containerOpen && rootNode.childCount > 0)
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case "placesCmd_open":
|
||||
@ -308,9 +308,9 @@ PlacesController.prototype = {
|
||||
|
||||
onEvent: function PC_onEvent(eventName) { },
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether or not the selection can be removed, either by the
|
||||
* Determine whether or not the selection can be removed, either by the
|
||||
* delete or cut operations based on whether or not any of its contents
|
||||
* are non-removable. We don't need to worry about recursion here since it
|
||||
* is a policy decision that a removable item not be placed inside a non-
|
||||
@ -373,14 +373,14 @@ PlacesController.prototype = {
|
||||
var root = this._view.result.root;
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
if (nodes[i] == root)
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Looks at the data on the clipboard to see if it is paste-able.
|
||||
* Looks at the data on the clipboard to see if it is paste-able.
|
||||
* Paste-able data is:
|
||||
* - in a format that the view can receive
|
||||
* @returns true if: - clipboard data is of a TYPE_X_MOZ_PLACE_* flavor,
|
||||
@ -427,7 +427,7 @@ PlacesController.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
/**
|
||||
* Gathers information about the selected nodes according to the following
|
||||
* rules:
|
||||
* "link" node is a URI
|
||||
@ -442,7 +442,7 @@ PlacesController.prototype = {
|
||||
*
|
||||
* @returns an array of objects corresponding the selected nodes. Each
|
||||
* object has each of the properties above set if its corresponding
|
||||
* node matches the rule. In addition, the annotations names for each
|
||||
* node matches the rule. In addition, the annotations names for each
|
||||
* node are set on its corresponding object as properties.
|
||||
* Notes:
|
||||
* 1) This can be slow, so don't call it anywhere performance critical!
|
||||
@ -456,7 +456,7 @@ PlacesController.prototype = {
|
||||
if (nodes.length == 0)
|
||||
nodes.push(root); // See the second note above
|
||||
|
||||
for (var i=0; i < nodes.length; i++) {
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var nodeData = {};
|
||||
var node = nodes[i];
|
||||
var nodeType = node.type;
|
||||
@ -514,16 +514,16 @@ PlacesController.prototype = {
|
||||
|
||||
// annotations
|
||||
if (uri) {
|
||||
var names = PlacesUtils.annotations.getPageAnnotationNames(uri);
|
||||
for (var j = 0; j < names.length; ++j)
|
||||
let names = PlacesUtils.annotations.getPageAnnotationNames(uri);
|
||||
for (let j = 0; j < names.length; ++j)
|
||||
nodeData[names[j]] = true;
|
||||
}
|
||||
|
||||
// For items also include the item-specific annotations
|
||||
if (node.itemId != -1) {
|
||||
names = PlacesUtils.annotations
|
||||
.getItemAnnotationNames(node.itemId);
|
||||
for (j = 0; j < names.length; ++j)
|
||||
let names = PlacesUtils.annotations
|
||||
.getItemAnnotationNames(node.itemId);
|
||||
for (let j = 0; j < names.length; ++j)
|
||||
nodeData[names[j]] = true;
|
||||
}
|
||||
metadata.push(nodeData);
|
||||
@ -532,14 +532,14 @@ PlacesController.prototype = {
|
||||
return metadata;
|
||||
},
|
||||
|
||||
/**
|
||||
/**
|
||||
* Determines if a context-menu item should be shown
|
||||
* @param aMenuItem
|
||||
* the context menu item
|
||||
* the context menu item
|
||||
* @param aMetaData
|
||||
* meta data about the selection
|
||||
* @returns true if the conditions (see buildContextMenu) are satisfied
|
||||
* and the item can be displayed, false otherwise.
|
||||
* and the item can be displayed, false otherwise.
|
||||
*/
|
||||
_shouldShowMenuItem: function PC__shouldShowMenuItem(aMenuItem, aMetaData) {
|
||||
var selectiontype = aMenuItem.getAttribute("selectiontype");
|
||||
@ -551,8 +551,8 @@ PlacesController.prototype = {
|
||||
var forceHideAttr = aMenuItem.getAttribute("forcehideselection");
|
||||
if (forceHideAttr) {
|
||||
var forceHideRules = forceHideAttr.split("|");
|
||||
for (var i = 0; i < aMetaData.length; ++i) {
|
||||
for (var j=0; j < forceHideRules.length; ++j) {
|
||||
for (let i = 0; i < aMetaData.length; ++i) {
|
||||
for (let j = 0; j < forceHideRules.length; ++j) {
|
||||
if (forceHideRules[j] in aMetaData[i])
|
||||
return false;
|
||||
}
|
||||
@ -682,7 +682,7 @@ PlacesController.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Select all links in the current view.
|
||||
* Select all links in the current view.
|
||||
*/
|
||||
selectAll: function PC_selectAll() {
|
||||
this._view.selectAll();
|
||||
@ -691,7 +691,7 @@ PlacesController.prototype = {
|
||||
/**
|
||||
* Opens the bookmark properties for the selected URI Node.
|
||||
*/
|
||||
showBookmarkPropertiesForSelection:
|
||||
showBookmarkPropertiesForSelection:
|
||||
function PC_showBookmarkPropertiesForSelection() {
|
||||
var node = this._view.selectedNode;
|
||||
if (!node)
|
||||
@ -717,7 +717,7 @@ PlacesController.prototype = {
|
||||
* receive a string instead of an nsIURI object.
|
||||
*/
|
||||
_assertURINotString: function PC__assertURINotString(value) {
|
||||
NS_ASSERT((typeof(value) == "object") && !(value instanceof String),
|
||||
NS_ASSERT((typeof(value) == "object") && !(value instanceof String),
|
||||
"This method should be passed a URI as a nsIURI object, not as a string.");
|
||||
},
|
||||
|
||||
@ -759,16 +759,15 @@ PlacesController.prototype = {
|
||||
|
||||
var messageKey = "tabs.openWarningMultipleBranded";
|
||||
var openKey = "tabs.openButtonMultiple";
|
||||
var strings = document.getElementById("placeBundle");
|
||||
const BRANDING_BUNDLE_URI = "chrome://branding/locale/brand.properties";
|
||||
var brandShortName = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
createBundle(BRANDING_BUNDLE_URI).
|
||||
GetStringFromName("brandShortName");
|
||||
|
||||
|
||||
var buttonPressed = promptService.confirmEx(window,
|
||||
PlacesUIUtils.getString("tabs.openWarningTitle"),
|
||||
PlacesUIUtils.getFormattedString(messageKey,
|
||||
PlacesUIUtils.getFormattedString(messageKey,
|
||||
[numTabsToOpen, brandShortName]),
|
||||
(promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0)
|
||||
+ (promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1),
|
||||
@ -788,7 +787,7 @@ PlacesController.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the links in the selected folder, or the selected links in new tabs.
|
||||
* Opens the links in the selected folder, or the selected links in new tabs.
|
||||
*/
|
||||
openSelectionInTabs: function PC_openLinksInTabs(aEvent) {
|
||||
var node = this._view.selectedNode;
|
||||
@ -828,7 +827,7 @@ PlacesController.prototype = {
|
||||
|
||||
/**
|
||||
* Create a new Bookmark folder somewhere. Prompts the user for the name
|
||||
* of the folder.
|
||||
* of the folder.
|
||||
*/
|
||||
newFolder: function PC_newFolder() {
|
||||
var ip = this._view.insertionPoint;
|
||||
@ -880,17 +879,17 @@ PlacesController.prototype = {
|
||||
|
||||
/**
|
||||
* Walk the list of folders we're removing in this delete operation, and
|
||||
* see if the selected node specified is already implicitly being removed
|
||||
* because it is a child of that folder.
|
||||
* see if the selected node specified is already implicitly being removed
|
||||
* because it is a child of that folder.
|
||||
* @param node
|
||||
* Node to check for containment.
|
||||
* Node to check for containment.
|
||||
* @param pastFolders
|
||||
* List of folders the calling function has already traversed
|
||||
* @returns true if the node should be skipped, false otherwise.
|
||||
* @returns true if the node should be skipped, false otherwise.
|
||||
*/
|
||||
_shouldSkipNode: function PC_shouldSkipNode(node, pastFolders) {
|
||||
/**
|
||||
* Determines if a node is contained by another node within a resultset.
|
||||
* Determines if a node is contained by another node within a resultset.
|
||||
* @param node
|
||||
* The node to check for containment for
|
||||
* @param parent
|
||||
@ -906,7 +905,7 @@ PlacesController.prototype = {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
for (var j = 0; j < pastFolders.length; ++j) {
|
||||
if (isContainedBy(node, pastFolders[j]))
|
||||
return true;
|
||||
@ -915,10 +914,10 @@ PlacesController.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a set of transactions for the removal of a range of items.
|
||||
* Creates a set of transactions for the removal of a range of items.
|
||||
* A range is an array of adjacent nodes in a view.
|
||||
* @param [in] range
|
||||
* An array of nodes to remove. Should all be adjacent.
|
||||
* An array of nodes to remove. Should all be adjacent.
|
||||
* @param [out] transactions
|
||||
* An array of transactions.
|
||||
* @param [optional] removedFolders
|
||||
@ -1090,7 +1089,7 @@ PlacesController.prototype = {
|
||||
|
||||
var root = this._view.result.root;
|
||||
|
||||
if (PlacesUtils.nodeIsFolder(root))
|
||||
if (PlacesUtils.nodeIsFolder(root))
|
||||
this._removeRowsFromBookmarks(aTxnName);
|
||||
else if (PlacesUtils.nodeIsQuery(root)) {
|
||||
var queryType = PlacesUtils.asQuery(root).queryOptions.queryType;
|
||||
@ -1136,7 +1135,7 @@ PlacesController.prototype = {
|
||||
addData(PlacesUtils.TYPE_HTML, index, overrideURI);
|
||||
}
|
||||
|
||||
// This order is _important_! It controls how this and other
|
||||
// This order is _important_! It controls how this and other
|
||||
// applications select data to be inserted based on type.
|
||||
addData(PlacesUtils.TYPE_X_MOZ_PLACE, i);
|
||||
|
||||
@ -1166,8 +1165,8 @@ PlacesController.prototype = {
|
||||
try {
|
||||
let nodes = this._view.selectedNodes;
|
||||
|
||||
let xferable = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
let xferable = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
let foundFolder = false, foundLink = false;
|
||||
let copiedFolders = [];
|
||||
let placeString, mozURLString, htmlString, unicodeString;
|
||||
@ -1179,11 +1178,11 @@ PlacesController.prototype = {
|
||||
continue;
|
||||
if (PlacesUtils.nodeIsFolder(node))
|
||||
copiedFolders.push(node);
|
||||
|
||||
|
||||
function generateChunk(type, overrideURI) {
|
||||
let suffix = i < (nodes.length - 1) ? PlacesUtils.endl : "";
|
||||
let uri = overrideURI;
|
||||
|
||||
|
||||
if (PlacesUtils.nodeIsLivemarkContainer(node))
|
||||
uri = PlacesUtils.livemarks.getFeedURI(node.itemId).spec
|
||||
|
||||
@ -1194,8 +1193,8 @@ PlacesController.prototype = {
|
||||
htmlString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_HTML,
|
||||
uri) + suffix);
|
||||
|
||||
var placeSuffix = i < (nodes.length - 1) ? "," : "";
|
||||
var resolveShortcuts = !PlacesControllerDragHelper.canMoveNode(node);
|
||||
let placeSuffix = i < (nodes.length - 1) ? "," : "";
|
||||
let resolveShortcuts = !PlacesControllerDragHelper.canMoveNode(node);
|
||||
return PlacesUtils.wrapNode(node, type, overrideURI, resolveShortcuts) + placeSuffix;
|
||||
}
|
||||
|
||||
@ -1207,7 +1206,7 @@ PlacesController.prototype = {
|
||||
xferable.addDataFlavor(type);
|
||||
xferable.setTransferData(type, PlacesUIUtils._wrapString(data), data.length * 2);
|
||||
}
|
||||
// This order is _important_! It controls how this and other applications
|
||||
// This order is _important_! It controls how this and other applications
|
||||
// select data to be inserted based on type.
|
||||
if (placeString)
|
||||
addData(PlacesUtils.TYPE_X_MOZ_PLACE, placeString);
|
||||
@ -1241,11 +1240,11 @@ PlacesController.prototype = {
|
||||
*/
|
||||
paste: function PC_paste() {
|
||||
// Strategy:
|
||||
//
|
||||
// There can be data of various types (folder, separator, link) on the
|
||||
//
|
||||
// There can be data of various types (folder, separator, link) on the
|
||||
// clipboard. We need to get all of that data and build edit transactions
|
||||
// for them. This means asking the clipboard once for each type and
|
||||
// aggregating the results.
|
||||
// for them. This means asking the clipboard once for each type and
|
||||
// aggregating the results.
|
||||
|
||||
/**
|
||||
* Constructs a transferable that can receive data of specific types.
|
||||
@ -1255,10 +1254,9 @@ PlacesController.prototype = {
|
||||
* @returns The transferable.
|
||||
*/
|
||||
function makeXferable(types) {
|
||||
var xferable =
|
||||
Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
for (var i = 0; i < types.length; ++i)
|
||||
var xferable = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
for (var i = 0; i < types.length; ++i)
|
||||
xferable.addDataFlavor(types[i]);
|
||||
return xferable;
|
||||
}
|
||||
@ -1291,10 +1289,10 @@ PlacesController.prototype = {
|
||||
if (ip.isTag) {
|
||||
var uri = PlacesUtils._uri(items[i].uri);
|
||||
txn = PlacesUIUtils.ptm.tagURI(uri, [ip.itemId]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// adjusted to make sure that items are given the correct index
|
||||
// transactions insert differently if index == -1
|
||||
// transactions insert differently if index == -1
|
||||
// transaction will enqueue the item.
|
||||
if (ip.index > -1)
|
||||
index = ip.index + i;
|
||||
@ -1307,18 +1305,18 @@ PlacesController.prototype = {
|
||||
}
|
||||
catch (e) {
|
||||
// getAnyTransferData will throw if there is no data of the specified
|
||||
// type on the clipboard.
|
||||
// type on the clipboard.
|
||||
// unwrapNodes will throw if the data that is present is malformed in
|
||||
// some way.
|
||||
// some way.
|
||||
// In either case, don't fail horribly, just return no data.
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
// Get transactions to paste any folders, separators or links that might
|
||||
// be on the clipboard, aggregate them and execute them.
|
||||
// be on the clipboard, aggregate them and execute them.
|
||||
var transactions = getTransactions([PlacesUtils.TYPE_X_MOZ_PLACE,
|
||||
PlacesUtils.TYPE_X_MOZ_URL,
|
||||
PlacesUtils.TYPE_X_MOZ_URL,
|
||||
PlacesUtils.TYPE_UNICODE]);
|
||||
var txn = PlacesUIUtils.ptm.aggregateTransactions("Paste", transactions);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
@ -1336,8 +1334,8 @@ PlacesController.prototype = {
|
||||
/**
|
||||
* Handles drag and drop operations for views. Note that this is view agnostic!
|
||||
* You should not use PlacesController._view within these methods, since
|
||||
* the view that the item(s) have been dropped on was not necessarily active.
|
||||
* Drop functions are passed the view that is being dropped on.
|
||||
* the view that the item(s) have been dropped on was not necessarily active.
|
||||
* Drop functions are passed the view that is being dropped on.
|
||||
*/
|
||||
let PlacesControllerDragHelper = {
|
||||
/**
|
||||
@ -1416,7 +1414,8 @@ let PlacesControllerDragHelper = {
|
||||
let dragged;
|
||||
try {
|
||||
dragged = PlacesUtils.unwrapNodes(data, flavor)[0];
|
||||
} catch (e) {
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1442,10 +1441,10 @@ let PlacesControllerDragHelper = {
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determines if a node can be moved.
|
||||
*
|
||||
*
|
||||
* @param aNode
|
||||
* A nsINavHistoryResultNode node.
|
||||
* @returns True if the node can be moved, false otherwise.
|
||||
@ -1477,7 +1476,7 @@ let PlacesControllerDragHelper = {
|
||||
|
||||
/**
|
||||
* Determines if a container node can be moved.
|
||||
*
|
||||
*
|
||||
* @param aId
|
||||
* A bookmark folder id.
|
||||
* @param [optional] aParentId
|
||||
|
@ -132,6 +132,6 @@ var SidebarUtils = {
|
||||
},
|
||||
|
||||
clearURLFromStatusBar: function SU_clearURLFromStatusBar() {
|
||||
window.top.XULBrowserWindow.setOverLink("", null);
|
||||
window.top.XULBrowserWindow.setOverLink("", null);
|
||||
}
|
||||
};
|
||||
|
@ -780,4 +780,3 @@
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
|
||||
|
@ -37,11 +37,21 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function PlacesTreeView(aFlatList, aOnOpenFlatContainer) {
|
||||
this._tree = null;
|
||||
this._result = null;
|
||||
this._selection = null;
|
||||
this._rootNode = null;
|
||||
this._rows = [];
|
||||
this._flatList = aFlatList;
|
||||
this._openContainerCallback = aOnOpenFlatContainer;
|
||||
}
|
||||
|
||||
PlacesTreeView.prototype = {
|
||||
_makeAtom: function PTV__makeAtom(aString) {
|
||||
return Cc["@mozilla.org/atom-service;1"].
|
||||
getService(Ci.nsIAtomService).
|
||||
getAtom(aString);
|
||||
return Cc["@mozilla.org/atom-service;1"].
|
||||
getService(Ci.nsIAtomService).
|
||||
getAtom(aString);
|
||||
},
|
||||
|
||||
_atoms: [],
|
||||
@ -122,8 +132,7 @@ PlacesTreeView.prototype = {
|
||||
if (!(aContainer instanceof Ci.nsINavHistoryQueryResultNode))
|
||||
return aContainer._plainContainer = false;
|
||||
|
||||
let resultType = aContainer.queryOptions.resultType;
|
||||
switch (resultType) {
|
||||
switch (aContainer.queryOptions.resultType) {
|
||||
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY:
|
||||
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY:
|
||||
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY:
|
||||
@ -602,8 +611,7 @@ PlacesTreeView.prototype = {
|
||||
return;
|
||||
|
||||
// Bail out for hidden separators.
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) &&
|
||||
this._result.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE)
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) && this.isSorted())
|
||||
return;
|
||||
|
||||
let parentRow;
|
||||
@ -632,7 +640,7 @@ PlacesTreeView.prototype = {
|
||||
// children themselves that would be in the way.
|
||||
let cc = aParentNode.childCount;
|
||||
let separatorsAreHidden = PlacesUtils.nodeIsSeparator(aNode) &&
|
||||
this._result.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
|
||||
this.isSorted();
|
||||
for (let i = aNewIndex + 1; i < cc; i++) {
|
||||
let node = aParentNode.getChild(i);
|
||||
if (!separatorsAreHidden || PlacesUtils.nodeIsSeparator(node)) {
|
||||
@ -679,8 +687,7 @@ PlacesTreeView.prototype = {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// Bail out for hidden separators.
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) &&
|
||||
this._result.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE)
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) && this.isSorted())
|
||||
return;
|
||||
|
||||
let parentRow = aParentNode == this._rootNode ?
|
||||
@ -728,8 +735,7 @@ PlacesTreeView.prototype = {
|
||||
return;
|
||||
|
||||
// Bail out for hidden separators.
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) &&
|
||||
this._result.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE)
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) && this.isSorted())
|
||||
return;
|
||||
|
||||
let oldRow = this._getRowForNode(aNode, true);
|
||||
@ -1204,7 +1210,7 @@ PlacesTreeView.prototype = {
|
||||
else {
|
||||
// Use the last-selected node's container.
|
||||
container = lastSelected.parent;
|
||||
|
||||
|
||||
// During its Drag & Drop operation, the tree code closes-and-opens
|
||||
// containers very often (part of the XUL "spring-loaded folders"
|
||||
// implementation). And in certain cases, we may reach a closed
|
||||
@ -1309,8 +1315,7 @@ PlacesTreeView.prototype = {
|
||||
|
||||
getCellText: function PTV_getCellText(aRow, aColumn) {
|
||||
let node = this._getNodeForRow(aRow);
|
||||
let columnType = this._getColumnType(aColumn);
|
||||
switch (columnType) {
|
||||
switch (this._getColumnType(aColumn)) {
|
||||
case this.COLUMN_TYPE_TITLE:
|
||||
// normally, this is just the title, but we don't want empty items in
|
||||
// the tree view so return a special string if the title is empty.
|
||||
@ -1428,8 +1433,7 @@ PlacesTreeView.prototype = {
|
||||
let newSort;
|
||||
let newSortingAnnotation = "";
|
||||
const NHQO = Ci.nsINavHistoryQueryOptions;
|
||||
let columnType = this._getColumnType(aColumn);
|
||||
switch (columnType) {
|
||||
switch (this._getColumnType(aColumn)) {
|
||||
case this.COLUMN_TYPE_TITLE:
|
||||
if (oldSort == NHQO.SORT_BY_TITLE_ASCENDING)
|
||||
newSort = NHQO.SORT_BY_TITLE_DESCENDING;
|
||||
@ -1576,13 +1580,3 @@ PlacesTreeView.prototype = {
|
||||
performActionOnRow: function(aAction, aRow) { },
|
||||
performActionOnCell: function(aAction, aRow, aColumn) { }
|
||||
};
|
||||
|
||||
function PlacesTreeView(aFlatList, aOnOpenFlatContainer) {
|
||||
this._tree = null;
|
||||
this._result = null;
|
||||
this._selection = null;
|
||||
this._rootNode = null;
|
||||
this._rows = [];
|
||||
this._flatList = aFlatList;
|
||||
this._openContainerCallback = aOnOpenFlatContainer;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ var PlacesUIUtils = {
|
||||
* @returns A URI object for the spec.
|
||||
*/
|
||||
createFixedURI: function PUIU_createFixedURI(aSpec) {
|
||||
return URIFixup.createFixupURI(aSpec, 0);
|
||||
return URIFixup.createFixupURI(aSpec, Ci.nsIURIFixup.FIXUP_FLAG_NONE);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -128,7 +128,7 @@ var PlacesUIUtils = {
|
||||
*/
|
||||
_getBookmarkItemCopyTransaction:
|
||||
function PUIU__getBookmarkItemCopyTransaction(aData, aContainer, aIndex,
|
||||
aExcludeAnnotations) {
|
||||
aExcludeAnnotations) {
|
||||
var itemURL = PlacesUtils._uri(aData.uri);
|
||||
var itemTitle = aData.title;
|
||||
var keyword = aData.keyword || null;
|
||||
@ -278,7 +278,7 @@ var PlacesUIUtils = {
|
||||
* the move/insert.
|
||||
*/
|
||||
makeTransaction: function PUIU_makeTransaction(data, type, container,
|
||||
index, copy) {
|
||||
index, copy) {
|
||||
switch (data.type) {
|
||||
case PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER:
|
||||
if (copy)
|
||||
@ -289,7 +289,7 @@ var PlacesUIUtils = {
|
||||
case PlacesUtils.TYPE_X_MOZ_PLACE:
|
||||
if (data.id == -1) // Not bookmarked.
|
||||
return this._getURIItemCopyTransaction(data, container, index);
|
||||
|
||||
|
||||
if (copy)
|
||||
return this._getBookmarkItemCopyTransaction(data, container, index);
|
||||
// Otherwise move the item.
|
||||
@ -361,14 +361,14 @@ var PlacesUIUtils = {
|
||||
* bookmarks root folder.
|
||||
*/
|
||||
showAddBookmarkUI: function PUIU_showAddBookmarkUI(aURI,
|
||||
aTitle,
|
||||
aDescription,
|
||||
aDefaultInsertionPoint,
|
||||
aShowPicker,
|
||||
aLoadInSidebar,
|
||||
aKeyword,
|
||||
aPostData,
|
||||
aCharSet) {
|
||||
aTitle,
|
||||
aDescription,
|
||||
aDefaultInsertionPoint,
|
||||
aShowPicker,
|
||||
aLoadInSidebar,
|
||||
aKeyword,
|
||||
aPostData,
|
||||
aCharSet) {
|
||||
var info = {
|
||||
action: "add",
|
||||
type: "bookmark"
|
||||
@ -417,9 +417,9 @@ var PlacesUIUtils = {
|
||||
*/
|
||||
showMinimalAddBookmarkUI:
|
||||
function PUIU_showMinimalAddBookmarkUI(aURI, aTitle, aDescription,
|
||||
aDefaultInsertionPoint, aShowPicker,
|
||||
aLoadInSidebar, aKeyword, aPostData,
|
||||
aCharSet) {
|
||||
aDefaultInsertionPoint, aShowPicker,
|
||||
aLoadInSidebar, aKeyword, aPostData,
|
||||
aCharSet) {
|
||||
var info = {
|
||||
action: "add",
|
||||
type: "bookmark",
|
||||
@ -485,11 +485,11 @@ var PlacesUIUtils = {
|
||||
* bookmarks root folder.
|
||||
*/
|
||||
showAddLivemarkUI: function PUIU_showAddLivemarkURI(aFeedURI,
|
||||
aSiteURI,
|
||||
aTitle,
|
||||
aDescription,
|
||||
aDefaultInsertionPoint,
|
||||
aShowPicker) {
|
||||
aSiteURI,
|
||||
aTitle,
|
||||
aDescription,
|
||||
aDefaultInsertionPoint,
|
||||
aShowPicker) {
|
||||
var info = {
|
||||
action: "add",
|
||||
type: "livemark"
|
||||
@ -525,8 +525,8 @@ var PlacesUIUtils = {
|
||||
*/
|
||||
showMinimalAddLivemarkUI:
|
||||
function PUIU_showMinimalAddLivemarkURI(aFeedURI, aSiteURI, aTitle,
|
||||
aDescription, aDefaultInsertionPoint,
|
||||
aShowPicker) {
|
||||
aDescription, aDefaultInsertionPoint,
|
||||
aShowPicker) {
|
||||
var info = {
|
||||
action: "add",
|
||||
type: "livemark",
|
||||
@ -706,7 +706,7 @@ var PlacesUIUtils = {
|
||||
/**
|
||||
* By calling this before visiting an URL, the visit will be associated to a
|
||||
* TRANSITION_BOOKMARK transition.
|
||||
* This is used when visiting pages from the bookmarks menu,
|
||||
* This is used when visiting pages from the bookmarks menu,
|
||||
* personal toolbar, and bookmarks from within the places organizer.
|
||||
* If this is not called visits will be marked as TRANSITION_LINK.
|
||||
*/
|
||||
@ -730,6 +730,8 @@ var PlacesUIUtils = {
|
||||
* bookmarked (see bug 224521).
|
||||
* @param aURINode
|
||||
* a URI node
|
||||
* @param aWindow
|
||||
* a window on which a potential error alert is shown on.
|
||||
* @return true if it's safe to open the node in the browser, false otherwise.
|
||||
*
|
||||
*/
|
||||
@ -890,7 +892,7 @@ var PlacesUIUtils = {
|
||||
openNodeWithEvent: function PUIU_openNodeWithEvent(aNode, aEvent) {
|
||||
this.openNodeIn(aNode, this._getCurrentActiveWin().whereToOpenLink(aEvent));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Loads the node's URL in the appropriate tab or window or as a
|
||||
* web panel.
|
||||
@ -927,12 +929,12 @@ var PlacesUIUtils = {
|
||||
* Used to avoid nsIURI overhead in frequently called UI functions.
|
||||
*
|
||||
* @param aUrlString the url to guess the scheme from.
|
||||
*
|
||||
*
|
||||
* @return guessed scheme for this url string.
|
||||
*
|
||||
* @note this is not supposed be perfect, so use it only for UI purposes.
|
||||
*/
|
||||
guessUrlSchemeForUI: function PUU_guessUrlSchemeForUI(aUrlString) {
|
||||
guessUrlSchemeForUI: function PUIU_guessUrlSchemeForUI(aUrlString) {
|
||||
return aUrlString.substr(0, aUrlString.indexOf(":"));
|
||||
},
|
||||
|
||||
@ -961,7 +963,7 @@ var PlacesUIUtils = {
|
||||
return title || this.getString("noTitle");
|
||||
},
|
||||
|
||||
get leftPaneQueries() {
|
||||
get leftPaneQueries() {
|
||||
// build the map
|
||||
this.leftPaneFolderId;
|
||||
return this.leftPaneQueries;
|
||||
@ -1239,7 +1241,7 @@ var PlacesUIUtils = {
|
||||
queryName = name;
|
||||
}
|
||||
}
|
||||
return queryName;
|
||||
return queryName;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1380,7 +1382,7 @@ XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ptm", function() {
|
||||
|
||||
/**
|
||||
* Transaction for editing a the description of a bookmark or a folder.
|
||||
*
|
||||
*
|
||||
* @param aItemId
|
||||
* id of the item to edit.
|
||||
* @param aDescription
|
||||
|
@ -1011,6 +1011,10 @@ toolbar[iconsize="small"] #fullscreen-button {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.notification-anchor-icon:-moz-focusring {
|
||||
outline: 1px dotted -moz-DialogText;
|
||||
}
|
||||
|
||||
#geo-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
|
||||
}
|
||||
|
@ -1874,6 +1874,11 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.notification-anchor-icon:-moz-focusring {
|
||||
-moz-box-shadow: 0 0 3px 1px -moz-mac-focusring inset,
|
||||
0 0 3px 2px -moz-mac-focusring;
|
||||
}
|
||||
|
||||
#geo-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
|
||||
}
|
||||
|
@ -21,6 +21,15 @@
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* the new titlebar requires this, or content will be clipped at the top of the screen. */
|
||||
#main-window[sizemode="maximized"][chromemargin^="0,"] {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
#main-window[sizemode="normal"][chromemargin^="0,"] {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
#main-window:not(:-moz-lwtheme)[inFullscreen="true"] {
|
||||
-moz-appearance: none;
|
||||
background-color: #556;
|
||||
|
@ -26,7 +26,6 @@
|
||||
* Blake Ross (blake@cs.stanford.edu)
|
||||
* Pamela Greene (pamg.bugs@gmail.com)
|
||||
* Dão Gottwald (dao@mozilla.com)
|
||||
* Jim Mathies (jmathies@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
|
||||
@ -102,7 +101,21 @@ statusbarpanel#statusbar-display {
|
||||
-moz-padding-start: 0;
|
||||
}
|
||||
|
||||
/* ::::: app menu button ::::: */
|
||||
/* App menu button */
|
||||
|
||||
%ifndef WINSTRIPE_AERO
|
||||
#appmenu-button-container {
|
||||
background: ActiveCaption;
|
||||
}
|
||||
|
||||
#appmenu-button-container:-moz-window-inactive {
|
||||
background: InactiveCaption;
|
||||
}
|
||||
%endif
|
||||
|
||||
#appmenu-button-container {
|
||||
-moz-binding: url("chrome://global/content/bindings/general.xml#windowdragbox");
|
||||
}
|
||||
|
||||
#appmenu-button {
|
||||
-moz-appearance: none;
|
||||
@ -157,84 +170,24 @@ statusbarpanel#statusbar-display {
|
||||
color: -moz-menuhovertext;
|
||||
}
|
||||
|
||||
/* ::::: titlebar ::::: */
|
||||
|
||||
#titlebar {
|
||||
-moz-appearance: -moz-window-titlebar;
|
||||
/* we only need to the middle section, hide the edges of the
|
||||
theme background beyond the window frame. */
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
}
|
||||
|
||||
#main-window[sizemode="maximized"] > #titlebar {
|
||||
-moz-appearance: -moz-window-titlebar-maximized;
|
||||
}
|
||||
|
||||
#titlebar-content {
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
/* aesthetic - push the fx button off the top window border */
|
||||
@media not all and (-moz-windows-classic) {
|
||||
#main-window[sizemode="normal"] > #titlebar > #titlebar-content > #appmenu-button-container {
|
||||
%ifndef WINSTRIPE_AERO
|
||||
margin-top: 1px;
|
||||
%else
|
||||
margin-top: 2px;
|
||||
/* XXX: stop-gap until the button can be drawn in the title bar */
|
||||
%ifdef WINSTRIPE_AERO
|
||||
@media not all and (-moz-windows-compositor) {
|
||||
%endif
|
||||
#main-window[tabsontop="true"] > #appmenu-button-container > #appmenu-button {
|
||||
position: relative !important;
|
||||
margin-bottom: -1.6em !important;
|
||||
}
|
||||
}
|
||||
|
||||
#titlebar-buttonbox {
|
||||
-moz-appearance: -moz-window-button-box;
|
||||
-moz-box-align: start;
|
||||
}
|
||||
|
||||
#main-window[sizemode="maximized"] > #titlebar > #titlebar-content > #titlebar-buttonbox {
|
||||
-moz-appearance: -moz-window-button-box-maximized;
|
||||
}
|
||||
|
||||
/* titlebar command buttons */
|
||||
|
||||
#titlebar-min {
|
||||
-moz-appearance: -moz-window-button-minimize;
|
||||
}
|
||||
|
||||
#titlebar-max {
|
||||
-moz-appearance: -moz-window-button-maximize;
|
||||
}
|
||||
|
||||
#main-window[sizemode="maximized"] > #titlebar > #titlebar-content > #titlebar-buttonbox > #titlebar-max {
|
||||
-moz-appearance: -moz-window-button-restore;
|
||||
}
|
||||
|
||||
#titlebar-close {
|
||||
-moz-appearance: -moz-window-button-close;
|
||||
}
|
||||
|
||||
@media not all and (-moz-windows-classic) {
|
||||
#titlebar-min {
|
||||
-moz-margin-end: 1px;
|
||||
#navigator-toolbox[tabsontop="true"] > #toolbar-menubar[autohide="true"] {
|
||||
position: relative !important;
|
||||
background-color: -moz-dialog !important;
|
||||
}
|
||||
|
||||
#titlebar-max {
|
||||
-moz-margin-start: 1px;
|
||||
-moz-margin-end: 1px;
|
||||
}
|
||||
|
||||
#titlebar-close {
|
||||
-moz-margin-start: 1px;
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (-moz-windows-classic) {
|
||||
#titlebar-close {
|
||||
-moz-margin-start: 2px !important;
|
||||
#navigator-toolbox[tabsontop="true"] > #toolbar-menubar[autohide="true"] ~ #TabsToolbar:not([inFullscreen]) {
|
||||
-moz-padding-start: 10em !important;
|
||||
}
|
||||
%ifdef WINSTRIPE_AERO
|
||||
}
|
||||
%endif
|
||||
|
||||
/* ::::: bookmark buttons ::::: */
|
||||
|
||||
@ -1160,9 +1113,16 @@ richlistitem[type="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-i
|
||||
|
||||
#TabsToolbar:not(:-moz-lwtheme),
|
||||
#TabsToolbar[tabsontop="false"] {
|
||||
background-image: -moz-linear-gradient(transparent, transparent 50%,
|
||||
rgba(0,0,0,.05) 90%, rgba(0,0,0,.1));
|
||||
}
|
||||
|
||||
#TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme) {
|
||||
-moz-box-shadow: 0 -1px ThreeDShadow inset;
|
||||
background-image: -moz-linear-gradient(transparent, transparent 10%,
|
||||
rgba(0,0,0,.03) 50%, rgba(0,0,0,.1) 90%, rgba(0,0,0,.2));
|
||||
}
|
||||
|
||||
#TabsToolbar[tabsontop="false"] {
|
||||
border-bottom: 1px solid ThreeDShadow !important;
|
||||
}
|
||||
|
||||
.tabbrowser-tabs:-moz-system-metric(touch-enabled) {
|
||||
@ -1664,6 +1624,11 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.notification-anchor-icon:-moz-focusring {
|
||||
outline: 1px dotted -moz-DialogText;
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
#geo-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
|
||||
}
|
||||
|
@ -51,5 +51,9 @@ _TEST_FILES = test_bug423375.html \
|
||||
test_bug470804.html \
|
||||
$(NULL)
|
||||
|
||||
test_bug292789.html : % : %.in
|
||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
|
||||
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
@ -38,7 +38,11 @@ function testScriptSrc(aCallback) {
|
||||
** moved the resource
|
||||
**/
|
||||
var resjs = document.createElement("script");
|
||||
#ifdef MOZ_CHROME_FILE_FORMAT_JAR
|
||||
resjs.src = "jar:resource://gre/chrome/toolkit.jar!/content/mozapps/xpinstall/xpinstallConfirm.js";
|
||||
#else
|
||||
resjs.src = "resource://gre/chrome/toolkit/content/mozapps/xpinstall/xpinstallConfirm.js";
|
||||
#endif
|
||||
resjs.onload = scriptOnload;
|
||||
document.getElementById("content").appendChild(resjs);
|
||||
|
||||
@ -55,7 +59,11 @@ function testScriptSrc(aCallback) {
|
||||
/** <img src=""> tests **/
|
||||
var img_global = "chrome://global/skin/icons/Error.png";
|
||||
var img_mozapps = "chrome://mozapps/skin/passwordmgr/key.png";
|
||||
#ifdef MOZ_CHROME_FILE_FORMAT_JAR
|
||||
var res_mozapps = "jar:resource://gre/chrome/toolkit.jar!/skin/classic/mozapps/passwordmgr/key.png";
|
||||
#else
|
||||
var res_mozapps = "resource://gre/chrome/toolkit/skin/classic/mozapps/passwordmgr/key.png";
|
||||
#endif
|
||||
|
||||
var imgTests = [[img_global, "success"],
|
||||
[img_mozapps, "fail"],
|
@ -1036,4 +1036,7 @@ event.h
|
||||
#ifdef MOZ_ENABLE_LIBPROXY
|
||||
proxy.h
|
||||
#endif
|
||||
#if MOZ_PLATFORM_MAEMO==6
|
||||
contentaction/contentaction.h
|
||||
#endif
|
||||
|
||||
|
73
configure.in
73
configure.in
@ -132,7 +132,7 @@ GCONF_VERSION=1.2.1
|
||||
GIO_VERSION=2.0
|
||||
STARTUP_NOTIFICATION_VERSION=0.8
|
||||
DBUS_VERSION=0.60
|
||||
SQLITE_VERSION=3.6.23.1
|
||||
SQLITE_VERSION=3.7.0.1
|
||||
LIBNOTIFY_VERSION=0.4
|
||||
|
||||
MSMANIFEST_TOOL=
|
||||
@ -5915,42 +5915,43 @@ if test -n "$MOZ_WEBM"; then
|
||||
dnl For Darwin x86, Darwin x86_64, Linux x86, and WINNT x86_64
|
||||
dnl we can use YASM.
|
||||
AC_MSG_CHECKING([for YASM assembler])
|
||||
AC_CHECK_PROGS(VPX_AS, yasm, "")
|
||||
if test -n "$VPX_AS"; then
|
||||
dnl We have YASM, see if we have assembly on this platform.
|
||||
case "$OS_ARCH:$OS_TEST" in
|
||||
Linux:x86|Linux:i?86)
|
||||
VPX_ASFLAGS="-f elf32 -rnasm -pnasm"
|
||||
AC_CHECK_PROGS(VPX_AS, $YASM yasm, "")
|
||||
dnl We have YASM, see if we have assembly on this platform.
|
||||
case "$OS_ARCH:$OS_TEST" in
|
||||
Linux:x86|Linux:i?86)
|
||||
VPX_ASFLAGS="-f elf32 -rnasm -pnasm"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Linux:x86_64)
|
||||
VPX_ASFLAGS="-f elf64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
SunOS:i?86)
|
||||
VPX_ASFLAGS="-f elf32 -rnasm -pnasm"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
SunOS:x86_64)
|
||||
VPX_ASFLAGS="-f elf64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Darwin:i?86)
|
||||
VPX_ASFLAGS="-f macho32 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Darwin:x86_64)
|
||||
VPX_ASFLAGS="-f macho64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
WINNT:x86_64)
|
||||
if test -z "$GNU_CC"; then
|
||||
VPX_ASFLAGS="-f x64 -rnasm -pnasm"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Linux:x86_64)
|
||||
VPX_ASFLAGS="-f elf64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
SunOS:i?86)
|
||||
VPX_ASFLAGS="-f elf32 -rnasm -pnasm"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
SunOS:x86_64)
|
||||
VPX_ASFLAGS="-f elf64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Darwin:i?86)
|
||||
VPX_ASFLAGS="-f macho32 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Darwin:x86_64)
|
||||
VPX_ASFLAGS="-f macho64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
WINNT:x86_64)
|
||||
if test -z "$GNU_CC"; then
|
||||
VPX_ASFLAGS="-f x64 -rnasm -pnasm"
|
||||
VPX_X86_ASM=1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi # end have YASM
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if test -n "$VPX_X86_ASM" -a -z "$VPX_AS"; then
|
||||
AC_MSG_ERROR([yasm is a required build tool for this architecture when webm is enabled. You may either install yasm or --disable-webm (which disables the WebM video format). See https://developer.mozilla.org/en/YASM for more details.])
|
||||
fi
|
||||
fi # end !WINNT_x86_MSVC
|
||||
|
||||
if test -n "$VPX_X86_ASM"; then
|
||||
|
@ -1889,6 +1889,14 @@ nsFrameLoader::EnsureMessageManager()
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mIsTopLevelContent
|
||||
#ifdef MOZ_IPC
|
||||
&& !mRemoteFrame
|
||||
#endif
|
||||
) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mMessageManager) {
|
||||
#ifdef MOZ_IPC
|
||||
if (ShouldUseRemoteProcess()) {
|
||||
|
@ -36,7 +36,6 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "nsFrameMessageManager.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIXPConnect.h"
|
||||
@ -44,6 +43,9 @@
|
||||
#include "jsarray.h"
|
||||
#include "jsinterp.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameMessageManager)
|
||||
|
||||
@ -505,3 +507,168 @@ NS_NewGlobalMessageManager(nsIChromeFrameMessageManager** aResult)
|
||||
NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY);
|
||||
return CallQueryInterface(mm, aResult);
|
||||
}
|
||||
|
||||
nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>*
|
||||
nsFrameScriptExecutor::sCachedScripts = nsnull;
|
||||
|
||||
void
|
||||
nsFrameScriptExecutor::DidCreateCx()
|
||||
{
|
||||
NS_ASSERTION(mCx, "Should have mCx!");
|
||||
if (!sCachedScripts) {
|
||||
sCachedScripts =
|
||||
new nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>;
|
||||
sCachedScripts->Init();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameScriptExecutor::DestroyCx()
|
||||
{
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
if (xpc) {
|
||||
xpc->ReleaseJSContext(mCx, PR_TRUE);
|
||||
} else {
|
||||
JS_DestroyContext(mCx);
|
||||
}
|
||||
mCx = nsnull;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
CachedScriptUnrooter(const nsAString& aKey,
|
||||
nsFrameScriptExecutorJSObjectHolder*& aData,
|
||||
void* aUserArg)
|
||||
{
|
||||
JSContext* cx = static_cast<JSContext*>(aUserArg);
|
||||
JS_RemoveObjectRoot(cx, &(aData->mObject));
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsFrameScriptExecutor::Shutdown()
|
||||
{
|
||||
if (sCachedScripts) {
|
||||
JSContext* cx = nsnull;
|
||||
nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
|
||||
if (cx) {
|
||||
#ifdef DEBUG_smaug
|
||||
printf("Will clear cached frame manager scripts!\n");
|
||||
#endif
|
||||
JSAutoRequest ar(cx);
|
||||
NS_ASSERTION(sCachedScripts != nsnull, "Need cached scripts");
|
||||
sCachedScripts->Enumerate(CachedScriptUnrooter, cx);
|
||||
} else {
|
||||
NS_WARNING("No context available. Leaking cached scripts!\n");
|
||||
}
|
||||
|
||||
delete sCachedScripts;
|
||||
sCachedScripts = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL)
|
||||
{
|
||||
if (!mGlobal || !mCx) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsFrameScriptExecutorJSObjectHolder* holder = sCachedScripts->Get(aURL);
|
||||
if (holder) {
|
||||
nsContentUtils::ThreadJSContextStack()->Push(mCx);
|
||||
{
|
||||
// Need to scope JSAutoRequest to happen after Push but before Pop,
|
||||
// at least for now. See bug 584673.
|
||||
JSAutoRequest ar(mCx);
|
||||
JSObject* global = nsnull;
|
||||
mGlobal->GetJSObject(&global);
|
||||
if (global) {
|
||||
jsval val;
|
||||
JS_ExecuteScript(mCx, global,
|
||||
(JSScript*)JS_GetPrivate(mCx, holder->mObject),
|
||||
&val);
|
||||
}
|
||||
}
|
||||
JSContext* unused;
|
||||
nsContentUtils::ThreadJSContextStack()->Pop(&unused);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString url = NS_ConvertUTF16toUTF8(aURL);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
NS_NewChannel(getter_AddRefs(channel), uri);
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> input;
|
||||
channel->Open(getter_AddRefs(input));
|
||||
nsString dataString;
|
||||
if (input) {
|
||||
const PRUint32 bufferSize = 1024;
|
||||
char buffer[bufferSize];
|
||||
nsCString data;
|
||||
PRUint32 avail = 0;
|
||||
input->Available(&avail);
|
||||
PRUint32 read = 0;
|
||||
if (avail) {
|
||||
while (NS_SUCCEEDED(input->Read(buffer, bufferSize, &read)) && read) {
|
||||
data.Append(buffer, read);
|
||||
read = 0;
|
||||
}
|
||||
}
|
||||
nsScriptLoader::ConvertToUTF16(channel, (PRUint8*)data.get(), data.Length(),
|
||||
EmptyString(), nsnull, dataString);
|
||||
}
|
||||
|
||||
if (!dataString.IsEmpty()) {
|
||||
nsContentUtils::ThreadJSContextStack()->Push(mCx);
|
||||
{
|
||||
// Need to scope JSAutoRequest to happen after Push but before Pop,
|
||||
// at least for now. See bug 584673.
|
||||
JSAutoRequest ar(mCx);
|
||||
JSObject* global = nsnull;
|
||||
mGlobal->GetJSObject(&global);
|
||||
if (global) {
|
||||
JSPrincipals* jsprin = nsnull;
|
||||
mPrincipal->GetJSPrincipals(mCx, &jsprin);
|
||||
nsContentUtils::XPConnect()->FlagSystemFilenamePrefix(url.get(), PR_TRUE);
|
||||
JSScript* script =
|
||||
JS_CompileUCScriptForPrincipals(mCx, nsnull, jsprin,
|
||||
(jschar*)dataString.get(),
|
||||
dataString.Length(),
|
||||
url.get(), 1);
|
||||
|
||||
if (script) {
|
||||
JSObject* scriptObj = JS_NewScriptObject(mCx, script);
|
||||
JS_AddObjectRoot(mCx, &scriptObj);
|
||||
nsCAutoString scheme;
|
||||
uri->GetScheme(scheme);
|
||||
// We don't cache data: scripts!
|
||||
if (!scheme.EqualsLiteral("data")) {
|
||||
nsFrameScriptExecutorJSObjectHolder* holder =
|
||||
new nsFrameScriptExecutorJSObjectHolder(scriptObj);
|
||||
// Root the object also for caching.
|
||||
JS_AddNamedObjectRoot(mCx, &(holder->mObject),
|
||||
"Cached message manager script");
|
||||
sCachedScripts->Put(aURL, holder);
|
||||
}
|
||||
jsval val;
|
||||
JS_ExecuteScript(mCx, global,
|
||||
(JSScript*)JS_GetPrivate(mCx, scriptObj), &val);
|
||||
JS_RemoveObjectRoot(mCx, &scriptObj);
|
||||
}
|
||||
//XXX Argh, JSPrincipals are manually refcounted!
|
||||
JSPRINCIPALS_DROP(mCx, jsprin);
|
||||
}
|
||||
}
|
||||
JSContext* unused;
|
||||
nsContentUtils::ThreadJSContextStack()->Pop(&unused);
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,9 @@
|
||||
#include "nsIAtom.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
class nsAXPCNativeCallContext;
|
||||
struct JSContext;
|
||||
@ -150,4 +153,26 @@ protected:
|
||||
nsTArray<nsString> mPendingScripts;
|
||||
};
|
||||
|
||||
struct nsFrameScriptExecutorJSObjectHolder
|
||||
{
|
||||
nsFrameScriptExecutorJSObjectHolder(JSObject* aObject) : mObject(aObject) {}
|
||||
JSObject* mObject;
|
||||
};
|
||||
|
||||
class nsFrameScriptExecutor
|
||||
{
|
||||
public:
|
||||
static void Shutdown();
|
||||
protected:
|
||||
nsFrameScriptExecutor() : mCx(nsnull) {}
|
||||
void DidCreateCx();
|
||||
// Call this when you want to destroy mCx.
|
||||
void DestroyCx();
|
||||
void LoadFrameScriptInternal(const nsAString& aURL);
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
|
||||
JSContext* mCx;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
static nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>* sCachedScripts;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -110,7 +110,7 @@ bool SendAsyncMessageToParent(void* aCallbackData,
|
||||
nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
|
||||
nsIContent* aOwner,
|
||||
nsFrameMessageManager* aChrome)
|
||||
: mCx(nsnull), mDocShell(aShell), mInitialized(PR_FALSE), mLoadingScript(PR_FALSE),
|
||||
: mDocShell(aShell), mInitialized(PR_FALSE), mLoadingScript(PR_FALSE),
|
||||
mDelayedDisconnect(PR_FALSE), mOwner(aOwner), mChromeMessageManager(aChrome)
|
||||
{
|
||||
}
|
||||
@ -196,8 +196,7 @@ nsInProcessTabChildGlobal::Disconnect()
|
||||
}
|
||||
if (!mLoadingScript) {
|
||||
if (mCx) {
|
||||
JS_DestroyContext(mCx);
|
||||
mCx = nsnull;
|
||||
DestroyCx();
|
||||
}
|
||||
} else {
|
||||
mDelayedDisconnect = PR_TRUE;
|
||||
@ -296,7 +295,7 @@ nsInProcessTabChildGlobal::InitTabChildGlobal()
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
JS_SetGlobalObject(cx, global);
|
||||
|
||||
DidCreateCx();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -307,69 +306,10 @@ nsInProcessTabChildGlobal::LoadFrameScript(const nsAString& aURL)
|
||||
mInitialized = PR_TRUE;
|
||||
Init();
|
||||
}
|
||||
if (!mGlobal || !mCx) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString url = NS_ConvertUTF16toUTF8(aURL);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
NS_NewChannel(getter_AddRefs(channel), uri);
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> input;
|
||||
channel->Open(getter_AddRefs(input));
|
||||
nsString dataString;
|
||||
if (input) {
|
||||
const PRUint32 bufferSize = 256;
|
||||
char buffer[bufferSize];
|
||||
nsCString data;
|
||||
PRUint32 avail = 0;
|
||||
input->Available(&avail);
|
||||
PRUint32 read = 0;
|
||||
if (avail) {
|
||||
while (NS_SUCCEEDED(input->Read(buffer, bufferSize, &read)) && read) {
|
||||
data.Append(buffer, read);
|
||||
read = 0;
|
||||
}
|
||||
}
|
||||
nsScriptLoader::ConvertToUTF16(channel, (PRUint8*)data.get(), data.Length(),
|
||||
EmptyString(), nsnull, dataString);
|
||||
}
|
||||
|
||||
if (!dataString.IsEmpty()) {
|
||||
nsContentUtils::ThreadJSContextStack()->Push(mCx);
|
||||
{
|
||||
// Need to scope JSAutoRequest to happen after Push but before Pop,
|
||||
// at least for now. See bug 584673.
|
||||
JSAutoRequest ar(mCx);
|
||||
jsval retval;
|
||||
JSObject* global = nsnull;
|
||||
mGlobal->GetJSObject(&global);
|
||||
if (global) {
|
||||
JSPrincipals* jsprin = nsnull;
|
||||
mPrincipal->GetJSPrincipals(mCx, &jsprin);
|
||||
nsContentUtils::XPConnect()->FlagSystemFilenamePrefix(url.get(), PR_TRUE);
|
||||
PRBool tmp = mLoadingScript;
|
||||
mLoadingScript = PR_TRUE;
|
||||
JS_EvaluateUCScriptForPrincipals(mCx, global, jsprin,
|
||||
(jschar*)dataString.get(),
|
||||
dataString.Length(),
|
||||
url.get(), 1, &retval);
|
||||
//XXX Argh, JSPrincipals are manually refcounted!
|
||||
JSPRINCIPALS_DROP(mCx, jsprin);
|
||||
mLoadingScript = tmp;
|
||||
}
|
||||
}
|
||||
JSContext* unused;
|
||||
nsContentUtils::ThreadJSContextStack()->Pop(&unused);
|
||||
}
|
||||
PRBool tmp = mLoadingScript;
|
||||
mLoadingScript = PR_TRUE;
|
||||
LoadFrameScriptInternal(aURL);
|
||||
mLoadingScript = tmp;
|
||||
if (!mLoadingScript && mDelayedDisconnect) {
|
||||
mDelayedDisconnect = PR_FALSE;
|
||||
Disconnect();
|
||||
|
@ -43,18 +43,17 @@
|
||||
#include "nsFrameMessageManager.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
class nsInProcessTabChildGlobal : public nsDOMEventTargetHelper,
|
||||
public nsFrameScriptExecutor,
|
||||
public nsIInProcessContentFrameMessageManager,
|
||||
public nsIScriptObjectPrincipal,
|
||||
public nsIScriptContextPrincipal
|
||||
@ -126,9 +125,6 @@ protected:
|
||||
nsresult Init();
|
||||
nsresult InitTabChildGlobal();
|
||||
nsCOMPtr<nsIContentFrameMessageManager> mMessageManager;
|
||||
JSContext* mCx;
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
PRPackedBool mInitialized;
|
||||
PRPackedBool mLoadingScript;
|
||||
|
@ -42,7 +42,6 @@
|
||||
*/
|
||||
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsMemory.h"
|
||||
@ -241,27 +240,6 @@ nsTextFragment::SetTo(const PRUnichar* aBuffer, PRInt32 aLength)
|
||||
mState.mLength = aLength;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFragment::AppendTo(nsAString& aString) const
|
||||
{
|
||||
if (mState.mIs2b) {
|
||||
aString.Append(m2b, mState.mLength);
|
||||
} else {
|
||||
AppendASCIItoUTF16(Substring(m1b, m1b + mState.mLength),
|
||||
aString);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFragment::AppendTo(nsAString& aString, PRInt32 aOffset, PRInt32 aLength) const
|
||||
{
|
||||
if (mState.mIs2b) {
|
||||
aString.Append(m2b + aOffset, aLength);
|
||||
} else {
|
||||
AppendASCIItoUTF16(Substring(m1b + aOffset, m1b + aOffset + aLength), aString);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFragment::CopyTo(PRUnichar *aDest, PRInt32 aOffset, PRInt32 aCount)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@
|
||||
#ifndef nsTextFragment_h___
|
||||
#define nsTextFragment_h___
|
||||
|
||||
#include "nsAString.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
class nsString;
|
||||
class nsCString;
|
||||
@ -165,14 +165,27 @@ public:
|
||||
/**
|
||||
* Append the contents of this string fragment to aString
|
||||
*/
|
||||
void AppendTo(nsAString& aString) const;
|
||||
void AppendTo(nsAString& aString) const {
|
||||
if (mState.mIs2b) {
|
||||
aString.Append(m2b, mState.mLength);
|
||||
} else {
|
||||
AppendASCIItoUTF16(Substring(m1b, m1b + mState.mLength),
|
||||
aString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a substring of the contents of this string fragment to aString.
|
||||
* @param aOffset where to start the substring in this text fragment
|
||||
* @param aLength the length of the substring
|
||||
*/
|
||||
void AppendTo(nsAString& aString, PRInt32 aOffset, PRInt32 aLength) const;
|
||||
void AppendTo(nsAString& aString, PRInt32 aOffset, PRInt32 aLength) const {
|
||||
if (mState.mIs2b) {
|
||||
aString.Append(m2b + aOffset, aLength);
|
||||
} else {
|
||||
AppendASCIItoUTF16(Substring(m1b + aOffset, m1b + aOffset + aLength), aString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a copy of the fragments contents starting at offset for
|
||||
|
@ -339,17 +339,6 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
|
||||
printf_stderr ("--- WebGL context created: %p\n", gl.get());
|
||||
|
||||
if (gl->IsGLES2()) {
|
||||
// On native GLES2, no need to validate, the compiler will do it
|
||||
mShaderValidation = PR_FALSE;
|
||||
} else {
|
||||
// Otherwise, check the shader validator pref
|
||||
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
|
||||
|
||||
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
|
||||
}
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mResetLayer = PR_TRUE;
|
||||
|
@ -56,7 +56,7 @@
|
||||
|
||||
#include "jstypedarray.h"
|
||||
|
||||
#if !defined(USE_GLES2) && defined(USE_ANGLE)
|
||||
#if defined(USE_ANGLE)
|
||||
// shader translator
|
||||
#include "angle/ShaderLang.h"
|
||||
#endif
|
||||
@ -2840,7 +2840,7 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
|
||||
return NS_OK;
|
||||
MakeContextCurrent();
|
||||
|
||||
#if !defined(USE_GLES2) && defined(USE_ANGLE)
|
||||
#if defined(USE_ANGLE)
|
||||
if (shader->NeedsTranslation() && mShaderValidation) {
|
||||
ShHandle compiler = 0;
|
||||
int debugFlags = 0;
|
||||
@ -2864,7 +2864,12 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
|
||||
const char *s = src.get();
|
||||
|
||||
if (!ShCompile(compiler, &s, 1, EShOptSimple, debugFlags)) {
|
||||
shader->SetTranslationFailure(nsDependentCString(ShGetInfoLog(compiler)));
|
||||
const char* info = ShGetInfoLog(compiler);
|
||||
if (info) {
|
||||
shader->SetTranslationFailure(nsDependentCString(info));
|
||||
} else {
|
||||
shader->SetTranslationFailure(NS_LITERAL_CSTRING("Internal error: failed to get shader info log"));
|
||||
}
|
||||
ShDestruct(compiler);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -39,9 +39,12 @@
|
||||
|
||||
#include "WebGLContext.h"
|
||||
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include "CheckedInt.h"
|
||||
|
||||
#if !defined(USE_GLES2) && defined(USE_ANGLE)
|
||||
#if defined(USE_ANGLE)
|
||||
#include "angle/ShaderLang.h"
|
||||
#endif
|
||||
|
||||
@ -444,17 +447,26 @@ WebGLContext::InitAndValidateGL()
|
||||
gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
}
|
||||
|
||||
#if !defined(USE_GLES2) && defined(USE_ANGLE)
|
||||
// initialize shader translator
|
||||
static bool didTranslatorInit = false;
|
||||
if (!didTranslatorInit && mShaderValidation) {
|
||||
if (!ShInitialize()) {
|
||||
LogMessage("GLSL translator initialization failed!");
|
||||
return PR_FALSE;
|
||||
static bool didTranslatorCheck = false;
|
||||
if (!didTranslatorCheck) {
|
||||
// Check the shader validator pref
|
||||
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
|
||||
|
||||
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
|
||||
|
||||
#if defined(USE_ANGLE)
|
||||
// initialize shader translator
|
||||
if (mShaderValidation) {
|
||||
if (!ShInitialize()) {
|
||||
LogMessage("GLSL translator initialization failed!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
didTranslatorInit = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
didTranslatorCheck = true;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
@ -106,6 +106,11 @@ nsHTMLDNSPrefetch::Initialize()
|
||||
rv = CallGetService(kDNSServiceCID, &sDNSService);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
if (mozilla::net::IsNeckoChild())
|
||||
mozilla::net::NeckoChild::InitNeckoChild();
|
||||
#endif
|
||||
|
||||
sInitialized = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
This is sqlite 3.6.23.1
|
||||
This is sqlite 3.7.0.1
|
||||
|
||||
-- Shawn Wilsher <me@shawnwilsher.com>, 03/2010
|
||||
-- Shawn Wilsher <me@shawnwilsher.com>, 08/2010
|
||||
|
||||
See http://www.sqlite.org/ for more info.
|
||||
|
||||
|
13408
db/sqlite3/src/sqlite3.c
13408
db/sqlite3/src/sqlite3.c
File diff suppressed because it is too large
Load Diff
@ -107,9 +107,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.6.23.1"
|
||||
#define SQLITE_VERSION_NUMBER 3006023
|
||||
#define SQLITE_SOURCE_ID "2010-03-26 22:28:06 b078b588d617e07886ad156e9f54ade6d823568e"
|
||||
#define SQLITE_VERSION "3.7.0.1"
|
||||
#define SQLITE_VERSION_NUMBER 3007000
|
||||
#define SQLITE_SOURCE_ID "2010-08-04 12:31:11 042a1abb030a0711386add7eb6e10832cc8b0f57"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -146,7 +146,6 @@ SQLITE_API const char *sqlite3_libversion(void);
|
||||
SQLITE_API const char *sqlite3_sourceid(void);
|
||||
SQLITE_API int sqlite3_libversion_number(void);
|
||||
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Compilation Options Diagnostics
|
||||
**
|
||||
@ -169,9 +168,10 @@ SQLITE_API int sqlite3_libversion_number(void);
|
||||
** See also: SQL functions [sqlite_compileoption_used()] and
|
||||
** [sqlite_compileoption_get()] and the [compile_options pragma].
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
SQLITE_API int sqlite3_compileoption_used(const char *zOptName);
|
||||
SQLITE_API const char *sqlite3_compileoption_get(int N);
|
||||
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** CAPI3REF: Test To See If The Library Is Threadsafe
|
||||
@ -393,7 +393,7 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */
|
||||
#define SQLITE_FULL 13 /* Insertion failed because database is full */
|
||||
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
|
||||
#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */
|
||||
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
|
||||
#define SQLITE_EMPTY 16 /* Database is empty */
|
||||
#define SQLITE_SCHEMA 17 /* The database schema changed */
|
||||
#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
|
||||
@ -449,7 +449,12 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
|
||||
#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
|
||||
#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8) )
|
||||
#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
|
||||
#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
|
||||
#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags For File Open Operations
|
||||
@ -476,11 +481,12 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Device Characteristics
|
||||
**
|
||||
** The xDeviceCapabilities method of the [sqlite3_io_methods]
|
||||
** The xDeviceCharacteristics method of the [sqlite3_io_methods]
|
||||
** object returns an integer which is a vector of the these
|
||||
** bit values expressing I/O characteristics of the mass storage
|
||||
** device that holds the file that the [sqlite3_io_methods]
|
||||
@ -497,17 +503,18 @@ SQLITE_API int sqlite3_exec(
|
||||
** information is written to disk in the same order as calls
|
||||
** to xWrite().
|
||||
*/
|
||||
#define SQLITE_IOCAP_ATOMIC 0x00000001
|
||||
#define SQLITE_IOCAP_ATOMIC512 0x00000002
|
||||
#define SQLITE_IOCAP_ATOMIC1K 0x00000004
|
||||
#define SQLITE_IOCAP_ATOMIC2K 0x00000008
|
||||
#define SQLITE_IOCAP_ATOMIC4K 0x00000010
|
||||
#define SQLITE_IOCAP_ATOMIC8K 0x00000020
|
||||
#define SQLITE_IOCAP_ATOMIC16K 0x00000040
|
||||
#define SQLITE_IOCAP_ATOMIC32K 0x00000080
|
||||
#define SQLITE_IOCAP_ATOMIC64K 0x00000100
|
||||
#define SQLITE_IOCAP_SAFE_APPEND 0x00000200
|
||||
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
|
||||
#define SQLITE_IOCAP_ATOMIC 0x00000001
|
||||
#define SQLITE_IOCAP_ATOMIC512 0x00000002
|
||||
#define SQLITE_IOCAP_ATOMIC1K 0x00000004
|
||||
#define SQLITE_IOCAP_ATOMIC2K 0x00000008
|
||||
#define SQLITE_IOCAP_ATOMIC4K 0x00000010
|
||||
#define SQLITE_IOCAP_ATOMIC8K 0x00000020
|
||||
#define SQLITE_IOCAP_ATOMIC16K 0x00000040
|
||||
#define SQLITE_IOCAP_ATOMIC32K 0x00000080
|
||||
#define SQLITE_IOCAP_ATOMIC64K 0x00000100
|
||||
#define SQLITE_IOCAP_SAFE_APPEND 0x00000200
|
||||
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
|
||||
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
|
||||
|
||||
/*
|
||||
** CAPI3REF: File Locking Levels
|
||||
@ -658,6 +665,12 @@ struct sqlite3_io_methods {
|
||||
int (*xFileControl)(sqlite3_file*, int op, void *pArg);
|
||||
int (*xSectorSize)(sqlite3_file*);
|
||||
int (*xDeviceCharacteristics)(sqlite3_file*);
|
||||
/* Methods above are valid for version 1 */
|
||||
int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
|
||||
int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
|
||||
void (*xShmBarrier)(sqlite3_file*);
|
||||
int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
|
||||
/* Methods above are valid for version 2 */
|
||||
/* Additional methods may be added in future releases */
|
||||
};
|
||||
|
||||
@ -675,11 +688,19 @@ struct sqlite3_io_methods {
|
||||
** into an integer that the pArg argument points to. This capability
|
||||
** is used during testing and only needs to be supported when SQLITE_TEST
|
||||
** is defined.
|
||||
**
|
||||
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
|
||||
** layer a hint of how large the database file will grow to be during the
|
||||
** current transaction. This hint is not guaranteed to be accurate but it
|
||||
** is often close. The underlying VFS might choose to preallocate database
|
||||
** file space based on this hint in order to help writes to the database
|
||||
** file run faster.
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
#define SQLITE_GET_LOCKPROXYFILE 2
|
||||
#define SQLITE_SET_LOCKPROXYFILE 3
|
||||
#define SQLITE_LAST_ERRNO 4
|
||||
#define SQLITE_FCNTL_SIZE_HINT 5
|
||||
|
||||
/*
|
||||
** CAPI3REF: Mutex Handle
|
||||
@ -811,20 +832,27 @@ typedef struct sqlite3_mutex sqlite3_mutex;
|
||||
** handled as a fatal error by SQLite, vfs implementations should endeavor
|
||||
** to prevent this by setting mxPathname to a sufficiently large value.
|
||||
**
|
||||
** The xRandomness(), xSleep(), and xCurrentTime() interfaces
|
||||
** are not strictly a part of the filesystem, but they are
|
||||
** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64()
|
||||
** interfaces are not strictly a part of the filesystem, but they are
|
||||
** included in the VFS structure for completeness.
|
||||
** The xRandomness() function attempts to return nBytes bytes
|
||||
** of good-quality randomness into zOut. The return value is
|
||||
** the actual number of bytes of randomness obtained.
|
||||
** The xSleep() method causes the calling thread to sleep for at
|
||||
** least the number of microseconds given. The xCurrentTime()
|
||||
** method returns a Julian Day Number for the current date and time.
|
||||
**
|
||||
** method returns a Julian Day Number for the current date and time as
|
||||
** a floating point value.
|
||||
** The xCurrentTimeInt64() method returns, as an integer, the Julian
|
||||
** Day Number multipled by 86400000 (the number of milliseconds in
|
||||
** a 24-hour day).
|
||||
** ^SQLite will use the xCurrentTimeInt64() method to get the current
|
||||
** date and time if that method is available (if iVersion is 2 or
|
||||
** greater and the function pointer is not NULL) and will fall back
|
||||
** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
|
||||
*/
|
||||
typedef struct sqlite3_vfs sqlite3_vfs;
|
||||
struct sqlite3_vfs {
|
||||
int iVersion; /* Structure version number */
|
||||
int iVersion; /* Structure version number (currently 2) */
|
||||
int szOsFile; /* Size of subclassed sqlite3_file */
|
||||
int mxPathname; /* Maximum file pathname length */
|
||||
sqlite3_vfs *pNext; /* Next registered VFS */
|
||||
@ -843,8 +871,16 @@ struct sqlite3_vfs {
|
||||
int (*xSleep)(sqlite3_vfs*, int microseconds);
|
||||
int (*xCurrentTime)(sqlite3_vfs*, double*);
|
||||
int (*xGetLastError)(sqlite3_vfs*, int, char *);
|
||||
/* New fields may be appended in figure versions. The iVersion
|
||||
** value will increment whenever this happens. */
|
||||
/*
|
||||
** The methods above are in version 1 of the sqlite_vfs object
|
||||
** definition. Those that follow are added in version 2 or later
|
||||
*/
|
||||
int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
|
||||
/*
|
||||
** The methods above are in versions 1 and 2 of the sqlite_vfs object.
|
||||
** New fields may be appended in figure versions. The iVersion
|
||||
** value will increment whenever this happens.
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
@ -856,13 +892,58 @@ struct sqlite3_vfs {
|
||||
** With SQLITE_ACCESS_EXISTS, the xAccess method
|
||||
** simply checks whether the file exists.
|
||||
** With SQLITE_ACCESS_READWRITE, the xAccess method
|
||||
** checks whether the file is both readable and writable.
|
||||
** checks whether the named directory is both readable and writable
|
||||
** (in other words, if files can be added, removed, and renamed within
|
||||
** the directory).
|
||||
** The SQLITE_ACCESS_READWRITE constant is currently used only by the
|
||||
** [temp_store_directory pragma], though this could change in a future
|
||||
** release of SQLite.
|
||||
** With SQLITE_ACCESS_READ, the xAccess method
|
||||
** checks whether the file is readable.
|
||||
** checks whether the file is readable. The SQLITE_ACCESS_READ constant is
|
||||
** currently unused, though it might be used in a future release of
|
||||
** SQLite.
|
||||
*/
|
||||
#define SQLITE_ACCESS_EXISTS 0
|
||||
#define SQLITE_ACCESS_READWRITE 1
|
||||
#define SQLITE_ACCESS_READ 2
|
||||
#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */
|
||||
#define SQLITE_ACCESS_READ 2 /* Unused */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags for the xShmLock VFS method
|
||||
**
|
||||
** These integer constants define the various locking operations
|
||||
** allowed by the xShmLock method of [sqlite3_io_methods]. The
|
||||
** following are the only legal combinations of flags to the
|
||||
** xShmLock method:
|
||||
**
|
||||
** <ul>
|
||||
** <li> SQLITE_SHM_LOCK | SQLITE_SHM_SHARED
|
||||
** <li> SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE
|
||||
** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED
|
||||
** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE
|
||||
** </ul>
|
||||
**
|
||||
** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as
|
||||
** was given no the corresponding lock.
|
||||
**
|
||||
** The xShmLock method can transition between unlocked and SHARED or
|
||||
** between unlocked and EXCLUSIVE. It cannot transition between SHARED
|
||||
** and EXCLUSIVE.
|
||||
*/
|
||||
#define SQLITE_SHM_UNLOCK 1
|
||||
#define SQLITE_SHM_LOCK 2
|
||||
#define SQLITE_SHM_SHARED 4
|
||||
#define SQLITE_SHM_EXCLUSIVE 8
|
||||
|
||||
/*
|
||||
** CAPI3REF: Maximum xShmLock index
|
||||
**
|
||||
** The xShmLock method on [sqlite3_io_methods] may use values
|
||||
** between 0 and this upper bound as its "offset" argument.
|
||||
** The SQLite core will never attempt to acquire or release a
|
||||
** lock outside of this range
|
||||
*/
|
||||
#define SQLITE_SHM_NLOCK 8
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Initialize The SQLite Library
|
||||
@ -973,11 +1054,10 @@ SQLITE_API int sqlite3_os_end(void);
|
||||
** ^If the option is unknown or SQLite is unable to set the option
|
||||
** then this routine returns a non-zero [error code].
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...);
|
||||
SQLITE_API int sqlite3_config(int, ...);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configure database connections
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** The sqlite3_db_config() interface is used to make configuration
|
||||
** changes to a [database connection]. The interface is similar to
|
||||
@ -997,11 +1077,10 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...);
|
||||
** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if
|
||||
** the call is considered successful.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_config(sqlite3*, int op, ...);
|
||||
SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Memory Allocation Routines
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** An instance of this object defines the interface between SQLite
|
||||
** and low-level memory allocation routines.
|
||||
@ -1083,7 +1162,6 @@ struct sqlite3_mem_methods {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configuration Options
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** These constants are the available integer configuration options that
|
||||
** can be passed as the first argument to the [sqlite3_config()] interface.
|
||||
@ -1269,6 +1347,24 @@ struct sqlite3_mem_methods {
|
||||
** [sqlite3_pcache_methods] object. SQLite copies of the current
|
||||
** page cache implementation into that object.)^ </dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_LOG</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
|
||||
** function with a call signature of void(*)(void*,int,const char*),
|
||||
** and a pointer to void. ^If the function pointer is not NULL, it is
|
||||
** invoked by [sqlite3_log()] to process each logging event. ^If the
|
||||
** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
|
||||
** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is
|
||||
** passed through as the first parameter to the application-defined logger
|
||||
** function whenever that function is invoked. ^The second parameter to
|
||||
** the logger function is a copy of the first parameter to the corresponding
|
||||
** [sqlite3_log()] call and is intended to be a [result code] or an
|
||||
** [extended result code]. ^The third parameter passed to the logger is
|
||||
** log message after formatting via [sqlite3_snprintf()].
|
||||
** The SQLite logging interface is not reentrant; the logger function
|
||||
** supplied by the application must not invoke any SQLite interface.
|
||||
** In a multi-threaded application, the application-defined logger
|
||||
** function must be threadsafe. </dd>
|
||||
**
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
||||
@ -1289,8 +1385,7 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configuration Options
|
||||
** EXPERIMENTAL
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
**
|
||||
** These constants are the available integer configuration options that
|
||||
** can be passed as the second argument to the [sqlite3_db_config()] interface.
|
||||
@ -2066,7 +2161,6 @@ SQLITE_API int sqlite3_set_authorizer(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Tracing And Profiling Functions
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** These routines register callback functions that can be used for
|
||||
** tracing and profiling the execution of SQL statements.
|
||||
@ -2084,7 +2178,7 @@ SQLITE_API int sqlite3_set_authorizer(
|
||||
** the original statement text and an estimate of wall-clock time
|
||||
** of how long that statement took to run.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
|
||||
SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
|
||||
SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
|
||||
void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
|
||||
|
||||
@ -2877,6 +2971,14 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
|
||||
** be the case that the same database connection is being used by two or
|
||||
** more threads at the same moment in time.
|
||||
**
|
||||
** For all versions of SQLite up to and including 3.6.23.1, it was required
|
||||
** after sqlite3_step() returned anything other than [SQLITE_ROW] that
|
||||
** [sqlite3_reset()] be called before any subsequent invocation of
|
||||
** sqlite3_step(). Failure to invoke [sqlite3_reset()] in this way would
|
||||
** result in an [SQLITE_MISUSE] return from sqlite3_step(). But after
|
||||
** version 3.6.23.1, sqlite3_step() began calling [sqlite3_reset()]
|
||||
** automatically in this circumstance rather than returning [SQLITE_MISUSE].
|
||||
**
|
||||
** <b>Goofy Interface Alert:</b> In the legacy interface, the sqlite3_step()
|
||||
** API always returns a generic error code, [SQLITE_ERROR], following any
|
||||
** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call
|
||||
@ -3689,7 +3791,7 @@ SQLITE_API int sqlite3_collation_needed16(
|
||||
void(*)(void*,sqlite3*,int eTextRep,const void*)
|
||||
);
|
||||
|
||||
#if SQLITE_HAS_CODEC
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
/*
|
||||
** Specify the key for an encrypted database. This routine should be
|
||||
** called right after sqlite3_open().
|
||||
@ -3872,8 +3974,6 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
|
||||
** an error or constraint causes an implicit rollback to occur.
|
||||
** ^The rollback callback is not invoked if a transaction is
|
||||
** automatically rolled back because the database connection is closed.
|
||||
** ^The rollback callback is not invoked if a transaction is
|
||||
** rolled back because a commit callback returned non-zero.
|
||||
**
|
||||
** See also the [sqlite3_update_hook()] interface.
|
||||
*/
|
||||
@ -4159,8 +4259,6 @@ SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
|
||||
SQLITE_API void sqlite3_reset_auto_extension(void);
|
||||
|
||||
/*
|
||||
****** EXPERIMENTAL - subject to change without notice **************
|
||||
**
|
||||
** The interface to the virtual-table mechanism is currently considered
|
||||
** to be experimental. The interface might change in incompatible ways.
|
||||
** If this is a problem for you, do not use the interface at this time.
|
||||
@ -4180,7 +4278,6 @@ typedef struct sqlite3_module sqlite3_module;
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Object
|
||||
** KEYWORDS: sqlite3_module {virtual table module}
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** This structure, sometimes called a a "virtual table module",
|
||||
** defines the implementation of a [virtual tables].
|
||||
@ -4227,7 +4324,6 @@ struct sqlite3_module {
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Indexing Information
|
||||
** KEYWORDS: sqlite3_index_info
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** The sqlite3_index_info structure and its substructures is used to
|
||||
** pass information into and receive the reply from the [xBestIndex]
|
||||
@ -4309,7 +4405,6 @@ struct sqlite3_index_info {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Register A Virtual Table Implementation
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^These routines are used to register a new [virtual table module] name.
|
||||
** ^Module names must be registered before
|
||||
@ -4331,13 +4426,13 @@ struct sqlite3_index_info {
|
||||
** interface is equivalent to sqlite3_create_module_v2() with a NULL
|
||||
** destructor.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module(
|
||||
SQLITE_API int sqlite3_create_module(
|
||||
sqlite3 *db, /* SQLite connection to register module with */
|
||||
const char *zName, /* Name of the module */
|
||||
const sqlite3_module *p, /* Methods for the module */
|
||||
void *pClientData /* Client data for xCreate/xConnect */
|
||||
);
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
|
||||
SQLITE_API int sqlite3_create_module_v2(
|
||||
sqlite3 *db, /* SQLite connection to register module with */
|
||||
const char *zName, /* Name of the module */
|
||||
const sqlite3_module *p, /* Methods for the module */
|
||||
@ -4348,7 +4443,6 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Instance Object
|
||||
** KEYWORDS: sqlite3_vtab
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** Every [virtual table module] implementation uses a subclass
|
||||
** of this object to describe a particular instance
|
||||
@ -4374,7 +4468,6 @@ struct sqlite3_vtab {
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Cursor Object
|
||||
** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor}
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** Every [virtual table module] implementation uses a subclass of the
|
||||
** following structure to describe cursors that point into the
|
||||
@ -4396,18 +4489,16 @@ struct sqlite3_vtab_cursor {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Declare The Schema Of A Virtual Table
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [xCreate] and [xConnect] methods of a
|
||||
** [virtual table module] call this interface
|
||||
** to declare the format (the names and datatypes of the columns) of
|
||||
** the virtual tables they implement.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
|
||||
SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Overload A Function For A Virtual Table
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^(Virtual tables can provide alternative implementations of functions
|
||||
** using the [xFindFunction] method of the [virtual table module].
|
||||
@ -4422,7 +4513,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zS
|
||||
** purpose is to be a placeholder function that can be overloaded
|
||||
** by a [virtual table].
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
|
||||
SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
|
||||
|
||||
/*
|
||||
** The interface to the virtual-table mechanism defined above (back up
|
||||
@ -4432,8 +4523,6 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const cha
|
||||
**
|
||||
** When the virtual-table mechanism stabilizes, we will declare the
|
||||
** interface fixed, support it indefinitely, and remove this comment.
|
||||
**
|
||||
****** EXPERIMENTAL - subject to change without notice **************
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -4776,7 +4865,6 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Mutex Methods Object
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** An instance of this structure defines the low-level routines
|
||||
** used to allocate and use mutexes.
|
||||
@ -4989,11 +5077,11 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_RESERVE 14
|
||||
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16
|
||||
#define SQLITE_TESTCTRL_LAST 16
|
||||
#define SQLITE_TESTCTRL_PGHDRSZ 17
|
||||
#define SQLITE_TESTCTRL_LAST 17
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQLite Runtime Status
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^This interface is used to retrieve runtime status information
|
||||
** about the preformance of SQLite, and optionally to reset various
|
||||
@ -5021,12 +5109,11 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
**
|
||||
** See also: [sqlite3_db_status()]
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Parameters
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** These integer constants designate various run-time status parameters
|
||||
** that can be returned by [sqlite3_status()].
|
||||
@ -5113,14 +5200,15 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pH
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Status
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^This interface is used to retrieve runtime status information
|
||||
** about a single [database connection]. ^The first argument is the
|
||||
** database connection object to be interrogated. ^The second argument
|
||||
** is the parameter to interrogate. ^Currently, the only allowed value
|
||||
** for the second parameter is [SQLITE_DBSTATUS_LOOKASIDE_USED].
|
||||
** Additional options will likely appear in future releases of SQLite.
|
||||
** is an integer constant, taken from the set of
|
||||
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
|
||||
** determiness the parameter to interrogate. The set of
|
||||
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
|
||||
** to grow in future releases of SQLite.
|
||||
**
|
||||
** ^The current value of the requested parameter is written into *pCur
|
||||
** and the highest instantaneous value is written into *pHiwtr. ^If
|
||||
@ -5129,11 +5217,10 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pH
|
||||
**
|
||||
** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Parameters for database connections
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** These constants are the available integer "verbs" that can be passed as
|
||||
** the second argument to the [sqlite3_db_status()] interface.
|
||||
@ -5148,14 +5235,21 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur
|
||||
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
|
||||
** <dd>This parameter returns the number of lookaside memory slots currently
|
||||
** checked out.</dd>)^
|
||||
**
|
||||
** <dt>SQLITE_DBSTATUS_CACHE_USED</dt>
|
||||
** <dd>^This parameter returns the approximate number of of bytes of heap
|
||||
** memory used by all pager caches associated with the database connection.
|
||||
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
|
||||
** </dd>
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
|
||||
#define SQLITE_DBSTATUS_CACHE_USED 1
|
||||
#define SQLITE_DBSTATUS_MAX 1 /* Largest defined DBSTATUS */
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Prepared Statement Status
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^(Each prepared statement maintains various
|
||||
** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
|
||||
@ -5177,11 +5271,10 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur
|
||||
**
|
||||
** See also: [sqlite3_status()] and [sqlite3_db_status()].
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
||||
SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Parameters for prepared statements
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** These preprocessor macros define integer codes that name counter
|
||||
** values associated with the [sqlite3_stmt_status()] interface.
|
||||
@ -5199,14 +5292,21 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_status(sqlite3_stmt*, int op,int
|
||||
** A non-zero value in this counter may indicate an opportunity to
|
||||
** improvement performance through careful use of indices.</dd>
|
||||
**
|
||||
** <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
|
||||
** <dd>^This is the number of rows inserted into transient indices that
|
||||
** were created automatically in order to help joins run faster.
|
||||
** A non-zero value in this counter may indicate an opportunity to
|
||||
** improvement performance by adding permanent indices that do not
|
||||
** need to be reinitialized each time the statement is run.</dd>
|
||||
**
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
|
||||
#define SQLITE_STMTSTATUS_SORT 2
|
||||
#define SQLITE_STMTSTATUS_AUTOINDEX 3
|
||||
|
||||
/*
|
||||
** CAPI3REF: Custom Page Cache Object
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** The sqlite3_pcache type is opaque. It is implemented by
|
||||
** the pluggable module. The SQLite core has no knowledge of
|
||||
@ -5221,7 +5321,6 @@ typedef struct sqlite3_pcache sqlite3_pcache;
|
||||
/*
|
||||
** CAPI3REF: Application Defined Page Cache.
|
||||
** KEYWORDS: {page cache}
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can
|
||||
** register an alternative page cache implementation by passing in an
|
||||
@ -5363,7 +5462,6 @@ struct sqlite3_pcache_methods {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Online Backup Object
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** The sqlite3_backup object records state information about an ongoing
|
||||
** online backup operation. ^The sqlite3_backup object is created by
|
||||
@ -5376,7 +5474,6 @@ typedef struct sqlite3_backup sqlite3_backup;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Online Backup API.
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** The backup API copies the content of one database into another.
|
||||
** It is useful either for creating backups of databases or
|
||||
@ -5445,10 +5542,14 @@ typedef struct sqlite3_backup sqlite3_backup;
|
||||
** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an
|
||||
** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code.
|
||||
**
|
||||
** ^The sqlite3_backup_step() might return [SQLITE_READONLY] if the destination
|
||||
** database was opened read-only or if
|
||||
** the destination is an in-memory database with a different page size
|
||||
** from the source database.
|
||||
** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if
|
||||
** <ol>
|
||||
** <li> the destination database was opened read-only, or
|
||||
** <li> the destination database is using write-ahead-log journaling
|
||||
** and the destination and source page sizes differ, or
|
||||
** <li> The destination database is an in-memory database and the
|
||||
** destination and source page sizes differ.
|
||||
** </ol>)^
|
||||
**
|
||||
** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then
|
||||
** the [sqlite3_busy_handler | busy-handler function]
|
||||
@ -5564,7 +5665,6 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Unlock Notification
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^When running in shared-cache mode, a database operation may fail with
|
||||
** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
|
||||
@ -5686,7 +5786,6 @@ SQLITE_API int sqlite3_unlock_notify(
|
||||
|
||||
/*
|
||||
** CAPI3REF: String Comparison
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [sqlite3_strnicmp()] API allows applications and extensions to
|
||||
** compare the contents of two buffers containing UTF-8 strings in a
|
||||
@ -5697,12 +5796,11 @@ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Error Logging Interface
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [sqlite3_log()] interface writes a message into the error log
|
||||
** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
|
||||
** ^If logging is enabled, the zFormat string and subsequent arguments are
|
||||
** passed through to [sqlite3_vmprintf()] to generate the final output string.
|
||||
** used with [sqlite3_snprintf()] to generate the final output string.
|
||||
**
|
||||
** The sqlite3_log() interface is intended for use by extensions such as
|
||||
** virtual tables, collating functions, and SQL functions. While there is
|
||||
@ -5719,6 +5817,89 @@ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
|
||||
*/
|
||||
SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Write-Ahead Log Commit Hook
|
||||
**
|
||||
** ^The [sqlite3_wal_hook()] function is used to register a callback that
|
||||
** will be invoked each time a database connection commits data to a
|
||||
** [write-ahead log] (i.e. whenever a transaction is committed in
|
||||
** [journal_mode | journal_mode=WAL mode]).
|
||||
**
|
||||
** ^The callback is invoked by SQLite after the commit has taken place and
|
||||
** the associated write-lock on the database released, so the implementation
|
||||
** may read, write or [checkpoint] the database as required.
|
||||
**
|
||||
** ^The first parameter passed to the callback function when it is invoked
|
||||
** is a copy of the third parameter passed to sqlite3_wal_hook() when
|
||||
** registering the callback. ^The second is a copy of the database handle.
|
||||
** ^The third parameter is the name of the database that was written to -
|
||||
** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter
|
||||
** is the number of pages currently in the write-ahead log file,
|
||||
** including those that were just committed.
|
||||
**
|
||||
** The callback function should normally return [SQLITE_OK]. ^If an error
|
||||
** code is returned, that error will propagate back up through the
|
||||
** SQLite code base to cause the statement that provoked the callback
|
||||
** to report an error, though the commit will have still occurred. If the
|
||||
** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value
|
||||
** that does not correspond to any valid SQLite error code, the results
|
||||
** are undefined.
|
||||
**
|
||||
** A single database handle may have at most a single write-ahead log callback
|
||||
** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
|
||||
** previously registered write-ahead log callback. ^Note that the
|
||||
** [sqlite3_wal_autocheckpoint()] interface and the
|
||||
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
|
||||
** those overwrite any prior [sqlite3_wal_hook()] settings.
|
||||
*/
|
||||
SQLITE_API void *sqlite3_wal_hook(
|
||||
sqlite3*,
|
||||
int(*)(void *,sqlite3*,const char*,int),
|
||||
void*
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configure an auto-checkpoint
|
||||
**
|
||||
** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
|
||||
** [sqlite3_wal_hook()] that causes any database on [database connection] D
|
||||
** to automatically [checkpoint]
|
||||
** after committing a transaction if there are N or
|
||||
** more frames in the [write-ahead log] file. ^Passing zero or
|
||||
** a negative value as the nFrame parameter disables automatic
|
||||
** checkpoints entirely.
|
||||
**
|
||||
** ^The callback registered by this function replaces any existing callback
|
||||
** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback
|
||||
** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
|
||||
** configured by this function.
|
||||
**
|
||||
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
|
||||
** from SQL.
|
||||
**
|
||||
** ^Every new [database connection] defaults to having the auto-checkpoint
|
||||
** enabled with a threshold of 1000 pages. The use of this interface
|
||||
** is only necessary if the default setting is found to be suboptimal
|
||||
** for a particular application.
|
||||
*/
|
||||
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Checkpoint a database
|
||||
**
|
||||
** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
|
||||
** on [database connection] D to be [checkpointed]. ^If X is NULL or an
|
||||
** empty string, then a checkpoint is run on all databases of
|
||||
** connection D. ^If the database connection D is not in
|
||||
** [WAL | write-ahead log mode] then this interface is a harmless no-op.
|
||||
**
|
||||
** ^The [wal_checkpoint pragma] can be used to invoke this interface
|
||||
** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
|
||||
** [wal_autocheckpoint pragma] can be used to cause this interface to be
|
||||
** run whenever the WAL reaches a certain size threshold.
|
||||
*/
|
||||
SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
|
||||
|
||||
/*
|
||||
** Undo the hack that converts floating point types to integer for
|
||||
** builds on processors without floating point support.
|
||||
|
@ -68,5 +68,22 @@ _TEST_FILES = \
|
||||
blank.html \
|
||||
$(NULL)
|
||||
|
||||
ifneq (mobile,$(MOZ_BUILD_APP))
|
||||
_BROWSER_TEST_FILES = \
|
||||
browser_bug343515.js \
|
||||
bug343515_pg1.html \
|
||||
bug343515_pg2.html \
|
||||
bug343515_pg3.html \
|
||||
bug343515_pg3_1.html \
|
||||
bug343515_pg3_2.html \
|
||||
bug343515_pg3_1_1.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
||||
ifneq (mobile,$(MOZ_BUILD_APP))
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
endif
|
||||
|
248
docshell/test/navigation/browser_bug343515.js
Normal file
248
docshell/test/navigation/browser_bug343515.js
Normal file
@ -0,0 +1,248 @@
|
||||
// Test for bug 343515 - Need API for tabbrowsers to tell docshells they're visible/hidden
|
||||
|
||||
// Globals
|
||||
var testPath = "http://mochi.test:8888/browser/docshell/test/navigation/";
|
||||
var Ci = Components.interfaces;
|
||||
var Cc = Components.classes;
|
||||
var ctx = {};
|
||||
|
||||
// Helper function to check if a window is active
|
||||
function isActive(aWindow) {
|
||||
var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
return docshell.isActive;
|
||||
}
|
||||
|
||||
// Returns a closure that will remove itself as a listener from
|
||||
// aElem and then call aCallback. aCallback is executed asynchronously,
|
||||
// which is handy because load events fire before mIsDocumentLoaded is actually
|
||||
// set to true. :(
|
||||
function autoRemovedListener(aElem, aType, aCallback) {
|
||||
|
||||
var elem = aElem;
|
||||
var type = aType;
|
||||
var callback = aCallback;
|
||||
|
||||
function remover() {
|
||||
elem.removeEventListener(type, remover, true);
|
||||
executeSoon(callback);
|
||||
}
|
||||
|
||||
return remover;
|
||||
}
|
||||
|
||||
// Returns a closure that iteratively (BFS) waits for all
|
||||
// of the descendant frames of aInitialWindow to finish loading,
|
||||
// then calls aFinalCallback.
|
||||
function frameLoadWaiter(aInitialWindow, aFinalCallback) {
|
||||
|
||||
// The window we're currently waiting on
|
||||
var curr = aInitialWindow;
|
||||
|
||||
// The windows we need to wait for
|
||||
var waitQueue = [];
|
||||
|
||||
// The callback to call when we're all done
|
||||
var finalCallback = aFinalCallback;
|
||||
|
||||
function frameLoadCallback() {
|
||||
|
||||
// Push any subframes of what we just got
|
||||
for (var i = 0; i < curr.frames.length; ++i)
|
||||
waitQueue.push(curr.frames[i]);
|
||||
|
||||
// Handle the next window in the queue
|
||||
if (waitQueue.length >= 1) {
|
||||
curr = waitQueue.shift();
|
||||
if (curr.document.readyState == "complete")
|
||||
frameLoadCallback();
|
||||
else
|
||||
curr.addEventListener("load", autoRemovedListener(curr, "load", frameLoadCallback), true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we're all done. Call the final callback
|
||||
finalCallback();
|
||||
}
|
||||
|
||||
return frameLoadCallback;
|
||||
}
|
||||
|
||||
// Entry point from Mochikit
|
||||
function test() {
|
||||
|
||||
// Lots of callbacks going on here
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Begin the test
|
||||
step1();
|
||||
}
|
||||
|
||||
function step1() {
|
||||
|
||||
// Get a handle on the initial tab
|
||||
ctx.tab0 = gBrowser.selectedTab;
|
||||
ctx.tab0Browser = gBrowser.getBrowserForTab(ctx.tab0);
|
||||
ctx.tab0Window = ctx.tab0Browser.contentWindow;
|
||||
|
||||
// Our current tab should be active
|
||||
ok(isActive(ctx.tab0Window), "Tab 0 should be active at test start");
|
||||
|
||||
// Open a New Tab
|
||||
ctx.tab1 = gBrowser.addTab(testPath + "bug343515_pg1.html");
|
||||
ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1);
|
||||
ctx.tab1Window = ctx.tab1Browser.contentWindow;
|
||||
ctx.tab1Browser.addEventListener("load",
|
||||
autoRemovedListener(ctx.tab1Browser, "load", step2),
|
||||
true);
|
||||
}
|
||||
|
||||
function step2() {
|
||||
|
||||
// Our current tab should still be active
|
||||
ok(isActive(ctx.tab0Window), "Tab 0 should still be active");
|
||||
ok(!isActive(ctx.tab1Window), "Tab 1 should not be active");
|
||||
|
||||
// Switch to tab 1
|
||||
gBrowser.selectedTab = ctx.tab1;
|
||||
|
||||
// Tab 1 should now be active
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
||||
|
||||
// Open another tab
|
||||
ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html");
|
||||
ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2);
|
||||
ctx.tab2Window = ctx.tab2Browser.contentWindow;
|
||||
ctx.tab2Browser.addEventListener("load",
|
||||
autoRemovedListener(ctx.tab2Browser, "load",
|
||||
frameLoadWaiter(ctx.tab2Window, step3)),
|
||||
true);
|
||||
}
|
||||
|
||||
function step3() {
|
||||
|
||||
// Tab 0 should be inactive, Tab 1 should be active
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
||||
|
||||
// Tab 2's window _and_ its iframes should be inactive
|
||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
||||
is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes");
|
||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
||||
|
||||
// Navigate tab 2 to a different page
|
||||
ctx.tab2Window.location = testPath + "bug343515_pg3.html";
|
||||
ctx.tab2Browser.addEventListener("load",
|
||||
autoRemovedListener(ctx.tab2Browser, "load",
|
||||
frameLoadWaiter(ctx.tab2Window, step4)),
|
||||
true);
|
||||
}
|
||||
|
||||
function step4() {
|
||||
|
||||
// Tab 0 should be inactive, Tab 1 should be active
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
||||
|
||||
// Tab2 and all descendants should be inactive
|
||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
||||
is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes");
|
||||
is(ctx.tab2Window.frames[0].frames.length, 1, "Tab 2 iframe 0 should have 1 iframes");
|
||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
||||
|
||||
// Switch to Tab 2
|
||||
gBrowser.selectedTab = ctx.tab2;
|
||||
|
||||
// Check everything
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
|
||||
ok(isActive(ctx.tab2Window), "Tab 2 should be active");
|
||||
ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
|
||||
ok(isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be active");
|
||||
ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
|
||||
|
||||
// Go back
|
||||
ctx.tab2Browser.addEventListener("pageshow",
|
||||
autoRemovedListener(ctx.tab2Browser, "pageshow",
|
||||
frameLoadWaiter(ctx.tab2Window, step5)),
|
||||
true);
|
||||
ctx.tab2Browser.goBack();
|
||||
|
||||
}
|
||||
|
||||
function step5() {
|
||||
|
||||
// Check everything
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
|
||||
ok(isActive(ctx.tab2Window), "Tab 2 should be active");
|
||||
ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
|
||||
ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
|
||||
|
||||
// Switch to tab 1
|
||||
gBrowser.selectedTab = ctx.tab1;
|
||||
|
||||
// Navigate to page 3
|
||||
ctx.tab1Window.location = testPath + "bug343515_pg3.html";
|
||||
ctx.tab1Browser.addEventListener("load",
|
||||
autoRemovedListener(ctx.tab1Browser, "load",
|
||||
frameLoadWaiter(ctx.tab1Window, step6)),
|
||||
true);
|
||||
}
|
||||
|
||||
function step6() {
|
||||
|
||||
// Check everything
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active");
|
||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
||||
|
||||
// Go forward on tab 2
|
||||
ctx.tab2Browser.addEventListener("pageshow",
|
||||
autoRemovedListener(ctx.tab2Browser, "pageshow",
|
||||
frameLoadWaiter(ctx.tab2Window, step7)),
|
||||
true);
|
||||
var tab2docshell = ctx.tab2Window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation);
|
||||
tab2docshell.goForward();
|
||||
}
|
||||
|
||||
function step7() {
|
||||
|
||||
ctx.tab2Window = ctx.tab2Browser.contentWindow;
|
||||
|
||||
// Check everything
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active");
|
||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
||||
|
||||
// That's probably enough
|
||||
allDone();
|
||||
}
|
||||
|
||||
function allDone() {
|
||||
|
||||
// Close the tabs we made
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.tabContainer.advanceSelectedTab(1, true);
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
// Tell the framework we're done
|
||||
finish();
|
||||
}
|
5
docshell/test/navigation/bug343515_pg1.html
Normal file
5
docshell/test/navigation/bug343515_pg1.html
Normal file
@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>Page 1
|
||||
</body>
|
||||
</html>
|
7
docshell/test/navigation/bug343515_pg2.html
Normal file
7
docshell/test/navigation/bug343515_pg2.html
Normal file
@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>Page 2
|
||||
<iframe src="data:text/html,<html><head></head><body>pg2 iframe 0</body></html>"></iframe>
|
||||
<iframe src="data:text/html,<html><head></head><body>pg2 iframe 1</body></html>"></iframe>
|
||||
</body>
|
||||
</html>
|
7
docshell/test/navigation/bug343515_pg3.html
Normal file
7
docshell/test/navigation/bug343515_pg3.html
Normal file
@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>Page 3
|
||||
<iframe src="bug343515_pg3_1.html"></iframe>
|
||||
<iframe src="bug343515_pg3_2.html"></iframe>
|
||||
</body>
|
||||
</html>
|
6
docshell/test/navigation/bug343515_pg3_1.html
Normal file
6
docshell/test/navigation/bug343515_pg3_1.html
Normal file
@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>pg3 - iframe 0
|
||||
<iframe src="bug343515_pg3_1_1.html"></iframe>
|
||||
</body>
|
||||
</html>
|
1
docshell/test/navigation/bug343515_pg3_1_1.html
Normal file
1
docshell/test/navigation/bug343515_pg3_1_1.html
Normal file
@ -0,0 +1 @@
|
||||
<html><head></head><body>How far does the rabbit hole go?</body></html>
|
1
docshell/test/navigation/bug343515_pg3_2.html
Normal file
1
docshell/test/navigation/bug343515_pg3_2.html
Normal file
@ -0,0 +1 @@
|
||||
<html><head></head><body>pg3 iframe 1</body></html>
|
@ -53,6 +53,8 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsChromeRegistryChrome.h"
|
||||
#include "nsExternalHelperAppService.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "AndroidBridge.h"
|
||||
@ -470,6 +472,17 @@ ContentParent::RecvSetURITitle(const IPC::URI& uri,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvLoadURIExternal(const IPC::URI& uri)
|
||||
{
|
||||
nsCOMPtr<nsIExternalProtocolService> extProtService(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
|
||||
if (!extProtService)
|
||||
return true;
|
||||
nsCOMPtr<nsIURI> ourURI(uri);
|
||||
extProtService->LoadURI(ourURI, nsnull);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* void onDispatchedEvent (in nsIThreadInternal thread); */
|
||||
NS_IMETHODIMP
|
||||
ContentParent::OnDispatchedEvent(nsIThreadInternal *thread)
|
||||
|
@ -162,6 +162,8 @@ private:
|
||||
;
|
||||
|
||||
|
||||
virtual bool RecvLoadURIExternal(const IPC::URI& uri);
|
||||
|
||||
mozilla::Monitor mMonitor;
|
||||
|
||||
GeckoChildProcessHost* mSubprocess;
|
||||
|
@ -82,6 +82,7 @@ LOCAL_INCLUDES += \
|
||||
-I$(srcdir)/../../toolkit/components/places/src \
|
||||
-I$(srcdir)/../src/geolocation \
|
||||
-I$(topsrcdir)/chrome/src \
|
||||
-I$(topsrcdir)/uriloader/exthandler \
|
||||
$(NULL)
|
||||
|
||||
CXXFLAGS += $(TK_CFLAGS)
|
||||
|
@ -81,6 +81,8 @@ parent:
|
||||
async VisitURI(URI uri, URI referrer, PRUint32 flags);
|
||||
async SetURITitle(URI uri, nsString title);
|
||||
|
||||
async LoadURIExternal(URI uri);
|
||||
|
||||
// PrefService messages
|
||||
sync GetPrefType(nsCString prefName) returns (PRInt32 retValue, nsresult rv);
|
||||
sync GetBoolPref(nsCString prefName) returns (PRBool retValue, nsresult rv);
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "mozilla/plugins/BrowserStreamParent.h"
|
||||
#include "PluginIdentifierParent.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
@ -69,6 +70,7 @@ using mozilla::ipc::SyncChannel;
|
||||
using namespace mozilla::plugins;
|
||||
|
||||
static const char kTimeoutPref[] = "dom.ipc.plugins.timeoutSecs";
|
||||
static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs";
|
||||
|
||||
template<>
|
||||
struct RunnableMethodTraits<mozilla::plugins::PluginModuleParent>
|
||||
@ -84,15 +86,21 @@ PluginModuleParent::LoadModule(const char* aFilePath)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
|
||||
PRInt32 prefSecs = nsContentUtils::GetIntPref(kLaunchTimeoutPref, 0);
|
||||
|
||||
// Block on the child process being launched and initialized.
|
||||
PluginModuleParent* parent = new PluginModuleParent(aFilePath);
|
||||
parent->mSubprocess->Launch();
|
||||
nsAutoPtr<PluginModuleParent> parent(new PluginModuleParent(aFilePath));
|
||||
bool launched = parent->mSubprocess->Launch(prefSecs * 1000);
|
||||
if (!launched) {
|
||||
// Need to set this so the destructor doesn't complain.
|
||||
parent->mShutdown = true;
|
||||
return nsnull;
|
||||
}
|
||||
parent->Open(parent->mSubprocess->GetChannel(),
|
||||
parent->mSubprocess->GetChildProcessHandle());
|
||||
|
||||
TimeoutChanged(kTimeoutPref, parent);
|
||||
|
||||
return parent;
|
||||
return parent.forget();
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,11 +68,11 @@ PluginProcessParent::~PluginProcessParent()
|
||||
}
|
||||
|
||||
bool
|
||||
PluginProcessParent::Launch()
|
||||
PluginProcessParent::Launch(PRInt32 timeoutMs)
|
||||
{
|
||||
vector<string> args;
|
||||
args.push_back(MungePluginDsoPath(mPluginFilePath));
|
||||
return SyncLaunch(args);
|
||||
return SyncLaunch(args, timeoutMs);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -61,9 +61,10 @@ public:
|
||||
~PluginProcessParent();
|
||||
|
||||
/**
|
||||
* Synchronously launch the plugin process.
|
||||
* Synchronously launch the plugin process. If the process fails to launch
|
||||
* after timeoutMs, this method will return false.
|
||||
*/
|
||||
bool Launch();
|
||||
bool Launch(PRInt32 timeoutMs);
|
||||
|
||||
void Delete();
|
||||
|
||||
|
@ -14,7 +14,8 @@
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<application android:label="@MOZ_APP_DISPLAYNAME@"
|
||||
android:icon="@drawable/icon">
|
||||
android:icon="@drawable/icon"
|
||||
android:debuggable="true">
|
||||
<activity android:name="App"
|
||||
android:label="@MOZ_APP_DISPLAYNAME@"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|mcc|mnc"
|
||||
|
@ -157,7 +157,7 @@ class GeckoAppShell
|
||||
sGeckoRunning = true;
|
||||
|
||||
// First argument is the .apk path
|
||||
String combinedArgs = apkPath;
|
||||
String combinedArgs = apkPath + " -omnijar " + apkPath;
|
||||
if (args != null)
|
||||
combinedArgs += " " + args;
|
||||
if (url != null)
|
||||
|
@ -91,6 +91,7 @@
|
||||
|
||||
// PSM2 includes
|
||||
#include "nsISecureBrowserUI.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
using namespace mozilla::layers;
|
||||
|
||||
@ -790,6 +791,7 @@ NS_IMETHODIMP nsWebBrowser::SetProperty(PRUint32 aId, PRUint32 aValue)
|
||||
NS_ENSURE_TRUE((aValue == PR_TRUE || aValue == PR_FALSE), NS_ERROR_INVALID_ARG);
|
||||
mDocShell->SetAllowDNSPrefetch(!!aValue);
|
||||
}
|
||||
break;
|
||||
case nsIWebBrowserSetup::SETUP_USE_GLOBAL_HISTORY:
|
||||
{
|
||||
NS_ENSURE_STATE(mDocShell);
|
||||
@ -1230,10 +1232,15 @@ NS_IMETHODIMP nsWebBrowser::Create()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mDocShellAsNav->SetSessionHistory(mInitInfo->sessionHistory);
|
||||
|
||||
// Hook up global history. Do not fail if we can't - just warn.
|
||||
rv = EnableGlobalHistory(mShouldEnableHistory);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "EnableGlobalHistory() failed");
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default)
|
||||
#endif
|
||||
{
|
||||
// Hook up global history. Do not fail if we can't - just warn.
|
||||
rv = EnableGlobalHistory(mShouldEnableHistory);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "EnableGlobalHistory() failed");
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(mDocShellAsWin->Create(), NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -107,7 +107,7 @@ static JSContext *autoconfig_cx = nsnull;
|
||||
static JSObject *autoconfig_glob;
|
||||
|
||||
static JSClass global_class = {
|
||||
"autoconfig_global", 0,
|
||||
"autoconfig_global", JSCLASS_GLOBAL_FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nsnull
|
||||
};
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsUnicharUtilCIID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsTextFragment.h"
|
||||
|
||||
// IsIgnorableCharacter
|
||||
//
|
||||
@ -429,13 +430,6 @@ IsBRElement(nsIDOMNode* aNode)
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
static void
|
||||
GetNodeText(nsIDOMNode* aNode, nsAutoString& aText)
|
||||
{
|
||||
nsresult rv = aNode->GetNodeValue(aText);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to get node text");
|
||||
}
|
||||
|
||||
// Find the previous node in the DOM tree in preorder. This isn't fast because
|
||||
// one call to GetPrevSibling can be O(N) in the number of siblings...
|
||||
static nsIDOMNode*
|
||||
@ -480,10 +474,12 @@ ContainsDOMWordSeparator(nsIDOMNode* aNode, PRInt32 aBeforeOffset,
|
||||
if (!IsTextNode(aNode))
|
||||
return PR_FALSE;
|
||||
|
||||
nsAutoString str;
|
||||
GetNodeText(aNode, str);
|
||||
for (PRInt32 i = NS_MIN(aBeforeOffset, PRInt32(str.Length())) - 1; i >= 0; --i) {
|
||||
if (IsDOMWordSeparator(str.CharAt(i))) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
|
||||
NS_ASSERTION(content, "Where is our content?");
|
||||
const nsTextFragment* textFragment = content->GetText();
|
||||
NS_ASSERTION(textFragment, "Where is our text?");
|
||||
for (PRInt32 i = NS_MIN(aBeforeOffset, PRInt32(textFragment->GetLength())) - 1; i >= 0; --i) {
|
||||
if (IsDOMWordSeparator(textFragment->CharAt(i))) {
|
||||
*aSeparatorOffset = i;
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -584,7 +580,6 @@ mozInlineSpellWordUtil::BuildSoftText()
|
||||
PRBool seenSoftEnd = PR_FALSE;
|
||||
// Leave this outside the loop so large heap string allocations can be reused
|
||||
// across iterations
|
||||
nsAutoString str;
|
||||
while (node) {
|
||||
if (node == mSoftEnd.mNode) {
|
||||
seenSoftEnd = PR_TRUE;
|
||||
@ -592,14 +587,17 @@ mozInlineSpellWordUtil::BuildSoftText()
|
||||
|
||||
PRBool exit = PR_FALSE;
|
||||
if (IsTextNode(node)) {
|
||||
GetNodeText(node, str);
|
||||
PRInt32 lastOffsetInNode = str.Length();
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
|
||||
NS_ASSERTION(content, "Where is our content?");
|
||||
const nsTextFragment* textFragment = content->GetText();
|
||||
NS_ASSERTION(textFragment, "Where is our text?");
|
||||
PRInt32 lastOffsetInNode = textFragment->GetLength();
|
||||
|
||||
if (seenSoftEnd) {
|
||||
// check whether we can stop after this
|
||||
for (PRInt32 i = node == mSoftEnd.mNode ? mSoftEnd.mOffset : 0;
|
||||
i < PRInt32(str.Length()); ++i) {
|
||||
if (IsDOMWordSeparator(str.CharAt(i))) {
|
||||
i < PRInt32(textFragment->GetLength()); ++i) {
|
||||
if (IsDOMWordSeparator(textFragment->CharAt(i))) {
|
||||
exit = PR_TRUE;
|
||||
// stop at the first separator after the soft end point
|
||||
lastOffsetInNode = i;
|
||||
@ -612,7 +610,7 @@ mozInlineSpellWordUtil::BuildSoftText()
|
||||
PRInt32 len = lastOffsetInNode - firstOffsetInNode;
|
||||
mSoftTextDOMMapping.AppendElement(
|
||||
DOMTextMapping(NodeOffset(node, firstOffsetInNode), mSoftText.Length(), len));
|
||||
mSoftText.Append(Substring(str, firstOffsetInNode, len));
|
||||
textFragment->AppendTo(mSoftText, firstOffsetInNode, len);
|
||||
}
|
||||
|
||||
firstOffsetInNode = 0;
|
||||
|
546
gfx/cairo/cairo/src/cairo-d2d-private-fx.h
Normal file
546
gfx/cairo/cairo/src/cairo-d2d-private-fx.h
Normal file
@ -0,0 +1,546 @@
|
||||
#if 0
|
||||
//
|
||||
// FX Version: fx_4_0
|
||||
// Child effect (requires effect pool): false
|
||||
//
|
||||
// 1 local buffer(s)
|
||||
//
|
||||
cbuffer cb0
|
||||
{
|
||||
float4 QuadDesc; // Offset: 0, size: 16
|
||||
float4 TexCoords; // Offset: 16, size: 16
|
||||
}
|
||||
|
||||
//
|
||||
// 2 local object(s)
|
||||
//
|
||||
Texture2D tex;
|
||||
SamplerState sSampler
|
||||
{
|
||||
Texture = tex;
|
||||
AddressU = uint(CLAMP /* 3 */);
|
||||
AddressV = uint(CLAMP /* 3 */);
|
||||
};
|
||||
|
||||
//
|
||||
// 1 technique(s)
|
||||
//
|
||||
technique10 SampleTexture
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
VertexShader = asm {
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
|
||||
//
|
||||
//
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer cb0
|
||||
// {
|
||||
//
|
||||
// float4 QuadDesc; // Offset: 0 Size: 16
|
||||
// float4 TexCoords; // Offset: 16 Size: 16
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Resource Bindings:
|
||||
//
|
||||
// Name Type Format Dim Slot Elements
|
||||
// ------------------------------ ---------- ------- ----------- ---- --------
|
||||
// cb0 cbuffer NA NA 0 1
|
||||
//
|
||||
//
|
||||
//
|
||||
// Input signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------ ------
|
||||
// POSITION 0 xyz 0 NONE float xy
|
||||
//
|
||||
//
|
||||
// Output signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------ ------
|
||||
// SV_Position 0 xyzw 0 POS float xyzw
|
||||
// TEXCOORD 0 xy 1 NONE float xy
|
||||
//
|
||||
//
|
||||
// Constant buffer to DX9 shader constant mappings:
|
||||
//
|
||||
// Target Reg Buffer Start Reg # of Regs Data Conversion
|
||||
// ---------- ------- --------- --------- ----------------------
|
||||
// c1 cb0 0 2 ( FLT, FLT, FLT, FLT)
|
||||
//
|
||||
//
|
||||
// Runtime generated constant mappings:
|
||||
//
|
||||
// Target Reg Constant Description
|
||||
// ---------- --------------------------------------------------
|
||||
// c0 Vertex Shader position offset
|
||||
//
|
||||
//
|
||||
// Level9 shader bytecode:
|
||||
//
|
||||
vs_2_x
|
||||
def c3, 0, 1, 0, 0
|
||||
dcl_texcoord v0
|
||||
mad oT0.xy, v0, c2.zwzw, c2
|
||||
mad r0.x, v0.x, c1.z, c1.x
|
||||
mad r0.y, v0.y, c1.w, c1.y
|
||||
add oPos.xy, r0, c0
|
||||
mov oPos.zw, c3.xyxy
|
||||
|
||||
// approximately 5 instruction slots used
|
||||
vs_4_0
|
||||
dcl_constantbuffer cb0[2], immediateIndexed
|
||||
dcl_input v0.xy
|
||||
dcl_output_siv o0.xyzw, position
|
||||
dcl_output o1.xy
|
||||
mad o0.xy, v0.xyxx, cb0[0].zwzz, cb0[0].xyxx
|
||||
mov o0.zw, l(0,0,0,1.000000)
|
||||
mad o1.xy, v0.xyxx, cb0[1].zwzz, cb0[1].xyxx
|
||||
ret
|
||||
// Approximately 4 instruction slots used
|
||||
|
||||
};
|
||||
GeometryShader = NULL;
|
||||
PixelShader = asm {
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
|
||||
//
|
||||
//
|
||||
// Resource Bindings:
|
||||
//
|
||||
// Name Type Format Dim Slot Elements
|
||||
// ------------------------------ ---------- ------- ----------- ---- --------
|
||||
// sSampler sampler NA NA 0 1
|
||||
// tex texture float4 2d 0 1
|
||||
//
|
||||
//
|
||||
//
|
||||
// Input signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------ ------
|
||||
// SV_Position 0 xyzw 0 POS float
|
||||
// TEXCOORD 0 xy 1 NONE float xy
|
||||
//
|
||||
//
|
||||
// Output signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------ ------
|
||||
// SV_Target 0 xyzw 0 TARGET float xyzw
|
||||
//
|
||||
//
|
||||
// Sampler/Resource to DX9 shader sampler mappings:
|
||||
//
|
||||
// Target Sampler Source Sampler Source Resource
|
||||
// -------------- --------------- ----------------
|
||||
// s0 s0 t0
|
||||
//
|
||||
//
|
||||
// Level9 shader bytecode:
|
||||
//
|
||||
ps_2_x
|
||||
dcl t0.xy
|
||||
dcl_2d s0
|
||||
texld r0, t0, s0
|
||||
mov oC0, r0
|
||||
|
||||
// approximately 2 instruction slots used (1 texture, 1 arithmetic)
|
||||
ps_4_0
|
||||
dcl_sampler s0, mode_default
|
||||
dcl_resource_texture2d (float,float,float,float) t0
|
||||
dcl_input_ps linear v1.xy
|
||||
dcl_output o0.xyzw
|
||||
sample o0.xyzw, v1.xyxx, t0.xyzw, s0
|
||||
ret
|
||||
// Approximately 2 instruction slots used
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const BYTE g_main[] =
|
||||
{
|
||||
68, 88, 66, 67, 235, 24,
|
||||
238, 6, 37, 230, 191, 228,
|
||||
58, 61, 41, 219, 70, 130,
|
||||
61, 51, 1, 0, 0, 0,
|
||||
187, 8, 0, 0, 1, 0,
|
||||
0, 0, 36, 0, 0, 0,
|
||||
70, 88, 49, 48, 143, 8,
|
||||
0, 0, 1, 16, 255, 254,
|
||||
1, 0, 0, 0, 2, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 79, 7,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 2, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 99, 98,
|
||||
48, 0, 102, 108, 111, 97,
|
||||
116, 52, 0, 8, 0, 0,
|
||||
0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 0, 16,
|
||||
0, 0, 0, 10, 33, 0,
|
||||
0, 81, 117, 97, 100, 68,
|
||||
101, 115, 99, 0, 84, 101,
|
||||
120, 67, 111, 111, 114, 100,
|
||||
115, 0, 84, 101, 120, 116,
|
||||
117, 114, 101, 50, 68, 0,
|
||||
62, 0, 0, 0, 2, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
12, 0, 0, 0, 116, 101,
|
||||
120, 0, 83, 97, 109, 112,
|
||||
108, 101, 114, 83, 116, 97,
|
||||
116, 101, 0, 104, 0, 0,
|
||||
0, 2, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 21, 0, 0,
|
||||
0, 115, 83, 97, 109, 112,
|
||||
108, 101, 114, 0, 1, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
3, 0, 0, 0, 1, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
3, 0, 0, 0, 83, 97,
|
||||
109, 112, 108, 101, 84, 101,
|
||||
120, 116, 117, 114, 101, 0,
|
||||
80, 48, 0, 172, 3, 0,
|
||||
0, 68, 88, 66, 67, 247,
|
||||
105, 31, 113, 120, 95, 58,
|
||||
12, 207, 141, 45, 76, 175,
|
||||
59, 223, 25, 1, 0, 0,
|
||||
0, 172, 3, 0, 0, 6,
|
||||
0, 0, 0, 56, 0, 0,
|
||||
0, 248, 0, 0, 0, 188,
|
||||
1, 0, 0, 56, 2, 0,
|
||||
0, 32, 3, 0, 0, 84,
|
||||
3, 0, 0, 65, 111, 110,
|
||||
57, 184, 0, 0, 0, 184,
|
||||
0, 0, 0, 0, 2, 254,
|
||||
255, 132, 0, 0, 0, 52,
|
||||
0, 0, 0, 1, 0, 36,
|
||||
0, 0, 0, 48, 0, 0,
|
||||
0, 48, 0, 0, 0, 36,
|
||||
0, 1, 0, 48, 0, 0,
|
||||
0, 0, 0, 2, 0, 1,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 2, 254,
|
||||
255, 81, 0, 0, 5, 3,
|
||||
0, 15, 160, 0, 0, 0,
|
||||
0, 0, 0, 128, 63, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 31, 0, 0, 2, 5,
|
||||
0, 0, 128, 0, 0, 15,
|
||||
144, 4, 0, 0, 4, 0,
|
||||
0, 3, 224, 0, 0, 228,
|
||||
144, 2, 0, 238, 160, 2,
|
||||
0, 228, 160, 4, 0, 0,
|
||||
4, 0, 0, 1, 128, 0,
|
||||
0, 0, 144, 1, 0, 170,
|
||||
160, 1, 0, 0, 160, 4,
|
||||
0, 0, 4, 0, 0, 2,
|
||||
128, 0, 0, 85, 144, 1,
|
||||
0, 255, 160, 1, 0, 85,
|
||||
160, 2, 0, 0, 3, 0,
|
||||
0, 3, 192, 0, 0, 228,
|
||||
128, 0, 0, 228, 160, 1,
|
||||
0, 0, 2, 0, 0, 12,
|
||||
192, 3, 0, 68, 160, 255,
|
||||
255, 0, 0, 83, 72, 68,
|
||||
82, 188, 0, 0, 0, 64,
|
||||
0, 1, 0, 47, 0, 0,
|
||||
0, 89, 0, 0, 4, 70,
|
||||
142, 32, 0, 0, 0, 0,
|
||||
0, 2, 0, 0, 0, 95,
|
||||
0, 0, 3, 50, 16, 16,
|
||||
0, 0, 0, 0, 0, 103,
|
||||
0, 0, 4, 242, 32, 16,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 101, 0, 0,
|
||||
3, 50, 32, 16, 0, 1,
|
||||
0, 0, 0, 50, 0, 0,
|
||||
11, 50, 32, 16, 0, 0,
|
||||
0, 0, 0, 70, 16, 16,
|
||||
0, 0, 0, 0, 0, 230,
|
||||
138, 32, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 70,
|
||||
128, 32, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 54,
|
||||
0, 0, 8, 194, 32, 16,
|
||||
0, 0, 0, 0, 0, 2,
|
||||
64, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 128,
|
||||
63, 50, 0, 0, 11, 50,
|
||||
32, 16, 0, 1, 0, 0,
|
||||
0, 70, 16, 16, 0, 0,
|
||||
0, 0, 0, 230, 138, 32,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 70, 128, 32,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 62, 0, 0,
|
||||
1, 83, 84, 65, 84, 116,
|
||||
0, 0, 0, 4, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 3, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 82,
|
||||
68, 69, 70, 224, 0, 0,
|
||||
0, 1, 0, 0, 0, 64,
|
||||
0, 0, 0, 1, 0, 0,
|
||||
0, 28, 0, 0, 0, 0,
|
||||
4, 254, 255, 0, 129, 0,
|
||||
0, 174, 0, 0, 0, 60,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 99, 98, 48, 0, 60,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 88, 0, 0, 0, 32,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 136,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 16, 0, 0, 0, 2,
|
||||
0, 0, 0, 148, 0, 0,
|
||||
0, 0, 0, 0, 0, 164,
|
||||
0, 0, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 0, 2,
|
||||
0, 0, 0, 148, 0, 0,
|
||||
0, 0, 0, 0, 0, 81,
|
||||
117, 97, 100, 68, 101, 115,
|
||||
99, 0, 171, 171, 171, 1,
|
||||
0, 3, 0, 1, 0, 4,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 84, 101, 120,
|
||||
67, 111, 111, 114, 100, 115,
|
||||
0, 77, 105, 99, 114, 111,
|
||||
115, 111, 102, 116, 32, 40,
|
||||
82, 41, 32, 72, 76, 83,
|
||||
76, 32, 83, 104, 97, 100,
|
||||
101, 114, 32, 67, 111, 109,
|
||||
112, 105, 108, 101, 114, 32,
|
||||
57, 46, 50, 55, 46, 57,
|
||||
53, 50, 46, 51, 48, 50,
|
||||
50, 0, 171, 73, 83, 71,
|
||||
78, 44, 0, 0, 0, 1,
|
||||
0, 0, 0, 8, 0, 0,
|
||||
0, 32, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 7, 3, 0,
|
||||
0, 80, 79, 83, 73, 84,
|
||||
73, 79, 78, 0, 171, 171,
|
||||
171, 79, 83, 71, 78, 80,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 8, 0, 0, 0, 56,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 3,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 15, 0, 0, 0, 68,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 3,
|
||||
0, 0, 0, 1, 0, 0,
|
||||
0, 3, 12, 0, 0, 83,
|
||||
86, 95, 80, 111, 115, 105,
|
||||
116, 105, 111, 110, 0, 84,
|
||||
69, 88, 67, 79, 79, 82,
|
||||
68, 0, 171, 171, 171, 195,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 2,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 188, 2, 0, 0, 68,
|
||||
88, 66, 67, 90, 17, 243,
|
||||
62, 104, 14, 0, 40, 49,
|
||||
70, 150, 92, 77, 1, 115,
|
||||
141, 1, 0, 0, 0, 188,
|
||||
2, 0, 0, 6, 0, 0,
|
||||
0, 56, 0, 0, 0, 164,
|
||||
0, 0, 0, 16, 1, 0,
|
||||
0, 140, 1, 0, 0, 48,
|
||||
2, 0, 0, 136, 2, 0,
|
||||
0, 65, 111, 110, 57, 100,
|
||||
0, 0, 0, 100, 0, 0,
|
||||
0, 0, 2, 255, 255, 60,
|
||||
0, 0, 0, 40, 0, 0,
|
||||
0, 0, 0, 40, 0, 0,
|
||||
0, 40, 0, 0, 0, 40,
|
||||
0, 1, 0, 36, 0, 0,
|
||||
0, 40, 0, 0, 0, 0,
|
||||
0, 1, 2, 255, 255, 31,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
128, 0, 0, 3, 176, 31,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
144, 0, 8, 15, 160, 66,
|
||||
0, 0, 3, 0, 0, 15,
|
||||
128, 0, 0, 228, 176, 0,
|
||||
8, 228, 160, 1, 0, 0,
|
||||
2, 0, 8, 15, 128, 0,
|
||||
0, 228, 128, 255, 255, 0,
|
||||
0, 83, 72, 68, 82, 100,
|
||||
0, 0, 0, 64, 0, 0,
|
||||
0, 25, 0, 0, 0, 90,
|
||||
0, 0, 3, 0, 96, 16,
|
||||
0, 0, 0, 0, 0, 88,
|
||||
24, 0, 4, 0, 112, 16,
|
||||
0, 0, 0, 0, 0, 85,
|
||||
85, 0, 0, 98, 16, 0,
|
||||
3, 50, 16, 16, 0, 1,
|
||||
0, 0, 0, 101, 0, 0,
|
||||
3, 242, 32, 16, 0, 0,
|
||||
0, 0, 0, 69, 0, 0,
|
||||
9, 242, 32, 16, 0, 0,
|
||||
0, 0, 0, 70, 16, 16,
|
||||
0, 1, 0, 0, 0, 70,
|
||||
126, 16, 0, 0, 0, 0,
|
||||
0, 0, 96, 16, 0, 0,
|
||||
0, 0, 0, 62, 0, 0,
|
||||
1, 83, 84, 65, 84, 116,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 82,
|
||||
68, 69, 70, 156, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 28, 0, 0, 0, 0,
|
||||
4, 255, 255, 0, 129, 0,
|
||||
0, 105, 0, 0, 0, 92,
|
||||
0, 0, 0, 3, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 101, 0, 0, 0, 2,
|
||||
0, 0, 0, 5, 0, 0,
|
||||
0, 4, 0, 0, 0, 255,
|
||||
255, 255, 255, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 12,
|
||||
0, 0, 0, 115, 83, 97,
|
||||
109, 112, 108, 101, 114, 0,
|
||||
116, 101, 120, 0, 77, 105,
|
||||
99, 114, 111, 115, 111, 102,
|
||||
116, 32, 40, 82, 41, 32,
|
||||
72, 76, 83, 76, 32, 83,
|
||||
104, 97, 100, 101, 114, 32,
|
||||
67, 111, 109, 112, 105, 108,
|
||||
101, 114, 32, 57, 46, 50,
|
||||
55, 46, 57, 53, 50, 46,
|
||||
51, 48, 50, 50, 0, 171,
|
||||
171, 73, 83, 71, 78, 80,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 8, 0, 0, 0, 56,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 3,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 15, 0, 0, 0, 68,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 3,
|
||||
0, 0, 0, 1, 0, 0,
|
||||
0, 3, 3, 0, 0, 83,
|
||||
86, 95, 80, 111, 115, 105,
|
||||
116, 105, 111, 110, 0, 84,
|
||||
69, 88, 67, 79, 79, 82,
|
||||
68, 0, 171, 171, 171, 79,
|
||||
83, 71, 78, 44, 0, 0,
|
||||
0, 1, 0, 0, 0, 8,
|
||||
0, 0, 0, 32, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 3, 0, 0,
|
||||
0, 0, 0, 0, 0, 15,
|
||||
0, 0, 0, 83, 86, 95,
|
||||
84, 97, 114, 103, 101, 116,
|
||||
0, 171, 171, 135, 4, 0,
|
||||
0, 0, 0, 0, 0, 4,
|
||||
0, 0, 0, 32, 0, 0,
|
||||
0, 0, 0, 0, 0, 2,
|
||||
0, 0, 0, 255, 255, 255,
|
||||
255, 0, 0, 0, 0, 43,
|
||||
0, 0, 0, 15, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 52, 0, 0,
|
||||
0, 15, 0, 0, 0, 0,
|
||||
0, 0, 0, 16, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 100, 0, 0, 0, 72,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 255, 255, 255, 255, 0,
|
||||
0, 0, 0, 145, 0, 0,
|
||||
0, 117, 0, 0, 0, 0,
|
||||
0, 0, 0, 255, 255, 255,
|
||||
255, 3, 0, 0, 0, 55,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 2, 0, 0, 0, 100,
|
||||
0, 0, 0, 46, 0, 0,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 154, 0, 0,
|
||||
0, 47, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 0, 0,
|
||||
0, 166, 0, 0, 0, 0,
|
||||
0, 0, 0, 178, 0, 0,
|
||||
0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 192, 0, 0,
|
||||
0, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 6, 0, 0,
|
||||
0, 0, 0, 0, 0, 7,
|
||||
0, 0, 0, 115, 4, 0,
|
||||
0, 8, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 0, 0,
|
||||
0, 123, 4, 0, 0, 7,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 7, 0, 0, 0, 71,
|
||||
7, 0, 0
|
||||
};
|
57
gfx/cairo/cairo/src/cairo-d2d-private.fx
Normal file
57
gfx/cairo/cairo/src/cairo-d2d-private.fx
Normal file
@ -0,0 +1,57 @@
|
||||
// We store vertex coordinates and the quad shape in a constant buffer, this is
|
||||
// easy to update and allows us to use a single call to set the x, y, w, h of
|
||||
// the quad.
|
||||
// The QuadDesc and TexCoords both work as follows:
|
||||
// The x component is the quad left point, the y component is the top point
|
||||
// the z component is the width, and the w component is the height. The quad
|
||||
// are specified in viewport coordinates, i.e. { -1.0f, 1.0f, 2.0f, -2.0f }
|
||||
// would cover the entire viewport (which runs from <-1.0f, 1.0f> left to right
|
||||
// and <-1.0f, 1.0f> -bottom- to top. The TexCoords desc is specified in texture
|
||||
// space <0, 1.0f> left to right and top to bottom. The input vertices of the
|
||||
// shader stage always form a rectangle from {0, 0} - {1, 1}
|
||||
cbuffer cb0
|
||||
{
|
||||
float4 QuadDesc;
|
||||
float4 TexCoords;
|
||||
}
|
||||
|
||||
struct VS_OUTPUT
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float2 TexCoord : TEXCOORD0;
|
||||
};
|
||||
|
||||
Texture2D tex;
|
||||
|
||||
sampler sSampler = sampler_state {
|
||||
Texture = tex;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
};
|
||||
|
||||
VS_OUTPUT SampleTextureVS(float3 pos : POSITION)
|
||||
{
|
||||
VS_OUTPUT Output;
|
||||
Output.Position.w = 1.0f;
|
||||
Output.Position.x = pos.x * QuadDesc.z + QuadDesc.x;
|
||||
Output.Position.y = pos.y * QuadDesc.w + QuadDesc.y;
|
||||
Output.Position.z = 0;
|
||||
Output.TexCoord.x = pos.x * TexCoords.z + TexCoords.x;
|
||||
Output.TexCoord.y = pos.y * TexCoords.w + TexCoords.y;
|
||||
return Output;
|
||||
}
|
||||
|
||||
float4 SampleTexturePS( VS_OUTPUT In) : SV_Target
|
||||
{
|
||||
return tex.Sample(sSampler, In.TexCoord);
|
||||
};
|
||||
|
||||
technique10 SampleTexture
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleTextureVS()));
|
||||
SetGeometryShader(NULL);
|
||||
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleTexturePS()));
|
||||
}
|
||||
}
|
@ -49,10 +49,28 @@ extern "C" {
|
||||
}
|
||||
|
||||
#include "cairo-win32-refptr.h"
|
||||
#include "cairo-d2d-private-fx.h"
|
||||
#include "cairo-win32.h"
|
||||
|
||||
/* describes the type of the currently applied clip so that we can pop it */
|
||||
struct d2d_clip;
|
||||
|
||||
#define MAX_OPERATORS CAIRO_OPERATOR_HSL_LUMINOSITY + 1
|
||||
|
||||
struct _cairo_d2d_device
|
||||
{
|
||||
cairo_device_t base;
|
||||
|
||||
HMODULE mD3D10_1;
|
||||
RefPtr<ID3D10Device1> mD3D10Device;
|
||||
RefPtr<ID3D10Effect> mSampleEffect;
|
||||
RefPtr<ID3D10InputLayout> mInputLayout;
|
||||
RefPtr<ID3D10Buffer> mQuadBuffer;
|
||||
RefPtr<ID3D10RasterizerState> mRasterizerState;
|
||||
RefPtr<ID3D10BlendState> mBlendStates[MAX_OPERATORS];
|
||||
};
|
||||
typedef struct _cairo_d2d_device cairo_d2d_device_t;
|
||||
|
||||
struct _cairo_d2d_surface {
|
||||
_cairo_d2d_surface() : d2d_clip(NULL), clipping(false), isDrawing(false),
|
||||
textRenderingInit(true)
|
||||
@ -61,6 +79,10 @@ struct _cairo_d2d_surface {
|
||||
}
|
||||
|
||||
cairo_surface_t base;
|
||||
/* Device used by this surface
|
||||
* NOTE: In upstream cairo this is in the surface base class */
|
||||
cairo_d2d_device_t *device;
|
||||
|
||||
/** Render target of the texture we render to */
|
||||
RefPtr<ID2D1RenderTarget> rt;
|
||||
/** Surface containing our backstore */
|
||||
@ -103,6 +125,10 @@ struct _cairo_d2d_surface {
|
||||
/** Indicates if text rendering is initialized */
|
||||
bool textRenderingInit;
|
||||
|
||||
RefPtr<ID3D10RenderTargetView> buffer_rt_view;
|
||||
RefPtr<ID3D10ShaderResourceView> buffer_sr_view;
|
||||
|
||||
|
||||
//cairo_surface_clipper_t clipper;
|
||||
};
|
||||
typedef struct _cairo_d2d_surface cairo_d2d_surface_t;
|
||||
@ -124,104 +150,14 @@ typedef HRESULT (WINAPI*D3D10CreateDevice1Func)(
|
||||
ID3D10Device1 **ppDevice
|
||||
);
|
||||
|
||||
class D2DSurfFactory
|
||||
{
|
||||
public:
|
||||
static ID2D1Factory *Instance()
|
||||
{
|
||||
if (!mFactoryInstance) {
|
||||
D2D1CreateFactoryFunc createD2DFactory = (D2D1CreateFactoryFunc)
|
||||
GetProcAddress(LoadLibraryW(L"d2d1.dll"), "D2D1CreateFactory");
|
||||
if (createD2DFactory) {
|
||||
D2D1_FACTORY_OPTIONS options;
|
||||
#ifdef DEBUG
|
||||
options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
|
||||
#else
|
||||
options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
|
||||
#endif
|
||||
createD2DFactory(
|
||||
D2D1_FACTORY_TYPE_SINGLE_THREADED,
|
||||
__uuidof(ID2D1Factory),
|
||||
&options,
|
||||
(void**)&mFactoryInstance);
|
||||
}
|
||||
}
|
||||
return mFactoryInstance;
|
||||
}
|
||||
private:
|
||||
static ID2D1Factory *mFactoryInstance;
|
||||
};
|
||||
|
||||
/**
|
||||
* On usage of D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS:
|
||||
* documentation on D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
|
||||
* can be misleading. In fact, that flag gives no such indication. I pointed this
|
||||
* out to Bas in my email. However, Microsoft is in fact using this flag to
|
||||
* indicate "light weight" DX applications. By light weight they are essentially
|
||||
* referring to applications that are not games. The idea is that when you create
|
||||
* a DX game, the driver assumes that you will pretty much have a single instance
|
||||
* and therefore it doesn't try to hold back when it comes to GPU resource
|
||||
* allocation as long as it can crank out performance. In other words, the
|
||||
* priority in regular DX applications is to make that one application run as fast
|
||||
* as you can. For "light weight" applications, including D2D applications, the
|
||||
* priorities are a bit different. Now you are no longer going to have a single
|
||||
* (or very few) instances. You can have a lot of them (say, for example, a
|
||||
* separate DX context/device per browser tab). In such cases, the GPU resource
|
||||
* allocation scheme changes.
|
||||
*/
|
||||
class D3D10Factory
|
||||
{
|
||||
public:
|
||||
static ID3D10Device1 *Device()
|
||||
{
|
||||
if (!mDeviceInstance) {
|
||||
D3D10CreateDevice1Func createD3DDevice = (D3D10CreateDevice1Func)
|
||||
GetProcAddress(LoadLibraryA("d3d10_1.dll"), "D3D10CreateDevice1");
|
||||
if (createD3DDevice) {
|
||||
HRESULT hr = createD3DDevice(
|
||||
NULL,
|
||||
D3D10_DRIVER_TYPE_HARDWARE,
|
||||
NULL,
|
||||
D3D10_CREATE_DEVICE_BGRA_SUPPORT |
|
||||
D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
|
||||
D3D10_FEATURE_LEVEL_10_1,
|
||||
D3D10_1_SDK_VERSION,
|
||||
&mDeviceInstance);
|
||||
if (FAILED(hr)) {
|
||||
HRESULT hr = createD3DDevice(
|
||||
NULL,
|
||||
D3D10_DRIVER_TYPE_HARDWARE,
|
||||
NULL,
|
||||
D3D10_CREATE_DEVICE_BGRA_SUPPORT |
|
||||
D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
|
||||
D3D10_FEATURE_LEVEL_10_0,
|
||||
D3D10_1_SDK_VERSION,
|
||||
&mDeviceInstance);
|
||||
if (FAILED(hr)) {
|
||||
/* TODO: D3D10Level9 might be slower than GDI */
|
||||
HRESULT hr = createD3DDevice(
|
||||
NULL,
|
||||
D3D10_DRIVER_TYPE_HARDWARE,
|
||||
NULL,
|
||||
D3D10_CREATE_DEVICE_BGRA_SUPPORT |
|
||||
D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
|
||||
D3D10_FEATURE_LEVEL_9_3,
|
||||
D3D10_1_SDK_VERSION,
|
||||
&mDeviceInstance);
|
||||
|
||||
}
|
||||
}
|
||||
if (SUCCEEDED(hr)) {
|
||||
mDeviceInstance->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mDeviceInstance;
|
||||
}
|
||||
private:
|
||||
static ID3D10Device1 *mDeviceInstance;
|
||||
};
|
||||
|
||||
typedef HRESULT (WINAPI*D3D10CreateEffectFromMemoryFunc)(
|
||||
void *pData,
|
||||
SIZE_T DataLength,
|
||||
UINT FXFlags,
|
||||
ID3D10Device *pDevice,
|
||||
ID3D10EffectPool *pEffectPool,
|
||||
ID3D10Effect **ppEffect
|
||||
);
|
||||
|
||||
RefPtr<ID2D1Brush>
|
||||
_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||
@ -229,8 +165,15 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||
bool unique = false);
|
||||
void
|
||||
_cairo_d2d_begin_draw_state(cairo_d2d_surface_t *d2dsurf);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_d2d_set_clip(cairo_d2d_surface_t *d2dsurf, cairo_clip_t *clip);
|
||||
|
||||
cairo_int_status_t _cairo_d2d_blend_temp_surface(cairo_d2d_surface_t *surf, cairo_operator_t op, ID2D1RenderTarget *rt, cairo_clip_t *clip, const cairo_rectangle_int_t *bounds = NULL);
|
||||
|
||||
RefPtr<ID2D1RenderTarget> _cairo_d2d_get_temp_rt(cairo_d2d_surface_t *surf, cairo_clip_t *clip);
|
||||
|
||||
cairo_operator_t _cairo_d2d_simplify_operator(cairo_operator_t op, const cairo_pattern_t *source);
|
||||
|
||||
#endif /* CAIRO_HAS_D2D_SURFACE */
|
||||
#endif /* CAIRO_D2D_PRIVATE_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1262,32 +1262,52 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
|
||||
if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_DWRITE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
op = _cairo_d2d_simplify_operator(op, source);
|
||||
|
||||
/* We can only handle operator SOURCE or OVER with the destination
|
||||
* having no alpha */
|
||||
if (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
/* We cannot handle operator SOURCE or CLEAR */
|
||||
if (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
_cairo_d2d_begin_draw_state (dst);
|
||||
_cairo_d2d_set_clip (dst, clip);
|
||||
RefPtr<ID2D1RenderTarget> target_rt = dst->rt;
|
||||
cairo_rectangle_int_t fontArea;
|
||||
#ifndef ALWAYS_MANUAL_COMPOSITE
|
||||
if (op != CAIRO_OPERATOR_OVER) {
|
||||
#endif
|
||||
target_rt = _cairo_d2d_get_temp_rt(dst, clip);
|
||||
|
||||
if (!target_rt) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
#ifndef ALWAYS_MANUAL_COMPOSITE
|
||||
} else {
|
||||
_cairo_d2d_begin_draw_state(dst);
|
||||
status = (cairo_int_status_t)_cairo_d2d_set_clip (dst, clip);
|
||||
|
||||
if (unlikely(status))
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
D2D1_TEXT_ANTIALIAS_MODE cleartype = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
D2D1_TEXT_ANTIALIAS_MODE highest_quality = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
|
||||
if (dst->base.content != CAIRO_CONTENT_COLOR) {
|
||||
cleartype = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||
// If we're rendering to a temporary surface we cannot do sub-pixel AA.
|
||||
if (dst->base.content != CAIRO_CONTENT_COLOR || dst->rt.get() != target_rt.get()) {
|
||||
highest_quality = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||
}
|
||||
|
||||
switch (scaled_font->options.antialias) {
|
||||
case CAIRO_ANTIALIAS_DEFAULT:
|
||||
dst->rt->SetTextAntialiasMode(cleartype);
|
||||
target_rt->SetTextAntialiasMode(highest_quality);
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_NONE:
|
||||
dst->rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
||||
target_rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_GRAY:
|
||||
dst->rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
target_rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||
dst->rt->SetTextAntialiasMode(cleartype);
|
||||
target_rt->SetTextAntialiasMode(highest_quality);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1349,7 +1369,29 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
|
||||
D2D1::Matrix3x2F mat = _cairo_d2d_matrix_from_matrix(&dwritesf->mat);
|
||||
|
||||
if (transform) {
|
||||
dst->rt->SetTransform(mat);
|
||||
target_rt->SetTransform(mat);
|
||||
}
|
||||
|
||||
if (dst->rt.get() != target_rt.get()) {
|
||||
RefPtr<IDWriteGlyphRunAnalysis> analysis;
|
||||
DWRITE_MATRIX dwmat = _cairo_dwrite_matrix_from_matrix(&dwritesf->mat);
|
||||
DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
|
||||
1.0f,
|
||||
transform ? &dwmat : 0,
|
||||
DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
|
||||
DWRITE_MEASURING_MODE_NATURAL,
|
||||
0,
|
||||
0,
|
||||
&analysis);
|
||||
|
||||
RECT bounds;
|
||||
analysis->GetAlphaTextureBounds(scaled_font->options.antialias == CAIRO_ANTIALIAS_NONE ?
|
||||
DWRITE_TEXTURE_ALIASED_1x1 : DWRITE_TEXTURE_CLEARTYPE_3x1,
|
||||
&bounds);
|
||||
fontArea.x = bounds.left;
|
||||
fontArea.y = bounds.top;
|
||||
fontArea.width = bounds.right - bounds.left;
|
||||
fontArea.height = bounds.bottom - bounds.top;
|
||||
}
|
||||
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst,
|
||||
@ -1374,15 +1416,19 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
|
||||
brush->SetTransform(&mat_brush);
|
||||
}
|
||||
|
||||
dst->rt->DrawGlyphRun(D2D1::Point2F(0, 0), &run, brush);
|
||||
target_rt->DrawGlyphRun(D2D1::Point2F(0, 0), &run, brush);
|
||||
|
||||
if (transform) {
|
||||
dst->rt->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
target_rt->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
}
|
||||
|
||||
delete [] indices;
|
||||
delete [] offsets;
|
||||
delete [] advances;
|
||||
|
||||
if (target_rt.get() != dst->rt.get()) {
|
||||
return _cairo_d2d_blend_temp_surface(dst, op, target_rt, clip, &fontArea);
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -94,6 +94,26 @@ _cairo_boxes_get_extents (const cairo_box_t *boxes,
|
||||
}
|
||||
}
|
||||
|
||||
/* This function will return 'true' if the containing_rectangle contains the
|
||||
* contained_rectangle, and false otherwise.
|
||||
*/
|
||||
cairo_bool_t
|
||||
_cairo_rectangle_contains (const cairo_rectangle_int_t *containing_rectangle,
|
||||
const cairo_rectangle_int_t *contained_rectangle)
|
||||
{
|
||||
if (containing_rectangle->x > contained_rectangle->x ||
|
||||
containing_rectangle->y > contained_rectangle->y)
|
||||
return FALSE;
|
||||
|
||||
if (containing_rectangle->x + containing_rectangle->width <
|
||||
contained_rectangle->x + contained_rectangle->width ||
|
||||
containing_rectangle->y + containing_rectangle->height <
|
||||
contained_rectangle->y + contained_rectangle->height)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* XXX We currently have a confusing mix of boxes and rectangles as
|
||||
* exemplified by this function. A #cairo_box_t is a rectangular area
|
||||
* represented by the coordinates of the upper left and lower right
|
||||
|
@ -107,6 +107,11 @@ public:
|
||||
return mPtr;
|
||||
}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
return mPtr;
|
||||
}
|
||||
|
||||
operator bool()
|
||||
{
|
||||
return (mPtr ? true : false);
|
||||
|
@ -126,30 +126,88 @@ cairo_dwrite_font_face_create_for_dwrite_fontface(void *dwrite_font, void *dwrit
|
||||
#endif /* CAIRO_HAS_DWRITE_FONT */
|
||||
|
||||
#if CAIRO_HAS_D2D_SURFACE
|
||||
|
||||
struct _cairo_device
|
||||
{
|
||||
int type;
|
||||
int refcount;
|
||||
};
|
||||
typedef struct _cairo_device cairo_device_t;
|
||||
|
||||
/**
|
||||
* Create a D2D device
|
||||
*
|
||||
* \return New D2D device, NULL if creation failed.
|
||||
*/
|
||||
cairo_device_t *
|
||||
cairo_d2d_create_device();
|
||||
|
||||
/**
|
||||
* Releases a D2D device.
|
||||
*
|
||||
* \return References left to the device
|
||||
*/
|
||||
int
|
||||
cairo_release_device(cairo_device_t *device);
|
||||
|
||||
/**
|
||||
* Addrefs a D2D device.
|
||||
*
|
||||
* \return References to the device
|
||||
*/
|
||||
int
|
||||
cairo_addref_device(cairo_device_t *device);
|
||||
|
||||
/**
|
||||
* Flushes a D3D device. In most cases the surface backend will do this
|
||||
* internally, but when using a surfaces created from a shared handle this
|
||||
* should be executed manually when a different device is going to be accessing
|
||||
* the same surface data. This will also block until the device is finished
|
||||
* processing all work.
|
||||
*/
|
||||
void
|
||||
cairo_d2d_finish_device(cairo_device_t *device);
|
||||
|
||||
/**
|
||||
* Create a D2D surface for an HWND
|
||||
*
|
||||
* \param device Device used to create the surface
|
||||
* \param wnd Handle for the window
|
||||
* \param content Content of the window, should be COLOR_ALPHA for transparent windows
|
||||
* \return New cairo surface
|
||||
*/
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_d2d_surface_create_for_hwnd(HWND wnd, cairo_content_t content);
|
||||
cairo_d2d_surface_create_for_hwnd(cairo_device_t *device, HWND wnd, cairo_content_t content);
|
||||
|
||||
/**
|
||||
* Create a D2D surface of a certain size.
|
||||
*
|
||||
* \param device Device used to create the surface
|
||||
* \param format Cairo format of the surface
|
||||
* \param width Width of the surface
|
||||
* \param height Height of the surface
|
||||
* \return New cairo surface
|
||||
*/
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_d2d_surface_create(cairo_format_t format,
|
||||
cairo_d2d_surface_create(cairo_device_t *device,
|
||||
cairo_format_t format,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
/**
|
||||
* Create a D3D surface from a Texture SharedHandle, this is obtained from a
|
||||
* CreateTexture call on a D3D9 device. This has to be an A8R8G8B8 format
|
||||
* or an A8 format, the treatment of the alpha channel can be indicated using
|
||||
* the content parameter.
|
||||
*
|
||||
* \param device Device used to create the surface
|
||||
* \param handle Shared handle to the texture we want to wrap
|
||||
* \param content Content of the texture, COLOR_ALPHA for ARGB
|
||||
* \return New cairo surface
|
||||
*/
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_d2d_surface_create_for_handle(cairo_device_t *device, HANDLE handle, cairo_content_t content);
|
||||
|
||||
/**
|
||||
* Present the backbuffer for a surface create for an HWND. This needs
|
||||
* to be called when the owner of the original window surface wants to
|
||||
@ -172,15 +230,6 @@ void cairo_d2d_present_backbuffer(cairo_surface_t *surface);
|
||||
*/
|
||||
void cairo_d2d_scroll(cairo_surface_t *surface, int x, int y, cairo_rectangle_t *clip);
|
||||
|
||||
/**
|
||||
* Verify if D2D surfaces are actually supported. This will confirm the needed
|
||||
* hardware is available.
|
||||
*
|
||||
* \return True if the support is available. If false surface creation will
|
||||
* return error surfaces.
|
||||
*/
|
||||
cairo_bool_t cairo_d2d_has_support();
|
||||
|
||||
/**
|
||||
* Get a DC for the current render target. When selecting the retention option this
|
||||
* call can be relatively slow, since it may require reading back contents from the
|
||||
|
@ -271,6 +271,10 @@ cairo_private void
|
||||
_cairo_box_from_rectangle (cairo_box_t *box,
|
||||
const cairo_rectangle_int_t *rectangle);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_rectangle_contains (const cairo_rectangle_int_t *containing_rectangle,
|
||||
const cairo_rectangle_int_t *contained_rectangle);
|
||||
|
||||
cairo_private void
|
||||
_cairo_box_round_to_rectangle (const cairo_box_t *box,
|
||||
cairo_rectangle_int_t *rectangle);
|
||||
|
@ -84,7 +84,10 @@ CPPSRCS = \
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
ifdef MOZ_ENABLE_D3D9_LAYER
|
||||
EXPORTS += LayerManagerD3D9.h
|
||||
EXPORTS += \
|
||||
LayerManagerD3D9.h \
|
||||
DeviceManagerD3D9.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS += \
|
||||
LayerManagerD3D9.cpp \
|
||||
@ -93,6 +96,7 @@ CPPSRCS += \
|
||||
ImageLayerD3D9.cpp \
|
||||
ColorLayerD3D9.cpp \
|
||||
CanvasLayerD3D9.cpp \
|
||||
DeviceManagerD3D9.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
endif
|
||||
|
@ -70,9 +70,17 @@ CanvasLayerD3D9::Initialize(const Data& aData)
|
||||
|
||||
mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
|
||||
|
||||
device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
if (mD3DManager->deviceManager()->HasDynamicTextures()) {
|
||||
device()->CreateTexture(mBounds.width, mBounds.height, 1, D3DUSAGE_DYNAMIC,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
} else {
|
||||
// D3DPOOL_MANAGED is fine here since we require Dynamic Textures for D3D9Ex
|
||||
// devices.
|
||||
device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -230,7 +238,7 @@ CanvasLayerD3D9::RenderLayer()
|
||||
opacity[0] = GetOpacity();
|
||||
device()->SetPixelShaderConstantF(0, opacity, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
|
||||
|
||||
if (!mGLBufferIsPremultiplied) {
|
||||
device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
|
@ -76,7 +76,7 @@ ColorLayerD3D9::RenderLayer()
|
||||
|
||||
device()->SetPixelShaderConstantF(0, color, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::SOLIDCOLORLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER);
|
||||
|
||||
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ ContainerLayerD3D9::RenderLayer()
|
||||
opacityVector[0] = opacity;
|
||||
device()->SetPixelShaderConstantF(0, opacityVector, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
|
||||
|
||||
device()->SetTexture(0, renderTexture);
|
||||
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
|
562
gfx/layers/d3d9/DeviceManagerD3D9.cpp
Normal file
562
gfx/layers/d3d9/DeviceManagerD3D9.cpp
Normal file
@ -0,0 +1,562 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** 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) 2009
|
||||
* 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 "DeviceManagerD3D9.h"
|
||||
#include "LayerManagerD3D9Shaders.h"
|
||||
#include "ThebesLayerD3D9.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
const LPCWSTR kClassName = L"D3D9WindowClass";
|
||||
|
||||
#define USE_D3D9EX
|
||||
|
||||
typedef IDirect3D9* (WINAPI*Direct3DCreate9Func)(
|
||||
UINT SDKVersion
|
||||
);
|
||||
|
||||
typedef HRESULT (WINAPI*Direct3DCreate9ExFunc)(
|
||||
UINT SDKVersion,
|
||||
IDirect3D9Ex **ppD3D
|
||||
);
|
||||
|
||||
struct vertex {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
SwapChainD3D9::SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager)
|
||||
: mDeviceManager(aDeviceManager)
|
||||
, mWnd(0)
|
||||
{
|
||||
mDeviceManager->mSwapChains.AppendElement(this);
|
||||
}
|
||||
|
||||
SwapChainD3D9::~SwapChainD3D9()
|
||||
{
|
||||
mDeviceManager->mSwapChains.RemoveElement(this);
|
||||
}
|
||||
|
||||
bool
|
||||
SwapChainD3D9::Init(HWND hWnd)
|
||||
{
|
||||
RECT r;
|
||||
::GetClientRect(hWnd, &r);
|
||||
|
||||
mWnd = hWnd;
|
||||
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
|
||||
pp.BackBufferFormat = D3DFMT_UNKNOWN;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_COPY;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
pp.hDeviceWindow = mWnd;
|
||||
if (r.left == r.right || r.top == r.bottom) {
|
||||
pp.BackBufferHeight = 1;
|
||||
pp.BackBufferWidth = 1;
|
||||
}
|
||||
|
||||
HRESULT hr = mDeviceManager->device()->
|
||||
CreateAdditionalSwapChain(&pp,
|
||||
getter_AddRefs(mSwapChain));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create swap chain for window.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SwapChainD3D9::PrepareForRendering()
|
||||
{
|
||||
RECT r;
|
||||
if (!::GetClientRect(mWnd, &r)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mDeviceManager->VerifyReadyForRendering()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mSwapChain) {
|
||||
Init(mWnd);
|
||||
}
|
||||
|
||||
if (mSwapChain) {
|
||||
nsRefPtr<IDirect3DSurface9> backBuffer;
|
||||
mSwapChain->GetBackBuffer(0,
|
||||
D3DBACKBUFFER_TYPE_MONO,
|
||||
getter_AddRefs(backBuffer));
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
backBuffer->GetDesc(&desc);
|
||||
|
||||
if (desc.Width == r.right - r.left && desc.Height == r.bottom - r.top) {
|
||||
mDeviceManager->device()->SetRenderTarget(0, backBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
mSwapChain = nsnull;
|
||||
|
||||
Init(mWnd);
|
||||
|
||||
if (!mSwapChain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mSwapChain->GetBackBuffer(0,
|
||||
D3DBACKBUFFER_TYPE_MONO,
|
||||
getter_AddRefs(backBuffer));
|
||||
|
||||
mDeviceManager->device()->SetRenderTarget(0, backBuffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SwapChainD3D9::Present(const nsIntRect &aRect)
|
||||
{
|
||||
RECT r;
|
||||
r.left = aRect.x;
|
||||
r.top = aRect.y;
|
||||
r.right = aRect.XMost();
|
||||
r.bottom = aRect.YMost();
|
||||
|
||||
mSwapChain->Present(&r, &r, 0, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
SwapChainD3D9::Reset()
|
||||
{
|
||||
mSwapChain = nsnull;
|
||||
}
|
||||
|
||||
#define HAS_CAP(a, b) (((a) & (b)) == (b))
|
||||
#define LACKS_CAP(a, b) !(((a) & (b)) == (b))
|
||||
|
||||
DeviceManagerD3D9::DeviceManagerD3D9()
|
||||
: mHasDynamicTextures(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D9::Init()
|
||||
{
|
||||
WNDCLASSW wc;
|
||||
HRESULT hr;
|
||||
|
||||
if (!GetClassInfoW(GetModuleHandle(NULL), kClassName, &wc)) {
|
||||
ZeroMemory(&wc, sizeof(WNDCLASSW));
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.lpfnWndProc = ::DefWindowProc;
|
||||
wc.lpszClassName = kClassName;
|
||||
if (!RegisterClassW(&wc)) {
|
||||
NS_WARNING("Failed to register window class for DeviceManager.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mFocusWnd = ::CreateWindowW(kClassName, L"D3D9Window", WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL,
|
||||
NULL, GetModuleHandle(NULL), NULL);
|
||||
|
||||
if (!mFocusWnd) {
|
||||
NS_WARNING("Failed to create DeviceManagerD3D9 Window.");
|
||||
return false;
|
||||
}
|
||||
|
||||
HMODULE d3d9 = LoadLibraryW(L"d3d9.dll");
|
||||
Direct3DCreate9Func d3d9Create = (Direct3DCreate9Func)
|
||||
GetProcAddress(d3d9, "Direct3DCreate9");
|
||||
Direct3DCreate9ExFunc d3d9CreateEx = (Direct3DCreate9ExFunc)
|
||||
GetProcAddress(d3d9, "Direct3DCreate9Ex");
|
||||
|
||||
#ifdef USE_D3D9EX
|
||||
if (d3d9CreateEx) {
|
||||
hr = d3d9CreateEx(D3D_SDK_VERSION, getter_AddRefs(mD3D9Ex));
|
||||
if (SUCCEEDED(hr)) {
|
||||
mD3D9 = mD3D9Ex;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!mD3D9) {
|
||||
if (!d3d9Create) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mD3D9 = dont_AddRef(d3d9Create(D3D_SDK_VERSION));
|
||||
|
||||
if (!mD3D9) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
|
||||
pp.BackBufferWidth = 1;
|
||||
pp.BackBufferHeight = 1;
|
||||
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
||||
pp.hDeviceWindow = mFocusWnd;
|
||||
|
||||
if (mD3D9Ex) {
|
||||
hr = mD3D9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT,
|
||||
D3DDEVTYPE_HAL,
|
||||
mFocusWnd,
|
||||
D3DCREATE_FPU_PRESERVE |
|
||||
D3DCREATE_MULTITHREADED |
|
||||
D3DCREATE_MIXED_VERTEXPROCESSING,
|
||||
&pp,
|
||||
NULL,
|
||||
getter_AddRefs(mDeviceEx));
|
||||
if (SUCCEEDED(hr)) {
|
||||
mDevice = mDeviceEx;
|
||||
}
|
||||
|
||||
D3DCAPS9 caps;
|
||||
if (mDeviceEx->GetDeviceCaps(&caps)) {
|
||||
if (LACKS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) {
|
||||
// XXX - Should we actually hit this we'll need a CanvasLayer that
|
||||
// supports static D3DPOOL_DEFAULT textures.
|
||||
NS_WARNING("D3D9Ex device not used because of lack of support for \
|
||||
dynamic textures. This is unexpected.");
|
||||
mDevice = nsnull;
|
||||
mDeviceEx = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mDevice) {
|
||||
hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT,
|
||||
D3DDEVTYPE_HAL,
|
||||
mFocusWnd,
|
||||
D3DCREATE_FPU_PRESERVE |
|
||||
D3DCREATE_MULTITHREADED |
|
||||
D3DCREATE_MIXED_VERTEXPROCESSING,
|
||||
&pp,
|
||||
getter_AddRefs(mDevice));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create Device for DeviceManagerD3D9.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!VerifyCaps()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
|
||||
getter_AddRefs(mLayerVS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS,
|
||||
getter_AddRefs(mRGBPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS,
|
||||
getter_AddRefs(mYCbCrPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS,
|
||||
getter_AddRefs(mSolidColorPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4,
|
||||
D3DUSAGE_WRITEONLY,
|
||||
0,
|
||||
D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mVB),
|
||||
NULL);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vertex *vertices;
|
||||
hr = mVB->Lock(0, 0, (void**)&vertices, 0);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vertices[0].x = vertices[0].y = 0;
|
||||
vertices[1].x = 1; vertices[1].y = 0;
|
||||
vertices[2].x = 0; vertices[2].y = 1;
|
||||
vertices[3].x = 1; vertices[3].y = 1;
|
||||
|
||||
mVB->Unlock();
|
||||
|
||||
hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DVERTEXELEMENT9 elements[] = {
|
||||
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
|
||||
D3DDECLUSAGE_POSITION, 0 },
|
||||
D3DDECL_END()
|
||||
};
|
||||
|
||||
mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD));
|
||||
|
||||
nsCOMPtr<nsIConsoleService>
|
||||
console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
|
||||
D3DADAPTER_IDENTIFIER9 identifier;
|
||||
mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
|
||||
|
||||
if (console) {
|
||||
nsString msg;
|
||||
msg +=
|
||||
NS_LITERAL_STRING("Direct3D 9 DeviceManager Initialized Succesfully.\nDriver: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsDependentCString((const char*)identifier.Driver));
|
||||
msg += NS_LITERAL_STRING("\nDescription: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsDependentCString((const char*)identifier.Description));
|
||||
msg += NS_LITERAL_STRING("\nVersion: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsPrintfCString("%d.%d.%d.%d",
|
||||
HIWORD(identifier.DriverVersion.HighPart),
|
||||
LOWORD(identifier.DriverVersion.HighPart),
|
||||
HIWORD(identifier.DriverVersion.LowPart),
|
||||
LOWORD(identifier.DriverVersion.LowPart)));
|
||||
console->LogStringMessage(msg.get());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DeviceManagerD3D9::SetupRenderState()
|
||||
{
|
||||
mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
|
||||
mDevice->SetVertexDeclaration(mVD);
|
||||
mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||
mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
}
|
||||
|
||||
already_AddRefed<SwapChainD3D9>
|
||||
DeviceManagerD3D9::CreateSwapChain(HWND hWnd)
|
||||
{
|
||||
nsRefPtr<SwapChainD3D9> swapChain = new SwapChainD3D9(this);
|
||||
|
||||
if (!swapChain->Init(hWnd)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return swapChain.forget();
|
||||
}
|
||||
|
||||
void
|
||||
DeviceManagerD3D9::SetShaderMode(ShaderMode aMode)
|
||||
{
|
||||
switch (aMode) {
|
||||
case RGBLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mRGBPS);
|
||||
break;
|
||||
case YCBCRLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mYCbCrPS);
|
||||
break;
|
||||
case SOLIDCOLORLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mSolidColorPS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D9::VerifyReadyForRendering()
|
||||
{
|
||||
HRESULT hr = mDevice->TestCooperativeLevel();
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (IsD3D9Ex()) {
|
||||
hr = mDeviceEx->CheckDeviceState(mFocusWnd);
|
||||
if (FAILED(hr)) {
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
|
||||
pp.BackBufferWidth = 1;
|
||||
pp.BackBufferHeight = 1;
|
||||
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
||||
pp.hDeviceWindow = mFocusWnd;
|
||||
|
||||
hr = mDeviceEx->ResetEx(&pp, NULL);
|
||||
// Handle D3DERR_DEVICEREMOVED!
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hr != D3DERR_DEVICENOTRESET) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < mThebesLayers.Length(); i++) {
|
||||
mThebesLayers[i]->CleanResources();
|
||||
}
|
||||
for(unsigned int i = 0; i < mSwapChains.Length(); i++) {
|
||||
mSwapChains[i]->Reset();
|
||||
}
|
||||
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
|
||||
pp.BackBufferWidth = 1;
|
||||
pp.BackBufferHeight = 1;
|
||||
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
||||
pp.hDeviceWindow = mFocusWnd;
|
||||
|
||||
hr = mDevice->Reset(&pp);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D9::VerifyCaps()
|
||||
{
|
||||
D3DCAPS9 caps;
|
||||
HRESULT hr = mDevice->GetDeviceCaps(&caps);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) ||
|
||||
LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) ||
|
||||
LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) ||
|
||||
HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) ||
|
||||
(HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) &&
|
||||
LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) ||
|
||||
LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (caps.MaxTextureHeight < 4096 ||
|
||||
caps.MaxTextureWidth < 4096) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((caps.PixelShaderVersion & 0xffff) < 0x200 ||
|
||||
(caps.VertexShaderVersion & 0xffff) < 0x200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HAS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) {
|
||||
mHasDynamicTextures = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* namespace layers */
|
||||
} /* namespace mozilla */
|
207
gfx/layers/d3d9/DeviceManagerD3D9.h
Normal file
207
gfx/layers/d3d9/DeviceManagerD3D9.h
Normal file
@ -0,0 +1,207 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** 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) 2009
|
||||
* 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 GFX_DEVICEMANAGERD3D9_H
|
||||
#define GFX_DEVICEMANAGERD3D9_H
|
||||
|
||||
#include "gfxTypes.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "d3d9.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class DeviceManagerD3D9;
|
||||
class ThebesLayerD3D9;
|
||||
|
||||
/**
|
||||
* SwapChain class, this class manages the swap chain belonging to a
|
||||
* LayerManagerD3D9.
|
||||
*/
|
||||
class THEBES_API SwapChainD3D9
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(SwapChainD3D9)
|
||||
public:
|
||||
~SwapChainD3D9();
|
||||
|
||||
/**
|
||||
* This function will prepare the device this swap chain belongs to for
|
||||
* rendering to this swap chain. Only after calling this function can the
|
||||
* swap chain be drawn to, and only until this function is called on another
|
||||
* swap chain belonging to this device will the device draw to it. Passed in
|
||||
* is the size of the swap chain. If the window size differs from the size
|
||||
* during the last call to this function the swap chain will resize. Note that
|
||||
* in no case does this function guarantee the backbuffer to still have its
|
||||
* old content.
|
||||
*/
|
||||
bool PrepareForRendering();
|
||||
|
||||
/**
|
||||
* This function will present the selected rectangle of the swap chain to
|
||||
* its associated window.
|
||||
*/
|
||||
void Present(const nsIntRect &aRect);
|
||||
|
||||
private:
|
||||
friend class DeviceManagerD3D9;
|
||||
|
||||
SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager);
|
||||
|
||||
bool Init(HWND hWnd);
|
||||
|
||||
/**
|
||||
* This causes us to release our swap chain, clearing out our resource usage
|
||||
* so the master device may reset.
|
||||
*/
|
||||
void Reset();
|
||||
|
||||
nsRefPtr<IDirect3DSwapChain9> mSwapChain;
|
||||
nsRefPtr<DeviceManagerD3D9> mDeviceManager;
|
||||
HWND mWnd;
|
||||
};
|
||||
|
||||
/**
|
||||
* Device manager, this class is used by the layer managers to share the D3D9
|
||||
* device and create swap chains for the individual windows the layer managers
|
||||
* belong to.
|
||||
*/
|
||||
class THEBES_API DeviceManagerD3D9
|
||||
{
|
||||
public:
|
||||
DeviceManagerD3D9();
|
||||
|
||||
// We want the nsrefcnt return value. So we cannot use the inline refcnt macro
|
||||
NS_IMPL_ADDREF(DeviceManagerD3D9)
|
||||
NS_IMPL_RELEASE(DeviceManagerD3D9)
|
||||
|
||||
bool Init();
|
||||
|
||||
/**
|
||||
* Sets up the render state for the device for layer rendering.
|
||||
*/
|
||||
void SetupRenderState();
|
||||
|
||||
/**
|
||||
* Create a swap chain setup to work with the specified window.
|
||||
*/
|
||||
already_AddRefed<SwapChainD3D9> CreateSwapChain(HWND hWnd);
|
||||
|
||||
IDirect3DDevice9 *device() { return mDevice; }
|
||||
|
||||
bool IsD3D9Ex() { return mDeviceEx; }
|
||||
|
||||
bool HasDynamicTextures() { return mHasDynamicTextures; }
|
||||
|
||||
enum ShaderMode {
|
||||
RGBLAYER,
|
||||
YCBCRLAYER,
|
||||
SOLIDCOLORLAYER
|
||||
};
|
||||
|
||||
void SetShaderMode(ShaderMode aMode);
|
||||
|
||||
/**
|
||||
* We keep a list of all thebes layers since we need their D3DPOOL_DEFAULT
|
||||
* surfaces to be released when we want to reset the device.
|
||||
*/
|
||||
nsTArray<ThebesLayerD3D9*> mThebesLayers;
|
||||
private:
|
||||
friend class SwapChainD3D9;
|
||||
|
||||
/**
|
||||
* This function verifies the device is ready for rendering, internally this
|
||||
* will test the cooperative level of the device and reset the device if
|
||||
* needed. If this returns false subsequent rendering calls may return errors.
|
||||
*/
|
||||
bool VerifyReadyForRendering();
|
||||
|
||||
/* Array used to store all swap chains for device resets */
|
||||
nsTArray<SwapChainD3D9*> mSwapChains;
|
||||
|
||||
/* The D3D device we use */
|
||||
nsRefPtr<IDirect3DDevice9> mDevice;
|
||||
|
||||
/* The D3D9Ex device - only valid on Vista+ with WDDM */
|
||||
nsRefPtr<IDirect3DDevice9Ex> mDeviceEx;
|
||||
|
||||
/* An instance of the D3D9 object */
|
||||
nsRefPtr<IDirect3D9> mD3D9;
|
||||
|
||||
/* An instance of the D3D9Ex object - only valid on Vista+ with WDDM */
|
||||
nsRefPtr<IDirect3D9Ex> mD3D9Ex;
|
||||
|
||||
/* Vertex shader used for layer quads */
|
||||
nsRefPtr<IDirect3DVertexShader9> mLayerVS;
|
||||
|
||||
/* Pixel shader used for RGB textures */
|
||||
nsRefPtr<IDirect3DPixelShader9> mRGBPS;
|
||||
|
||||
/* Pixel shader used for RGB textures */
|
||||
nsRefPtr<IDirect3DPixelShader9> mYCbCrPS;
|
||||
|
||||
/* Pixel shader used for solid colors */
|
||||
nsRefPtr<IDirect3DPixelShader9> mSolidColorPS;
|
||||
|
||||
/* Vertex buffer containing our basic vertex structure */
|
||||
nsRefPtr<IDirect3DVertexBuffer9> mVB;
|
||||
|
||||
/* Our vertex declaration */
|
||||
nsRefPtr<IDirect3DVertexDeclaration9> mVD;
|
||||
|
||||
/* Our focus window - this is really a dummy window we can associate our
|
||||
* device with.
|
||||
*/
|
||||
HWND mFocusWnd;
|
||||
|
||||
/* If this device supports dynamic textures */
|
||||
bool mHasDynamicTextures;
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
/**
|
||||
* Verifies all required device capabilities are present.
|
||||
*/
|
||||
bool VerifyCaps();
|
||||
};
|
||||
|
||||
} /* namespace layers */
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* GFX_DEVICEMANAGERD3D9_H */
|
@ -185,7 +185,7 @@ ImageLayerD3D9::RenderLayer()
|
||||
opacity[0] = GetOpacity();
|
||||
device()->SetPixelShaderConstantF(0, opacity, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::YCBCRLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER);
|
||||
|
||||
device()->SetTexture(0, yuvImage->mYTexture);
|
||||
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
@ -227,7 +227,7 @@ ImageLayerD3D9::RenderLayer()
|
||||
opacity[0] = GetOpacity();
|
||||
device()->SetPixelShaderConstantF(0, opacity, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
|
||||
|
||||
device()->SetTexture(0, cairoImage->mTexture);
|
||||
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
@ -244,6 +244,7 @@ PlanarYCbCrImageD3D9::PlanarYCbCrImageD3D9(mozilla::layers::LayerManagerD3D9* aM
|
||||
void
|
||||
PlanarYCbCrImageD3D9::SetData(const PlanarYCbCrImage::Data &aData)
|
||||
{
|
||||
// XXX - For D3D9Ex we really should just copy to systemmem surfaces here.
|
||||
// For now, we copy the data
|
||||
int width_shift = 0;
|
||||
int height_shift = 0;
|
||||
@ -309,76 +310,116 @@ PlanarYCbCrImageD3D9::AllocateTextures()
|
||||
{
|
||||
|
||||
|
||||
D3DLOCKED_RECT lockrect;
|
||||
D3DLOCKED_RECT lockrectY;
|
||||
D3DLOCKED_RECT lockrectCb;
|
||||
D3DLOCKED_RECT lockrectCr;
|
||||
PRUint8* src;
|
||||
PRUint8* dest;
|
||||
//XXX: ensure correct usage flags
|
||||
mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mYTexture), NULL);
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> tmpSurfaceY;
|
||||
nsRefPtr<IDirect3DSurface9> tmpSurfaceCb;
|
||||
nsRefPtr<IDirect3DSurface9> tmpSurfaceCr;
|
||||
|
||||
/* lock the entire texture */
|
||||
mYTexture->LockRect(0, &lockrect, NULL, 0);
|
||||
if (mManager->deviceManager()->IsD3D9Ex()) {
|
||||
// D3D9Ex does not support the managed pool, could use dynamic textures
|
||||
// here. But since an Image is immutable static textures are probably a
|
||||
// better idea.
|
||||
mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mYTexture), NULL);
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mCbTexture), NULL);
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mCrTexture), NULL);
|
||||
mManager->device()->CreateOffscreenPlainSurface(mData.mYSize.width,
|
||||
mData.mYSize.height,
|
||||
D3DFMT_L8,
|
||||
D3DPOOL_SYSTEMMEM,
|
||||
getter_AddRefs(tmpSurfaceY),
|
||||
NULL);
|
||||
mManager->device()->CreateOffscreenPlainSurface(mData.mCbCrSize.width,
|
||||
mData.mCbCrSize.height,
|
||||
D3DFMT_L8,
|
||||
D3DPOOL_SYSTEMMEM,
|
||||
getter_AddRefs(tmpSurfaceCb),
|
||||
NULL);
|
||||
mManager->device()->CreateOffscreenPlainSurface(mData.mCbCrSize.width,
|
||||
mData.mCbCrSize.height,
|
||||
D3DFMT_L8,
|
||||
D3DPOOL_SYSTEMMEM,
|
||||
getter_AddRefs(tmpSurfaceCr),
|
||||
NULL);
|
||||
tmpSurfaceY->LockRect(&lockrectY, NULL, 0);
|
||||
tmpSurfaceCb->LockRect(&lockrectCb, NULL, 0);
|
||||
tmpSurfaceCr->LockRect(&lockrectCr, NULL, 0);
|
||||
} else {
|
||||
mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mYTexture), NULL);
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mCbTexture), NULL);
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mCrTexture), NULL);
|
||||
|
||||
/* lock the entire texture */
|
||||
mYTexture->LockRect(0, &lockrectY, NULL, 0);
|
||||
mCbTexture->LockRect(0, &lockrectCb, NULL, 0);
|
||||
mCrTexture->LockRect(0, &lockrectCr, NULL, 0);
|
||||
}
|
||||
|
||||
src = mData.mYChannel;
|
||||
//FIX cast
|
||||
dest = (PRUint8*)lockrect.pBits;
|
||||
dest = (PRUint8*)lockrectY.pBits;
|
||||
|
||||
// copy over data
|
||||
for (int h=0; h<mData.mYSize.height; h++) {
|
||||
memcpy(dest, src, mData.mYSize.width);
|
||||
dest += lockrect.Pitch;
|
||||
dest += lockrectY.Pitch;
|
||||
src += mData.mYStride;
|
||||
}
|
||||
|
||||
mYTexture->UnlockRect(0);
|
||||
|
||||
//XXX: ensure correct usage flags
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mCbTexture), NULL);
|
||||
|
||||
|
||||
/* lock the entire texture */
|
||||
mCbTexture->LockRect(0, &lockrect, NULL, 0);
|
||||
|
||||
src = mData.mCbChannel;
|
||||
//FIX cast
|
||||
dest = (PRUint8*)lockrect.pBits;
|
||||
dest = (PRUint8*)lockrectCb.pBits;
|
||||
|
||||
// copy over data
|
||||
for (int h=0; h<mData.mCbCrSize.height; h++) {
|
||||
memcpy(dest, src, mData.mCbCrSize.width);
|
||||
dest += lockrect.Pitch;
|
||||
dest += lockrectCb.Pitch;
|
||||
src += mData.mCbCrStride;
|
||||
}
|
||||
|
||||
mCbTexture->UnlockRect(0);
|
||||
|
||||
|
||||
//XXX: ensure correct usage flags
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mCrTexture), NULL);
|
||||
|
||||
|
||||
/* lock the entire texture */
|
||||
mCrTexture->LockRect(0, &lockrect, NULL, 0);
|
||||
|
||||
src = mData.mCrChannel;
|
||||
//FIX cast
|
||||
dest = (PRUint8*)lockrect.pBits;
|
||||
dest = (PRUint8*)lockrectCr.pBits;
|
||||
|
||||
// copy over data
|
||||
for (int h=0; h<mData.mCbCrSize.height; h++) {
|
||||
memcpy(dest, src, mData.mCbCrSize.width);
|
||||
dest += lockrect.Pitch;
|
||||
dest += lockrectCr.Pitch;
|
||||
src += mData.mCbCrStride;
|
||||
}
|
||||
|
||||
mCrTexture->UnlockRect(0);
|
||||
|
||||
if (mManager->deviceManager()->IsD3D9Ex()) {
|
||||
tmpSurfaceY->UnlockRect();
|
||||
tmpSurfaceCb->UnlockRect();
|
||||
tmpSurfaceCr->UnlockRect();
|
||||
nsRefPtr<IDirect3DSurface9> dstSurface;
|
||||
mYTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
mManager->device()->UpdateSurface(tmpSurfaceY, NULL, dstSurface, NULL);
|
||||
mCbTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
mManager->device()->UpdateSurface(tmpSurfaceCb, NULL, dstSurface, NULL);
|
||||
mCrTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
mManager->device()->UpdateSurface(tmpSurfaceCr, NULL, dstSurface, NULL);
|
||||
} else {
|
||||
mYTexture->UnlockRect(0);
|
||||
mCbTexture->UnlockRect(0);
|
||||
mCrTexture->UnlockRect(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -426,31 +467,49 @@ CairoImageD3D9::SetData(const CairoImage::Data &aData)
|
||||
context->SetSource(aData.mSurface);
|
||||
context->Paint();
|
||||
|
||||
//XXX: make sure we're using the correct usage flags
|
||||
mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
|
||||
1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
if (mManager->deviceManager()->IsD3D9Ex()) {
|
||||
// D3D9Ex doesn't support managed textures. We could use dynamic textures
|
||||
// here but since Images are immutable that probably isn't such a great
|
||||
// idea.
|
||||
mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
|
||||
1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
nsRefPtr<IDirect3DSurface9> surface;
|
||||
mManager->device()->CreateOffscreenPlainSurface(aData.mSize.width,
|
||||
aData.mSize.height,
|
||||
D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_SYSTEMMEM,
|
||||
getter_AddRefs(surface),
|
||||
NULL);
|
||||
D3DLOCKED_RECT lockedRect;
|
||||
surface->LockRect(&lockedRect, NULL, 0);
|
||||
for (int y = 0; y < aData.mSize.height; y++) {
|
||||
memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y,
|
||||
imageSurface->Data() + imageSurface->Stride() * y,
|
||||
aData.mSize.width * 4);
|
||||
}
|
||||
surface->UnlockRect();
|
||||
nsRefPtr<IDirect3DSurface9> dstSurface;
|
||||
mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
mManager->device()->UpdateSurface(surface, NULL, dstSurface, NULL);
|
||||
} else {
|
||||
mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
|
||||
1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
D3DLOCKED_RECT lockrect;
|
||||
/* lock the entire texture */
|
||||
mTexture->LockRect(0, &lockrect, NULL, 0);
|
||||
|
||||
D3DLOCKED_RECT lockrect;
|
||||
/* lock the entire texture */
|
||||
mTexture->LockRect(0, &lockrect, NULL, 0);
|
||||
// copy over data. If we don't need to do any swaping we can
|
||||
// use memcpy
|
||||
for (int y = 0; y < aData.mSize.height; y++) {
|
||||
memcpy((char*)lockrect.pBits + lockrect.Pitch * y,
|
||||
imageSurface->Data() + imageSurface->Stride() * y,
|
||||
aData.mSize.width * 4);
|
||||
}
|
||||
|
||||
PRUint8* src = imageSurface->Data();
|
||||
//FIX cast
|
||||
PRUint8* dest = (PRUint8*)lockrect.pBits;
|
||||
|
||||
// copy over data. If we don't need to do any swaping we can
|
||||
// use memcpy
|
||||
for (int i=0; i<aData.mSize.width*aData.mSize.height; i++) {
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = src[3];
|
||||
dest += 4;
|
||||
src += 4;
|
||||
mTexture->UnlockRect(0);
|
||||
}
|
||||
|
||||
mTexture->UnlockRect(0);
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
|
@ -43,25 +43,10 @@
|
||||
#include "ColorLayerD3D9.h"
|
||||
#include "CanvasLayerD3D9.h"
|
||||
|
||||
#include "LayerManagerD3D9Shaders.h"
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
struct vertex {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
IDirect3D9 *LayerManagerD3D9::mD3D9 = NULL;
|
||||
|
||||
typedef IDirect3D9* (WINAPI*Direct3DCreate9Func)(
|
||||
UINT SDKVersion
|
||||
);
|
||||
|
||||
DeviceManagerD3D9 *LayerManagerD3D9::mDeviceManager = nsnull;
|
||||
|
||||
LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget)
|
||||
{
|
||||
@ -72,145 +57,39 @@ LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget)
|
||||
|
||||
LayerManagerD3D9::~LayerManagerD3D9()
|
||||
{
|
||||
}
|
||||
/* Important to release this first since it also holds a reference to the
|
||||
* device manager
|
||||
*/
|
||||
mSwapChain = nsnull;
|
||||
|
||||
#define HAS_CAP(a, b) (((a) & (b)) == (b))
|
||||
#define LACKS_CAP(a, b) !(((a) & (b)) == (b))
|
||||
if (mDeviceManager) {
|
||||
if (!mDeviceManager->Release()) {
|
||||
mDeviceManager = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
LayerManagerD3D9::Initialize()
|
||||
{
|
||||
if (!mD3D9) {
|
||||
Direct3DCreate9Func d3d9create = (Direct3DCreate9Func)
|
||||
GetProcAddress(LoadLibraryW(L"d3d9.dll"), "Direct3DCreate9");
|
||||
if (!d3d9create) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (!mDeviceManager) {
|
||||
mDeviceManager = new DeviceManagerD3D9;
|
||||
|
||||
mD3D9 = d3d9create(D3D_SDK_VERSION);
|
||||
if (!mD3D9) {
|
||||
if (!mDeviceManager->Init()) {
|
||||
mDeviceManager = nsnull;
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
mDeviceManager->AddRef();
|
||||
|
||||
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_COPY;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
||||
pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
mSwapChain = mDeviceManager->
|
||||
CreateSwapChain((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW));
|
||||
|
||||
HRESULT hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT,
|
||||
D3DDEVTYPE_HAL,
|
||||
NULL,
|
||||
D3DCREATE_FPU_PRESERVE |
|
||||
D3DCREATE_MULTITHREADED |
|
||||
D3DCREATE_MIXED_VERTEXPROCESSING,
|
||||
&pp,
|
||||
getter_AddRefs(mDevice));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
if (!mSwapChain) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!VerifyCaps()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
|
||||
getter_AddRefs(mLayerVS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS,
|
||||
getter_AddRefs(mRGBPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS,
|
||||
getter_AddRefs(mYCbCrPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS,
|
||||
getter_AddRefs(mSolidColorPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4,
|
||||
0,
|
||||
0,
|
||||
D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mVB),
|
||||
NULL);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
vertex *vertices;
|
||||
hr = mVB->Lock(0, 0, (void**)&vertices, 0);
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
vertices[0].x = vertices[0].y = 0;
|
||||
vertices[1].x = 1; vertices[1].y = 0;
|
||||
vertices[2].x = 0; vertices[2].y = 1;
|
||||
vertices[3].x = 1; vertices[3].y = 1;
|
||||
|
||||
mVB->Unlock();
|
||||
|
||||
hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
D3DVERTEXELEMENT9 elements[] = {
|
||||
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
|
||||
D3DDECLUSAGE_POSITION, 0 },
|
||||
D3DDECL_END()
|
||||
};
|
||||
|
||||
mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD));
|
||||
|
||||
SetupRenderState();
|
||||
|
||||
nsCOMPtr<nsIConsoleService>
|
||||
console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
|
||||
D3DADAPTER_IDENTIFIER9 identifier;
|
||||
mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
|
||||
|
||||
if (console) {
|
||||
nsString msg;
|
||||
msg +=
|
||||
NS_LITERAL_STRING("Direct3D 9 LayerManager Initialized Succesfully.\nDriver: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsDependentCString((const char*)identifier.Driver));
|
||||
msg += NS_LITERAL_STRING("\nDescription: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsDependentCString((const char*)identifier.Description));
|
||||
msg += NS_LITERAL_STRING("\nVersion: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsPrintfCString("%d.%d.%d.%d",
|
||||
HIWORD(identifier.DriverVersion.HighPart),
|
||||
LOWORD(identifier.DriverVersion.HighPart),
|
||||
HIWORD(identifier.DriverVersion.LowPart),
|
||||
LOWORD(identifier.DriverVersion.LowPart)));
|
||||
console->LogStringMessage(msg.get());
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
@ -298,38 +177,21 @@ LayerManagerD3D9::CreateImageContainer()
|
||||
return container.forget();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D9::SetShaderMode(ShaderMode aMode)
|
||||
{
|
||||
switch (aMode) {
|
||||
case RGBLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mRGBPS);
|
||||
break;
|
||||
case YCBCRLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mYCbCrPS);
|
||||
break;
|
||||
case SOLIDCOLORLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mSolidColorPS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D9::Render()
|
||||
{
|
||||
if (!SetupBackBuffer()) {
|
||||
if (!mSwapChain->PrepareForRendering()) {
|
||||
return;
|
||||
}
|
||||
deviceManager()->SetupRenderState();
|
||||
|
||||
SetupPipeline();
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
|
||||
mDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0, 0);
|
||||
device()->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 0, 0);
|
||||
|
||||
mDevice->BeginScene();
|
||||
device()->BeginScene();
|
||||
|
||||
if (mRootLayer) {
|
||||
const nsIntRect *clipRect = mRootLayer->GetLayer()->GetClipRect();
|
||||
@ -344,24 +206,18 @@ LayerManagerD3D9::Render()
|
||||
r.right = rect.width;
|
||||
r.bottom = rect.height;
|
||||
}
|
||||
mDevice->SetScissorRect(&r);
|
||||
device()->SetScissorRect(&r);
|
||||
|
||||
mRootLayer->RenderLayer();
|
||||
}
|
||||
|
||||
mDevice->EndScene();
|
||||
device()->EndScene();
|
||||
|
||||
if (!mTarget) {
|
||||
const nsIntRect *r;
|
||||
for (nsIntRegionRectIterator iter(mClippingRegion);
|
||||
(r = iter.Next()) != nsnull;) {
|
||||
RECT rect;
|
||||
rect.left = r->x;
|
||||
rect.top = r->y;
|
||||
rect.right = r->XMost();
|
||||
rect.bottom = r->YMost();
|
||||
|
||||
mDevice->Present(&rect, &rect, NULL, NULL);
|
||||
mSwapChain->Present(*r);
|
||||
}
|
||||
} else {
|
||||
PaintToTarget();
|
||||
@ -387,86 +243,29 @@ LayerManagerD3D9::SetupPipeline()
|
||||
viewMatrix[3][1] = 1.0f;
|
||||
viewMatrix[3][3] = 1.0f;
|
||||
|
||||
HRESULT hr = mDevice->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
|
||||
HRESULT hr = device()->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to set projection shader constant!");
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
LayerManagerD3D9::SetupBackBuffer()
|
||||
{
|
||||
nsRefPtr<IDirect3DSurface9> backBuffer;
|
||||
mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
|
||||
getter_AddRefs(backBuffer));
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
backBuffer->GetDesc(&desc);
|
||||
|
||||
HRESULT hr = mDevice->TestCooperativeLevel();
|
||||
|
||||
/* The device is lost or something else is wrong, failure */
|
||||
if (FAILED(hr) && hr != D3DERR_DEVICENOTRESET) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the backbuffer is the right size, and the device is not lost, we can
|
||||
* safely render without doing anything.
|
||||
*/
|
||||
if ((desc.Width == rect.width && desc.Height == rect.height) &&
|
||||
SUCCEEDED(hr)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Our device is lost or our backbuffer needs resizing, start by clearing
|
||||
* out all D3DPOOL_DEFAULT surfaces.
|
||||
*/
|
||||
for(unsigned int i = 0; i < mThebesLayers.Length(); i++) {
|
||||
mThebesLayers[i]->CleanResources();
|
||||
}
|
||||
|
||||
backBuffer = NULL;
|
||||
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
|
||||
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_COPY;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
||||
pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
|
||||
hr = mDevice->Reset(&pp);
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
SetupRenderState();
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D9::PaintToTarget()
|
||||
{
|
||||
nsRefPtr<IDirect3DSurface9> backBuff;
|
||||
nsRefPtr<IDirect3DSurface9> destSurf;
|
||||
mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
|
||||
device()->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
|
||||
getter_AddRefs(backBuff));
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
backBuff->GetDesc(&desc);
|
||||
|
||||
mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height,
|
||||
device()->CreateOffscreenPlainSurface(desc.Width, desc.Height,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
|
||||
getter_AddRefs(destSurf), NULL);
|
||||
|
||||
mDevice->GetRenderTargetData(backBuff, destSurf);
|
||||
device()->GetRenderTargetData(backBuff, destSurf);
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
destSurf->LockRect(&rect, NULL, D3DLOCK_READONLY);
|
||||
@ -483,81 +282,6 @@ LayerManagerD3D9::PaintToTarget()
|
||||
destSurf->UnlockRect();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D9::SetupRenderState()
|
||||
{
|
||||
mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
|
||||
mDevice->SetVertexDeclaration(mVD);
|
||||
mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||
mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
}
|
||||
|
||||
PRBool
|
||||
LayerManagerD3D9::VerifyCaps()
|
||||
{
|
||||
D3DCAPS9 caps;
|
||||
HRESULT hr = mDevice->GetDeviceCaps(&caps);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) ||
|
||||
LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) ||
|
||||
LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) ||
|
||||
HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) ||
|
||||
(HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) &&
|
||||
LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) ||
|
||||
LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (caps.MaxTextureHeight < 4096 ||
|
||||
caps.MaxTextureWidth < 4096) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if ((caps.PixelShaderVersion & 0xffff) < 0x200 ||
|
||||
(caps.VertexShaderVersion & 0xffff) < 0x200) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
LayerD3D9::LayerD3D9(LayerManagerD3D9 *aManager)
|
||||
: mD3DManager(aManager)
|
||||
{
|
||||
|
@ -46,6 +46,8 @@
|
||||
#include "gfxContext.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "DeviceManagerD3D9.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
@ -122,49 +124,27 @@ public:
|
||||
*/
|
||||
void SetClippingEnabled(PRBool aEnabled);
|
||||
|
||||
IDirect3DDevice9 *device() const { return mDevice; }
|
||||
void SetShaderMode(DeviceManagerD3D9::ShaderMode aMode)
|
||||
{ mDeviceManager->SetShaderMode(aMode); }
|
||||
|
||||
enum ShaderMode {
|
||||
RGBLAYER,
|
||||
YCBCRLAYER,
|
||||
SOLIDCOLORLAYER
|
||||
};
|
||||
|
||||
void SetShaderMode(ShaderMode aMode);
|
||||
|
||||
nsTArray<ThebesLayerD3D9*> mThebesLayers;
|
||||
IDirect3DDevice9 *device() const { return mDeviceManager->device(); }
|
||||
DeviceManagerD3D9 *deviceManager() const { return mDeviceManager; }
|
||||
|
||||
private:
|
||||
/* Direct3D9 instance */
|
||||
static IDirect3D9 *mD3D9;
|
||||
/* Device manager instance */
|
||||
static DeviceManagerD3D9 *mDeviceManager;
|
||||
|
||||
/* Swap chain associated with this layer manager */
|
||||
nsRefPtr<SwapChainD3D9> mSwapChain;
|
||||
|
||||
/* Widget associated with this layer manager */
|
||||
nsIWidget *mWidget;
|
||||
|
||||
/*
|
||||
* Context target, NULL when drawing directly to our swap chain.
|
||||
*/
|
||||
nsRefPtr<gfxContext> mTarget;
|
||||
|
||||
nsRefPtr<IDirect3DDevice9> mDevice;
|
||||
|
||||
/* Vertex shader used for layer quads */
|
||||
nsRefPtr<IDirect3DVertexShader9> mLayerVS;
|
||||
|
||||
/* Pixel shader used for RGB textures */
|
||||
nsRefPtr<IDirect3DPixelShader9> mRGBPS;
|
||||
|
||||
/* Pixel shader used for RGB textures */
|
||||
nsRefPtr<IDirect3DPixelShader9> mYCbCrPS;
|
||||
|
||||
/* Pixel shader used for solid colors */
|
||||
nsRefPtr<IDirect3DPixelShader9> mSolidColorPS;
|
||||
|
||||
/* Vertex buffer containing our basic vertex structure */
|
||||
nsRefPtr<IDirect3DVertexBuffer9> mVB;
|
||||
|
||||
/* Our vertex declaration */
|
||||
nsRefPtr<IDirect3DVertexDeclaration9> mVD;
|
||||
|
||||
/* Current root layer. */
|
||||
LayerD3D9 *mRootLayer;
|
||||
|
||||
@ -175,32 +155,21 @@ private:
|
||||
* Region we're clipping our current drawing to.
|
||||
*/
|
||||
nsIntRegion mClippingRegion;
|
||||
|
||||
/*
|
||||
* Render the current layer tree to the active target.
|
||||
*/
|
||||
void Render();
|
||||
|
||||
/*
|
||||
* Setup the pipeline.
|
||||
*/
|
||||
void SetupPipeline();
|
||||
/*
|
||||
* Setup the backbuffer.
|
||||
*
|
||||
* \return PR_TRUE if setup was succesful
|
||||
*/
|
||||
PRBool SetupBackBuffer();
|
||||
/*
|
||||
* Setup the render state for the surface.
|
||||
*/
|
||||
void SetupRenderState();
|
||||
|
||||
/*
|
||||
* Copies the content of our backbuffer to the set transaction target.
|
||||
*/
|
||||
void PaintToTarget();
|
||||
/*
|
||||
* Verifies all required device capabilities are present.
|
||||
*/
|
||||
PRBool VerifyCaps();
|
||||
|
||||
};
|
||||
|
||||
|
@ -39,6 +39,9 @@
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
#include "gfxD2DSurface.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -69,12 +72,12 @@ ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager)
|
||||
, LayerD3D9(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D9*>(this);
|
||||
aManager->mThebesLayers.AppendElement(this);
|
||||
aManager->deviceManager()->mThebesLayers.AppendElement(this);
|
||||
}
|
||||
|
||||
ThebesLayerD3D9::~ThebesLayerD3D9()
|
||||
{
|
||||
mD3DManager->mThebesLayers.RemoveElement(this);
|
||||
mD3DManager->deviceManager()->mThebesLayers.RemoveElement(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,7 +104,8 @@ ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
|
||||
return;
|
||||
}
|
||||
|
||||
D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||
D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ?
|
||||
D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
mTexture->GetLevelDesc(0, &desc);
|
||||
@ -116,10 +120,8 @@ ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
|
||||
|
||||
nsIntRect oldBounds = oldVisibleRegion.GetBounds();
|
||||
nsIntRect newBounds = mVisibleRegion.GetBounds();
|
||||
|
||||
device()->CreateTexture(newBounds.width, newBounds.height, 1,
|
||||
D3DUSAGE_RENDERTARGET, fmt,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
|
||||
|
||||
CreateNewTexture(gfxIntSize(newBounds.width, newBounds.height));
|
||||
|
||||
// Old visible region will become the region that is covered by both the
|
||||
// old and the new visible region.
|
||||
@ -191,13 +193,14 @@ ThebesLayerD3D9::RenderLayer()
|
||||
if (mVisibleRegion.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
HRESULT hr;
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
// We differentiate between these formats since D3D9 will only allow us to
|
||||
// call GetDC on an opaque surface.
|
||||
D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||
D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ?
|
||||
D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||
|
||||
if (mTexture) {
|
||||
D3DSURFACE_DESC desc;
|
||||
mTexture->GetLevelDesc(0, &desc);
|
||||
@ -211,103 +214,16 @@ ThebesLayerD3D9::RenderLayer()
|
||||
}
|
||||
|
||||
if (!mTexture) {
|
||||
device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
|
||||
D3DUSAGE_RENDERTARGET, fmt,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
|
||||
CreateNewTexture(gfxIntSize(visibleRect.width, visibleRect.height));
|
||||
mValidRegion.SetEmpty();
|
||||
}
|
||||
|
||||
if (!mValidRegion.IsEqual(mVisibleRegion)) {
|
||||
nsIntRegion region;
|
||||
region.Sub(mVisibleRegion, mValidRegion);
|
||||
nsIntRect bounds = region.GetBounds();
|
||||
|
||||
gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;
|
||||
nsRefPtr<gfxASurface> destinationSurface;
|
||||
nsRefPtr<gfxContext> context;
|
||||
DrawRegion(region);
|
||||
|
||||
nsRefPtr<IDirect3DTexture9> tmpTexture;
|
||||
device()->CreateTexture(bounds.width, bounds.height, 1,
|
||||
0, fmt,
|
||||
D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> surf;
|
||||
HDC dc;
|
||||
if (UseOpaqueSurface(this)) {
|
||||
hr = tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surf));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
// Uh-oh, bail.
|
||||
NS_WARNING("Failed to get texture surface level.");
|
||||
return;
|
||||
}
|
||||
|
||||
hr = surf->GetDC(&dc);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to get device context for texture surface.");
|
||||
return;
|
||||
}
|
||||
|
||||
destinationSurface = new gfxWindowsSurface(dc);
|
||||
} else {
|
||||
// XXX - We may consider retaining a SYSTEMMEM texture texture the size
|
||||
// of our DEFAULT texture and then use UpdateTexture and add dirty rects
|
||||
// to update in a single call.
|
||||
destinationSurface =
|
||||
gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gfxIntSize(bounds.width,
|
||||
bounds.height),
|
||||
imageFormat);
|
||||
}
|
||||
|
||||
context = new gfxContext(destinationSurface);
|
||||
context->Translate(gfxPoint(-bounds.x, -bounds.y));
|
||||
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
cbInfo.Callback(this, context, region, nsIntRegion(), cbInfo.CallbackData);
|
||||
|
||||
if (UseOpaqueSurface(this)) {
|
||||
surf->ReleaseDC(dc);
|
||||
} else {
|
||||
D3DLOCKED_RECT r;
|
||||
tmpTexture->LockRect(0, &r, NULL, 0);
|
||||
|
||||
nsRefPtr<gfxImageSurface> imgSurface =
|
||||
new gfxImageSurface((unsigned char *)r.pBits,
|
||||
gfxIntSize(bounds.width,
|
||||
bounds.height),
|
||||
r.Pitch,
|
||||
imageFormat);
|
||||
|
||||
context = new gfxContext(imgSurface);
|
||||
context->SetSource(destinationSurface);
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
context->Paint();
|
||||
|
||||
imgSurface = NULL;
|
||||
|
||||
tmpTexture->UnlockRect(0);
|
||||
}
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> srcSurface;
|
||||
nsRefPtr<IDirect3DSurface9> dstSurface;
|
||||
|
||||
mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
tmpTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
|
||||
|
||||
nsIntRegionRectIterator iter(region);
|
||||
const nsIntRect *iterRect;
|
||||
while ((iterRect = iter.Next())) {
|
||||
RECT rect;
|
||||
rect.left = iterRect->x - bounds.x;
|
||||
rect.top = iterRect->y - bounds.y;
|
||||
rect.right = rect.left + iterRect->width;
|
||||
rect.bottom = rect.top + iterRect->height;
|
||||
POINT point;
|
||||
point.x = iterRect->x - visibleRect.x;
|
||||
point.y = iterRect->y - visibleRect.y;
|
||||
device()->UpdateSurface(srcSurface, &rect, dstSurface, &point);
|
||||
}
|
||||
mValidRegion = mVisibleRegion;
|
||||
}
|
||||
|
||||
@ -338,7 +254,7 @@ ThebesLayerD3D9::RenderLayer()
|
||||
opacity[0] = GetOpacity();
|
||||
device()->SetPixelShaderConstantF(0, opacity, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
|
||||
|
||||
device()->SetTexture(0, mTexture);
|
||||
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
@ -362,5 +278,168 @@ ThebesLayerD3D9::IsEmpty()
|
||||
return !mTexture;
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion)
|
||||
{
|
||||
HRESULT hr;
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
nsRefPtr<gfxContext> context;
|
||||
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
if (mD2DSurface) {
|
||||
context = new gfxContext(mD2DSurface);
|
||||
nsIntRegionRectIterator iter(aRegion);
|
||||
context->Translate(gfxPoint(-visibleRect.x, -visibleRect.y));
|
||||
context->NewPath();
|
||||
const nsIntRect *iterRect;
|
||||
while ((iterRect = iter.Next())) {
|
||||
context->Rectangle(gfxRect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
|
||||
}
|
||||
context->Clip();
|
||||
if (mD2DSurface->GetContentType() != gfxASurface::CONTENT_COLOR) {
|
||||
context->SetOperator(gfxContext::OPERATOR_CLEAR);
|
||||
context->Paint();
|
||||
context->SetOperator(gfxContext::OPERATOR_OVER);
|
||||
}
|
||||
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
|
||||
mD2DSurface->Flush();
|
||||
|
||||
// XXX - This call is quite expensive, we may want to consider doing our
|
||||
// drawing in a seperate 'validation' iteration. And then flushing once for
|
||||
// all the D2D surfaces we might have drawn, before doing our D3D9 rendering
|
||||
// loop.
|
||||
cairo_d2d_finish_device(gfxWindowsPlatform::GetPlatform()->GetD2DDevice());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||
nsIntRect bounds = aRegion.GetBounds();
|
||||
|
||||
gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;
|
||||
nsRefPtr<gfxASurface> destinationSurface;
|
||||
|
||||
nsRefPtr<IDirect3DTexture9> tmpTexture;
|
||||
device()->CreateTexture(bounds.width, bounds.height, 1,
|
||||
0, fmt,
|
||||
D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> surf;
|
||||
HDC dc;
|
||||
if (UseOpaqueSurface(this)) {
|
||||
hr = tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surf));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
// Uh-oh, bail.
|
||||
NS_WARNING("Failed to get texture surface level.");
|
||||
return;
|
||||
}
|
||||
|
||||
hr = surf->GetDC(&dc);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to get device context for texture surface.");
|
||||
return;
|
||||
}
|
||||
|
||||
destinationSurface = new gfxWindowsSurface(dc);
|
||||
} else {
|
||||
// XXX - We may consider retaining a SYSTEMMEM texture texture the size
|
||||
// of our DEFAULT texture and then use UpdateTexture and add dirty rects
|
||||
// to update in a single call.
|
||||
destinationSurface =
|
||||
gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gfxIntSize(bounds.width,
|
||||
bounds.height),
|
||||
imageFormat);
|
||||
}
|
||||
|
||||
context = new gfxContext(destinationSurface);
|
||||
context->Translate(gfxPoint(-bounds.x, -bounds.y));
|
||||
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
|
||||
|
||||
if (UseOpaqueSurface(this)) {
|
||||
surf->ReleaseDC(dc);
|
||||
} else {
|
||||
D3DLOCKED_RECT r;
|
||||
tmpTexture->LockRect(0, &r, NULL, 0);
|
||||
|
||||
nsRefPtr<gfxImageSurface> imgSurface =
|
||||
new gfxImageSurface((unsigned char *)r.pBits,
|
||||
gfxIntSize(bounds.width,
|
||||
bounds.height),
|
||||
r.Pitch,
|
||||
imageFormat);
|
||||
|
||||
context = new gfxContext(imgSurface);
|
||||
context->SetSource(destinationSurface);
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
context->Paint();
|
||||
|
||||
imgSurface = NULL;
|
||||
|
||||
tmpTexture->UnlockRect(0);
|
||||
}
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> srcSurface;
|
||||
nsRefPtr<IDirect3DSurface9> dstSurface;
|
||||
|
||||
mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
tmpTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
|
||||
|
||||
nsIntRegionRectIterator iter(aRegion);
|
||||
const nsIntRect *iterRect;
|
||||
while ((iterRect = iter.Next())) {
|
||||
RECT rect;
|
||||
rect.left = iterRect->x - bounds.x;
|
||||
rect.top = iterRect->y - bounds.y;
|
||||
rect.right = rect.left + iterRect->width;
|
||||
rect.bottom = rect.top + iterRect->height;
|
||||
POINT point;
|
||||
point.x = iterRect->x - visibleRect.x;
|
||||
point.y = iterRect->y - visibleRect.y;
|
||||
device()->UpdateSurface(srcSurface, &rect, dstSurface, &point);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize)
|
||||
{
|
||||
if (aSize.width == 0 | aSize.height == 0) {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
mTexture = nsnull;
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
|
||||
gfxWindowsPlatform::RENDER_DIRECT2D) {
|
||||
if (mD3DManager->deviceManager()->IsD3D9Ex()) {
|
||||
// We should have D3D9Ex where we have D2D.
|
||||
HANDLE sharedHandle = 0;
|
||||
device()->CreateTexture(aSize.width, aSize.height, 1,
|
||||
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), &sharedHandle);
|
||||
|
||||
mD2DSurface = new gfxD2DSurface(sharedHandle, UseOpaqueSurface(this) ?
|
||||
gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA);
|
||||
|
||||
// If there's an error, go on and do what we always do.
|
||||
if (mD2DSurface->CairoStatus()) {
|
||||
mD2DSurface = nsnull;
|
||||
mTexture = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!mTexture) {
|
||||
device()->CreateTexture(aSize.width, aSize.height, 1,
|
||||
D3DUSAGE_RENDERTARGET, UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace layers */
|
||||
} /* namespace mozilla */
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "LayerManagerD3D9.h"
|
||||
#include "gfxImageSurface.h"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
@ -70,6 +69,15 @@ private:
|
||||
* D3D9 texture
|
||||
*/
|
||||
nsRefPtr<IDirect3DTexture9> mTexture;
|
||||
|
||||
/* This contains the D2D surface if we have one */
|
||||
nsRefPtr<gfxASurface> mD2DSurface;
|
||||
|
||||
/* Have a region of our layer drawn */
|
||||
void DrawRegion(const nsIntRegion &aRegion);
|
||||
|
||||
/* Create a new texture */
|
||||
void CreateNewTexture(const gfxIntSize &aSize);
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
|
@ -36,10 +36,22 @@
|
||||
#include "gfxD2DSurface.h"
|
||||
#include "cairo.h"
|
||||
#include "cairo-win32.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
|
||||
gfxD2DSurface::gfxD2DSurface(HWND aWnd, gfxContentType aContent)
|
||||
{
|
||||
Init(cairo_d2d_surface_create_for_hwnd(aWnd, (cairo_content_t)aContent));
|
||||
Init(cairo_d2d_surface_create_for_hwnd(
|
||||
gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
|
||||
aWnd,
|
||||
(cairo_content_t)aContent));
|
||||
}
|
||||
|
||||
gfxD2DSurface::gfxD2DSurface(HANDLE handle, gfxContentType aContent)
|
||||
{
|
||||
Init(cairo_d2d_surface_create_for_handle(
|
||||
gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
|
||||
handle,
|
||||
(cairo_content_t)aContent));
|
||||
}
|
||||
|
||||
gfxD2DSurface::gfxD2DSurface(cairo_surface_t *csurf)
|
||||
@ -50,7 +62,10 @@ gfxD2DSurface::gfxD2DSurface(cairo_surface_t *csurf)
|
||||
gfxD2DSurface::gfxD2DSurface(const gfxIntSize& size,
|
||||
gfxImageFormat imageFormat)
|
||||
{
|
||||
Init(cairo_d2d_surface_create((cairo_format_t)imageFormat, size.width, size.height));
|
||||
Init(cairo_d2d_surface_create(
|
||||
gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
|
||||
(cairo_format_t)imageFormat,
|
||||
size.width, size.height));
|
||||
}
|
||||
|
||||
gfxD2DSurface::~gfxD2DSurface()
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
gfxD2DSurface(const gfxIntSize& size,
|
||||
gfxImageFormat imageFormat = ImageFormatRGB24);
|
||||
|
||||
gfxD2DSurface(HANDLE handle, gfxContentType aContent);
|
||||
|
||||
gfxD2DSurface(cairo_surface_t *csurf);
|
||||
|
||||
|
@ -170,6 +170,7 @@ gfxWindowsPlatform::gfxWindowsPlatform()
|
||||
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
NS_RegisterMemoryReporter(new D2DCacheReporter());
|
||||
mD2DDevice = NULL;
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||
nsresult rv;
|
||||
@ -213,7 +214,8 @@ gfxWindowsPlatform::gfxWindowsPlatform()
|
||||
#ifndef CAIRO_HAS_D2D_SURFACE
|
||||
return;
|
||||
#else
|
||||
if (!cairo_d2d_has_support()) {
|
||||
mD2DDevice = cairo_d2d_create_device();
|
||||
if (!mD2DDevice) {
|
||||
return;
|
||||
}
|
||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||
@ -235,6 +237,11 @@ gfxWindowsPlatform::~gfxWindowsPlatform()
|
||||
{
|
||||
// not calling FT_Done_FreeType because cairo may still hold references to
|
||||
// these FT_Faces. See bug 458169.
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
if (mD2DDevice) {
|
||||
cairo_release_device(mD2DDevice);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
gfxPlatformFontList*
|
||||
|
@ -214,6 +214,9 @@ public:
|
||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||
IDWriteFactory *GetDWriteFactory() { return mDWriteFactory; }
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
cairo_device_t *GetD2DDevice() { return mD2DDevice; }
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
FT_Library GetFTLibrary();
|
||||
@ -233,6 +236,9 @@ private:
|
||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||
nsRefPtr<IDWriteFactory> mDWriteFactory;
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
cairo_device_t *mD2DDevice;
|
||||
#endif
|
||||
|
||||
virtual qcms_profile* GetPlatformCMSOutputProfile();
|
||||
|
||||
|
@ -60,6 +60,9 @@
|
||||
# include <locale.h>
|
||||
# include <stdlib.h>
|
||||
# include "nsIPosixLocale.h"
|
||||
#if (MOZ_PLATFORM_MAEMO >= 6)
|
||||
# include "nsIGConfService.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
@ -174,24 +177,43 @@ nsLocaleService::nsLocaleService(void)
|
||||
if ( resultLocale == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get system configuration
|
||||
char* lang = getenv("LANG");
|
||||
#if (MOZ_PLATFORM_MAEMO >= 6)
|
||||
nsCAutoString gconfLocaleString;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIGConfService> gconf =
|
||||
do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = gconf->GetString(NS_LITERAL_CSTRING("/meegotouch/i18n/language"),
|
||||
gconfLocaleString);
|
||||
if (NS_SUCCEEDED(rv) && !gconfLocaleString.IsEmpty()) {
|
||||
lang = static_cast<const char*>(gconfLocaleString.get());
|
||||
// For setlocale() doing the right thing we need to export
|
||||
// this as LANG to the environment
|
||||
setenv("LANG", lang, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( i = 0; i < LocaleListLength; i++ ) {
|
||||
nsresult result;
|
||||
// setlocale( , "") evaluates LC_* and LANG
|
||||
char* lc_temp = setlocale(posix_locale_category[i], "");
|
||||
CopyASCIItoUTF16(LocaleList[i], category);
|
||||
category_platform = category;
|
||||
category_platform = category;
|
||||
category_platform.AppendLiteral("##PLATFORM");
|
||||
if (lc_temp != nsnull) {
|
||||
result = posixConverter->GetXPLocale(lc_temp, xpLocale);
|
||||
CopyASCIItoUTF16(lc_temp, platformLocale);
|
||||
} else {
|
||||
char* lang = getenv("LANG");
|
||||
if ( lang == nsnull ) {
|
||||
platformLocale.AssignLiteral("en_US");
|
||||
result = posixConverter->GetXPLocale("en-US", xpLocale);
|
||||
}
|
||||
else {
|
||||
CopyASCIItoUTF16(lang, platformLocale);
|
||||
result = posixConverter->GetXPLocale(lang, xpLocale);
|
||||
result = posixConverter->GetXPLocale(lang, xpLocale);
|
||||
}
|
||||
}
|
||||
if (NS_FAILED(result)) {
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "base/singleton.h"
|
||||
#include "base/waitable_event.h"
|
||||
#ifdef CHROMIUM_MOZILLA_BUILD
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
#include "mozilla/ipc/BrowserProcessSubThread.h"
|
||||
typedef mozilla::ipc::BrowserProcessSubThread ChromeThread;
|
||||
#else
|
||||
@ -121,6 +122,8 @@ bool ChildProcessHost::Send(IPC::Message* msg) {
|
||||
void ChildProcessHost::Notify(NotificationType type) {
|
||||
#ifdef CHROMIUM_MOZILLA_BUILD
|
||||
MessageLoop* loop = ChromeThread::GetMessageLoop(ChromeThread::IO);
|
||||
if (!loop)
|
||||
loop = mozilla::ipc::ProcessChild::message_loop();
|
||||
if (!loop)
|
||||
loop = MessageLoop::current();
|
||||
loop->PostTask(
|
||||
|
@ -131,12 +131,14 @@ void GeckoChildProcessHost::InitWindowsGroupID()
|
||||
#endif
|
||||
|
||||
bool
|
||||
GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTimeoutMs)
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
InitWindowsGroupID();
|
||||
#endif
|
||||
|
||||
PRIntervalTime timeoutTicks = (aTimeoutMs > 0) ?
|
||||
PR_MillisecondsToInterval(aTimeoutMs) : PR_INTERVAL_NO_TIMEOUT;
|
||||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
||||
NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI");
|
||||
|
||||
@ -144,15 +146,29 @@ GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
NewRunnableMethod(this,
|
||||
&GeckoChildProcessHost::PerformAsyncLaunch,
|
||||
aExtraOpts));
|
||||
|
||||
// NB: this uses a different mechanism than the chromium parent
|
||||
// class.
|
||||
MonitorAutoEnter mon(mMonitor);
|
||||
PRIntervalTime waitStart = PR_IntervalNow();
|
||||
PRIntervalTime current;
|
||||
|
||||
// We'll receive several notifications, we need to exit when we
|
||||
// have either successfully launched or have timed out.
|
||||
while (!mLaunched) {
|
||||
mon.Wait();
|
||||
mon.Wait(timeoutTicks);
|
||||
|
||||
if (timeoutTicks != PR_INTERVAL_NO_TIMEOUT) {
|
||||
current = PR_IntervalNow();
|
||||
PRIntervalTime elapsed = current - waitStart;
|
||||
if (elapsed > timeoutTicks) {
|
||||
break;
|
||||
}
|
||||
timeoutTicks = timeoutTicks - elapsed;
|
||||
waitStart = current;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return mLaunched;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -237,14 +253,6 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
newEnvVars["LD_LIBRARY_PATH"] = path.get();
|
||||
#elif OS_MACOSX
|
||||
newEnvVars["DYLD_LIBRARY_PATH"] = path.get();
|
||||
#endif
|
||||
#ifdef MOZ_OMNIJAR
|
||||
// Make sure the child process can find the omnijar
|
||||
// See ScopedXPCOMStartup::Initialize in nsAppRunner.cpp
|
||||
nsCAutoString omnijarPath;
|
||||
if (mozilla::OmnijarPath())
|
||||
mozilla::OmnijarPath()->GetNativePath(omnijarPath);
|
||||
newEnvVars["OMNIJAR_PATH"] = omnijarPath.get();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
@ -280,6 +288,17 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
|
||||
childArgv.insert(childArgv.end(), aExtraOpts.begin(), aExtraOpts.end());
|
||||
|
||||
#ifdef MOZ_OMNIJAR
|
||||
// Make sure the child process can find the omnijar
|
||||
// See XRE_InitCommandLine in nsAppRunner.cpp
|
||||
nsCAutoString omnijarPath;
|
||||
if (mozilla::OmnijarPath()) {
|
||||
mozilla::OmnijarPath()->GetNativePath(omnijarPath);
|
||||
childArgv.push_back("-omnijar");
|
||||
childArgv.push_back(omnijarPath.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
childArgv.push_back(pidstring);
|
||||
childArgv.push_back(childProcessType);
|
||||
|
||||
@ -330,6 +349,18 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
}
|
||||
|
||||
cmdLine.AppendLooseValue(std::wstring(mGroupId.get()));
|
||||
|
||||
#ifdef MOZ_OMNIJAR
|
||||
// Make sure the child process can find the omnijar
|
||||
// See XRE_InitCommandLine in nsAppRunner.cpp
|
||||
nsAutoString omnijarPath;
|
||||
if (mozilla::OmnijarPath()) {
|
||||
mozilla::OmnijarPath()->GetPath(omnijarPath);
|
||||
cmdLine.AppendLooseValue(UTF8ToWide("-omnijar"));
|
||||
cmdLine.AppendLooseValue(omnijarPath.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(pidstring));
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(childProcessType));
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
|
||||
~GeckoChildProcessHost();
|
||||
|
||||
bool SyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>());
|
||||
bool SyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>(), int32 timeoutMs=0);
|
||||
bool AsyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>());
|
||||
bool PerformAsyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>());
|
||||
|
||||
|
@ -486,7 +486,6 @@ def _cxxRefType(ipdltype, side):
|
||||
def _cxxConstRefType(ipdltype, side):
|
||||
t = _cxxBareType(ipdltype, side)
|
||||
if ipdltype.isIPDL() and ipdltype.isActor():
|
||||
t.const = 1 # const Actor*
|
||||
return t
|
||||
if ipdltype.isIPDL() and ipdltype.isShmem():
|
||||
t.ref = 1
|
||||
@ -508,8 +507,7 @@ def _cxxConstPtrToType(ipdltype, side):
|
||||
t = _cxxBareType(ipdltype, side)
|
||||
if ipdltype.isIPDL() and ipdltype.isActor():
|
||||
t.ptr = 0
|
||||
t.const = 1
|
||||
t.ptrconstptr = 1 # const Actor* const*
|
||||
t.ptrconstptr = 1
|
||||
return t
|
||||
t.const = 1
|
||||
t.ptrconst = 1
|
||||
|
@ -78,6 +78,7 @@ IPDLTESTS = \
|
||||
TestShutdown \
|
||||
TestStackHooks \
|
||||
TestSyncWakeup \
|
||||
TestSyncHang \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH),Linux)
|
||||
|
15
ipc/ipdl/test/cxx/PTestSyncHang.ipdl
Normal file
15
ipc/ipdl/test/cxx/PTestSyncHang.ipdl
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestSyncHang {
|
||||
|
||||
child:
|
||||
__delete__();
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
71
ipc/ipdl/test/cxx/TestSyncHang.cpp
Normal file
71
ipc/ipdl/test/cxx/TestSyncHang.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include "TestSyncHang.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
|
||||
mozilla::ipc::GeckoChildProcessHost* gSyncHangSubprocess;
|
||||
|
||||
TestSyncHangParent::TestSyncHangParent()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestSyncHangParent);
|
||||
}
|
||||
|
||||
TestSyncHangParent::~TestSyncHangParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestSyncHangParent);
|
||||
}
|
||||
|
||||
void
|
||||
DeleteSyncHangSubprocess(MessageLoop* uiLoop)
|
||||
{
|
||||
delete gSyncHangSubprocess;
|
||||
}
|
||||
|
||||
void
|
||||
DeferredSyncHangParentShutdown()
|
||||
{
|
||||
// ping to DeleteSubprocess
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(DeleteSyncHangSubprocess, MessageLoop::current()));
|
||||
}
|
||||
|
||||
void
|
||||
TestSyncHangParent::Main()
|
||||
{
|
||||
vector<string> args;
|
||||
args.push_back("fake/path");
|
||||
gSyncHangSubprocess = new mozilla::ipc::GeckoChildProcessHost(GeckoProcessType_Plugin);
|
||||
bool launched = gSyncHangSubprocess->SyncLaunch(args, 2);
|
||||
if (launched)
|
||||
fail("Calling SyncLaunch with an invalid path should return false");
|
||||
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE, NewRunnableFunction(DeferredSyncHangParentShutdown));
|
||||
Close();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
TestSyncHangChild::TestSyncHangChild()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestSyncHangChild);
|
||||
}
|
||||
|
||||
TestSyncHangChild::~TestSyncHangChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestSyncHangChild);
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
56
ipc/ipdl/test/cxx/TestSyncHang.h
Normal file
56
ipc/ipdl/test/cxx/TestSyncHang.h
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef mozilla__ipdltest_TestSyncHang_h
|
||||
#define mozilla__ipdltest_TestSyncHang_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestSyncHangParent.h"
|
||||
#include "mozilla/_ipdltest/PTestSyncHangChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
class TestSyncHangParent :
|
||||
public PTestSyncHangParent
|
||||
{
|
||||
public:
|
||||
TestSyncHangParent();
|
||||
virtual ~TestSyncHangParent();
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TestSyncHangChild :
|
||||
public PTestSyncHangChild
|
||||
{
|
||||
public:
|
||||
TestSyncHangChild();
|
||||
virtual ~TestSyncHangChild();
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
QuitChild();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestSyncHang_h
|
@ -30,5 +30,6 @@ IPDLSRCS = \
|
||||
PTestShutdownSubsub.ipdl \
|
||||
PTestStackHooks.ipdl \
|
||||
PTestSyncWakeup.ipdl \
|
||||
PTestSyncHang.ipdl \
|
||||
PTestSysVShmem.ipdl \
|
||||
$(NULL)
|
||||
|
@ -1215,6 +1215,9 @@ bool
|
||||
XPCShellEnvironment::EvaluateString(const nsString& aString,
|
||||
nsString* aResult)
|
||||
{
|
||||
XPCShellEnvironment* env = Environment(mCx);
|
||||
XPCShellEnvironment::AutoContextPusher pusher(env);
|
||||
|
||||
JSAutoRequest ar(mCx);
|
||||
|
||||
JS_ClearPendingException(mCx);
|
||||
|
@ -48,6 +48,8 @@
|
||||
#include "jsobj.h"
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace jetpack {
|
||||
|
||||
@ -62,7 +64,8 @@ class Handle
|
||||
Handle(Handle* parent)
|
||||
: mParent(parent)
|
||||
, mObj(NULL)
|
||||
, mRuntime(NULL)
|
||||
, mCx(NULL)
|
||||
, mRooted(false)
|
||||
{}
|
||||
|
||||
BaseType* AllocPHandle() {
|
||||
@ -79,7 +82,8 @@ public:
|
||||
Handle()
|
||||
: mParent(NULL)
|
||||
, mObj(NULL)
|
||||
, mRuntime(NULL)
|
||||
, mCx(NULL)
|
||||
, mRooted(false)
|
||||
{}
|
||||
|
||||
~Handle() { TearDown(); }
|
||||
@ -95,8 +99,28 @@ public:
|
||||
return Unwrap(cx, JSVAL_TO_OBJECT(val));
|
||||
}
|
||||
|
||||
JSObject* ToJSObject(JSContext* cx) const {
|
||||
if (!mObj && !mRuntime) {
|
||||
void Root() {
|
||||
NS_ASSERTION(mObj && mCx, "Rooting with no object unexpected.");
|
||||
if (mRooted)
|
||||
return;
|
||||
|
||||
if (!JS_AddNamedObjectRoot(mCx, &mObj, "Jetpack Handle")) {
|
||||
NS_RUNTIMEABORT("Failed to add root.");
|
||||
}
|
||||
mRooted = true;
|
||||
}
|
||||
|
||||
void Unroot() {
|
||||
NS_ASSERTION(mCx, "Unrooting with no JSContext unexpected.");
|
||||
if (!mRooted)
|
||||
return;
|
||||
|
||||
JS_RemoveObjectRoot(mCx, &mObj);
|
||||
mRooted = false;
|
||||
}
|
||||
|
||||
JSObject* ToJSObject(JSContext* cx) {
|
||||
if (!mObj && !mCx) {
|
||||
JSAutoRequest request(cx);
|
||||
|
||||
JSClass* clasp = const_cast<JSClass*>(&sHandle_JSClass);
|
||||
@ -107,16 +131,13 @@ public:
|
||||
|
||||
JSPropertySpec* ps = const_cast<JSPropertySpec*>(sHandle_Properties);
|
||||
JSFunctionSpec* fs = const_cast<JSFunctionSpec*>(sHandle_Functions);
|
||||
JSRuntime* rt;
|
||||
|
||||
if (JS_SetPrivate(cx, obj, (void*)this) &&
|
||||
JS_DefineProperties(cx, obj, ps) &&
|
||||
JS_DefineFunctions(cx, obj, fs) &&
|
||||
(rt = JS_GetRuntime(cx)) &&
|
||||
JS_AddObjectRoot(cx, &mObj))
|
||||
{
|
||||
JS_DefineFunctions(cx, obj, fs)) {
|
||||
mObj = obj;
|
||||
mRuntime = rt;
|
||||
mCx = cx;
|
||||
Root();
|
||||
}
|
||||
}
|
||||
return mObj;
|
||||
@ -134,16 +155,33 @@ private:
|
||||
static bool IsParent(const PHandleChild* handle) { return false; }
|
||||
|
||||
void TearDown() {
|
||||
if (mObj) {
|
||||
mObj->setPrivate(NULL);
|
||||
mObj = NULL;
|
||||
if (mCx) {
|
||||
JSAutoRequest ar(mCx);
|
||||
|
||||
if (mObj) {
|
||||
mObj->setPrivate(NULL);
|
||||
|
||||
js::AutoObjectRooter obj(mCx, mObj);
|
||||
mObj = NULL;
|
||||
|
||||
JSBool hasOnInvalidate;
|
||||
if (JS_HasProperty(mCx, obj.object(), "onInvalidate",
|
||||
&hasOnInvalidate) && hasOnInvalidate) {
|
||||
js::AutoValueRooter r(mCx);
|
||||
JSBool ok = JS_CallFunctionName(mCx, obj.object(), "onInvalidate", 0,
|
||||
NULL, r.jsval_addr());
|
||||
if (!ok)
|
||||
JS_ReportPendingException(mCx);
|
||||
}
|
||||
|
||||
// By not nulling out mContext, we prevent ToJSObject from
|
||||
// reviving an invalidated/destroyed handle.
|
||||
}
|
||||
|
||||
// Nulling out mObj effectively unroots the object, but we still
|
||||
// need to remove the root, else the JS engine will complain at
|
||||
// shutdown.
|
||||
NS_ASSERTION(mRuntime, "Should have a JSRuntime if we had an object");
|
||||
js_RemoveRoot(mRuntime, (void*)&mObj);
|
||||
// By not nulling out mRuntime, we prevent ToJSObject from
|
||||
// reviving an invalidated/destroyed handle.
|
||||
Unroot();
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,8 +193,9 @@ private:
|
||||
|
||||
// Used to cache the JSObject returned by ToJSObject, which is
|
||||
// otherwise a const method.
|
||||
mutable JSObject* mObj;
|
||||
mutable JSRuntime* mRuntime;
|
||||
JSObject* mObj;
|
||||
JSContext* mCx;
|
||||
bool mRooted;
|
||||
|
||||
static Handle*
|
||||
Unwrap(JSContext* cx, JSObject* obj) {
|
||||
@ -199,6 +238,38 @@ private:
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GetIsRooted(JSContext* cx, JSObject* obj, jsid, jsval* vp) {
|
||||
Handle* self = Unwrap(cx, obj);
|
||||
bool rooted = self ? self->mRooted : false;
|
||||
JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(rooted));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
SetIsRooted(JSContext* cx, JSObject* obj, jsid, jsval* vp) {
|
||||
Handle* self = Unwrap(cx, obj);
|
||||
JSBool v;
|
||||
if (!JS_ValueToBoolean(cx, *vp, &v))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!self) {
|
||||
if (v) {
|
||||
JS_ReportError(cx, "Cannot root invalidated handle.");
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (v)
|
||||
self->Root();
|
||||
else
|
||||
self->Unroot();
|
||||
|
||||
*vp = BOOLEAN_TO_JSVAL(v);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Invalidate(JSContext* cx, uintN argc, jsval* vp) {
|
||||
if (argc > 0) {
|
||||
@ -207,15 +278,10 @@ private:
|
||||
}
|
||||
|
||||
Handle* self = Unwrap(cx, JS_THIS_OBJECT(cx, vp));
|
||||
if (self) {
|
||||
JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_TRUE));
|
||||
if (!Send__delete__(self)) {
|
||||
JS_ReportError(cx, "Failed to send __delete__ while invalidating");
|
||||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_FALSE));
|
||||
}
|
||||
if (self)
|
||||
unused << Send__delete__(self);
|
||||
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -248,10 +314,13 @@ private:
|
||||
static void
|
||||
Finalize(JSContext* cx, JSObject* obj) {
|
||||
Handle* self = Unwrap(cx, obj);
|
||||
// Avoid warnings about unused return values:
|
||||
self && Send__delete__(self);
|
||||
if (self) {
|
||||
NS_ASSERTION(!self->mRooted, "Finalizing a rooted object?");
|
||||
self->mCx = NULL;
|
||||
self->mObj = NULL;
|
||||
unused << Send__delete__(self);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <class BaseType>
|
||||
@ -265,13 +334,14 @@ Handle<BaseType>::sHandle_JSClass = {
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
#define HANDLE_PROP_FLAGS (JSPROP_READONLY | JSPROP_PERMANENT)
|
||||
#define HANDLE_PROP_FLAGS (JSPROP_PERMANENT | JSPROP_SHARED)
|
||||
|
||||
template <class BaseType>
|
||||
const JSPropertySpec
|
||||
Handle<BaseType>::sHandle_Properties[] = {
|
||||
{ "parent", 0, HANDLE_PROP_FLAGS, GetParent, NULL },
|
||||
{ "isValid", 0, HANDLE_PROP_FLAGS, GetIsValid, NULL },
|
||||
{ "parent", 0, HANDLE_PROP_FLAGS | JSPROP_READONLY, GetParent, NULL },
|
||||
{ "isValid", 0, HANDLE_PROP_FLAGS | JSPROP_READONLY, GetIsValid, NULL },
|
||||
{ "isRooted", 0, HANDLE_PROP_FLAGS, GetIsRooted, SetIsRooted },
|
||||
{ 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -298,7 +298,7 @@ JetpackActorCommon::jsval_from_PrimVariant(JSContext* cx,
|
||||
|
||||
case PrimVariant::TPHandleParent: {
|
||||
JSObject* hobj =
|
||||
static_cast<const HandleParent*>(from.get_PHandleParent())->ToJSObject(cx);
|
||||
static_cast<HandleParent*>(from.get_PHandleParent())->ToJSObject(cx);
|
||||
if (!hobj)
|
||||
return false;
|
||||
*to = OBJECT_TO_JSVAL(hobj);
|
||||
@ -307,7 +307,7 @@ JetpackActorCommon::jsval_from_PrimVariant(JSContext* cx,
|
||||
|
||||
case PrimVariant::TPHandleChild: {
|
||||
JSObject* hobj =
|
||||
static_cast<const HandleChild*>(from.get_PHandleChild())->ToJSObject(cx);
|
||||
static_cast<HandleChild*>(from.get_PHandleChild())->ToJSObject(cx);
|
||||
if (!hobj)
|
||||
return false;
|
||||
*to = OBJECT_TO_JSVAL(hobj);
|
||||
|
@ -68,10 +68,13 @@ JetpackChild::sImplMethods[] = {
|
||||
JS_FN("registerReceiver", RegisterReceiver, 2, IMPL_METHOD_FLAGS),
|
||||
JS_FN("unregisterReceiver", UnregisterReceiver, 2, IMPL_METHOD_FLAGS),
|
||||
JS_FN("unregisterReceivers", UnregisterReceivers, 1, IMPL_METHOD_FLAGS),
|
||||
JS_FN("wrap", Wrap, 1, IMPL_METHOD_FLAGS),
|
||||
JS_FN("createHandle", CreateHandle, 0, IMPL_METHOD_FLAGS),
|
||||
JS_FN("createSandbox", CreateSandbox, 0, IMPL_METHOD_FLAGS),
|
||||
JS_FN("evalInSandbox", EvalInSandbox, 2, IMPL_METHOD_FLAGS),
|
||||
JS_FN("gc", GC, 0, IMPL_METHOD_FLAGS),
|
||||
#ifdef JS_GC_ZEAL
|
||||
JS_FN("gczeal", GCZeal, 1, IMPL_METHOD_FLAGS),
|
||||
#endif
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
@ -362,13 +365,6 @@ JetpackChild::UnregisterReceivers(JSContext* cx, uintN argc, jsval* vp)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JetpackChild::Wrap(JSContext* cx, uintN argc, jsval* vp)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("wrap not yet implemented (depends on bug 563010)");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JetpackChild::CreateHandle(JSContext* cx, uintN argc, jsval* vp)
|
||||
{
|
||||
@ -476,5 +472,27 @@ JetpackChild::ReportError(JSContext* cx, const char* message,
|
||||
sReportingError = false;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JetpackChild::GC(JSContext* cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JS_GC(cx);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
JSBool
|
||||
JetpackChild::GCZeal(JSContext* cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval* argv = JS_ARGV(cx, vp);
|
||||
|
||||
uint32 zeal;
|
||||
if (!JS_ValueToECMAUint32(cx, argv[0], &zeal))
|
||||
return JS_FALSE;
|
||||
|
||||
JS_SetGCZeal(cx, PRUint8(zeal));
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace jetpack
|
||||
} // namespace mozilla
|
||||
|
@ -86,10 +86,13 @@ private:
|
||||
static JSBool RegisterReceiver(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool UnregisterReceiver(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool UnregisterReceivers(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool Wrap(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool CreateHandle(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool CreateSandbox(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool EvalInSandbox(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool GC(JSContext* cx, uintN argc, jsval *vp);
|
||||
#ifdef JS_GC_ZEAL
|
||||
static JSBool GCZeal(JSContext* cx, uintN argc, jsval *vp);
|
||||
#endif
|
||||
|
||||
static void ReportError(JSContext* cx, const char* message,
|
||||
JSErrorReport* report);
|
||||
|
@ -38,15 +38,17 @@ function test_local_invalidation() {
|
||||
var parent = createHandle(),
|
||||
child = parent.createHandle();
|
||||
|
||||
do_check_true(child.invalidate());
|
||||
dump("test_local_invalidation\n");
|
||||
|
||||
child.invalidate();
|
||||
do_check_false(child.isValid);
|
||||
do_check_true(parent.isValid);
|
||||
|
||||
child = parent.createHandle();
|
||||
do_check_true(child.isValid);
|
||||
|
||||
do_check_true(parent.invalidate());
|
||||
do_check_false(parent.invalidate());
|
||||
parent.invalidate();
|
||||
parent.invalidate();
|
||||
do_check_false(child.isValid);
|
||||
do_check_false(parent.isValid);
|
||||
|
||||
@ -60,7 +62,7 @@ function test_local_invalidation() {
|
||||
do_check_eq(child.parent.parent, parent);
|
||||
do_check_true(child.parent.isValid);
|
||||
|
||||
do_check_true(child.parent.invalidate());
|
||||
child.parent.invalidate();
|
||||
do_check_false(child.isValid);
|
||||
do_check_true(parent.isValid);
|
||||
|
||||
@ -80,7 +82,7 @@ function test_long_parent_chain(len) {
|
||||
handle = handle.parent;
|
||||
|
||||
do_check_true(child.isValid);
|
||||
do_check_true(ancestor.invalidate());
|
||||
ancestor.invalidate();
|
||||
do_check_false(child.isValid);
|
||||
}
|
||||
|
||||
|
46
js/jetpack/tests/unit/head_jetpack.js
Normal file
46
js/jetpack/tests/unit/head_jetpack.js
Normal file
@ -0,0 +1,46 @@
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
function createJetpack(args)
|
||||
{
|
||||
var jp = Components.classes["@mozilla.org/jetpack/service;1"].
|
||||
getService(Components.interfaces.nsIJetpackService).
|
||||
createJetpack();
|
||||
|
||||
if (!args.skipRegisterCleanup)
|
||||
do_register_cleanup(function() {
|
||||
jp.destroy();
|
||||
});
|
||||
|
||||
if (!args.skipRegisterError)
|
||||
jp.registerReceiver("core:exception", function(msgName, e) {
|
||||
dump("Received exception from remote code: " + e + "\n");
|
||||
do_check_true(false);
|
||||
});
|
||||
|
||||
if (args.scriptFile)
|
||||
jp.evalScript(read_file(args.scriptFile));
|
||||
|
||||
return jp;
|
||||
}
|
||||
|
||||
const PR_RDONLY = 0x1;
|
||||
|
||||
function read_file(f)
|
||||
{
|
||||
var fis = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
fis.init(f, PR_RDONLY, 0444, Ci.nsIFileInputStream.CLOSE_ON_EOF);
|
||||
|
||||
var lis = Cc["@mozilla.org/intl/converter-input-stream;1"]
|
||||
.createInstance(Ci.nsIConverterInputStream);
|
||||
lis.init(fis, "UTF-8", 1024, 0);
|
||||
|
||||
var data = "";
|
||||
|
||||
var r = {};
|
||||
while (lis.readString(0x0FFFFFFF, r))
|
||||
data += r.value;
|
||||
|
||||
return data;
|
||||
}
|
5
js/jetpack/tests/unit/impl_rooting.js
Normal file
5
js/jetpack/tests/unit/impl_rooting.js
Normal file
@ -0,0 +1,5 @@
|
||||
registerReceiver("ReceiveGCHandle", function(name, handle) {
|
||||
handle.onInvalidate = function() {
|
||||
sendMessage("onInvalidateReceived", handle.isValid);
|
||||
};
|
||||
});
|
@ -1,8 +1,3 @@
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
var jps = Components.classes["@mozilla.org/jetpack/service;1"]
|
||||
.getService(Components.interfaces.nsIJetpackService);
|
||||
var jetpack = null;
|
||||
|
||||
load("handle_tests.js");
|
||||
@ -10,33 +5,13 @@ function createHandle() {
|
||||
return jetpack.createHandle();
|
||||
}
|
||||
|
||||
const PR_RDONLY = 0x1;
|
||||
|
||||
function read_file(f)
|
||||
{
|
||||
var fis = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
fis.init(f, PR_RDONLY, 0444, Ci.nsIFileInputStream.CLOSE_ON_EOF);
|
||||
|
||||
var lis = Cc["@mozilla.org/intl/converter-input-stream;1"]
|
||||
.createInstance(Ci.nsIConverterInputStream);
|
||||
lis.init(fis, "UTF-8", 1024, 0);
|
||||
|
||||
var data = "";
|
||||
|
||||
var r = {};
|
||||
while (lis.readString(0x0FFFFFFF, r))
|
||||
data += r.value;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
jetpack = jps.createJetpack();
|
||||
jetpack = createJetpack({
|
||||
skipRegisterError: true,
|
||||
scriptFile: do_get_file("impl.js")
|
||||
});
|
||||
run_handle_tests();
|
||||
|
||||
jetpack.evalScript(read_file(do_get_file("impl.js")));
|
||||
|
||||
var circ1 = {},
|
||||
circ2 = {},
|
||||
circ3 = {},
|
||||
@ -226,8 +201,4 @@ function run_test() {
|
||||
|
||||
jetpack.sendMessage("test sandbox");
|
||||
jetpack.sendMessage("throw");
|
||||
|
||||
do_register_cleanup(function() {
|
||||
jetpack.destroy();
|
||||
});
|
||||
}
|
||||
|
16
js/jetpack/tests/unit/test_rooting.js
Normal file
16
js/jetpack/tests/unit/test_rooting.js
Normal file
@ -0,0 +1,16 @@
|
||||
function run_test() {
|
||||
return;
|
||||
var jetpack = createJetpack({
|
||||
scriptFile: do_get_file("impl_rooting.js")
|
||||
});
|
||||
jetpack.registerReceiver("onInvalidateReceived", function(name, isValid) {
|
||||
do_check_false(isValid, "onInvalidateReceived: isValid");
|
||||
do_test_finished();
|
||||
});
|
||||
var gchandle = jetpack.createHandle();
|
||||
jetpack.sendMessage("ReceiveGCHandle", gchandle);
|
||||
gchandle.isRooted = false;
|
||||
gchandle = null;
|
||||
do_execute_soon(gc);
|
||||
do_test_pending();
|
||||
}
|
@ -1036,4 +1036,7 @@ event.h
|
||||
#ifdef MOZ_ENABLE_LIBPROXY
|
||||
proxy.h
|
||||
#endif
|
||||
#if MOZ_PLATFORM_MAEMO==6
|
||||
contentaction/contentaction.h
|
||||
#endif
|
||||
|
||||
|
@ -105,41 +105,41 @@ class JSWrapper : public js::JSProxyHandler {
|
||||
};
|
||||
|
||||
/* Base class for all cross compartment wrapper handlers. */
|
||||
class JSCrossCompartmentWrapper : public JSWrapper {
|
||||
class JS_FRIEND_API(JSCrossCompartmentWrapper) : public JSWrapper {
|
||||
public:
|
||||
JS_FRIEND_API(JSCrossCompartmentWrapper(uintN flags));
|
||||
JSCrossCompartmentWrapper(uintN flags);
|
||||
|
||||
virtual JS_FRIEND_API(~JSCrossCompartmentWrapper());
|
||||
virtual ~JSCrossCompartmentWrapper();
|
||||
|
||||
/* ES5 Harmony fundamental wrapper traps. */
|
||||
virtual JS_FRIEND_API(bool) getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
js::PropertyDescriptor *desc);
|
||||
virtual JS_FRIEND_API(bool) getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
js::PropertyDescriptor *desc);
|
||||
virtual JS_FRIEND_API(bool) defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
js::PropertyDescriptor *desc);
|
||||
virtual JS_FRIEND_API(bool) getOwnPropertyNames(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props);
|
||||
virtual JS_FRIEND_API(bool) delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
|
||||
virtual JS_FRIEND_API(bool) enumerate(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props);
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
js::PropertyDescriptor *desc);
|
||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
js::PropertyDescriptor *desc);
|
||||
virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
js::PropertyDescriptor *desc);
|
||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props);
|
||||
virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
|
||||
virtual bool enumerate(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props);
|
||||
|
||||
/* ES5 Harmony derived wrapper traps. */
|
||||
virtual JS_FRIEND_API(bool) has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
|
||||
virtual JS_FRIEND_API(bool) hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
|
||||
virtual JS_FRIEND_API(bool) get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, js::Value *vp);
|
||||
virtual JS_FRIEND_API(bool) set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, js::Value *vp);
|
||||
virtual JS_FRIEND_API(bool) enumerateOwn(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props);
|
||||
virtual JS_FRIEND_API(bool) iterate(JSContext *cx, JSObject *wrapper, uintN flags, js::Value *vp);
|
||||
virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
|
||||
virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
|
||||
virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, js::Value *vp);
|
||||
virtual bool set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, js::Value *vp);
|
||||
virtual bool enumerateOwn(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props);
|
||||
virtual bool iterate(JSContext *cx, JSObject *wrapper, uintN flags, js::Value *vp);
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual JS_FRIEND_API(bool) call(JSContext *cx, JSObject *wrapper, uintN argc, js::Value *vp);
|
||||
virtual JS_FRIEND_API(bool) construct(JSContext *cx, JSObject *wrapper,
|
||||
uintN argc, js::Value *argv, js::Value *rval);
|
||||
virtual JS_FRIEND_API(JSString *) obj_toString(JSContext *cx, JSObject *wrapper);
|
||||
virtual JS_FRIEND_API(JSString *) fun_toString(JSContext *cx, JSObject *wrapper, uintN indent);
|
||||
virtual bool call(JSContext *cx, JSObject *wrapper, uintN argc, js::Value *vp);
|
||||
virtual bool construct(JSContext *cx, JSObject *wrapper,
|
||||
uintN argc, js::Value *argv, js::Value *rval);
|
||||
virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper);
|
||||
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent);
|
||||
|
||||
static JS_FRIEND_API(bool) isCrossCompartmentWrapper(JSObject *obj);
|
||||
static bool isCrossCompartmentWrapper(JSObject *obj);
|
||||
|
||||
static JS_FRIEND_API(JSCrossCompartmentWrapper) singleton;
|
||||
static JSCrossCompartmentWrapper singleton;
|
||||
};
|
||||
|
||||
namespace js {
|
||||
|
@ -67,13 +67,12 @@ function run_test() {
|
||||
|
||||
do_check_true(scope2.XPCOMUtils == scope.XPCOMUtils);
|
||||
|
||||
// try on a new object using a file URL
|
||||
// try on a new object using the resolved URL
|
||||
var res = Components.classes["@mozilla.org/network/protocol;1?name=resource"]
|
||||
.getService(Components.interfaces.nsIResProtocolHandler);
|
||||
var resURI = res.newURI("resource://gre/modules/XPCOMUtils.jsm", null, null);
|
||||
dump("resURI: " + resURI + "\n");
|
||||
var filePath = res.resolveURI(resURI);
|
||||
do_check_eq(filePath.indexOf("file://"), 0);
|
||||
var scope3 = {};
|
||||
Components.utils.import(filePath, scope3);
|
||||
do_check_eq(typeof(scope3.XPCOMUtils), "object");
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user