Merge last PGO-green changeset of mozilla-inbound to mozilla-central

This commit is contained in:
Ed Morley 2012-02-02 10:22:32 +00:00
Родитель 71edb76c65 562b1a7223
Коммит 20833ba752
354 изменённых файлов: 9699 добавлений и 3311 удалений

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

@ -105,7 +105,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
roles::PUSHBUTTON,
kUseMapRole,
eNoValue,
eClickAction,
ePressAction,
eNoLiveAttr,
kNoReqStates,
eARIAPressed
@ -219,15 +219,6 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoLiveAttr,
kNoReqStates
},
{
"label",
roles::LABEL,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates
},
{
"link",
roles::LINK,

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

@ -78,6 +78,7 @@ enum EActionRule
eNoAction,
eActivateAction,
eClickAction,
ePressAction,
eCheckUncheckAction,
eExpandAction,
eJumpAction,

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

@ -1828,6 +1828,10 @@ nsAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
aName.AssignLiteral("click");
return NS_OK;
case ePressAction:
aName.AssignLiteral("press");
return NS_OK;
case eCheckUncheckAction:
if (states & states::CHECKED)
aName.AssignLiteral("uncheck");

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

@ -49,6 +49,15 @@
new scrollingChecker(getAccessible("bottom1"))
]
},
{ // jump again (test for bug 437607)
ID: "anchor1",
actionName: "jump",
actionIndex: 0,
events: CLICK_EVENTS,
eventSeq: [
new scrollingChecker(getAccessible("bottom1"))
]
},
{
ID: "anchor2",
actionName: "jump",

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

@ -27,7 +27,7 @@
},
{
ID: "button",
actionName: "click",
actionName: "press",
events: CLICK_EVENTS
},
{

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

@ -49,6 +49,22 @@ function currentTabDocument()
return currentBrowser().contentDocument;
}
/**
* Return browser element of the tab at the given index.
*/
function browserAt(aIndex)
{
return tabBrowser().getBrowserAtIndex(aIndex);
}
/**
* Return DOM document of the tab at the given index.
*/
function tabDocumentAt(aIndex)
{
return browserAt(aIndex).contentDocument;
}
/**
* Return input element of address bar.
*/

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

@ -82,6 +82,7 @@ _TEST_FILES =\
test_menu.xul \
test_mutation.html \
test_mutation.xhtml \
test_scroll.xul \
test_selection_aria.html \
test_selection.html \
test_selection.xul \

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

