Merge m-c to fx-team.

This commit is contained in:
Ryan VanderMeulen 2014-03-31 17:31:19 -04:00
commit a30c6ca187
179 changed files with 4503 additions and 3015 deletions

View File

@ -55,6 +55,7 @@ enum AccType {
eProgressType,
eRootType,
eXULLabelType,
eXULListItemType,
eXULTabpanelsType,
eXULTreeType,

View File

@ -9,6 +9,7 @@
#include "nsEventShell.h"
#include "DocAccessible.h"
#include "nsAccessibilityService.h"
#include "nsTextEquivUtils.h"
#ifdef A11Y_LOG
#include "Logging.h"
#endif
@ -37,6 +38,38 @@ EventQueue::PushEvent(AccEvent* aEvent)
// Filter events.
CoalesceEvents();
// Fire name change event on parent given that this event hasn't been
// coalesced, the parent's name was calculated from its subtree, and the
// subtree was changed.
Accessible* target = aEvent->mAccessible;
if (aEvent->mEventRule != AccEvent::eDoNotEmit &&
target->HasNameDependentParent() &&
(aEvent->mEventType == nsIAccessibleEvent::EVENT_NAME_CHANGE ||
aEvent->mEventType == nsIAccessibleEvent::EVENT_TEXT_REMOVED ||
aEvent->mEventType == nsIAccessibleEvent::EVENT_TEXT_INSERTED ||
aEvent->mEventType == nsIAccessibleEvent::EVENT_SHOW ||
aEvent->mEventType == nsIAccessibleEvent::EVENT_HIDE)) {
// Only continue traversing up the tree if it's possible that the parent
// accessible's name can depend on this accessible's name.
Accessible* parent = target->Parent();
while (parent &&
nsTextEquivUtils::HasNameRule(parent, eNameFromSubtreeIfReqRule)) {
// Test possible name dependent parent.
if (nsTextEquivUtils::HasNameRule(parent, eNameFromSubtreeRule)) {
nsAutoString name;
ENameValueFlag nameFlag = parent->Name(name);
// If name is obtained from subtree, fire name change event.
if (nameFlag == eNameFromSubtree) {
nsRefPtr<AccEvent> nameChangeEvent =
new AccEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, parent);
PushEvent(nameChangeEvent);
}
break;
}
parent = parent->Parent();
}
}
// Associate text change with hide event if it wasn't stolen from hiding
// siblings during coalescence.
AccMutationEvent* showOrHideEvent = downcast_accEvent(aEvent);

View File

@ -344,7 +344,7 @@ nsTextEquivUtils::AppendString(nsAString *aString,
return true;
}
uint32_t
uint32_t
nsTextEquivUtils::GetRoleRule(role aRole)
{
#define ROLE(geckoRole, stringRole, atkRole, \
@ -360,4 +360,3 @@ nsTextEquivUtils::GetRoleRule(role aRole)
#undef ROLE
}

View File

@ -43,6 +43,18 @@ class nsTextEquivUtils
public:
typedef mozilla::a11y::Accessible Accessible;
/**
* Determines if the accessible has a given name rule.
*
* @param aAccessible [in] the given accessible
* @param aRule [in] a given name rule
* @return true if the accessible has the rule
*/
static inline bool HasNameRule(Accessible* aAccessible, ETextEquivRule aRule)
{
return (GetRoleRule(aAccessible->Role()) & aRule) == aRule;
}
/**
* Calculates the name from accessible subtree if allowed.
*

View File

@ -111,8 +111,8 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(Accessible, LastRelease())
Accessible::Accessible(nsIContent* aContent, DocAccessible* aDoc) :
mContent(aContent), mDoc(aDoc),
mParent(nullptr), mIndexInParent(-1), mChildrenFlags(eChildrenUninitialized),
mStateFlags(0), mType(0), mGenericTypes(0), mIndexOfEmbeddedChild(-1),
mRoleMapEntry(nullptr)
mStateFlags(0), mContextFlags(0), mType(0), mGenericTypes(0),
mIndexOfEmbeddedChild(-1), mRoleMapEntry(nullptr)
{
#ifdef NS_DEBUG_X
{
@ -2533,6 +2533,12 @@ Accessible::BindToParent(Accessible* aParent, uint32_t aIndexInParent)
mIndexInParent = aIndexInParent;
mParent->InvalidateChildrenGroupInfo();
// Note: this is currently only used for richlistitems and their children.
if (mParent->HasNameDependentParent() || mParent->IsXULListItem())
mContextFlags |= eHasNameDependentParent;
else
mContextFlags &= ~eHasNameDependentParent;
}
// Accessible protected
@ -2544,6 +2550,7 @@ Accessible::UnbindFromParent()
mIndexInParent = -1;
mIndexOfEmbeddedChild = -1;
mGroupInfo = nullptr;
mContextFlags &= ~eHasNameDependentParent;
}
////////////////////////////////////////////////////////////////////////////////
@ -3241,6 +3248,8 @@ Accessible::StaticAsserts() const
"Accessible::mStateFlags was oversized by eLastStateFlag!");
static_assert(eLastAccType <= (1 << kTypeBits) - 1,
"Accessible::mType was oversized by eLastAccType!");
static_assert(eLastContextFlag <= (1 << kContextFlagsBits) - 1,
"Accessible::mContextFlags was oversized by eLastContextFlag!");
static_assert(eLastAccGenericType <= (1 << kGenericTypesBits) - 1,
"Accessible::mGenericType was oversized by eLastAccGenericType!");
}

View File

@ -579,6 +579,8 @@ public:
bool IsXULLabel() const { return mType == eXULLabelType; }
XULLabelAccessible* AsXULLabel();
bool IsXULListItem() const { return mType == eXULListItemType; }
bool IsXULTabpanels() const { return mType == eXULTabpanelsType; }
bool IsXULTree() const { return mType == eXULTreeType; }
@ -790,6 +792,13 @@ public:
bool NeedsDOMUIEvent() const
{ return !(mStateFlags & eIgnoreDOMUIEvent); }
/**
* Return true if this accessible has a parent whose name depends on this
* accessible.
*/
bool HasNameDependentParent() const
{ return mContextFlags & eHasNameDependentParent; }
protected:
/**
@ -867,6 +876,15 @@ protected:
eLastStateFlag = eGroupInfoDirty
};
/**
* Flags used for contextual information about the accessible.
*/
enum ContextFlags {
eHasNameDependentParent = 1 << 0, // Parent's name depends on this accessible.
eLastContextFlag = eHasNameDependentParent
};
protected:
//////////////////////////////////////////////////////////////////////////////
@ -970,14 +988,16 @@ protected:
static const uint8_t kChildrenFlagsBits = 2;
static const uint8_t kStateFlagsBits = 6;
static const uint8_t kContextFlagsBits = 1;
static const uint8_t kTypeBits = 6;
static const uint8_t kGenericTypesBits = 12;
/**
* Keep in sync with ChildrenFlags, StateFlags and AccTypes.
* Keep in sync with ChildrenFlags, StateFlags, ContextFlags, and AccTypes.
*/
uint32_t mChildrenFlags : kChildrenFlagsBits;
uint32_t mStateFlags : kStateFlagsBits;
uint32_t mContextFlags : kContextFlagsBits;
uint32_t mType : kTypeBits;
uint32_t mGenericTypes : kGenericTypesBits;

View File

@ -582,6 +582,7 @@ XULListitemAccessible::
nsGkAtoms::type,
nsGkAtoms::checkbox,
eCaseMatters);
mType = eXULListItemType;
}
NS_IMPL_ISUPPORTS_INHERITED0(XULListitemAccessible, Accessible)

View File

@ -41,6 +41,7 @@ skip-if = os == 'win' || os == 'linux'
[test_menu.xul]
[test_mutation.html]
[test_mutation.xhtml]
[test_name.xul]
[test_scroll.xul]
[test_selection.html]
[test_selection.xul]

View File

@ -0,0 +1,92 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
<![CDATA[
/**
* Check name changed a11y event.
*/
function nameChangeChecker(aMsg, aID)
{
this.type = EVENT_NAME_CHANGE;
function targetGetter()
{
return getAccessible(aID);
}
Object.defineProperty(this, "target", { get: targetGetter });
this.getID = function getID()
{
return aMsg + " name changed";
}
}
function changeRichListItemChild()
{
this.invoke = function changeRichListItemChild_invoke()
{
getNode('childcontent').setAttribute('value', 'Changed.');
}
this.eventSeq =
[
new nameChangeChecker("changeRichListItemChild: ", "listitem")
];
this.getID = function changeRichListItemChild_getID()
{
return "changeRichListItemChild";
}
}
function doTest()
{
var queue = new eventQueue();
queue.push(new changeRichListItemChild());
queue.invoke();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<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=986054"
title="Propagate name change events">
Mozilla Bug 986054
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<richlistbox>
<richlistitem id="listitem">
<description id="childcontent" value="This will be changed."/>
</richlistitem>
</richlistbox>
</vbox>
</window>

View File

@ -596,10 +596,9 @@ var shell = {
},
openAppForSystemMessage: function shell_openAppForSystemMessage(msg) {
let origin = Services.io.newURI(msg.manifest, null, null).prePath;
let payload = {
url: msg.uri,
manifestURL: msg.manifest,
url: msg.pageURL,
manifestURL: msg.manifestURL,
isActivity: (msg.type == 'activity'),
onlyShowApp: msg.onlyShowApp,
showApp: msg.showApp,
@ -877,7 +876,7 @@ var AlertsHelper = {
});
},
showNotification: function alert_showNotification(imageUrl,
showNotification: function alert_showNotification(imageURL,
title,
text,
textClickable,
@ -885,37 +884,37 @@ var AlertsHelper = {
uid,
bidi,
lang,
manifestUrl) {
manifestURL) {
function send(appName, appIcon) {
shell.sendChromeEvent({
type: "desktop-notification",
id: uid,
icon: imageUrl,
icon: imageURL,
title: title,
text: text,
bidi: bidi,
lang: lang,
appName: appName,
appIcon: appIcon,
manifestURL: manifestUrl
manifestURL: manifestURL
});
}
if (!manifestUrl || !manifestUrl.length) {
if (!manifestURL || !manifestURL.length) {
send(null, null);
return;
}
// If we have a manifest URL, get the icon and title from the manifest
// to prevent spoofing.
let app = DOMApplicationRegistry.getAppByManifestURL(manifestUrl);
DOMApplicationRegistry.getManifestFor(manifestUrl).then((aManifest) => {
let app = DOMApplicationRegistry.getAppByManifestURL(manifestURL);
DOMApplicationRegistry.getManifestFor(manifestURL).then((aManifest) => {
let helper = new ManifestHelper(aManifest, app.origin);
send(helper.name, helper.iconURLForSize(128));
});
},
showAlertNotification: function alert_showAlertNotification(imageUrl,
showAlertNotification: function alert_showAlertNotification(imageURL,
title,
text,
textClickable,
@ -930,7 +929,7 @@ var AlertsHelper = {
}
this.registerListener(name, cookie, alertListener);
this.showNotification(imageUrl, title, text, textClickable, cookie,
this.showNotification(imageURL, title, text, textClickable, cookie,
name, bidi, lang, null);
},

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="26839cb46f856d610b192f5655a8c38a6bfe0829"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="26839cb46f856d610b192f5655a8c38a6bfe0829"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="89c5816399e71bda92a8959b5b771c04d6672ea3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="a9e08b91e9cd1f0930f16cfc49ec72f63575d5fe">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="26839cb46f856d610b192f5655a8c38a6bfe0829"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="26839cb46f856d610b192f5655a8c38a6bfe0829"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "5f0660e48c2689c6de19a50aebfabf29e01a144e",
"revision": "6c593455e3d1292120a6f3d41ec5d06bc91019f1",
"repo_path": "/integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="26839cb46f856d610b192f5655a8c38a6bfe0829"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="26839cb46f856d610b192f5655a8c38a6bfe0829"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="26839cb46f856d610b192f5655a8c38a6bfe0829"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="26839cb46f856d610b192f5655a8c38a6bfe0829"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="26839cb46f856d610b192f5655a8c38a6bfe0829"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="89c5816399e71bda92a8959b5b771c04d6672ea3"/>

View File

@ -0,0 +1,31 @@
. $topsrcdir/build/macosx/mozconfig.common
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-signmar
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
#ac_add_options --with-macbundlename-prefix=Firefox
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# B2G Stuff
ac_add_options --enable-application=b2g
ac_add_options --enable-debug-symbols
ac_add_options --enable-debug
ac_add_options --with-ccache
ENABLE_MARIONETTE=1
export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
GAIADIR=$topsrcdir/gaia
. "$topsrcdir/b2g/config/mozconfigs/common.override"

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="26839cb46f856d610b192f5655a8c38a6bfe0829"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -5840,6 +5840,10 @@ if test "$OS_TARGET" = "WINNT" -a -z "$CROSS_COMPILE"; then
fi
fi
# On mingw, check if headers are provided by toolchain.
if test "$OS_TARGET" = "WINNT" -a -n "$GNU_CC"; then
MOZ_CHECK_HEADER(d3d10.h, MOZ_HAS_WINSDK_WITH_D3D=1)
fi
dnl ========================================================
dnl D3D compiler DLL
@ -5914,7 +5918,7 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
fi
fi
if test -z "$MOZ_D3DCOMPILER_DLL_PATH" -a -z "$MOZ_D3DCOMPILER_CAB"; then
if test -z "$MOZ_D3DCOMPILER_DLL_PATH" -a -z "$MOZ_D3DCOMPILER_CAB" -a -z "$CROSS_COMPILE"; then
AC_MSG_ERROR([Couldn't find an acceptable D3D compiler DLL. Either install Windows SDK 8.0+ and reconfigure with --enable-winsdk-directx, install DirectX SDK (June 2010 version or newer), or reconfigure with --disable-webgl.])
fi
fi

View File

@ -7,8 +7,9 @@
#include "base/basictypes.h"
#include "gfx2DGlue.h"
#include "gfxImageSurface.h"
#include "gfxPattern.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMWindow.h"
#include "nsIDocShell.h"
@ -26,6 +27,7 @@
#include "mozilla/gfx/Matrix.h"
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::ipc;
DocumentRendererChild::DocumentRendererChild()
@ -72,12 +74,13 @@ DocumentRendererChild::RenderDocument(nsIDOMWindow *window,
// Draw directly into the output array.
data.SetLength(renderSize.width * renderSize.height * 4);
nsRefPtr<gfxImageSurface> surf =
new gfxImageSurface(reinterpret_cast<uint8_t*>(data.BeginWriting()),
gfxIntSize(renderSize.width, renderSize.height),
4 * renderSize.width,
gfxImageFormat::ARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
RefPtr<DrawTarget> dt =
Factory::CreateDrawTargetForData(BackendType::CAIRO,
reinterpret_cast<uint8_t*>(data.BeginWriting()),
IntSize(renderSize.width, renderSize.height),
4 * renderSize.width,
SurfaceFormat::B8G8R8A8);
nsRefPtr<gfxContext> ctx = new gfxContext(dt);
ctx->SetMatrix(mozilla::gfx::ThebesMatrix(transform));
nsCOMPtr<nsIPresShell> shell = presContext->PresShell();

View File

@ -816,7 +816,6 @@ protected:
WebGLVertexAttrib0Status WhatDoesVertexAttrib0Need();
bool DoFakeVertexAttrib0(GLuint vertexCount);
void UndoFakeVertexAttrib0();
void InvalidateFakeVertexAttrib0();
static CheckedUint32 GetImageSize(GLsizei height,
GLsizei width,

View File

@ -60,7 +60,7 @@ WebGLContext::CreateQuery()
if (IsContextLost())
return nullptr;
if (mActiveOcclusionQuery && !gl->IsGLES2()) {
if (mActiveOcclusionQuery && !gl->IsGLES()) {
/* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
* Calling either GenQueriesARB or DeleteQueriesARB while any query of
* any target is active causes an INVALID_OPERATION error to be
@ -95,7 +95,7 @@ WebGLContext::DeleteQuery(WebGLQuery *query)
EndQuery(query->mType);
}
if (mActiveOcclusionQuery && !gl->IsGLES2()) {
if (mActiveOcclusionQuery && !gl->IsGLES()) {
/* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
* Calling either GenQueriesARB or DeleteQueriesARB while any query of
* any target is active causes an INVALID_OPERATION error to be

View File

@ -0,0 +1,726 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "GLContext.h"
#include "mozilla/CheckedInt.h"
#include "WebGLBuffer.h"
#include "WebGLFramebuffer.h"
#include "WebGLProgram.h"
#include "WebGLRenderbuffer.h"
#include "WebGLShader.h"
#include "WebGLTexture.h"
#include "WebGLUniformInfo.h"
#include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::gl;
// For a Tegra workaround.
static const int MAX_DRAW_CALLS_SINCE_FLUSH = 100;
bool
WebGLContext::DrawInstanced_check(const char* info)
{
// This restriction was removed in GLES3, so WebGL2 shouldn't have it.
if (!IsWebGL2() &&
IsExtensionEnabled(ANGLE_instanced_arrays) &&
!mBufferFetchingHasPerVertex)
{
/* http://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_instanced_arrays.txt
* If all of the enabled vertex attribute arrays that are bound to active
* generic attributes in the program have a non-zero divisor, the draw
* call should return INVALID_OPERATION.
*
* NB: This also appears to apply to NV_instanced_arrays, though the
* INVALID_OPERATION emission is not explicitly stated.
* ARB_instanced_arrays does not have this restriction.
*/
ErrorInvalidOperation("%s: at least one vertex attribute divisor should be 0", info);
return false;
}
return true;
}
bool WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount, const char* info)
{
if (first < 0 || count < 0) {
ErrorInvalidValue("%s: negative first or count", info);
return false;
}
if (primcount < 0) {
ErrorInvalidValue("%s: negative primcount", info);
return false;
}
if (!ValidateStencilParamsForDrawCall()) {
return false;
}
// If count is 0, there's nothing to do.
if (count == 0 || primcount == 0) {
return false;
}
// If there is no current program, this is silently ignored.
// Any checks below this depend on a program being available.
if (!mCurrentProgram) {
return false;
}
if (!ValidateBufferFetching(info)) {
return false;
}
CheckedInt<GLsizei> checked_firstPlusCount = CheckedInt<GLsizei>(first) + count;
if (!checked_firstPlusCount.isValid()) {
ErrorInvalidOperation("%s: overflow in first+count", info);
return false;
}
if (uint32_t(checked_firstPlusCount.value()) > mMaxFetchedVertices) {
ErrorInvalidOperation("%s: bound vertex attribute buffers do not have sufficient size for given first and count", info);
return false;
}
if (uint32_t(primcount) > mMaxFetchedInstances) {
ErrorInvalidOperation("%s: bound instance attribute buffers do not have sufficient size for given primcount", info);
return false;
}
MakeContextCurrent();
if (mBoundFramebuffer) {
if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
return false;
}
}
if (!DoFakeVertexAttrib0(checked_firstPlusCount.value())) {
return false;
}
BindFakeBlackTextures();
return true;
}
void
WebGLContext::DrawArrays(GLenum mode, GLint first, GLsizei count)
{
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, "drawArrays: mode"))
return;
if (!DrawArrays_check(first, count, 1, "drawArrays"))
return;
SetupContextLossTimer();
gl->fDrawArrays(mode, first, count);
Draw_cleanup();
}
void
WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
{
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, "drawArraysInstanced: mode"))
return;
if (!DrawArrays_check(first, count, primcount, "drawArraysInstanced"))
return;
if (!DrawInstanced_check("drawArraysInstanced"))
return;
SetupContextLossTimer();
gl->fDrawArraysInstanced(mode, first, count, primcount);
Draw_cleanup();
}
bool
WebGLContext::DrawElements_check(GLsizei count, GLenum type,
WebGLintptr byteOffset, GLsizei primcount,
const char* info, GLuint* out_upperBound)
{
if (count < 0 || byteOffset < 0) {
ErrorInvalidValue("%s: negative count or offset", info);
return false;
}
if (primcount < 0) {
ErrorInvalidValue("%s: negative primcount", info);
return false;
}
if (!ValidateStencilParamsForDrawCall()) {
return false;
}
// If count is 0, there's nothing to do.
if (count == 0 || primcount == 0) {
return false;
}
CheckedUint32 checked_byteCount;
GLsizei first = 0;
if (type == LOCAL_GL_UNSIGNED_SHORT) {
checked_byteCount = 2 * CheckedUint32(count);
if (byteOffset % 2 != 0) {
ErrorInvalidOperation("%s: invalid byteOffset for UNSIGNED_SHORT (must be a multiple of 2)", info);
return false;
}
first = byteOffset / 2;
}
else if (type == LOCAL_GL_UNSIGNED_BYTE) {
checked_byteCount = count;
first = byteOffset;
}
else if (type == LOCAL_GL_UNSIGNED_INT && IsExtensionEnabled(OES_element_index_uint)) {
checked_byteCount = 4 * CheckedUint32(count);
if (byteOffset % 4 != 0) {
ErrorInvalidOperation("%s: invalid byteOffset for UNSIGNED_INT (must be a multiple of 4)", info);
return false;
}
first = byteOffset / 4;
}
else {
ErrorInvalidEnum("%s: type must be UNSIGNED_SHORT or UNSIGNED_BYTE", info);
return false;
}
if (!checked_byteCount.isValid()) {
ErrorInvalidValue("%s: overflow in byteCount", info);
return false;
}
// If there is no current program, this is silently ignored.
// Any checks below this depend on a program being available.
if (!mCurrentProgram) {
return false;
}
if (!mBoundVertexArray->mBoundElementArrayBuffer) {
ErrorInvalidOperation("%s: must have element array buffer binding", info);
return false;
}
WebGLBuffer& elemArrayBuffer = *mBoundVertexArray->mBoundElementArrayBuffer;
if (!elemArrayBuffer.ByteLength()) {
ErrorInvalidOperation("%s: bound element array buffer doesn't have any data", info);
return false;
}
CheckedInt<GLsizei> checked_neededByteCount = checked_byteCount.toChecked<GLsizei>() + byteOffset;
if (!checked_neededByteCount.isValid()) {
ErrorInvalidOperation("%s: overflow in byteOffset+byteCount", info);
return false;
}
if (uint32_t(checked_neededByteCount.value()) > elemArrayBuffer.ByteLength()) {
ErrorInvalidOperation("%s: bound element array buffer is too small for given count and offset", info);
return false;
}
if (!ValidateBufferFetching(info))
return false;
if (!mMaxFetchedVertices ||
!elemArrayBuffer.Validate(type, mMaxFetchedVertices - 1, first, count, out_upperBound))
{
ErrorInvalidOperation(
"%s: bound vertex attribute buffers do not have sufficient "
"size for given indices from the bound element array", info);
return false;
}
if (uint32_t(primcount) > mMaxFetchedInstances) {
ErrorInvalidOperation("%s: bound instance attribute buffers do not have sufficient size for given primcount", info);
return false;
}
MakeContextCurrent();
if (mBoundFramebuffer) {
if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
return false;
}
}
if (!DoFakeVertexAttrib0(mMaxFetchedVertices)) {
return false;
}
BindFakeBlackTextures();
return true;
}
void
WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
WebGLintptr byteOffset)
{
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, "drawElements: mode"))
return;
GLuint upperBound = UINT_MAX;
if (!DrawElements_check(count, type, byteOffset, 1, "drawElements",
&upperBound))
{
return;
}
SetupContextLossTimer();
if (gl->IsSupported(gl::GLFeature::draw_range_elements)) {
gl->fDrawRangeElements(mode, 0, upperBound,
count, type, reinterpret_cast<GLvoid*>(byteOffset));
} else {
gl->fDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset));
}
Draw_cleanup();
}
void
WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
WebGLintptr byteOffset, GLsizei primcount)
{
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, "drawElementsInstanced: mode"))
return;
if (!DrawElements_check(count, type, byteOffset, primcount, "drawElementsInstanced"))
return;
if (!DrawInstanced_check("drawElementsInstanced"))
return;
SetupContextLossTimer();
gl->fDrawElementsInstanced(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset), primcount);
Draw_cleanup();
}
void WebGLContext::Draw_cleanup()
{
UndoFakeVertexAttrib0();
UnbindFakeBlackTextures();
if (!mBoundFramebuffer) {
Invalidate();
mShouldPresent = true;
mIsScreenCleared = false;
}
if (gl->WorkAroundDriverBugs()) {
if (gl->Renderer() == gl::GLRenderer::Tegra) {
mDrawCallsSinceLastFlush++;
if (mDrawCallsSinceLastFlush >= MAX_DRAW_CALLS_SINCE_FLUSH) {
gl->fFlush();
mDrawCallsSinceLastFlush = 0;
}
}
}
// Let's check the viewport
const WebGLRectangleObject* rect = CurValidFBRectObject();
if (rect) {
if (mViewportWidth > rect->Width() ||
mViewportHeight > rect->Height())
{
if (!mAlreadyWarnedAboutViewportLargerThanDest) {
GenerateWarning("Drawing to a destination rect smaller than the viewport rect. "
"(This warning will only be given once)");
mAlreadyWarnedAboutViewportLargerThanDest = true;
}
}
}
}
/*
* Verify that state is consistent for drawing, and compute max number of elements (maxAllowedCount)
* that will be legal to be read from bound VBOs.
*/
bool
WebGLContext::ValidateBufferFetching(const char *info)
{
#ifdef DEBUG
GLint currentProgram = 0;
MakeContextCurrent();
gl->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &currentProgram);
MOZ_ASSERT(GLuint(currentProgram) == mCurrentProgram->GLName(),
"WebGL: current program doesn't agree with GL state");
#endif
if (mBufferFetchingIsVerified) {
return true;
}
bool hasPerVertex = false;
uint32_t maxVertices = UINT32_MAX;
uint32_t maxInstances = UINT32_MAX;
uint32_t attribs = mBoundVertexArray->mAttribs.Length();
for (uint32_t i = 0; i < attribs; ++i) {
const WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[i];
// If the attrib array isn't enabled, there's nothing to check;
// it's a static value.
if (!vd.enabled)
continue;
if (vd.buf == nullptr) {
ErrorInvalidOperation("%s: no VBO bound to enabled vertex attrib index %d!", info, i);
return false;
}
// If the attrib is not in use, then we don't have to validate
// it, just need to make sure that the binding is non-null.
if (!mCurrentProgram->IsAttribInUse(i))
continue;
// the base offset
CheckedUint32 checked_byteLength = CheckedUint32(vd.buf->ByteLength()) - vd.byteOffset;
CheckedUint32 checked_sizeOfLastElement = CheckedUint32(vd.componentSize()) * vd.size;
if (!checked_byteLength.isValid() ||
!checked_sizeOfLastElement.isValid())
{
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
return false;
}
if (checked_byteLength.value() < checked_sizeOfLastElement.value()) {
maxVertices = 0;
maxInstances = 0;
break;
}
CheckedUint32 checked_maxAllowedCount = ((checked_byteLength - checked_sizeOfLastElement) / vd.actualStride()) + 1;
if (!checked_maxAllowedCount.isValid()) {
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
return false;
}
if (vd.divisor == 0) {
maxVertices = std::min(maxVertices, checked_maxAllowedCount.value());
hasPerVertex = true;
} else {
maxInstances = std::min(maxInstances, checked_maxAllowedCount.value() / vd.divisor);
}
}
mBufferFetchingIsVerified = true;
mBufferFetchingHasPerVertex = hasPerVertex;
mMaxFetchedVertices = maxVertices;
mMaxFetchedInstances = maxInstances;
return true;
}
WebGLVertexAttrib0Status
WebGLContext::WhatDoesVertexAttrib0Need()
{
MOZ_ASSERT(mCurrentProgram);
// work around Mac OSX crash, see bug 631420
#ifdef XP_MACOSX
if (gl->WorkAroundDriverBugs() &&
mBoundVertexArray->IsAttribArrayEnabled(0) &&
!mCurrentProgram->IsAttribInUse(0))
{
return WebGLVertexAttrib0Status::EmulatedUninitializedArray;
}
#endif
if (MOZ_LIKELY(gl->IsGLES() ||
mBoundVertexArray->IsAttribArrayEnabled(0)))
{
return WebGLVertexAttrib0Status::Default;
}
return mCurrentProgram->IsAttribInUse(0)
? WebGLVertexAttrib0Status::EmulatedInitializedArray
: WebGLVertexAttrib0Status::EmulatedUninitializedArray;
}
bool
WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
{
WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
if (MOZ_LIKELY(whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default))
return true;
if (!mAlreadyWarnedAboutFakeVertexAttrib0) {
GenerateWarning("Drawing without vertex attrib 0 array enabled forces the browser "
"to do expensive emulation work when running on desktop OpenGL "
"platforms, for example on Mac. It is preferable to always draw "
"with vertex attrib 0 array enabled, by using bindAttribLocation "
"to bind some always-used attribute to location 0.");
mAlreadyWarnedAboutFakeVertexAttrib0 = true;
}
CheckedUint32 checked_dataSize = CheckedUint32(vertexCount) * 4 * sizeof(GLfloat);
if (!checked_dataSize.isValid()) {
ErrorOutOfMemory("Integer overflow trying to construct a fake vertex attrib 0 array for a draw-operation "
"with %d vertices. Try reducing the number of vertices.", vertexCount);
return false;
}
GLuint dataSize = checked_dataSize.value();
if (!mFakeVertexAttrib0BufferObject) {
gl->fGenBuffers(1, &mFakeVertexAttrib0BufferObject);
}
// if the VBO status is already exactly what we need, or if the only difference is that it's initialized and
// we don't need it to be, then consider it OK
bool vertexAttrib0BufferStatusOK =
mFakeVertexAttrib0BufferStatus == whatDoesAttrib0Need ||
(mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray &&
whatDoesAttrib0Need == WebGLVertexAttrib0Status::EmulatedUninitializedArray);
if (!vertexAttrib0BufferStatusOK ||
mFakeVertexAttrib0BufferObjectSize < dataSize ||
mFakeVertexAttrib0BufferObjectVector[0] != mVertexAttrib0Vector[0] ||
mFakeVertexAttrib0BufferObjectVector[1] != mVertexAttrib0Vector[1] ||
mFakeVertexAttrib0BufferObjectVector[2] != mVertexAttrib0Vector[2] ||
mFakeVertexAttrib0BufferObjectVector[3] != mVertexAttrib0Vector[3])
{
mFakeVertexAttrib0BufferStatus = whatDoesAttrib0Need;
mFakeVertexAttrib0BufferObjectSize = dataSize;
mFakeVertexAttrib0BufferObjectVector[0] = mVertexAttrib0Vector[0];
mFakeVertexAttrib0BufferObjectVector[1] = mVertexAttrib0Vector[1];
mFakeVertexAttrib0BufferObjectVector[2] = mVertexAttrib0Vector[2];
mFakeVertexAttrib0BufferObjectVector[3] = mVertexAttrib0Vector[3];
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
GetAndFlushUnderlyingGLErrors();
if (mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray) {
nsAutoArrayPtr<GLfloat> array(new GLfloat[4 * vertexCount]);
for(size_t i = 0; i < vertexCount; ++i) {
array[4 * i + 0] = mVertexAttrib0Vector[0];
array[4 * i + 1] = mVertexAttrib0Vector[1];
array[4 * i + 2] = mVertexAttrib0Vector[2];
array[4 * i + 3] = mVertexAttrib0Vector[3];
}
gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, array, LOCAL_GL_DYNAMIC_DRAW);
} else {
gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, nullptr, LOCAL_GL_DYNAMIC_DRAW);
}
GLenum error = GetAndFlushUnderlyingGLErrors();
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
// note that we do this error checking and early return AFTER having restored the buffer binding above
if (error) {
ErrorOutOfMemory("Ran out of memory trying to construct a fake vertex attrib 0 array for a draw-operation "
"with %d vertices. Try reducing the number of vertices.", vertexCount);
return false;
}
}
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
gl->fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0);
return true;
}
void
WebGLContext::UndoFakeVertexAttrib0()
{
WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
if (MOZ_LIKELY(whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default))
return;
if (mBoundVertexArray->HasAttrib(0) && mBoundVertexArray->mAttribs[0].buf) {
const WebGLVertexAttribData& attrib0 = mBoundVertexArray->mAttribs[0];
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0.buf->GLName());
gl->fVertexAttribPointer(0,
attrib0.size,
attrib0.type,
attrib0.normalized,
attrib0.stride,
reinterpret_cast<const GLvoid *>(attrib0.byteOffset));
} else {
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
}
WebGLContextFakeBlackStatus
WebGLContext::ResolvedFakeBlackStatus()
{
// handle this case first, it's the generic case
if (MOZ_LIKELY(mFakeBlackStatus == WebGLContextFakeBlackStatus::NotNeeded))
return mFakeBlackStatus;
if (mFakeBlackStatus == WebGLContextFakeBlackStatus::Needed)
return mFakeBlackStatus;
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
if ((mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) ||
(mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded))
{
mFakeBlackStatus = WebGLContextFakeBlackStatus::Needed;
return mFakeBlackStatus;
}
}
// we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
// that means that we do NOT need it.
mFakeBlackStatus = WebGLContextFakeBlackStatus::NotNeeded;
return mFakeBlackStatus;
}
void
WebGLContext::BindFakeBlackTexturesHelper(
GLenum target,
const nsTArray<WebGLRefPtr<WebGLTexture> > & boundTexturesArray,
ScopedDeletePtr<FakeBlackTexture> & opaqueTextureScopedPtr,
ScopedDeletePtr<FakeBlackTexture> & transparentTextureScopedPtr)
{
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
if (!boundTexturesArray[i]) {
continue;
}
WebGLTextureFakeBlackStatus s = boundTexturesArray[i]->ResolvedFakeBlackStatus();
MOZ_ASSERT(s != WebGLTextureFakeBlackStatus::Unknown);
if (MOZ_LIKELY(s == WebGLTextureFakeBlackStatus::NotNeeded)) {
continue;
}
bool alpha = s == WebGLTextureFakeBlackStatus::UninitializedImageData &&
FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().InternalFormat());
ScopedDeletePtr<FakeBlackTexture>&
blackTexturePtr = alpha
? transparentTextureScopedPtr
: opaqueTextureScopedPtr;
if (!blackTexturePtr) {
GLenum format = alpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
blackTexturePtr
= new FakeBlackTexture(gl, target, format);
}
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
gl->fBindTexture(target,
blackTexturePtr->GLName());
}
}
void
WebGLContext::BindFakeBlackTextures()
{
// this is the generic case: try to return early
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
return;
BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_2D,
mBound2DTextures,
mBlackOpaqueTexture2D,
mBlackTransparentTexture2D);
BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_CUBE_MAP,
mBoundCubeMapTextures,
mBlackOpaqueTextureCubeMap,
mBlackTransparentTextureCubeMap);
}
void
WebGLContext::UnbindFakeBlackTextures()
{
// this is the generic case: try to return early
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
return;
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
if (mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBound2DTextures[i]->GLName());
}
if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBoundCubeMapTextures[i]->GLName());
}
}
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
}
WebGLContext::FakeBlackTexture::FakeBlackTexture(GLContext *gl, GLenum target, GLenum format)
: mGL(gl)
, mGLName(0)
{
MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D || target == LOCAL_GL_TEXTURE_CUBE_MAP);
MOZ_ASSERT(format == LOCAL_GL_RGB || format == LOCAL_GL_RGBA);
mGL->MakeCurrent();
GLuint formerBinding = 0;
gl->GetUIntegerv(target == LOCAL_GL_TEXTURE_2D
? LOCAL_GL_TEXTURE_BINDING_2D
: LOCAL_GL_TEXTURE_BINDING_CUBE_MAP,
&formerBinding);
gl->fGenTextures(1, &mGLName);
gl->fBindTexture(target, mGLName);
// we allocate our zeros on the heap, and we overallocate (16 bytes instead of 4)
// to minimize the risk of running into a driver bug in texImage2D, as it is
// a bit unusual maybe to create 1x1 textures, and the stack may not have the alignment
// that texImage2D expects.
void* zeros = calloc(1, 16);
if (target == LOCAL_GL_TEXTURE_2D) {
gl->fTexImage2D(target, 0, format, 1, 1,
0, format, LOCAL_GL_UNSIGNED_BYTE, zeros);
} else {
for (GLuint i = 0; i < 6; ++i) {
gl->fTexImage2D(LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, 1, 1,
0, format, LOCAL_GL_UNSIGNED_BYTE, zeros);
}
}
free(zeros);
gl->fBindTexture(target, formerBinding);
}
WebGLContext::FakeBlackTexture::~FakeBlackTexture()
{
if (mGL) {
mGL->MakeCurrent();
mGL->fDeleteTextures(1, &mGLName);
}
}