@ -1,13 +1,6 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<!-- Firefox tabbrowser -->
<?xml-stylesheet href="chrome://browser/content/browser.css"
type="text/css"?>
<!-- SeaMonkey tabbrowser -->
<?xml-stylesheet href="chrome://navigator/content/navigator.css"
type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
@ -16,7 +9,7 @@
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://browser/content/utilityOverlay.js"/>
src="chrome://mochikit/content/chrome-harness.js"/>
<script type="application/javascript"
src="../common.js" />
@ -26,95 +19,74 @@
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.js"/>
src="../browser.js"></script>
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Hacks to make xul:tabbrowser work
const Ci = Components.interfaces;
const CC = Components.classes;
Components.utils.import("resource://gre/modules/Services.jsm");
var handleDroppedLink = null;
var XULBrowserWindow = {
isBusy: false,
setOverLink: function (link, b) {
}
};
var gURLBar = {
focused: false
};
var gFindBarInitialized = false;
function goSetCommandEnabled() {}
////////////////////////////////////////////////////////////////////////////
// Tests
function getTabDocument()
function getAnchorJumpInTabDocument(aTabIdx)
{
return getNode("tabBrowser").selectedBrowser.contentDocument;
var tabDoc = aTabIdx ? tabDocumentAt(aTabIdx) : currentTabDocument();
return tabDoc.querySelector("a[name='link1']");
}
function getAnchorJumpInTabDocument()
function loadTab(aURL)
{
return getTabDocument().querySelector("a[name='link1']");
}
function loadTab(aTabBrowserID, aURL)
{
function loadTabChecker()
{
this.type = EVENT_REORDER;
this.match = function loadTabChecker_match(aEvent)
{
var target = aEvent.accessible;
if (target.role == ROLE_INTERNAL_FRAME &&
target.parent.parent == getAccessible(getNode(aTabBrowserID).mTabBox.tabpanels)) {
return true;
}
return false;
}
}
this.eventSeq = [ new loadTabChecker() ];
this.eventSeq = [
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new invokerChecker(EVENT_SCROLLING_START, getAnchorJumpInTabDocument)
];
this.invoke = function loadTab_invoke()
{
getNode(aTabBrowserID).loadURI(aURL);
tabBrowser().loadURI(aURL);
}
this.getID = function loadTab_getID()
{
return "load tab " + aURL + " for " + prettyName(aTabBrowserID);
return "load tab: " + aURL;
}
}
function advanceFocusIntoTab(aTabBrowserID)
function loadTabInBackground(aURL)
{
this.eventSeq = [
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, tabDocumentAt, 1)
];
this.unexpectedEventSeq = [
new invokerChecker(EVENT_SCROLLING_START, getAnchorJumpInTabDocument, 1)
];
this.invoke = function loadTabInBackground_invoke()
{
tabBrowser().loadOneTab(aURL, null, "", null, true);
}
this.getID = function loadTabInBackground_getID()
{
return "load tab in background: " + aURL;
}
}
function switchToBackgroundTab()
{
this.eventSeq = [
new focusChecker(getTabDocument),
new invokerChecker(EVENT_SCROLLING_START, getAnchorJumpInTabDocument)
];
this.invoke = function advanceFocusIntoTab_invoke()
this.invoke = function switchToBackgroundTab_invoke()
{
var tabDoc = getAccessible(getTabDocument());
tabDoc.takeFocus();
tabBrowser().selectTabAtIndex(1);
}
this.getID = function advanceFocusIntoTab_getID()
this.getID = function switchToBackgroundTab_getID()
{
return "advance focus into loaded tab";
return "switch to background tab";
}
}
@ -138,28 +110,22 @@
var url = rootDir + "scroll.html#link1";
gQueue = new eventQueue();
gQueue.push(new loadTab("tabBrowser", url));
gQueue.push(new advanceFocusIntoTab("tabBrowser"));
gQueue.push(new loadTab(url));
gQueue.push(new loadTabInBackground(url));
gQueue.push(new switchToBackgroundTab());
gQueue.onFinish = function() { closeBrowserWindow(); }
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
openBrowserWindow(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<vbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=437607"
title="Clicking the 'Skip to main content' link once works, second time fails to initiate a V cursor jump">
Mozilla Bug 437607
</a><br/>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=519303"
title="Same page links to targets with content fires scrolling start accessible event on leaf text node">
Mozilla Bug 519303
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=691734"
title="Make sure scrolling start event is fired when document receive focus">
@ -173,33 +139,6 @@
</pre>
</body>
<vbox flex="1">
<!-- Hack to make xul:tabbrowser work -->
<menubar>
<menu label="menu">
<menupopup>
<menuitem label="close window hook" id="menu_closeWindow"/>
<menuitem label="close hook" id="menu_close"/>
</menupopup>
</menu>
</menubar>
<keyset>
<key id="key_close"/>
</keyset>
<hbox>
<tabs id="tabbrowser-tabs" class="tabbrowser-tabs"
tabbrowser="tabBrowser"
flex="1">
<tab class="tabbrowser-tab" selected="true" label="tab"/>
</tabs>
</hbox>
<tabbrowser id="tabBrowser"
type="content-primary"
tabcontainer="tabbrowser-tabs"
flex="1"/>
</vbox>
<toolbar id="addon-bar"/>
</hbox>
<vbox id="eventdump"></vbox>
</vbox>
</window>

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

@ -131,7 +131,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=529289
<tr><td>hi<td></tr></table>
<!-- test gEmptyRoleMap -->
<table role="label">
<table role="button">
<tr>
<td id="cell">cell</td>
</tr>

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

@ -37,15 +37,15 @@
testChildAtPoint(txt, -10000, 10000, false, null);
testChildAtPoint(txt, -10000, 10000, true, null);
// Not specific case, point is inside of label accessible.
var label = getAccessible("label");
var labelText = label.firstChild;
testChildAtPoint(label, 1, 1, false, labelText);
testChildAtPoint(label, 1, 1, true, labelText);
// Not specific case, point is inside of btn accessible.
var btn = getAccessible("btn");
var btnText = btn.firstChild;
testChildAtPoint(btn, 1, 1, false, btnText);
testChildAtPoint(btn, 1, 1, true, btnText);
// Not specific case, point is outside of label accessible.
testChildAtPoint(label, -1, 1, false, null);
testChildAtPoint(label, -1, 1, true, null);
// Not specific case, point is outside of btn accessible.
testChildAtPoint(btn, -1, 1, false, null);
testChildAtPoint(btn, -1, 1, true, null);
// Out of flow accessible testing, do not return out of flow accessible
// because it's not a child of the accessible even visually it is.
@ -78,7 +78,7 @@
<div role="listitem" id="listitem"><span role="image" id="image">img</span>item</div>
</div>
<span role="label">label1</span><span role="label" id="label">label2</span>
<span role="button">button1</span><span role="button" id="btn">button2</span>
<span role="textbox">textbox1</span><span role="textbox" id="txt">textbox2</span>

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

@ -38,7 +38,6 @@
#filter substitution
pref("toolkit.defaultChromeURI", "chrome://browser/content/shell.xul");
pref("general.useragent.compatMode.firefox", true);
pref("browser.chromeURL", "chrome://browser/content/");
#ifdef MOZ_OFFICIAL_BRANDING
pref("browser.homescreenURL", "file:///system/home/homescreen.html");
@ -394,6 +393,15 @@ pref("layers.acceleration.force-enabled", true);
pref("dom.screenEnabledProperty.enabled", true);
pref("dom.screenBrightnessProperty.enabled", true);
// handle links targeting new windows
// 1=current window/tab, 2=new window, 3=new tab in most recent window
pref("browser.link.open_newwindow", 3);
// 0: no restrictions - divert everything
// 1: don't divert window.open at all
// 2: don't divert window.open with features
pref("browser.link.open_newwindow.restriction", 0);
// Enable browser frame
pref("dom.mozBrowserFramesEnabled", true);
pref("dom.mozBrowserFramesWhitelist", "http://localhost:6666");
@ -401,6 +409,7 @@ pref("dom.mozBrowserFramesWhitelist", "http://localhost:6666");
// Temporary permission hack for WebSMS
pref("dom.sms.enabled", true);
pref("dom.sms.whitelist", "file://,http://localhost:6666");
// Ignore X-Frame-Options headers.
pref("b2g.ignoreXFrameOptions", true);

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

@ -47,18 +47,16 @@ const LocalFile = CC('@mozilla.org/file/local;1',
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
XPCOMUtils.defineLazyGetter(Services, 'env', function() {
return Cc['@mozilla.org/process/environment;1']
.getService(Ci.nsIEnvironment);
});
XPCOMUtils.defineLazyGetter(Services, 'ss', function() {
return Cc['@mozilla.org/content/style-sheet-service;1']
.getService(Ci.nsIStyleSheetService);
});
XPCOMUtils.defineLazyGetter(Services, 'fm', function() {
return Cc['@mozilla.org/focus-manager;1']
.getService(Ci.nsIFocusManager);
});
// In order to use http:// scheme instead of file:// scheme
// (that is much more restricted) the following code kick-off
@ -76,7 +74,7 @@ function startupHttpd(baseDir, port) {
// FIXME Bug 707625
// until we have a proper security model, add some rights to
// the pre-installed web applications
// the pre-installed web applications
function addPermissions(urls) {
let permissions = [
'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app'
@ -84,7 +82,7 @@ function addPermissions(urls) {
urls.forEach(function(url) {
let uri = Services.io.newURI(url, null, null);
let allow = Ci.nsIPermissionManager.ALLOW_ACTION;
permissions.forEach(function(permission) {
Services.perms.add(uri, permission, allow);
});
@ -96,9 +94,9 @@ var shell = {
// FIXME/bug 678695: this should be a system setting
preferredScreenBrightness: 1.0,
get home() {
delete this.home;
return this.home = document.getElementById('homescreen');
get contentBrowser() {
delete this.contentBrowser;
return this.contentBrowser = document.getElementById('homescreen');
},
get homeURL() {
@ -131,7 +129,7 @@ var shell = {
window.controllers.appendController(this);
window.addEventListener('keypress', this);
window.addEventListener('MozApplicationManifest', this);
this.home.addEventListener('load', this, true);
this.contentBrowser.addEventListener('load', this, true);
try {
Services.io.offline = false;
@ -156,7 +154,15 @@ var shell = {
return alert(msg);
}
let browser = this.home;
// Load webapi+apps.js as a frame script
let frameScriptUrl = 'chrome://browser/content/webapi.js';
try {
messageManager.loadFrameScript(frameScriptUrl, true);
} catch (e) {
dump('Error when loading ' + frameScriptUrl + ' as a frame script: ' + e + '\n');
}
let browser = this.contentBrowser;
browser.homePage = homeURL;
browser.goHome();
},
@ -187,7 +193,7 @@ var shell = {
doCommand: function shell_doCommand(cmd) {
switch (cmd) {
case 'cmd_close':
this.home.contentWindow.postMessage('appclose', '*');
content.postMessage('appclose', '*');
break;
}
},
@ -197,7 +203,7 @@ var shell = {
case 'keypress':
switch (evt.keyCode) {
case evt.DOM_VK_HOME:
this.sendEvent(this.home.contentWindow, 'home');
this.sendEvent(content, 'home');
break;
case evt.DOM_VK_SLEEP:
this.toggleScreen();
@ -205,7 +211,7 @@ var shell = {
let details = {
'enabled': screen.mozEnabled
};
this.sendEvent(this.home.contentWindow, 'sleep', details);
this.sendEvent(content, 'sleep', details);
break;
case evt.DOM_VK_ESCAPE:
if (evt.defaultPrevented)
@ -215,8 +221,12 @@ var shell = {
}
break;
case 'load':
this.home.removeEventListener('load', this, true);
this.contentBrowser.removeEventListener('load', this, true);
this.turnScreenOn();
let chromeWindow = window.QueryInterface(Ci.nsIDOMChromeWindow);
chromeWindow.browserDOMWindow = new nsBrowserAccess();
this.sendEvent(window, 'ContentStart');
break;
case 'MozApplicationManifest':
@ -229,7 +239,7 @@ var shell = {
if (!documentElement)
return;
let manifest = documentElement.getAttribute("manifest");
let manifest = documentElement.getAttribute('manifest');
if (!manifest)
return;
@ -273,78 +283,38 @@ var shell = {
turnScreenOn: function shell_turnScreenOn() {
screen.mozEnabled = true;
screen.mozBrightness = this.preferredScreenBrightness;
},
};
(function VirtualKeyboardManager() {
let activeElement = null;
let isKeyboardOpened = false;
let constructor = {
handleEvent: function vkm_handleEvent(evt) {
let contentWindow = shell.home.contentWindow.wrappedJSObject;
switch (evt.type) {
case 'ContentStart':
contentWindow.navigator.mozKeyboard = new MozKeyboard();
break;
case 'keypress':
if (evt.keyCode != evt.DOM_VK_ESCAPE || !isKeyboardOpened)
return;
shell.sendEvent(contentWindow, 'hideime');
isKeyboardOpened = false;
evt.preventDefault();
evt.stopPropagation();
break;
case 'mousedown':
if (evt.target != activeElement || isKeyboardOpened)
return;
let type = activeElement.type;
shell.sendEvent(contentWindow, 'showime', { type: type });
isKeyboardOpened = true;
break;
}
},
observe: function vkm_observe(subject, topic, data) {
let contentWindow = shell.home.contentWindow;
let shouldOpen = parseInt(data);
if (shouldOpen && !isKeyboardOpened) {
activeElement = Services.fm.focusedElement;
if (!activeElement)
return;
let type = activeElement.type;
shell.sendEvent(contentWindow, 'showime', { type: type });
} else if (!shouldOpen && isKeyboardOpened) {
shell.sendEvent(contentWindow, 'hideime');
}
isKeyboardOpened = shouldOpen;
}
};
Services.obs.addObserver(constructor, 'ime-enabled-state-changed', false);
['ContentStart', 'keypress', 'mousedown'].forEach(function vkm_events(type) {
window.addEventListener(type, constructor, true);
});
})();
function MozKeyboard() {
}
MozKeyboard.prototype = {
sendKey: function mozKeyboardSendKey(keyCode, charCode) {
charCode = (charCode == undefined) ? keyCode : charCode;
var utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
['keydown', 'keypress', 'keyup'].forEach(function sendKeyEvents(type) {
utils.sendKeyEvent(type, keyCode, charCode, null);
});
}
};
function nsBrowserAccess() {
}
nsBrowserAccess.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow]),
openURI: function openURI(uri, opener, where, context) {
// TODO This should be replaced by an 'open-browser-window' intent
let contentWindow = content.wrappedJSObject;
if (!('getApplicationManager' in contentWindow))
return null;
let applicationManager = contentWindow.getApplicationManager();
if (!applicationManager)
return null;
let url = uri ? uri.spec : 'about:blank';
let window = applicationManager.launch(url, where);
return window.contentWindow;
},
openURIInFrame: function openURIInFrame(uri, opener, where, context) {
throw new Error('Not Implemented');
},
isTabContentWindow: function isTabContentWindow(contentWindow) {
return contentWindow == window;
}
};

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

@ -66,12 +66,12 @@
events: ['mousedown', 'mousemove', 'mouseup', 'click', 'unload'],
start: function teh_start() {
this.events.forEach((function(evt) {
shell.home.addEventListener(evt, this, true);
shell.contentBrowser.addEventListener(evt, this, true);
}).bind(this));
},
stop: function teh_stop() {
this.events.forEach((function(evt) {
shell.home.removeEventListener(evt, this, true);
shell.contentBrowser.removeEventListener(evt, this, true);
}).bind(this));
},
handleEvent: function teh_handleEvent(evt) {
@ -139,12 +139,7 @@
return;
case 'click':
if (!isNewTouchAction) {
debug('click: cancel');
evt.preventDefault();
evt.stopPropagation();
} else {
if (isNewTouchAction) {
// Mouse events has been cancelled so dispatch a sequence
// of events to where touchend has been fired
if (preventMouseEvents) {

1791
b2g/chrome/content/webapi.js Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -9,6 +9,7 @@ chrome.jar:
content/touch.js (content/touch.js)
content/commandUtil.js (content/commandUtil.js)
content/httpd.js (content/httpd.js)
content/webapi.js (content/webapi.js)
content/content.css (content/content.css)
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml

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

@ -38,7 +38,8 @@
MOZ_APP_BASENAME=B2G
MOZ_APP_VENDOR=Mozilla
MOZ_APP_VERSION=11.0a1
MOZ_APP_VERSION=13.0a1
MOZ_APP_UA_NAME=Firefox
MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official

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

@ -68,6 +68,18 @@ var gSetBackground = {
if (this._screenWidth / this._screenHeight >= 1.6)
document.getElementById("monitor").setAttribute("aspectratio", "16:10");
#ifdef XP_WIN
// hide fill + fit options if <win7 since don't work
var version = Components.classes["@mozilla.org/system-info;1"]
.getService(Ci.nsIPropertyBag2)
.getProperty("version");
var isWindows7OrHigher = (parseFloat(version) >= 6.1);
if (!isWindows7OrHigher) {
document.getElementById("fillPosition").hidden = true;
document.getElementById("fitPosition").hidden = true;
}
#endif
// make sure that the correct dimensions will be used
setTimeout(function(self) {
self.init(window.arguments[0]);
@ -198,6 +210,39 @@ var gSetBackground = {
var x = (this._screenWidth - this._image.naturalWidth) / 2;
var y = (this._screenHeight - this._image.naturalHeight) / 2;
ctx.drawImage(this._image, x, y);
break;
case "FILL":
//Try maxing width first, overflow height
var widthRatio = this._screenWidth / this._image.naturalWidth;
var width = this._image.naturalWidth * widthRatio;
var height = this._image.naturalHeight * widthRatio;
if (height < this._screenHeight) {
//height less than screen, max height and overflow width
var heightRatio = this._screenHeight / this._image.naturalHeight;
width = this._image.naturalWidth * heightRatio;
height = this._image.naturalHeight * heightRatio;
}
var x = (this._screenWidth - width) / 2;
var y = (this._screenHeight - height) / 2;
ctx.drawImage(this._image, x, y, width, height);
break;
case "FIT":
//Try maxing width first, top and bottom borders
var widthRatio = this._screenWidth / this._image.naturalWidth;
var width = this._image.naturalWidth * widthRatio;
var height = this._image.naturalHeight * widthRatio;
var x = 0;
var y = (this._screenHeight - height) / 2;
if (height > this._screenHeight) {
//height overflow, maximise height, side borders
var heightRatio = this._screenHeight / this._image.naturalHeight;
width = this._image.naturalWidth * heightRatio;
height = this._image.naturalHeight * heightRatio;
x = (this._screenWidth - width) / 2;
y = 0;
}
ctx.drawImage(this._image, x, y, width, height);
break;
}
}
};

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

@ -78,6 +78,8 @@
<menuitem label="&center.label;" value="CENTER"/>
<menuitem label="&tile.label;" value="TILE"/>
<menuitem label="&stretch.label;" value="STRETCH"/>
<menuitem label="&fill.label;" value="FILL" id="fillPosition"/>
<menuitem label="&fit.label;" value="FIT" id="fitPosition"/>
</menupopup>
</menulist>
<spacer flex="1"/>

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

@ -81,6 +81,7 @@ interface nsIShellService : nsISupports
const long BACKGROUND_STRETCH = 2;
const long BACKGROUND_CENTER = 3;
const long BACKGROUND_FILL = 4;
const long BACKGROUND_FIT = 5;
/**
* Sets the desktop background image using either the HTML <IMG>

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

@ -427,6 +427,10 @@ nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement,
options.Assign("wallpaper");
else if (aPosition == BACKGROUND_STRETCH)
options.Assign("stretched");
else if (aPosition == BACKGROUND_FILL)
options.Assign("zoom");
else if (aPosition == BACKGROUND_FIT)
options.Assign("scaled");
else
options.Assign("centered");

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

@ -640,6 +640,14 @@ nsWindowsShellService::SetDesktopBackground(nsIDOMElement* aElement,
style.AssignLiteral("2");
tile.AssignLiteral("0");
break;
case BACKGROUND_FILL:
style.AssignLiteral("10");
tile.AssignLiteral("0");
break;
case BACKGROUND_FIT:
style.AssignLiteral("6");
tile.AssignLiteral("0");
break;
}
rv = regKey->WriteStringValue(NS_LITERAL_STRING("TileWallpaper"), tile);

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

@ -52,7 +52,8 @@ function onPageLoad() {
checkWallpaper(Ci.nsIShellService.BACKGROUND_TILE, "wallpaper");
checkWallpaper(Ci.nsIShellService.BACKGROUND_STRETCH, "stretched");
checkWallpaper(Ci.nsIShellService.BACKGROUND_CENTER, "centered");
checkWallpaper(Ci.nsIShellService.BACKGROUND_FILL, "centered");
checkWallpaper(Ci.nsIShellService.BACKGROUND_FILL, "zoom");
checkWallpaper(Ci.nsIShellService.BACKGROUND_FIT, "scaled");
// Restore GConf and wallpaper

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

@ -2,6 +2,8 @@
<!ENTITY tile.label "Tile">
<!ENTITY center.label "Center">
<!ENTITY stretch.label "Stretch">
<!ENTITY fill.label "Fill">
<!ENTITY fit.label "Fit">
<!ENTITY preview.label "Preview">
<!ENTITY color.label "Color:">
<!ENTITY setDesktopBackground.title "Set Desktop Background">

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

@ -14,8 +14,10 @@ class DeviceManagerADB(DeviceManager):
self.retries = 0
self._sock = None
self.useRunAs = False
self.haveRoot = False
self.useZip = False
self.packageName = None
self.tempDir = None
if packageName == None:
if os.getenv('USER'):
packageName = 'org.mozilla.fennec_' + os.getenv('USER')
@ -36,18 +38,30 @@ class DeviceManagerADB(DeviceManager):
self.verifyZip()
except:
self.useZip = False
try:
def verifyRoot():
# a test to see if we have root privs
files = self.listFiles("/data/data")
if (len(files) == 1):
if (files[0].find("Permission denied") != -1):
print "NOT running as root"
raise Exception("not running as root")
self.haveRoot = True
try:
verifyRoot()
except:
try:
self.checkCmd(["root"])
# The root command does not fail even if ADB cannot get
# root rights (e.g. due to production builds), so we have
# to check again ourselves that we have root now.
verifyRoot()
except:
print "restarting as root failed"
if (self.useRunAs):
print "restarting as root failed, but run-as available"
else:
print "restarting as root failed"
# external function
# returns:
@ -58,9 +72,12 @@ class DeviceManagerADB(DeviceManager):
if (os.name == "nt"):
destname = destname.replace('\\', '/')
if (self.useRunAs):
remoteTmpFile = self.tmpDir + "/" + os.path.basename(localname)
remoteTmpFile = self.getTempDir() + "/" + os.path.basename(localname)
self.checkCmd(["push", os.path.realpath(localname), remoteTmpFile])
self.checkCmdAs(["shell", "cp", remoteTmpFile, destname])
if self.useDDCopy:
self.checkCmdAs(["shell", "dd", "if=" + remoteTmpFile, "of=" + destname])
else:
self.checkCmdAs(["shell", "cp", remoteTmpFile, destname])
self.checkCmd(["shell", "rm", remoteTmpFile])
else:
self.checkCmd(["push", os.path.realpath(localname), destname])
@ -329,7 +346,26 @@ class DeviceManagerADB(DeviceManager):
# TODO: add debug flags and allow for printing stdout
# self.runCmd(["pull", remoteFile, localFile])
try:
self.runCmd(["pull", remoteFile, localFile]).stdout.read()
# First attempt to pull file regularly
outerr = self.runCmd(["pull", remoteFile, localFile]).communicate()
# Now check stderr for errors
errl = outerr[1].splitlines()
if (len(errl) == 1):
if (((errl[0].find("Permission denied") != -1)
or (errl[0].find("does not exist") != -1))
and self.useRunAs):
# If we lack permissions to read but have run-as, then we should try
# to copy the file to a world-readable location first before attempting
# to pull it again.
remoteTmpFile = self.getTempDir() + "/" + os.path.basename(remoteFile)
self.checkCmdAs(["shell", "dd", "if=" + remoteFile, "of=" + remoteTmpFile])
self.checkCmdAs(["shell", "chmod", "777", remoteTmpFile])
self.runCmd(["pull", remoteTmpFile, localFile]).stdout.read()
# Clean up temporary file
self.checkCmdAs(["shell", "rm", remoteTmpFile])
f = open(localFile)
ret = f.read()
f.close()
@ -422,6 +458,23 @@ class DeviceManagerADB(DeviceManager):
self.mkDir(testRoot)
return testRoot
# Gets the temporary directory we are using on this device
# base on our device root, ensuring also that it exists.
#
# internal function
# returns:
# success: path for temporary directory
# failure: None
def getTempDir(self):
# Cache result to speed up operations depending
# on the temporary directory.
if self.tempDir == None:
self.tempDir = self.getDeviceRoot() + "/tmp"
if (not self.dirExists(self.tempDir)):
return self.mkDir(self.tempDir)
return self.tempDir
# Either we will have /tests/fennec or /tests/firefox but we will never have
# both. Return the one that exists
# TODO: ensure we can support org.mozilla.firefox
@ -543,6 +596,11 @@ class DeviceManagerADB(DeviceManager):
return ret
def runCmd(self, args):
# If we are not root but have run-as, and we're trying to execute
# a shell command then using run-as is the best we can do
if (not self.haveRoot and self.useRunAs and args[0] == "shell" and args[1] != "run-as"):
args.insert(1, "run-as")
args.insert(2, self.packageName)
args.insert(0, "adb")
return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -553,6 +611,11 @@ class DeviceManagerADB(DeviceManager):
return self.runCmd(args)
def checkCmd(self, args):
# If we are not root but have run-as, and we're trying to execute
# a shell command then using run-as is the best we can do
if (not self.haveRoot and self.useRunAs and args[0] == "shell" and args[1] != "run-as"):
args.insert(1, "run-as")
args.insert(2, self.packageName)
args.insert(0, "adb")
return subprocess.check_call(args)
@ -591,6 +654,11 @@ class DeviceManagerADB(DeviceManager):
if (re.search('Usage', data)):
return True
else:
data = self.runCmd(["shell", "dd", "-"]).stdout.read()
if (re.search('unknown operand', data)):
print "'cp' not found, but 'dd' was found as a replacement"
self.useDDCopy = True
return True
print "unable to execute 'cp' on device; consider installing busybox from Android Market"
return False
@ -605,12 +673,14 @@ class DeviceManagerADB(DeviceManager):
self.useRunAs = False
devroot = self.getDeviceRoot()
if (packageName and self.isCpAvailable() and devroot):
self.tmpDir = devroot + "/tmp"
if (not self.dirExists(self.tmpDir)):
self.mkDir(self.tmpDir)
tmpDir = self.getTempDir()
self.checkCmd(["shell", "run-as", packageName, "mkdir", devroot + "/sanity"])
self.checkCmd(["push", os.path.abspath(sys.argv[0]), self.tmpDir + "/tmpfile"])
self.checkCmd(["shell", "run-as", packageName, "cp", self.tmpDir + "/tmpfile", devroot + "/sanity"])
self.checkCmd(["push", os.path.abspath(sys.argv[0]), tmpDir + "/tmpfile"])
if self.useDDCopy:
self.checkCmd(["shell", "run-as", packageName, "dd", "if=" + tmpDir + "/tmpfile", "of=" + devroot + "/sanity/tmpfile"])
else:
self.checkCmd(["shell", "run-as", packageName, "cp", tmpDir + "/tmpfile", devroot + "/sanity"])
if (self.fileExists(devroot + "/sanity/tmpfile")):
print "will execute commands via run-as " + packageName
self.packageName = packageName

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

@ -134,11 +134,15 @@ public class FennecNativeDriver implements Driver {
private void getGeckoInfo() {
View geckoLayout = activity.findViewById(Integer.decode((String)locators.get("gecko_layout")));
if (geckoLayout != null) {
geckoTop = geckoLayout.getTop();
geckoLeft = geckoLayout.getLeft();
int[] pos = new int[2];
geckoLayout.getLocationOnScreen(pos);
geckoTop = pos[1];
geckoLeft = pos[0];
geckoWidth = geckoLayout.getWidth();
geckoHeight = geckoLayout.getHeight();
geckoInfo = true;
} else {
throw new RoboCopException("Unable to find view gecko_layout");
}
}

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

@ -160,6 +160,7 @@ MOZ_ZIPWRITER = @MOZ_ZIPWRITER@
MOZ_OGG = @MOZ_OGG@
MOZ_RAW = @MOZ_RAW@
MOZ_SYDNEYAUDIO = @MOZ_SYDNEYAUDIO@
MOZ_CUBEB = @MOZ_CUBEB@
MOZ_WAVE = @MOZ_WAVE@
MOZ_MEDIA = @MOZ_MEDIA@
MOZ_VORBIS = @MOZ_VORBIS@

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

@ -1050,4 +1050,5 @@ tremor/ivorbiscodec.h
ogg/ogg.h
ogg/os_types.h
nestegg/nestegg.h
cubeb/cubeb.h
#endif

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

@ -460,6 +460,9 @@ case "$target" in
if test -z "$ANDROID_PACKAGE_NAME" ; then
ANDROID_PACKAGE_NAME='org.mozilla.$(MOZ_APP_NAME)'
fi
if test -z "$MOZ_MOBILE_COMPAT" ; then
MOZ_MOBILE_COMPAT='All'
fi
AC_DEFINE(ANDROID)
AC_DEFINE_UNQUOTED(ANDROID_VERSION, $android_version)
@ -481,6 +484,7 @@ AC_SUBST(ANDROID_PLATFORM)
AC_SUBST(ANDROID_SDK)
AC_SUBST(ANDROID_PLATFORM_TOOLS)
AC_SUBST(ANDROID_PACKAGE_NAME)
AC_SUBST(MOZ_MOBILE_COMPAT)
AC_SUBST(OBJCOPY)
dnl ========================================================
@ -4582,6 +4586,7 @@ MOZ_AUTH_EXTENSION=1
MOZ_OGG=1
MOZ_RAW=
MOZ_SYDNEYAUDIO=
MOZ_CUBEB=
MOZ_VORBIS=
MOZ_TREMOR=
MOZ_WAVE=1
@ -5592,6 +5597,7 @@ MOZ_ARG_DISABLE_BOOL(ogg,
if test -n "$MOZ_OGG"; then
AC_DEFINE(MOZ_OGG)
MOZ_SYDNEYAUDIO=1
MOZ_CUBEB=1
MOZ_MEDIA=1
case "$target_cpu" in
arm*)
@ -5709,6 +5715,7 @@ AC_SUBST(MOZ_LIBVPX_LIBS)
if test -n "$MOZ_WEBM" -a -z "$MOZ_NATIVE_LIBVPX"; then
MOZ_SYDNEYAUDIO=1
MOZ_CUBEB=1
MOZ_MEDIA=1
case "$target_cpu" in
arm*)
@ -5820,17 +5827,29 @@ MOZ_ARG_DISABLE_BOOL(wave,
if test -n "$MOZ_WAVE"; then
AC_DEFINE(MOZ_WAVE)
MOZ_SYDNEYAUDIO=1
MOZ_CUBEB=1
MOZ_MEDIA=1
fi
dnl ========================================================
dnl = Handle dependent SYDNEYAUDIO and MEDIA defines
dnl = Handle dependent SYDNEYAUDIO, CUBEB, and MEDIA defines
dnl ========================================================
if test -n "$MOZ_SYDNEYAUDIO"; then
AC_DEFINE(MOZ_SYDNEYAUDIO)
fi
if test -n "$MOZ_CUBEB"; then
case "$target" in
*-mingw*)
AC_DEFINE(MOZ_CUBEB)
;;
*)
dnl Other targets will be enabled soon.
;;
esac
fi
if test -n "$MOZ_MEDIA"; then
AC_DEFINE(MOZ_MEDIA)
fi
@ -8692,6 +8711,7 @@ AC_SUBST(MOZ_APP_EXTRA_LIBS)
AC_SUBST(MOZ_MEDIA)
AC_SUBST(MOZ_SYDNEYAUDIO)
AC_SUBST(MOZ_CUBEB)
AC_SUBST(MOZ_WAVE)
AC_SUBST(MOZ_VORBIS)
AC_SUBST(MOZ_TREMOR)

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

@ -1617,6 +1617,8 @@ public:
}
}
virtual size_t SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const = 0;
private:
PRUint64 mWarnedAbout;

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

@ -9140,3 +9140,18 @@ nsDocument::GetMozVisibilityState(nsAString& aState)
aState.AssignASCII(states[mVisibilityState]);
return NS_OK;
}
static size_t
SizeOfStyleSheetsElementIncludingThis(nsIStyleSheet* aStyleSheet,
nsMallocSizeOfFun aMallocSizeOf,
void* aData)
{
return aStyleSheet->SizeOfIncludingThis(aMallocSizeOf);
}
/* virtual */ size_t
nsDocument::SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const
{
return mStyleSheets.SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
aMallocSizeOf);
}

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

@ -991,6 +991,8 @@ public:
// Posts an event to call UpdateVisibilityState
virtual void PostVisibilityUpdateEvent();
virtual size_t SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const;
protected:
friend class nsNodeUtils;

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

@ -866,8 +866,6 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope)
nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
JS_SetNativeStackQuota(cx, 128 * sizeof(size_t) * 1024);
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS);
JS_SetVersion(cx, JSVERSION_LATEST);
JS_SetErrorReporter(cx, ContentScriptErrorReporter);

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

@ -91,9 +91,9 @@ using namespace mozilla;
#define TRUE_OR_FAIL_WEBSOCKET(x, ret) \
PR_BEGIN_MACRO \
if (NS_UNLIKELY(!(x))) { \
NS_WARNING("ENSURE_TRUE_AND_FAIL_IF_FAILED(" #x ") failed"); \
FailConnection(); \
return ret; \
NS_WARNING("ENSURE_TRUE_AND_FAIL_IF_FAILED(" #x ") failed"); \
FailConnection(nsIWebSocketChannel::CLOSE_INTERNAL_ERROR); \
return ret; \
} \
PR_END_MACRO
@ -102,7 +102,7 @@ using namespace mozilla;
nsresult __rv = res; \
if (NS_FAILED(__rv)) { \
NS_ENSURE_SUCCESS_BODY(res, ret) \
FailConnection(); \
FailConnection(nsIWebSocketChannel::CLOSE_INTERNAL_ERROR); \
return ret; \
} \
PR_END_MACRO
@ -159,7 +159,8 @@ nsWebSocket::PrintErrorOnConsole(const char *aBundleURI,
// when this is called the browser side wants no more part of it
nsresult
nsWebSocket::CloseConnection()
nsWebSocket::CloseConnection(PRUint16 aReasonCode,
const nsACString& aReasonString)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
if (mDisconnected)
@ -172,7 +173,7 @@ nsWebSocket::CloseConnection()
if (mReadyState == nsIWebSocket::CONNECTING) {
SetReadyState(nsIWebSocket::CLOSED);
if (mChannel) {
mChannel->Close(mClientReasonCode, mClientReason);
mChannel->Close(aReasonCode, aReasonString);
}
Disconnect();
return NS_OK;
@ -186,7 +187,7 @@ nsWebSocket::CloseConnection()
return NS_OK;
}
return mChannel->Close(mClientReasonCode, mClientReason);
return mChannel->Close(aReasonCode, aReasonString);
}
nsresult
@ -219,12 +220,13 @@ nsWebSocket::ConsoleError()
nsresult
nsWebSocket::FailConnection()
nsWebSocket::FailConnection(PRUint16 aReasonCode,
const nsACString& aReasonString)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
ConsoleError();
nsresult rv = CloseConnection();
nsresult rv = CloseConnection(aReasonCode, aReasonString);
NS_ENSURE_SUCCESS(rv, rv);
rv = CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("error"));
@ -322,7 +324,7 @@ nsWebSocket::OnStop(nsISupports *aContext, nsresult aStatusCode)
if (mDisconnected)
return NS_OK;
mClosedCleanly = NS_SUCCEEDED(aStatusCode);
mCloseEventWasClean = NS_SUCCEEDED(aStatusCode);
if (aStatusCode == NS_BASE_STREAM_CLOSED &&
mReadyState >= nsIWebSocket::CLOSING) {
@ -360,10 +362,16 @@ nsWebSocket::OnServerClose(nsISupports *aContext, PRUint16 aCode,
const nsACString &aReason)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
mServerReasonCode = aCode;
CopyUTF8toUTF16(aReason, mServerReason);
CloseConnection(); /* reciprocate! */
// store code/string for onclose DOM event
mCloseEventCode = aCode;
CopyUTF8toUTF16(aReason, mCloseEventReason);
// Send reciprocal Close frame.
// 5.5.1: "When sending a Close frame in response, the endpoint typically
// echos the status code it received"
CloseConnection(aCode, aReason);
return NS_OK;
}
@ -406,10 +414,9 @@ nsWebSocket::GetInterface(const nsIID &aIID, void **aResult)
nsWebSocket::nsWebSocket() : mKeepingAlive(false),
mCheckMustKeepAlive(true),
mTriggeredCloseEvent(false),
mClosedCleanly(false),
mDisconnected(false),
mClientReasonCode(0),
mServerReasonCode(nsIWebSocketChannel::CLOSE_ABNORMAL),
mCloseEventWasClean(false),
mCloseEventCode(nsIWebSocketChannel::CLOSE_ABNORMAL),
mReadyState(nsIWebSocket::CONNECTING),
mOutgoingBufferedAmount(0),
mBinaryType(WS_BINARY_TYPE_BLOB),
@ -623,7 +630,7 @@ public:
~nsAutoCloseWS()
{
if (!mWebSocket->mChannel) {
mWebSocket->CloseConnection();
mWebSocket->CloseConnection(nsIWebSocketChannel::CLOSE_INTERNAL_ERROR);
}
}
private:
@ -906,9 +913,9 @@ nsWebSocket::SetReadyState(PRUint16 aNewReadyState)
mReadyState = aNewReadyState;
// The close event must be dispatched asynchronously.
rv = NS_DispatchToMainThread(new nsWSCloseEvent(this, mClosedCleanly,
mServerReasonCode,
mServerReason),
rv = NS_DispatchToMainThread(new nsWSCloseEvent(this, mCloseEventWasClean,
mCloseEventCode,
mCloseEventReason),
NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch the close event");
@ -1413,29 +1420,27 @@ nsWebSocket::Close(PRUint16 code, const nsAString & reason, PRUint8 argc)
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
// the reason code is optional, but if provided it must be in a specific range
PRUint16 closeCode = 0;
if (argc >= 1) {
if (code != 1000 && (code < 3000 || code > 4999))
if (code != 1000 && (code < 3000 || code > 4999)) {
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
closeCode = code;
}
nsCAutoString utf8Reason;
nsCAutoString closeReason;
if (argc >= 2) {
if (ContainsUnpairedSurrogates(reason))
if (ContainsUnpairedSurrogates(reason)) {
return NS_ERROR_DOM_SYNTAX_ERR;
CopyUTF16toUTF8(reason, utf8Reason);
}
CopyUTF16toUTF8(reason, closeReason);
// The API requires the UTF-8 string to be 123 or less bytes
if (utf8Reason.Length() > 123)
if (closeReason.Length() > 123) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
}
// Format checks for reason and code both passed, they can now be assigned.
if (argc >= 1)
mClientReasonCode = code;
if (argc >= 2)
mClientReason = utf8Reason;
if (mReadyState == nsIWebSocket::CLOSING ||
mReadyState == nsIWebSocket::CLOSED) {
return NS_OK;
@ -1446,12 +1451,12 @@ nsWebSocket::Close(PRUint16 code, const nsAString & reason, PRUint8 argc)
// before calling it
nsRefPtr<nsWebSocket> kungfuDeathGrip = this;
FailConnection();
FailConnection(closeCode, closeReason);
return NS_OK;
}
// mReadyState == nsIWebSocket::OPEN
CloseConnection();
CloseConnection(closeCode, closeReason);
return NS_OK;
}
@ -1594,8 +1599,7 @@ nsWebSocket::Cancel(nsresult aStatus)
return NS_OK;
ConsoleError();
mClientReasonCode = nsIWebSocketChannel::CLOSE_GOING_AWAY;
return CloseConnection();
return CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
}
NS_IMETHODIMP

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

@ -111,9 +111,11 @@ protected:
nsresult ParseURL(const nsString& aURL);
nsresult EstablishConnection();
// these three methods when called can release the WebSocket object
nsresult FailConnection();
nsresult CloseConnection();
// These methods when called can release the WebSocket object
nsresult FailConnection(PRUint16 reasonCode,
const nsACString& aReasonString = EmptyCString());
nsresult CloseConnection(PRUint16 reasonCode,
const nsACString& aReasonString = EmptyCString());
nsresult Disconnect();
nsresult ConsoleError();
@ -166,13 +168,12 @@ protected:
bool mKeepingAlive;
bool mCheckMustKeepAlive;
bool mTriggeredCloseEvent;
bool mClosedCleanly;
bool mDisconnected;
nsCString mClientReason;
nsString mServerReason;
PRUint16 mClientReasonCode;
PRUint16 mServerReasonCode;
// Set attributes of DOM 'onclose' message
bool mCloseEventWasClean;
nsString mCloseEventReason;
PRUint16 mCloseEventCode;
nsCString mAsciiHost; // hostname
PRUint32 mPort;

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

@ -2087,10 +2087,6 @@ nsresult nsHTMLMediaElement::FinishDecoderSetup(nsMediaDecoder* aDecoder)
{
NS_ASSERTION(mLoadingSrc, "mLoadingSrc set up");
nsCAutoString src;
GetCurrentSpec(src);
printf("*** nsHTMLElement::FinishDecoderSetup() mDecoder=%p stream=%p src=%s\n",
aDecoder, aDecoder->GetStream(), src.get());
mDecoder = aDecoder;
AddMediaElementToURITable();
@ -2490,15 +2486,7 @@ ImageContainer* nsHTMLMediaElement::GetImageContainer()
if (!video)
return nsnull;
nsRefPtr<LayerManager> manager =
nsContentUtils::PersistentLayerManagerForDocument(OwnerDoc());
if (!manager)
return nsnull;
mImageContainer = manager->CreateImageContainer();
if (manager->IsCompositingCheap()) {
mImageContainer->SetDelayedConversion(true);
}
mImageContainer = LayerManager::CreateImageContainer();
return mImageContainer;
}

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

@ -60,6 +60,11 @@ extern "C" {
#include "nsThreadUtils.h"
#include "mozilla/Preferences.h"
#if defined(MOZ_CUBEB)
#include "nsAutoRef.h"
#include "cubeb/cubeb.h"
#endif
using namespace mozilla;
#if defined(XP_MACOSX)
@ -78,6 +83,10 @@ using mozilla::TimeStamp;
PRLogModuleInfo* gAudioStreamLog = nsnull;
#endif
#if defined(MOZ_CUBEB)
static cubeb* gCubebContext;
#endif
static const PRUint32 FAKE_BUFFER_SIZE = 176400;
// Number of milliseconds per second.
@ -170,9 +179,9 @@ class AudioInitEvent : public nsRunnable
{
ContentChild * cpc = ContentChild::GetSingleton();
NS_ASSERTION(cpc, "Content Protocol is NULL!");
mOwner->mAudioChild = static_cast<AudioChild*> (cpc->SendPAudioConstructor(mOwner->mChannels,
mOwner->mRate,
mOwner->mFormat));
mOwner->mAudioChild = static_cast<AudioChild*>(cpc->SendPAudioConstructor(mOwner->mChannels,
mOwner->mRate,
mOwner->mFormat));
return NS_OK;
}
@ -316,42 +325,78 @@ class AudioShutdownEvent : public nsRunnable
};
#endif
static mozilla::Mutex* gVolumeScaleLock = nsnull;
#define PREF_VOLUME_SCALE "media.volume_scale"
#define PREF_USE_CUBEB "media.use_cubeb"
static mozilla::Mutex* gAudioPrefsLock = nsnull;
static double gVolumeScale = 1.0;
static bool gUseCubeb = false;
static int VolumeScaleChanged(const char* aPref, void *aClosure) {
nsAdoptingString value = Preferences::GetString("media.volume_scale");
mozilla::MutexAutoLock lock(*gVolumeScaleLock);
if (value.IsEmpty()) {
gVolumeScale = 1.0;
} else {
NS_ConvertUTF16toUTF8 utf8(value);
gVolumeScale = NS_MAX<double>(0, PR_strtod(utf8.get(), nsnull));
static int PrefChanged(const char* aPref, void* aClosure)
{
if (strcmp(aPref, PREF_VOLUME_SCALE) == 0) {
nsAdoptingString value = Preferences::GetString(aPref);
mozilla::MutexAutoLock lock(*gAudioPrefsLock);
if (value.IsEmpty()) {
gVolumeScale = 1.0;
} else {
NS_ConvertUTF16toUTF8 utf8(value);
gVolumeScale = NS_MAX<double>(0, PR_strtod(utf8.get(), nsnull));
}
} else if (strcmp(aPref, PREF_USE_CUBEB) == 0) {
bool value = Preferences::GetBool(aPref, true);
mozilla::MutexAutoLock lock(*gAudioPrefsLock);
gUseCubeb = value;
}
return 0;
}
static double GetVolumeScale() {
mozilla::MutexAutoLock lock(*gVolumeScaleLock);
static double GetVolumeScale()
{
mozilla::MutexAutoLock lock(*gAudioPrefsLock);
return gVolumeScale;
}
#if defined(MOZ_CUBEB)
static bool GetUseCubeb()
{
mozilla::MutexAutoLock lock(*gAudioPrefsLock);
return gUseCubeb;
}
#endif
void nsAudioStream::InitLibrary()
{
#ifdef PR_LOGGING
gAudioStreamLog = PR_NewLogModule("nsAudioStream");
#endif
gVolumeScaleLock = new mozilla::Mutex("nsAudioStream::gVolumeScaleLock");
VolumeScaleChanged(nsnull, nsnull);
Preferences::RegisterCallback(VolumeScaleChanged, "media.volume_scale");
gAudioPrefsLock = new mozilla::Mutex("nsAudioStream::gAudioPrefsLock");
PrefChanged(PREF_VOLUME_SCALE, nsnull);
Preferences::RegisterCallback(PrefChanged, PREF_VOLUME_SCALE);
#if defined(MOZ_CUBEB)
PrefChanged(PREF_USE_CUBEB, nsnull);
Preferences::RegisterCallback(PrefChanged, PREF_USE_CUBEB);
if (cubeb_init(&gCubebContext, "nsAudioStream") != 0) {
NS_WARNING("cubeb_init failed");
}
#endif
}
void nsAudioStream::ShutdownLibrary()
{
Preferences::UnregisterCallback(VolumeScaleChanged, "media.volume_scale");
delete gVolumeScaleLock;
gVolumeScaleLock = nsnull;
Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE);
#if defined(MOZ_CUBEB)
Preferences::UnregisterCallback(PrefChanged, PREF_USE_CUBEB);
#endif
delete gAudioPrefsLock;
gAudioPrefsLock = nsnull;
#if defined(MOZ_CUBEB)
if (gCubebContext) {
cubeb_destroy(gCubebContext);
gCubebContext = nsnull;
}
#endif
}
nsIThread *
@ -365,16 +410,6 @@ nsAudioStream::GetThread()
return mAudioPlaybackThread;
}
nsAudioStream* nsAudioStream::AllocateStream()
{
#if defined(REMOTE_AUDIO)
if (XRE_GetProcessType() == GeckoProcessType_Content) {
return new nsRemotedAudioStream();
}
#endif
return new nsNativeAudioStream();
}
class AsyncShutdownPlaybackThread : public nsRunnable
{
public:
@ -770,3 +805,398 @@ nsRemotedAudioStream::IsPaused()
}
#endif
#if defined(MOZ_CUBEB)
template <>
class nsAutoRefTraits<cubeb_stream> : public nsPointerRefTraits<cubeb_stream>
{
public:
static void Release(cubeb_stream* aStream) { cubeb_stream_destroy(aStream); }
};
class nsBufferedAudioStream : public nsAudioStream
{
public:
NS_DECL_ISUPPORTS
nsBufferedAudioStream();
~nsBufferedAudioStream();
nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat);
void Shutdown();
nsresult Write(const void* aBuf, PRUint32 aFrames);
PRUint32 Available();
void SetVolume(double aVolume);
void Drain();
void Pause();
void Resume();
PRInt64 GetPosition();
PRInt64 GetPositionInFrames();
bool IsPaused();
PRInt32 GetMinWriteSize();
private:
static long DataCallback_S(cubeb_stream*, void* aThis, void* aBuffer, long aFrames)
{
return static_cast<nsBufferedAudioStream*>(aThis)->DataCallback(aBuffer, aFrames);
}
static int StateCallback_S(cubeb_stream*, void* aThis, cubeb_state aState)
{
return static_cast<nsBufferedAudioStream*>(aThis)->StateCallback(aState);
}
long DataCallback(void* aBuffer, long aFrames);
int StateCallback(cubeb_state aState);
// Shared implementation of underflow adjusted position calculation.
// Caller must own the monitor.
PRInt64 GetPositionInFramesUnlocked();
// The monitor is held to protect all access to member variables. Write()
// waits while mBuffer is full; DataCallback() notifies as it consumes
// data from mBuffer. Drain() waits while mState is DRAINING;
// StateCallback() notifies when mState is DRAINED.
Monitor mMonitor;
// Sum of silent frames written when DataCallback requests more frames
// than are available in mBuffer.
PRUint64 mLostFrames;
// Temporary audio buffer. Filled by Write() and consumed by
// DataCallback(). Once mBufferLimit is reached, Write() blocks until
// sufficient space becomes available in mBuffer. The buffer and buffer
// limit deal in bytes, not frames.
nsTArray<PRUint8> mBuffer;
PRUint32 mBufferLimit;
// Software volume level. Applied during the servicing of DataCallback().
double mVolume;
// Owning reference to a cubeb_stream. cubeb_stream_destroy is called by
// nsAutoRef's destructor.
nsAutoRef<cubeb_stream> mCubebStream;
PRInt32 mRate;
PRInt32 mChannels;
SampleFormat mFormat;
PRUint32 mBytesPerFrame;
enum StreamState {
INITIALIZED, // Initialized, playback has not begun.
STARTED, // Started by a call to Write() (iff INITIALIZED) or Resume().
STOPPED, // Stopped by a call to Pause().
DRAINING, // Drain requested. DataCallback will indicate end of stream
// once the remaining contents of mBuffer are requested by
// cubeb, after which StateCallback will indicate drain
// completion.
DRAINED // StateCallback has indicated that the drain is complete.
};
StreamState mState;
// Arbitrary default stream latency. The higher this value, the longer stream
// volume changes will take to become audible.
static const unsigned int DEFAULT_LATENCY_MS = 100;
};
#endif
nsAudioStream* nsAudioStream::AllocateStream()
{
#if defined(REMOTE_AUDIO)
if (XRE_GetProcessType() == GeckoProcessType_Content) {
return new nsRemotedAudioStream();
}
#endif
#if defined(MOZ_CUBEB)
if (GetUseCubeb()) {
return new nsBufferedAudioStream();
}
#endif
return new nsNativeAudioStream();
}
#if defined(MOZ_CUBEB)
nsBufferedAudioStream::nsBufferedAudioStream()
: mMonitor("nsBufferedAudioStream"), mLostFrames(0), mVolume(1.0), mRate(0), mChannels(0),
mBytesPerFrame(0), mState(INITIALIZED)
{
}
nsBufferedAudioStream::~nsBufferedAudioStream()
{
Shutdown();
}
NS_IMPL_THREADSAFE_ISUPPORTS0(nsBufferedAudioStream)
nsresult
nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat)
{
if (!gCubebContext || aNumChannels < 0 || aRate < 0) {
return NS_ERROR_FAILURE;
}
mRate = aRate;
mChannels = aNumChannels;
mFormat = aFormat;
cubeb_stream_params params;
params.rate = aRate;
params.channels = aNumChannels;
switch (aFormat) {
case FORMAT_S16_LE:
params.format = CUBEB_SAMPLE_S16LE;
mBytesPerFrame = sizeof(short) * aNumChannels;
break;
case FORMAT_FLOAT32:
params.format = CUBEB_SAMPLE_FLOAT32LE;
mBytesPerFrame = sizeof(float) * aNumChannels;
break;
default:
return NS_ERROR_FAILURE;
}
{
cubeb_stream* stream;
if (cubeb_stream_init(gCubebContext, &stream, "nsBufferedAudioStream", params,
DEFAULT_LATENCY_MS, DataCallback_S, StateCallback_S, this) == CUBEB_OK) {
mCubebStream.own(stream);
}
}
if (!mCubebStream) {
return NS_ERROR_FAILURE;
}
// Limit mBuffer to one second of audio. This value is arbitrary, and was
// selected based on the observed behaviour of the existing nsAudioStream
// implementations.
mBufferLimit = aRate * mBytesPerFrame;
NS_ABORT_IF_FALSE(mBufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
// Pre-allocate the buffer. nsTArray::RemoveElementsAt shrinks the buffer
// only if its length reaches zero, so allocator thrashing should be
// minimal.
mBuffer.SetCapacity(mBufferLimit);
return NS_OK;
}
void
nsBufferedAudioStream::Shutdown()
{
if (mCubebStream) {
cubeb_stream_stop(mCubebStream);
mCubebStream.reset();
}
}
nsresult
nsBufferedAudioStream::Write(const void* aBuf, PRUint32 aFrames)
{
MonitorAutoLock mon(mMonitor);
if (!mCubebStream) {
return NS_ERROR_FAILURE;
}
NS_ASSERTION(mState == INITIALIZED || mState == STARTED, "Stream write in unexpected state.");
const PRUint8* src = static_cast<const PRUint8*>(aBuf);
PRUint32 bytesToCopy = aFrames * mBytesPerFrame;
while (bytesToCopy > 0) {
NS_ABORT_IF_FALSE(mBuffer.Length() <= mBufferLimit, "Buffer invariant violated.");
PRUint32 available = NS_MIN(bytesToCopy, mBufferLimit - mBuffer.Length());
NS_ABORT_IF_FALSE(available % mBytesPerFrame == 0, "Must copy complete frames.");
mBuffer.AppendElements(src, available);
src += available;
bytesToCopy -= available;
if (mState != STARTED && cubeb_stream_start(mCubebStream) == CUBEB_OK) {
mState = STARTED;
}
if (bytesToCopy > 0) {
mon.Wait();
}
}
return NS_OK;
}
PRUint32
nsBufferedAudioStream::Available()
{
MonitorAutoLock mon(mMonitor);
NS_ABORT_IF_FALSE(mBuffer.Length() <= mBufferLimit, "Buffer invariant violated.");
NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Buffer invariant violated.");
return (mBufferLimit - mBuffer.Length()) / mBytesPerFrame;
}
PRInt32 nsBufferedAudioStream::GetMinWriteSize()
{
return 1;
}
void
nsBufferedAudioStream::SetVolume(double aVolume)
{
MonitorAutoLock mon(mMonitor);
NS_ABORT_IF_FALSE(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
mVolume = aVolume;
}
void
nsBufferedAudioStream::Drain()
{
MonitorAutoLock mon(mMonitor);
if (mState != STARTED) {
return;
}
mState = DRAINING;
while (mState != DRAINED) {
mon.Wait();
}
}
void
nsBufferedAudioStream::Pause()
{
MonitorAutoLock mon(mMonitor);
if (!mCubebStream || mState != STARTED) {
return;
}
if (cubeb_stream_stop(mCubebStream) == CUBEB_OK) {
mState = STOPPED;
}
}
void
nsBufferedAudioStream::Resume()
{
MonitorAutoLock mon(mMonitor);
if (!mCubebStream || mState != STOPPED) {
return;
}
if (cubeb_stream_start(mCubebStream) == CUBEB_OK) {
mState = STARTED;
}
}
PRInt64 nsBufferedAudioStream::GetPosition()
{
MonitorAutoLock mon(mMonitor);
PRInt64 frames = GetPositionInFramesUnlocked();
if (frames >= 0) {
return USECS_PER_S * frames / mRate;
}
return -1;
}
PRInt64
nsBufferedAudioStream::GetPositionInFrames()
{
MonitorAutoLock mon(mMonitor);
return GetPositionInFramesUnlocked();
}
PRInt64
nsBufferedAudioStream::GetPositionInFramesUnlocked()
{
mMonitor.AssertCurrentThreadOwns();
if (!mCubebStream) {
return -1;
}
uint64_t position = 0;
if (cubeb_stream_get_position(mCubebStream, &position) != CUBEB_OK) {
return -1;
}
// Adjust the reported position by the number of silent frames written
// during stream underruns.
PRInt64 adjustedPosition = 0;
if (position >= mLostFrames) {
adjustedPosition = position - mLostFrames;
}
return adjustedPosition;
}
bool
nsBufferedAudioStream::IsPaused()
{
MonitorAutoLock mon(mMonitor);
return mState == STOPPED;
}
template<typename T>
void
SampleCopy(void* aDst, const PRUint8* aSrc, PRUint32 aSamples, double aVolume)
{
const T* src = reinterpret_cast<const T*>(aSrc);
double scaled_volume = GetVolumeScale() * aVolume;
T* dst = static_cast<T*>(aDst);
for (PRUint32 i = 0; i < aSamples; ++i) {
dst[i] = T(src[i] * scaled_volume);
}
}
long
nsBufferedAudioStream::DataCallback(void* aBuffer, long aFrames)
{
MonitorAutoLock mon(mMonitor);
PRUint32 bytesWanted = aFrames * mBytesPerFrame;
// Adjust bytesWanted to fit what is available in mBuffer.
PRUint32 available = NS_MIN(bytesWanted, mBuffer.Length());
NS_ABORT_IF_FALSE(available % mBytesPerFrame == 0, "Must copy complete frames");
// Copy each sample from mBuffer to aBuffer, adjusting the volume during the copy.
PRUint32 samplesToCopy = available / mBytesPerFrame * mChannels;
switch (mFormat) {
case FORMAT_S16_LE:
SampleCopy<PRInt16>(aBuffer, mBuffer.Elements(), samplesToCopy, mVolume);
break;
case FORMAT_FLOAT32:
SampleCopy<float>(aBuffer, mBuffer.Elements(), samplesToCopy, mVolume);
break;
default:
return -1;
}
// Remove copied data from the temporary audio buffer.
mBuffer.RemoveElementsAt(0, available);
NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Must copy complete frames");
// Notify any blocked Write() call that more space is available in mBuffer.
mon.NotifyAll();
// Calculate remaining bytes requested by caller. If the stream is not
// draining an underrun has occurred, so fill the remaining buffer with
// silence.
bytesWanted -= available;
if (mState != DRAINING) {
memset(static_cast<PRUint8*>(aBuffer) + available, 0, bytesWanted);
mLostFrames += bytesWanted / mBytesPerFrame;
bytesWanted = 0;
}
return aFrames - (bytesWanted / mBytesPerFrame);
}
int
nsBufferedAudioStream::StateCallback(cubeb_state aState)
{
if (aState == CUBEB_STATE_DRAINED) {
MonitorAutoLock mon(mMonitor);
mState = DRAINED;
mon.NotifyAll();
}
return CUBEB_OK;
}
#endif

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

@ -233,7 +233,7 @@ const PRUint8 nsSMILTimedElement::sMaxNumInstanceTimes = 100;
// Detect if we arrive in some sort of undetected recursive syncbase dependency
// relationship
const PRUint16 nsSMILTimedElement::sMaxUpdateIntervalRecursionDepth = 20;
const PRUint8 nsSMILTimedElement::sMaxUpdateIntervalRecursionDepth = 20;
//----------------------------------------------------------------------
// Ctor, dtor
@ -252,6 +252,7 @@ nsSMILTimedElement::nsSMILTimedElement()
mSeekState(SEEK_NOT_SEEKING),
mDeferIntervalUpdates(false),
mDoDeferredUpdate(false),
mDeleteCount(0),
mUpdateIntervalRecursionDepth(0)
{
mSimpleDur.SetIndefinite();
@ -1960,12 +1961,29 @@ nsSMILTimedElement::UpdateCurrentInterval(bool aForceChangeNotice)
if (mElementState == STATE_STARTUP)
return;
// Although SMIL gives rules for detecting cycles in change notifications,
// some configurations can lead to create-delete-create-delete-etc. cycles
// which SMIL does not consider.
//
// In order to provide consistent behavior in such cases, we detect two
// deletes in a row and then refuse to create any further intervals. That is,
// we say the configuration is invalid.
if (mDeleteCount > 1) {
// When we update the delete count we also set the state to post active, so
// if we're not post active here then something other than
// UpdateCurrentInterval has updated the element state in between and all
// bets are off.
NS_ABORT_IF_FALSE(mElementState == STATE_POSTACTIVE,
"Expected to be in post-active state after performing double delete");
return;
}
// Check that we aren't stuck in infinite recursion updating some syncbase
// dependencies. Generally such situations should be detected in advance and
// the chain broken in a sensible and predictable manner, so if we're hitting
// this assertion we need to work out how to detect the case that's causing
// it. In release builds, just bail out before we overflow the stack.
AutoRestore<PRUint16> depthRestorer(mUpdateIntervalRecursionDepth);
AutoRestore<PRUint8> depthRestorer(mUpdateIntervalRecursionDepth);
if (++mUpdateIntervalRecursionDepth > sMaxUpdateIntervalRecursionDepth) {
NS_ABORT_IF_FALSE(false,
"Update current interval recursion depth exceeded threshold");
@ -2026,6 +2044,8 @@ nsSMILTimedElement::UpdateCurrentInterval(bool aForceChangeNotice)
// sample (along with firing end events, clearing intervals etc.)
RegisterMilestone();
} else if (mElementState == STATE_WAITING) {
AutoRestore<PRUint8> deleteCountRestorer(mDeleteCount);
++mDeleteCount;
mElementState = STATE_POSTACTIVE;
ResetCurrentInterval();
}

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

@ -625,13 +625,13 @@ protected:
// Used to batch updates to the timing model
class AutoIntervalUpdateBatcher;
bool mDeferIntervalUpdates;
bool mDoDeferredUpdate; // Set if an update to the current interval
// was requested while mDeferIntervalUpdates
// was set
bool mDoDeferredUpdate; // Set if an update to the current interval was
// requested while mDeferIntervalUpdates was set
// Recursion depth checking
PRUint16 mUpdateIntervalRecursionDepth;
static const PRUint16 sMaxUpdateIntervalRecursionDepth;
PRUint8 mDeleteCount;
PRUint8 mUpdateIntervalRecursionDepth;
static const PRUint8 sMaxUpdateIntervalRecursionDepth;
};
#endif // NS_SMILTIMEDELEMENT_H_

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

@ -4927,7 +4927,7 @@ GenerateNormal(float *N, const PRUint8 *data, PRInt32 stride,
PRInt32 x, PRInt32 y, float surfaceScale)
{
// See this for source of constants:
// http://www.w3.org/TR/SVG11/filters.html#feDiffuseLighting
// http://www.w3.org/TR/SVG11/filters.html#feDiffuseLightingElement
static const PRInt8 Kx[3][3][3][3] =
{ { { { 0, 0, 0}, { 0, -2, 2}, { 0, -1, 1} },
{ { 0, 0, 0}, {-2, 0, 2}, {-1, 0, 1} },

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

@ -0,0 +1,14 @@
<!DOCTYPE html>
<script>
var collection = document.images;
var other = document.embeds;
var options = document.createElement("select").options;
collection.toString;
options.selectedIndex;
Object.getPrototypeOf(collection).item = {};
other.toString;
collection.toString;
options.selectedIndex;
options.toString;
</script>

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

@ -0,0 +1,16 @@
<!DOCTYPE html>
<script>
var collection = document.images;
var other = document.embeds;
var options = document.createElement("select").options;
collection.toString;
options.selectedIndex;
Object.defineProperty(Object.getPrototypeOf(collection),
"item",
{ value: {}, enumerable: true, configurable: true });
other.toString;
collection.toString;
options.selectedIndex;
options.toString;
</script>

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

@ -0,0 +1,4 @@
<!DOCTYPE html>
<script>
document.createElement("p").constructor = function(){};
</script>

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

@ -30,6 +30,9 @@ load 637116.html
load 666869.html
load 675621-1.html
load 693894.html
load 693811-1.html
load 693811-2.html
load 693811-3.html
load 695867.html
load 697643.html
load 706283-1.html

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

@ -88,14 +88,22 @@ AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr)
return true;
}
static void
CollectWindowMemoryUsage(nsGlobalWindow *aWindow,
nsIMemoryMultiReporterCallback *aCb,
nsISupports *aClosure)
struct WindowTotals
{
NS_NAMED_LITERAL_CSTRING(kWindowDesc,
"Memory used by a window and the DOM within it.");
WindowTotals() : mDom(0), mStyleSheets(0) {}
size_t mDom;
size_t mStyleSheets;
};
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WindowStyleSheetsMallocSizeOf,
"window/style-sheets")
static void
CollectWindowReports(nsGlobalWindow *aWindow,
WindowTotals *aWindowTotals,
nsIMemoryMultiReporterCallback *aCb,
nsISupports *aClosure)
{
// DOM window objects fall into one of three categories:
// - "active" windows are currently either displayed in an active
// tab, or a child of such a window.
@ -119,7 +127,7 @@ CollectWindowMemoryUsage(nsGlobalWindow *aWindow,
// The path we give to the reporter callback for inner windows are
// as follows:
//
// explicit/dom/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
// explicit/dom+style/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
//
// Where:
// - <category> is active, cached, or other, as described above.
@ -138,62 +146,82 @@ CollectWindowMemoryUsage(nsGlobalWindow *aWindow,
//
// For outer windows we simply use:
//
// explicit/dom/window-objects/<category>/outer-windows
// explicit/dom+style/window-objects/<category>/outer-windows
//
// Which gives us simple counts of how many outer windows (and their
// combined sizes) per category.
nsCAutoString str("explicit/dom/window-objects/");
nsCAutoString windowPath("explicit/dom+style/window-objects/");
nsIDocShell *docShell = aWindow->GetDocShell();
nsGlobalWindow *top = aWindow->GetTop();
PRInt64 windowSize = aWindow->SizeOf();
PRInt64 windowDOMSize = aWindow->SizeOf();
PRInt64 styleSheetsSize = aWindow->SizeOfStyleSheets(WindowStyleSheetsMallocSizeOf);
if (docShell && aWindow->IsFrozen()) {
str += NS_LITERAL_CSTRING("cached/");
windowPath += NS_LITERAL_CSTRING("cached/");
} else if (docShell) {
str += NS_LITERAL_CSTRING("active/");
windowPath += NS_LITERAL_CSTRING("active/");
} else {
str += NS_LITERAL_CSTRING("other/");
windowPath += NS_LITERAL_CSTRING("other/");
}
if (aWindow->IsInnerWindow()) {
str += NS_LITERAL_CSTRING("top=");
windowPath += NS_LITERAL_CSTRING("top=");
if (top) {
str.AppendInt(top->WindowID());
windowPath.AppendInt(top->WindowID());
nsGlobalWindow *topInner = top->GetCurrentInnerWindowInternal();
if (topInner) {
str += NS_LITERAL_CSTRING(" (inner=");
str.AppendInt(topInner->WindowID());
str += NS_LITERAL_CSTRING(")");
windowPath += NS_LITERAL_CSTRING(" (inner=");
windowPath.AppendInt(topInner->WindowID());
windowPath += NS_LITERAL_CSTRING(")");
}
} else {
str += NS_LITERAL_CSTRING("none");
windowPath += NS_LITERAL_CSTRING("none");
}
str += NS_LITERAL_CSTRING("/inner-window(id=");
str.AppendInt(aWindow->WindowID());
str += NS_LITERAL_CSTRING(", uri=");
windowPath += NS_LITERAL_CSTRING("/inner-window(id=");
windowPath.AppendInt(aWindow->WindowID());
windowPath += NS_LITERAL_CSTRING(", uri=");
if (!AppendWindowURI(aWindow, str)) {
str += NS_LITERAL_CSTRING("[system]");
if (!AppendWindowURI(aWindow, windowPath)) {
windowPath += NS_LITERAL_CSTRING("[system]");
}
str += NS_LITERAL_CSTRING(")");
windowPath += NS_LITERAL_CSTRING(")");
} else {
// Combine all outer windows per section (active/cached/other) as
// they basically never contain anything of interest, and are
// always pretty much the same size.
str += NS_LITERAL_CSTRING("outer-windows");
windowPath += NS_LITERAL_CSTRING("outer-windows");
}
aCb->Callback(EmptyCString(), str, nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES, windowSize, kWindowDesc,
aClosure);
if (windowDOMSize > 0) {
nsCAutoString domPath(windowPath);
domPath += "/dom";
NS_NAMED_LITERAL_CSTRING(kWindowDesc,
"Memory used by a window and the DOM within it.");
aCb->Callback(EmptyCString(), domPath, nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES, windowDOMSize, kWindowDesc,
aClosure);
aWindowTotals->mDom += windowDOMSize;
}
if (styleSheetsSize > 0) {
nsCAutoString styleSheetsPath(windowPath);
styleSheetsPath += "/style-sheets";
NS_NAMED_LITERAL_CSTRING(kStyleSheetsDesc,
"Memory used by style sheets within a window.");
aCb->Callback(EmptyCString(), styleSheetsPath,
nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES, styleSheetsSize,
kStyleSheetsDesc, aClosure);
aWindowTotals->mStyleSheets += styleSheetsSize;
}
}
typedef nsTArray< nsRefPtr<nsGlobalWindow> > WindowArray;
@ -223,10 +251,27 @@ nsDOMMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
// Collect window memory usage.
nsRefPtr<nsGlobalWindow> *w = windows.Elements();
nsRefPtr<nsGlobalWindow> *end = w + windows.Length();
WindowTotals windowTotals;
for (; w != end; ++w) {
CollectWindowMemoryUsage(*w, aCb, aClosure);
CollectWindowReports(*w, &windowTotals, aCb, aClosure);
}
NS_NAMED_LITERAL_CSTRING(kDomTotalWindowsDesc,
"Memory used for the DOM within windows. This is the sum of all windows' "
"'dom' numbers.");
aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING("dom-total-window"),
nsIMemoryReporter::KIND_OTHER,
nsIMemoryReporter::UNITS_BYTES, windowTotals.mDom,
kDomTotalWindowsDesc, aClosure);
NS_NAMED_LITERAL_CSTRING(kLayoutTotalWindowStyleSheetsDesc,
"Memory used for style sheets within windows. This is the sum of all windows' "
"'style-sheets' numbers.");
aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING("style-sheets-total-window"),
nsIMemoryReporter::KIND_OTHER,
nsIMemoryReporter::UNITS_BYTES, windowTotals.mStyleSheets,
kLayoutTotalWindowStyleSheetsDesc, aClosure);
return NS_OK;
}

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

@ -10296,6 +10296,16 @@ nsGlobalWindow::SizeOf() const
return size;
}
size_t
nsGlobalWindow::SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const
{
size_t n = 0;
if (IsInnerWindow() && mDoc) {
n += mDoc->SizeOfStyleSheets(aMallocSizeOf);
}
return n;
}
// nsGlobalChromeWindow implementation
NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)

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

@ -576,6 +576,7 @@ public:
}
PRInt64 SizeOf() const;
size_t SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const;
void UnmarkGrayTimers();
private:

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

@ -138,6 +138,7 @@ endif
LOCAL_INCLUDES += \
-DSK_BUILD_FOR_ANDROID_NDK \
-I$(topsrcdir)/widget/android \
-I$(topsrcdir)/xpcom/base/ \
-I$(topsrcdir)/gfx/skia/include/core \
-I$(topsrcdir)/gfx/skia/include/config \

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

@ -306,7 +306,6 @@ anp_audio_start(ANPAudioTrack* s)
if (s->keepGoing) {
// we are already playing. Ignore.
LOG("anp_audio_start called twice!");
return;
}
@ -359,7 +358,14 @@ anp_audio_isStopped(ANPAudioTrack* s)
return s->isStopped;
}
void InitAudioTrackInterface(ANPAudioTrackInterfaceV0 *i) {
uint32_t
anp_audio_trackLatency(ANPAudioTrack* s) {
// Bug 721835
NOT_IMPLEMENTED();
return 1;
}
void InitAudioTrackInterfaceV0(ANPAudioTrackInterfaceV0 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, newTrack);
ASSIGN(i, deleteTrack);
@ -368,3 +374,14 @@ void InitAudioTrackInterface(ANPAudioTrackInterfaceV0 *i) {
ASSIGN(i, stop);
ASSIGN(i, isStopped);
}
void InitAudioTrackInterfaceV1(ANPAudioTrackInterfaceV1 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, newTrack);
ASSIGN(i, deleteTrack);
ASSIGN(i, start);
ASSIGN(i, pause);
ASSIGN(i, stop);
ASSIGN(i, isStopped);
ASSIGN(i, trackLatency);
}

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

@ -36,8 +36,8 @@
*
* ***** END LICENSE BLOCK ***** */
#include "android_npapi.h"
#include <stdlib.h>
#include "android_npapi.h"
#include "nsAutoPtr.h"
#include "nsISupportsImpl.h"
@ -53,7 +53,8 @@
"!!!!!!!!!!!!!! %s not implemented %s, %d", \
__PRETTY_FUNCTION__, __FILE__, __LINE__); \
void InitAudioTrackInterface(ANPAudioTrackInterfaceV0 *i);
void InitAudioTrackInterfaceV0(ANPAudioTrackInterfaceV0 *i);
void InitAudioTrackInterfaceV1(ANPAudioTrackInterfaceV1* i);
void InitBitmapInterface(ANPBitmapInterfaceV0 *i);
void InitCanvasInterface(ANPCanvasInterfaceV0 *i);
void InitEventInterface(ANPEventInterfaceV0 *i);
@ -63,5 +64,13 @@ void InitPaintInterface(ANPPaintInterfaceV0 *i);
void InitPathInterface(ANPPathInterfaceV0 *i);
void InitSurfaceInterface(ANPSurfaceInterfaceV0 *i);
void InitSystemInterface(ANPSystemInterfaceV0 *i);
void InitSystemInterfaceV1(ANPSystemInterfaceV1 *i);
void InitSystemInterfaceV2(ANPSystemInterfaceV2 *i);
void InitTypeFaceInterface(ANPTypefaceInterfaceV0 *i);
void InitWindowInterface(ANPWindowInterfaceV0 *i);
void InitWindowInterfaceV1(ANPWindowInterfaceV1 *i);
void InitWindowInterfaceV2(ANPWindowInterfaceV2 *i);
void InitVideoInterfaceV0(ANPVideoInterfaceV0 *i);
void InitVideoInterfaceV1(ANPVideoInterfaceV1 *i);
void InitOpenGLInterface(ANPOpenGLInterfaceV0 *i);
void InitNativeWindowInterface(ANPNativeWindowInterfaceV0 *i);

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

@ -0,0 +1,85 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Android NPAPI support code
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@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 ***** */
// must include config.h first for webkit to fiddle with new/delete
#include <android/log.h>
#include "AndroidBridge.h"
#include "AndroidMediaLayer.h"
#include "ANPBase.h"
#include "nsIPluginInstanceOwner.h"
#include "nsPluginInstanceOwner.h"
#include "nsNPAPIPluginInstance.h"
#include "gfxRect.h"
using namespace mozilla;
using namespace mozilla;
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#define ASSIGN(obj, name) (obj)->name = anp_native_window_##name
static ANPNativeWindow anp_native_window_acquireNativeWindow(NPP instance) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
nsPluginInstanceOwner* owner;
if (NS_FAILED(pinst->GetOwner((nsIPluginInstanceOwner**)&owner))) {
return NULL;
}
ANPNativeWindow window = owner->Layer()->GetNativeWindowForContent();
owner->Invalidate();
return window;
}
static void anp_native_window_invertPluginContent(NPP instance, bool isContentInverted) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
nsPluginInstanceOwner* owner;
if (NS_FAILED(pinst->GetOwner((nsIPluginInstanceOwner**)&owner))) {
return;
}
owner->Layer()->SetInverted(isContentInverted);
}
void InitNativeWindowInterface(ANPNativeWindowInterfaceV0* i) {
ASSIGN(i, acquireNativeWindow);
ASSIGN(i, invertPluginContent);
}

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

@ -0,0 +1,65 @@
/* The Original Code is Android NPAPI support code
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@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 <dlfcn.h>
#include <android/log.h>
#include "AndroidBridge.h"
#include "ANPBase.h"
#include "GLContextProvider.h"
#include "nsNPAPIPluginInstance.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#define ASSIGN(obj, name) (obj)->name = anp_opengl_##name
using namespace mozilla;
using namespace mozilla::gl;
static ANPEGLContext anp_opengl_acquireContext(NPP inst) {
// Bug 687267
NOT_IMPLEMENTED();
return NULL;
}
static ANPTextureInfo anp_opengl_lockTexture(NPP instance) {
ANPTextureInfo info = { 0, 0, 0, 0 };
NOT_IMPLEMENTED();
return info;
}
static void anp_opengl_releaseTexture(NPP instance, const ANPTextureInfo* info) {
NOT_IMPLEMENTED();
}
static void anp_opengl_invertPluginContent(NPP instance, bool isContentInverted) {
NOT_IMPLEMENTED();
}
///////////////////////////////////////////////////////////////////////////////
void InitOpenGLInterface(ANPOpenGLInterfaceV0* i) {
ASSIGN(i, acquireContext);
ASSIGN(i, lockTexture);
ASSIGN(i, releaseTexture);
ASSIGN(i, invertPluginContent);
}

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

@ -62,6 +62,12 @@ anp_system_getApplicationDataDirectory()
return dir;
}
const char*
anp_system_getApplicationDataDirectory(NPP instance)
{
return anp_system_getApplicationDataDirectory();
}
jclass anp_system_loadJavaClass(NPP instance, const char* className)
{
LOG("%s", __PRETTY_FUNCTION__);
@ -88,8 +94,27 @@ jclass anp_system_loadJavaClass(NPP instance, const char* className)
return reinterpret_cast<jclass>(obj);
}
void anp_system_setPowerState(NPP instance, ANPPowerState powerState)
{
NOT_IMPLEMENTED();
}
void InitSystemInterface(ANPSystemInterfaceV0 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, getApplicationDataDirectory);
ASSIGN(i, loadJavaClass);
}
void InitSystemInterfaceV1(ANPSystemInterfaceV1 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, getApplicationDataDirectory);
ASSIGN(i, loadJavaClass);
ASSIGN(i, setPowerState);
}
void InitSystemInterfaceV2(ANPSystemInterfaceV2 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, getApplicationDataDirectory);
ASSIGN(i, loadJavaClass);
ASSIGN(i, setPowerState);
}

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

@ -0,0 +1,109 @@
/* The Original Code is Android NPAPI support code
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@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 <android/log.h>
#include "ANPBase.h"
#include "AndroidMediaLayer.h"
#include "nsIPluginInstanceOwner.h"
#include "nsPluginInstanceOwner.h"
#include "nsNPAPIPluginInstance.h"
#include "gfxRect.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#define ASSIGN(obj, name) (obj)->name = anp_video_##name
using namespace mozilla;
static AndroidMediaLayer* GetLayerForInstance(NPP instance) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
nsPluginInstanceOwner* owner;
if (NS_FAILED(pinst->GetOwner((nsIPluginInstanceOwner**)&owner))) {
return NULL;
}
return owner->Layer();
}
static void Invalidate(NPP instance) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
nsPluginInstanceOwner* owner;
if (NS_FAILED(pinst->GetOwner((nsIPluginInstanceOwner**)&owner)))
return;
owner->Invalidate();
}
static ANPNativeWindow anp_video_acquireNativeWindow(NPP instance) {
AndroidMediaLayer* layer = GetLayerForInstance(instance);
if (!layer)
return NULL;
return layer->RequestNativeWindowForVideo();
}
static void anp_video_setWindowDimensions(NPP instance, const ANPNativeWindow window,
const ANPRectF* dimensions) {
AndroidMediaLayer* layer = GetLayerForInstance(instance);
if (!layer)
return;
gfxRect rect(dimensions->left, dimensions->top,
dimensions->right - dimensions->left,
dimensions->bottom - dimensions->top);
layer->SetNativeWindowDimensions(window, rect);
Invalidate(instance);
}
static void anp_video_releaseNativeWindow(NPP instance, ANPNativeWindow window) {
AndroidMediaLayer* layer = GetLayerForInstance(instance);
if (!layer)
return;
layer->ReleaseNativeWindowForVideo(window);
Invalidate(instance);
}
static void anp_video_setFramerateCallback(NPP instance, const ANPNativeWindow window, ANPVideoFrameCallbackProc callback) {
// Bug 722682
NOT_IMPLEMENTED();
}
///////////////////////////////////////////////////////////////////////////////
void InitVideoInterfaceV0(ANPVideoInterfaceV0* i) {
ASSIGN(i, acquireNativeWindow);
ASSIGN(i, setWindowDimensions);
ASSIGN(i, releaseNativeWindow);
}
void InitVideoInterfaceV1(ANPVideoInterfaceV1* i) {
ASSIGN(i, acquireNativeWindow);
ASSIGN(i, setWindowDimensions);
ASSIGN(i, releaseNativeWindow);
ASSIGN(i, setFramerateCallback);
}

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

@ -39,10 +39,16 @@
#include "assert.h"
#include "ANPBase.h"
#include <android/log.h>
#include "AndroidBridge.h"
#include "nsNPAPIPluginInstance.h"
#include "nsIPluginInstanceOwner.h"
#include "nsPluginInstanceOwner.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#define ASSIGN(obj, name) (obj)->name = anp_window_##name
using namespace mozilla;
void
anp_window_setVisibleRects(NPP instance, const ANPRectI rects[], int32_t count)
{
@ -79,6 +85,32 @@ anp_window_requestCenterFitZoom(NPP instance)
NOT_IMPLEMENTED();
}
ANPRectI
anp_window_visibleRect(NPP instance)
{
ANPRectI rect = { 0, 0, 0, 0 };
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
nsPluginInstanceOwner* owner;
if (NS_FAILED(pinst->GetOwner((nsIPluginInstanceOwner**)&owner))) {
return rect;
}
nsIntRect visibleRect = owner->GetVisibleRect();
rect.left = visibleRect.x;
rect.top = visibleRect.y;
rect.right = visibleRect.x + visibleRect.width;
rect.bottom = visibleRect.y + visibleRect.height;
return rect;
}
void anp_window_requestFullScreenOrientation(NPP instance, ANPScreenOrientation orientation)
{
NOT_IMPLEMENTED();
}
void InitWindowInterface(ANPWindowInterfaceV0 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, setVisibleRects);
@ -89,3 +121,26 @@ void InitWindowInterface(ANPWindowInterfaceV0 *i) {
ASSIGN(i, requestCenterFitZoom);
}
void InitWindowInterfaceV1(ANPWindowInterfaceV1 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, setVisibleRects);
ASSIGN(i, clearVisibleRects);
ASSIGN(i, showKeyboard);
ASSIGN(i, requestFullScreen);
ASSIGN(i, exitFullScreen);
ASSIGN(i, requestCenterFitZoom);
ASSIGN(i, visibleRect);
}
void InitWindowInterfaceV2(ANPWindowInterfaceV2 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, setVisibleRects);
ASSIGN(i, clearVisibleRects);
ASSIGN(i, showKeyboard);
ASSIGN(i, requestFullScreen);
ASSIGN(i, exitFullScreen);
ASSIGN(i, requestCenterFitZoom);
ASSIGN(i, visibleRect);
ASSIGN(i, requestFullScreenOrientation);
}

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

@ -63,12 +63,17 @@ CPPSRCS += ANPAudio.cpp \
ANPWindow.cpp \
ANPBitmap.cpp \
ANPLog.cpp \
ANPNativeWindow.cpp \
ANPSurface.cpp \
ANPVideo.cpp \
ANPOpenGL.cpp \
$(NULL)
LOCAL_INCLUDES += \
-I$(topsrcdir)/widget/android \
-I$(topsrcdir)/dom/plugins/base \
-I$(topsrcdir)/dom/plugins/base/android/include \
-I$(topsrcdir)/gfx/gl \
$(MOZ_CAIRO_CFLAGS) \
$(NULL)

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

@ -36,8 +36,9 @@
#define android_npapi_H
#include <stdint.h>
#include "npapi.h"
#include <jni.h>
#include "npapi.h"
#include "GLDefs.h"
///////////////////////////////////////////////////////////////////////////////
// General types
@ -120,6 +121,16 @@ typedef uint32_t ANPMatrixFlag;
#define kSystemInterfaceV0_ANPGetValue ((NPNVariable)1010)
#define kEventInterfaceV0_ANPGetValue ((NPNVariable)1011)
#define kAudioTrackInterfaceV1_ANPGetValue ((NPNVariable)1012)
#define kOpenGLInterfaceV0_ANPGetValue ((NPNVariable)1013)
#define kWindowInterfaceV1_ANPGetValue ((NPNVariable)1014)
#define kVideoInterfaceV0_ANPGetValue ((NPNVariable)1015)
#define kSystemInterfaceV1_ANPGetValue ((NPNVariable)1016)
#define kSystemInterfaceV2_ANPGetValue ((NPNVariable)1017)
#define kWindowInterfaceV2_ANPGetValue ((NPNVariable)1018)
#define kNativeWindowInterfaceV0_ANPGetValue ((NPNVariable)1019)
#define kVideoInterfaceV1_ANPGetValue ((NPNVariable)1020)
/** queries for the drawing models supported on this device.
NPN_GetValue(inst, kSupportedDrawingModel_ANPGetValue, uint32_t* bits)
@ -180,6 +191,7 @@ enum ANPDrawingModels {
surface object.
*/
kSurface_ANPDrawingModel = 1 << 1,
kOpenGL_ANPDrawingModel = 1 << 2,
};
typedef int32_t ANPDrawingModel;
@ -678,6 +690,25 @@ struct ANPWindowInterfaceV0 : ANPInterface {
void (*requestCenterFitZoom)(NPP instance);
};
struct ANPWindowInterfaceV1 : ANPWindowInterfaceV0 {
/** Returns a rectangle representing the visible area of the plugin on
screen. The coordinates are relative to the size of the plugin in the
document and therefore will never be negative or exceed the plugin's size.
*/
ANPRectI (*visibleRect)(NPP instance);
};
typedef int32_t ANPScreenOrientation;
struct ANPWindowInterfaceV2 : ANPWindowInterfaceV1 {
/** Called when the plugin wants to specify a particular screen orientation
when entering into full screen mode. The orientation must be set prior
to entering into full screen. After entering full screen any subsequent
changes will be updated the next time the plugin goes full screen.
*/
void (*requestFullScreenOrientation)(NPP instance, ANPScreenOrientation orientation);
};
///////////////////////////////////////////////////////////////////////////////
enum ANPSampleFormats {
@ -762,6 +793,12 @@ struct ANPAudioTrackInterfaceV0 : ANPInterface {
bool (*isStopped)(ANPAudioTrack*);
};
struct ANPAudioTrackInterfaceV1 : ANPAudioTrackInterfaceV0 {
/** Returns the track's latency in milliseconds. */
uint32_t (*trackLatency)(ANPAudioTrack*);
};
///////////////////////////////////////////////////////////////////////////////
// DEFINITION OF VALUES PASSED THROUGH NPP_HandleEvent
@ -922,12 +959,16 @@ struct ANPEvent {
// use based on the value in model
union {
ANPBitmap bitmap;
struct {
int32_t width;
int32_t height;
} surfaceSize;
} data;
} draw;
int32_t other[8];
} data;
};
struct ANPEventInterfaceV0 : ANPInterface {
/** Post a copy of the specified event to the plugin. The event will be
delivered to the plugin in its main thread (the thread that receives
@ -976,4 +1017,117 @@ typedef uint32_t uint32;
typedef int16_t int16;
typedef uint16_t uint16;
/**
* TODO should we not use EGL and GL data types for ABI safety?
*/
struct ANPTextureInfo {
GLuint textureId;
uint32_t width;
uint32_t height;
GLenum internalFormat;
};
typedef void* ANPEGLContext;
struct ANPOpenGLInterfaceV0 : ANPInterface {
ANPEGLContext (*acquireContext)(NPP instance);
ANPTextureInfo (*lockTexture)(NPP instance);
void (*releaseTexture)(NPP instance, const ANPTextureInfo*);
/**
* Invert the contents of the plugin on the y-axis.
* default is to not be inverted (i.e. use OpenGL coordinates)
*/
void (*invertPluginContent)(NPP instance, bool isContentInverted);
};
enum ANPPowerStates {
kDefault_ANPPowerState = 0,
kScreenOn_ANPPowerState = 1
};
typedef int32_t ANPPowerState;
struct ANPSystemInterfaceV1 : ANPSystemInterfaceV0 {
void (*setPowerState)(NPP instance, ANPPowerState powerState);
};
struct ANPSystemInterfaceV2 : ANPInterface {
/** Return the path name for the current Application's plugin data directory,
or NULL if not supported. This directory will change depending on whether
or not the plugin is found within an incognito tab.
*/
const char* (*getApplicationDataDirectory)(NPP instance);
// redeclaration of existing features
jclass (*loadJavaClass)(NPP instance, const char* className);
void (*setPowerState)(NPP instance, ANPPowerState powerState);
};
typedef void* ANPNativeWindow;
struct ANPVideoInterfaceV0 : ANPInterface {
/**
* Constructs a new native window to be used for rendering video content.
*
* Subsequent calls will produce new windows, but may also return NULL after
* n attempts if the browser has reached it's limit. Further, if the browser
* is unable to acquire the window quickly it may also return NULL in order
* to not prevent the plugin from executing. A subsequent call will then
* return the window if it is avaiable.
*
* NOTE: The hardware may fail if you try to decode more than the allowable
* number of videos supported on that device.
*/
ANPNativeWindow (*acquireNativeWindow)(NPP instance);
/**
* Sets the rectangle that specifies where the video content is to be drawn.
* The dimensions are in document space. Further, if the rect is NULL the
* browser will not attempt to draw the window, therefore do not set the
* dimensions until you queue the first buffer in the window.
*/
void (*setWindowDimensions)(NPP instance, const ANPNativeWindow window, const ANPRectF* dimensions);
/**
*/
void (*releaseNativeWindow)(NPP instance, ANPNativeWindow window);
};
/** Called to notify the plugin that a video frame has been composited by the
* browser for display. This will be called in a separate thread and as such
* you cannot call releaseNativeWindow from the callback.
*
* The timestamp is in nanoseconds, and is monotonically increasing.
*/
typedef void (*ANPVideoFrameCallbackProc)(ANPNativeWindow* window, int64_t timestamp);
struct ANPVideoInterfaceV1 : ANPVideoInterfaceV0 {
/** Set a callback to be notified when an ANPNativeWindow is composited by
* the browser.
*/
void (*setFramerateCallback)(NPP instance, const ANPNativeWindow window, ANPVideoFrameCallbackProc);
};
struct ANPNativeWindowInterfaceV0 : ANPInterface {
/**
* Constructs a new native window to be used for rendering plugin content.
*
* Subsequent calls will return the original constructed window. Further, if
* the browser is unable to acquire the window quickly it may return NULL in
* order to not block the plugin indefinitely. A subsequent call will then
* return the window if it is available.
*/
ANPNativeWindow (*acquireNativeWindow)(NPP instance);
/**
* Invert the contents of the plugin on the y-axis.
* default is to not be inverted (e.g. use OpenGL coordinates)
*/
void (*invertPluginContent)(NPP instance, bool isContentInverted);
};
#endif

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

@ -132,9 +132,10 @@ using mozilla::plugins::PluginModuleParent;
#endif
#ifdef MOZ_WIDGET_ANDROID
#include <android/log.h>
#include "android_npapi.h"
#include "ANPBase.h"
#include "AndroidBridge.h"
#include <android/log.h>
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#endif
@ -2348,7 +2349,7 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
case kAudioTrackInterfaceV0_ANPGetValue: {
LOG("get audio interface");
ANPAudioTrackInterfaceV0 *i = (ANPAudioTrackInterfaceV0 *) result;
InitAudioTrackInterface(i);
InitAudioTrackInterfaceV0(i);
return NPERR_NO_ERROR;
}
@ -2363,7 +2364,6 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
LOG("get system interface");
ANPSystemInterfaceV0* i = reinterpret_cast<ANPSystemInterfaceV0*>(result);
InitSystemInterface(i);
LOG("done system interface");
return NPERR_NO_ERROR;
}
@ -2395,6 +2395,71 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
*i = reinterpret_cast<int32_t>(ret);
return NPERR_NO_ERROR;
}
case kAudioTrackInterfaceV1_ANPGetValue: {
LOG("get audio interface v1");
ANPAudioTrackInterfaceV1 *i = (ANPAudioTrackInterfaceV1 *) result;
InitAudioTrackInterfaceV1(i);
return NPERR_NO_ERROR;
}
case kNativeWindowInterfaceV0_ANPGetValue: {
LOG("get native window interface v0");
ANPNativeWindowInterfaceV0* i = (ANPNativeWindowInterfaceV0 *) result;
InitNativeWindowInterface(i);
return NPERR_NO_ERROR;
}
case kOpenGLInterfaceV0_ANPGetValue: {
LOG("get openGL interface");
ANPOpenGLInterfaceV0 *i = (ANPOpenGLInterfaceV0*) result;
InitOpenGLInterface(i);
return NPERR_NO_ERROR;
}
case kWindowInterfaceV1_ANPGetValue: {
LOG("get Window interface V1");
ANPWindowInterfaceV1 *i = (ANPWindowInterfaceV1 *) result;
InitWindowInterfaceV1(i);
return NPERR_NO_ERROR;
}
case kWindowInterfaceV2_ANPGetValue: {
LOG("get Window interface V2");
ANPWindowInterfaceV2 *i = (ANPWindowInterfaceV2 *) result;
InitWindowInterfaceV2(i);
return NPERR_NO_ERROR;
}
case kVideoInterfaceV0_ANPGetValue: {
LOG("get video interface");
ANPVideoInterfaceV0 *i = (ANPVideoInterfaceV0*) result;
InitVideoInterfaceV0(i);
return NPERR_NO_ERROR;
}
case kVideoInterfaceV1_ANPGetValue: {
LOG("get video interface");
ANPVideoInterfaceV1 *i = (ANPVideoInterfaceV1*) result;
InitVideoInterfaceV1(i);
return NPERR_NO_ERROR;
}
case kSystemInterfaceV1_ANPGetValue: {
LOG("get system interface v1");
ANPSystemInterfaceV1* i = reinterpret_cast<ANPSystemInterfaceV1*>(result);
InitSystemInterfaceV1(i);
return NPERR_NO_ERROR;
}
case kSystemInterfaceV2_ANPGetValue: {
LOG("get system interface v2");
ANPSystemInterfaceV2* i = reinterpret_cast<ANPSystemInterfaceV2*>(result);
InitSystemInterfaceV2(i);
return NPERR_NO_ERROR;
}
#endif
// we no longer hand out any XPCOM objects

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

@ -150,6 +150,8 @@ public:
#ifdef MOZ_WIDGET_ANDROID
PRUint32 GetANPDrawingModel() { return mANPDrawingModel; }
void SetANPDrawingModel(PRUint32 aModel);
// This stuff is for kSurface_ANPDrawingModel
void* GetJavaSurface();
void SetJavaSurface(void* aSurface);
void RequestJavaSurface();

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

@ -122,6 +122,7 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#include "ANPBase.h"
#include "android_npapi.h"
#include "AndroidBridge.h"
#include "AndroidMediaLayer.h"
using namespace mozilla::dom;
#include <android/log.h>
@ -262,23 +263,14 @@ nsPluginInstanceOwner::UseAsyncRendering()
if (mUseAsyncRendering) {
return true;
}
nsRefPtr<ImageContainer> container;
if (mObjectFrame) {
container = mObjectFrame->GetImageContainer();
}
#endif
bool useAsyncRendering;
bool result = (mInstance &&
NS_SUCCEEDED(mInstance->UseAsyncPainting(&useAsyncRendering)) &&
useAsyncRendering &&
#ifdef XP_MACOSX
container &&
container->GetBackendType() ==
LayerManager::LAYERS_OPENGL
#else
(!mPluginWindow ||
useAsyncRendering
#ifndef XP_MACOSX
&& (!mPluginWindow ||
mPluginWindow->type == NPWindowTypeDrawable)
#endif
);
@ -348,8 +340,9 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
mWaitingForPaint = false;
#ifdef MOZ_WIDGET_ANDROID
mPluginViewAdded = false;
mLastPluginRect = gfxRect(0, 0, 0, 0);
mOnScreen = false;
mInverted = false;
mLayer = new AndroidMediaLayer();
#endif
}
@ -400,6 +393,13 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
PLUG_DeletePluginNativeWindow(mPluginWindow);
mPluginWindow = nsnull;
#ifdef MOZ_WIDGET_ANDROID
if (mLayer) {
delete mLayer;
mLayer = nsnull;
}
#endif
if (mInstance) {
mInstance->InvalidateOwner();
}
@ -1683,6 +1683,43 @@ void nsPluginInstanceOwner::ScrollPositionDidChange(nscoord aX, nscoord aY)
}
#ifdef MOZ_WIDGET_ANDROID
void nsPluginInstanceOwner::SendSize(int width, int height)
{
if (!mInstance)
return;
PRInt32 model = mInstance->GetANPDrawingModel();
if (model != kOpenGL_ANPDrawingModel)
return;
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kDraw_ANPEventType;
event.data.draw.model = kOpenGL_ANPDrawingModel;
event.data.draw.data.surfaceSize.width = width;
event.data.draw.data.surfaceSize.height = height;
mInstance->HandleEvent(&event, nsnull);
}
void nsPluginInstanceOwner::SendOnScreenEvent(bool onScreen)
{
if (!mInstance)
return;
if ((onScreen && !mOnScreen) || (!onScreen && mOnScreen)) {
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kLifecycle_ANPEventType;
event.data.lifecycle.action = onScreen ? kOnScreen_ANPLifecycleAction : kOffScreen_ANPLifecycleAction;
mInstance->HandleEvent(&event, nsnull);
mOnScreen = onScreen;
}
}
bool nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect)
{
void* javaSurface = mInstance->GetJavaSurface();
@ -1691,11 +1728,6 @@ bool nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect)
return false;
}
if (aRect.IsEqualEdges(mLastPluginRect)) {
// Already added and in position, no work to do
return true;
}
JNIEnv* env = GetJNIForThread();
if (!env)
return false;
@ -1738,26 +1770,16 @@ bool nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect)
aRect.height);
#endif
if (!mPluginViewAdded) {
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kLifecycle_ANPEventType;
event.data.lifecycle.action = kOnScreen_ANPLifecycleAction;
mInstance->HandleEvent(&event, nsnull);
mPluginViewAdded = true;
}
SendOnScreenEvent(true);
return true;
}
void nsPluginInstanceOwner::RemovePluginView()
{
if (!mInstance || !mObjectFrame | !mPluginViewAdded)
if (!mInstance || !mObjectFrame | !mOnScreen)
return;
mPluginViewAdded = false;
void* surface = mInstance->GetJavaSurface();
if (!surface)
return;
@ -1773,13 +1795,17 @@ void nsPluginInstanceOwner::RemovePluginView()
"removePluginView",
"(Landroid/view/View;)V");
env->CallStaticVoidMethod(cls, method, surface);
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kLifecycle_ANPEventType;
event.data.lifecycle.action = kOffScreen_ANPLifecycleAction;
mInstance->HandleEvent(&event, nsnull);
SendOnScreenEvent(false);
}
void nsPluginInstanceOwner::Invalidate() {
NPRect rect;
rect.left = rect.top = 0;
rect.right = mPluginWindow->width;
rect.bottom = mPluginWindow->height;
InvalidateRect(&rect);
}
#endif
nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
@ -2861,15 +2887,21 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
if (model == kSurface_ANPDrawingModel) {
if (!AddPluginView(aFrameRect)) {
NPRect rect;
rect.left = rect.top = 0;
rect.right = aFrameRect.width;
rect.bottom = aFrameRect.height;
InvalidateRect(&rect);
Invalidate();
}
return;
}
if (model == kOpenGL_ANPDrawingModel) {
// FIXME: this is gross
float zoomLevel = aFrameRect.width / (float)mPluginWindow->width;
mLayer->UpdatePosition(aFrameRect, zoomLevel);
SendOnScreenEvent(true);
SendSize((int)aFrameRect.width, (int)aFrameRect.height);
return;
}
if (model != kBitmap_ANPDrawingModel)
return;
@ -3566,8 +3598,16 @@ void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(bool aSetWindow)
} else {
mPluginWindow->clipRect.right = 0;
mPluginWindow->clipRect.bottom = 0;
#ifdef MOZ_WIDGET_ANDROID
RemovePluginView();
#if 0 //MOZ_WIDGET_ANDROID
if (mInstance) {
PRInt32 model = mInstance->GetANPDrawingModel();
if (model == kSurface_ANPDrawingModel) {
RemovePluginView();
} else if (model == kOpenGL_ANPDrawingModel) {
HidePluginLayer();
}
}
#endif
}

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

@ -94,6 +94,12 @@ class gfxXlibSurface;
#include <os2.h>
#endif
#ifdef MOZ_WIDGET_ANDROID
namespace mozilla {
class AndroidMediaLayer;
}
#endif
// X.h defines KeyPress
#ifdef KeyPress
#undef KeyPress
@ -286,6 +292,26 @@ public:
void EndUpdateBackground(gfxContext* aContext, const nsIntRect& aRect);
bool UseAsyncRendering();
#ifdef MOZ_WIDGET_ANDROID
nsIntRect GetVisibleRect() {
return nsIntRect(0, 0, mPluginWindow->width, mPluginWindow->height);
}
void SetInverted(bool aInverted) {
mInverted = aInverted;
}
bool Inverted() {
return mInverted;
}
mozilla::AndroidMediaLayer* Layer() {
return mLayer;
}
void Invalidate();
#endif
private:
@ -298,11 +324,18 @@ private:
}
void FixUpURLS(const nsString &name, nsAString &value);
#ifdef ANDROID
#ifdef MOZ_WIDGET_ANDROID
void SendSize(int width, int height);
void SendOnScreenEvent(bool onScreen);
bool AddPluginView(const gfxRect& aRect);
void RemovePluginView();
bool mPluginViewAdded;
gfxRect mLastPluginRect;
bool mOnScreen;
bool mInverted;
// For kOpenGL_ANPDrawingModel
mozilla::AndroidMediaLayer *mLayer;
#endif
nsPluginNativeWindow *mPluginWindow;

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

@ -647,9 +647,6 @@ PluginInstanceParent::GetImage(ImageContainer* aContainer, Image** aImage)
#ifdef XP_MACOSX
if (ioSurface) {
format = Image::MAC_IO_SURFACE;
if (!aContainer->Manager()) {
return NS_ERROR_FAILURE;
}
}
#endif

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

@ -293,6 +293,8 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate)
JS_SetGCParameter(runtime, JSGC_MAX_BYTES,
aWorkerPrivate->GetJSRuntimeHeapSize());
JS_SetNativeStackQuota(runtime, WORKER_CONTEXT_NATIVE_STACK_LIMIT);
JSContext* workerCx = JS_NewContext(runtime, 0);
if (!workerCx) {
JS_DestroyRuntime(runtime);
@ -306,8 +308,6 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate)
JS_SetOperationCallback(workerCx, OperationCallback);
JS_SetNativeStackQuota(workerCx, WORKER_CONTEXT_NATIVE_STACK_LIMIT);
NS_ASSERTION((aWorkerPrivate->GetJSContextOptions() &
kRequiredJSContextOptions) == kRequiredJSContextOptions,
"Somehow we lost our required options!");

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

@ -155,6 +155,8 @@ SwapToISupportsArray(SmartPtr<T>& aSrc,
dest->swap(rawSupports);
}
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsWorkerMallocSizeOf, "js-worker")
class WorkerMemoryReporter : public nsIMemoryMultiReporter
{
WorkerPrivate* mWorkerPrivate;
@ -232,7 +234,7 @@ public:
{
AssertIsOnMainThread();
JS::RuntimeStats rtStats(xpc::JsMallocSizeOf, xpc::GetCompartmentName,
JS::RuntimeStats rtStats(JsWorkerMallocSizeOf, xpc::GetCompartmentName,
xpc::DestroyCompartmentName);
nsresult rv = CollectForRuntime(/* isQuick = */false, &rtStats);
if (NS_FAILED(rv)) {
@ -1523,7 +1525,7 @@ public:
JSAutoSuspendRequest asr(aCx);
*mSucceeded = mIsQuick
? JS::GetExplicitNonHeapForRuntime(JS_GetRuntime(aCx), static_cast<int64_t*>(mData), xpc::JsMallocSizeOf)
? JS::GetExplicitNonHeapForRuntime(JS_GetRuntime(aCx), static_cast<int64_t*>(mData), JsWorkerMallocSizeOf)
: JS::CollectRuntimeStats(JS_GetRuntime(aCx), static_cast<JS::RuntimeStats*>(mData));
{

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

@ -9,9 +9,17 @@
android:sharedUserId="@MOZ_ANDROID_SHARED_ID@"
#endif
>
<uses-sdk android:minSdkVersion="5"
android:targetSdkVersion="11"/>
#ifdef MOZ_TABLETS_ONLY
<supports-screens android:smallScreens="false"
android:normalScreens="false"
android:largeScreens="false"
android:xlargeScreens="true" />
#endif
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>

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

@ -1792,5 +1792,5 @@ public class GeckoAppShell
}
// This is only used in Native Fennec.
public static void preventPanning() { }
public static void setPreventPanning(final boolean aPreventPanning) { }
}

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

@ -79,7 +79,8 @@ MIN_CPU_VERSION=5
endif
ifeq (,$(ANDROID_VERSION_CODE))
ANDROID_VERSION_CODE=$(shell $(PYTHON) $(topsrcdir)/toolkit/xre/make-platformini.py --print-buildid | cut -c1-10)
# increment the version code by 1 so xul fennec will win any compatability ties
ANDROID_VERSION_CODE=$(shell echo `$(PYTHON) $(topsrcdir)/toolkit/xre/make-platformini.py --print-buildid | cut -c1-10` + 1 | bc)
endif
DEFINES += \
@ -94,6 +95,11 @@ DEFINES += \
-DMOZILLA_OFFICIAL=$(MOZILLA_OFFICIAL) \
$(NULL)
MOZ_MOBILE_COMPAT = @MOZ_MOBILE_COMPAT@
ifeq (Tablets,$(MOZ_MOBILE_COMPAT))
DEFINES += -DMOZ_TABLETS_ONLY=1
endif
GARBAGE += \
AndroidManifest.xml \
classes.dex \

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

@ -1108,8 +1108,6 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c
return true;
}
const bool firstTime = (mOffscreenDrawFBO == 0 && mOffscreenReadFBO == 0);
GLuint curBoundFramebufferDraw = 0;
GLuint curBoundFramebufferRead = 0;
GLuint curBoundRenderbuffer = 0;
@ -1412,8 +1410,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c
#ifdef DEBUG
if (DebugMode()) {
printf_stderr("%s %dx%d offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d samples: %d\n",
firstTime ? "Created" : "Resized",
printf_stderr("Resized %dx%d offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d samples: %d\n",
mOffscreenActualSize.width, mOffscreenActualSize.height,
mActualFormat.red, mActualFormat.green, mActualFormat.blue, mActualFormat.alpha,
mActualFormat.depth, mActualFormat.stencil, mActualFormat.samples);
@ -1429,13 +1426,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c
BindReadFBO(curBoundFramebufferRead);
fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture);
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer);
// -don't- restore the viewport the first time through this, since
// the previous one isn't valid.
if (firstTime)
fViewport(0, 0, aSize.width, aSize.height); // XXX This is coming out in 711642
else
fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
return true;
}

275
gfx/layers/ImageLayers.cpp Normal file
Просмотреть файл

@ -0,0 +1,275 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 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 "mozilla/ipc/Shmem.h"
#include "ImageLayers.h"
#include "gfxImageSurface.h"
#include "yuv_convert.h"
#ifdef XP_MACOSX
#include "nsCoreAnimationSupport.h"
#endif
using namespace mozilla::ipc;
namespace mozilla {
namespace layers {
already_AddRefed<Image>
ImageFactory::CreateImage(const Image::Format *aFormats,
PRUint32 aNumFormats,
const gfxIntSize &,
BufferRecycleBin *aRecycleBin)
{
if (!aNumFormats) {
return nsnull;
}
nsRefPtr<Image> img;
if (FormatInList(aFormats, aNumFormats, Image::PLANAR_YCBCR)) {
img = new PlanarYCbCrImage(aRecycleBin);
} else if (FormatInList(aFormats, aNumFormats, Image::CAIRO_SURFACE)) {
img = new CairoImage();
#ifdef XP_MACOSX
} else if (FormatInList(aFormats, aNumFormats, Image::MAC_IO_SURFACE)) {
img = new MacIOSurfaceImage();
#endif
}
return img.forget();
}
BufferRecycleBin::BufferRecycleBin()
: mLock("mozilla.layers.BufferRecycleBin.mLock")
{
}
void
BufferRecycleBin::RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize)
{
MutexAutoLock lock(mLock);
if (!mRecycledBuffers.IsEmpty() && aSize != mRecycledBufferSize) {
mRecycledBuffers.Clear();
}
mRecycledBufferSize = aSize;
mRecycledBuffers.AppendElement(aBuffer);
}
PRUint8*
BufferRecycleBin::GetBuffer(PRUint32 aSize)
{
MutexAutoLock lock(mLock);
if (mRecycledBuffers.IsEmpty() || mRecycledBufferSize != aSize)
return new PRUint8[aSize];
PRUint32 last = mRecycledBuffers.Length() - 1;
PRUint8* result = mRecycledBuffers[last].forget();
mRecycledBuffers.RemoveElementAt(last);
return result;
}
ImageContainer::~ImageContainer()
{
}
already_AddRefed<Image>
ImageContainer::CreateImage(const Image::Format *aFormats,
PRUint32 aNumFormats)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
return mImageFactory->CreateImage(aFormats, aNumFormats, mScaleHint, mRecycleBin);
}
void
ImageContainer::SetCurrentImage(Image *aImage)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mActiveImage = aImage;
CurrentImageChanged();
}
already_AddRefed<gfxASurface>
ImageContainer::GetCurrentAsSurface(gfxIntSize *aSize)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mActiveImage) {
return nsnull;
}
*aSize = mActiveImage->GetSize();
return mActiveImage->GetAsSurface();
}
gfxIntSize
ImageContainer::GetCurrentSize()
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mActiveImage) {
return gfxIntSize(0,0);
}
return mActiveImage->GetSize();
}
PlanarYCbCrImage::PlanarYCbCrImage(BufferRecycleBin *aRecycleBin)
: Image(nsnull, PLANAR_YCBCR)
, mBufferSize(0)
, mRecycleBin(aRecycleBin)
{
}
PlanarYCbCrImage::~PlanarYCbCrImage()
{
if (mBuffer) {
mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
}
}
PRUint8*
PlanarYCbCrImage::AllocateBuffer(PRUint32 aSize)
{
return mRecycleBin->GetBuffer(aSize);
}
void
PlanarYCbCrImage::CopyData(const Data& aData)
{
mData = aData;
mData.mYStride = mData.mYSize.width;
mData.mCbCrStride = mData.mCbCrSize.width;
// update buffer size
mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
mData.mYStride * mData.mYSize.height;
// get new buffer
mBuffer = AllocateBuffer(mBufferSize);
if (!mBuffer)
return;
mData.mYChannel = mBuffer;
mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
for (int i = 0; i < mData.mYSize.height; i++) {
memcpy(mData.mYChannel + i * mData.mYStride,
aData.mYChannel + i * aData.mYStride,
mData.mYStride);
}
for (int i = 0; i < mData.mCbCrSize.height; i++) {
memcpy(mData.mCbChannel + i * mData.mCbCrStride,
aData.mCbChannel + i * aData.mCbCrStride,
mData.mCbCrStride);
memcpy(mData.mCrChannel + i * mData.mCbCrStride,
aData.mCrChannel + i * aData.mCbCrStride,
mData.mCbCrStride);
}
mSize = aData.mPicSize;
}
void
PlanarYCbCrImage::SetData(const Data &aData)
{
CopyData(aData);
}
already_AddRefed<gfxASurface>
PlanarYCbCrImage::GetAsSurface()
{
if (mSurface) {
nsRefPtr<gfxASurface> result = mSurface.get();
return result.forget();
}
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24);
gfx::YUVType type =
gfx::TypeFromSize(mData.mYSize.width,
mData.mYSize.height,
mData.mCbCrSize.width,
mData.mCbCrSize.height);
// Convert from YCbCr to RGB now
gfx::ConvertYCbCrToRGB32(mData.mYChannel,
mData.mCbChannel,
mData.mCrChannel,
imageSurface->Data(),
mData.mPicX,
mData.mPicY,
mData.mPicSize.width,
mData.mPicSize.height,
mData.mYStride,
mData.mCbCrStride,
imageSurface->Stride(),
type);
mSurface = imageSurface;
return imageSurface.forget().get();
}
#ifdef XP_MACOSX
void
MacIOSurfaceImage::SetData(const Data& aData)
{
mIOSurface = nsIOSurface::LookupSurface(aData.mIOSurface->GetIOSurfaceID());
mSize = gfxIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight());
}
already_AddRefed<gfxASurface>
MacIOSurfaceImage::GetAsSurface()
{
return mIOSurface->GetAsSurface();
}
void
MacIOSurfaceImage::Update(ImageContainer* aContainer)
{
if (mUpdateCallback) {
mUpdateCallback(aContainer, mPluginInstanceOwner);
}
}
#endif
}
}

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