View File

@ -72,49 +72,6 @@ WebGLContext::CurValidFBRectObject() const
return rect;
}
WebGLContext::FakeBlackTexture::FakeBlackTexture(GLContext *gl, GLenum target, GLenum format)
: mGL(gl)
, mGLName(0)
{
MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D || target == LOCAL_GL_TEXTURE_CUBE_MAP);
MOZ_ASSERT(format == LOCAL_GL_RGB || format == LOCAL_GL_RGBA);
mGL->MakeCurrent();
GLuint formerBinding = 0;
gl->GetUIntegerv(target == LOCAL_GL_TEXTURE_2D
? LOCAL_GL_TEXTURE_BINDING_2D
: LOCAL_GL_TEXTURE_BINDING_CUBE_MAP,
&formerBinding);
gl->fGenTextures(1, &mGLName);
gl->fBindTexture(target, mGLName);
// we allocate our zeros on the heap, and we overallocate (16 bytes instead of 4)
// to minimize the risk of running into a driver bug in texImage2D, as it is
// a bit unusual maybe to create 1x1 textures, and the stack may not have the alignment
// that texImage2D expects.
void* zeros = calloc(1, 16);
if (target == LOCAL_GL_TEXTURE_2D) {
gl->fTexImage2D(target, 0, format, 1, 1,
0, format, LOCAL_GL_UNSIGNED_BYTE, zeros);
} else {
for (GLuint i = 0; i < 6; ++i) {
gl->fTexImage2D(LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, 1, 1,
0, format, LOCAL_GL_UNSIGNED_BYTE, zeros);
}
}
free(zeros);
gl->fBindTexture(target, formerBinding);
}
WebGLContext::FakeBlackTexture::~FakeBlackTexture()
{
if (mGL) {
mGL->MakeCurrent();
mGL->fDeleteTextures(1, &mGLName);
}
}
//
// WebGL API
//
@ -834,237 +791,6 @@ WebGLContext::DepthRange(GLfloat zNear, GLfloat zFar)
gl->fDepthRange(zNear, zFar);
}
WebGLVertexAttrib0Status
WebGLContext::WhatDoesVertexAttrib0Need()
{
// here we may assume that mCurrentProgram != null
// work around Mac OSX crash, see bug 631420
#ifdef XP_MACOSX
if (gl->WorkAroundDriverBugs() &&
mBoundVertexArray->IsAttribArrayEnabled(0) &&
!mCurrentProgram->IsAttribInUse(0))
{
return WebGLVertexAttrib0Status::EmulatedUninitializedArray;
}
#endif
return (gl->IsGLES2() || mBoundVertexArray->IsAttribArrayEnabled(0)) ? WebGLVertexAttrib0Status::Default
: mCurrentProgram->IsAttribInUse(0) ? WebGLVertexAttrib0Status::EmulatedInitializedArray
: WebGLVertexAttrib0Status::EmulatedUninitializedArray;
}
bool
WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
{
WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
if (whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default)
return true;
if (!mAlreadyWarnedAboutFakeVertexAttrib0) {
GenerateWarning("Drawing without vertex attrib 0 array enabled forces the browser "
"to do expensive emulation work when running on desktop OpenGL "
"platforms, for example on Mac. It is preferable to always draw "
"with vertex attrib 0 array enabled, by using bindAttribLocation "
"to bind some always-used attribute to location 0.");
mAlreadyWarnedAboutFakeVertexAttrib0 = true;
}
CheckedUint32 checked_dataSize = CheckedUint32(vertexCount) * 4 * sizeof(GLfloat);
if (!checked_dataSize.isValid()) {
ErrorOutOfMemory("Integer overflow trying to construct a fake vertex attrib 0 array for a draw-operation "
"with %d vertices. Try reducing the number of vertices.", vertexCount);
return false;
}
GLuint dataSize = checked_dataSize.value();
if (!mFakeVertexAttrib0BufferObject) {
gl->fGenBuffers(1, &mFakeVertexAttrib0BufferObject);
}
// if the VBO status is already exactly what we need, or if the only difference is that it's initialized and
// we don't need it to be, then consider it OK
bool vertexAttrib0BufferStatusOK =
mFakeVertexAttrib0BufferStatus == whatDoesAttrib0Need ||
(mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray &&
whatDoesAttrib0Need == WebGLVertexAttrib0Status::EmulatedUninitializedArray);
if (!vertexAttrib0BufferStatusOK ||
mFakeVertexAttrib0BufferObjectSize < dataSize ||
mFakeVertexAttrib0BufferObjectVector[0] != mVertexAttrib0Vector[0] ||
mFakeVertexAttrib0BufferObjectVector[1] != mVertexAttrib0Vector[1] ||
mFakeVertexAttrib0BufferObjectVector[2] != mVertexAttrib0Vector[2] ||
mFakeVertexAttrib0BufferObjectVector[3] != mVertexAttrib0Vector[3])
{
mFakeVertexAttrib0BufferStatus = whatDoesAttrib0Need;
mFakeVertexAttrib0BufferObjectSize = dataSize;
mFakeVertexAttrib0BufferObjectVector[0] = mVertexAttrib0Vector[0];
mFakeVertexAttrib0BufferObjectVector[1] = mVertexAttrib0Vector[1];
mFakeVertexAttrib0BufferObjectVector[2] = mVertexAttrib0Vector[2];
mFakeVertexAttrib0BufferObjectVector[3] = mVertexAttrib0Vector[3];
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
GetAndFlushUnderlyingGLErrors();
if (mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray) {
nsAutoArrayPtr<GLfloat> array(new GLfloat[4 * vertexCount]);
for(size_t i = 0; i < vertexCount; ++i) {
array[4 * i + 0] = mVertexAttrib0Vector[0];
array[4 * i + 1] = mVertexAttrib0Vector[1];
array[4 * i + 2] = mVertexAttrib0Vector[2];
array[4 * i + 3] = mVertexAttrib0Vector[3];
}
gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, array, LOCAL_GL_DYNAMIC_DRAW);
} else {
gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, nullptr, LOCAL_GL_DYNAMIC_DRAW);
}
GLenum error = GetAndFlushUnderlyingGLErrors();
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
// note that we do this error checking and early return AFTER having restored the buffer binding above
if (error) {
ErrorOutOfMemory("Ran out of memory trying to construct a fake vertex attrib 0 array for a draw-operation "
"with %d vertices. Try reducing the number of vertices.", vertexCount);
return false;
}
}
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
gl->fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0);
return true;
}
void
WebGLContext::UndoFakeVertexAttrib0()
{
WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
if (whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default)
return;
if (mBoundVertexArray->HasAttrib(0) && mBoundVertexArray->mAttribs[0].buf) {
const WebGLVertexAttribData& attrib0 = mBoundVertexArray->mAttribs[0];
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0.buf->GLName());
gl->fVertexAttribPointer(0,
attrib0.size,
attrib0.type,
attrib0.normalized,
attrib0.stride,
reinterpret_cast<const GLvoid *>(attrib0.byteOffset));
} else {
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
}
WebGLContextFakeBlackStatus
WebGLContext::ResolvedFakeBlackStatus()
{
// handle this case first, it's the generic case
if (MOZ_LIKELY(mFakeBlackStatus == WebGLContextFakeBlackStatus::NotNeeded))
return mFakeBlackStatus;
if (mFakeBlackStatus == WebGLContextFakeBlackStatus::Needed)
return mFakeBlackStatus;
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
if ((mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) ||
(mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded))
{
mFakeBlackStatus = WebGLContextFakeBlackStatus::Needed;
return mFakeBlackStatus;
}
}
// we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
// that means that we do NOT need it.
mFakeBlackStatus = WebGLContextFakeBlackStatus::NotNeeded;
return mFakeBlackStatus;
}
void
WebGLContext::BindFakeBlackTexturesHelper(
GLenum target,
const nsTArray<WebGLRefPtr<WebGLTexture> > & boundTexturesArray,
ScopedDeletePtr<FakeBlackTexture> & opaqueTextureScopedPtr,
ScopedDeletePtr<FakeBlackTexture> & transparentTextureScopedPtr)
{
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
if (!boundTexturesArray[i]) {
continue;
}
WebGLTextureFakeBlackStatus s = boundTexturesArray[i]->ResolvedFakeBlackStatus();
MOZ_ASSERT(s != WebGLTextureFakeBlackStatus::Unknown);
if (MOZ_LIKELY(s == WebGLTextureFakeBlackStatus::NotNeeded)) {
continue;
}
bool alpha = s == WebGLTextureFakeBlackStatus::UninitializedImageData &&
FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().InternalFormat());
ScopedDeletePtr<FakeBlackTexture>&
blackTexturePtr = alpha
? transparentTextureScopedPtr
: opaqueTextureScopedPtr;
if (!blackTexturePtr) {
GLenum format = alpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
blackTexturePtr
= new FakeBlackTexture(gl, target, format);
}
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
gl->fBindTexture(target,
blackTexturePtr->GLName());
}
}
void
WebGLContext::BindFakeBlackTextures()
{
// this is the generic case: try to return early
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
return;
BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_2D,
mBound2DTextures,
mBlackOpaqueTexture2D,
mBlackTransparentTexture2D);
BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_CUBE_MAP,
mBoundCubeMapTextures,
mBlackOpaqueTextureCubeMap,
mBlackTransparentTextureCubeMap);
}
void
WebGLContext::UnbindFakeBlackTextures()
{
// this is the generic case: try to return early
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
return;
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
if (mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBound2DTextures[i]->GLName());
}
if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBoundCubeMapTextures[i]->GLName());
}
}
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
}
void
WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum rbtarget, WebGLRenderbuffer *wrb)
{
@ -2622,14 +2348,14 @@ WebGLContext::RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei
case LOCAL_GL_RGBA4:
case LOCAL_GL_RGB5_A1:
// 16-bit RGBA formats are not supported on desktop GL
if (!gl->IsGLES2()) internalformatForGL = LOCAL_GL_RGBA8;
if (!gl->IsGLES()) internalformatForGL = LOCAL_GL_RGBA8;
break;
case LOCAL_GL_RGB565:
// the RGB565 format is not supported on desktop GL
if (!gl->IsGLES2()) internalformatForGL = LOCAL_GL_RGB8;
if (!gl->IsGLES()) internalformatForGL = LOCAL_GL_RGB8;
break;
case LOCAL_GL_DEPTH_COMPONENT16:
if (!gl->IsGLES2() || gl->IsExtensionSupported(gl::GLContext::OES_depth24))
if (!gl->IsGLES() || gl->IsExtensionSupported(gl::GLContext::OES_depth24))
internalformatForGL = LOCAL_GL_DEPTH_COMPONENT24;
else if (gl->IsExtensionSupported(gl::GLContext::OES_packed_depth_stencil))
internalformatForGL = LOCAL_GL_DEPTH24_STENCIL8;
@ -3230,7 +2956,7 @@ WebGLContext::CompileShader(WebGLShader *shader)
MakeContextCurrent();
ShShaderOutput targetShaderSourceLanguage = gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT;
ShShaderOutput targetShaderSourceLanguage = gl->IsGLES() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT;
bool useShaderSourceTranslation = true;
if (shader->NeedsTranslation() && mShaderValidation) {
@ -3800,7 +3526,7 @@ GLenum WebGLContext::CheckedTexImage2D(GLenum target,
// convert type for half float if not on GLES2
GLenum realType = type;
if (realType == LOCAL_GL_HALF_FLOAT_OES && !gl->IsGLES2()) {
if (realType == LOCAL_GL_HALF_FLOAT_OES && !gl->IsGLES()) {
realType = LOCAL_GL_HALF_FLOAT;
}
@ -3882,7 +3608,7 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
// Handle ES2 and GL differences in floating point internal formats. Note that
// format == internalformat, as checked above and as required by ES.
internalformat = InternalFormatForFormatAndType(format, type, gl->IsGLES2());
internalformat = InternalFormatForFormatAndType(format, type, gl->IsGLES());
// Handle ES2 and GL differences when supporting sRGB internal formats. GL ES
// requires that format == internalformat, but GL will fail in this case.
@ -3890,7 +3616,7 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
// format -> internalformat
// GL_RGB GL_SRGB_EXT
// GL_RGBA GL_SRGB_ALPHA_EXT
if (!gl->IsGLES2()) {
if (!gl->IsGLES()) {
switch (internalformat) {
case LOCAL_GL_SRGB_EXT:
format = LOCAL_GL_RGB;

View File

@ -1631,7 +1631,7 @@ WebGLContext::InitAndValidateGL()
MakeContextCurrent();
// on desktop OpenGL, we always keep vertex attrib 0 array enabled
if (!gl->IsGLES2()) {
if (!gl->IsGLES()) {
gl->fEnableVertexAttribArray(0);
}
@ -1729,7 +1729,7 @@ WebGLContext::InitAndValidateGL()
// Always 1 for GLES2
mMaxFramebufferColorAttachments = 1;
if (!gl->IsGLES2()) {
if (!gl->IsGLES()) {
// gl_PointSize is always available in ES2 GLSL, but has to be
// specifically enabled on desktop GLSL.
gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);

View File

@ -20,9 +20,6 @@
using namespace mozilla;
using namespace dom;
// For a Tegra workaround.
static const int MAX_DRAW_CALLS_SINCE_FLUSH = 100;
void
WebGLContext::VertexAttrib1f(GLuint index, GLfloat x0)
{
@ -38,7 +35,7 @@ WebGLContext::VertexAttrib1f(GLuint index, GLfloat x0)
mVertexAttrib0Vector[1] = 0;
mVertexAttrib0Vector[2] = 0;
mVertexAttrib0Vector[3] = 1;
if (gl->IsGLES2())
if (gl->IsGLES())
gl->fVertexAttrib1f(index, x0);
}
}
@ -58,7 +55,7 @@ WebGLContext::VertexAttrib2f(GLuint index, GLfloat x0, GLfloat x1)
mVertexAttrib0Vector[1] = x1;
mVertexAttrib0Vector[2] = 0;
mVertexAttrib0Vector[3] = 1;
if (gl->IsGLES2())
if (gl->IsGLES())
gl->fVertexAttrib2f(index, x0, x1);
}
}
@ -78,7 +75,7 @@ WebGLContext::VertexAttrib3f(GLuint index, GLfloat x0, GLfloat x1, GLfloat x2)
mVertexAttrib0Vector[1] = x1;
mVertexAttrib0Vector[2] = x2;
mVertexAttrib0Vector[3] = 1;
if (gl->IsGLES2())
if (gl->IsGLES())
gl->fVertexAttrib3f(index, x0, x1, x2);
}
}
@ -99,7 +96,7 @@ WebGLContext::VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1,
mVertexAttrib0Vector[1] = x1;
mVertexAttrib0Vector[2] = x2;
mVertexAttrib0Vector[3] = x3;
if (gl->IsGLES2())
if (gl->IsGLES())
gl->fVertexAttrib4f(index, x0, x1, x2, x3);
}
}
@ -120,7 +117,7 @@ WebGLContext::VertexAttrib1fv_base(GLuint idx, uint32_t arrayLength,
mVertexAttrib0Vector[1] = GLfloat(0);
mVertexAttrib0Vector[2] = GLfloat(0);
mVertexAttrib0Vector[3] = GLfloat(1);
if (gl->IsGLES2())
if (gl->IsGLES())
gl->fVertexAttrib1fv(idx, ptr);
}
}
@ -140,7 +137,7 @@ WebGLContext::VertexAttrib2fv_base(GLuint idx, uint32_t arrayLength,
mVertexAttrib0Vector[1] = ptr[1];
mVertexAttrib0Vector[2] = GLfloat(0);
mVertexAttrib0Vector[3] = GLfloat(1);
if (gl->IsGLES2())
if (gl->IsGLES())
gl->fVertexAttrib2fv(idx, ptr);
}
}
@ -160,7 +157,7 @@ WebGLContext::VertexAttrib3fv_base(GLuint idx, uint32_t arrayLength,
mVertexAttrib0Vector[1] = ptr[1];
mVertexAttrib0Vector[2] = ptr[2];
mVertexAttrib0Vector[3] = GLfloat(1);
if (gl->IsGLES2())
if (gl->IsGLES())
gl->fVertexAttrib3fv(idx, ptr);
}
}
@ -180,7 +177,7 @@ WebGLContext::VertexAttrib4fv_base(GLuint idx, uint32_t arrayLength,
mVertexAttrib0Vector[1] = ptr[1];
mVertexAttrib0Vector[2] = ptr[2];
mVertexAttrib0Vector[3] = ptr[3];
if (gl->IsGLES2())
if (gl->IsGLES())
gl->fVertexAttrib4fv(idx, ptr);
}
}
@ -214,7 +211,7 @@ WebGLContext::DisableVertexAttribArray(GLuint index)
MakeContextCurrent();
InvalidateBufferFetching();
if (index || gl->IsGLES2())
if (index || gl->IsGLES())
gl->fDisableVertexAttribArray(index);
MOZ_ASSERT(mBoundVertexArray->HasAttrib(index)); // should have been validated earlier
@ -426,425 +423,3 @@ WebGLContext::VertexAttribDivisor(GLuint index, GLuint divisor)
gl->fVertexAttribDivisor(index, divisor);
}
bool
WebGLContext::DrawInstanced_check(const char* info)
{
// This restriction was removed in GLES3, so WebGL2 shouldn't have it.
if (!IsWebGL2() &&
IsExtensionEnabled(ANGLE_instanced_arrays) &&
!mBufferFetchingHasPerVertex)
{
/* http://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_instanced_arrays.txt
* If all of the enabled vertex attribute arrays that are bound to active
* generic attributes in the program have a non-zero divisor, the draw
* call should return INVALID_OPERATION.
*
* NB: This also appears to apply to NV_instanced_arrays, though the
* INVALID_OPERATION emission is not explicitly stated.
* ARB_instanced_arrays does not have this restriction.
*/
ErrorInvalidOperation("%s: at least one vertex attribute divisor should be 0", info);
return false;
}
return true;
}
bool WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount, const char* info)
{
if (first < 0 || count < 0) {
ErrorInvalidValue("%s: negative first or count", info);
return false;
}
if (primcount < 0) {
ErrorInvalidValue("%s: negative primcount", info);
return false;
}
if (!ValidateStencilParamsForDrawCall()) {
return false;
}
// If count is 0, there's nothing to do.
if (count == 0 || primcount == 0) {
return false;
}
// If there is no current program, this is silently ignored.
// Any checks below this depend on a program being available.
if (!mCurrentProgram) {
return false;
}
if (!ValidateBufferFetching(info)) {
return false;
}
CheckedInt<GLsizei> checked_firstPlusCount = CheckedInt<GLsizei>(first) + count;
if (!checked_firstPlusCount.isValid()) {
ErrorInvalidOperation("%s: overflow in first+count", info);
return false;
}
if (uint32_t(checked_firstPlusCount.value()) > mMaxFetchedVertices) {
ErrorInvalidOperation("%s: bound vertex attribute buffers do not have sufficient size for given first and count", info);
return false;
}
if (uint32_t(primcount) > mMaxFetchedInstances) {
ErrorInvalidOperation("%s: bound instance attribute buffers do not have sufficient size for given primcount", info);
return false;
}
MakeContextCurrent();
if (mBoundFramebuffer) {
if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
return false;
}
}
if (!DoFakeVertexAttrib0(checked_firstPlusCount.value())) {
return false;
}
BindFakeBlackTextures();
return true;
}
void
WebGLContext::DrawArrays(GLenum mode, GLint first, GLsizei count)
{
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, "drawArrays: mode"))
return;
if (!DrawArrays_check(first, count, 1, "drawArrays"))
return;
SetupContextLossTimer();
gl->fDrawArrays(mode, first, count);
Draw_cleanup();
}
void
WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
{
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, "drawArraysInstanced: mode"))
return;
if (!DrawArrays_check(first, count, primcount, "drawArraysInstanced"))
return;
if (!DrawInstanced_check("drawArraysInstanced"))
return;
SetupContextLossTimer();
gl->fDrawArraysInstanced(mode, first, count, primcount);
Draw_cleanup();
}
bool
WebGLContext::DrawElements_check(GLsizei count, GLenum type,
WebGLintptr byteOffset, GLsizei primcount,
const char* info, GLuint* out_upperBound)
{
if (count < 0 || byteOffset < 0) {
ErrorInvalidValue("%s: negative count or offset", info);
return false;
}
if (primcount < 0) {
ErrorInvalidValue("%s: negative primcount", info);
return false;
}
if (!ValidateStencilParamsForDrawCall()) {
return false;
}
// If count is 0, there's nothing to do.
if (count == 0 || primcount == 0) {
return false;
}
CheckedUint32 checked_byteCount;
GLsizei first = 0;
if (type == LOCAL_GL_UNSIGNED_SHORT) {
checked_byteCount = 2 * CheckedUint32(count);
if (byteOffset % 2 != 0) {
ErrorInvalidOperation("%s: invalid byteOffset for UNSIGNED_SHORT (must be a multiple of 2)", info);
return false;
}
first = byteOffset / 2;
}
else if (type == LOCAL_GL_UNSIGNED_BYTE) {
checked_byteCount = count;
first = byteOffset;
}
else if (type == LOCAL_GL_UNSIGNED_INT && IsExtensionEnabled(OES_element_index_uint)) {
checked_byteCount = 4 * CheckedUint32(count);
if (byteOffset % 4 != 0) {
ErrorInvalidOperation("%s: invalid byteOffset for UNSIGNED_INT (must be a multiple of 4)", info);
return false;
}
first = byteOffset / 4;
}
else {
ErrorInvalidEnum("%s: type must be UNSIGNED_SHORT or UNSIGNED_BYTE", info);
return false;
}
if (!checked_byteCount.isValid()) {
ErrorInvalidValue("%s: overflow in byteCount", info);
return false;
}
// If there is no current program, this is silently ignored.
// Any checks below this depend on a program being available.
if (!mCurrentProgram) {
return false;
}
if (!mBoundVertexArray->mBoundElementArrayBuffer) {
ErrorInvalidOperation("%s: must have element array buffer binding", info);
return false;
}
WebGLBuffer& elemArrayBuffer = *mBoundVertexArray->mBoundElementArrayBuffer;
if (!elemArrayBuffer.ByteLength()) {
ErrorInvalidOperation("%s: bound element array buffer doesn't have any data", info);
return false;
}
CheckedInt<GLsizei> checked_neededByteCount = checked_byteCount.toChecked<GLsizei>() + byteOffset;
if (!checked_neededByteCount.isValid()) {
ErrorInvalidOperation("%s: overflow in byteOffset+byteCount", info);
return false;
}
if (uint32_t(checked_neededByteCount.value()) > elemArrayBuffer.ByteLength()) {
ErrorInvalidOperation("%s: bound element array buffer is too small for given count and offset", info);
return false;
}
if (!ValidateBufferFetching(info))
return false;
if (!mMaxFetchedVertices ||
!elemArrayBuffer.Validate(type, mMaxFetchedVertices - 1, first, count, out_upperBound))
{
ErrorInvalidOperation(
"%s: bound vertex attribute buffers do not have sufficient "
"size for given indices from the bound element array", info);
return false;
}
if (uint32_t(primcount) > mMaxFetchedInstances) {
ErrorInvalidOperation("%s: bound instance attribute buffers do not have sufficient size for given primcount", info);
return false;
}
MakeContextCurrent();
if (mBoundFramebuffer) {
if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
return false;
}
}
if (!DoFakeVertexAttrib0(mMaxFetchedVertices)) {
return false;
}
BindFakeBlackTextures();
return true;
}
void
WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
WebGLintptr byteOffset)
{
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, "drawElements: mode"))
return;
GLuint upperBound = UINT_MAX;
if (!DrawElements_check(count, type, byteOffset, 1, "drawElements",
&upperBound))
{
return;
}
SetupContextLossTimer();
if (gl->IsSupported(gl::GLFeature::draw_range_elements)) {
gl->fDrawRangeElements(mode, 0, upperBound,
count, type, reinterpret_cast<GLvoid*>(byteOffset));
} else {
gl->fDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset));
}
Draw_cleanup();
}
void
WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
WebGLintptr byteOffset, GLsizei primcount)
{
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, "drawElementsInstanced: mode"))
return;
if (!DrawElements_check(count, type, byteOffset, primcount, "drawElementsInstanced"))
return;
if (!DrawInstanced_check("drawElementsInstanced"))
return;
SetupContextLossTimer();
gl->fDrawElementsInstanced(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset), primcount);
Draw_cleanup();
}
void WebGLContext::Draw_cleanup()
{
UndoFakeVertexAttrib0();
UnbindFakeBlackTextures();
if (!mBoundFramebuffer) {
Invalidate();
mShouldPresent = true;
mIsScreenCleared = false;
}
if (gl->WorkAroundDriverBugs()) {
if (gl->Renderer() == gl::GLRenderer::Tegra) {
mDrawCallsSinceLastFlush++;
if (mDrawCallsSinceLastFlush >= MAX_DRAW_CALLS_SINCE_FLUSH) {
gl->fFlush();
mDrawCallsSinceLastFlush = 0;
}
}
}
// Let's check the viewport
const WebGLRectangleObject* rect = CurValidFBRectObject();
if (rect) {
if (mViewportWidth > rect->Width() ||
mViewportHeight > rect->Height())
{
if (!mAlreadyWarnedAboutViewportLargerThanDest) {
GenerateWarning("Drawing to a destination rect smaller than the viewport rect. "
"(This warning will only be given once)");
mAlreadyWarnedAboutViewportLargerThanDest = true;
}
}
}
}
/*
* Verify that state is consistent for drawing, and compute max number of elements (maxAllowedCount)
* that will be legal to be read from bound VBOs.
*/
bool
WebGLContext::ValidateBufferFetching(const char *info)
{
#ifdef DEBUG
GLint currentProgram = 0;
MakeContextCurrent();
gl->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &currentProgram);
MOZ_ASSERT(GLuint(currentProgram) == mCurrentProgram->GLName(),
"WebGL: current program doesn't agree with GL state");
#endif
if (mBufferFetchingIsVerified) {
return true;
}
bool hasPerVertex = false;
uint32_t maxVertices = UINT32_MAX;
uint32_t maxInstances = UINT32_MAX;
uint32_t attribs = mBoundVertexArray->mAttribs.Length();
for (uint32_t i = 0; i < attribs; ++i) {
const WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[i];
// If the attrib array isn't enabled, there's nothing to check;
// it's a static value.
if (!vd.enabled)
continue;
if (vd.buf == nullptr) {
ErrorInvalidOperation("%s: no VBO bound to enabled vertex attrib index %d!", info, i);
return false;
}
// If the attrib is not in use, then we don't have to validate
// it, just need to make sure that the binding is non-null.
if (!mCurrentProgram->IsAttribInUse(i))
continue;
// the base offset
CheckedUint32 checked_byteLength = CheckedUint32(vd.buf->ByteLength()) - vd.byteOffset;
CheckedUint32 checked_sizeOfLastElement = CheckedUint32(vd.componentSize()) * vd.size;
if (!checked_byteLength.isValid() ||
!checked_sizeOfLastElement.isValid())
{
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
return false;
}
if (checked_byteLength.value() < checked_sizeOfLastElement.value()) {
maxVertices = 0;
maxInstances = 0;
break;
}
CheckedUint32 checked_maxAllowedCount = ((checked_byteLength - checked_sizeOfLastElement) / vd.actualStride()) + 1;
if (!checked_maxAllowedCount.isValid()) {
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
return false;
}
if (vd.divisor == 0) {
maxVertices = std::min(maxVertices, checked_maxAllowedCount.value());
hasPerVertex = true;
} else {
maxInstances = std::min(maxInstances, checked_maxAllowedCount.value() / vd.divisor);
}
}
mBufferFetchingIsVerified = true;
mBufferFetchingHasPerVertex = hasPerVertex;
mMaxFetchedVertices = maxVertices;
mMaxFetchedInstances = maxInstances;
return true;
}