@ -46,8 +46,12 @@
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/mozalloc.h"
#include "mozilla/Mutex.h"
#include "gfxPlatform.h"
class nsIOSurface;
#ifdef XP_MACOSX
#include "nsIOSurface.h"
#endif
namespace mozilla {
namespace layers {
@ -60,6 +64,14 @@ enum StereoMode {
STEREO_MODE_TOP_BOTTOM
};
struct ImageBackendData
{
virtual ~ImageBackendData() {}
protected:
ImageBackendData() {}
};
/**
* A class representing a buffer of pixel data. The data can be in one
* of various formats including YCbCr.
@ -104,8 +116,7 @@ public:
CAIRO_SURFACE,
/**
* The MAC_IO_SURFACE format creates a MacIOSurfaceImage. This
* is only supported on Mac with OpenGL layers.
* The MAC_IO_SURFACE format creates a MacIOSurfaceImage.
*
* It wraps an IOSurface object and binds it directly to a GL texture.
*/
@ -115,16 +126,106 @@ public:
Format GetFormat() { return mFormat; }
void* GetImplData() { return mImplData; }
virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
virtual gfxIntSize GetSize() = 0;
ImageBackendData* GetBackendData(LayerManager::LayersBackend aBackend)
{ return mBackendData[aBackend]; }
void SetBackendData(LayerManager::LayersBackend aBackend, ImageBackendData* aData)
{ mBackendData[aBackend] = aData; }
protected:
Image(void* aImplData, Format aFormat) :
mImplData(aImplData),
mFormat(aFormat)
{}
nsAutoPtr<ImageBackendData> mBackendData[LayerManager::LAYERS_LAST];
void* mImplData;
Format mFormat;
};
/**
* A RecycleBin is owned by an ImageContainer. We store buffers in it that we
* want to recycle from one image to the next.It's a separate object from
* ImageContainer because images need to store a strong ref to their RecycleBin
* and we must avoid creating a reference loop between an ImageContainer and
* its active image.
*/
class BufferRecycleBin {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RecycleBin)
typedef mozilla::gl::GLContext GLContext;
public:
BufferRecycleBin();
void RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize);
// Returns a recycled buffer of the right size, or allocates a new buffer.
PRUint8* GetBuffer(PRUint32 aSize);
private:
typedef mozilla::Mutex Mutex;
// This protects mRecycledBuffers, mRecycledBufferSize, mRecycledTextures
// and mRecycledTextureSizes
Mutex mLock;
// We should probably do something to prune this list on a timer so we don't
// eat excess memory while video is paused...
nsTArray<nsAutoArrayPtr<PRUint8> > mRecycledBuffers;
// This is only valid if mRecycledBuffers is non-empty
PRUint32 mRecycledBufferSize;
};
/**
* Returns true if aFormat is in the given format array.
*/
static inline bool
FormatInList(const Image::Format* aFormats, PRUint32 aNumFormats,
Image::Format aFormat)
{
for (PRUint32 i = 0; i < aNumFormats; ++i) {
if (aFormats[i] == aFormat) {
return true;
}
}
return false;
}
/**
* A class that manages Image creation for a LayerManager. The only reason
* we need a separate class here is that LayerMananers aren't threadsafe
* (because layers can only be used on the main thread) and we want to
* be able to create images from any thread, to facilitate video playback
* without involving the main thread, for example.
* Different layer managers can implement child classes of this making it
* possible to create layer manager specific images.
* This class is not meant to be used directly but rather can be set on an
* image container. This is usually done by the layer system internally and
* not explicitly by users. For PlanarYCbCr or Cairo images the default
* implementation will creates images whose data lives in system memory, for
* MacIOSurfaces the default implementation will be a simple nsIOSurface
* wrapper.
*/
class THEBES_API ImageFactory
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageFactory)
protected:
friend class ImageContainer;
ImageFactory() {}
virtual ~ImageFactory() {}
virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
PRUint32 aNumFormats,
const gfxIntSize &aScaleHint,
BufferRecycleBin *aRecycleBin);
};
/**
* A class that manages Images for an ImageLayer. The only reason
* we need a separate class here is that ImageLayers aren't threadsafe
@ -139,10 +240,12 @@ public:
ImageContainer() :
mReentrantMonitor("ImageContainer.mReentrantMonitor"),
mPaintCount(0),
mPreviousImagePainted(false)
mPreviousImagePainted(false),
mImageFactory(new ImageFactory()),
mRecycleBin(new BufferRecycleBin())
{}
virtual ~ImageContainer() {}
~ImageContainer();
/**
* Create an Image in one of the given formats.
@ -152,8 +255,8 @@ public:
* Can be called on any thread. This method takes mReentrantMonitor
* when accessing thread-shared state.
*/
virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
PRUint32 aNumFormats) = 0;
already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
PRUint32 aNumFormats);
/**
* Set an Image as the current image to display. The Image must have
@ -163,13 +266,7 @@ public:
*
* The Image data must not be modified after this method is called!
*/
virtual void SetCurrentImage(Image* aImage) = 0;
/**
* Ask any PlanarYCbCr images created by this container to delay
* YUV -> RGB conversion until draw time. See PlanarYCbCrImage::SetDelayedConversion.
*/
virtual void SetDelayedConversion(bool aDelayed) {}
void SetCurrentImage(Image* aImage);
/**
* Get the current Image.
@ -181,7 +278,13 @@ public:
* Implementations must call CurrentImageChanged() while holding
* mReentrantMonitor.
*/
virtual already_AddRefed<Image> GetCurrentImage() = 0;
already_AddRefed<Image> GetCurrentImage()
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
nsRefPtr<Image> retval = mActiveImage;
return retval.forget();
}
/**
* Get the current image as a gfxASurface. This is useful for fallback
@ -198,32 +301,14 @@ public:
* Can be called on any thread. This method takes mReentrantMonitor
* when accessing thread-shared state.
*/
virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSizeResult) = 0;
/**
* Returns the layer manager for this container. This can only
* be used on the main thread, since layer managers should only be
* accessed on the main thread.
*/
LayerManager* Manager()
{
NS_PRECONDITION(NS_IsMainThread(), "Must be called on main thread");
return mManager;
}
already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSizeResult);
/**
* Returns the size of the image in pixels.
* Can be called on any thread. This method takes mReentrantMonitor when accessing
* thread-shared state.
*/
virtual gfxIntSize GetCurrentSize() = 0;
/**
* Set a new layer manager for this image container. It must be
* either of the same type as the container's current layer manager,
* or null. TRUE is returned on success. Main thread only.
*/
virtual bool SetLayerManager(LayerManager *aManager) = 0;
gfxIntSize GetCurrentSize();
/**
* Sets a size that the image is expected to be rendered at.
@ -232,14 +317,14 @@ public:
* Can be called on any thread. This method takes mReentrantMonitor
* when accessing thread-shared state.
*/
virtual void SetScaleHint(const gfxIntSize& /* aScaleHint */) { }
void SetScaleHint(const gfxIntSize& aScaleHint)
{ mScaleHint = aScaleHint; }
/**
* Get the layer manager type this image container was created with,
* presumably its users might want to do something special if types do not
* match. Can be called on any thread.
*/
virtual LayerManager::LayersBackend GetBackendType() = 0;
void SetImageFactory(ImageFactory *aFactory)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mImageFactory = aFactory ? aFactory : new ImageFactory();
}
/**
* Returns the time at which the currently contained image was first
@ -285,19 +370,11 @@ public:
protected:
typedef mozilla::ReentrantMonitor ReentrantMonitor;
LayerManager* mManager;
// ReentrantMonitor to protect thread safe access to the "current
// image", and any other state which is shared between threads.
ReentrantMonitor mReentrantMonitor;
ImageContainer(LayerManager* aManager) :
mManager(aManager),
mReentrantMonitor("ImageContainer.mReentrantMonitor"),
mPaintCount(0),
mPreviousImagePainted(false)
{}
// Performs necessary housekeeping to ensure the painted frame statistics
// are accurate. Must be called by SetCurrentImage() implementations with
// mReentrantMonitor held.
@ -307,6 +384,8 @@ protected:
mPaintTime = TimeStamp();
}
nsRefPtr<Image> mActiveImage;
// Number of contained images that have been painted at least once. It's up
// to the ImageContainer implementation to ensure accesses to this are
// threadsafe.
@ -318,6 +397,15 @@ protected:
// Denotes whether the previous image was painted.
bool mPreviousImagePainted;
// This is the image factory used by this container, layer managers using
// this container can set an alternative image factory that will be used to
// create images for this container.
nsRefPtr<ImageFactory> mImageFactory;
gfxIntSize mScaleHint;
nsRefPtr<BufferRecycleBin> mRecycleBin;
};
/**
@ -332,8 +420,6 @@ public:
*/
void SetContainer(ImageContainer* aContainer)
{
NS_ASSERTION(!aContainer->Manager() || aContainer->Manager() == Manager(),
"ImageContainer must have the same manager as the ImageLayer");
mContainer = aContainer;
}
/**
@ -422,13 +508,13 @@ public:
MAX_DIMENSION = 16384
};
~PlanarYCbCrImage();
/**
* This makes a copy of the data buffers.
* XXX Eventually we will change this to not make a copy of the data,
* Right now it doesn't matter because the BasicLayer implementation
* does YCbCr conversion here anyway.
* This makes a copy of the data buffers, in order to support functioning
* in all different layer managers.
*/
virtual void SetData(const Data& aData) = 0;
virtual void SetData(const Data& aData);
/**
* Ask this Image to not convert YUV to RGB during SetData, and make
@ -440,19 +526,14 @@ public:
/**
* Grab the original YUV data. This is optional.
*/
virtual const Data* GetData() { return nsnull; }
virtual const Data* GetData() { return &mData; }
/**
* Make a copy of the YCbCr data.
* Make a copy of the YCbCr data into local storage.
*
* @param aDest Data object to store the plane data in.
* @param aDestSize Size of the Y plane that was copied.
* @param aDestBufferSize Number of bytes allocated for storage.
* @param aData Input image data.
* @return Raw data pointer for the planes or nsnull on failure.
*/
PRUint8 *CopyData(Data& aDest, gfxIntSize& aDestSize,
PRUint32& aDestBufferSize, const Data& aData);
void CopyData(const Data& aData);
/**
* Return a buffer to store image data in.
@ -464,15 +545,31 @@ public:
/**
* Return the number of bytes of heap memory used to store this image.
*/
virtual PRUint32 GetDataSize() = 0;
virtual PRUint32 GetDataSize() { return mBufferSize; }
protected:
PlanarYCbCrImage(void* aImplData) : Image(aImplData, PLANAR_YCBCR) {}
already_AddRefed<gfxASurface> GetAsSurface();
virtual gfxIntSize GetSize() { return mSize; }
void SetOffscreenFormat(gfxImageFormat aFormat) { mOffscreenFormat = aFormat; }
gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
// XXX - not easy to protect these sadly.
nsAutoArrayPtr<PRUint8> mBuffer;
PRUint32 mBufferSize;
Data mData;
gfxIntSize mSize;
gfxImageFormat mOffscreenFormat;
nsCountedRef<nsMainThreadSurfaceRef> mSurface;
nsRefPtr<BufferRecycleBin> mRecycleBin;
PlanarYCbCrImage(BufferRecycleBin *aRecycleBin);
};
/**
* Currently, the data in a CairoImage surface is treated as being in the
* device output color space.
* device output color space. This class is very simple as all backends
* have to know about how to deal with drawing a cairo image.
*/
class THEBES_API CairoImage : public Image {
public:
@ -486,10 +583,26 @@ public:
* to the surface (which will eventually be released on the main thread).
* The surface must not be modified after this call!!!
*/
virtual void SetData(const Data& aData) = 0;
void SetData(const Data& aData)
{
mSurface = aData.mSurface;
mSize = aData.mSize;
}
protected:
CairoImage(void* aImplData) : Image(aImplData, CAIRO_SURFACE) {}
virtual already_AddRefed<gfxASurface> GetAsSurface()
{
NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
nsRefPtr<gfxASurface> surface = mSurface.get();
return surface.forget();
}
gfxIntSize GetSize() { return mSize; }
CairoImage() : Image(NULL, CAIRO_SURFACE) {}
nsCountedRef<nsMainThreadSurfaceRef> mSurface;
gfxIntSize mSize;
};
#ifdef XP_MACOSX
@ -499,12 +612,27 @@ public:
nsIOSurface* mIOSurface;
};
MacIOSurfaceImage()
: Image(NULL, MAC_IO_SURFACE)
, mSize(0, 0)
, mPluginInstanceOwner(NULL)
, mUpdateCallback(NULL)
, mDestroyCallback(NULL)
{}
virtual ~MacIOSurfaceImage()
{
if (mDestroyCallback) {
mDestroyCallback(mPluginInstanceOwner);
}
}
/**
* This can only be called on the main thread. It may add a reference
* to the surface (which will eventually be released on the main thread).
* The surface must not be modified after this call!!!
*/
virtual void SetData(const Data& aData) = 0;
virtual void SetData(const Data& aData);
/**
* Temporary hacks to force plugin drawing during an empty transaction.
@ -512,12 +640,38 @@ public:
* when async plugin rendering is complete.
*/
typedef void (*UpdateSurfaceCallback)(ImageContainer* aContainer, void* aInstanceOwner);
virtual void SetUpdateCallback(UpdateSurfaceCallback aCallback, void* aInstanceOwner) = 0;
typedef void (*DestroyCallback)(void* aInstanceOwner);
virtual void SetDestroyCallback(DestroyCallback aCallback) = 0;
virtual void SetUpdateCallback(UpdateSurfaceCallback aCallback, void* aInstanceOwner)
{
mUpdateCallback = aCallback;
mPluginInstanceOwner = aInstanceOwner;
}
protected:
MacIOSurfaceImage(void* aImplData) : Image(aImplData, MAC_IO_SURFACE) {}
typedef void (*DestroyCallback)(void* aInstanceOwner);
virtual void SetDestroyCallback(DestroyCallback aCallback)
{
mDestroyCallback = aCallback;
}
virtual gfxIntSize GetSize()
{
return mSize;
}
nsIOSurface* GetIOSurface()
{
return mIOSurface;
}
void Update(ImageContainer* aContainer);
virtual already_AddRefed<gfxASurface> GetAsSurface();
private:
gfxIntSize mSize;
nsRefPtr<nsIOSurface> mIOSurface;
void* mPluginInstanceOwner;
UpdateSurfaceCallback mUpdateCallback;
DestroyCallback mDestroyCallback;
};
#endif

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

@ -229,6 +229,13 @@ LayerManager::Mutated(Layer* aLayer)
}
#endif // DEBUG
already_AddRefed<ImageContainer>
LayerManager::CreateImageContainer()
{
nsRefPtr<ImageContainer> container = new ImageContainer();
return container.forget();
}
//--------------------------------------------------
// Layer
@ -513,54 +520,7 @@ ContainerLayer::DidInsertChild(Layer* aLayer)
mMayHaveReadbackChild = true;
}
}
PRUint8*
PlanarYCbCrImage::AllocateBuffer(PRUint32 aSize)
{
const fallible_t fallible = fallible_t();
return new (fallible) PRUint8[aSize];
}
PRUint8*
PlanarYCbCrImage::CopyData(Data& aDest, gfxIntSize& aDestSize,
PRUint32& aDestBufferSize, const Data& aData)
{
aDest = aData;
aDest.mYStride = aDest.mYSize.width;
aDest.mCbCrStride = aDest.mCbCrSize.width;
// update buffer size
aDestBufferSize = aDest.mCbCrStride * aDest.mCbCrSize.height * 2 +
aDest.mYStride * aDest.mYSize.height;
// get new buffer
PRUint8* buffer = AllocateBuffer(aDestBufferSize);
if (!buffer)
return nsnull;
aDest.mYChannel = buffer;
aDest.mCbChannel = aDest.mYChannel + aDest.mYStride * aDest.mYSize.height;
aDest.mCrChannel = aDest.mCbChannel + aDest.mCbCrStride * aDest.mCbCrSize.height;
for (int i = 0; i < aDest.mYSize.height; i++) {
memcpy(aDest.mYChannel + i * aDest.mYStride,
aData.mYChannel + i * aData.mYStride,
aDest.mYStride);
}
for (int i = 0; i < aDest.mCbCrSize.height; i++) {
memcpy(aDest.mCbChannel + i * aDest.mCbCrStride,
aData.mCbChannel + i * aData.mCbCrStride,
aDest.mCbCrStride);
memcpy(aDest.mCrChannel + i * aDest.mCbCrStride,
aData.mCrChannel + i * aData.mCbCrStride,
aDest.mCbCrStride);
}
aDestSize = aData.mPicSize;
return buffer;
}
void
LayerManager::StartFrameTimeRecording()
{

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

@ -49,6 +49,7 @@
#include "gfxColor.h"
#include "gfxPattern.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/TimeStamp.h"
@ -428,9 +429,9 @@ public:
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer() { return nsnull; }
/**
* Can be called anytime
* Can be called anytime, from any thread.
*/
virtual already_AddRefed<ImageContainer> CreateImageContainer() = 0;
static already_AddRefed<ImageContainer> CreateImageContainer();
/**
* Type of layer manager his is. This is to be used sparsely in order to

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

@ -82,14 +82,9 @@ CPPSRCS = \
LayerManagerOGL.cpp \
ThebesLayerOGL.cpp \
LayerSorter.cpp \
ImageLayers.cpp \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
CMMSRCS = \
MacIOSurfaceImageOGL.mm \
$(NULL)
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
ifdef MOZ_ENABLE_D3D9_LAYER
EXPORTS += \

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

@ -56,106 +56,70 @@ using mozilla::ReentrantMonitor;
namespace mozilla {
namespace layers {
/**
* All our images can yield up a cairo surface and their size.
*/
class BasicImageImplData {
class BasicPlanarYCbCrImage : public PlanarYCbCrImage
{
public:
/**
* This must be called on the main thread.
*/
virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
BasicPlanarYCbCrImage(const gfxIntSize& aScaleHint, gfxImageFormat aOffscreenFormat, BufferRecycleBin *aRecycleBin)
: PlanarYCbCrImage(aRecycleBin)
, mScaleHint(aScaleHint)
, mOffscreenFormat(aOffscreenFormat)
{}
gfxIntSize GetSize() { return mSize; }
protected:
gfxIntSize mSize;
};
/**
* Since BasicLayers only paint on the main thread, handling a CairoImage
* is extremely simple. We just hang on to a reference to the surface and
* return that surface when BasicImageLayer::Paint asks for it via
* BasicImageContainer::GetAsSurface.
*/
class BasicCairoImage : public CairoImage, public BasicImageImplData {
public:
BasicCairoImage() : CairoImage(static_cast<BasicImageImplData*>(this)) {}
virtual void SetData(const Data& aData)
~BasicPlanarYCbCrImage()
{
mSurface = aData.mSurface;
mSize = aData.mSize;
if (mDecodedBuffer) {
// Right now this only happens if the Image was never drawn, otherwise
// this will have been tossed away at surface destruction.
mRecycleBin->RecycleBuffer(mDecodedBuffer.forget(), mSize.height * mStride);
}
}
virtual already_AddRefed<gfxASurface> GetAsSurface()
{
NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
nsRefPtr<gfxASurface> surface = mSurface.get();
return surface.forget();
}
protected:
nsCountedRef<nsMainThreadSurfaceRef> mSurface;
};
/**
* We handle YCbCr by converting to RGB when the image is initialized
* (which should be done off the main thread). The RGB results are stored
* in a memory buffer and converted to a cairo surface lazily.
*/
class BasicPlanarYCbCrImage : public PlanarYCbCrImage, public BasicImageImplData {
typedef gfxASurface::gfxImageFormat gfxImageFormat;
public:
/**
* aScaleHint is a size that the image is expected to be rendered at.
* This is a hint for image backends to optimize scaling.
*/
BasicPlanarYCbCrImage(const gfxIntSize& aScaleHint) :
PlanarYCbCrImage(static_cast<BasicImageImplData*>(this)),
mScaleHint(aScaleHint),
mOffscreenFormat(gfxASurface::ImageFormatUnknown),
mDelayedConversion(false)
{}
virtual void SetData(const Data& aData);
virtual void SetDelayedConversion(bool aDelayed) { mDelayedConversion = aDelayed; }
already_AddRefed<gfxASurface> GetAsSurface();
virtual already_AddRefed<gfxASurface> GetAsSurface();
private:
gfxIntSize mScaleHint;
gfxImageFormat mOffscreenFormat;
int mStride;
nsAutoArrayPtr<PRUint8> mDecodedBuffer;
};
const Data* GetData() { return &mData; }
class BasicImageFactory : public ImageFactory
{
public:
BasicImageFactory() {}
void SetOffscreenFormat(gfxImageFormat aFormat) { mOffscreenFormat = aFormat; }
gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
PRUint32 aNumFormats,
const gfxIntSize &aScaleHint,
BufferRecycleBin *aRecycleBin)
{
if (!aNumFormats) {
return nsnull;
}
PRUint32 GetDataSize() { return mBuffer ? mDelayedConversion ? mBufferSize : mSize.height * mStride : 0; }
nsRefPtr<Image> image;
if (aFormats[0] == Image::PLANAR_YCBCR) {
image = new BasicPlanarYCbCrImage(aScaleHint, gfxPlatform::GetPlatform()->GetOffscreenFormat(), aRecycleBin);
return image.forget();
}
protected:
nsAutoArrayPtr<PRUint8> mBuffer;
nsCountedRef<nsMainThreadSurfaceRef> mSurface;
gfxIntSize mScaleHint;
PRInt32 mStride;
gfxImageFormat mOffscreenFormat;
Data mData;
PRUint32 mBufferSize;
bool mDelayedConversion;
return ImageFactory::CreateImage(aFormats, aNumFormats, aScaleHint, aRecycleBin);
}
};
void
BasicPlanarYCbCrImage::SetData(const Data& aData)
{
PlanarYCbCrImage::SetData(aData);
// Do some sanity checks to prevent integer overflow
if (aData.mYSize.width > PlanarYCbCrImage::MAX_DIMENSION ||
aData.mYSize.height > PlanarYCbCrImage::MAX_DIMENSION) {
NS_ERROR("Illegal image source width or height");
return;
}
if (mDelayedConversion) {
mBuffer = CopyData(mData, mSize, mBufferSize, aData);
return;
}
gfxASurface::gfxImageFormat format = GetOffscreenFormat();
gfxIntSize size(mScaleHint);
@ -167,13 +131,13 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
}
mStride = gfxASurface::FormatStrideForWidth(format, size.width);
mBuffer = AllocateBuffer(size.height * mStride);
if (!mBuffer) {
mDecodedBuffer = AllocateBuffer(size.height * mStride);
if (!mDecodedBuffer) {
// out of memory
return;
}
gfxUtils::ConvertYCbCrToRGB(aData, format, size, mBuffer, mStride);
gfxUtils::ConvertYCbCrToRGB(aData, format, size, mDecodedBuffer, mStride);
SetOffscreenFormat(format);
mSize = size;
}
@ -196,22 +160,20 @@ BasicPlanarYCbCrImage::GetAsSurface()
return result.forget();
}
// XXX: If we forced delayed conversion, are we ever going to hit this?
// We may need to implement the conversion here.
if (!mBuffer || mDelayedConversion) {
return nsnull;
if (!mDecodedBuffer) {
return PlanarYCbCrImage::GetAsSurface();
}
gfxASurface::gfxImageFormat format = GetOffscreenFormat();
nsRefPtr<gfxImageSurface> imgSurface =
new gfxImageSurface(mBuffer, mSize, mStride, format);
new gfxImageSurface(mDecodedBuffer, mSize, mStride, format);
if (!imgSurface || imgSurface->CairoStatus() != 0) {
return nsnull;
}
// Pass ownership of the buffer to the surface
imgSurface->SetData(&imageSurfaceDataKey, mBuffer.forget(), DestroyBuffer);
imgSurface->SetData(&imageSurfaceDataKey, mDecodedBuffer.forget(), DestroyBuffer);
nsRefPtr<gfxASurface> result = imgSurface.get();
#if defined(XP_MACOSX)
@ -221,144 +183,20 @@ BasicPlanarYCbCrImage::GetAsSurface()
result = quartzSurface.forget();
}
#endif
mSurface = result.get();
mSurface = result;
return result.forget();
}
/**
* Our image container is very simple. It's really just a factory
* for the image objects. We use a ReentrantMonitor to synchronize access to
* mImage.
*/
class BasicImageContainer : public ImageContainer {
public:
typedef gfxASurface::gfxImageFormat gfxImageFormat;
BasicImageContainer() :
ImageContainer(nsnull),
mScaleHint(-1, -1),
mOffscreenFormat(gfxASurface::ImageFormatUnknown),
mDelayed(false)
{}
virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
PRUint32 aNumFormats);
virtual void SetDelayedConversion(bool aDelayed) { mDelayed = aDelayed; }
virtual void SetCurrentImage(Image* aImage);
virtual already_AddRefed<Image> GetCurrentImage();
virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
virtual gfxIntSize GetCurrentSize();
virtual bool SetLayerManager(LayerManager *aManager);
virtual void SetScaleHint(const gfxIntSize& aScaleHint);
void SetOffscreenFormat(gfxImageFormat aFormat) { mOffscreenFormat = aFormat; }
virtual LayerManager::LayersBackend GetBackendType() { return LayerManager::LAYERS_BASIC; }
protected:
nsRefPtr<Image> mImage;
gfxIntSize mScaleHint;
gfxImageFormat mOffscreenFormat;
bool mDelayed;
};
/**
* Returns true if aFormat is in the given format array.
*/
static bool
FormatInList(const Image::Format* aFormats, PRUint32 aNumFormats,
Image::Format aFormat)
ImageFactory*
BasicLayerManager::GetImageFactory()
{
for (PRUint32 i = 0; i < aNumFormats; ++i) {
if (aFormats[i] == aFormat) {
return true;
}
}
return false;
}
already_AddRefed<Image>
BasicImageContainer::CreateImage(const Image::Format* aFormats,
PRUint32 aNumFormats)
{
nsRefPtr<Image> image;
// Prefer cairo surfaces because they're native for us
if (FormatInList(aFormats, aNumFormats, Image::CAIRO_SURFACE)) {
image = new BasicCairoImage();
} else if (FormatInList(aFormats, aNumFormats, Image::PLANAR_YCBCR)) {
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
image = new BasicPlanarYCbCrImage(mScaleHint);
static_cast<BasicPlanarYCbCrImage*>(image.get())->SetOffscreenFormat(mOffscreenFormat);
static_cast<BasicPlanarYCbCrImage*>(image.get())->SetDelayedConversion(mDelayed);
}
return image.forget();
}
void
BasicImageContainer::SetCurrentImage(Image* aImage)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mImage = aImage;
CurrentImageChanged();
}
already_AddRefed<Image>
BasicImageContainer::GetCurrentImage()
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
nsRefPtr<Image> image = mImage;
return image.forget();
}
static BasicImageImplData*
ToImageData(Image* aImage)
{
return static_cast<BasicImageImplData*>(aImage->GetImplData());
}
already_AddRefed<gfxASurface>
BasicImageContainer::GetCurrentAsSurface(gfxIntSize* aSizeResult)
{
NS_PRECONDITION(NS_IsMainThread(), "Must be called on main thread");
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mImage) {
return nsnull;
}
*aSizeResult = ToImageData(mImage)->GetSize();
return ToImageData(mImage)->GetAsSurface();
}
gfxIntSize
BasicImageContainer::GetCurrentSize()
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
return !mImage ? gfxIntSize(0,0) : ToImageData(mImage)->GetSize();
}
void BasicImageContainer::SetScaleHint(const gfxIntSize& aScaleHint)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mScaleHint = aScaleHint;
}
bool
BasicImageContainer::SetLayerManager(LayerManager *aManager)
{
if (aManager &&
aManager->GetBackendType() != LayerManager::LAYERS_BASIC)
{
return false;
if (!mFactory) {
mFactory = new BasicImageFactory();
}
return true;
}
already_AddRefed<ImageContainer>
BasicLayerManager::CreateImageContainer()
{
nsRefPtr<ImageContainer> container = new BasicImageContainer();
static_cast<BasicImageContainer*>(container.get())->
SetOffscreenFormat(gfxPlatform::GetPlatform()->GetOffscreenFormat());
return container.forget();
return mFactory.get();
}
}

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

@ -899,6 +899,8 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
if (!mContainer)
return nsnull;
mContainer->SetImageFactory(mManager->IsCompositingCheap() ? nsnull : BasicManager()->GetImageFactory());
nsRefPtr<Image> image = mContainer->GetCurrentImage();
nsRefPtr<gfxASurface> surface = mContainer->GetCurrentAsSurface(&mSize);

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

@ -131,9 +131,10 @@ public:
virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
virtual already_AddRefed<ImageLayer> CreateImageLayer();
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
virtual already_AddRefed<ImageContainer> CreateImageContainer();
virtual already_AddRefed<ColorLayer> CreateColorLayer();
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
virtual ImageFactory *GetImageFactory();
virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer()
{ return nsnull; }
virtual already_AddRefed<ShadowContainerLayer> CreateShadowContainerLayer()
@ -207,6 +208,8 @@ protected:
nsRefPtr<gfxContext> mDefaultTarget;
// The context to draw into.
nsRefPtr<gfxContext> mTarget;
// Image factory we use.
nsRefPtr<ImageFactory> mFactory;
// Cached surface for double buffering
gfxCachedTempSurface mCachedSurface;
@ -276,54 +279,4 @@ private:
}
}
/**
* We need to be able to hold a reference to a gfxASurface from Image
* subclasses. This is potentially a problem since Images can be addrefed
* or released off the main thread. We can ensure that we never AddRef
* a gfxASurface off the main thread, but we might want to Release due
* to an Image being destroyed off the main thread.
*
* We use nsCountedRef<nsMainThreadSurfaceRef> to reference the
* gfxASurface. When AddRefing, we assert that we're on the main thread.
* When Releasing, if we're not on the main thread, we post an event to
* the main thread to do the actual release.
*/
class nsMainThreadSurfaceRef;
template <>
class nsAutoRefTraits<nsMainThreadSurfaceRef> {
public:
typedef gfxASurface* RawRef;
/**
* The XPCOM event that will do the actual release on the main thread.
*/
class SurfaceReleaser : public nsRunnable {
public:
SurfaceReleaser(RawRef aRef) : mRef(aRef) {}
NS_IMETHOD Run() {
mRef->Release();
return NS_OK;
}
RawRef mRef;
};
static RawRef Void() { return nsnull; }
static void Release(RawRef aRawRef)
{
if (NS_IsMainThread()) {
aRawRef->Release();
return;
}
nsCOMPtr<nsIRunnable> runnable = new SurfaceReleaser(aRawRef);
NS_DispatchToMainThread(runnable);
}
static void AddRef(RawRef aRawRef)
{
NS_ASSERTION(NS_IsMainThread(),
"Can only add a reference on the main thread");
aRawRef->AddRef();
}
};
#endif /* GFX_BASICLAYERS_H */

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