View File

@ -890,7 +890,7 @@ FinalizeDrawAndReadBuffers(GLContext* aGL, bool aColorBufferDefined)
//
// Note that this test is not performed if OpenGL 4.2 or ARB_ES2_compatibility is
// available.
if (aGL->IsGLES2() ||
if (aGL->IsGLES() ||
aGL->IsSupported(GLFeature::ES2_compatibility) ||
aGL->IsAtLeast(ContextProfile::OpenGL, 420))
{

View File

@ -16,7 +16,7 @@ using namespace mozilla::gl;
static GLenum
DepthStencilDepthFormat(GLContext* gl) {
// We might not be able to get 24-bit, so let's pretend!
if (gl->IsGLES2() && !gl->IsExtensionSupported(gl::GLContext::OES_depth24))
if (gl->IsGLES() && !gl->IsExtensionSupported(gl::GLContext::OES_depth24))
return LOCAL_GL_DEPTH_COMPONENT16;
return LOCAL_GL_DEPTH_COMPONENT24;

View File

@ -125,7 +125,7 @@ WebGLTexture::Bind(GLenum aTarget) {
// thanks to the WebKit people for finding this out: GL_TEXTURE_WRAP_R is not
// present in GLES 2, but is present in GL and it seems as if for cube maps
// we need to set it to GL_CLAMP_TO_EDGE to get the expected GLES behavior.
if (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP && !mContext->gl->IsGLES2())
if (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP && !mContext->gl->IsGLES())
mContext->gl->fTexParameteri(mTarget, LOCAL_GL_TEXTURE_WRAP_R, LOCAL_GL_CLAMP_TO_EDGE);
}

View File

@ -32,6 +32,7 @@ if CONFIG['MOZ_WEBGL']:
'WebGLContext.cpp',
'WebGLContextAsyncQueries.cpp',
'WebGLContextBuffers.cpp',
'WebGLContextDraw.cpp',
'WebGLContextExtensions.cpp',
'WebGLContextFramebufferOperations.cpp',
'WebGLContextGL.cpp',

View File

@ -7,10 +7,15 @@
#include "MediaInfo.h"
#ifdef MOZ_OMX_DECODER
#include "GrallocImages.h"
#include "mozilla/layers/TextureClient.h"
#endif
#include "VideoUtils.h"
#include "ImageContainer.h"
#ifdef MOZ_WIDGET_GONK
#include <cutils/properties.h>
#endif
namespace mozilla {
using namespace mozilla::gfx;
@ -56,6 +61,15 @@ IsYV12Format(const VideoData::YCbCrBuffer::Plane& aYPlane,
aCbPlane.mWidth == aCrPlane.mWidth &&
aCbPlane.mHeight == aCrPlane.mHeight;
}
static bool
IsInEmulator()
{
char propQemu[PROPERTY_VALUE_MAX];
property_get("ro.kernel.qemu", propQemu, "");
return !strncmp(propQemu, "1", 1);
}
#endif
VideoData::VideoData(int64_t aOffset, int64_t aTime, int64_t aDuration, int64_t aTimecode)
@ -229,7 +243,7 @@ VideoData* VideoData::Create(VideoInfo& aInfo,
// Currently our decoder only knows how to output to ImageFormat::PLANAR_YCBCR
// format.
#ifdef MOZ_WIDGET_GONK
if (IsYV12Format(Y, Cb, Cr)) {
if (IsYV12Format(Y, Cb, Cr) && !IsInEmulator()) {
v->mImage = aContainer->CreateImage(ImageFormat::GRALLOC_PLANAR_YCBCR);
}
#endif
@ -329,7 +343,7 @@ VideoData* VideoData::Create(VideoInfo& aInfo,
int64_t aOffset,
int64_t aTime,
int64_t aDuration,
mozilla::layers::GraphicBufferLocked* aBuffer,
mozilla::layers::TextureClient* aBuffer,
bool aKeyframe,
int64_t aTimecode,
const IntRect& aPicture)

View File

@ -101,7 +101,7 @@ public:
};
namespace layers {
class GraphicBufferLocked;
class TextureClient;
class PlanarYCbCrImage;
}
@ -179,7 +179,7 @@ public:
int64_t aOffset,
int64_t aTime,
int64_t aDuration,
layers::GraphicBufferLocked* aBuffer,
layers::TextureClient* aBuffer,
bool aKeyframe,
int64_t aTimecode,
const IntRect& aPicture);

View File

@ -1505,7 +1505,10 @@ MediaDecoderStateMachine::EnsureActive()
return;
}
mIsReaderIdle = false;
SetReaderActive();
{
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
SetReaderActive();
}
}
void

View File

@ -7,7 +7,7 @@
#define MPAPI_h_
#include <stdint.h>
#include "GrallocImages.h"
#include "mozilla/layers/TextureClient.h"
namespace MPAPI {
@ -41,7 +41,7 @@ struct VideoFrame {
VideoPlane Y;
VideoPlane Cb;
VideoPlane Cr;
nsRefPtr<mozilla::layers::GraphicBufferLocked> mGraphicBuffer;
mozilla::RefPtr<mozilla::layers::TextureClient> mGraphicBuffer;
VideoFrame() :
mTimeUs(0),

View File

@ -19,6 +19,8 @@
#include <ui/Fence.h>
#endif
#include "mozilla/layers/GrallocTextureClient.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/Preferences.h"
#include "mozilla/Types.h"
#include "mozilla/Monitor.h"
@ -42,6 +44,7 @@ PRLogModuleInfo *gOmxDecoderLog;
using namespace MPAPI;
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::layers;
namespace mozilla {
@ -190,43 +193,6 @@ private:
bool mCompleted;
};
namespace layers {
VideoGraphicBuffer::VideoGraphicBuffer(const android::wp<android::OmxDecoder> aOmxDecoder,
android::MediaBuffer *aBuffer,
SurfaceDescriptor& aDescriptor)
: GraphicBufferLocked(aDescriptor),
mMediaBuffer(aBuffer),
mOmxDecoder(aOmxDecoder)
{
mMediaBuffer->add_ref();
}
VideoGraphicBuffer::~VideoGraphicBuffer()
{
MOZ_ASSERT(!mMediaBuffer);
}
void
VideoGraphicBuffer::Unlock()
{
android::sp<android::OmxDecoder> omxDecoder = mOmxDecoder.promote();
if (omxDecoder.get()) {
// Post kNotifyPostReleaseVideoBuffer message to OmxDecoder via ALooper.
// The message is delivered to OmxDecoder on ALooper thread.
// MediaBuffer::release() could take a very long time.
// PostReleaseVideoBuffer() prevents long time locking.
omxDecoder->PostReleaseVideoBuffer(mMediaBuffer, mReleaseFenceHandle);
} else {
NS_WARNING("OmxDecoder is not present");
if (mMediaBuffer) {
mMediaBuffer->release();
}
}
mMediaBuffer = nullptr;
}
}
}
namespace android {
@ -837,20 +803,21 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
unreadable = 0;
}
mozilla::layers::SurfaceDescriptor *descriptor = nullptr;
RefPtr<mozilla::layers::TextureClient> textureClient;
if ((mVideoBuffer->graphicBuffer().get())) {
descriptor = mNativeWindow->getSurfaceDescriptorFromBuffer(mVideoBuffer->graphicBuffer().get());
textureClient = mNativeWindow->getTextureClientFromBuffer(mVideoBuffer->graphicBuffer().get());
}
if (descriptor) {
// Change the descriptor's size to video's size. There are cases that
// GraphicBuffer's size and actual video size is different.
// See Bug 850566.
mozilla::layers::SurfaceDescriptorGralloc newDescriptor = descriptor->get_SurfaceDescriptorGralloc();
newDescriptor.size() = IntSize(mVideoWidth, mVideoHeight);
if (textureClient) {
// Manually increment reference count to keep MediaBuffer alive
// during TextureClient is in use.
mVideoBuffer->add_ref();
GrallocTextureClientOGL* grallocClient = static_cast<GrallocTextureClientOGL*>(textureClient.get());
grallocClient->SetMediaBuffer(mVideoBuffer);
// Set recycle callback for TextureClient
textureClient->SetRecycleCallback(OmxDecoder::RecycleCallback, this);
mozilla::layers::SurfaceDescriptor descWrapper(newDescriptor);
aFrame->mGraphicBuffer = new mozilla::layers::VideoGraphicBuffer(this, mVideoBuffer, descWrapper);
aFrame->mGraphicBuffer = textureClient;
aFrame->mRotation = mVideoRotation;
aFrame->mTimeUs = timeUs;
aFrame->mKeyFrame = keyFrame;
@ -1099,6 +1066,16 @@ void OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
releasingVideoBuffers.clear();
}
/* static */ void
OmxDecoder::RecycleCallback(TextureClient* aClient, void* aClosure)
{
OmxDecoder* decoder = static_cast<OmxDecoder*>(aClosure);
GrallocTextureClientOGL* client = static_cast<GrallocTextureClientOGL*>(aClient);
aClient->ClearRecycleCallback();
decoder->PostReleaseVideoBuffer(client->GetMediaBuffer(), client->GetReleaseFenceHandle());
}
int64_t OmxDecoder::ProcessCachedData(int64_t aOffset, bool aWaitForCompletion)
{
// We read data in chunks of 32 KiB. We can reduce this

View File

@ -9,7 +9,6 @@
#include "GonkNativeWindow.h"
#include "GonkNativeWindowClient.h"
#include "GrallocImages.h"
#include "mozilla/layers/FenceUtils.h"
#include "MP3FrameParser.h"
#include "MPAPI.h"
@ -21,26 +20,6 @@ namespace android {
class OmxDecoder;
};
namespace mozilla {
namespace layers {
class VideoGraphicBuffer : public GraphicBufferLocked {
// XXX change this to an actual smart pointer at some point
android::MediaBuffer *mMediaBuffer;
android::wp<android::OmxDecoder> mOmxDecoder;
public:
VideoGraphicBuffer(const android::wp<android::OmxDecoder> aOmxDecoder,
android::MediaBuffer *aBuffer,
SurfaceDescriptor& aDescriptor);
~VideoGraphicBuffer();
protected:
void Unlock();
};
}
}
namespace android {
// MediaStreamSource is a DataSource that reads from a MPAPI media stream.
@ -85,6 +64,7 @@ class OmxDecoder : public OMXCodecProxy::EventListener {
typedef mozilla::MediaResource MediaResource;
typedef mozilla::AbstractMediaDecoder AbstractMediaDecoder;
typedef mozilla::layers::FenceHandle FenceHandle;
typedef mozilla::layers::TextureClient TextureClient;
enum {
kPreferSoftwareCodecs = 1,
@ -263,6 +243,8 @@ public:
void onMessageReceived(const sp<AMessage> &msg);
int64_t ProcessCachedData(int64_t aOffset, bool aWaitForCompletion);
static void RecycleCallback(TextureClient* aClient, void* aClosure);
};
}

View File

@ -312,6 +312,9 @@ RtspOmxReader::ReadMetadata(MediaInfo* aInfo,
}
void RtspOmxReader::SetIdle() {
// Call parent class to set OMXCodec idle.
MediaOmxReader::SetIdle();
// Need to pause RTSP streaming OMXCodec decoding.
if (mRtspResource) {
nsIStreamingProtocolController* controller =
@ -320,9 +323,6 @@ void RtspOmxReader::SetIdle() {
controller->Pause();
}
}
// Call parent class to set OMXCodec idle.
MediaOmxReader::SetIdle();
}
void RtspOmxReader::SetActive() {

View File

@ -669,6 +669,22 @@ CouldBeDOMBinding(nsWrapperCache* aCache)
return aCache->IsDOMBinding();
}
inline bool
TryToOuterize(JSContext* cx, JS::MutableHandle<JS::Value> rval)
{
if (js::IsInnerObject(&rval.toObject())) {
JS::Rooted<JSObject*> obj(cx, &rval.toObject());
obj = JS_ObjectToOuterObject(cx, obj);
if (!obj) {
return false;
}
rval.set(JS::ObjectValue(*obj));
}
return true;
}
// Make sure to wrap the given string value into the right compartment, as
// needed.
MOZ_ALWAYS_INLINE
@ -697,10 +713,10 @@ MaybeWrapObjectValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
return JS_WrapValue(cx, rval);
}
// We're same-compartment. If we're a WebIDL object, we're done.
// We're same-compartment, but even then we might need to wrap
// objects specially. Check for that.
if (IsDOMObject(obj)) {
rval.set(JS::ObjectValue(*obj));
return true;
return TryToOuterize(cx, rval);
}
// It's not a WebIDL object. But it might be an XPConnect one, in which case
@ -821,14 +837,17 @@ WrapNewBindingObject(JSContext* cx, JS::Handle<JSObject*> scope, T* value,
MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
#endif
rval.set(JS::ObjectValue(*obj));
bool sameCompartment =
js::GetObjectCompartment(obj) == js::GetContextCompartment(cx);
if (sameCompartment && couldBeDOMBinding) {
rval.set(JS::ObjectValue(*obj));
return true;
// We only need to outerize Window objects, so anything inheriting from
// nsGlobalWindow (which inherits from EventTarget itself).
return IsBaseOf<nsGlobalWindow, T>::value || IsSame<EventTarget, T>::value ?
TryToOuterize(cx, rval) : true;
}
rval.set(JS::ObjectValue(*obj));
return JS_WrapValue(cx, rval);
}

View File

@ -1365,14 +1365,14 @@ nsGonkCameraControl::GetRecorderProfileManagerImpl()
}
void
nsGonkCameraControl::OnNewPreviewFrame(layers::GraphicBufferLocked* aBuffer)
nsGonkCameraControl::OnNewPreviewFrame(layers::TextureClient* aBuffer)
{
nsRefPtr<Image> frame = mImageContainer->CreateImage(ImageFormat::GRALLOC_PLANAR_YCBCR);
GrallocImage* videoImage = static_cast<GrallocImage*>(frame.get());
GrallocImage::GrallocData data;
data.mGraphicBuffer = static_cast<layers::GraphicBufferLocked*>(aBuffer);
data.mGraphicBuffer = aBuffer;
data.mPicSize = IntSize(mCurrentConfiguration.mPreviewSize.width,
mCurrentConfiguration.mPreviewSize.height);
videoImage->SetData(data);
@ -1415,7 +1415,7 @@ OnAutoFocusComplete(nsGonkCameraControl* gc, bool aSuccess)
}
void
OnNewPreviewFrame(nsGonkCameraControl* gc, layers::GraphicBufferLocked* aBuffer)
OnNewPreviewFrame(nsGonkCameraControl* gc, layers::TextureClient* aBuffer)
{
gc->OnNewPreviewFrame(aBuffer);
}

View File

@ -36,7 +36,7 @@ namespace android {
namespace mozilla {
namespace layers {
class GraphicBufferLocked;
class TextureClient;
class ImageContainer;
}
@ -51,7 +51,7 @@ public:
void OnAutoFocusComplete(bool aSuccess);
void OnTakePictureComplete(uint8_t* aData, uint32_t aLength);
void OnTakePictureError();
void OnNewPreviewFrame(layers::GraphicBufferLocked* aBuffer);
void OnNewPreviewFrame(layers::TextureClient* aBuffer);
void OnRecorderEvent(int msg, int ext1, int ext2);
void OnError(CameraControlListener::CameraErrorContext aWhere,
CameraControlListener::CameraError aError);
@ -163,7 +163,7 @@ private:
void OnTakePictureComplete(nsGonkCameraControl* gc, uint8_t* aData, uint32_t aLength);
void OnTakePictureError(nsGonkCameraControl* gc);
void OnAutoFocusComplete(nsGonkCameraControl* gc, bool aSuccess);
void OnNewPreviewFrame(nsGonkCameraControl* gc, layers::GraphicBufferLocked* aBuffer);
void OnNewPreviewFrame(nsGonkCameraControl* gc, layers::TextureClient* aBuffer);
void OnShutter(nsGonkCameraControl* gc);
void OnClosed(nsGonkCameraControl* gc);
void OnError(nsGonkCameraControl* gc, CameraControlListener::CameraError aError,

View File

@ -22,7 +22,9 @@
#include "base/basictypes.h"
#include "nsDebug.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/Preferences.h"
#include "mozilla/RefPtr.h"
#include "GonkCameraControl.h"
#include "GonkNativeWindow.h"
#include "CameraCommon.h"
@ -48,7 +50,7 @@ GonkCameraHardware::OnNewFrame()
if (mClosing) {
return;
}
nsRefPtr<GraphicBufferLocked> buffer = mNativeWindow->getCurrentBuffer();
RefPtr<TextureClient> buffer = mNativeWindow->getCurrentBuffer();
if (!buffer) {
DOM_CAMERA_LOGW("received null frame");
return;

View File

@ -14,18 +14,19 @@ Cu.import("resource://gre/modules/ContactService.jsm", imports);
Cu.import("resource://gre/modules/Promise.jsm", imports);
Cu.importGlobalProperties(["indexedDB"]);
// |const| will not work because
// it will make the Promise object immutable before assigning.
// Using |let| and Object.freeze() instead.
let {
const {
STORE_NAME,
SAVED_GETALL_STORE_NAME,
REVISION_STORE,
DB_NAME,
ContactService,
Promise
} = imports;
Object.freeze(imports);
// |const| will not work because
// it will make the Promise object immutable before assigning.
// Using Object.defineProperty() instead.
Object.defineProperty(this, "Promise", {
value: imports.Promise, writable: false, configurable: false
});
let DEBUG = false;
function debug(str) {

View File

@ -28,7 +28,8 @@ XPCOMUtils.defineLazyServiceGetter(this, "powerManagerService",
// Limit the number of pending messages for a given page.
let kMaxPendingMessages;
try {
kMaxPendingMessages = Services.prefs.getIntPref("dom.messages.maxPendingMessages");
kMaxPendingMessages =
Services.prefs.getIntPref("dom.messages.maxPendingMessages");
} catch(e) {
// getIntPref throws when the pref is not set.
kMaxPendingMessages = 5;
@ -66,7 +67,7 @@ function SystemMessageInternal() {
this._pages = [];
// The set of listeners. This is a multi-dimensional object. The _listeners
// object itself is a map from manifest ID -> an array mapping proccesses to
// object itself is a map from manifest URL -> an array mapping proccesses to
// windows. We do this so that we can track both what processes we have to
// send system messages to as well as supporting the single-process case
// where we track windows instead.
@ -91,10 +92,11 @@ function SystemMessageInternal() {
SystemMessageInternal.prototype = {
_getMessageConfigurator: function _getMessageConfigurator(aType) {
_getMessageConfigurator: function(aType) {
debug("_getMessageConfigurator for type: " + aType);
if (this._configurators[aType] === undefined) {
let contractID = "@mozilla.org/dom/system-messages/configurator/" + aType + ";1";
let contractID =
"@mozilla.org/dom/system-messages/configurator/" + aType + ";1";
if (contractID in Cc) {
debug(contractID + " is registered, creating an instance");
this._configurators[aType] =
@ -107,7 +109,7 @@ SystemMessageInternal.prototype = {
return this._configurators[aType] || defaultMessageConfigurator;
},
_cancelCpuWakeLock: function _cancelCpuWakeLock(aPageKey) {
_cancelCpuWakeLock: function(aPageKey) {
let cpuWakeLock = this._cpuWakeLocks[aPageKey];
if (cpuWakeLock) {
debug("Releasing the CPU wake lock for page key = " + aPageKey);
@ -117,7 +119,7 @@ SystemMessageInternal.prototype = {
}
},
_acquireCpuWakeLock: function _acquireCpuWakeLock(aPageKey) {
_acquireCpuWakeLock: function(aPageKey) {
let cpuWakeLock = this._cpuWakeLocks[aPageKey];
if (!cpuWakeLock) {
// We have to ensure the CPU doesn't sleep during the process of the page
@ -157,7 +159,7 @@ SystemMessageInternal.prototype = {
}
},
_findPage: function _findPage(aType, aPageURL, aManifestURL) {
_findPage: function(aType, aPageURL, aManifestURL) {
let page = null;
this._pages.some(function(aPage) {
if (this._isPageMatched(aPage, aType, aPageURL, aManifestURL)) {
@ -168,7 +170,7 @@ SystemMessageInternal.prototype = {
return page;
},
sendMessage: function sendMessage(aType, aMessage, aPageURI, aManifestURI, aExtra) {
sendMessage: function(aType, aMessage, aPageURI, aManifestURI, aExtra) {
// Buffer system messages until the webapps' registration is ready,
// so that we can know the correct pages registered to be sent.
if (!this._webappsRegistryReady) {
@ -212,7 +214,7 @@ SystemMessageInternal.prototype = {
}
},
broadcastMessage: function broadcastMessage(aType, aMessage, aExtra) {
broadcastMessage: function(aType, aMessage, aExtra) {
// Buffer system messages until the webapps' registration is ready,
// so that we can know the correct pages registered to be broadcasted.
if (!this._webappsRegistryReady) {
@ -235,8 +237,8 @@ SystemMessageInternal.prototype = {
let result = this._sendMessageCommon(aType,
aMessage,
messageID,
aPage.uri,
aPage.manifest,
aPage.pageURL,
aPage.manifestURL,
aExtra);
debug("Returned status of sending message: " + result);
@ -255,7 +257,7 @@ SystemMessageInternal.prototype = {
}, this);
},
registerPage: function registerPage(aType, aPageURI, aManifestURI) {
registerPage: function(aType, aPageURI, aManifestURI) {
if (!aPageURI || !aManifestURI) {
throw Cr.NS_ERROR_INVALID_ARG;
}
@ -272,12 +274,12 @@ SystemMessageInternal.prototype = {
}
this._pages.push({ type: aType,
uri: pageURL,
manifest: manifestURL,
pageURL: pageURL,
manifestURL: manifestURL,
pendingMessages: [] });
},
_findTargetIndex: function _findTargetIndex(aTargets, aTarget) {
_findTargetIndex: function(aTargets, aTarget) {
if (!aTargets || !aTarget) {
return -1;
}
@ -290,18 +292,18 @@ SystemMessageInternal.prototype = {
return -1;
},
_isEmptyObject: function _isEmptyObject(aObj) {
_isEmptyObject: function(aObj) {
for (let name in aObj) {
return false;
}
return true;
},
_removeTargetFromListener: function _removeTargetFromListener(aTarget,
aManifest,
aRemoveListener,
aUri) {
let targets = this._listeners[aManifest];
_removeTargetFromListener: function(aTarget,
aManifestURL,
aRemoveListener,
aPageURL) {
let targets = this._listeners[aManifestURL];
if (!targets) {
return false;
}
@ -312,22 +314,22 @@ SystemMessageInternal.prototype = {
}
if (aRemoveListener) {
debug("remove the listener for " + aManifest);
delete this._listeners[aManifest];
debug("remove the listener for " + aManifestURL);
delete this._listeners[aManifestURL];
return true;
}
let target = targets[index];
if (aUri && target.winCounts[aUri] !== undefined &&
--target.winCounts[aUri] === 0) {
delete target.winCounts[aUri];
if (aPageURL && target.winCounts[aPageURL] !== undefined &&
--target.winCounts[aPageURL] === 0) {
delete target.winCounts[aPageURL];
}
if (this._isEmptyObject(target.winCounts)) {
if (targets.length === 1) {
// If it's the only one, get rid of this manifest entirely.
debug("remove the listener for " + aManifest);
delete this._listeners[aManifest];
// If it's the only one, get rid of the entry of manifest URL entirely.
debug("remove the listener for " + aManifestURL);
delete this._listeners[aManifestURL];
} else {
// If more than one left, remove this one and leave the rest.
targets.splice(index, 1);
@ -336,7 +338,7 @@ SystemMessageInternal.prototype = {
return true;
},
receiveMessage: function receiveMessage(aMessage) {
receiveMessage: function(aMessage) {
let msg = aMessage.json;
// To prevent the hacked child process from sending commands to parent
@ -348,7 +350,7 @@ SystemMessageInternal.prototype = {
"SystemMessageManager:HasPendingMessages",
"SystemMessageManager:Message:Return:OK",
"SystemMessageManager:HandleMessagesDone"].indexOf(aMessage.name) != -1) {
if (!aMessage.target.assertContainApp(msg.manifest)) {
if (!aMessage.target.assertContainApp(msg.manifestURL)) {
debug("Got message from a child process containing illegal manifest URL.");
return null;
}
@ -360,37 +362,42 @@ SystemMessageInternal.prototype = {
break;
case "SystemMessageManager:Register":
{
debug("Got Register from " + msg.uri + " @ " + msg.manifest);
let uri = msg.uri;
debug("Got Register from " + msg.pageURL + " @ " + msg.manifestURL);
let pageURL = msg.pageURL;
let targets, index;
if (!(targets = this._listeners[msg.manifest])) {
if (!(targets = this._listeners[msg.manifestURL])) {
let winCounts = {};
winCounts[uri] = 1;
this._listeners[msg.manifest] = [{ target: aMessage.target,
winCounts: winCounts }];
} else if ((index = this._findTargetIndex(targets, aMessage.target)) === -1) {
winCounts[pageURL] = 1;
this._listeners[msg.manifestURL] = [{ target: aMessage.target,
winCounts: winCounts }];
} else if ((index = this._findTargetIndex(targets,
aMessage.target)) === -1) {
let winCounts = {};
winCounts[uri] = 1;
winCounts[pageURL] = 1;
targets.push({ target: aMessage.target,
winCounts: winCounts });
} else {
let winCounts = targets[index].winCounts;
if (winCounts[uri] === undefined) {
winCounts[uri] = 1;
if (winCounts[pageURL] === undefined) {
winCounts[pageURL] = 1;
} else {
winCounts[uri]++;
winCounts[pageURL]++;
}
}
debug("listeners for " + msg.manifest + " innerWinID " + msg.innerWindowID);
debug("listeners for " + msg.manifestURL +
" innerWinID " + msg.innerWindowID);
break;
}
case "child-process-shutdown":
{
debug("Got child-process-shutdown from " + aMessage.target);
for (let manifest in this._listeners) {
// See if any processes in this manifest have this target.
if (this._removeTargetFromListener(aMessage.target, manifest, true, null)) {
for (let manifestURL in this._listeners) {
// See if any processes in this manifest URL have this target.
if (this._removeTargetFromListener(aMessage.target,
manifestURL,
true,
null)) {
break;
}
}
@ -398,18 +405,22 @@ SystemMessageInternal.prototype = {
}
case "SystemMessageManager:Unregister":
{
debug("Got Unregister from " + aMessage.target + "innerWinID " + msg.innerWindowID);
this._removeTargetFromListener(aMessage.target, msg.manifest, false, msg.uri);
debug("Got Unregister from " + aMessage.target +
" innerWinID " + msg.innerWindowID);
this._removeTargetFromListener(aMessage.target,
msg.manifestURL,
false,
msg.pageURL);
break;
}
case "SystemMessageManager:GetPendingMessages":
{
debug("received SystemMessageManager:GetPendingMessages " + msg.type +
" for " + msg.uri + " @ " + msg.manifest);
" for " + msg.pageURL + " @ " + msg.manifestURL);
// This is a sync call used to return the pending messages for a page.
// Find the right page to get its corresponding pending messages.
let page = this._findPage(msg.type, msg.uri, msg.manifest);
let page = this._findPage(msg.type, msg.pageURL, msg.manifestURL);
if (!page) {
return;
}
@ -428,19 +439,19 @@ SystemMessageInternal.prototype = {
aMessage.target
.sendAsyncMessage("SystemMessageManager:GetPendingMessages:Return",
{ type: msg.type,
manifest: msg.manifest,
uri: msg.uri,
manifestURL: msg.manifestURL,
pageURL: msg.pageURL,
msgQueue: pendingMessages });
break;
}
case "SystemMessageManager:HasPendingMessages":
{
debug("received SystemMessageManager:HasPendingMessages " + msg.type +
" for " + msg.uri + " @ " + msg.manifest);
" for " + msg.pageURL + " @ " + msg.manifestURL);
// This is a sync call used to return if a page has pending messages.
// Find the right page to get its corresponding pending messages.
let page = this._findPage(msg.type, msg.uri, msg.manifest);
let page = this._findPage(msg.type, msg.pageURL, msg.manifestURL);
if (!page) {
return false;
}
@ -451,11 +462,11 @@ SystemMessageInternal.prototype = {
case "SystemMessageManager:Message:Return:OK":
{
debug("received SystemMessageManager:Message:Return:OK " + msg.type +
" for " + msg.uri + " @ " + msg.manifest);
" for " + msg.pageURL + " @ " + msg.manifestURL);
// We need to clean up the pending message since the app has already
// received it, thus avoiding the re-lanunched app handling it again.
let page = this._findPage(msg.type, msg.uri, msg.manifest);
let page = this._findPage(msg.type, msg.pageURL, msg.manifestURL);
if (page) {
let pendingMessages = page.pendingMessages;
for (let i = 0; i < pendingMessages.length; i++) {
@ -470,7 +481,8 @@ SystemMessageInternal.prototype = {
case "SystemMessageManager:HandleMessagesDone":
{
debug("received SystemMessageManager:HandleMessagesDone " + msg.type +
" with " + msg.handledCount + " for " + msg.uri + " @ " + msg.manifest);
" with " + msg.handledCount + " for " + msg.pageURL +
" @ " + msg.manifestURL);
// A page has finished handling some of its system messages, so we try
// to release the CPU wake lock we acquired on behalf of that page.
@ -480,7 +492,7 @@ SystemMessageInternal.prototype = {
}
},
observe: function observe(aSubject, aTopic, aData) {
observe: function(aSubject, aTopic, aData) {
switch (aTopic) {
case "xpcom-shutdown":
kMessages.forEach(function(aMsg) {
@ -504,7 +516,8 @@ SystemMessageInternal.prototype = {
switch (aSysMsg.how) {
case "send":
this.sendMessage(
aSysMsg.type, aSysMsg.msg, aSysMsg.pageURI, aSysMsg.manifestURI, aSysMsg.extra);
aSysMsg.type, aSysMsg.msg,
aSysMsg.pageURI, aSysMsg.manifestURI, aSysMsg.extra);
break;
case "broadcast":
this.broadcastMessage(aSysMsg.type, aSysMsg.msg, aSysMsg.extra);
@ -516,7 +529,7 @@ SystemMessageInternal.prototype = {
}
},
_queueMessage: function _queueMessage(aPage, aMessage, aMessageID) {
_queueMessage: function(aPage, aMessage, aMessageID) {
// Queue the message for this page because we've never known if an app is
// opened or not. We'll clean it up when the app has already received it.
aPage.pendingMessages.push({ msg: aMessage, msgID: aMessageID });
@ -525,7 +538,7 @@ SystemMessageInternal.prototype = {
}
},
_openAppPage: function _openAppPage(aPage, aMessage, aExtra, aMsgSentStatus) {
_openAppPage: function(aPage, aMessage, aExtra, aMsgSentStatus) {
// This means the app must be brought to the foreground.
let showApp = this._getMessageConfigurator(aPage.type).mustShowRunningApp;
@ -540,21 +553,23 @@ SystemMessageInternal.prototype = {
let onlyShowApp = (aMsgSentStatus === MSG_SENT_SUCCESS) && showApp;
// We don't need to send the full object to observers.
let page = { uri: aPage.uri,
manifest: aPage.manifest,
let page = { pageURL: aPage.pageURL,
manifestURL: aPage.manifestURL,
type: aPage.type,
extra: aExtra,
target: aMessage.target,
onlyShowApp: onlyShowApp,
showApp: showApp };
debug("Asking to open " + JSON.stringify(page));
Services.obs.notifyObservers(this, "system-messages-open-app", JSON.stringify(page));
Services.obs.notifyObservers(this,
"system-messages-open-app",
JSON.stringify(page));
},
_isPageMatched: function _isPageMatched(aPage, aType, aPageURI, aManifestURI) {
_isPageMatched: function(aPage, aType, aPageURL, aManifestURL) {
return (aPage.type === aType &&
aPage.manifest === aManifestURI &&
aPage.uri === aPageURI)
aPage.manifestURL === aManifestURL &&
aPage.pageURL === aPageURL)
},
_createKeyForPage: function _createKeyForPage(aPage) {
@ -566,8 +581,8 @@ SystemMessageInternal.prototype = {
.createInstance(Ci.nsICryptoHash);
hasher.init(hasher.SHA1);
// add uri and action to the hash
["type", "manifest", "uri"].forEach(function(aProp) {
// add manifest/page URL and action to the hash
["type", "manifestURL", "pageURL"].forEach(function(aProp) {
let data = converter.convertToByteArray(aPage[aProp], {});
hasher.update(data, data.length);
});
@ -575,29 +590,29 @@ SystemMessageInternal.prototype = {
return hasher.finish(true);
},
_sendMessageCommon:
function _sendMessageCommon(aType, aMessage, aMessageID, aPageURI, aManifestURI, aExtra) {
_sendMessageCommon: function(aType, aMessage, aMessageID,
aPageURL, aManifestURL, aExtra) {
// Don't send the system message not granted by the app's permissions.
if (!SystemMessagePermissionsChecker
.isSystemMessagePermittedToSend(aType,
aPageURI,
aManifestURI)) {
aPageURL,
aManifestURL)) {
return MSG_SENT_FAILURE_PERM_DENIED;
}
let appPageIsRunning = false;
let pageKey = this._createKeyForPage({ type: aType,
manifest: aManifestURI,
uri: aPageURI });
manifestURL: aManifestURL,
pageURL: aPageURL });
let targets = this._listeners[aManifestURI];
let targets = this._listeners[aManifestURL];
if (targets) {
for (let index = 0; index < targets.length; ++index) {
let target = targets[index];
// We only need to send the system message to the targets (processes)
// which contain the window page that matches the manifest/page URL of
// the destination of system message.
if (target.winCounts[aPageURI] === undefined) {
if (target.winCounts[aPageURL] === undefined) {
continue;
}
@ -615,8 +630,8 @@ SystemMessageInternal.prototype = {
manager.sendAsyncMessage("SystemMessageManager:Message",
{ type: aType,
msg: aMessage,
manifest: aManifestURI,
uri: aPageURI,
manifestURL: aManifestURL,
pageURL: aPageURL,
msgID: aMessageID });
}
}
@ -637,7 +652,8 @@ SystemMessageInternal.prototype = {
classID: Components.ID("{70589ca5-91ac-4b9e-b839-d6a88167d714}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessagesInternal, Ci.nsIObserver])
QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessagesInternal,
Ci.nsIObserver])
}
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SystemMessageInternal]);

View File

@ -39,8 +39,8 @@ function SystemMessageManager() {
// Pending messages for this page, keyed by message type.
this._pendings = {};
// Flag to specify if this process has already registered manifest.
this._registerManifestReady = false;
// Flag to specify if this process has already registered the manifest URL.
this._registerManifestURLReady = false;
// Flag to determine this process is a parent or child process.
let appInfo = Cc["@mozilla.org/xre/app-info;1"];
@ -57,7 +57,7 @@ function SystemMessageManager() {
SystemMessageManager.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
_dispatchMessage: function sysMessMgr_dispatchMessage(aType, aDispatcher, aMessage) {
_dispatchMessage: function(aType, aDispatcher, aMessage) {
if (aDispatcher.isHandling) {
// Queue up the incomming message if we're currently dispatching a
// message; we'll send the message once we finish with the current one.
@ -73,8 +73,7 @@ SystemMessageManager.prototype = {
aDispatcher.isHandling = true;
// We get a json blob, but in some cases we want another kind of object
// to be dispatched.
// To do so, we check if we have a with a contract ID of
// to be dispatched. To do so, we check if we have a valid contract ID of
// "@mozilla.org/dom/system-messages/wrapper/TYPE;1" component implementing
// nsISystemMessageWrapper.
debug("Dispatching " + JSON.stringify(aMessage) + "\n");
@ -99,17 +98,27 @@ SystemMessageManager.prototype = {
// so the parent can release the CPU wake lock it took on our behalf.
cpmm.sendAsyncMessage("SystemMessageManager:HandleMessagesDone",
{ type: aType,
manifest: this._manifest,
uri: this._uri,
manifestURL: this._manifestURL,
pageURL: this._pageURL,
handledCount: 1 });
aDispatcher.isHandling = false;
if (aDispatcher.messages.length > 0) {
this._dispatchMessage(aType, aDispatcher, aDispatcher.messages.shift());
} else {
// No more messages that need to be handled, we can notify the
// ContentChild to release the CPU wake lock grabbed by the ContentParent
// (i.e. NewWakeLockOnBehalfOfProcess()) and reset the process's priority.
//
// TODO: Bug 874353 - Remove SystemMessageHandledListener in ContentParent
Services.obs.notifyObservers(/* aSubject */ null,
"handle-system-messages-done",
/* aData */ null);
}
},
mozSetMessageHandler: function sysMessMgr_setMessageHandler(aType, aHandler) {
mozSetMessageHandler: function(aType, aHandler) {
debug("set message handler for [" + aType + "] " + aHandler);
if (this._isInBrowserElement) {
@ -137,11 +146,11 @@ SystemMessageManager.prototype = {
// Ask for the list of currently pending messages.
cpmm.sendAsyncMessage("SystemMessageManager:GetPendingMessages",
{ type: aType,
uri: this._uri,
manifest: this._manifest });
pageURL: this._pageURL,
manifestURL: this._manifestURL });
},
mozHasPendingMessage: function sysMessMgr_hasPendingMessage(aType) {
mozHasPendingMessage: function(aType) {
debug("asking pending message for [" + aType + "]");
if (this._isInBrowserElement) {
@ -157,11 +166,11 @@ SystemMessageManager.prototype = {
return cpmm.sendSyncMessage("SystemMessageManager:HasPendingMessages",
{ type: aType,
uri: this._uri,
manifest: this._manifest })[0];
pageURL: this._pageURL,
manifestURL: this._manifestURL })[0];
},
uninit: function sysMessMgr_uninit() {
uninit: function() {
this._dispatchers = null;
this._pendings = null;
@ -171,13 +180,13 @@ SystemMessageManager.prototype = {
if (this._isInBrowserElement) {
debug("the app loaded in the browser doesn't need to unregister " +
"the manifest for listening to the system messages");
"the manifest URL for listening to the system messages");
return;
}
cpmm.sendAsyncMessage("SystemMessageManager:Unregister",
{ manifest: this._manifest,
uri: this._uri,
{ manifestURL: this._manifestURL,
pageURL: this._pageURL,
innerWindowID: this.innerWindowID });
},
@ -191,17 +200,20 @@ SystemMessageManager.prototype = {
// This one will be received when the starting child process wants to
// retrieve the pending system messages from the parent (i.e. after
// sending SystemMessageManager:GetPendingMessages).
receiveMessage: function sysMessMgr_receiveMessage(aMessage) {
receiveMessage: function(aMessage) {
let msg = aMessage.data;
debug("receiveMessage " + aMessage.name + " for [" + msg.type + "] " +
"with manifest = " + msg.manifest + " and uri = " + msg.uri);
"with manifest URL = " + msg.manifestURL +
" and page URL = " + msg.pageURL);
// Multiple windows can share the same target (process), the content
// window needs to check if the manifest/page URL is matched. Only
// *one* window should handle the system message.
if (msg.manifest !== this._manifest || msg.uri !== this._uri) {
if (msg.manifestURL !== this._manifestURL ||
msg.pageURL !== this._pageURL) {
debug("This page shouldn't handle the messages because its " +
"manifest = " + this._manifest + " and uri = " + this._uri);
"manifest URL = " + this._manifestURL +
" and page URL = " + this._pageURL);
return;
}
@ -210,8 +222,8 @@ SystemMessageManager.prototype = {
// so a re-launched app won't handle it again, which is redundant.
cpmm.sendAsyncMessage("SystemMessageManager:Message:Return:OK",
{ type: msg.type,
manifest: this._manifest,
uri: this._uri,
manifestURL: this._manifestURL,
pageURL: this._pageURL,
msgID: msg.msgID });
}
@ -226,17 +238,20 @@ SystemMessageManager.prototype = {
this._dispatchMessage(msg.type, dispatcher, aMsg);
}, this);
} else {
// We need to notify the parent that all the queued system messages have
// been handled (notice |handledCount: messages.length|), so the parent
// can release the CPU wake lock it took on our behalf.
// Since no handlers are registered, we need to notify the parent as if
// all the queued system messages have been handled (notice |handledCount:
// messages.length|), so the parent can release the CPU wake lock it took
// on our behalf.
cpmm.sendAsyncMessage("SystemMessageManager:HandleMessagesDone",
{ type: msg.type,
manifest: this._manifest,
uri: this._uri,
manifestURL: this._manifestURL,
pageURL: this._pageURL,
handledCount: messages.length });
}
if (!dispatcher || !dispatcher.isHandling) {
// We also need to notify the ContentChild to release the CPU wake lock
// grabbed by the ContentParent (i.e. NewWakeLockOnBehalfOfProcess()) and
// reset the process's priority.
//
// TODO: Bug 874353 - Remove SystemMessageHandledListener in ContentParent
Services.obs.notifyObservers(/* aSubject */ null,
"handle-system-messages-done",
@ -245,20 +260,21 @@ SystemMessageManager.prototype = {
},
// nsIDOMGlobalPropertyInitializer implementation.
init: function sysMessMgr_init(aWindow) {
init: function(aWindow) {
debug("init");
this.initDOMRequestHelper(aWindow, ["SystemMessageManager:Message",
"SystemMessageManager:GetPendingMessages:Return"]);
this.initDOMRequestHelper(aWindow,
["SystemMessageManager:Message",
"SystemMessageManager:GetPendingMessages:Return"]);
let principal = aWindow.document.nodePrincipal;
this._isInBrowserElement = principal.isInBrowserElement;
this._uri = principal.URI.spec;
this._pageURL = principal.URI.spec;
let appsService = Cc["@mozilla.org/AppsService;1"]
.getService(Ci.nsIAppsService);
this._manifest = appsService.getManifestURLByLocalId(principal.appId);
this._manifestURL = appsService.getManifestURLByLocalId(principal.appId);
// Two cases are valid to register the manifest for the current process:
// Two cases are valid to register the manifest URL for the current process:
// 1. This is asked by a child process (parent process must be ready).
// 2. Parent process has already constructed the |SystemMessageInternal|.
// Otherwise, delay to do it when the |SystemMessageInternal| is ready.
@ -271,35 +287,35 @@ SystemMessageManager.prototype = {
}
}
if (readyToRegister) {
this._registerManifest();
this._registerManifestURL();
}
debug("done");
},
observe: function sysMessMgr_observe(aSubject, aTopic, aData) {
observe: function(aSubject, aTopic, aData) {
if (aTopic === kSystemMessageInternalReady) {
this._registerManifest();
this._registerManifestURL();
}
// Call the DOMRequestIpcHelper.observe method.
this.__proto__.__proto__.observe.call(this, aSubject, aTopic, aData);
},
_registerManifest: function sysMessMgr_registerManifest() {
_registerManifestURL: function() {
if (this._isInBrowserElement) {
debug("the app loaded in the browser doesn't need to register " +
"the manifest for listening to the system messages");
"the manifest URL for listening to the system messages");
return;
}
if (!this._registerManifestReady) {
if (!this._registerManifestURLReady) {
cpmm.sendAsyncMessage("SystemMessageManager:Register",
{ manifest: this._manifest,
uri: this._uri,
{ manifestURL: this._manifestURL,
pageURL: this._pageURL,
innerWindowID: this.innerWindowID });
this._registerManifestReady = true;
this._registerManifestURLReady = true;
}
},

View File

@ -249,18 +249,18 @@ this.SystemMessagePermissionsChecker = {
* app's page at run-time based on the current app's permissions.
* @param string aSysMsgName
* The system messsage name.
* @param string aPageURI
* The app's page URI.
* @param string aPageURL
* The app's page URL.
* @param string aManifestURL
* The app's manifest URL.
* @returns bool
* Is permitted or not.
**/
isSystemMessagePermittedToSend:
function isSystemMessagePermittedToSend(aSysMsgName, aPageURI, aManifestURL) {
function isSystemMessagePermittedToSend(aSysMsgName, aPageURL, aManifestURL) {
debug("isSystemMessagePermittedToSend(): " +
"aSysMsgName: " + aSysMsgName + ", " +
"aPageURI: " + aPageURI + ", " +
"aPageURL: " + aPageURL + ", " +
"aManifestURL: " + aManifestURL);
let permNames = this.getSystemMessagePermissions(aSysMsgName);
@ -268,7 +268,7 @@ this.SystemMessagePermissionsChecker = {
return false;
}
let pageURI = Services.io.newURI(aPageURI, null, null);
let pageURI = Services.io.newURI(aPageURL, null, null);
for (let permName in permNames) {
let permNamesWithAccess = permNames[permName];

View File

@ -419,7 +419,7 @@ nsPluginTag::GetMimeTypes(uint32_t* aCount, char16_t*** aResults)
*aCount = count;
for (uint32_t i = 0; i < count; i++) {
(*aResults)[i] = ToNewUnicode(mMimeTypes[i]);
(*aResults)[i] = ToNewUnicode(NS_ConvertUTF8toUTF16(mMimeTypes[i]));
}
return NS_OK;
@ -436,7 +436,7 @@ nsPluginTag::GetMimeDescriptions(uint32_t* aCount, char16_t*** aResults)
*aCount = count;
for (uint32_t i = 0; i < count; i++) {
(*aResults)[i] = ToNewUnicode(mMimeDescriptions[i]);
(*aResults)[i] = ToNewUnicode(NS_ConvertUTF8toUTF16(mMimeDescriptions[i]));
}
return NS_OK;
@ -453,7 +453,7 @@ nsPluginTag::GetExtensions(uint32_t* aCount, char16_t*** aResults)
*aCount = count;
for (uint32_t i = 0; i < count; i++) {
(*aResults)[i] = ToNewUnicode(mExtensions[i]);
(*aResults)[i] = ToNewUnicode(NS_ConvertUTF8toUTF16(mExtensions[i]));
}
return NS_OK;

View File

@ -39,6 +39,7 @@ support-files =
[test_bug863792.html]
[test_bug967694.html]
[test_bug985859.html]
[test_bug986930.html]
[test_cocoa_focus.html]
skip-if = toolkit != "cocoa"
support-files = cocoa_focus.html

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Test for Bug 986930</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="utils.js"></script>
</head>
<body>
<script class="testbody" type="application/javascript">
var testPlugin = getTestPlugin("Test Plug-in");
var mimeDescriptions = testPlugin.getMimeDescriptions({});
is(mimeDescriptions[0], "Test \u2122 mimetype",
"Plugin should handle non-ascii mime description");
</script>
</body>
</html>

View File

@ -31,7 +31,7 @@
<string>tst</string>
</array>
<key>WebPluginTypeDescription</key>
<string>Test mimetype</string>
<string>Test mimetype</string>
</dict>
</dict>
</dict>

View File

@ -26,7 +26,7 @@ BEGIN
VALUE "CompanyName", "mozilla.org"
VALUE "FileDescription", L"Plug-in for testing purposes.\x2122 (\x0939\x093f\x0928\x094d\x0926\x0940 \x4e2d\x6587 \x0627\x0644\x0639\x0631\x0628\x064a\x0629)"
VALUE "FileExtents", "tst"
VALUE "FileOpenName", "Test mimetype"
VALUE "FileOpenName", L"Test \x2122 mimetype"
VALUE "FileVersion", "1.0"
VALUE "InternalName", "nptest"
VALUE "MIMEType", "application/x-test"

View File

@ -3,4 +3,4 @@ const char *sPluginDescription = "Plug-in for testing purposes.\xE2\x84\xA2 " \
"(\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\xa8\xe0\xa5\x8d\xe0\xa4\xa6\xe0\xa5\x80 " \
"\xe4\xb8\xad\xe6\x96\x87 " \
"\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9)";
const char *sMimeDescription = "application/x-test:tst:Test mimetype";
const char *sMimeDescription = "application/x-test:tst:Test \xE2\x84\xA2 mimetype";

View File

@ -304,6 +304,9 @@ partial interface Window {
*/
[Throws] readonly attribute unsigned long long mozPaintCount;
[Pure]
attribute EventHandler onwheel;
attribute EventHandler ondevicemotion;
attribute EventHandler ondeviceorientation;
attribute EventHandler ondeviceproximity;

View File

@ -111,11 +111,17 @@ var WifiManager = (function() {
schedScanRecovery: libcutils.property_get("ro.moz.wifi.sched_scan_recover") === "false" ? false : true,
driverDelay: libcutils.property_get("ro.moz.wifi.driverDelay"),
p2pSupported: libcutils.property_get("ro.moz.wifi.p2p_supported") === "1",
eapSimSupported: libcutils.property_get("ro.moz.wifi.eapsim_supported") === "1",
ifname: libcutils.property_get("wifi.interface")
};
}
let {sdkVersion, unloadDriverEnabled, schedScanRecovery, driverDelay, p2pSupported, ifname} = getStartupPrefs();
let {sdkVersion, unloadDriverEnabled, schedScanRecovery,
driverDelay, p2pSupported, eapSimSupported, ifname} = getStartupPrefs();
let capabilities = {
eapSim: eapSimSupported
};
let wifiListener = {
onWaitEvent: function(event, iface) {
@ -1303,6 +1309,10 @@ var WifiManager = (function() {
});
};
manager.getCapabilities = function() {
return capabilities;
}
return manager;
})();
@ -1767,7 +1777,7 @@ function WifiWorker() {
});
try {
self._allowWpaEap = Services.prefs.getBoolPref("b2g.wifi.allow_unsafe_wpa_eap");
self._allowWpaEap = WifiManager.getCapabilities().eapSim;
} catch (e) {
self._allowWpaEap = false;
}

View File

@ -336,6 +336,16 @@ public:
* DataSourceSurface's data can be accessed directly.
*/
virtual TemporaryRef<DataSourceSurface> GetDataSurface() = 0;
void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) {
mUserData.Add(key, userData, destroy);
}
void *GetUserData(UserDataKey *key) {
return mUserData.Get(key);
}
protected:
UserData mUserData;
};
class DataSourceSurface : public SourceSurface

View File

@ -5,7 +5,7 @@
ifdef MOZ_ANGLE_RENDERER
libs::
ifdef MOZ_HAS_WINSDK_WITH_D3D
ifdef MOZ_D3DCOMPILER_DLL_PATH
cp -fp "$(MOZ_D3DCOMPILER_DLL_PATH)" "$(DIST)/bin"
else
ifdef MOZ_D3DCOMPILER_CAB

View File

@ -5,6 +5,8 @@
ifndef GNU_CC
# Enable unwind semantics for exception handlers in response to warning C4530.
OS_CPPFLAGS += -EHsc
else
OS_CXXFLAGS := $(filter-out -fno-exceptions,$(OS_CXXFLAGS)) -fexceptions
endif
# End build_angle.gypi transcription.
@ -15,19 +17,9 @@ ifndef MOZ_HAS_WINSDK_WITH_D3D
CXXFLAGS += -I'$(MOZ_DIRECTX_SDK_PATH)/include'
endif
ifdef GNU_CC
OS_CXXFLAGS := $(filter-out -fno-exceptions,$(OS_CXXFLAGS)) -fexceptions
OS_LIBS += -ld3d9 -ldxguid
else
ifdef MOZ_HAS_WINSDK_WITH_D3D
EXTRA_DSO_LDOPTS = d3d9.lib dxguid.lib delayimp.lib
EXTRA_DSO_LDOPTS = $(call EXPAND_LIBNAME,d3d9 dxguid)
else
EXTRA_DSO_LDOPTS = '$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/d3d9.lib' \
'$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/dxguid.lib' \
delayimp.lib
endif
EXTRA_DSO_LDOPTS = $(call EXPAND_LIBNAME_PATH,d3d9 dxguid,$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX))
endif
EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME,delayimp)

View File

@ -47,10 +47,6 @@ public:
InfallibleTArray<coord>& texCoords() {
return mTexCoords;
}
unsigned int elements() {
return mVertexCoords.Length();
}
private:
// Reserve inline storage for one quad (2 triangles, 3 coords).
nsAutoTArray<coord, 6> mVertexCoords;

View File

@ -12,6 +12,7 @@
#include "nsRect.h"
#include "gfx2DGlue.h"
#include "gfxUtils.h"
#include "GLDrawRectHelper.h"
namespace mozilla {
namespace gl {
@ -147,25 +148,10 @@ GLBlitTextureImageHelper::BlitTextureImage(TextureImage *aSrc, const nsIntRect&
ScopedBindTextureUnit autoTexUnit(mGL, LOCAL_GL_TEXTURE0);
ScopedBindTexture autoTex(mGL, aSrc->GetTextureID());
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertCoords().Elements());
mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoords().Elements());
mGL->fEnableVertexAttribArray(0);
mGL->fEnableVertexAttribArray(1);
mGL->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
mGL->fDisableVertexAttribArray(0);
mGL->fDisableVertexAttribArray(1);
mGL->DrawRectHelper()->DrawRects(0, 1, rects);
} while (aSrc->NextTile());
} while (aDst->NextTile());
mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, nullptr);
mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, nullptr);
// unbind the previous texture from the framebuffer
SetBlitFramebufferForDestTexture(0);

View File

@ -13,6 +13,7 @@
#include "GLBlitHelper.h"
#include "GLBlitTextureImageHelper.h"
#include "GLReadTexImageHelper.h"
#include "GLDrawRectHelper.h"
#include "gfxCrashReporterUtils.h"
#include "gfxUtils.h"
@ -483,7 +484,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
// Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
if (mInitialized) {
if (IsGLES2()) {
if (IsGLES()) {
SymLoadStruct symbols_ES2[] = {
{ (PRFuncPtr*) &mSymbols.fGetShaderPrecisionFormat, { "GetShaderPrecisionFormat", nullptr } },
{ (PRFuncPtr*) &mSymbols.fClearDepthf, { "ClearDepthf", nullptr } },
@ -1337,7 +1338,7 @@ GLContext::ChooseGLFormats(const SurfaceCaps& caps) const
// If we're on ES2 hardware and we have an explicit request for 16 bits of color or less
// OR we don't support full 8-bit color, return a 4444 or 565 format.
bool bpp16 = caps.bpp16;
if (IsGLES2()) {
if (IsGLES()) {
if (!IsExtensionSupported(OES_rgb8_rgba8))
bpp16 = true;
} else {
@ -1347,7 +1348,7 @@ GLContext::ChooseGLFormats(const SurfaceCaps& caps) const
}
if (bpp16) {
MOZ_ASSERT(IsGLES2());
MOZ_ASSERT(IsGLES());
if (caps.alpha) {
formats.color_texInternalFormat = LOCAL_GL_RGBA;
formats.color_texFormat = LOCAL_GL_RGBA;
@ -1363,11 +1364,11 @@ GLContext::ChooseGLFormats(const SurfaceCaps& caps) const
formats.color_texType = LOCAL_GL_UNSIGNED_BYTE;
if (caps.alpha) {
formats.color_texInternalFormat = IsGLES2() ? LOCAL_GL_RGBA : LOCAL_GL_RGBA8;
formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGBA : LOCAL_GL_RGBA8;
formats.color_texFormat = LOCAL_GL_RGBA;
formats.color_rbFormat = LOCAL_GL_RGBA8;
} else {
formats.color_texInternalFormat = IsGLES2() ? LOCAL_GL_RGB : LOCAL_GL_RGB8;
formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGB : LOCAL_GL_RGB8;
formats.color_texFormat = LOCAL_GL_RGB;
formats.color_rbFormat = LOCAL_GL_RGB8;
}
@ -1386,12 +1387,12 @@ GLContext::ChooseGLFormats(const SurfaceCaps& caps) const
// Be clear that these are 0 if unavailable.
formats.depthStencil = 0;
if (!IsGLES2() || IsExtensionSupported(OES_packed_depth_stencil)) {
if (!IsGLES() || IsExtensionSupported(OES_packed_depth_stencil)) {
formats.depthStencil = LOCAL_GL_DEPTH24_STENCIL8;
}
formats.depth = 0;
if (IsGLES2()) {
if (IsGLES()) {
if (IsExtensionSupported(OES_depth24)) {
formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
} else {
@ -1685,6 +1686,7 @@ GLContext::MarkDestroyed()
mBlitHelper = nullptr;
mBlitTextureImageHelper = nullptr;
mReadTexImageHelper = nullptr;
mDrawRectHelper = nullptr;
mTexGarbageBin->GLContextTeardown();
} else {
@ -2010,6 +2012,16 @@ GLContext::ReadTexImageHelper()
return mReadTexImageHelper;
}
GLDrawRectHelper*
GLContext::DrawRectHelper()
{
if (!mDrawRectHelper) {
mDrawRectHelper = new GLDrawRectHelper(this);
}
return mDrawRectHelper;
}
bool
DoesStringMatch(const char* aString, const char *aWantedString)
{

View File

@ -71,6 +71,7 @@ namespace mozilla {
class GLBlitTextureImageHelper;
class GLReadTexImageHelper;
class SharedSurface_GL;
class GLDrawRectHelper;
}
namespace layers {
@ -287,16 +288,6 @@ public:
virtual bool IsCurrent() = 0;
/**
* If this context is the GLES2 API, returns TRUE.
* This means that various GLES2 restrictions might be in effect (modulo
* extensions).
*/
inline bool IsGLES2() const {
return IsAtLeast(ContextProfile::OpenGLES, 200);
}
protected:
bool mInitialized;
@ -1779,7 +1770,7 @@ public:
private:
void raw_fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
MOZ_ASSERT(IsGLES2());
MOZ_ASSERT(IsGLES());
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fGetShaderPrecisionFormat);
@ -1789,7 +1780,7 @@ private:
public:
void fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
if (IsGLES2()) {
if (IsGLES()) {
raw_fGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
} else {
// Fall back to automatic values because almost all desktop hardware supports the OpenGL standard precisions.
@ -1877,7 +1868,7 @@ public:
private:
void raw_fDepthRange(GLclampf a, GLclampf b) {
MOZ_ASSERT(!IsGLES2());
MOZ_ASSERT(!IsGLES());
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fDepthRange);
@ -1886,7 +1877,7 @@ private:
}
void raw_fDepthRangef(GLclampf a, GLclampf b) {
MOZ_ASSERT(IsGLES2());
MOZ_ASSERT(IsGLES());
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fDepthRangef);
@ -1895,7 +1886,7 @@ private:
}
void raw_fClearDepth(GLclampf v) {
MOZ_ASSERT(!IsGLES2());
MOZ_ASSERT(!IsGLES());
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fClearDepth);
@ -1904,7 +1895,7 @@ private:
}
void raw_fClearDepthf(GLclampf v) {
MOZ_ASSERT(IsGLES2());
MOZ_ASSERT(IsGLES());
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fClearDepthf);
@ -1914,7 +1905,7 @@ private:
public:
void fDepthRange(GLclampf a, GLclampf b) {
if (IsGLES2()) {
if (IsGLES()) {
raw_fDepthRangef(a, b);
} else {
raw_fDepthRange(a, b);
@ -1922,7 +1913,7 @@ public:
}
void fClearDepth(GLclampf v) {
if (IsGLES2()) {
if (IsGLES()) {
raw_fClearDepthf(v);
} else {
raw_fClearDepth(v);
@ -2735,11 +2726,13 @@ protected:
ScopedDeletePtr<GLBlitHelper> mBlitHelper;
ScopedDeletePtr<GLBlitTextureImageHelper> mBlitTextureImageHelper;
ScopedDeletePtr<GLReadTexImageHelper> mReadTexImageHelper;
ScopedDeletePtr<GLDrawRectHelper> mDrawRectHelper;
public:
GLBlitHelper* BlitHelper();
GLBlitTextureImageHelper* BlitTextureImageHelper();
GLReadTexImageHelper* ReadTexImageHelper();
GLDrawRectHelper* DrawRectHelper();
// Assumes shares are created by all sharing with the same global context.
bool SharesWith(const GLContext* other) const {

122
gfx/gl/GLDrawRectHelper.cpp Normal file
View File

@ -0,0 +1,122 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GLDrawRectHelper.h"
#include "GLContext.h"
#include "DecomposeIntoNoRepeatTriangles.h"
namespace mozilla {
namespace gl {
static GLfloat quad[] = {
/* First quad vertices */
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
/* Then quad texcoords */
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
};
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
GLDrawRectHelper::GLDrawRectHelper(GLContext *aGL)
: mGL(aGL)
{
mGL->fGenBuffers(1, &mQuadVBO);
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO);
mGL->fBufferData(LOCAL_GL_ARRAY_BUFFER, sizeof(quad), quad, LOCAL_GL_STATIC_DRAW);
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
GLDrawRectHelper::~GLDrawRectHelper()
{
mGL->fDeleteBuffers(1, &mQuadVBO);
}
void
GLDrawRectHelper::DrawRect(GLuint aVertAttribIndex,
GLuint aTexCoordAttribIndex)
{
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO);
mGL->fVertexAttribPointer(aVertAttribIndex,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, BUFFER_OFFSET(0));
mGL->fEnableVertexAttribArray(aVertAttribIndex);
if (aTexCoordAttribIndex != GLuint(-1)) {
mGL->fVertexAttribPointer(aTexCoordAttribIndex,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, BUFFER_OFFSET(sizeof(quad)/2));
mGL->fEnableVertexAttribArray(aTexCoordAttribIndex);
}
mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
if (aTexCoordAttribIndex != GLuint(-1)) {
mGL->fDisableVertexAttribArray(aTexCoordAttribIndex);
}
mGL->fDisableVertexAttribArray(aVertAttribIndex);
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
void
GLDrawRectHelper::DrawRects(GLuint aVertAttribIndex,
GLuint aTexCoordAttribIndex,
RectTriangles& aRects)
{
GLsizei bytes = aRects.vertCoords().Length() * 2 * sizeof(GLfloat);
GLsizei total = bytes;
if (aTexCoordAttribIndex != GLuint(-1)) {
total *= 2;
}
GLuint vbo;
mGL->fGenBuffers(1, &vbo);
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, vbo);
mGL->fBufferData(LOCAL_GL_ARRAY_BUFFER,
total,
nullptr,
LOCAL_GL_STREAM_DRAW);
mGL->fBufferSubData(LOCAL_GL_ARRAY_BUFFER,
0,
bytes,
aRects.vertCoords().Elements());
mGL->fVertexAttribPointer(aVertAttribIndex,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, BUFFER_OFFSET(0));
mGL->fEnableVertexAttribArray(aVertAttribIndex);
if (aTexCoordAttribIndex != GLuint(-1)) {
mGL->fBufferSubData(LOCAL_GL_ARRAY_BUFFER,
bytes,
bytes,
aRects.texCoords().Elements());
mGL->fVertexAttribPointer(aTexCoordAttribIndex,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, BUFFER_OFFSET(bytes));
mGL->fEnableVertexAttribArray(aTexCoordAttribIndex);
}
mGL->fDrawArrays(LOCAL_GL_TRIANGLES, 0, aRects.vertCoords().Length());
if (aTexCoordAttribIndex != GLuint(-1)) {
mGL->fDisableVertexAttribArray(aTexCoordAttribIndex);
}
mGL->fDisableVertexAttribArray(aVertAttribIndex);
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
mGL->fDeleteBuffers(1, &vbo);
}
}
}

41
gfx/gl/GLDrawRectHelper.h Normal file
View File

@ -0,0 +1,41 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GLDRAWRECTHELPER_H_
#define GLDRAWRECTHELPER_H_
#include "GLContextTypes.h"
#include "GLConsts.h"
namespace mozilla {
namespace gl {
class GLContext;
class RectTriangles;
/** Helper to draw rectangles to the frame buffer. */
class GLDrawRectHelper MOZ_FINAL
{
public:
GLDrawRectHelper(GLContext* aGL);
~GLDrawRectHelper();
void DrawRect(GLuint aVertAttribIndex,
GLuint aTexCoordAttribIndex);
void DrawRects(GLuint aVertAttribIndex,
GLuint aTexCoordAttribIndex,
RectTriangles& aRects);
private:
// The GLContext is the sole owner of the GLDrawHelper.
GLContext* mGL;
GLuint mQuadVBO;
};
}
}
#endif // GLDRAWRECTHELPER_H_

View File

@ -168,7 +168,7 @@ GetActualReadFormats(GLContext* gl,
}
bool fallback = true;
if (gl->IsGLES2()) {
if (gl->IsGLES()) {
GLenum auxFormat = 0;
GLenum auxType = 0;
@ -209,6 +209,10 @@ GetActualReadFormats(GLContext* gl,
static void SwapRAndBComponents(DataSourceSurface* surf)
{
uint8_t *row = surf->GetData();
if (!row) {
MOZ_ASSERT(false, "SwapRAndBComponents: Failed to get data from DataSourceSurface.");
return;
}
size_t rowBytes = surf->GetSize().width*4;
size_t rowHole = surf->Stride() - rowBytes;
@ -764,7 +768,7 @@ GLReadTexImageHelper::ReadTexImage(GLuint aTextureId,
mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, rb);
GLenum rbInternalFormat =
mGL->IsGLES2()
mGL->IsGLES()
? (mGL->IsExtensionSupported(GLContext::OES_rgb8_rgba8) ? LOCAL_GL_RGBA8 : LOCAL_GL_RGBA4)
: LOCAL_GL_RGBA;
mGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, rbInternalFormat, aSize.width, aSize.height);

View File

@ -225,7 +225,7 @@ TexSubImage2DHelper(GLContext *gl,
GLint pixelsize, GLenum format,
GLenum type, const GLvoid* pixels)
{
if (gl->IsGLES2()) {
if (gl->IsGLES()) {
if (stride == width * pixelsize) {
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
std::min(GetAddressAlignment((ptrdiff_t)pixels),
@ -278,7 +278,7 @@ TexImage2DHelper(GLContext *gl,
GLint pixelsize, GLint border, GLenum format,
GLenum type, const GLvoid *pixels)
{
if (gl->IsGLES2()) {
if (gl->IsGLES()) {
NS_ASSERTION(format == (GLenum)internalformat,
"format and internalformat not the same for glTexImage2D on GLES2");

View File

@ -322,7 +322,7 @@ const GLubyte* glGetString_mozilla(GrGLenum name)
// on the GL implementation and change them to match what GLContext actually exposes.
if (name == LOCAL_GL_VERSION) {
if (sGLContext.get()->IsGLES2()) {
if (sGLContext.get()->IsGLES()) {
return reinterpret_cast<const GLubyte*>("OpenGL ES 2.0");
} else {
return reinterpret_cast<const GLubyte*>("2.0");
@ -336,7 +336,7 @@ const GLubyte* glGetString_mozilla(GrGLenum name)
if (!extensionsStringBuilt) {
extensionsString[0] = '\0';
if (sGLContext.get()->IsGLES2()) {
if (sGLContext.get()->IsGLES()) {
// OES is only applicable to GLES2
if (sGLContext.get()->IsExtensionSupported(GLContext::OES_packed_depth_stencil)) {
strcat(extensionsString, "GL_OES_packed_depth_stencil ");
@ -384,7 +384,7 @@ const GLubyte* glGetString_mozilla(GrGLenum name)
return reinterpret_cast<const GLubyte*>(extensionsString);
} else if (name == LOCAL_GL_SHADING_LANGUAGE_VERSION) {
if (sGLContext.get()->IsGLES2()) {
if (sGLContext.get()->IsGLES()) {
return reinterpret_cast<const GLubyte*>("OpenGL ES GLSL ES 1.0");
} else {
return reinterpret_cast<const GLubyte*>("1.10");
@ -770,7 +770,7 @@ static GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context)
context->MakeCurrent();
// We support both desktop GL and GLES2
if (context->IsGLES2()) {
if (context->IsGLES()) {
i->fStandard = kGLES_GrGLStandard;
} else {
i->fStandard = kGL_GrGLStandard;

View File

@ -38,6 +38,7 @@ EXPORTS += [
'GLContextSymbols.h',
'GLContextTypes.h',
'GLDefs.h',
'GLDrawRectHelper.h',
'GLLibraryEGL.h',
'GLLibraryLoader.h',
'GLReadTexImageHelper.h',
@ -123,6 +124,7 @@ UNIFIED_SOURCES += [
'GLContextFeatures.cpp',
'GLContextTypes.cpp',
'GLDebugUtils.cpp',
'GLDrawRectHelper.cpp',
'GLLibraryEGL.cpp',
'GLLibraryLoader.cpp',
'GLReadTexImageHelper.cpp',

View File

@ -14,8 +14,10 @@
#include "gfxImageSurface.h"
#include "YCbCrUtils.h" // for YCbCr conversions
#include <OMX_IVCommon.h>
#include <ColorConverter.h>
#include <cutils/properties.h>
#include <OMX_IVCommon.h>
using namespace mozilla::ipc;
using namespace android;
@ -46,36 +48,28 @@ struct GraphicBufferAutoUnlock {
~GraphicBufferAutoUnlock() { mGraphicBuffer->unlock(); }
};
static bool
IsInEmulator()
{
char propQemu[PROPERTY_VALUE_MAX];
property_get("ro.kernel.qemu", propQemu, "");
return !strncmp(propQemu, "1", 1);
}
GrallocImage::GrallocImage()
: PlanarYCbCrImage(nullptr),
mBufferAllocated(false),
mGraphicBufferLocked(nullptr),
mTextureClient(nullptr)
: PlanarYCbCrImage(nullptr)
{
mFormat = ImageFormat::GRALLOC_PLANAR_YCBCR;
}
GrallocImage::~GrallocImage()
{
// If we have a texture client, the latter takes over the responsibility to
// unlock the GraphicBufferLocked.
if (mGraphicBufferLocked.get() && !mTextureClient) {
// mBufferAllocated is set when gralloc buffer is allocated
// in the GrallocImage.
// XXX the way of handling gralloc buffer in GrallocImage is inconsistent
// between gralloc buffer allocation in GrallocImage and
// gralloc buffer allocation outside of GrallocImage
if (mBufferAllocated) {
ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
ibc->DeallocSurfaceDescriptorGralloc(mGraphicBufferLocked->GetSurfaceDescriptor());
mBufferAllocated = false;
}
}
}
void
GrallocImage::SetData(const Data& aData)
{
MOZ_ASSERT(!mTextureClient, "TextureClient is already set");
NS_PRECONDITION(aData.mYSize.width % 2 == 0, "Image should have even width");
NS_PRECONDITION(aData.mYSize.height % 2 == 0, "Image should have even height");
NS_PRECONDITION(aData.mYStride % 16 == 0, "Image should have stride of multiple of 16 pixels");
@ -83,34 +77,29 @@ GrallocImage::SetData(const Data& aData)
mData = aData;
mSize = aData.mPicSize;
if (!mGraphicBufferLocked.get()) {
SurfaceDescriptor desc;
ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
ibc->AllocSurfaceDescriptorGralloc(aData.mYSize,
HAL_PIXEL_FORMAT_YV12,
GraphicBuffer::USAGE_SW_READ_OFTEN |
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE,
&desc);
if (desc.type() == SurfaceDescriptor::T__None) {
return;
}
mBufferAllocated = true;
mGraphicBufferLocked = new GraphicBufferLocked(desc);
}
sp<GraphicBuffer> graphicBuffer =
GrallocBufferActor::GetFrom(
mGraphicBufferLocked->GetSurfaceDescriptor().get_SurfaceDescriptorGralloc());
if (!graphicBuffer.get()) {
if (IsInEmulator()) {
// Emulator does not support HAL_PIXEL_FORMAT_YV12.
return;
}
if (graphicBuffer->initCheck() != NO_ERROR) {
RefPtr<GrallocTextureClientOGL> textureClient =
new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
gfx::SurfaceFormat::UNKNOWN,
gfx::BackendType::NONE);
bool result =
textureClient->AllocateGralloc(mData.mYSize,
HAL_PIXEL_FORMAT_YV12,
GraphicBuffer::USAGE_SW_READ_OFTEN |
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE);
sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
if (!result || !graphicBuffer.get()) {
mTextureClient = nullptr;
return;
}
mTextureClient = textureClient;
void* vaddr;
if (graphicBuffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
&vaddr) != OK) {
@ -159,7 +148,7 @@ GrallocImage::SetData(const Data& aData)
void GrallocImage::SetData(const GrallocData& aData)
{
mGraphicBufferLocked = aData.mGraphicBuffer;
mTextureClient = static_cast<GrallocTextureClientOGL*>(aData.mGraphicBuffer.get());
mSize = aData.mPicSize;
}
@ -207,8 +196,11 @@ ConvertYVU420SPToRGB565(void *aYData, uint32_t aYStride,
already_AddRefed<gfxASurface>
GrallocImage::DeprecatedGetAsSurface()
{
if (!mTextureClient) {
return nullptr;
}
android::sp<GraphicBuffer> graphicBuffer =
GrallocBufferActor::GetFrom(GetSurfaceDescriptor());
mTextureClient->GetGraphicBuffer();
void *buffer;
int32_t rv =
@ -297,8 +289,11 @@ GrallocImage::DeprecatedGetAsSurface()
TemporaryRef<gfx::SourceSurface>
GrallocImage::GetAsSourceSurface()
{
if (!mTextureClient) {
return nullptr;
}
android::sp<GraphicBuffer> graphicBuffer =
GrallocBufferActor::GetFrom(GetSurfaceDescriptor());
mTextureClient->GetGraphicBuffer();
void *buffer;
int32_t rv =
@ -400,24 +395,33 @@ GrallocImage::GetAsSourceSurface()
return surface;
}
void*
GrallocImage::GetNativeBuffer()
{
if (!mTextureClient) {
return nullptr;
}
android::sp<android::GraphicBuffer> graphicBuffer =
mTextureClient->GetGraphicBuffer();
if (!graphicBuffer.get()) {
return nullptr;
}
return graphicBuffer->getNativeBuffer();
}
SurfaceDescriptor
GrallocImage::GetSurfaceDescriptor()
{
SurfaceDescriptor desc;
if (mTextureClient && mTextureClient->ToSurfaceDescriptor(desc)) {
return desc;
}
return SurfaceDescriptor();
}
TextureClient*
GrallocImage::GetTextureClient(CompositableClient* aClient)
{
if (!mTextureClient) {
const SurfaceDescriptor& sd = GetSurfaceDescriptor();
if (sd.type() != SurfaceDescriptor::TSurfaceDescriptorGralloc) {
return nullptr;
}
const SurfaceDescriptorGralloc& desc = sd.get_SurfaceDescriptorGralloc();
TextureFlags flags = desc.external() ? TEXTURE_DEALLOCATE_CLIENT : 0;
if (desc.isRBSwapped()) {
flags |= TEXTURE_RB_SWAPPED;
}
GrallocBufferActor* actor = static_cast<GrallocBufferActor*>(desc.bufferChild());
mTextureClient = new GrallocTextureClientOGL(actor, mSize, gfx::BackendType::NONE, flags);
mTextureClient->SetGraphicBufferLocked(mGraphicBufferLocked);
}
return mTextureClient;
}

View File

@ -22,63 +22,6 @@ namespace layers {
class GrallocTextureClientOGL;
/**
* The gralloc buffer maintained by android GraphicBuffer can be
* shared between the compositor thread and the producer thread. The
* mGraphicBuffer is owned by the producer thread, but when it is
* wrapped by GraphicBufferLocked and passed to the compositor, the
* buffer content is guaranteed to not change until Unlock() is
* called. Each producer must maintain their own buffer queue and
* implement the GraphicBufferLocked::Unlock() interface.
*/
class GraphicBufferLocked
: public AtomicRefCountedWithFinalize<GraphicBufferLocked>
{
public:
GraphicBufferLocked(SurfaceDescriptor aGraphicBuffer)
: mSurfaceDescriptor(aGraphicBuffer)
{}
virtual ~GraphicBufferLocked() {}
SurfaceDescriptor GetSurfaceDescriptor()
{
return mSurfaceDescriptor;
}
void SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle)
{
mReleaseFenceHandle = aReleaseFenceHandle;
}
const FenceHandle& GetReleaseFenceHandle() const
{
return mReleaseFenceHandle;
}
protected:
virtual void Unlock() {}
private:
/**
* Called once, just before the destructor.
*
* Here goes the shut-down code that uses virtual methods.
* Must only be called by Release().
*/
void Finalize()
{
Unlock();
}
friend class AtomicRefCountedWithFinalize<GraphicBufferLocked>;
protected:
SurfaceDescriptor mSurfaceDescriptor;
FenceHandle mReleaseFenceHandle;
};
/**
* The YUV format supported by Android HAL
*
@ -107,7 +50,7 @@ class GrallocImage : public PlanarYCbCrImage
static uint32_t sColorIdMap[];
public:
struct GrallocData {
nsRefPtr<GraphicBufferLocked> mGraphicBuffer;
nsRefPtr<TextureClient> mGraphicBuffer;
gfx::IntSize mPicSize;
};
@ -141,23 +84,11 @@ public:
virtual already_AddRefed<gfxASurface> DeprecatedGetAsSurface();
virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE;
void* GetNativeBuffer()
{
if (IsValid()) {
return GrallocBufferActor::GetFrom(GetSurfaceDescriptor())->getNativeBuffer();
} else {
return nullptr;
}
}
void* GetNativeBuffer();
virtual bool IsValid() { return GetSurfaceDescriptor().type() != SurfaceDescriptor::T__None; }
SurfaceDescriptor GetSurfaceDescriptor() {
if (mGraphicBufferLocked.get()) {
return mGraphicBufferLocked->GetSurfaceDescriptor();
}
return SurfaceDescriptor();
}
SurfaceDescriptor GetSurfaceDescriptor();
virtual ISharedImage* AsSharedImage() MOZ_OVERRIDE { return this; }
@ -169,8 +100,6 @@ public:
}
private:
bool mBufferAllocated;
nsRefPtr<GraphicBufferLocked> mGraphicBufferLocked;
RefPtr<GrallocTextureClientOGL> mTextureClient;
};

View File

@ -41,10 +41,6 @@ CanvasClient::CreateCanvasClient(CanvasClientType aType,
aFlags |= TEXTURE_DEALLOCATE_CLIENT;
return new CanvasClientSurfaceStream(aForwarder, aFlags);
}
if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
aFlags |= TEXTURE_DEALLOCATE_CLIENT;
return new DeprecatedCanvasClient2D(aForwarder, aFlags);
}
return new CanvasClient2D(aForwarder, aFlags);
}
@ -65,21 +61,12 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
: gfxContentType::COLOR_ALPHA;
gfxImageFormat format
= gfxPlatform::GetPlatform()->OptimalFormatForContent(contentType);
mBuffer = CreateTextureClientForDrawing(gfx::ImageFormatToSurfaceFormat(format),
TEXTURE_FLAGS_DEFAULT,
gfxPlatform::GetPlatform()->GetPreferredCanvasBackend(),
aSize);
bool allocSuccess = false;
if (mBuffer->AsTextureClientSurface()) {
allocSuccess = mBuffer->AsTextureClientSurface()->AllocateForSurface(aSize);
} else {
MOZ_ASSERT(mBuffer->AsTextureClientDrawTarget());
allocSuccess = mBuffer->AsTextureClientDrawTarget()->AllocateForSurface(aSize);
}
if (!allocSuccess) {
mBuffer = nullptr;
return;
}
mBuffer = CreateBufferTextureClient(gfx::ImageFormatToSurfaceFormat(format),
TEXTURE_FLAGS_DEFAULT,
gfxPlatform::GetPlatform()->GetPreferredCanvasBackend());
MOZ_ASSERT(mBuffer->AsTextureClientSurface());
mBuffer->AsTextureClientSurface()->AllocateForSurface(aSize);
bufferCreated = true;
}
@ -90,18 +77,8 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
bool updated = false;
{
// Restrict drawTarget to a scope so that terminates before Unlock.
nsRefPtr<gfxASurface> surface;
if (mBuffer->AsTextureClientSurface()) {
surface = mBuffer->AsTextureClientSurface()->GetAsSurface();
} else {
RefPtr<gfx::DrawTarget> dt
= mBuffer->AsTextureClientDrawTarget()->GetAsDrawTarget();
if (dt) {
surface = gfxPlatform::GetPlatform()->CreateThebesSurfaceAliasForDrawTarget_hack(dt);
}
// the DrawTarget will be kept alive until mBuffer->Unlock() so it's
// OK to let go of dt before we destroy surface.
}
nsRefPtr<gfxASurface> surface =
mBuffer->AsTextureClientSurface()->GetAsSurface();
if (surface) {
aLayer->DeprecatedUpdateSurface(surface);
updated = true;
@ -199,133 +176,5 @@ CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
aLayer->Painted();
}
void
DeprecatedCanvasClient2D::Updated()
{
mForwarder->UpdateTexture(this, 1, mDeprecatedTextureClient->LockSurfaceDescriptor());
}
DeprecatedCanvasClient2D::DeprecatedCanvasClient2D(CompositableForwarder* aFwd,
TextureFlags aFlags)
: CanvasClient(aFwd, aFlags)
{
mTextureInfo.mCompositableType = BUFFER_IMAGE_SINGLE;
}
void
DeprecatedCanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
gfxContentType contentType = isOpaque
? gfxContentType::COLOR
: gfxContentType::COLOR_ALPHA;
if (!mDeprecatedTextureClient) {
mDeprecatedTextureClient = CreateDeprecatedTextureClient(TEXTURE_CONTENT, contentType);
if (!mDeprecatedTextureClient) {
mDeprecatedTextureClient = CreateDeprecatedTextureClient(TEXTURE_FALLBACK, contentType);
if (!mDeprecatedTextureClient) {
NS_WARNING("Could not create texture client");
return;
}
}
}
if (!mDeprecatedTextureClient->EnsureAllocated(aSize, contentType)) {
// We might already be on the fallback texture client if we couldn't create a
// better one above. In which case this call to create is wasted. But I don't
// think this will happen often enough to be worth complicating the code with
// further checks.
mDeprecatedTextureClient = CreateDeprecatedTextureClient(TEXTURE_FALLBACK, contentType);
MOZ_ASSERT(mDeprecatedTextureClient, "Failed to create texture client");
if (!mDeprecatedTextureClient->EnsureAllocated(aSize, contentType)) {
NS_WARNING("Could not allocate texture client");
return;
}
}
gfxASurface* surface = mDeprecatedTextureClient->LockSurface();
aLayer->DeprecatedUpdateSurface(surface);
mDeprecatedTextureClient->Unlock();
}
void
DeprecatedCanvasClientSurfaceStream::Updated()
{
mForwarder->UpdateTextureNoSwap(this, 1, mDeprecatedTextureClient->LockSurfaceDescriptor());
}
DeprecatedCanvasClientSurfaceStream::DeprecatedCanvasClientSurfaceStream(CompositableForwarder* aFwd,
TextureFlags aFlags)
: CanvasClient(aFwd, aFlags)
{
mTextureInfo.mCompositableType = BUFFER_IMAGE_SINGLE;
}
void
DeprecatedCanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
if (!mDeprecatedTextureClient) {
mDeprecatedTextureClient = CreateDeprecatedTextureClient(TEXTURE_STREAM_GL,
aLayer->GetSurfaceMode() == SurfaceMode::SURFACE_OPAQUE
? gfxContentType::COLOR
: gfxContentType::COLOR_ALPHA);
MOZ_ASSERT(mDeprecatedTextureClient, "Failed to create texture client");
}
NS_ASSERTION(aLayer->mGLContext, "CanvasClientSurfaceStream should only be used with GL canvases");
// the content type won't be used
mDeprecatedTextureClient->EnsureAllocated(aSize, gfxContentType::COLOR);
GLScreenBuffer* screen = aLayer->mGLContext->Screen();
SurfaceStream* stream = nullptr;
if (aLayer->mStream) {
stream = aLayer->mStream;
stream->CopySurfaceToProducer(aLayer->mTextureSurface, aLayer->mFactory);
stream->SwapProducer(aLayer->mFactory, gfx::IntSize(aSize.width, aSize.height));
} else {
stream = screen->Stream();
}
bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
if (isCrossProcess) {
// swap staging -> consumer so we can send it to the compositor
SharedSurface* surf = stream->SwapConsumer();
if (!surf) {
printf_stderr("surf is null post-SwapConsumer!\n");
return;
}
#ifdef MOZ_WIDGET_GONK
if (surf->Type() != SharedSurfaceType::Gralloc) {
printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!");
return;
}
SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf);
//XXX todo
//mDeprecatedTextureClient->SetDescriptor(grallocSurf->GetDescriptor());
#else
printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!");
MOZ_ASSERT(false);
#endif
} else {
SurfaceStreamHandle handle = stream->GetShareHandle();
mDeprecatedTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false));
// Bug 894405
//
// Ref this so the SurfaceStream doesn't disappear unexpectedly. The
// Compositor will need to unref it when finished.
aLayer->mGLContext->AddRef();
}
aLayer->Painted();
}
}
}

View File

@ -132,56 +132,6 @@ private:
RefPtr<TextureClient> mBuffer;
};
class DeprecatedCanvasClient2D : public CanvasClient
{
public:
DeprecatedCanvasClient2D(CompositableForwarder* aLayerForwarder,
TextureFlags aFlags);
TextureInfo GetTextureInfo() const MOZ_OVERRIDE
{
return mTextureInfo;
}
virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer);
virtual void Updated() MOZ_OVERRIDE;
virtual void SetDescriptorFromReply(TextureIdentifier aTextureId,
const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE
{
mDeprecatedTextureClient->SetDescriptorFromReply(aDescriptor);
}
private:
RefPtr<DeprecatedTextureClient> mDeprecatedTextureClient;
};
// Used for GL canvases where we don't need to do any readback, i.e., with a
// GL backend.
class DeprecatedCanvasClientSurfaceStream : public CanvasClient
{
public:
DeprecatedCanvasClientSurfaceStream(CompositableForwarder* aFwd,
TextureFlags aFlags);
TextureInfo GetTextureInfo() const MOZ_OVERRIDE
{
return mTextureInfo;
}
virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer);
virtual void Updated() MOZ_OVERRIDE;
virtual void SetDescriptorFromReply(TextureIdentifier aTextureId,
const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE
{
mDeprecatedTextureClient->SetDescriptorFromReply(aDescriptor);
}
private:
RefPtr<DeprecatedTextureClient> mDeprecatedTextureClient;
};
}
}

View File

@ -216,13 +216,17 @@ ClientTiledThebesLayer::RenderLayer()
ToClientLayer(GetMaskLayer())->RenderLayer();
}
bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition();
// Fast path for no progressive updates, no low-precision updates and no
// critical display-port set, or no display-port set.
// critical display-port set, or no display-port set, or this is a fixed
// position layer/contained in a fixed position layer
const FrameMetrics& parentMetrics = GetParent()->GetFrameMetrics();
if ((!gfxPrefs::UseProgressiveTilePainting() &&
!gfxPrefs::UseLowPrecisionBuffer() &&
parentMetrics.mCriticalDisplayPort.IsEmpty()) ||
parentMetrics.mDisplayPort.IsEmpty()) {
parentMetrics.mDisplayPort.IsEmpty() ||
isFixed) {
mValidRegion = mVisibleRegion;
NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");

View File

@ -38,6 +38,22 @@ using namespace gfx;
namespace layers {
static TextureFlags TextureFlagsForRotatedContentBufferFlags(uint32_t aBufferFlags)
{
TextureFlags result = 0;
if (aBufferFlags & RotatedContentBuffer::BUFFER_COMPONENT_ALPHA) {
result |= TEXTURE_COMPONENT_ALPHA;
}
if (aBufferFlags & RotatedContentBuffer::ALLOW_REPEAT) {
result |= TEXTURE_ALLOW_REPEAT;
}
return result;
}
/* static */ TemporaryRef<ContentClient>
ContentClient::CreateContentClient(CompositableForwarder* aForwarder)
{
@ -51,7 +67,12 @@ ContentClient::CreateContentClient(CompositableForwarder* aForwarder)
bool useDoubleBuffering = false;
bool useDeprecatedTextures = true;
// XXX We need support for gralloc with non-deprecated textures content before
// we can use them with FirefoxOS (bug 946720). We need the same locking for
// Windows.
#if !defined(XP_WIN)
useDeprecatedTextures = gfxPlatform::GetPlatform()->UseDeprecatedTextures();
#endif
#ifdef XP_WIN
if (backend == LayersBackend::LAYERS_D3D11) {
@ -210,7 +231,7 @@ ContentClientRemoteBuffer::BuildTextureClients(SurfaceFormat aFormat,
mSurfaceFormat = aFormat;
mSize = gfx::IntSize(aRect.width, aRect.height);
mTextureInfo.mTextureFlags = aFlags & ~TEXTURE_DEALLOCATE_CLIENT;
mTextureInfo.mTextureFlags = TextureFlagsForRotatedContentBufferFlags(aFlags);
if (!CreateAndAllocateTextureClient(mTextureClient, TEXTURE_ON_BLACK) ||
!AddTextureClient(mTextureClient)) {
@ -396,19 +417,18 @@ DeprecatedContentClientRemoteBuffer::BuildDeprecatedTextureClients(ContentType a
mContentType = aType;
mSize = gfx::IntSize(aRect.width, aRect.height);
mTextureInfo.mTextureFlags = aFlags & ~TEXTURE_DEALLOCATE_CLIENT;
mTextureInfo.mTextureFlags = TextureFlagsForRotatedContentBufferFlags(aFlags);
if (!CreateAndAllocateDeprecatedTextureClient(mDeprecatedTextureClient)) {
return;
}
if (aFlags & BUFFER_COMPONENT_ALPHA) {
if (!CreateAndAllocateDeprecatedTextureClient(mDeprecatedTextureClientOnWhite)) {
mDeprecatedTextureClient->SetFlags(0);
mDeprecatedTextureClient = nullptr;
return;
}
mTextureInfo.mTextureFlags |= TEXTURE_COMPONENT_ALPHA;
}
CreateFrontBufferAndNotify(aRect);

View File

@ -282,10 +282,6 @@ TextureClient::CreateTextureClientForDrawing(ISurfaceAllocator* aAllocator,
aMoz2DBackend = gfxPlatform::GetPlatform()->GetContentBackend();
}
#if defined(XP_WIN) || defined(MOZ_WIDGET_GONK)
int32_t maxTextureSize = aAllocator->GetMaxTextureSize();
#endif
RefPtr<TextureClient> result;
#ifdef XP_WIN
@ -294,10 +290,9 @@ TextureClient::CreateTextureClientForDrawing(ISurfaceAllocator* aAllocator,
(aMoz2DBackend == gfx::BackendType::DIRECT2D ||
aMoz2DBackend == gfx::BackendType::DIRECT2D1_1) &&
gfxWindowsPlatform::GetPlatform()->GetD2DDevice() &&
!(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) {
if (aSizeHint.width <= maxTextureSize && aSizeHint.height <= maxTextureSize) {
result = new TextureClientD3D11(aFormat, aTextureFlags);
}
result = new TextureClientD3D11(aFormat, aTextureFlags);
}
if (parentBackend == LayersBackend::LAYERS_D3D9 &&
aMoz2DBackend == gfx::BackendType::CAIRO &&
@ -342,6 +337,7 @@ TextureClient::CreateTextureClientForDrawing(ISurfaceAllocator* aAllocator,
if (!DisableGralloc(aFormat, aSizeHint)) {
// Don't allow Gralloc texture clients to exceed the maximum texture size.
// BufferTextureClients have code to handle tiling the surface client-side.
int32_t maxTextureSize = aAllocator->GetMaxTextureSize();
if (aSizeHint.width <= maxTextureSize && aSizeHint.height <= maxTextureSize) {
result = new GrallocTextureClientOGL(aAllocator, aFormat, aMoz2DBackend,
aTextureFlags);

View File

@ -132,6 +132,7 @@ ThebesLayerComposite::RenderLayer(const nsIntRect& aClipRect)
EffectChain effectChain(this);
LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain);
nsIntRegion visibleRegion = GetEffectiveVisibleRegion();
TiledLayerProperties tiledLayerProps;

View File

@ -171,10 +171,6 @@ bool
TextureClientD3D11::Lock(OpenMode aMode)
{
MOZ_ASSERT(!mIsLocked, "The Texture is already locked!");
if (!mTexture) {
return false;
}
LockD3DTexture(mTexture.get());
mIsLocked = true;
@ -215,10 +211,6 @@ TextureClientD3D11::GetAsDrawTarget()
return mDrawTarget;
}
if (!mTexture) {
return nullptr;
}
mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture, mFormat);
return mDrawTarget;
}
@ -229,7 +221,7 @@ TextureClientD3D11::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlag
mSize = aSize;
ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
CD3D10_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
CD3D10_TEXTURE2D_DESC newDesc(SurfaceFormatToDXGIFormat(mFormat),
aSize.width, aSize.height, 1, 1,
D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE);
@ -337,10 +329,10 @@ DataTextureSourceD3D11::Update(DataSourceSurface* aSurface,
nsIntRegion* aDestRegion,
IntPoint* aSrcOffset)
{
// Right now we only support full surface update. If aDestRegion is provided,
// It will be ignered. Incremental update with a source offset is only used
// on Mac so it is not clear that we ever will need to support it for D3D.
MOZ_ASSERT(!aSrcOffset);
// Right now we only support null aDestRegion and aSrcOffset (which means)
// full surface update. Incremental update is only used on Mac so it is
// not clear that we ever will need to support it for D3D.
MOZ_ASSERT(!aDestRegion && !aSrcOffset);
MOZ_ASSERT(aSurface);
if (!mCompositor || !mCompositor->GetDevice()) {

View File

@ -1061,10 +1061,10 @@ DataTextureSourceD3D9::Update(gfx::DataSourceSurface* aSurface,
nsIntRegion* aDestRegion,
gfx::IntPoint* aSrcOffset)
{
// Right now we only support full surface update. If aDestRegion is provided,
// It will be ignered. Incremental update with a source offset is only used
// on Mac so it is not clear that we ever will need to support it for D3D.
MOZ_ASSERT(!aSrcOffset);
// Right now we only support null aDestRegion and aSrcOffset (which means
// full surface update). Incremental update is only used on Mac so it is
// not clear that we ever will need to support it for D3D.
MOZ_ASSERT(!aDestRegion && !aSrcOffset);
if (!mCompositor || !mCompositor->device()) {
NS_WARNING("No D3D device to update the texture.");

View File

@ -20,7 +20,7 @@
#include "base/message_loop.h" // for MessageLoop
#include "base/task.h" // for NewRunnableMethod, etc
#include "base/tracked.h" // for FROM_HERE
#include "gfxPrefs.h" // for gfxPrefs::UseProgressiveTilePainting
#include "gfxPrefs.h" // for gfxPrefs
#include "gfxTypes.h" // for gfxFloat
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/BasicEvents.h" // for Modifiers, MODIFIER_*
@ -133,18 +133,100 @@ namespace layers {
typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior;
/**
* Specifies whether touch-action property is in force.
*/
static bool gTouchActionPropertyEnabled = false;
/**
/*
* The following prefs are used to control the behaviour of the APZC.
* The default values are provided in gfxPrefs.h.
*
* "apz.allow-checkerboarding"
* Pref that allows or disallows checkerboarding
*
* "apz.asyncscroll.throttle"
* The time period in ms that throttles mozbrowserasyncscroll event.
*
* "apz.asyncscroll.timeout"
* The timeout in ms for mAsyncScrollTimeoutTask delay task.
*
* "apz.axis_lock_mode"
* The preferred axis locking style. See AxisLockMode for possible values.
*
* "apz.content_response_timeout"
* Amount of time before we timeout response from content. For example, if
* content is being unruly/slow and we don't get a response back within this
* time, we will just pretend that content did not preventDefault any touch
* events we dispatched to it.
*
* "apz.cross_slide_enabled"
* Pref that enables integration with the Metro "cross-slide" gesture.
*
* "apz.enlarge_displayport_when_clipped"
* Pref that enables enlarging of the displayport along one axis when the
* generated displayport's size is beyond that of the scrollable rect on the
* opposite axis.
*
* "apz.fling_friction"
* Amount of friction applied during flings.
*
* "apz.fling_repaint_interval"
* Maximum amount of time flinging before sending a viewport change. This will
* asynchronously repaint the page.
*
* "apz.fling_stopped_threshold"
* When flinging, if the velocity goes below this number, we just stop the
* animation completely. This is to prevent asymptotically approaching 0
* velocity and rerendering unnecessarily.
*
* "apz.max_velocity_inches_per_ms"
* Maximum velocity in inches per millisecond. Velocity will be capped at this
* value if a faster fling occurs. Negative values indicate unlimited velocity.
*
* "apz.max_velocity_queue_size"
* Maximum size of velocity queue. The queue contains last N velocity records.
* On touch end we calculate the average velocity in order to compensate
* touch/mouse drivers misbehaviour.
*
* "apz.min_skate_speed"
* Minimum amount of speed along an axis before we switch to "skate" multipliers
* rather than using the "stationary" multipliers.
*
* "apz.num_paint_duration_samples"
* Number of samples to store of how long it took to paint after the previous
* requests.
*
* "apz.pan_repaint_interval"
* Maximum amount of time while panning before sending a viewport change. This
* will asynchronously repaint the page. It is also forced when panning stops.
*
* "apz.touch_start_tolerance"
* Constant describing the tolerance in distance we use, multiplied by the
* device DPI, before we start panning the screen. This is to prevent us from
* accidentally processing taps as touch moves, and from very short/accidental
* touches moving the screen.
*
* "apz.use_paint_duration"
* Whether or not to use the estimated paint duration as a factor when projecting
* the displayport in the direction of scrolling. If this value is set to false,
* a constant 50ms paint time is used; the projection can be scaled as desired
* using the apz.velocity_bias pref below.
*
* "apz.velocity_bias"
* How much to adjust the displayport in the direction of scrolling. This value
* is multiplied by the velocity and added to the displayport offset.
*
* "apz.x_skate_size_multiplier", "apz.y_skate_size_multiplier"
* The multiplier we apply to the displayport size if it is skating (current
* velocity is above apz.min_skate_speed). We prefer to increase the size of the
* Y axis because it is more natural in the case that a user is reading a page
* that scrolls up/down. Note that one, both or neither of these may be used
* at any instant.
* In general we want apz.[xy]_skate_size_multiplier to be smaller than the corresponding
* stationary size multiplier because when panning fast we would like to paint
* less and get faster, more predictable paint times. When panning slowly we
* can afford to paint more even though it's slower.
*
* "apz.x_stationary_size_multiplier", "apz.y_stationary_size_multiplier"
* The multiplier we apply to the displayport size if it is not skating (see
* documentation for the skate size multipliers above).
*/
static float gTouchStartTolerance = 1.0f/4.5f;
/**
* Default touch behavior (is used when not touch behavior is set).
@ -177,43 +259,6 @@ static const double AXIS_BREAKOUT_ANGLE = M_PI / 8.0; // 22.5 degrees
*/
static const double ALLOWED_DIRECT_PAN_ANGLE = M_PI / 3.0; // 60 degrees
/**
* The preferred axis locking style. See AxisLockMode for possible values.
*/
static int32_t gAxisLockMode = 0;
/**
* Maximum amount of time while panning before sending a viewport change. This
* will asynchronously repaint the page. It is also forced when panning stops.
*/
static int32_t gPanRepaintInterval = 250;
/**
* Maximum amount of time flinging before sending a viewport change. This will
* asynchronously repaint the page.
*/
static int32_t gFlingRepaintInterval = 75;
/**
* Minimum amount of speed along an axis before we switch to "skate" multipliers
* rather than using the "stationary" multipliers.
*/
static float gMinSkateSpeed = 1.0f;
/**
* Whether or not to use the estimated paint duration as a factor when projecting
* the displayport in the direction of scrolling. If this value is set to false,
* a constant 50ms paint time is used; the projection can be scaled as desired
* using the gVelocityBias pref below.
*/
static bool gUsePaintDuration = true;
/**
* How much to adjust the displayport in the direction of scrolling. This value
* is multiplied by the velocity and added to the displayport offset.
*/
static float gVelocityBias = 1.0f;
/**
* Duration of a zoom to animation.
*/
@ -234,71 +279,6 @@ static const CSSToScreenScale MAX_ZOOM(8.0f);
*/
static const CSSToScreenScale MIN_ZOOM(0.125f);
/**
* Amount of time before we timeout response from content. For example, if
* content is being unruly/slow and we don't get a response back within this
* time, we will just pretend that content did not preventDefault any touch
* events we dispatched to it.
*/
static int gContentResponseTimeout = 300;
/**
* Number of samples to store of how long it took to paint after the previous
* requests.
*/
static int gNumPaintDurationSamples = 3;
/**
* The multiplier we apply to the displayport size if it is skating (current
* velocity is above gMinSkateSpeed). We prefer to increase the size of the
* Y axis because it is more natural in the case that a user is reading a page
* that scrolls up/down. Note that one, both or neither of these may be used
* at any instant.
* In general we want g[XY]SkateSizeMultiplier to be smaller than the corresponding
* stationary size multiplier because when panning fast we would like to paint
* less and get faster, more predictable paint times. When panning slowly we
* can afford to paint more even though it's slower.
*/
static float gXSkateSizeMultiplier = 1.5f;
static float gYSkateSizeMultiplier = 2.5f;
/**
* The multiplier we apply to the displayport size if it is not skating (see
* documentation for gXSkateSizeMultiplier).
*/
static float gXStationarySizeMultiplier = 3.0f;
static float gYStationarySizeMultiplier = 3.5f;
/**
* The time period in ms that throttles mozbrowserasyncscroll event.
* Default is 100ms if there is no "apz.asyncscroll.throttle" in preference.
*/
static int gAsyncScrollThrottleTime = 100;
/**
* The timeout in ms for mAsyncScrollTimeoutTask delay task.
* Default is 300ms if there is no "apz.asyncscroll.timeout" in preference.
*/
static int gAsyncScrollTimeout = 300;
/**
* Pref that enables integration with the Metro "cross-slide" gesture.
*/
static bool gCrossSlideEnabled = false;
/**
* Pref that allows or disallows checkerboarding
*/
static bool gAllowCheckerboarding = true;
/**
* Pref that enables enlarging of the displayport along one axis when the
* generated displayport's size is beyond that of the scrollable rect on the
* opposite axis.
*/
static bool gEnlargeDisplayPortWhenClipped = false;
/**
* Is aAngle within the given threshold of the horizontal axis?
* @param aAngle an angle in radians in the range [0, pi]
@ -350,7 +330,7 @@ GetFrameTime() {
class FlingAnimation: public AsyncPanZoomAnimation {
public:
FlingAnimation(AsyncPanZoomController& aApzc)
: AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gFlingRepaintInterval))
: AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gfxPrefs::APZFlingRepaintInterval()))
, mApzc(aApzc)
{}
/**
@ -411,27 +391,6 @@ AsyncPanZoomController::InitializeGlobalState()
return;
sInitialized = true;
Preferences::AddBoolVarCache(&gTouchActionPropertyEnabled, "layout.css.touch_action.enabled", gTouchActionPropertyEnabled);
Preferences::AddIntVarCache(&gPanRepaintInterval, "apz.pan_repaint_interval", gPanRepaintInterval);
Preferences::AddIntVarCache(&gFlingRepaintInterval, "apz.fling_repaint_interval", gFlingRepaintInterval);
Preferences::AddFloatVarCache(&gMinSkateSpeed, "apz.min_skate_speed", gMinSkateSpeed);
Preferences::AddBoolVarCache(&gUsePaintDuration, "apz.use_paint_duration", gUsePaintDuration);
Preferences::AddFloatVarCache(&gVelocityBias, "apz.velocity_bias", gVelocityBias);
Preferences::AddIntVarCache(&gContentResponseTimeout, "apz.content_response_timeout", gContentResponseTimeout);
Preferences::AddIntVarCache(&gNumPaintDurationSamples, "apz.num_paint_duration_samples", gNumPaintDurationSamples);
Preferences::AddFloatVarCache(&gTouchStartTolerance, "apz.touch_start_tolerance", gTouchStartTolerance);
Preferences::AddFloatVarCache(&gXSkateSizeMultiplier, "apz.x_skate_size_multiplier", gXSkateSizeMultiplier);
Preferences::AddFloatVarCache(&gYSkateSizeMultiplier, "apz.y_skate_size_multiplier", gYSkateSizeMultiplier);
Preferences::AddFloatVarCache(&gXStationarySizeMultiplier, "apz.x_stationary_size_multiplier", gXStationarySizeMultiplier);
Preferences::AddFloatVarCache(&gYStationarySizeMultiplier, "apz.y_stationary_size_multiplier", gYStationarySizeMultiplier);
Preferences::AddIntVarCache(&gAsyncScrollThrottleTime, "apz.asyncscroll.throttle", gAsyncScrollThrottleTime);
Preferences::AddIntVarCache(&gAsyncScrollTimeout, "apz.asyncscroll.timeout", gAsyncScrollTimeout);
Preferences::AddBoolVarCache(&gCrossSlideEnabled, "apz.cross_slide.enabled", gCrossSlideEnabled);
Preferences::AddIntVarCache(&gAxisLockMode, "apz.axis_lock_mode", gAxisLockMode);
Preferences::AddBoolVarCache(&gAllowCheckerboarding, "apz.allow-checkerboarding", gAllowCheckerboarding);
Preferences::AddBoolVarCache(&gEnlargeDisplayPortWhenClipped, "apz.enlarge_displayport_when_clipped",
gEnlargeDisplayPortWhenClipped);
gComputedTimingFunction = new ComputedTimingFunction();
gComputedTimingFunction->Init(
nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
@ -448,7 +407,7 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
mGeckoContentController(aGeckoContentController),
mRefPtrMonitor("RefPtrMonitor"),
mMonitor("AsyncPanZoomController"),
mTouchActionPropertyEnabled(gTouchActionPropertyEnabled),
mTouchActionPropertyEnabled(gfxPrefs::TouchActionEnabled()),
mContentResponseTimeoutTask(nullptr),
mX(MOZ_THIS_IN_INITIALIZER_LIST()),
mY(MOZ_THIS_IN_INITIALIZER_LIST()),
@ -529,12 +488,12 @@ AsyncPanZoomController::IsDestroyed()
/* static */float
AsyncPanZoomController::GetTouchStartTolerance()
{
return (gTouchStartTolerance * APZCTreeManager::GetDPI());
return (gfxPrefs::APZTouchStartTolerance() * APZCTreeManager::GetDPI());
}
/* static */AsyncPanZoomController::AxisLockMode AsyncPanZoomController::GetAxisLockMode()
{
return static_cast<AxisLockMode>(gAxisLockMode);
return static_cast<AxisLockMode>(gfxPrefs::APZAxisLockMode());
}
nsEventStatus AsyncPanZoomController::ReceiveInputEvent(const InputData& aEvent) {
@ -1088,7 +1047,7 @@ void AsyncPanZoomController::HandlePanningWithTouchAction(double aAngle, TouchBe
}
void AsyncPanZoomController::HandlePanning(double aAngle) {
if (!gCrossSlideEnabled && (!mX.Scrollable() || !mY.Scrollable())) {
if (!gfxPrefs::APZCrossSlideEnabled() && (!mX.Scrollable() || !mY.Scrollable())) {
SetState(PANNING);
} else if (IsCloseToHorizontal(aAngle, AXIS_LOCK_ANGLE)) {
mY.SetAxisLocked(true);
@ -1187,7 +1146,7 @@ void AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
ScheduleComposite();
TimeDuration timePaintDelta = mPaintThrottler.TimeSinceLastRequest(GetFrameTime());
if (timePaintDelta.ToMilliseconds() > gPanRepaintInterval) {
if (timePaintDelta.ToMilliseconds() > gfxPrefs::APZPanRepaintInterval()) {
RequestContentRepaint();
}
UpdateSharedCompositorFrameMetrics();
@ -1386,12 +1345,12 @@ static CSSSize
CalculateDisplayPortSize(const CSSSize& aCompositionSize,
const CSSPoint& aVelocity)
{
float xMultiplier = fabsf(aVelocity.x) < gMinSkateSpeed
? gXStationarySizeMultiplier
: gXSkateSizeMultiplier;
float yMultiplier = fabsf(aVelocity.y) < gMinSkateSpeed
? gYStationarySizeMultiplier
: gYSkateSizeMultiplier;
float xMultiplier = fabsf(aVelocity.x) < gfxPrefs::APZMinSkateSpeed()
? gfxPrefs::APZXStationarySizeMultiplier()
: gfxPrefs::APZXSkateSizeMultiplier();
float yMultiplier = fabsf(aVelocity.y) < gfxPrefs::APZMinSkateSpeed()
? gfxPrefs::APZYStationarySizeMultiplier()
: gfxPrefs::APZYSkateSizeMultiplier();
return CSSSize(aCompositionSize.width * xMultiplier,
aCompositionSize.height * yMultiplier);
}
@ -1439,15 +1398,15 @@ const LayerMargin AsyncPanZoomController::CalculatePendingDisplayPort(
// Calculate the displayport size based on how fast we're moving along each axis.
CSSSize displayPortSize = CalculateDisplayPortSize(compositionSize, velocity);
if (gEnlargeDisplayPortWhenClipped) {
if (gfxPrefs::APZEnlargeDisplayPortWhenClipped()) {
RedistributeDisplayPortExcess(displayPortSize, scrollableRect);
}
// Offset the displayport, depending on how fast we're moving and the
// estimated time it takes to paint, to try to minimise checkerboarding.
float estimatedPaintDurationMillis = (float)(aEstimatedPaintDuration * 1000.0);
float paintFactor = (gUsePaintDuration ? estimatedPaintDurationMillis : 50.0f);
CSSRect displayPort = CSSRect(scrollOffset + (velocity * paintFactor * gVelocityBias),
float paintFactor = (gfxPrefs::APZUsePaintDuration() ? estimatedPaintDurationMillis : 50.0f);
CSSRect displayPort = CSSRect(scrollOffset + (velocity * paintFactor * gfxPrefs::APZVelocityBias()),
displayPortSize);
// Re-center the displayport based on its expansion over the composition size.
@ -1646,7 +1605,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
// with the last event.
// Otherwise, start a timer to fire the event sAsyncScrollTimeout ms from now.
TimeDuration delta = aSampleTime - mLastAsyncScrollTime;
if (delta.ToMilliseconds() > gAsyncScrollThrottleTime &&
if (delta.ToMilliseconds() > gfxPrefs::APZAsyncScrollThrottleTime() &&
mCurrentAsyncScrollOffset != mLastAsyncScrollOffset) {
ReentrantMonitorAutoEnter lock(mMonitor);
mLastAsyncScrollTime = aSampleTime;
@ -1658,7 +1617,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
NewRunnableMethod(this, &AsyncPanZoomController::FireAsyncScrollOnTimeout);
MessageLoop::current()->PostDelayedTask(FROM_HERE,
mAsyncScrollTimeoutTask,
gAsyncScrollTimeout);
gfxPrefs::APZAsyncScrollTimeout());
}
return requestAnimationFrame;
@ -1677,7 +1636,7 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() {
// If checkerboarding has been disallowed, clamp the scroll position to stay
// within rendered content.
if (!gAllowCheckerboarding &&
if (!gfxPrefs::APZAllowCheckerboarding() &&
!mLastContentPaintMetrics.mDisplayPort.IsEmpty()) {
CSSSize compositedSize = mLastContentPaintMetrics.CalculateCompositedSizeInCssPixels();
CSSPoint maxScrollOffset = lastPaintScrollOffset +
@ -1756,7 +1715,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
// Initialize our internal state to something sane when the content
// that was just painted is something we knew nothing about previously
mPaintThrottler.ClearHistory();
mPaintThrottler.SetMaxDurations(gNumPaintDurationSamples);
mPaintThrottler.SetMaxDurations(gfxPrefs::APZNumPaintDurationSamples());
mX.CancelTouch();
mY.CancelTouch();
@ -2045,7 +2004,7 @@ void AsyncPanZoomController::SetContentResponseTimer() {
mContentResponseTimeoutTask =
NewRunnableMethod(this, &AsyncPanZoomController::TimeoutContentResponse);
PostDelayedTask(mContentResponseTimeoutTask, gContentResponseTimeout);
PostDelayedTask(mContentResponseTimeoutTask, gfxPrefs::APZContentResponseTimeout());
}
}

View File

@ -22,58 +22,6 @@
namespace mozilla {
namespace layers {
/**
* These are the preferences that control the behavior of APZ
*/
/**
* "apz.max_event_acceleration"
*
* Maximum acceleration that can happen between two frames. Velocity is
* throttled if it's above this. This may happen if a time delta is very low,
* or we get a touch point very far away from the previous position for some
* reason.
*
* The default value is 999.0f, set in gfxPrefs.h
*/
/**
* "apz.fling_friction"
*
* Amount of friction applied during flings.
*
* The default value is 0.002f, set in gfxPrefs.h
*/
/**
* "apz.fling_stopped_threshold"
*
* When flinging, if the velocity goes below this number, we just stop the
* animation completely. This is to prevent asymptotically approaching 0
* velocity and rerendering unnecessarily.
*
* The default value is 0.01f, set in gfxPrefs.h.
*/
/**
* "apz.max_velocity_queue_size"
*
* Maximum size of velocity queue. The queue contains last N velocity records.
* On touch end we calculate the average velocity in order to compensate
* touch/mouse drivers misbehaviour.
*
* The default value is 5, set in gfxPrefs.h
*/
/**
* "apz.max_velocity_inches_per_ms"
*
* Maximum velocity in inches per millisecond. Velocity will be capped at this
* value if a faster fling occurs. Negative values indicate unlimited velocity.
*
* The default value is -1.0f, set in gfxPrefs.h
*/
Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController)
: mPos(0),
mVelocity(0.0f),

View File

@ -228,42 +228,34 @@ struct GrallocParam {
IntSize size;
uint32_t format;
uint32_t usage;
SurfaceDescriptor* buffer;
MaybeMagicGrallocBufferHandle* handle;
PGrallocBufferChild** child;
GrallocParam(const IntSize& aSize,
const uint32_t& aFormat,
const uint32_t& aUsage,
SurfaceDescriptor* aBuffer)
MaybeMagicGrallocBufferHandle* aHandle,
PGrallocBufferChild** aChild)
: size(aSize)
, format(aFormat)
, usage(aUsage)
, buffer(aBuffer)
, handle(aHandle)
, child(aChild)
{}
};
// dispatched function
static void AllocSurfaceDescriptorGrallocSync(const GrallocParam& aParam,
Monitor* aBarrier,
bool* aDone)
static void AllocGrallocBufferSync(const GrallocParam& aParam,
Monitor* aBarrier,
bool* aDone)
{
MonitorAutoLock autoMon(*aBarrier);
sImageBridgeChildSingleton->AllocSurfaceDescriptorGrallocNow(aParam.size,
aParam.format,
aParam.usage,
aParam.buffer);
*aDone = true;
aBarrier->NotifyAll();
}
// dispatched function
static void DeallocSurfaceDescriptorGrallocSync(const SurfaceDescriptor& aBuffer,
Monitor* aBarrier,
bool* aDone)
{
MonitorAutoLock autoMon(*aBarrier);
sImageBridgeChildSingleton->DeallocSurfaceDescriptorGrallocNow(aBuffer);
sImageBridgeChildSingleton->AllocGrallocBufferNow(aParam.size,
aParam.format,
aParam.usage,
aParam.handle,
aParam.child);
*aDone = true;
aBarrier->NotifyAll();
}
@ -712,92 +704,6 @@ ImageBridgeChild::DeallocPGrallocBufferChild(PGrallocBufferChild* actor)
#endif
}
bool
ImageBridgeChild::AllocSurfaceDescriptorGralloc(const IntSize& aSize,
const uint32_t& aFormat,
const uint32_t& aUsage,
SurfaceDescriptor* aBuffer)
{
if (InImageBridgeChildThread()) {
return ImageBridgeChild::AllocSurfaceDescriptorGrallocNow(aSize, aFormat, aUsage, aBuffer);
}
Monitor barrier("AllocSurfaceDescriptorGralloc Lock");
MonitorAutoLock autoMon(barrier);
bool done = false;
GetMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(&AllocSurfaceDescriptorGrallocSync,
GrallocParam(aSize, aFormat, aUsage, aBuffer), &barrier, &done));
while (!done) {
barrier.Wait();
}
return true;
}
bool
ImageBridgeChild::AllocSurfaceDescriptorGrallocNow(const IntSize& aSize,
const uint32_t& aFormat,
const uint32_t& aUsage,
SurfaceDescriptor* aBuffer)
{
#ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
MaybeMagicGrallocBufferHandle handle;
PGrallocBufferChild* gc = SendPGrallocBufferConstructor(aSize, aFormat, aUsage, &handle);
if (handle.Tnull_t == handle.type()) {
PGrallocBufferChild::Send__delete__(gc);
return false;
}
GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc);
gba->InitFromHandle(handle.get_MagicGrallocBufferHandle());
*aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false, /* swapRB */ false);
return true;
#else
NS_RUNTIMEABORT("No gralloc buffers for you");
return false;
#endif
}
bool
ImageBridgeChild::DeallocSurfaceDescriptorGralloc(const SurfaceDescriptor& aBuffer)
{
if (InImageBridgeChildThread()) {
return ImageBridgeChild::DeallocSurfaceDescriptorGrallocNow(aBuffer);
}
Monitor barrier("DeallocSurfaceDescriptor Lock");
MonitorAutoLock autoMon(barrier);
bool done = false;
GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&DeallocSurfaceDescriptorGrallocSync,
aBuffer, &barrier, &done));
while (!done) {
barrier.Wait();
}
return true;
}
bool
ImageBridgeChild::DeallocSurfaceDescriptorGrallocNow(const SurfaceDescriptor& aBuffer)
{
#ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
PGrallocBufferChild* gbp =
aBuffer.get_SurfaceDescriptorGralloc().bufferChild();
PGrallocBufferChild::Send__delete__(gbp);
return true;
#else
NS_RUNTIMEABORT("Um, how did we get here?");
return false;
#endif
}
bool
ImageBridgeChild::AllocUnsafeShmem(size_t aSize,
ipc::SharedMemory::SharedMemoryType aType,
@ -924,15 +830,44 @@ ImageBridgeChild::AllocGrallocBuffer(const IntSize& aSize,
uint32_t aFormat,
uint32_t aUsage,
MaybeMagicGrallocBufferHandle* aHandle)
{
if (InImageBridgeChildThread()) {
PGrallocBufferChild* child = nullptr;
ImageBridgeChild::AllocGrallocBufferNow(aSize, aFormat, aUsage, aHandle, &child);
return child;
}
Monitor barrier("AllocGrallocBuffer Lock");
MonitorAutoLock autoMon(barrier);
bool done = false;
PGrallocBufferChild* child = nullptr;
GetMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(&AllocGrallocBufferSync,
GrallocParam(aSize, aFormat, aUsage, aHandle, &child), &barrier, &done));
while (!done) {
barrier.Wait();
}
return child;
}
void
ImageBridgeChild::AllocGrallocBufferNow(const gfx::IntSize& aSize,
uint32_t aFormat, uint32_t aUsage,
MaybeMagicGrallocBufferHandle* aHandle,
PGrallocBufferChild** aChild)
{
#ifdef MOZ_WIDGET_GONK
return SendPGrallocBufferConstructor(aSize,
aFormat,
aUsage,
aHandle);
*aChild = SendPGrallocBufferConstructor(aSize,
aFormat,
aUsage,
aHandle);
#else
NS_RUNTIMEABORT("not implemented");
return nullptr;
aChild = nullptr;
#endif
}

View File

@ -200,44 +200,6 @@ public:
virtual bool
DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE;
/**
* Allocate a gralloc SurfaceDescriptor remotely.
*/
bool
AllocSurfaceDescriptorGralloc(const gfx::IntSize& aSize,
const uint32_t& aFormat,
const uint32_t& aUsage,
SurfaceDescriptor* aBuffer);
/**
* Part of the allocation of gralloc SurfaceDescriptor that is
* executed on the ImageBridgeChild thread after invoking
* AllocSurfaceDescriptorGralloc.
*
* Must be called from the ImageBridgeChild thread.
*/
bool
AllocSurfaceDescriptorGrallocNow(const gfx::IntSize& aSize,
const uint32_t& aFormat,
const uint32_t& aUsage,
SurfaceDescriptor* aBuffer);
/**
* Deallocate a remotely allocated gralloc buffer.
*/
bool
DeallocSurfaceDescriptorGralloc(const SurfaceDescriptor& aBuffer);
/**
* Part of the deallocation of gralloc SurfaceDescriptor that is
* executed on the ImageBridgeChild thread after invoking
* DeallocSurfaceDescriptorGralloc.
*
* Must be called from the ImageBridgeChild thread.
*/
bool
DeallocSurfaceDescriptorGrallocNow(const SurfaceDescriptor& aBuffer);
TemporaryRef<ImageClient> CreateImageClient(CompositableType aType);
TemporaryRef<ImageClient> CreateImageClientNow(CompositableType aType);
@ -383,6 +345,10 @@ public:
virtual bool IsSameProcess() const MOZ_OVERRIDE;
void AllocGrallocBufferNow(const gfx::IntSize& aSize,
uint32_t aFormat, uint32_t aUsage,
MaybeMagicGrallocBufferHandle* aHandle,
PGrallocBufferChild** aChild);
protected:
ImageBridgeChild();
bool DispatchAllocShmemInternal(size_t aSize,

View File

@ -449,10 +449,6 @@ void
ShadowLayerForwarder::RemoveTextureFromCompositable(CompositableClient* aCompositable,
TextureClient* aTexture)
{
MOZ_ASSERT(aCompositable);
MOZ_ASSERT(aCompositable->GetIPDLActor());
MOZ_ASSERT(aTexture);
MOZ_ASSERT(aTexture->GetIPDLActor());
mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
nullptr, aTexture->GetIPDLActor()));
if (aTexture->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {

View File

@ -98,7 +98,7 @@ DrawQuads(GLContext *aGLContext,
aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib);
bool texCoords = (texCoordAttribIndex != GLuint(-1));
GLsizei bytes = aRects.elements() * 2 * sizeof(GLfloat);
GLsizei bytes = aRects.vertCoords().Length() * 2 * sizeof(GLfloat);
GLsizei total = bytes;
if (texCoords) {
@ -136,7 +136,7 @@ DrawQuads(GLContext *aGLContext,
aGLContext->fDisableVertexAttribArray(texCoordAttribIndex);
}
aGLContext->fDrawArrays(aMode, 0, aRects.elements());
aGLContext->fDrawArrays(aMode, 0, aRects.vertCoords().Length());
aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
@ -282,7 +282,7 @@ CompositorOGL::Initialize()
LOCAL_GL_NONE
};
if (!mGLContext->IsGLES2()) {
if (!mGLContext->IsGLES()) {
// No TEXTURE_RECTANGLE_ARB available on ES2
textureTargets[1] = LOCAL_GL_TEXTURE_RECTANGLE_ARB;
}
@ -372,8 +372,6 @@ CompositorOGL::Initialize()
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
/* Then quad texcoords */
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
/* Then flipped quad texcoords */
0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
};
mGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER, sizeof(vertices), vertices, LOCAL_GL_STATIC_DRAW);
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
@ -479,7 +477,7 @@ CompositorOGL::BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg,
Matrix4x4 transform;
ToMatrix4x4(aTextureTransform * textureTransform, transform);
aProg->SetTextureTransform(transform);
BindAndDrawQuad(aProg, false);
BindAndDrawQuad(aProg);
} else {
Matrix4x4 transform;
ToMatrix4x4(aTextureTransform, transform);
@ -736,7 +734,7 @@ CompositorOGL::CreateFBOWithTexture(const IntRect& aRect, bool aCopyFromSource,
GetFrameBufferInternalFormat(gl(), aSourceFrameBuffer, mWidget);
bool isFormatCompatibleWithRGBA
= gl()->IsGLES2() ? (format == LOCAL_GL_RGBA)
= gl()->IsGLES() ? (format == LOCAL_GL_RGBA)
: true;
if (isFormatCompatibleWithRGBA) {
@ -988,7 +986,7 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE0, maskQuadTransform);
}
BindAndDrawQuad(program, false, aDrawMode);
BindAndDrawQuad(program, aDrawMode);
}
break;
@ -1072,7 +1070,12 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
surface->BindTexture(LOCAL_GL_TEXTURE0, mFBOTextureTarget);
program->SetTextureTransform(Matrix4x4());
// Drawing is always flipped, but when copying between surfaces we want to avoid
// this, so apply a flip here to cancel the other one out.
Matrix transform;
transform.Translate(0.0, 1.0);
transform.Scale(1.0f, -1.0f);
program->SetTextureTransform(Matrix4x4::From2D(transform));
program->SetTextureUnit(0);
if (maskType != MaskNone) {
@ -1089,7 +1092,7 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
// Drawing is always flipped, but when copying between surfaces we want to avoid
// this. Pass true for the flip parameter to introduce a second flip
// that cancels the other one out.
BindAndDrawQuad(program, true);
BindAndDrawQuad(program);
}
break;
case EFFECT_COMPONENT_ALPHA: {
@ -1190,19 +1193,19 @@ CompositorOGL::EndFrame()
// Unbind all textures
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, 0);
if (!mGLContext->IsGLES2()) {
if (!mGLContext->IsGLES()) {
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
}
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE1);
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, 0);
if (!mGLContext->IsGLES2()) {
if (!mGLContext->IsGLES()) {
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
}
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE2);
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, 0);
if (!mGLContext->IsGLES2()) {
if (!mGLContext->IsGLES()) {
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
}
}
@ -1317,7 +1320,7 @@ CompositorOGL::CopyToTarget(DrawTarget *aTarget, const gfx::Matrix& aTransform)
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
if (!mGLContext->IsGLES2()) {
if (!mGLContext->IsGLES()) {
// GLES2 promises that binding to any custom FBO will attach
// to GL_COLOR_ATTACHMENT0 attachment point.
mGLContext->fReadBuffer(LOCAL_GL_BACK);
@ -1429,28 +1432,16 @@ CompositorOGL::QuadVBOTexCoordsAttrib(GLuint aAttribIndex) {
(GLvoid*) QuadVBOTexCoordOffset());
}
void
CompositorOGL::QuadVBOFlippedTexCoordsAttrib(GLuint aAttribIndex) {
mGLContext->fVertexAttribPointer(aAttribIndex, 2,
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
(GLvoid*) QuadVBOFlippedTexCoordOffset());
}
void
CompositorOGL::BindAndDrawQuad(GLuint aVertAttribIndex,
GLuint aTexCoordAttribIndex,
bool aFlipped,
GLuint aDrawMode)
{
BindQuadVBO();
QuadVBOVerticesAttrib(aVertAttribIndex);
if (aTexCoordAttribIndex != GLuint(-1)) {
if (aFlipped)
QuadVBOFlippedTexCoordsAttrib(aTexCoordAttribIndex);
else
QuadVBOTexCoordsAttrib(aTexCoordAttribIndex);
QuadVBOTexCoordsAttrib(aTexCoordAttribIndex);
mGLContext->fEnableVertexAttribArray(aTexCoordAttribIndex);
}
@ -1464,13 +1455,12 @@ CompositorOGL::BindAndDrawQuad(GLuint aVertAttribIndex,
void
CompositorOGL::BindAndDrawQuad(ShaderProgramOGL *aProg,
bool aFlipped,
GLuint aDrawMode)
{
NS_ASSERTION(aProg->HasInitialized(), "Shader program not correctly initialized");
BindAndDrawQuad(aProg->AttribLocation(ShaderProgramOGL::VertexCoordAttrib),
aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib),
aFlipped, aDrawMode);
aDrawMode);
}
GLuint

View File

@ -311,9 +311,10 @@ private:
CompositingRenderTargetOGL* mWindowRenderTarget;
#endif
/** VBO that has some basics in it for a textured quad,
* including vertex coords and texcoords for both
* flipped and unflipped textures */
/**
* VBO that has some basics in it for a textured quad, including vertex
* coords and texcoords.
*/
GLuint mQuadVBO;
/**
@ -366,18 +367,14 @@ private:
GLintptr QuadVBOVertexOffset() { return 0; }
GLintptr QuadVBOTexCoordOffset() { return sizeof(float)*4*2; }
GLintptr QuadVBOFlippedTexCoordOffset() { return sizeof(float)*8*2; }
void BindQuadVBO();
void QuadVBOVerticesAttrib(GLuint aAttribIndex);
void QuadVBOTexCoordsAttrib(GLuint aAttribIndex);
void QuadVBOFlippedTexCoordsAttrib(GLuint aAttribIndex);
void BindAndDrawQuad(GLuint aVertAttribIndex,
GLuint aTexCoordAttribIndex,
bool aFlipped = false,
GLuint aDrawMode = LOCAL_GL_TRIANGLE_STRIP);
void BindAndDrawQuad(ShaderProgramOGL *aProg,
bool aFlipped = false,
GLuint aDrawMode = LOCAL_GL_TRIANGLE_STRIP);
void BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg,
const gfx3DMatrix& aTextureTransform,

View File

@ -13,7 +13,6 @@
#include "gfx2DGlue.h"
#include "gfxASurface.h"
#include "gfxImageSurface.h" // for gfxImageSurface
#include "GrallocImages.h"
namespace mozilla {
namespace layers {
@ -21,29 +20,6 @@ namespace layers {
using namespace mozilla::gfx;
using namespace android;
class GraphicBufferLockedTextureClientData : public TextureClientData {
public:
GraphicBufferLockedTextureClientData(GraphicBufferLocked* aBufferLocked)
: mBufferLocked(aBufferLocked)
{
MOZ_COUNT_CTOR(GrallocTextureClientData);
}
~GraphicBufferLockedTextureClientData()
{
MOZ_COUNT_DTOR(GrallocTextureClientData);
MOZ_ASSERT(!mBufferLocked, "Forgot to unlock the GraphicBufferLocked?");
}
virtual void DeallocateSharedData(ISurfaceAllocator*) MOZ_OVERRIDE
{
mBufferLocked = nullptr;
}
private:
RefPtr<GraphicBufferLocked> mBufferLocked;
};
class GrallocTextureClientData : public TextureClientData {
public:
GrallocTextureClientData(GrallocBufferActor* aActor)
@ -55,7 +31,7 @@ public:
~GrallocTextureClientData()
{
MOZ_COUNT_DTOR(GrallocTextureClientData);
MOZ_ASSERT(!mGrallocActor, "Forgot to unlock the GraphicBufferLocked?");
MOZ_ASSERT(!mGrallocActor);
}
virtual void DeallocateSharedData(ISurfaceAllocator* allocator) MOZ_OVERRIDE
@ -76,18 +52,10 @@ private:
TextureClientData*
GrallocTextureClientOGL::DropTextureData()
{
if (mBufferLocked) {
TextureClientData* result = new GraphicBufferLockedTextureClientData(mBufferLocked);
mBufferLocked = nullptr;
mGrallocActor = nullptr;
mGraphicBuffer = nullptr;
return result;
} else {
TextureClientData* result = new GrallocTextureClientData(mGrallocActor);
mGrallocActor = nullptr;
mGraphicBuffer = nullptr;
return result;
}
TextureClientData* result = new GrallocTextureClientData(mGrallocActor);
mGrallocActor = nullptr;
mGraphicBuffer = nullptr;
return result;
}
GrallocTextureClientOGL::GrallocTextureClientOGL(GrallocBufferActor* aActor,
@ -96,6 +64,7 @@ GrallocTextureClientOGL::GrallocTextureClientOGL(GrallocBufferActor* aActor,
TextureFlags aFlags)
: BufferTextureClient(nullptr, gfx::SurfaceFormat::UNKNOWN, aMoz2dBackend, aFlags)
, mMappedBuffer(nullptr)
, mMediaBuffer(nullptr)
{
InitWith(aActor, aSize);
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
@ -107,6 +76,7 @@ GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
TextureFlags aFlags)
: BufferTextureClient(aAllocator, aFormat, aMoz2dBackend, aFlags)
, mMappedBuffer(nullptr)
, mMediaBuffer(nullptr)
{
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
}
@ -117,16 +87,14 @@ GrallocTextureClientOGL::~GrallocTextureClientOGL()
if (ShouldDeallocateInDestructor()) {
// If the buffer has never been shared we must deallocate it or it would
// leak.
if (!mBufferLocked) {
// We just need to wrap the actor in a SurfaceDescriptor because that's what
// ISurfaceAllocator uses as input, we don't care about the other parameters.
SurfaceDescriptor sd = SurfaceDescriptorGralloc(nullptr, mGrallocActor,
IntSize(0, 0),
false, false);
// We just need to wrap the actor in a SurfaceDescriptor because that's what
// ISurfaceAllocator uses as input, we don't care about the other parameters.
SurfaceDescriptor sd = SurfaceDescriptorGralloc(nullptr, mGrallocActor,
IntSize(0, 0),
false, false);
ISurfaceAllocator* allocator = GetAllocator();
allocator->DestroySharedSurface(&sd);
}
ISurfaceAllocator* allocator = GetAllocator();
allocator->DestroySharedSurface(&sd);
}
}
@ -141,12 +109,6 @@ GrallocTextureClientOGL::InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize
mSize = aSize;
}
void
GrallocTextureClientOGL::SetGraphicBufferLocked(GraphicBufferLocked* aBufferLocked)
{
mBufferLocked = aBufferLocked;
}
bool
GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
@ -180,11 +142,7 @@ GrallocTextureClientOGL::UpdateSurface(gfxASurface* aSurface)
void
GrallocTextureClientOGL::SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle)
{
if (mBufferLocked) {
mBufferLocked->SetReleaseFenceHandle(aReleaseFenceHandle);
} else {
mReleaseFenceHandle = aReleaseFenceHandle;
}
mReleaseFenceHandle = aReleaseFenceHandle;
}
void

View File

@ -13,11 +13,14 @@
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
#include <ui/GraphicBuffer.h>
namespace android {
class MediaBuffer;
};
namespace mozilla {
namespace layers {
class GraphicBufferLocked;
/**
* A TextureClient implementation based on android::GraphicBuffer (also referred to
* as "gralloc").
@ -102,7 +105,20 @@ public:
virtual size_t GetBufferSize() const MOZ_OVERRIDE;
void SetGraphicBufferLocked(GraphicBufferLocked* aBufferLocked);
/**
* Hold android::MediaBuffer.
* MediaBuffer needs to be add refed to keep MediaBuffer alive
* during TextureClient is in use.
*/
void SetMediaBuffer(android::MediaBuffer* aMediaBuffer)
{
mMediaBuffer = aMediaBuffer;
}
android::MediaBuffer* GetMediaBuffer()
{
return mMediaBuffer;
}
protected:
/**
@ -110,8 +126,6 @@ protected:
*/
GrallocBufferActor* mGrallocActor;
RefPtr<GraphicBufferLocked> mBufferLocked;
android::sp<android::GraphicBuffer> mGraphicBuffer;
/**
@ -128,6 +142,8 @@ protected:
* Extra size member is necessary. See Bug 850566.
*/
gfx::IntSize mSize;
android::MediaBuffer* mMediaBuffer;
};
} // namespace layers

View File

@ -74,6 +74,14 @@ public:
NS_ERROR("This shouldn't be called because we never enable hyphens");
return 0;
}
virtual already_AddRefed<gfxContext> GetContext() {
NS_ERROR("This shouldn't be called because we never enable hyphens");
return nullptr;
}
virtual uint32_t GetAppUnitsPerDevUnit() {
NS_ERROR("This shouldn't be called because we never enable hyphens");
return 60;
}
virtual void GetSpacing(uint32_t aStart, uint32_t aLength,
Spacing* aSpacing) {
NS_ERROR("This shouldn't be called because we never enable spacing");

View File

@ -335,14 +335,14 @@ ApzcTap(AsyncPanZoomController* apzc, int aX, int aY, int& aTime, int aTapLength
return ApzcUp(apzc, aX, aY, aTime);
}
TEST(AsyncPanZoomController, Constructor) {
TEST_F(AsyncPanZoomControllerTester, Constructor) {
// RefCounted class can't live in the stack
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
apzc->SetFrameMetrics(TestFrameMetrics());
}
TEST(AsyncPanZoomController, Pinch) {
TEST_F(AsyncPanZoomControllerTester, Pinch) {
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
@ -385,7 +385,7 @@ TEST(AsyncPanZoomController, Pinch) {
apzc->Destroy();
}
TEST(AsyncPanZoomController, PinchWithTouchActionNone) {
TEST_F(AsyncPanZoomControllerTester, PinchWithTouchActionNone) {
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
@ -419,7 +419,7 @@ TEST(AsyncPanZoomController, PinchWithTouchActionNone) {
EXPECT_EQ(fm.GetScrollOffset().y, 300);
}
TEST(AsyncPanZoomController, Overzoom) {
TEST_F(AsyncPanZoomControllerTester, Overzoom) {
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
@ -446,7 +446,7 @@ TEST(AsyncPanZoomController, Overzoom) {
EXPECT_LT(abs(fm.GetScrollOffset().y), 1e-5);
}
TEST(AsyncPanZoomController, SimpleTransform) {
TEST_F(AsyncPanZoomControllerTester, SimpleTransform) {
TimeStamp testStartTime = TimeStamp::Now();
// RefCounted class can't live in the stack
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
@ -462,7 +462,7 @@ TEST(AsyncPanZoomController, SimpleTransform) {
}
TEST(AsyncPanZoomController, ComplexTransform) {
TEST_F(AsyncPanZoomControllerTester, ComplexTransform) {
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
@ -962,7 +962,7 @@ GetTargetAPZC(APZCTreeManager* manager, const ScreenPoint& aPoint,
}
// A simple hit testing test that doesn't involve any transforms on layers.
TEST(APZCTreeManager, HitTesting1) {
TEST_F(APZCTreeManagerTester, HitTesting1) {
nsTArray<nsRefPtr<Layer> > layers;
nsRefPtr<LayerManager> lm;
nsRefPtr<Layer> root = CreateTestLayerTree1(lm, layers);

1039
gfx/thebes/CJKCompatSVS.cpp Normal file

File diff suppressed because it is too large Load Diff

77
gfx/thebes/gencjkcisvs.py Normal file
View File

@ -0,0 +1,77 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
import os.path
import re
import sys
f = open(sys.argv[1] if len(sys.argv) > 1 else 'StandardizedVariants.txt')
line = f.readline()
m = re.compile('^# (StandardizedVariants(-\d+(\.\d+)*)?\.txt)').search(line)
fileversion = m.group(1)
vsdict = {}
r = re.compile('^([0-9A-F]{4,6}) (FE0[0-9A-F]); CJK COMPATIBILITY IDEOGRAPH-([0-9A-F]{4,6});')
while True:
line = f.readline()
if not line:
break
if not 'CJK COMPATIBILITY IDEOGRAPH-' in line:
continue
m = r.search(line)
unified = int(m.group(1), 16)
vs = int(m.group(2), 16)
compat = int(m.group(3), 16)
if not vs in vsdict:
vsdict[vs] = {}
vsdict[vs][unified] = compat
f.close
offsets = []
length = 10 + 11 * len(vsdict)
for (k, mappings) in sorted(vsdict.items()):
offsets.append(length)
length += 4 + 5 * len(mappings)
f = open(sys.argv[2] if len(sys.argv) > 2 else 'CJKCompatSVS.cpp', 'wb')
f.write("""// Generated by %s. Do not edit.
#include <stdint.h>
#define U16(v) (((v) >> 8) & 0xFF), ((v) & 0xFF)
#define U24(v) (((v) >> 16) & 0xFF), (((v) >> 8) & 0xFF), ((v) & 0xFF)
#define U32(v) (((v) >> 24) & 0xFF), (((v) >> 16) & 0xFF), (((v) >> 8) & 0xFF), ((v) & 0xFF)
#define GLYPH(v) U16(v >= 0x2F800 ? (v) - (0x2F800 - 0xFB00) : (v))
// Fallback mappings for CJK Compatibility Ideographs Standardized Variants
// taken from %s.
// Using OpenType format 14 cmap subtable structure to reuse the lookup code
// for fonts. The glyphID field is used to store the corresponding codepoints
// CJK Compatibility Ideographs. To fit codepoints into the 16-bit glyphID
// field, CJK Compatibility Ideographs Supplement (U+2F800..U+2FA1F) will be
// mapped to 0xFB00..0xFD1F.
extern const uint8_t sCJKCompatSVSTable[] = {
""" % (os.path.basename(sys.argv[0]), fileversion))
f.write(' U16(14), // format\n')
f.write(' U32(%d), // length\n' % length)
f.write(' U32(%d), // numVarSelectorRecords\n' % len(vsdict))
for i, k in enumerate(sorted(vsdict.keys())):
f.write(' U24(0x%04X), U32(0), U32(%d), // varSelectorRecord[%d]\n' % (k, offsets[i], i))
for (k, mappings) in sorted(vsdict.items()):
f.write(' // 0x%04X\n' % k)
f.write(' U32(%d), // numUVSMappings\n' % len(mappings))
for (unified, compat) in sorted(mappings.items()):
f.write(' U24(0x%04X), GLYPH(0x%04X),\n' % (unified, compat))
f.write("""};
#undef U16
#undef U24
#undef U32
#undef GLYPH
static_assert(sizeof sCJKCompatSVSTable == %d, "Table generator has a bug.");
""" % length)

View File

@ -8,6 +8,7 @@
#include "harfbuzz/hb.h"
#include "mozilla/Likely.h"
#include "gfxFontConstants.h"
#include "gfxFontUtils.h"
using namespace mozilla::gfx;
@ -155,6 +156,10 @@ gfxFT2FontBase::GetGlyph(uint32_t unicode, uint32_t variation_selector)
gfxFT2LockedFace(this).GetUVSGlyph(unicode, variation_selector);
if (id)
return id;
id = gfxFontUtils::GetUVSFallback(unicode, variation_selector);
if (id) {
unicode = id;
}
}
return GetGlyph(unicode);

View File

@ -4878,13 +4878,17 @@ gfxFontGroup::MakeHyphenTextRun(gfxContext *aCtx, uint32_t aAppUnitsPerDevUnit)
}
gfxFloat
gfxFontGroup::GetHyphenWidth(gfxContext *aCtx, uint32_t aAppUnitsPerDevUnit)
gfxFontGroup::GetHyphenWidth(gfxTextRun::PropertyProvider *aProvider)
{
if (mHyphenWidth < 0) {
nsAutoPtr<gfxTextRun> hyphRun(MakeHyphenTextRun(aCtx,
aAppUnitsPerDevUnit));
mHyphenWidth = hyphRun.get() ?
hyphRun->GetAdvanceWidth(0, hyphRun->GetLength(), nullptr) : 0;
nsRefPtr<gfxContext> ctx(aProvider->GetContext());
if (ctx) {
nsAutoPtr<gfxTextRun>
hyphRun(MakeHyphenTextRun(ctx,
aProvider->GetAppUnitsPerDevUnit()));
mHyphenWidth = hyphRun.get() ?
hyphRun->GetAdvanceWidth(0, hyphRun->GetLength(), nullptr) : 0;
}
}
return mHyphenWidth;
}

View File

@ -2834,6 +2834,14 @@ public:
*/
virtual void GetSpacing(uint32_t aStart, uint32_t aLength,
Spacing *aSpacing) = 0;
// Returns a gfxContext that can be used to measure the hyphen glyph.
// Only called if the hyphen width is requested.
virtual already_AddRefed<gfxContext> GetContext() = 0;
// Return the appUnitsPerDevUnit value to be used when measuring.
// Only called if the hyphen width is requested.
virtual uint32_t GetAppUnitsPerDevUnit() = 0;
};
class ClusterIterator {
@ -3433,7 +3441,7 @@ public:
* needed to initialize the cached hyphen width; otherwise they are
* ignored.
*/
gfxFloat GetHyphenWidth(gfxContext *aCtx, uint32_t aAppUnitsPerDevUnit);
gfxFloat GetHyphenWidth(gfxTextRun::PropertyProvider* aProvider);
/**
* Make a text run representing a single hyphen character.

View File

@ -692,9 +692,27 @@ gfxFontUtils::MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength,
uint32_t varGID =
gfxFontUtils::MapUVSToGlyphFormat14(aCmapBuf + uvsOffset,
aUnicode, aVarSelector);
if (!varGID) {
aUnicode = gfxFontUtils::GetUVSFallback(aUnicode, aVarSelector);
if (aUnicode) {
switch (format) {
case 4:
if (aUnicode < UNICODE_BMP_LIMIT) {
varGID = MapCharToGlyphFormat4(aCmapBuf + offset,
char16_t(aUnicode));
}
break;
case 12:
varGID = MapCharToGlyphFormat12(aCmapBuf + offset,
aUnicode);
break;
}
}
}
if (varGID) {
gid = varGID;
}
// else the variation sequence was not supported, use default mapping
// of the character code alone
}

View File

@ -639,6 +639,8 @@ enum gfxUserFontType {
GFX_USERFONT_WOFF = 3
};
extern const uint8_t sCJKCompatSVSTable[];
class gfxFontUtils {
public:
@ -784,6 +786,15 @@ public:
static uint16_t
MapUVSToGlyphFormat14(const uint8_t *aBuf, uint32_t aCh, uint32_t aVS);
// sCJKCompatSVSTable is a 'cmap' format 14 subtable that maps
// <char + var-selector> pairs to the corresponding Unicode
// compatibility ideograph codepoints.
static MOZ_ALWAYS_INLINE uint32_t
GetUVSFallback(uint32_t aCh, uint32_t aVS) {
aCh = MapUVSToGlyphFormat14(sCJKCompatSVSTable, aCh, aVS);
return aCh >= 0xFB00 ? aCh + (0x2F800 - 0xFB00) : aCh;
}
static uint32_t
MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength,
uint32_t aUnicode, uint32_t aVarSelector = 0);

View File

@ -95,6 +95,24 @@ gfxHarfBuzzShaper::GetGlyph(hb_codepoint_t unicode,
unicode,
variation_selector);
}
if (!gid) {
uint32_t compat =
gfxFontUtils::GetUVSFallback(unicode, variation_selector);
if (compat) {
switch (mCmapFormat) {
case 4:
if (compat < UNICODE_BMP_LIMIT) {
gid = gfxFontUtils::MapCharToGlyphFormat4(data + mSubtableOffset,
compat);
}
break;
case 12:
gid = gfxFontUtils::MapCharToGlyphFormat12(data + mSubtableOffset,
compat);
break;
}
}
}
// If the variation sequence was not supported, return zero here;
// harfbuzz will call us again for the base character alone
return gid;

View File

@ -273,7 +273,7 @@ gfxPlatform::gfxPlatform()
#ifdef XP_WIN
// XXX - When 957560 is fixed, the pref can go away entirely
mLayersUseDeprecated =
Preferences::GetBool("layers.use-deprecated-textures", false)
Preferences::GetBool("layers.use-deprecated-textures", true)
&& !gfxPrefs::LayersPreferOpenGL();
#else
mLayersUseDeprecated = false;
@ -632,6 +632,18 @@ void SourceBufferDestroy(void *srcSurfUD)
delete static_cast<SourceSurfaceUserData*>(srcSurfUD);
}
UserDataKey kThebesSurface;
struct DependentSourceSurfaceUserData
{
nsRefPtr<gfxASurface> mSurface;
};
void SourceSurfaceDestroyed(void *aData)
{
delete static_cast<DependentSourceSurfaceUserData*>(aData);
}
#if MOZ_TREE_CAIRO
void SourceSnapshotDetached(cairo_surface_t *nullSurf)
{
@ -654,6 +666,34 @@ gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface *aSurface)
aSurface->SetData(&kSourceSurface, nullptr, nullptr);
}
static TemporaryRef<DataSourceSurface>
CopySurface(gfxASurface* aSurface)
{
const nsIntSize size = aSurface->GetSize();
gfxImageFormat format = gfxPlatform::GetPlatform()->OptimalFormatForContent(aSurface->GetContentType());
RefPtr<DataSourceSurface> data =
Factory::CreateDataSourceSurface(ToIntSize(size),
ImageFormatToSurfaceFormat(format));
if (!data) {
return nullptr;
}
DataSourceSurface::MappedSurface map;
DebugOnly<bool> result = data->Map(DataSourceSurface::WRITE, &map);
MOZ_ASSERT(result, "Should always succeed mapping raw data surfaces!");
nsRefPtr<gfxImageSurface> image = new gfxImageSurface(map.mData, size, map.mStride, format);
nsRefPtr<gfxContext> ctx = new gfxContext(image);
ctx->SetSource(aSurface);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->Paint();
data->Unmap();
return data;
}
RefPtr<SourceSurface>
gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurface)
{
@ -722,18 +762,24 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
}
}
bool dependsOnData = false;
if (!srcBuffer) {
nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
bool isWin32ImageSurf = imgSurface &&
aSurface->GetType() == gfxSurfaceType::Win32;
RefPtr<DataSourceSurface> copy;
if (!imgSurface) {
imgSurface = new gfxImageSurface(aSurface->GetSize(), OptimalFormatForContent(aSurface->GetContentType()));
nsRefPtr<gfxContext> ctx = new gfxContext(imgSurface);
ctx->SetSource(aSurface);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->Paint();
copy = CopySurface(aSurface);
if (!copy) {
return nullptr;
}
DataSourceSurface::MappedSurface map;
DebugOnly<bool> result = copy->Map(DataSourceSurface::WRITE, &map);
MOZ_ASSERT(result, "Should always succeed mapping raw data surfaces!");
imgSurface = new gfxImageSurface(map.mData, aSurface->GetSize(), map.mStride,
SurfaceFormatToImageFormat(copy->GetFormat()));
}
gfxImageFormat cairoFormat = imgSurface->Format();
@ -760,38 +806,56 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
imgSurface->Stride(),
format);
if (!srcBuffer) {
// We need to check if our gfxASurface will keep the underlying data
// alive. This is true if gfxASurface actually -is- an ImageSurface or
// if it is a gfxWindowsSurface which supports GetAsImageSurface.
if (imgSurface != aSurface && !isWin32ImageSurf) {
return nullptr;
}
srcBuffer = Factory::CreateWrappingDataSourceSurface(imgSurface->Data(),
imgSurface->Stride(),
size, format);
if (copy) {
copy->Unmap();
}
if (!srcBuffer) {
// If we had to make a copy, then just return that. Otherwise aSurface
// must have supported GetAsImageSurface, so we can just wrap that data.
if (copy) {
srcBuffer = copy;
} else {
srcBuffer = Factory::CreateWrappingDataSourceSurface(imgSurface->Data(),
imgSurface->Stride(),
size, format);
dependsOnData = true;
}
}
if (!srcBuffer) {
return nullptr;
}
if (!dependsOnData) {
#if MOZ_TREE_CAIRO
cairo_surface_t *nullSurf =
cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
cairo_surface_set_user_data(nullSurf,
&kSourceSurface,
imgSurface,
nullptr);
cairo_surface_attach_snapshot(imgSurface->CairoSurface(), nullSurf, SourceSnapshotDetached);
cairo_surface_destroy(nullSurf);
cairo_surface_t *nullSurf =
cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
cairo_surface_set_user_data(nullSurf,
&kSourceSurface,
imgSurface,
nullptr);
cairo_surface_attach_snapshot(imgSurface->CairoSurface(), nullSurf, SourceSnapshotDetached);
cairo_surface_destroy(nullSurf);
#else
cairo_surface_set_mime_data(imgSurface->CairoSurface(), "mozilla/magic", (const unsigned char*) "data", 4, SourceSnapshotDetached, imgSurface.get());
cairo_surface_set_mime_data(imgSurface->CairoSurface(), "mozilla/magic", (const unsigned char*) "data", 4, SourceSnapshotDetached, imgSurface.get());
#endif
}
}
SourceSurfaceUserData *srcSurfUD = new SourceSurfaceUserData;
srcSurfUD->mBackendType = aTarget->GetType();
srcSurfUD->mSrcSurface = srcBuffer;
aSurface->SetData(&kSourceSurface, srcSurfUD, SourceBufferDestroy);
if (dependsOnData) {
// If we wrapped the underlying data of aSurface, then we need to add user data
// to make sure aSurface stays alive until we are done with the data.
DependentSourceSurfaceUserData *srcSurfUD = new DependentSourceSurfaceUserData;
srcSurfUD->mSurface = aSurface;
srcBuffer->AddUserData(&kThebesSurface, srcSurfUD, SourceSurfaceDestroyed);
} else {
// Otherwise add user data to aSurface so we can cache lookups in the future.
SourceSurfaceUserData *srcSurfUD = new SourceSurfaceUserData;
srcSurfUD->mBackendType = aTarget->GetType();
srcSurfUD->mSrcSurface = srcBuffer;
aSurface->SetData(&kSourceSurface, srcSurfUD, SourceBufferDestroy);
}
return srcBuffer;
}

Some files were not shown because too many files have changed in this diff Show More