@ -100,102 +100,6 @@ SurfaceToTexture(ID3D10Device *aDevice,
return texture.forget();
}
ImageContainerD3D10::ImageContainerD3D10(ID3D10Device1 *aDevice)
: ImageContainer(nsnull)
, mDevice(aDevice)
{
}
already_AddRefed<Image>
ImageContainerD3D10::CreateImage(const Image::Format *aFormats,
PRUint32 aNumFormats)
{
if (!aNumFormats) {
return nsnull;
}
nsRefPtr<Image> img;
if (aFormats[0] == Image::PLANAR_YCBCR) {
img = new PlanarYCbCrImageD3D10(mDevice);
} else if (aFormats[0] == Image::CAIRO_SURFACE) {
img = new CairoImageD3D10(mDevice);
}
return img.forget();
}
void
ImageContainerD3D10::SetCurrentImage(Image *aImage)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mActiveImage = aImage;
CurrentImageChanged();
}
already_AddRefed<Image>
ImageContainerD3D10::GetCurrentImage()
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
nsRefPtr<Image> retval = mActiveImage;
return retval.forget();
}
already_AddRefed<gfxASurface>
ImageContainerD3D10::GetCurrentAsSurface(gfxIntSize *aSize)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mActiveImage) {
return nsnull;
}
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageD3D10 *yuvImage =
static_cast<PlanarYCbCrImageD3D10*>(mActiveImage.get());
if (yuvImage->HasData()) {
*aSize = yuvImage->mSize;
}
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageD3D10 *cairoImage =
static_cast<CairoImageD3D10*>(mActiveImage.get());
*aSize = cairoImage->mSize;
}
return static_cast<ImageD3D10*>(mActiveImage->GetImplData())->GetAsSurface();
}
gfxIntSize
ImageContainerD3D10::GetCurrentSize()
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mActiveImage) {
return gfxIntSize(0,0);
}
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageD3D10 *yuvImage =
static_cast<PlanarYCbCrImageD3D10*>(mActiveImage.get());
if (!yuvImage->HasData()) {
return gfxIntSize(0,0);
}
return yuvImage->mSize;
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageD3D10 *cairoImage =
static_cast<CairoImageD3D10*>(mActiveImage.get());
return cairoImage->mSize;
}
return gfxIntSize(0,0);
}
bool
ImageContainerD3D10::SetLayerManager(LayerManager *aManager)
{
if (aManager->GetBackendType() == LayerManager::LAYERS_D3D10) {
return true;
}
return false;
}
Layer*
ImageLayerD3D10::GetLayer()
{
@ -218,51 +122,39 @@ ImageLayerD3D10::RenderLayer()
ID3D10EffectTechnique *technique;
if (GetContainer()->GetBackendType() != LayerManager::LAYERS_D3D10 ||
image->GetFormat() == Image::CAIRO_SURFACE)
if (image->GetFormat() == Image::CAIRO_SURFACE)
{
gfxIntSize size;
bool hasAlpha;
nsRefPtr<ID3D10ShaderResourceView> srView;
CairoImage *cairoImage =
static_cast<CairoImage*>(image.get());
if (GetContainer()->GetBackendType() != LayerManager::LAYERS_D3D10)
{
nsRefPtr<gfxASurface> surf = GetContainer()->GetCurrentAsSurface(&size);
nsRefPtr<ID3D10Texture2D> texture = SurfaceToTexture(device(), surf, size);
if (!texture) {
NS_WARNING("Failed to create texture for surface.");
return;
}
hasAlpha = surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA;
device()->CreateShaderResourceView(texture, NULL, getter_AddRefs(srView));
} else {
ImageContainerD3D10 *container =
static_cast<ImageContainerD3D10*>(GetContainer());
if (container->device() != device()) {
container->SetDevice(device());
}
// image->GetFormat() == Image::CAIRO_SURFACE
CairoImageD3D10 *cairoImage =
static_cast<CairoImageD3D10*>(image.get());
if (cairoImage->mDevice != device()) {
// This shader resource view was for an old device! Can't draw that
// now.
return;
}
srView = cairoImage->mSRView;
hasAlpha = cairoImage->mHasAlpha;
size = cairoImage->mSize;
if (!cairoImage->mSurface) {
return;
}
if (hasAlpha) {
if (!cairoImage->GetBackendData(LayerManager::LAYERS_D3D10)) {
nsAutoPtr<CairoD3D10BackendData> dat = new CairoD3D10BackendData();
dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
if (dat->mTexture) {
device()->CreateShaderResourceView(dat->mTexture, NULL, getter_AddRefs(dat->mSRView));
cairoImage->SetBackendData(LayerManager::LAYERS_D3D10, dat.forget());
}
}
CairoD3D10BackendData *data =
static_cast<CairoD3D10BackendData*>(cairoImage->GetBackendData(LayerManager::LAYERS_D3D10));
if (!data) {
return;
}
nsRefPtr<ID3D10Device> dev;
data->mTexture->GetDevice(getter_AddRefs(dev));
if (dev != device()) {
return;
}
if (cairoImage->mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
if (mFilter == gfxPattern::FILTER_NEAREST) {
technique = effect()->GetTechniqueByName("RenderRGBALayerPremulPoint");
} else {
@ -276,29 +168,38 @@ ImageLayerD3D10::RenderLayer()
}
}
if (srView) {
effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(srView);
}
effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(data->mSRView);
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
ShaderConstantRectD3D10(
(float)0,
(float)0,
(float)size.width,
(float)size.height)
(float)cairoImage->mSize.width,
(float)cairoImage->mSize.height)
);
} else if (image->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageD3D10 *yuvImage =
static_cast<PlanarYCbCrImageD3D10*>(image.get());
PlanarYCbCrImage *yuvImage =
static_cast<PlanarYCbCrImage*>(image.get());
if (!yuvImage->HasData()) {
if (!yuvImage->mBufferSize) {
return;
}
if (yuvImage->mDevice != device()) {
// These shader resources were created for an old device! Can't draw
// that here.
return;
if (!yuvImage->GetBackendData(LayerManager::LAYERS_D3D10)) {
AllocateTexturesYCbCr(yuvImage);
}
PlanarYCbCrD3D10BackendData *data =
static_cast<PlanarYCbCrD3D10BackendData*>(yuvImage->GetBackendData(LayerManager::LAYERS_D3D10));
if (!data) {
return;
}
nsRefPtr<ID3D10Device> dev;
data->mYTexture->GetDevice(getter_AddRefs(dev));
if (dev != device()) {
return;
}
// TODO: At some point we should try to deal with mFilter here, you don't
@ -308,9 +209,9 @@ ImageLayerD3D10::RenderLayer()
technique = effect()->GetTechniqueByName("RenderYCbCrLayer");
effect()->GetVariableByName("tY")->AsShaderResource()->SetResource(yuvImage->mYView);
effect()->GetVariableByName("tCb")->AsShaderResource()->SetResource(yuvImage->mCbView);
effect()->GetVariableByName("tCr")->AsShaderResource()->SetResource(yuvImage->mCrView);
effect()->GetVariableByName("tY")->AsShaderResource()->SetResource(data->mYView);
effect()->GetVariableByName("tCb")->AsShaderResource()->SetResource(data->mCbView);
effect()->GetVariableByName("tCr")->AsShaderResource()->SetResource(data->mCrView);
/*
* Send 3d control data and metadata to NV3DVUtils
@ -341,7 +242,7 @@ ImageLayerD3D10::RenderLayer()
if (yuvImage->mData.mStereoMode != STEREO_MODE_MONO) {
// Dst resource is optional
GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->mSize.width,
(unsigned int)yuvImage->mSize.height, (HANDLE)(yuvImage->mYTexture), (HANDLE)(NULL));
(unsigned int)yuvImage->mSize.height, (HANDLE)(data->mYTexture), (HANDLE)(NULL));
}
}
@ -373,146 +274,49 @@ ImageLayerD3D10::RenderLayer()
GetContainer()->NotifyPaintedImage(image);
}
PlanarYCbCrImageD3D10::PlanarYCbCrImageD3D10(ID3D10Device1 *aDevice)
: PlanarYCbCrImage(static_cast<ImageD3D10*>(this))
, mBufferSize(0)
, mDevice(aDevice)
, mHasData(false)
void ImageLayerD3D10::AllocateTexturesYCbCr(PlanarYCbCrImage *aImage)
{
}
nsAutoPtr<PlanarYCbCrD3D10BackendData> backendData =
new PlanarYCbCrD3D10BackendData;
void
PlanarYCbCrImageD3D10::SetData(const PlanarYCbCrImage::Data &aData)
{
mBuffer = CopyData(mData, mSize, mBufferSize, aData);
PlanarYCbCrImage::Data &data = aImage->mData;
AllocateTextures();
mHasData = true;
}
void
PlanarYCbCrImageD3D10::AllocateTextures()
{
D3D10_SUBRESOURCE_DATA dataY;
D3D10_SUBRESOURCE_DATA dataCb;
D3D10_SUBRESOURCE_DATA dataCr;
CD3D10_TEXTURE2D_DESC descY(DXGI_FORMAT_R8_UNORM,
mData.mYSize.width,
mData.mYSize.height, 1, 1);
data.mYSize.width,
data.mYSize.height, 1, 1);
CD3D10_TEXTURE2D_DESC descCbCr(DXGI_FORMAT_R8_UNORM,
mData.mCbCrSize.width,
mData.mCbCrSize.height, 1, 1);
data.mCbCrSize.width,
data.mCbCrSize.height, 1, 1);
descY.Usage = descCbCr.Usage = D3D10_USAGE_IMMUTABLE;
dataY.pSysMem = mData.mYChannel;
dataY.SysMemPitch = mData.mYStride;
dataCb.pSysMem = mData.mCbChannel;
dataCb.SysMemPitch = mData.mCbCrStride;
dataCr.pSysMem = mData.mCrChannel;
dataCr.SysMemPitch = mData.mCbCrStride;
dataY.pSysMem = data.mYChannel;
dataY.SysMemPitch = data.mYStride;
dataCb.pSysMem = data.mCbChannel;
dataCb.SysMemPitch = data.mCbCrStride;
dataCr.pSysMem = data.mCrChannel;
dataCr.SysMemPitch = data.mCbCrStride;
HRESULT hr = mDevice->CreateTexture2D(&descY, &dataY, getter_AddRefs(mYTexture));
HRESULT hr = device()->CreateTexture2D(&descY, &dataY, getter_AddRefs(backendData->mYTexture));
if (!FAILED(hr)) {
hr = mDevice->CreateTexture2D(&descCbCr, &dataCb, getter_AddRefs(mCbTexture));
hr = device()->CreateTexture2D(&descCbCr, &dataCb, getter_AddRefs(backendData->mCbTexture));
}
if (!FAILED(hr)) {
hr = mDevice->CreateTexture2D(&descCbCr, &dataCr, getter_AddRefs(mCrTexture));
hr = device()->CreateTexture2D(&descCbCr, &dataCr, getter_AddRefs(backendData->mCrTexture));
}
if (FAILED(hr)) {
LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D10::AllocateTextures(): Failed to create texture"),
hr);
return;
}
mDevice->CreateShaderResourceView(mYTexture, NULL, getter_AddRefs(mYView));
mDevice->CreateShaderResourceView(mCbTexture, NULL, getter_AddRefs(mCbView));
mDevice->CreateShaderResourceView(mCrTexture, NULL, getter_AddRefs(mCrView));
}
device()->CreateShaderResourceView(backendData->mYTexture, NULL, getter_AddRefs(backendData->mYView));
device()->CreateShaderResourceView(backendData->mCbTexture, NULL, getter_AddRefs(backendData->mCbView));
device()->CreateShaderResourceView(backendData->mCrTexture, NULL, getter_AddRefs(backendData->mCrView));
already_AddRefed<gfxASurface>
PlanarYCbCrImageD3D10::GetAsSurface()
{
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24);
gfx::YUVType type =
gfx::TypeFromSize(mData.mYSize.width,
mData.mYSize.height,
mData.mCbCrSize.width,
mData.mCbCrSize.height);
// Convert from YCbCr to RGB now
gfx::ConvertYCbCrToRGB32(mData.mYChannel,
mData.mCbChannel,
mData.mCrChannel,
imageSurface->Data(),
mData.mPicX,
mData.mPicY,
mData.mPicSize.width,
mData.mPicSize.height,
mData.mYStride,
mData.mCbCrStride,
imageSurface->Stride(),
type);
return imageSurface.forget().get();
}
CairoImageD3D10::~CairoImageD3D10()
{
}
void
CairoImageD3D10::SetData(const CairoImage::Data &aData)
{
mSize = aData.mSize;
NS_ASSERTION(aData.mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA,
"Invalid content type passed to CairoImageD3D10.");
mTexture = SurfaceToTexture(mDevice, aData.mSurface, mSize);
if (!mTexture) {
NS_WARNING("Failed to create texture for CairoImage.");
return;
}
if (aData.mSurface->GetContentType() == gfxASurface::CONTENT_COLOR) {
mHasAlpha = false;
} else {
mHasAlpha = true;
}
mDevice->CreateShaderResourceView(mTexture, NULL, getter_AddRefs(mSRView));
}
already_AddRefed<gfxASurface>
CairoImageD3D10::GetAsSurface()
{
nsRefPtr<ID3D10Texture2D> surfTexture;
// Make a copy of the texture since our current texture is not suitable for
// drawing with Direct2D because it is immutable and cannot be bound as a
// render target.
D3D10_TEXTURE2D_DESC texDesc;
mTexture->GetDesc(&texDesc);
texDesc.Usage = D3D10_USAGE_DEFAULT;
texDesc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
texDesc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
HRESULT hr = mDevice->CreateTexture2D(&texDesc, NULL, getter_AddRefs(surfTexture));
if (FAILED(hr)) {
LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("CairoImageD3D10::GetAsSurface(): Failed to create texture"),
hr);
return nsnull;
}
mDevice->CopyResource(surfTexture, mTexture);
nsRefPtr<gfxASurface> surf =
new gfxD2DSurface(surfTexture, mHasAlpha ? gfxASurface::CONTENT_COLOR_ALPHA :
gfxASurface::CONTENT_COLOR);
return surf.forget();
aImage->SetBackendData(LayerManager::LAYERS_D3D10, backendData.forget());
}
} /* layers */

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

@ -45,35 +45,6 @@
namespace mozilla {
namespace layers {
class THEBES_API ImageContainerD3D10 : public ImageContainer
{
public:
ImageContainerD3D10(ID3D10Device1 *aDevice);
virtual ~ImageContainerD3D10() {}
virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
PRUint32 aNumFormats);
virtual void SetCurrentImage(Image* aImage);
virtual already_AddRefed<Image> GetCurrentImage();
virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
virtual gfxIntSize GetCurrentSize();
virtual bool SetLayerManager(LayerManager *aManager);
virtual LayerManager::LayersBackend GetBackendType() { return LayerManager::LAYERS_D3D10; }
ID3D10Device1 *device() { return mDevice; }
void SetDevice(ID3D10Device1 *aDevice) { mDevice = aDevice; }
private:
nsRefPtr<Image> mActiveImage;
nsRefPtr<ID3D10Device1> mDevice;
};
class THEBES_API ImageLayerD3D10 : public ImageLayer,
public LayerD3D10
{
@ -89,70 +60,24 @@ public:
virtual Layer* GetLayer();
virtual void RenderLayer();
void AllocateTexturesYCbCr(PlanarYCbCrImage *aImage);
};
class THEBES_API ImageD3D10
struct PlanarYCbCrD3D10BackendData : public ImageBackendData
{
public:
virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
};
class THEBES_API PlanarYCbCrImageD3D10 : public PlanarYCbCrImage,
public ImageD3D10
{
public:
PlanarYCbCrImageD3D10(ID3D10Device1 *aDevice);
~PlanarYCbCrImageD3D10() {}
virtual void SetData(const Data &aData);
/*
* Upload the data from out mData into our textures. For now we use this to
* make sure the textures are created and filled on the main thread.
*/
void AllocateTextures();
bool HasData() { return mHasData; }
PRUint32 GetDataSize() { return mBuffer ? mBufferSize : 0; }
virtual already_AddRefed<gfxASurface> GetAsSurface();
nsAutoArrayPtr<PRUint8> mBuffer;
PRUint32 mBufferSize;
nsRefPtr<ID3D10Device1> mDevice;
Data mData;
gfxIntSize mSize;
nsRefPtr<ID3D10Texture2D> mYTexture;
nsRefPtr<ID3D10Texture2D> mCrTexture;
nsRefPtr<ID3D10Texture2D> mCbTexture;
nsRefPtr<ID3D10ShaderResourceView> mYView;
nsRefPtr<ID3D10ShaderResourceView> mCbView;
nsRefPtr<ID3D10ShaderResourceView> mCrView;
bool mHasData;
};
class THEBES_API CairoImageD3D10 : public CairoImage,
public ImageD3D10
struct CairoD3D10BackendData : public ImageBackendData
{
public:
CairoImageD3D10(ID3D10Device1 *aDevice)
: CairoImage(static_cast<ImageD3D10*>(this))
, mDevice(aDevice)
, mHasAlpha(true)
{ }
~CairoImageD3D10();
virtual void SetData(const Data &aData);
virtual already_AddRefed<gfxASurface> GetAsSurface();
nsRefPtr<ID3D10Device1> mDevice;
nsRefPtr<ID3D10Texture2D> mTexture;
nsRefPtr<ID3D10ShaderResourceView> mSRView;
gfxIntSize mSize;
bool mHasAlpha;
};
} /* layers */

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

@ -421,13 +421,6 @@ LayerManagerD3D10::CreateReadbackLayer()
return layer.forget();
}
already_AddRefed<ImageContainer>
LayerManagerD3D10::CreateImageContainer()
{
nsRefPtr<ImageContainer> layer = new ImageContainerD3D10(mDevice);
return layer.forget();
}
static void ReleaseTexture(void *texture)
{
static_cast<ID3D10Texture2D*>(texture)->Release();

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

@ -161,8 +161,6 @@ public:
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
virtual already_AddRefed<ImageContainer> CreateImageContainer();
virtual already_AddRefed<gfxASurface>
CreateOptimalSurface(const gfxIntSize &aSize,
gfxASurface::gfxImageFormat imageFormat);

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

@ -137,101 +137,160 @@ SurfaceToTexture(IDirect3DDevice9 *aDevice,
return texture.forget();
}
ImageContainerD3D9::ImageContainerD3D9(IDirect3DDevice9 *aDevice)
: ImageContainer(nsnull)
, mDevice(aDevice)
static void AllocateTexturesYCbCr(PlanarYCbCrImage *aImage,
IDirect3DDevice9 *aDevice,
LayerManagerD3D9 *aManager)
{
}
nsAutoPtr<PlanarYCbCrD3D9BackendData> backendData =
new PlanarYCbCrD3D9BackendData;
already_AddRefed<Image>
ImageContainerD3D9::CreateImage(const Image::Format *aFormats,
PRUint32 aNumFormats)
{
if (!aNumFormats) {
return nsnull;
}
nsRefPtr<Image> img;
if (aFormats[0] == Image::PLANAR_YCBCR) {
img = new PlanarYCbCrImageD3D9();
} else if (aFormats[0] == Image::CAIRO_SURFACE) {
img = new CairoImageD3D9(mDevice);
}
return img.forget();
}
PlanarYCbCrImage::Data &data = aImage->mData;
void
ImageContainerD3D9::SetCurrentImage(Image *aImage)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
D3DLOCKED_RECT lockrectY;
D3DLOCKED_RECT lockrectCb;
D3DLOCKED_RECT lockrectCr;
PRUint8* src;
PRUint8* dest;
mActiveImage = aImage;
CurrentImageChanged();
}
nsRefPtr<IDirect3DSurface9> tmpSurfaceY;
nsRefPtr<IDirect3DSurface9> tmpSurfaceCb;
nsRefPtr<IDirect3DSurface9> tmpSurfaceCr;
already_AddRefed<Image>
ImageContainerD3D9::GetCurrentImage()
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
nsRefPtr<IDirect3DDevice9Ex> deviceEx;
aDevice->QueryInterface(IID_IDirect3DDevice9Ex,
getter_AddRefs(deviceEx));
nsRefPtr<Image> retval = mActiveImage;
return retval.forget();
}
bool isD3D9Ex = deviceEx;
already_AddRefed<gfxASurface>
ImageContainerD3D9::GetCurrentAsSurface(gfxIntSize *aSize)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mActiveImage) {
return nsnull;
}
if (isD3D9Ex) {
nsRefPtr<IDirect3DTexture9> tmpYTexture;
nsRefPtr<IDirect3DTexture9> tmpCbTexture;
nsRefPtr<IDirect3DTexture9> tmpCrTexture;
// 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.
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageD3D9 *yuvImage =
static_cast<PlanarYCbCrImageD3D9*>(mActiveImage.get());
if (yuvImage->HasData()) {
*aSize = yuvImage->mSize;
HRESULT hr;
hr = aDevice->CreateTexture(data.mYSize.width, data.mYSize.height,
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
getter_AddRefs(backendData->mYTexture), NULL);
if (!FAILED(hr)) {
hr = aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
getter_AddRefs(backendData->mCbTexture), NULL);
}
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageD3D9 *cairoImage =
static_cast<CairoImageD3D9*>(mActiveImage.get());
*aSize = cairoImage->GetSize();
}
return static_cast<ImageD3D9*>(mActiveImage->GetImplData())->GetAsSurface();
}
gfxIntSize
ImageContainerD3D9::GetCurrentSize()
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mActiveImage) {
return gfxIntSize(0,0);
}
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageD3D9 *yuvImage =
static_cast<PlanarYCbCrImageD3D9*>(mActiveImage.get());
if (!yuvImage->HasData()) {
return gfxIntSize(0,0);
if (!FAILED(hr)) {
hr = aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
getter_AddRefs(backendData->mCrTexture), NULL);
}
if (!FAILED(hr)) {
hr = aDevice->CreateTexture(data.mYSize.width, data.mYSize.height,
1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM,
getter_AddRefs(tmpYTexture), NULL);
}
if (!FAILED(hr)) {
hr = aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM,
getter_AddRefs(tmpCbTexture), NULL);
}
if (!FAILED(hr)) {
hr = aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM,
getter_AddRefs(tmpCrTexture), NULL);
}
return yuvImage->mSize;
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageD3D9 *cairoImage =
static_cast<CairoImageD3D9*>(mActiveImage.get());
return cairoImage->GetSize();
if (FAILED(hr)) {
aManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (isD3D9Ex)"),
hr);
return;
}
tmpYTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceY));
tmpCbTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceCb));
tmpCrTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceCr));
tmpSurfaceY->LockRect(&lockrectY, NULL, 0);
tmpSurfaceCb->LockRect(&lockrectCb, NULL, 0);
tmpSurfaceCr->LockRect(&lockrectCr, NULL, 0);
} else {
HRESULT hr;
hr = aDevice->CreateTexture(data.mYSize.width, data.mYSize.height,
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
getter_AddRefs(backendData->mYTexture), NULL);
if (!FAILED(hr)) {
aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
getter_AddRefs(backendData->mCbTexture), NULL);
}
if (!FAILED(hr)) {
aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
getter_AddRefs(backendData->mCrTexture), NULL);
}
if (FAILED(hr)) {
aManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (!isD3D9Ex)"),
hr);
return;
}
/* lock the entire texture */
backendData->mYTexture->LockRect(0, &lockrectY, NULL, 0);
backendData->mCbTexture->LockRect(0, &lockrectCb, NULL, 0);
backendData->mCrTexture->LockRect(0, &lockrectCr, NULL, 0);
}
return gfxIntSize(0,0);
}
src = data.mYChannel;
//FIX cast
dest = (PRUint8*)lockrectY.pBits;
bool
ImageContainerD3D9::SetLayerManager(LayerManager *aManager)
{
if (aManager->GetBackendType() == LayerManager::LAYERS_D3D9) {
return true;
// copy over data
for (int h=0; h<data.mYSize.height; h++) {
memcpy(dest, src, data.mYSize.width);
dest += lockrectY.Pitch;
src += data.mYStride;
}
return false;
src = data.mCbChannel;
//FIX cast
dest = (PRUint8*)lockrectCb.pBits;
// copy over data
for (int h=0; h<data.mCbCrSize.height; h++) {
memcpy(dest, src, data.mCbCrSize.width);
dest += lockrectCb.Pitch;
src += data.mCbCrStride;
}
src = data.mCrChannel;
//FIX cast
dest = (PRUint8*)lockrectCr.pBits;
// copy over data
for (int h=0; h<data.mCbCrSize.height; h++) {
memcpy(dest, src, data.mCbCrSize.width);
dest += lockrectCr.Pitch;
src += data.mCbCrStride;
}
if (isD3D9Ex) {
tmpSurfaceY->UnlockRect();
tmpSurfaceCb->UnlockRect();
tmpSurfaceCr->UnlockRect();
nsRefPtr<IDirect3DSurface9> dstSurface;
backendData->mYTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
aDevice->UpdateSurface(tmpSurfaceY, NULL, dstSurface, NULL);
backendData->mCbTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
aDevice->UpdateSurface(tmpSurfaceCb, NULL, dstSurface, NULL);
backendData->mCrTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
aDevice->UpdateSurface(tmpSurfaceCr, NULL, dstSurface, NULL);
} else {
backendData->mYTexture->UnlockRect(0);
backendData->mCbTexture->UnlockRect(0);
backendData->mCrTexture->UnlockRect(0);
}
aImage->SetBackendData(LayerManager::LAYERS_D3D9, backendData.forget());
}
Layer*
@ -254,8 +313,37 @@ ImageLayerD3D9::RenderLayer()
SetShaderTransformAndOpacity();
if (GetContainer()->GetBackendType() != LayerManager::LAYERS_D3D9)
if (image->GetFormat() == Image::CAIRO_SURFACE)
{
CairoImage *cairoImage =
static_cast<CairoImage*>(image.get());
if (!cairoImage->mSurface) {
return;
}
if (!cairoImage->GetBackendData(LayerManager::LAYERS_D3D9)) {
nsAutoPtr<CairoD3D9BackendData> dat = new CairoD3D9BackendData();
dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
if (dat->mTexture) {
cairoImage->SetBackendData(LayerManager::LAYERS_D3D9, dat.forget());
}
}
CairoD3D9BackendData *data =
static_cast<CairoD3D9BackendData*>(cairoImage->GetBackendData(LayerManager::LAYERS_D3D9));
if (!data) {
return;
}
nsRefPtr<IDirect3DDevice9> dev;
data->mTexture->GetDevice(getter_AddRefs(dev));
if (dev != device()) {
return;
}
gfxIntSize size;
nsRefPtr<gfxASurface> surface =
GetContainer()->GetCurrentAsSurface(&size);
@ -275,16 +363,40 @@ ImageLayerD3D9::RenderLayer()
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
}
if (mFilter == gfxPattern::FILTER_NEAREST) {
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
}
device()->SetTexture(0, texture);
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
} else if (image->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageD3D9 *yuvImage =
static_cast<PlanarYCbCrImageD3D9*>(image.get());
if (mFilter == gfxPattern::FILTER_NEAREST) {
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
}
} else {
PlanarYCbCrImage *yuvImage =
static_cast<PlanarYCbCrImage*>(image.get());
if (!yuvImage->HasData()) {
if (!yuvImage->mBufferSize) {
return;
}
if (!yuvImage->GetBackendData(LayerManager::LAYERS_D3D9)) {
AllocateTexturesYCbCr(yuvImage, device(), mD3DManager);
}
PlanarYCbCrD3D9BackendData *data =
static_cast<PlanarYCbCrD3D9BackendData*>(yuvImage->GetBackendData(LayerManager::LAYERS_D3D9));
if (!data) {
return;
}
nsRefPtr<IDirect3DDevice9> dev;
data->mYTexture->GetDevice(getter_AddRefs(dev));
if (dev != device()) {
return;
}
yuvImage->AllocateTextures(device());
device()->SetVertexShaderConstantF(CBvLayerQuad,
ShaderConstantRect(0,
@ -336,300 +448,26 @@ ImageLayerD3D9::RenderLayer()
nsRefPtr<IDirect3DSurface9> renderTarget;
device()->GetRenderTarget(0, getter_AddRefs(renderTarget));
mD3DManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->mSize.width,
(unsigned int)yuvImage->mSize.height, (HANDLE)(yuvImage->mYTexture), (HANDLE)(renderTarget));
(unsigned int)yuvImage->mSize.height, (HANDLE)(data->mYTexture), (HANDLE)(renderTarget));
}
}
// Linear scaling is default here, adhering to mFilter is difficult since
// presumably even with point filtering we'll still want chroma upsampling
// to be linear. In the current approach we can't.
device()->SetTexture(0, yuvImage->mYTexture);
device()->SetTexture(1, yuvImage->mCbTexture);
device()->SetTexture(2, yuvImage->mCrTexture);
device()->SetTexture(0, data->mYTexture);
device()->SetTexture(1, data->mCbTexture);
device()->SetTexture(2, data->mCrTexture);
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
device()->SetVertexShaderConstantF(CBvTextureCoords,
ShaderConstantRect(0, 0, 1.0f, 1.0f), 1);
} else if (image->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageD3D9 *cairoImage =
static_cast<CairoImageD3D9*>(image.get());
ImageContainerD3D9 *container =
static_cast<ImageContainerD3D9*>(GetContainer());
if (container->device() != device()) {
// Ensure future images get created with the right device.
container->SetDevice(device());
}
if (cairoImage->device() != device()) {
cairoImage->SetDevice(device());
}
device()->SetVertexShaderConstantF(CBvLayerQuad,
ShaderConstantRect(0,
0,
cairoImage->GetSize().width,
cairoImage->GetSize().height),
1);
if (cairoImage->HasAlpha()) {
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
} else {
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
}
if (mFilter == gfxPattern::FILTER_NEAREST) {
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
}
device()->SetTexture(0, cairoImage->GetOrCreateTexture());
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
if (mFilter == gfxPattern::FILTER_NEAREST) {
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
}
}
GetContainer()->NotifyPaintedImage(image);
}
PlanarYCbCrImageD3D9::PlanarYCbCrImageD3D9()
: PlanarYCbCrImage(static_cast<ImageD3D9*>(this))
, mBufferSize(0)
, mHasData(false)
{
}
void
PlanarYCbCrImageD3D9::SetData(const PlanarYCbCrImage::Data &aData)
{
mBuffer = CopyData(mData, mSize, mBufferSize, aData);
mHasData = true;
}
void
PlanarYCbCrImageD3D9::AllocateTextures(IDirect3DDevice9 *aDevice)
{
D3DLOCKED_RECT lockrectY;
D3DLOCKED_RECT lockrectCb;
D3DLOCKED_RECT lockrectCr;
PRUint8* src;
PRUint8* dest;
nsRefPtr<IDirect3DSurface9> tmpSurfaceY;
nsRefPtr<IDirect3DSurface9> tmpSurfaceCb;
nsRefPtr<IDirect3DSurface9> tmpSurfaceCr;
nsRefPtr<IDirect3DDevice9Ex> deviceEx;
aDevice->QueryInterface(IID_IDirect3DDevice9Ex,
getter_AddRefs(deviceEx));
bool isD3D9Ex = deviceEx;
if (isD3D9Ex) {
nsRefPtr<IDirect3DTexture9> tmpYTexture;
nsRefPtr<IDirect3DTexture9> tmpCbTexture;
nsRefPtr<IDirect3DTexture9> tmpCrTexture;
// 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.
HRESULT hr;
hr = aDevice->CreateTexture(mData.mYSize.width, mData.mYSize.height,
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
getter_AddRefs(mYTexture), NULL);
if (!FAILED(hr)) {
hr = aDevice->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
getter_AddRefs(mCbTexture), NULL);
}
if (!FAILED(hr)) {
hr = aDevice->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
getter_AddRefs(mCrTexture), NULL);
}
if (!FAILED(hr)) {
hr = aDevice->CreateTexture(mData.mYSize.width, mData.mYSize.height,
1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM,
getter_AddRefs(tmpYTexture), NULL);
}
if (!FAILED(hr)) {
hr = aDevice->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM,
getter_AddRefs(tmpCbTexture), NULL);
}
if (!FAILED(hr)) {
hr = aDevice->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM,
getter_AddRefs(tmpCrTexture), NULL);
}
if (FAILED(hr)) {
mManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (isD3D9Ex)"),
hr);
return;
}
tmpYTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceY));
tmpCbTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceCb));
tmpCrTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceCr));
tmpSurfaceY->LockRect(&lockrectY, NULL, 0);
tmpSurfaceCb->LockRect(&lockrectCb, NULL, 0);
tmpSurfaceCr->LockRect(&lockrectCr, NULL, 0);
} else {
HRESULT hr;
hr = aDevice->CreateTexture(mData.mYSize.width, mData.mYSize.height,
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
getter_AddRefs(mYTexture), NULL);
if (!FAILED(hr)) {
aDevice->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
getter_AddRefs(mCbTexture), NULL);
}
if (!FAILED(hr)) {
aDevice->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
getter_AddRefs(mCrTexture), NULL);
}
if (FAILED(hr)) {
mManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (!isD3D9Ex)"),
hr);
return;
}
/* 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*)lockrectY.pBits;
// copy over data
for (int h=0; h<mData.mYSize.height; h++) {
memcpy(dest, src, mData.mYSize.width);
dest += lockrectY.Pitch;
src += mData.mYStride;
}
src = mData.mCbChannel;
//FIX cast
dest = (PRUint8*)lockrectCb.pBits;
// copy over data
for (int h=0; h<mData.mCbCrSize.height; h++) {
memcpy(dest, src, mData.mCbCrSize.width);
dest += lockrectCb.Pitch;
src += mData.mCbCrStride;
}
src = mData.mCrChannel;
//FIX cast
dest = (PRUint8*)lockrectCr.pBits;
// copy over data
for (int h=0; h<mData.mCbCrSize.height; h++) {
memcpy(dest, src, mData.mCbCrSize.width);
dest += lockrectCr.Pitch;
src += mData.mCbCrStride;
}
if (isD3D9Ex) {
tmpSurfaceY->UnlockRect();
tmpSurfaceCb->UnlockRect();
tmpSurfaceCr->UnlockRect();
nsRefPtr<IDirect3DSurface9> dstSurface;
mYTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
aDevice->UpdateSurface(tmpSurfaceY, NULL, dstSurface, NULL);
mCbTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
aDevice->UpdateSurface(tmpSurfaceCb, NULL, dstSurface, NULL);
mCrTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
aDevice->UpdateSurface(tmpSurfaceCr, NULL, dstSurface, NULL);
} else {
mYTexture->UnlockRect(0);
mCbTexture->UnlockRect(0);
mCrTexture->UnlockRect(0);
}
}
void
PlanarYCbCrImageD3D9::FreeTextures()
{
}
already_AddRefed<gfxASurface>
PlanarYCbCrImageD3D9::GetAsSurface()
{
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24);
gfx::YUVType type =
gfx::TypeFromSize(mData.mYSize.width,
mData.mYSize.height,
mData.mCbCrSize.width,
mData.mCbCrSize.height);
// Convert from YCbCr to RGB now
gfx::ConvertYCbCrToRGB32(mData.mYChannel,
mData.mCbChannel,
mData.mCrChannel,
imageSurface->Data(),
mData.mPicX,
mData.mPicY,
mData.mPicSize.width,
mData.mPicSize.height,
mData.mYStride,
mData.mCbCrStride,
imageSurface->Stride(),
type);
return imageSurface.forget().get();
}
CairoImageD3D9::~CairoImageD3D9()
{
}
void
CairoImageD3D9::SetDevice(IDirect3DDevice9 *aDevice)
{
mTexture = NULL;
mDevice = aDevice;
}
void
CairoImageD3D9::SetData(const CairoImage::Data &aData)
{
mSize = aData.mSize;
mCachedSurface = aData.mSurface;
mTexture = NULL;
}
IDirect3DTexture9*
CairoImageD3D9::GetOrCreateTexture()
{
if (mTexture)
return mTexture;
mTexture = SurfaceToTexture(mDevice, mCachedSurface, mSize);
// We need to keep our cached surface around in case the device changes.
return mTexture;
}
already_AddRefed<gfxASurface>
CairoImageD3D9::GetAsSurface()
{
nsRefPtr<gfxASurface> surface = mCachedSurface;
return surface.forget();
}
ShadowImageLayerD3D9::ShadowImageLayerD3D9(LayerManagerD3D9* aManager)
: ShadowImageLayer(aManager, nsnull)
, LayerD3D9(aManager)
@ -675,7 +513,7 @@ ShadowImageLayerD3D9::Swap(const SharedImage& aNewFront,
data.mPicY = 0;
if (!mYCbCrImage) {
mYCbCrImage = new PlanarYCbCrImageD3D9();
mYCbCrImage = new PlanarYCbCrImage(new BufferRecycleBin());
}
mYCbCrImage->SetData(data);
@ -710,12 +548,25 @@ ShadowImageLayerD3D9::RenderLayer()
if (mBuffer) {
mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
} else if (mYCbCrImage) {
if (!mYCbCrImage->HasData()) {
if (!mYCbCrImage->mBufferSize) {
return;
}
if (!mYCbCrImage->GetBackendData(LayerManager::LAYERS_D3D9)) {
AllocateTexturesYCbCr(mYCbCrImage, device(), mD3DManager);
}
PlanarYCbCrD3D9BackendData *data =
static_cast<PlanarYCbCrD3D9BackendData*>(mYCbCrImage->GetBackendData(LayerManager::LAYERS_D3D9));
if (!data) {
return;
}
if (!mYCbCrImage->mBufferSize) {
return;
}
mYCbCrImage->AllocateTextures(device());
SetShaderTransformAndOpacity();
device()->SetVertexShaderConstantF(CBvLayerQuad,
@ -737,9 +588,9 @@ ShadowImageLayerD3D9::RenderLayer()
// Linear scaling is default here, adhering to mFilter is difficult since
// presumably even with point filtering we'll still want chroma upsampling
// to be linear. In the current approach we can't.
device()->SetTexture(0, mYCbCrImage->mYTexture);
device()->SetTexture(1, mYCbCrImage->mCbTexture);
device()->SetTexture(2, mYCbCrImage->mCrTexture);
device()->SetTexture(0, data->mYTexture);
device()->SetTexture(1, data->mCbTexture);
device()->SetTexture(2, data->mCrTexture);
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
} else {

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

@ -47,36 +47,6 @@ namespace layers {
class ShadowBufferD3D9;
class THEBES_API ImageContainerD3D9 : public ImageContainer
{
public:
ImageContainerD3D9(IDirect3DDevice9 *aDevice);
virtual ~ImageContainerD3D9() {}
virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
PRUint32 aNumFormats);
virtual void SetCurrentImage(Image* aImage);
virtual already_AddRefed<Image> GetCurrentImage();
virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
virtual gfxIntSize GetCurrentSize();
virtual bool SetLayerManager(LayerManager *aManager);
virtual LayerManager::LayersBackend GetBackendType() { return LayerManager::LAYERS_D3D9; }
IDirect3DDevice9 *device() { return mDevice; }
void SetDevice(IDirect3DDevice9 *aDevice) { mDevice = aDevice; }
private:
nsRefPtr<Image> mActiveImage;
nsRefPtr<IDirect3DDevice9> mDevice;
};
class THEBES_API ImageLayerD3D9 : public ImageLayer,
public LayerD3D9
{
@ -100,81 +70,17 @@ public:
virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
};
class THEBES_API PlanarYCbCrImageD3D9 : public PlanarYCbCrImage,
public ImageD3D9
struct CairoD3D9BackendData : public ImageBackendData
{
public:
PlanarYCbCrImageD3D9();
~PlanarYCbCrImageD3D9() {}
nsRefPtr<IDirect3DTexture9> mTexture;
};
virtual void SetData(const Data &aData);
/*
* Upload the data from out mData into our textures. For now we use this to
* make sure the textures are created and filled on the main thread.
*/
void AllocateTextures(IDirect3DDevice9 *aDevice);
/*
* XXX
* Free the textures, we call this from the main thread when we're done
* drawing this frame. We cannot free this from the constructor since it may
* be destroyed off the main-thread and might not be able to properly clean
* up its textures
*/
void FreeTextures();
bool HasData() { return mHasData; }
PRUint32 GetDataSize() { return mBuffer ? mBufferSize : 0; }
virtual already_AddRefed<gfxASurface> GetAsSurface();
nsAutoArrayPtr<PRUint8> mBuffer;
PRUint32 mBufferSize;
LayerManagerD3D9 *mManager;
Data mData;
gfxIntSize mSize;
struct PlanarYCbCrD3D9BackendData : public ImageBackendData
{
nsRefPtr<IDirect3DTexture9> mYTexture;
nsRefPtr<IDirect3DTexture9> mCrTexture;
nsRefPtr<IDirect3DTexture9> mCbTexture;
bool mHasData;
};
class THEBES_API CairoImageD3D9 : public CairoImage,
public ImageD3D9
{
public:
CairoImageD3D9(IDirect3DDevice9 *aDevice)
: CairoImage(static_cast<ImageD3D9*>(this))
, mDevice(aDevice)
{ }
~CairoImageD3D9();
virtual void SetData(const Data &aData);
virtual already_AddRefed<gfxASurface> GetAsSurface();
IDirect3DDevice9 *device() { return mDevice; }
void SetDevice(IDirect3DDevice9 *aDevice);
/**
* Uploading a texture may fail if the screen is locked. If this happens,
* we need to save the backing surface and retry when we are asked to paint.
*/
virtual IDirect3DTexture9* GetOrCreateTexture();
const gfxIntSize& GetSize() { return mSize; }
bool HasAlpha() {
return mCachedSurface->GetContentType() ==
gfxASurface::CONTENT_COLOR_ALPHA;
}
private:
gfxIntSize mSize;
nsRefPtr<gfxASurface> mCachedSurface;
nsRefPtr<IDirect3DDevice9> mDevice;
nsRefPtr<IDirect3DTexture9> mTexture;
LayerManagerD3D9 *mManager;
};
class ShadowImageLayerD3D9 : public ShadowImageLayer,
@ -199,7 +105,7 @@ public:
private:
nsRefPtr<ShadowBufferD3D9> mBuffer;
nsRefPtr<PlanarYCbCrImageD3D9> mYCbCrImage;
nsRefPtr<PlanarYCbCrImage> mYCbCrImage;
};
} /* layers */

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

@ -239,13 +239,6 @@ LayerManagerD3D9::CreateReadbackLayer()
return layer.forget();
}
already_AddRefed<ImageContainer>
LayerManagerD3D9::CreateImageContainer()
{
nsRefPtr<ImageContainer> container = new ImageContainerD3D9(device());
return container.forget();
}
already_AddRefed<ShadowThebesLayer>
LayerManagerD3D9::CreateShadowThebesLayer()
{

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

@ -165,8 +165,6 @@ public:
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
virtual already_AddRefed<ImageContainer> CreateImageContainer();
virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer();
virtual already_AddRefed<ShadowContainerLayer> CreateShadowContainerLayer();
virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer();

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

@ -42,7 +42,6 @@
#include "gfxImageSurface.h"
#include "yuv_convert.h"
#include "GLContextProvider.h"
#include "MacIOSurfaceImageOGL.h"
#if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
# include "GLXLibrary.h"
# include "mozilla/X11Util.h"
@ -136,39 +135,13 @@ GLTexture::Release()
mContext = nsnull;
}
RecycleBin::RecycleBin()
: mLock("mozilla.layers.RecycleBin.mLock")
TextureRecycleBin::TextureRecycleBin()
: mLock("mozilla.layers.TextureRecycleBin.mLock")
{
}
void
RecycleBin::RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize)
{
MutexAutoLock lock(mLock);
if (!mRecycledBuffers.IsEmpty() && aSize != mRecycledBufferSize) {
mRecycledBuffers.Clear();
}
mRecycledBufferSize = aSize;
mRecycledBuffers.AppendElement(aBuffer);
}
PRUint8*
RecycleBin::GetBuffer(PRUint32 aSize)
{
MutexAutoLock lock(mLock);
if (mRecycledBuffers.IsEmpty() || mRecycledBufferSize != aSize)
return new PRUint8[aSize];
PRUint32 last = mRecycledBuffers.Length() - 1;
PRUint8* result = mRecycledBuffers[last].forget();
mRecycledBuffers.RemoveElementAt(last);
return result;
}
void
RecycleBin::RecycleTexture(GLTexture *aTexture, TextureType aType,
TextureRecycleBin::RecycleTexture(GLTexture *aTexture, TextureType aType,
const gfxIntSize& aSize)
{
MutexAutoLock lock(mLock);
@ -184,7 +157,7 @@ RecycleBin::RecycleTexture(GLTexture *aTexture, TextureType aType,
}
void
RecycleBin::GetTexture(TextureType aType, const gfxIntSize& aSize,
TextureRecycleBin::GetTexture(TextureType aType, const gfxIntSize& aSize,
GLContext *aContext, GLTexture *aOutTexture)
{
MutexAutoLock lock(mLock);
@ -198,204 +171,40 @@ RecycleBin::GetTexture(TextureType aType, const gfxIntSize& aSize,
mRecycledTextures[aType].RemoveElementAt(last);
}
ImageContainerOGL::ImageContainerOGL(LayerManagerOGL *aManager)
: ImageContainer(aManager)
, mRecycleBin(new RecycleBin())
struct THEBES_API MacIOSurfaceImageOGLBackendData : public ImageBackendData
{
}
GLTexture mTexture;
};
ImageContainerOGL::~ImageContainerOGL()
{
if (mManager) {
NS_ASSERTION(mManager->GetBackendType() == LayerManager::LAYERS_OPENGL, "Wrong layer manager got assigned to ImageContainerOGL!");
static_cast<LayerManagerOGL*>(mManager)->ForgetImageContainer(this);
}
}
already_AddRefed<Image>
ImageContainerOGL::CreateImage(const Image::Format *aFormats,
PRUint32 aNumFormats)
{
if (!aNumFormats) {
return nsnull;
}
nsRefPtr<Image> img;
if (aFormats[0] == Image::PLANAR_YCBCR) {
img = new PlanarYCbCrImageOGL(static_cast<LayerManagerOGL*>(mManager),
mRecycleBin);
} else if (aFormats[0] == Image::CAIRO_SURFACE) {
img = new CairoImageOGL(static_cast<LayerManagerOGL*>(mManager));
}
#ifdef XP_MACOSX
else if (aFormats[0] == Image::MAC_IO_SURFACE) {
img = new MacIOSurfaceImageOGL(static_cast<LayerManagerOGL*>(mManager));
}
#endif
return img.forget();
}
void
ImageContainerOGL::SetCurrentImage(Image *aImage)
AllocateTextureIOSurface(MacIOSurfaceImage *aIOImage, mozilla::gl::GLContext* aGL)
{
nsRefPtr<Image> oldImage;
nsAutoPtr<MacIOSurfaceImageOGLBackendData> backendData(
new MacIOSurfaceImageOGLBackendData);
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
backendData->mTexture.Allocate(aGL);
aGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, backendData->mTexture.GetTextureID());
aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
LOCAL_GL_TEXTURE_MIN_FILTER,
LOCAL_GL_NEAREST);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
LOCAL_GL_TEXTURE_MAG_FILTER,
LOCAL_GL_NEAREST);
oldImage = mActiveImage.forget();
mActiveImage = aImage;
CurrentImageChanged();
}
void *nativeCtx = aGL->GetNativeData(GLContext::NativeGLContext);
NSOpenGLContext* nsCtx = (NSOpenGLContext*)nativeCtx;
// Make sure oldImage is released outside the lock, so it can take our
// lock in RecycleBuffer
aIOImage->GetIOSurface()->CGLTexImageIOSurface2D(nsCtx,
LOCAL_GL_RGBA, LOCAL_GL_BGRA,
LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV, 0);
aGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
aIOImage->SetBackendData(LayerManager::LAYERS_OPENGL, backendData.forget());
}
already_AddRefed<Image>
ImageContainerOGL::GetCurrentImage()
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
nsRefPtr<Image> retval = mActiveImage;
return retval.forget();
}
already_AddRefed<gfxASurface>
ImageContainerOGL::GetCurrentAsSurface(gfxIntSize *aSize)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mActiveImage) {
*aSize = gfxIntSize(0,0);
return nsnull;
}
GLContext *gl = nsnull;
// tex1 will be RGBA or Y, tex2 will Cb, tex3 will be Cr
GLuint tex1 = 0;
gfxIntSize size;
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageOGL *yuvImage =
static_cast<PlanarYCbCrImageOGL*>(mActiveImage.get());
if (!yuvImage->HasData()) {
*aSize = gfxIntSize(0, 0);
return nsnull;
}
size = yuvImage->mData.mPicSize;
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(size, gfxASurface::ImageFormatRGB24);
gfx::YUVType type =
gfx::TypeFromSize(yuvImage->mData.mYSize.width,
yuvImage->mData.mYSize.height,
yuvImage->mData.mCbCrSize.width,
yuvImage->mData.mCbCrSize.height);
gfx::ConvertYCbCrToRGB32(yuvImage->mData.mYChannel,
yuvImage->mData.mCbChannel,
yuvImage->mData.mCrChannel,
imageSurface->Data(),
yuvImage->mData.mPicX,
yuvImage->mData.mPicY,
size.width,
size.height,
yuvImage->mData.mYStride,
yuvImage->mData.mCbCrStride,
imageSurface->Stride(),
type);
*aSize = size;
return imageSurface.forget().get();
}
if (mActiveImage->GetFormat() != Image::CAIRO_SURFACE)
{
*aSize = gfxIntSize(0, 0);
return nsnull;
}
CairoImageOGL *cairoImage =
static_cast<CairoImageOGL*>(mActiveImage.get());
size = cairoImage->mSize;
gl = cairoImage->mTexture.GetGLContext();
tex1 = cairoImage->mTexture.GetTextureID();
nsRefPtr<gfxImageSurface> s = gl->ReadTextureImage(tex1, size, LOCAL_GL_RGBA);
*aSize = size;
return s.forget();
}
gfxIntSize
ImageContainerOGL::GetCurrentSize()
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mActiveImage) {
return gfxIntSize(0,0);
}
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageOGL *yuvImage =
static_cast<PlanarYCbCrImageOGL*>(mActiveImage.get());
if (!yuvImage->HasData()) {
return gfxIntSize(0,0);
}
return yuvImage->mSize;
}
if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageOGL *cairoImage =
static_cast<CairoImageOGL*>(mActiveImage.get());
return cairoImage->mSize;
}
#ifdef XP_MACOSX
if (mActiveImage->GetFormat() == Image::MAC_IO_SURFACE) {
MacIOSurfaceImageOGL *ioImage =
static_cast<MacIOSurfaceImageOGL*>(mActiveImage.get());
return ioImage->mSize;
}
#endif
return gfxIntSize(0,0);
}
bool
ImageContainerOGL::SetLayerManager(LayerManager *aManager)
{
if (!aManager) {
// the layer manager just entirely went away
// XXX if we don't have context sharing, we should tell our images
// that their textures are no longer valid.
mManager = nsnull;
return true;
}
if (aManager->GetBackendType() != LayerManager::LAYERS_OPENGL) {
return false;
}
LayerManagerOGL* lmOld = static_cast<LayerManagerOGL*>(mManager);
LayerManagerOGL* lmNew = static_cast<LayerManagerOGL*>(aManager);
if (lmOld) {
NS_ASSERTION(lmNew->glForResources() == lmOld->glForResources(),
"We require GL context sharing here!");
lmOld->ForgetImageContainer(this);
}
mManager = aManager;
lmNew->RememberImageContainer(this);
return true;
}
Layer*
ImageLayerOGL::GetLayer()
{
@ -417,27 +226,34 @@ ImageLayerOGL::RenderLayer(int,
}
if (image->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageOGL *yuvImage =
static_cast<PlanarYCbCrImageOGL*>(image.get());
PlanarYCbCrImage *yuvImage =
static_cast<PlanarYCbCrImage*>(image.get());
if (!yuvImage->HasData()) {
if (!yuvImage->mBufferSize) {
return;
}
if (!yuvImage->HasTextures()) {
yuvImage->AllocateTextures(gl());
if (!yuvImage->GetBackendData(LayerManager::LAYERS_OPENGL)) {
AllocateTexturesYCbCr(yuvImage);
}
yuvImage->UpdateTextures(gl());
PlanarYCbCrOGLBackendData *data =
static_cast<PlanarYCbCrOGLBackendData*>(yuvImage->GetBackendData(LayerManager::LAYERS_OPENGL));
if (!data || data->mTextures->GetGLContext() != mOGLManager->glForResources()) {
// XXX - Can this ever happen? If so I need to fix this!
return;
}
gl()->MakeCurrent();
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[0].GetTextureID());
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[0].GetTextureID());
gl()->ApplyFilterToBoundTexture(mFilter);
gl()->fActiveTexture(LOCAL_GL_TEXTURE1);
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[1].GetTextureID());
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[1].GetTextureID());
gl()->ApplyFilterToBoundTexture(mFilter);
gl()->fActiveTexture(LOCAL_GL_TEXTURE2);
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[2].GetTextureID());
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[2].GetTextureID());
gl()->ApplyFilterToBoundTexture(mFilter);
YCbCrTextureLayerProgram *program = mOGLManager->GetYCbCrLayerProgram();
@ -460,16 +276,32 @@ ImageLayerOGL::RenderLayer(int,
// someone else forgets.
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
} else if (image->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageOGL *cairoImage =
static_cast<CairoImageOGL*>(image.get());
CairoImage *cairoImage =
static_cast<CairoImage*>(image.get());
cairoImage->SetTiling(mUseTileSourceRect);
if (!cairoImage->mSurface) {
return;
}
if (!cairoImage->GetBackendData(LayerManager::LAYERS_OPENGL)) {
AllocateTexturesCairo(cairoImage);
}
CairoOGLBackendData *data =
static_cast<CairoOGLBackendData*>(cairoImage->GetBackendData(LayerManager::LAYERS_OPENGL));
if (!data || data->mTexture.GetGLContext() != mOGLManager->glForResources()) {
// XXX - Can this ever happen? If so I need to fix this!
return;
}
data->SetTiling(mUseTileSourceRect);
gl()->MakeCurrent();
unsigned int iwidth = cairoImage->mSize.width;
unsigned int iheight = cairoImage->mSize.height;
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, cairoImage->mTexture.GetTextureID());
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTexture.GetTextureID());
#if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
GLXPixmap pixmap;
@ -484,7 +316,7 @@ ImageLayerOGL::RenderLayer(int,
#endif
ColorTextureLayerProgram *program =
mOGLManager->GetColorTextureLayerProgram(cairoImage->mLayerProgram);
mOGLManager->GetColorTextureLayerProgram(data->mLayerProgram);
gl()->ApplyFilterToBoundTexture(mFilter);
@ -592,8 +424,8 @@ ImageLayerOGL::RenderLayer(int,
#endif
#ifdef XP_MACOSX
} else if (image->GetFormat() == Image::MAC_IO_SURFACE) {
MacIOSurfaceImageOGL *ioImage =
static_cast<MacIOSurfaceImageOGL*>(image.get());
MacIOSurfaceImage *ioImage =
static_cast<MacIOSurfaceImage*>(image.get());
if (!mOGLManager->GetThebesLayerCallback()) {
// If its an empty transaction we still need to update
@ -602,15 +434,24 @@ ImageLayerOGL::RenderLayer(int,
ioImage->Update(GetContainer());
image = GetContainer()->GetCurrentImage();
gl()->MakeCurrent();
ioImage = static_cast<MacIOSurfaceImageOGL*>(image.get());
ioImage = static_cast<MacIOSurfaceImage*>(image.get());
}
if (!ioImage) {
return;
}
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, ioImage->mTexture.GetTextureID());
if (!ioImage->GetBackendData(LayerManager::LAYERS_OPENGL)) {
AllocateTextureIOSurface(ioImage, gl());
}
MacIOSurfaceImageOGLBackendData *data =
static_cast<MacIOSurfaceImageOGLBackendData*>(ioImage->GetBackendData(LayerManager::LAYERS_OPENGL));
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, data->mTexture.GetTextureID());
ColorTextureLayerProgram *program =
mOGLManager->GetRGBARectLayerProgram();
@ -618,7 +459,7 @@ ImageLayerOGL::RenderLayer(int,
program->Activate();
if (program->GetTexCoordMultiplierUniformLocation() != -1) {
// 2DRect case, get the multiplier right for a sampler2DRect
float f[] = { float(ioImage->mSize.width), float(ioImage->mSize.height) };
float f[] = { float(ioImage->GetSize().width), float(ioImage->GetSize().height) };
program->SetUniform(program->GetTexCoordMultiplierUniformLocation(),
2, f);
} else {
@ -626,8 +467,8 @@ ImageLayerOGL::RenderLayer(int,
}
program->SetLayerQuadRect(nsIntRect(0, 0,
ioImage->mSize.width,
ioImage->mSize.height));
ioImage->GetSize().width,
ioImage->GetSize().height));
program->SetLayerTransform(GetEffectiveTransform());
program->SetLayerOpacity(GetEffectiveOpacity());
program->SetRenderOffset(aOffset);
@ -660,61 +501,6 @@ InitTexture(GLContext* aGL, GLuint aTexture, GLenum aFormat, const gfxIntSize& a
NULL);
}
PlanarYCbCrImageOGL::PlanarYCbCrImageOGL(LayerManagerOGL *aManager,
RecycleBin *aRecycleBin)
: PlanarYCbCrImage(nsnull), mRecycleBin(aRecycleBin), mHasData(false)
{
#if 0
// We really want to allocate this on the decode thread -- but to do that,
// we need to create a per-thread shared GL context, and it will only work
// if we have context sharing. For now, create the textures on the main
// thread the first time we render.
if (aManager) {
AllocateTextures(aManager->glForResources());
}
#endif
}
PlanarYCbCrImageOGL::~PlanarYCbCrImageOGL()
{
if (mBuffer) {
mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
}
if (HasTextures()) {
mRecycleBin->RecycleTexture(&mTextures[0], RecycleBin::TEXTURE_Y, mData.mYSize);
mRecycleBin->RecycleTexture(&mTextures[1], RecycleBin::TEXTURE_C, mData.mCbCrSize);
mRecycleBin->RecycleTexture(&mTextures[2], RecycleBin::TEXTURE_C, mData.mCbCrSize);
}
}
void
PlanarYCbCrImageOGL::SetData(const PlanarYCbCrImage::Data &aData)
{
// Recycle the previous image main-memory buffer now that we're about to get a new buffer
if (mBuffer)
mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
mBuffer = CopyData(mData, mSize, mBufferSize, aData);
mHasData = true;
}
void
PlanarYCbCrImageOGL::AllocateTextures(mozilla::gl::GLContext *gl)
{
gl->MakeCurrent();
mRecycleBin->GetTexture(RecycleBin::TEXTURE_Y, mData.mYSize, gl, &mTextures[0]);
InitTexture(gl, mTextures[0].GetTextureID(), LOCAL_GL_LUMINANCE, mData.mYSize);
mRecycleBin->GetTexture(RecycleBin::TEXTURE_C, mData.mCbCrSize, gl, &mTextures[1]);
InitTexture(gl, mTextures[1].GetTextureID(), LOCAL_GL_LUMINANCE, mData.mCbCrSize);
mRecycleBin->GetTexture(RecycleBin::TEXTURE_C, mData.mCbCrSize, gl, &mTextures[2]);
InitTexture(gl, mTextures[2].GetTextureID(), LOCAL_GL_LUMINANCE, mData.mCbCrSize);
}
static void
UploadYUVToTexture(GLContext* gl, const PlanarYCbCrImage::Data& aData,
GLTexture* aYTexture,
@ -745,62 +531,91 @@ UploadYUVToTexture(GLContext* gl, const PlanarYCbCrImage::Data& aData,
gl->UploadSurfaceToTexture(surf, size, texture, true);
}
void
PlanarYCbCrImageOGL::UpdateTextures(GLContext *gl)
{
if (!mBuffer || !mHasData)
return;
UploadYUVToTexture(gl, mData, &mTextures[0], &mTextures[1], &mTextures[2]);
ImageLayerOGL::ImageLayerOGL(LayerManagerOGL *aManager)
: ImageLayer(aManager, NULL)
, LayerOGL(aManager)
, mTextureRecycleBin(new TextureRecycleBin())
{
mImplData = static_cast<LayerOGL*>(this);
}
CairoImageOGL::CairoImageOGL(LayerManagerOGL *aManager)
: CairoImage(nsnull), mSize(0, 0), mTiling(false)
void
ImageLayerOGL::AllocateTexturesYCbCr(PlanarYCbCrImage *aImage)
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread to create a cairo image");
if (!aImage->mBufferSize)
return;
if (aManager) {
// Allocate texture now to grab a reference to the GLContext
mTexture.Allocate(aManager->glForResources());
nsAutoPtr<PlanarYCbCrOGLBackendData> backendData(
new PlanarYCbCrOGLBackendData);
PlanarYCbCrImage::Data &data = aImage->mData;
GLContext *gl = mOGLManager->glForResources();
gl->MakeCurrent();
mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_Y, data.mYSize, gl, &backendData->mTextures[0]);
InitTexture(gl, backendData->mTextures[0].GetTextureID(), LOCAL_GL_LUMINANCE, data.mYSize);
mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_C, data.mCbCrSize, gl, &backendData->mTextures[1]);
InitTexture(gl, backendData->mTextures[1].GetTextureID(), LOCAL_GL_LUMINANCE, data.mCbCrSize);
mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_C, data.mCbCrSize, gl, &backendData->mTextures[2]);
InitTexture(gl, backendData->mTextures[2].GetTextureID(), LOCAL_GL_LUMINANCE, data.mCbCrSize);
UploadYUVToTexture(gl, aImage->mData,
&backendData->mTextures[0],
&backendData->mTextures[1],
&backendData->mTextures[2]);
backendData->mYSize = aImage->mData.mYSize;
backendData->mCbCrSize = aImage->mData.mCbCrSize;
backendData->mTextureRecycleBin = mTextureRecycleBin;
aImage->SetBackendData(LayerManager::LAYERS_OPENGL, backendData.forget());
}
void
ImageLayerOGL::AllocateTexturesCairo(CairoImage *aImage)
{
nsAutoPtr<CairoOGLBackendData> backendData(
new CairoOGLBackendData);
GLTexture &texture = backendData->mTexture;
texture.Allocate(mOGLManager->glForResources());
if (!texture.IsAllocated()) {
return;
}
}
void
CairoImageOGL::SetData(const CairoImage::Data &aData)
{
#if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
mSurface = nsnull;
#endif
if (!mTexture.IsAllocated())
return;
mozilla::gl::GLContext *gl = mTexture.GetGLContext();
mozilla::gl::GLContext *gl = texture.GetGLContext();
gl->MakeCurrent();
GLuint tex = mTexture.GetTextureID();
GLuint tex = texture.GetTextureID();
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
mSize = aData.mSize;
#if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
if (sGLXLibrary.SupportsTextureFromPixmap(aData.mSurface)) {
mSurface = aData.mSurface;
if (mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
mLayerProgram = gl::RGBALayerProgramType;
if (sGLXLibrary.SupportsTextureFromPixmap(aImage->mSurface)) {
if (aImage->mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
backendData->mLayerProgram = gl::RGBALayerProgramType;
} else {
mLayerProgram = gl::RGBXLayerProgramType;
backendData->mLayerProgram = gl::RGBXLayerProgramType;
}
aImage->SetBackendData(LayerManager::LAYERS_OPENGL, backendData.forget());
return;
}
#endif
mLayerProgram =
gl->UploadSurfaceToTexture(aData.mSurface,
nsIntRect(0,0, mSize.width, mSize.height),
backendData->mLayerProgram =
gl->UploadSurfaceToTexture(aImage->mSurface,
nsIntRect(0,0, aImage->mSize.width, aImage->mSize.height),
tex, true);
aImage->SetBackendData(LayerManager::LAYERS_OPENGL, backendData.forget());
}
void CairoImageOGL::SetTiling(bool aTiling)
void CairoOGLBackendData::SetTiling(bool aTiling)
{
if (aTiling == mTiling)
return;

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

@ -90,23 +90,19 @@ private:
};
/**
* A RecycleBin is owned by an ImageContainerOGL. We store buffers
* and textures in it that we want to recycle from one image to the next.
* It's a separate object from ImageContainerOGL because images need to store
* a strong ref to their RecycleBin and we must avoid creating a
* reference loop between an ImageContainerOGL and its active image.
* A RecycleBin is owned by an ImageLayer. We store textures in it that we
* want to recycle from one image to the next. It's a separate object from
* ImageContainer because images need to store a strong ref to their RecycleBin
* and we must avoid creating a reference loop between an ImageContainer and
* its active image.
*/
class RecycleBin {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RecycleBin)
class TextureRecycleBin {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureRecycleBin)
typedef mozilla::gl::GLContext GLContext;
public:
RecycleBin();
void RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize);
// Returns a recycled buffer of the right size, or allocates a new buffer.
PRUint8* GetBuffer(PRUint32 aSize);
TextureRecycleBin();
enum TextureType {
TEXTURE_Y,
@ -125,53 +121,15 @@ private:
// and mRecycledTextureSizes
Mutex mLock;
// We should probably do something to prune this list on a timer so we don't
// eat excess memory while video is paused...
nsTArray<nsAutoArrayPtr<PRUint8> > mRecycledBuffers;
// This is only valid if mRecycledBuffers is non-empty
PRUint32 mRecycledBufferSize;
nsTArray<GLTexture> mRecycledTextures[2];
gfxIntSize mRecycledTextureSizes[2];
};
class THEBES_API ImageContainerOGL : public ImageContainer
{
public:
ImageContainerOGL(LayerManagerOGL *aManager);
virtual ~ImageContainerOGL();
virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
PRUint32 aNumFormats);
virtual void SetCurrentImage(Image* aImage);
virtual already_AddRefed<Image> GetCurrentImage();
virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
virtual gfxIntSize GetCurrentSize();
virtual bool SetLayerManager(LayerManager *aManager);
virtual LayerManager::LayersBackend GetBackendType() { return LayerManager::LAYERS_OPENGL; }
private:
nsRefPtr<RecycleBin> mRecycleBin;
nsRefPtr<Image> mActiveImage;
};
class THEBES_API ImageLayerOGL : public ImageLayer,
public LayerOGL
{
public:
ImageLayerOGL(LayerManagerOGL *aManager)
: ImageLayer(aManager, NULL)
, LayerOGL(aManager)
{
mImplData = static_cast<LayerOGL*>(this);
}
ImageLayerOGL(LayerManagerOGL *aManager);
~ImageLayerOGL() { Destroy(); }
// LayerOGL Implementation
@ -181,66 +139,43 @@ public:
virtual void RenderLayer(int aPreviousFrameBuffer,
const nsIntPoint& aOffset);
virtual void CleanupResources() {}
void AllocateTexturesYCbCr(PlanarYCbCrImage *aImage);
void AllocateTexturesCairo(CairoImage *aImage);
protected:
nsRefPtr<TextureRecycleBin> mTextureRecycleBin;
};
class THEBES_API PlanarYCbCrImageOGL : public PlanarYCbCrImage
struct THEBES_API PlanarYCbCrOGLBackendData : public ImageBackendData
{
typedef mozilla::gl::GLContext GLContext;
~PlanarYCbCrOGLBackendData()
{
if (HasTextures()) {
mTextureRecycleBin->RecycleTexture(&mTextures[0], TextureRecycleBin::TEXTURE_Y, mYSize);
mTextureRecycleBin->RecycleTexture(&mTextures[1], TextureRecycleBin::TEXTURE_C, mCbCrSize);
mTextureRecycleBin->RecycleTexture(&mTextures[2], TextureRecycleBin::TEXTURE_C, mCbCrSize);
}
}
public:
PlanarYCbCrImageOGL(LayerManagerOGL *aManager,
RecycleBin *aRecycleBin);
~PlanarYCbCrImageOGL();
virtual void SetData(const Data &aData);
/**
* Upload the data from out mData into our textures. For now we use this to
* make sure the textures are created and filled on the main thread.
*/
void AllocateTextures(GLContext *gl);
void UpdateTextures(GLContext *gl);
bool HasData() { return mHasData; }
bool HasTextures()
{
return mTextures[0].IsAllocated() && mTextures[1].IsAllocated() &&
mTextures[2].IsAllocated();
}
PRUint8* AllocateBuffer(PRUint32 aSize) {
return mRecycleBin->GetBuffer(aSize);
}
PRUint32 GetDataSize() { return mBuffer ? mBufferSize : 0; }
nsAutoArrayPtr<PRUint8> mBuffer;
PRUint32 mBufferSize;
nsRefPtr<RecycleBin> mRecycleBin;
GLTexture mTextures[3];
Data mData;
gfxIntSize mSize;
bool mHasData;
gfxIntSize mYSize, mCbCrSize;
nsRefPtr<TextureRecycleBin> mTextureRecycleBin;
};
class THEBES_API CairoImageOGL : public CairoImage
struct CairoOGLBackendData : public ImageBackendData
{
typedef mozilla::gl::GLContext GLContext;
public:
CairoImageOGL(LayerManagerOGL *aManager);
void SetData(const Data &aData);
GLTexture mTexture;
gfxIntSize mSize;
gl::ShaderProgramType mLayerProgram;
#if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
nsRefPtr<gfxASurface> mSurface;
#endif
CairoOGLBackendData() : mLayerProgram(gl::RGBALayerProgramType), mTiling(false) {}
void SetTiling(bool aTiling);
private:
GLTexture mTexture;
gl::ShaderProgramType mLayerProgram;
bool mTiling;
};

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

@ -102,14 +102,6 @@ LayerManagerOGL::Destroy()
}
mRoot = nsnull;
// Make a copy, since SetLayerManager will cause mImageContainers
// to get mutated.
nsTArray<ImageContainer*> imageContainers(mImageContainers);
for (PRUint32 i = 0; i < imageContainers.Length(); ++i) {
ImageContainer *c = imageContainers[i];
c->SetLayerManager(nsnull);
}
CleanupResources();
mDestroyed = true;
@ -477,19 +469,6 @@ LayerManagerOGL::CreateContainerLayer()
return layer.forget();
}
already_AddRefed<ImageContainer>
LayerManagerOGL::CreateImageContainer()
{
if (mDestroyed) {
NS_WARNING("Call on destroyed layer manager");
return nsnull;
}
nsRefPtr<ImageContainer> container = new ImageContainerOGL(this);
RememberImageContainer(container);
return container.forget();
}
already_AddRefed<ImageLayer>
LayerManagerOGL::CreateImageLayer()
{
@ -526,26 +505,6 @@ LayerManagerOGL::CreateCanvasLayer()
return layer.forget();
}
void
LayerManagerOGL::ForgetImageContainer(ImageContainer *aContainer)
{
NS_ASSERTION(aContainer->Manager() == this,
"ForgetImageContainer called on non-owned container!");
if (!mImageContainers.RemoveElement(aContainer)) {
NS_WARNING("ForgetImageContainer couldn't find container it was supposed to forget!");
return;
}
}
void
LayerManagerOGL::RememberImageContainer(ImageContainer *aContainer)
{
NS_ASSERTION(aContainer->Manager() == this,
"RememberImageContainer called on non-owned container!");
mImageContainers.AppendElement(aContainer);
}
LayerOGL*
LayerManagerOGL::RootLayer() const
{

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

@ -162,8 +162,6 @@ public:
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
virtual already_AddRefed<ImageContainer> CreateImageContainer();
virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer();
virtual already_AddRefed<ShadowContainerLayer> CreateShadowContainerLayer();
virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer();
@ -173,16 +171,6 @@ public:
virtual LayersBackend GetBackendType() { return LAYERS_OPENGL; }
virtual void GetBackendName(nsAString& name) { name.AssignLiteral("OpenGL"); }
/**
* Image Container management.
*/
/* Forget this image container. Should be called by ImageContainerOGL
* on its current layer manager before switching to a new one.
*/
void ForgetImageContainer(ImageContainer* aContainer);
void RememberImageContainer(ImageContainer* aContainer);
/**
* Helper methods.
*/
@ -423,11 +411,6 @@ private:
already_AddRefed<mozilla::gl::GLContext> CreateContext();
// The image containers that this layer manager has created.
// The destructor will tell the layer manager to remove
// it from the list.
nsTArray<ImageContainer*> mImageContainers;
static ProgramType sLayerProgramTypes[];
/** Backbuffer */

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

@ -1,120 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Matt Woodrow <mwoodrow@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 "ImageLayerOGL.h"
#include "MacIOSurfaceImageOGL.h"
#include <AppKit/NSOpenGL.h>
#include "OpenGL/OpenGL.h"
using namespace mozilla::gl;
namespace mozilla {
namespace layers {
MacIOSurfaceImageOGL::MacIOSurfaceImageOGL(LayerManagerOGL *aManager)
: MacIOSurfaceImage(nsnull), mSize(0, 0), mPluginInstanceOwner(nsnull),
mUpdateCallback(nsnull), mDestroyCallback(nsnull)
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread to create a cairo image");
if (aManager) {
// Allocate texture now to grab a reference to the GLContext
GLContext *gl = aManager->glForResources();
mTexture.Allocate(gl);
gl->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, mTexture.GetTextureID());
gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
LOCAL_GL_TEXTURE_MIN_FILTER,
LOCAL_GL_NEAREST);
gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
LOCAL_GL_TEXTURE_MAG_FILTER,
LOCAL_GL_NEAREST);
gl->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
}
}
MacIOSurfaceImageOGL::~MacIOSurfaceImageOGL()
{
if (mDestroyCallback) {
mDestroyCallback(mPluginInstanceOwner);
}
}
void
MacIOSurfaceImageOGL::SetData(const MacIOSurfaceImage::Data &aData)
{
mIOSurface = nsIOSurface::LookupSurface(aData.mIOSurface->GetIOSurfaceID());
mSize = gfxIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight());
GLContext *gl = mTexture.GetGLContext();
gl->MakeCurrent();
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
gl->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, mTexture.GetTextureID());
void *nativeCtx = gl->GetNativeData(GLContext::NativeGLContext);
NSOpenGLContext* nsCtx = (NSOpenGLContext*)nativeCtx;
mIOSurface->CGLTexImageIOSurface2D((CGLContextObj)[nsCtx CGLContextObj],
LOCAL_GL_RGBA, LOCAL_GL_BGRA,
LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV, 0);
gl->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
}
void
MacIOSurfaceImageOGL::SetUpdateCallback(UpdateSurfaceCallback aCallback, void* aPluginInstanceOwner)
{
mUpdateCallback = aCallback;
mPluginInstanceOwner = aPluginInstanceOwner;
}
void
MacIOSurfaceImageOGL::SetDestroyCallback(DestroyCallback aCallback)
{
mDestroyCallback = aCallback;
}
void
MacIOSurfaceImageOGL::Update(ImageContainer* aContainer)
{
if (mUpdateCallback) {
mUpdateCallback(aContainer, mPluginInstanceOwner);
}
}
} /* layers */
} /* mozilla */

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

@ -79,6 +79,7 @@ EXPORTS = \
gfxUtils.h \
gfxUserFontSet.h \
nsCoreAnimationSupport.h \
nsIOSurface.h \
gfxSharedImageSurface.h \
$(NULL)

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

@ -41,6 +41,9 @@
#include "gfxTypes.h"
#include "gfxRect.h"
#include "nsAutoPtr.h"
#include "nsAutoRef.h"
#include "nsThreadUtils.h"
typedef struct _cairo_surface cairo_surface_t;
typedef struct _cairo_user_data_key cairo_user_data_key_t;
@ -358,4 +361,56 @@ public:
virtual ~gfxUnknownSurface() { }
};
#ifndef XPCOM_GLUE_AVOID_NSPR
/**
* We need to be able to hold a reference to a gfxASurface from Image
* subclasses. This is potentially a problem since Images can be addrefed
* or released off the main thread. We can ensure that we never AddRef
* a gfxASurface off the main thread, but we might want to Release due
* to an Image being destroyed off the main thread.
*
* We use nsCountedRef<nsMainThreadSurfaceRef> to reference the
* gfxASurface. When AddRefing, we assert that we're on the main thread.
* When Releasing, if we're not on the main thread, we post an event to
* the main thread to do the actual release.
*/
class nsMainThreadSurfaceRef;
template <>
class nsAutoRefTraits<nsMainThreadSurfaceRef> {
public:
typedef gfxASurface* RawRef;
/**
* The XPCOM event that will do the actual release on the main thread.
*/
class SurfaceReleaser : public nsRunnable {
public:
SurfaceReleaser(RawRef aRef) : mRef(aRef) {}
NS_IMETHOD Run() {
mRef->Release();
return NS_OK;
}
RawRef mRef;
};
static RawRef Void() { return nsnull; }
static void Release(RawRef aRawRef)
{
if (NS_IsMainThread()) {
aRawRef->Release();
return;
}
nsCOMPtr<nsIRunnable> runnable = new SurfaceReleaser(aRawRef);
NS_DispatchToMainThread(runnable);
}
static void AddRef(RawRef aRawRef)
{
NS_ASSERTION(NS_IsMainThread(),
"Can only add a reference on the main thread");
aRawRef->AddRef();
}
};
#endif
#endif /* GFX_ASURFACE_H */

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

@ -58,16 +58,16 @@ gfxAlphaBoxBlur::Init(const gfxRect& aRect,
const gfxRect* aDirtyRect,
const gfxRect* aSkipRect)
{
Rect rect(aRect.x, aRect.y, aRect.width, aRect.height);
mozilla::gfx::Rect rect(aRect.x, aRect.y, aRect.width, aRect.height);
IntSize spreadRadius(aSpreadRadius.width, aSpreadRadius.height);
IntSize blurRadius(aBlurRadius.width, aBlurRadius.height);
nsAutoPtr<Rect> dirtyRect;
nsAutoPtr<mozilla::gfx::Rect> dirtyRect;
if (aDirtyRect) {
dirtyRect = new Rect(aDirtyRect->x, aDirtyRect->y, aDirtyRect->width, aDirtyRect->height);
dirtyRect = new mozilla::gfx::Rect(aDirtyRect->x, aDirtyRect->y, aDirtyRect->width, aDirtyRect->height);
}
nsAutoPtr<Rect> skipRect;
nsAutoPtr<mozilla::gfx::Rect> skipRect;
if (aSkipRect) {
skipRect = new Rect(aSkipRect->x, aSkipRect->y, aSkipRect->width, aSkipRect->height);
skipRect = new mozilla::gfx::Rect(aSkipRect->x, aSkipRect->y, aSkipRect->width, aSkipRect->height);
}
mBlur = new AlphaBoxBlur(rect, spreadRadius, blurRadius, dirtyRect, skipRect);
@ -106,7 +106,7 @@ gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx, const gfxPoint& offset)
mBlur->Blur();
Rect* dirtyrect = mBlur->GetDirtyRect();
mozilla::gfx::Rect* dirtyrect = mBlur->GetDirtyRect();
// Avoid a semi-expensive clip operation if we can, otherwise
// clip to the dirty rect
@ -125,7 +125,7 @@ gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx, const gfxPoint& offset)
gfxIntSize gfxAlphaBoxBlur::CalculateBlurRadius(const gfxPoint& aStd)
{
Point std(aStd.x, aStd.y);
mozilla::gfx::Point std(aStd.x, aStd.y);
IntSize size = AlphaBoxBlur::CalculateBlurRadius(std);
return gfxIntSize(size.width, size.height);
}

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

@ -41,11 +41,12 @@
#define nsCoreAnimationSupport_h__
#ifdef XP_MACOSX
#import <QuartzCore/QuartzCore.h>
#import <OpenGL/OpenGL.h>
#import "ApplicationServices/ApplicationServices.h"
#include "nscore.h"
#include "gfxTypes.h"
#include "nsAutoPtr.h"
#include "nsIOSurface.h"
// Get the system color space.
CGColorSpaceRef THEBES_API CreateSystemColorSpace();
@ -53,12 +54,9 @@ CGColorSpaceRef THEBES_API CreateSystemColorSpace();
// Manages a CARenderer
struct _CGLPBufferObject;
struct _CGLContextObject;
class nsIOSurface;
enum AllowOfflineRendererEnum { ALLOW_OFFLINE_RENDERER, DISALLOW_OFFLINE_RENDERER };
typedef uint32_t IOSurfaceID;
class THEBES_API nsCARenderer {
NS_INLINE_DECL_REFCOUNTING(nsCARenderer)
public:
@ -110,30 +108,6 @@ private:
AllowOfflineRendererEnum mAllowOfflineRenderer;
};
class THEBES_API nsIOSurface {
NS_INLINE_DECL_REFCOUNTING(nsIOSurface)
public:
static already_AddRefed<nsIOSurface> CreateIOSurface(int aWidth, int aHeight);
static void ReleaseIOSurface(nsIOSurface *aIOSurface);
static already_AddRefed<nsIOSurface> LookupSurface(IOSurfaceID aSurfaceID);
nsIOSurface(CFTypeRef aIOSurfacePtr) : mIOSurfacePtr(aIOSurfacePtr) {}
~nsIOSurface() { CFRelease(mIOSurfacePtr); }
IOSurfaceID GetIOSurfaceID();
void *GetBaseAddress();
size_t GetWidth();
size_t GetHeight();
size_t GetBytesPerRow();
void Lock();
void Unlock();
CGLError CGLTexImageIOSurface2D(CGLContextObj ctxt,
GLenum internalFormat, GLenum format,
GLenum type, GLuint plane);
private:
friend class nsCARenderer;
CFTypeRef mIOSurfacePtr;
};
#endif // XP_MACOSX
#endif // nsCoreAnimationSupport_h__

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

@ -202,7 +202,7 @@ CGLError nsIOSurfaceLib::CGLTexImageIOSurface2D(CGLContextObj ctxt,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
IOSurfacePtr ioSurface, GLuint plane) {
return sTexImage(ctxt, target, internalFormat, width, height,
return sTexImage(ctxt, target, internalFormat, width, height,
format, type, ioSurface, plane);
}
@ -267,6 +267,10 @@ void nsIOSurfaceLib::CloseLibrary() {
sOpenGLFramework = nsnull;
}
nsIOSurface::~nsIOSurface() {
CFRelease(mIOSurfacePtr);
}
already_AddRefed<nsIOSurface> nsIOSurface::CreateIOSurface(int aWidth, int aHeight) {
if (!nsIOSurfaceLib::isInit())
return nsnull;
@ -354,13 +358,37 @@ void nsIOSurface::Unlock() {
nsIOSurfaceLib::IOSurfaceUnlock(mIOSurfacePtr, READ_ONLY, NULL);
}
#include "gfxImageSurface.h"
already_AddRefed<gfxASurface>
nsIOSurface::GetAsSurface() {
Lock();
size_t bytesPerRow = GetBytesPerRow();
size_t ioWidth = GetWidth();
size_t ioHeight = GetHeight();
unsigned char* ioData = (unsigned char*)GetBaseAddress();
nsRefPtr<gfxImageSurface> imgSurface =
new gfxImageSurface(gfxIntSize(ioWidth, ioHeight), gfxASurface::ImageFormatARGB32);
for (int i = 0; i < ioHeight; i++) {
memcpy(imgSurface->Data() + i * imgSurface->Stride(),
ioData + i * bytesPerRow, ioWidth * 4);
}
Unlock();
return imgSurface.forget();
}
CGLError
nsIOSurface::CGLTexImageIOSurface2D(CGLContextObj ctxt,
nsIOSurface::CGLTexImageIOSurface2D(NSOpenGLContext *ctxt,
GLenum internalFormat, GLenum format,
GLenum type, GLuint plane)
{
return nsIOSurfaceLib::CGLTexImageIOSurface2D(ctxt,
GL_TEXTURE_RECTANGLE_ARB,
return nsIOSurfaceLib::CGLTexImageIOSurface2D((CGLContextObj)[ctxt CGLContextObj],
GL_TEXTURE_RECTANGLE_ARB,
internalFormat,
GetWidth(), GetHeight(),
format, type,

79
gfx/thebes/nsIOSurface.h Normal file
Просмотреть файл

@ -0,0 +1,79 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:set ts=2 sts=2 sw=2 et cin:
/* ***** 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.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* bgirard <b56girard@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 nsIOSurface_h__
#define nsIOSurface_h__
#ifdef XP_MACOSX
#import <OpenGL/OpenGL.h>
class gfxASurface;
class _CGLContextObject;
class NSOpenGLContext;
typedef _CGLContextObject* CGLContextObj;
typedef uint32_t IOSurfaceID;
class THEBES_API nsIOSurface {
NS_INLINE_DECL_REFCOUNTING(nsIOSurface)
public:
static already_AddRefed<nsIOSurface> CreateIOSurface(int aWidth, int aHeight);
static void ReleaseIOSurface(nsIOSurface *aIOSurface);
static already_AddRefed<nsIOSurface> LookupSurface(IOSurfaceID aSurfaceID);
nsIOSurface(const void *aIOSurfacePtr) : mIOSurfacePtr(aIOSurfacePtr) {}
~nsIOSurface();
IOSurfaceID GetIOSurfaceID();
void *GetBaseAddress();
size_t GetWidth();
size_t GetHeight();
size_t GetBytesPerRow();
void Lock();
void Unlock();
CGLError CGLTexImageIOSurface2D(NSOpenGLContext *ctxt,
GLenum internalFormat, GLenum format,
GLenum type, GLuint plane);
already_AddRefed<gfxASurface> GetAsSurface();
private:
friend class nsCARenderer;
const void* mIOSurfacePtr;
};
#endif
#endif

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

@ -184,16 +184,20 @@ public:
}
};
#define LOG_SCOPE_APPEND_LINE_NUMBER_PASTE(id, line) id ## line
#define LOG_SCOPE_APPEND_LINE_NUMBER_EXPAND(id, line) LOG_SCOPE_APPEND_LINE_NUMBER_PASTE(id, line)
#define LOG_SCOPE_APPEND_LINE_NUMBER(id) LOG_SCOPE_APPEND_LINE_NUMBER_EXPAND(id, __LINE__)
#define LOG_SCOPE(l, s) \
LogScope LOG_SCOPE_TMP_VAR ##__LINE__ (l, \
static_cast<void *>(this), \
NS_LITERAL_CSTRING(s))
LogScope LOG_SCOPE_APPEND_LINE_NUMBER(LOG_SCOPE_TMP_VAR) (l, \
static_cast<void *>(this), \
NS_LITERAL_CSTRING(s))
#define LOG_SCOPE_WITH_PARAM(l, s, pn, pv) \
LogScope LOG_SCOPE_TMP_VAR ##__LINE__ (l, \
static_cast<void *>(this), \
NS_LITERAL_CSTRING(s), \
NS_LITERAL_CSTRING(pn), pv)
LogScope LOG_SCOPE_APPEND_LINE_NUMBER(LOG_SCOPE_TMP_VAR) (l, \
static_cast<void *>(this), \
NS_LITERAL_CSTRING(s), \
NS_LITERAL_CSTRING(pn), pv)
#define LOG_FUNC(l, s) \
LogFunc(l, \

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

@ -93,7 +93,7 @@ native gfxGraphicsFilter(gfxPattern::GraphicsFilter);
*
* Internally, imgIContainer also manages animation of images.
*/
[scriptable, uuid(8c82b89f-f90c-4a31-a544-6e1f759673d4)]
[scriptable, uuid(2506249c-e0a1-4d8f-846c-2d478247f8d8)]
interface imgIContainer : nsISupports
{
/**
@ -189,10 +189,8 @@ interface imgIContainer : nsISupports
/**
* Attempts to create an ImageContainer (and Image) containing the current
* frame. Only valid for RASTER type images.
*
* @param aManager The layer manager to use to create the ImageContainer.
*/
[noscript] ImageContainer getImageContainer(in LayerManager aManager);
[noscript] ImageContainer getImageContainer();
/**
* Create and return a new copy of the given frame that you can write to

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

@ -945,13 +945,9 @@ RasterImage::GetFrame(PRUint32 aWhichFrame,
NS_IMETHODIMP
RasterImage::GetImageContainer(LayerManager* aManager,
ImageContainer **_retval)
RasterImage::GetImageContainer(ImageContainer **_retval)
{
if (mImageContainer &&
(mImageContainer->Manager() == aManager ||
(!mImageContainer->Manager() &&
(mImageContainer->GetBackendType() == aManager->GetBackendType())))) {
if (mImageContainer) {
*_retval = mImageContainer;
NS_ADDREF(*_retval);
return NS_OK;
@ -966,8 +962,7 @@ RasterImage::GetImageContainer(LayerManager* aManager,
GetWidth(&cairoData.mSize.width);
GetHeight(&cairoData.mSize.height);
mImageContainer = aManager->CreateImageContainer();
NS_ASSERTION(mImageContainer, "Failed to create ImageContainer!");
mImageContainer = LayerManager::CreateImageContainer();
// Now create a CairoImage to display the surface.
layers::Image::Format cairoFormat = layers::Image::CAIRO_SURFACE;

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

@ -190,7 +190,7 @@ public:
NS_SCRIPTABLE NS_IMETHOD GetAnimated(bool *aAnimated);
NS_SCRIPTABLE NS_IMETHOD GetCurrentFrameIsOpaque(bool *aCurrentFrameIsOpaque);
NS_IMETHOD GetFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxASurface **_retval NS_OUTPARAM);
NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager, mozilla::layers::ImageContainer **_retval NS_OUTPARAM);
NS_IMETHOD GetImageContainer(mozilla::layers::ImageContainer **_retval NS_OUTPARAM);
NS_IMETHOD CopyFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxImageSurface **_retval NS_OUTPARAM);
NS_IMETHOD ExtractFrame(PRUint32 aWhichFrame, const nsIntRect & aRect, PRUint32 aFlags, imgIContainer **_retval NS_OUTPARAM);
NS_IMETHOD Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix & aUserSpaceToImageSpace, const gfxRect & aFill, const nsIntRect & aSubimage, const nsIntSize & aViewportSize, PRUint32 aFlags);

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

@ -73,7 +73,7 @@ public:
NS_SCRIPTABLE NS_IMETHOD GetAnimated(bool *aAnimated);
NS_SCRIPTABLE NS_IMETHOD GetCurrentFrameIsOpaque(bool *aCurrentFrameIsOpaque);
NS_IMETHOD GetFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxASurface **_retval NS_OUTPARAM);
NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager, mozilla::layers::ImageContainer **_retval NS_OUTPARAM) { *_retval = NULL; return NS_OK; }
NS_IMETHOD GetImageContainer(mozilla::layers::ImageContainer **_retval NS_OUTPARAM) { *_retval = NULL; return NS_OK; }
NS_IMETHOD CopyFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxImageSurface **_retval NS_OUTPARAM);
NS_IMETHOD ExtractFrame(PRUint32 aWhichFrame, const nsIntRect & aRect, PRUint32 aFlags, imgIContainer **_retval NS_OUTPARAM);
NS_IMETHOD Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix & aUserSpaceToImageSpace, const gfxRect & aFill, const nsIntRect & aSubimage, const nsIntSize & aViewportSize, PRUint32 aFlags);

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

@ -90,14 +90,10 @@ HashableValue::setValue(JSContext *cx, const Value &v)
if (JSDOUBLE_IS_INT32(d, &i)) {
/* Normalize int32-valued doubles to int32 for faster hashing and testing. */
value = Int32Value(i);
} else if (JSDOUBLE_IS_NaN(d)) {
/* NaNs with different bits must hash and test identically. */
value = DoubleValue(js_NaN);
} else {
#ifdef DEBUG
/* All NaN values are the same. The bit-pattern must reflect this. */
jsval_layout a, b;
a.asDouble = d;
b.asDouble = JS_CANONICALIZE_NAN(d);
JS_ASSERT(a.asBits == b.asBits);
#endif
value = v;
}
} else {

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