Merge inbound to m-c

This commit is contained in:
Wes Kocher 2014-05-22 17:30:30 -07:00
commit e4bc303ace
184 changed files with 7566 additions and 5164 deletions

View File

@ -569,6 +569,15 @@ nsContentList::GetSupportedNames(unsigned aFlags, nsTArray<nsString>& aNames)
nsAutoTArray<nsIAtom*, 8> atoms;
for (uint32_t i = 0; i < mElements.Length(); ++i) {
nsIContent *content = mElements.ElementAt(i);
if (content->HasID()) {
nsIAtom* id = content->GetID();
MOZ_ASSERT(id != nsGkAtoms::_empty,
"Empty ids don't get atomized");
if (!atoms.Contains(id)) {
atoms.AppendElement(id);
}
}
nsGenericHTMLElement* el = nsGenericHTMLElement::FromContent(content);
if (el) {
// XXXbz should we be checking for particular tags here? How
@ -585,14 +594,6 @@ nsContentList::GetSupportedNames(unsigned aFlags, nsTArray<nsString>& aNames)
}
}
}
if (content->HasID()) {
nsIAtom* id = content->GetID();
MOZ_ASSERT(id != nsGkAtoms::_empty,
"Empty ids don't get atomized");
if (!atoms.Contains(id)) {
atoms.AppendElement(id);
}
}
}
aNames.SetCapacity(atoms.Length());

View File

@ -1973,6 +1973,7 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
if (mUploadTransferred < mUploadTotal) {
mUploadTransferred = mUploadTotal;
mProgressSinceLastProgressEvent = true;
mUploadLengthComputable = true;
MaybeDispatchProgressEvents(true);
}
mUploadComplete = true;

View File

@ -37,6 +37,9 @@ function logEvent(evt) {
if (evt.type == "loadstart") {
uploadTotal = evt.total
} else {
if (evt.type == "progress") {
ok(evt.lengthComputable, "event(" + evt.type + ").lengthComputable should be true.");
}
is(evt.total, uploadTotal, "event(" + evt.type + ").total should not change during upload.");
}
}

View File

@ -47,8 +47,8 @@ is(names[2], "2", "Entry 3")
is(names[3], "3", "Entry 4")
is(names[4], "x", "Entry 5")
is(names[5], "y", "Entry 6")
is(names[6], "z", "Entry 7")
is(names[7], "w", "Entry 8")
is(names[6], "w", "Entry 7")
is(names[7], "z", "Entry 8")
is(names[8], "something", "Entry 9")
</script>
</pre>

View File

@ -67,6 +67,28 @@ HTMLAllCollection::Collection()
return mCollection;
}
static bool
IsAllNamedElement(nsIContent* aContent)
{
nsIAtom* tag = aContent->Tag();
return
tag == nsGkAtoms::a ||
tag == nsGkAtoms::applet ||
tag == nsGkAtoms::button ||
tag == nsGkAtoms::embed ||
tag == nsGkAtoms::form ||
tag == nsGkAtoms::iframe ||
tag == nsGkAtoms::img ||
tag == nsGkAtoms::input ||
tag == nsGkAtoms::map ||
tag == nsGkAtoms::meta ||
tag == nsGkAtoms::object ||
tag == nsGkAtoms::select ||
tag == nsGkAtoms::textarea ||
tag == nsGkAtoms::frame ||
tag == nsGkAtoms::frameset;
}
static bool
DocAllResultMatch(nsIContent* aContent, int32_t aNamespaceID, nsIAtom* aAtom,
void* aData)
@ -80,20 +102,7 @@ DocAllResultMatch(nsIContent* aContent, int32_t aNamespaceID, nsIAtom* aAtom,
return false;
}
nsIAtom* tag = elm->Tag();
if (tag != nsGkAtoms::a &&
tag != nsGkAtoms::applet &&
tag != nsGkAtoms::button &&
tag != nsGkAtoms::embed &&
tag != nsGkAtoms::form &&
tag != nsGkAtoms::iframe &&
tag != nsGkAtoms::img &&
tag != nsGkAtoms::input &&
tag != nsGkAtoms::map &&
tag != nsGkAtoms::meta &&
tag != nsGkAtoms::object &&
tag != nsGkAtoms::select &&
tag != nsGkAtoms::textarea) {
if (!IsAllNamedElement(elm)) {
return false;
}
@ -159,6 +168,51 @@ HTMLAllCollection::NamedGetter(const nsAString& aID,
aResult.SetNull();
}
void
HTMLAllCollection::GetSupportedNames(unsigned aFlags, nsTArray<nsString>& aNames)
{
if (!(aFlags & JSITER_HIDDEN)) {
return;
}
// XXXbz this is very similar to nsContentList::GetSupportedNames,
// but has to check IsAllNamedElement for the name case.
nsAutoTArray<nsIAtom*, 8> atoms;
for (uint32_t i = 0; i < Length(); ++i) {
nsIContent *content = Item(i);
if (content->HasID()) {
nsIAtom* id = content->GetID();
MOZ_ASSERT(id != nsGkAtoms::_empty,
"Empty ids don't get atomized");
if (!atoms.Contains(id)) {
atoms.AppendElement(id);
}
}
nsGenericHTMLElement* el = nsGenericHTMLElement::FromContent(content);
if (el) {
// Note: nsINode::HasName means the name is exposed on the document,
// which is false for options, so we don't check it here.
const nsAttrValue* val = el->GetParsedAttr(nsGkAtoms::name);
if (val && val->Type() == nsAttrValue::eAtom &&
IsAllNamedElement(content)) {
nsIAtom* name = val->GetAtomValue();
MOZ_ASSERT(name != nsGkAtoms::_empty,
"Empty names don't get atomized");
if (!atoms.Contains(name)) {
atoms.AppendElement(name);
}
}
}
}
aNames.SetCapacity(atoms.Length());
for (uint32_t i = 0; i < atoms.Length(); ++i) {
aNames.AppendElement(nsDependentAtomString(atoms[i]));
}
}
JSObject*
HTMLAllCollection::WrapObject(JSContext* aCx)
{

View File

@ -64,9 +64,7 @@ public:
void NamedGetter(const nsAString& aName,
bool& aFound,
Nullable<OwningNodeOrHTMLCollection>& aResult);
void GetSupportedNames(unsigned flags, nsTArray<nsString>& aNames)
{
}
void GetSupportedNames(unsigned aFlags, nsTArray<nsString>& aNames);
bool NameIsEnumerable(const nsAString& aName)
{
return false;

View File

@ -78,3 +78,5 @@ skip-if = buildapp == 'b2g' || e10s
[test_bug871161.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
support-files = file_bug871161-1.html file_bug871161-2.html
[test_bug1013316.html]

View File

@ -0,0 +1,46 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1013316
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1013316</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">
/** Test for Bug 1013316 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
is(Object.keys(document.all).length, 15, "We have 15 indexed props");
var props = Object.getOwnPropertyNames(document.all);
is(props.length, 20, "Should have five names");
is(props[15], "display", "display first");
is(props[16], "content", "content second");
is(props[17], "bar", "bar third");
is(props[18], "foo", "foo fourth");
is(props[19], "test", "test fifth");
is(Object.keys(document.images).length, 2, "We have 2 indexed props");
props = Object.getOwnPropertyNames(document.images);
is(props.length, 5, "Should have 3 names");
is(props[2], "display", "display first on document.images");
is(props[3], "bar", "bar second on document.images");
is(props[4], "foo", "foo third on document.images");
SimpleTest.finish();
})
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1013316">Mozilla Bug 1013316</a>
<p id="display"></p>
<div id="content" style="display: none">
<img id="display">
<img name="foo" id="bar">
<div name="baz">
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -121,7 +121,7 @@ var elementNames =
'optgroup','button','span','strike','strong','td'].sort();
var hasName =
['applet','a','embed','form','iframe','img','input','object','textarea',
'select','map','meta','button'].sort();
'select','map','meta','button','frame','frameset'].sort();
elementNames.forEach(function (name) {
nameval = 'namefor' + name;

View File

@ -430,22 +430,29 @@ AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer,
DecodeSuccessCallback& aSuccessCallback,
const Optional<OwningNonNull<DecodeErrorCallback> >& aFailureCallback)
{
AutoJSAPI jsapi;
JSContext* cx = jsapi.cx();
JSAutoCompartment ac(cx, aBuffer.Obj());
// Neuter the array buffer
size_t length = aBuffer.Length();
JS::RootedObject obj(cx, aBuffer.Obj());
uint8_t* data = static_cast<uint8_t*>(JS_StealArrayBufferContents(cx, obj));
// Sniff the content of the media.
// Failed type sniffing will be handled by AsyncDecodeMedia.
nsAutoCString contentType;
NS_SniffContent(NS_DATA_SNIFFER_CATEGORY, nullptr,
aBuffer.Data(), aBuffer.Length(),
contentType);
NS_SniffContent(NS_DATA_SNIFFER_CATEGORY, nullptr, data, length, contentType);
nsRefPtr<DecodeErrorCallback> failureCallback;
if (aFailureCallback.WasPassed()) {
failureCallback = &aFailureCallback.Value();
}
nsRefPtr<WebAudioDecodeJob> job(
new WebAudioDecodeJob(contentType, this, aBuffer,
new WebAudioDecodeJob(contentType, this,
&aSuccessCallback, failureCallback));
mDecoder.AsyncDecodeMedia(contentType.get(),
aBuffer.Data(), aBuffer.Length(), *job);
mDecoder.AsyncDecodeMedia(contentType.get(), data, length, *job);
// Transfer the ownership to mDecodeJobs
mDecodeJobs.AppendElement(job);
}

View File

@ -30,7 +30,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebAudioDecodeJob)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutput)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuccessCallback)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFailureCallback)
tmp->mArrayBuffer = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebAudioDecodeJob)
@ -42,9 +41,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebAudioDecodeJob)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WebAudioDecodeJob)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mArrayBuffer)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebAudioDecodeJob, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebAudioDecodeJob, Release)
@ -143,6 +140,7 @@ private:
// Destruct MediaDecoderReader first.
mDecoderReader = nullptr;
mBufferDecoder = nullptr;
JS_free(nullptr, mBuffer);
}
private:
@ -482,7 +480,6 @@ MediaBufferDecoder::EnsureThreadPoolInitialized()
WebAudioDecodeJob::WebAudioDecodeJob(const nsACString& aContentType,
AudioContext* aContext,
const ArrayBuffer& aBuffer,
DecodeSuccessCallback* aSuccessCallback,
DecodeErrorCallback* aFailureCallback)
: mContentType(aContentType)
@ -495,18 +492,12 @@ WebAudioDecodeJob::WebAudioDecodeJob(const nsACString& aContentType,
MOZ_ASSERT(aSuccessCallback);
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_CTOR(WebAudioDecodeJob);
mArrayBuffer = aBuffer.Obj();
mozilla::HoldJSObjects(this);
}
WebAudioDecodeJob::~WebAudioDecodeJob()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_DTOR(WebAudioDecodeJob);
mArrayBuffer = nullptr;
mozilla::DropJSObjects(this);
}
void

View File

@ -32,7 +32,6 @@ struct WebAudioDecodeJob MOZ_FINAL
// The callbacks are only necessary for asynchronous operation.
WebAudioDecodeJob(const nsACString& aContentType,
dom::AudioContext* aContext,
const dom::ArrayBuffer& aBuffer,
dom::DecodeSuccessCallback* aSuccessCallback = nullptr,
dom::DecodeErrorCallback* aFailureCallback = nullptr);
~WebAudioDecodeJob();
@ -59,7 +58,6 @@ struct WebAudioDecodeJob MOZ_FINAL
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
JS::Heap<JSObject*> mArrayBuffer;
nsCString mContentType;
uint32_t mWriteIndex;
nsRefPtr<dom::AudioContext> mContext;

View File

@ -311,6 +311,9 @@ function runResampling(test, response, callback) {
}
function runTest(test, response, callback) {
// We need to copy the array here, because decodeAudioData is going to neuter
// the array.
var compressedAudio = response.slice(0);
var expectCallback = false;
var cx = new OfflineAudioContext(test.numberOfChannels || 1,
test.frames || 1, test.sampleRate);
@ -322,7 +325,7 @@ function runTest(test, response, callback) {
test.expectedBuffer = asyncResult;
test.nativeContext = cx;
runResampling(test, response, callback);
runResampling(test, compressedAudio, callback);
}, function onFailure() {
ok(expectCallback, "Failure callback should fire asynchronously");
ok(!test.valid, "Did expect failure for test " + test.url);

View File

@ -420,7 +420,11 @@ nsresult LoadInfo::UpdateSystemLoad()
return NS_OK;
#elif defined(__DragonFly__) || defined(__FreeBSD__) \
|| defined(__NetBSD__) || defined(__OpenBSD__)
#if defined(__NetBSD__)
uint64_t cp_time[CPUSTATES];
#else
long cp_time[CPUSTATES];
#endif // __NetBSD__
size_t sz = sizeof(cp_time);
#ifdef KERN_CP_TIME
int mib[] = {
@ -431,7 +435,7 @@ nsresult LoadInfo::UpdateSystemLoad()
if (sysctl(mib, miblen, &cp_time, &sz, NULL, 0)) {
#else
if (sysctlbyname("kern.cp_time", &cp_time, &sz, NULL, 0)) {
#endif
#endif // KERN_CP_TIME
LOG(("sysctl kern.cp_time failed"));
return NS_ERROR_FAILURE;
}

View File

@ -2912,16 +2912,6 @@ AsmJSCacheOpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
aSize, aMemory, aHandle);
}
static void
OnLargeAllocationFailure()
{
nsCOMPtr<nsIObserverService> os =
mozilla::services::GetObserverService();
if (os) {
os->NotifyObservers(nullptr, "memory-pressure", MOZ_UTF16("heap-minimize"));
}
}
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
void
@ -2981,8 +2971,6 @@ nsJSContext::EnsureStatics()
};
JS::SetAsmJSCacheOps(sRuntime, &asmJSCacheOps);
JS::SetLargeAllocationFailureCallback(sRuntime, OnLargeAllocationFailure);
// Set these global xpconnect options...
Preferences::RegisterCallbackAndCall(ReportAllJSExceptionsPrefChangedCallback,
"dom.report_all_js_exceptions");

View File

@ -1344,8 +1344,18 @@ class CGAbstractMethod(CGThing):
return self._define(True)
return "%s%s%s(%s);\n" % (self._template(), self._decorators(), self.name, self._argstring(True))
def indent_body(self, body):
"""
Indent the code returned by self.definition_body(). Most classes
simply indent everything two spaces. This is here for
CGRegisterProtos, which needs custom indentation.
"""
return indent(body)
def _define(self, fromDeclare=False):
return self.definition_prologue(fromDeclare) + self.definition_body() + self.definition_epilogue()
return (self.definition_prologue(fromDeclare) +
self.indent_body(self.definition_body()) +
self.definition_epilogue())
def define(self):
return "" if self.inline else self._define()
@ -1386,7 +1396,7 @@ class CGAbstractClassHook(CGAbstractStaticMethod):
def definition_body_prologue(self):
return ("\n" # BOGUS extra blank line at start of function
" %s* self = UnwrapDOMObject<%s>(obj);\n" %
"%s* self = UnwrapDOMObject<%s>(obj);\n" %
(self.descriptor.nativeType, self.descriptor.nativeType))
def definition_body(self):
@ -1402,7 +1412,7 @@ class CGGetJSClassMethod(CGAbstractMethod):
[])
def definition_body(self):
return " return Class.ToJSClass();\n"
return "return Class.ToJSClass();\n"
class CGAddPropertyHook(CGAbstractClassHook):
@ -1419,13 +1429,13 @@ class CGAddPropertyHook(CGAbstractClassHook):
def generate_code(self):
assert self.descriptor.wrapperCache
return indent(dedent("""
return dedent("""
// We don't want to preserve if we don't have a wrapper.
if (self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
"""))
""")
def DeferredFinalizeSmartPtr(descriptor):
@ -1459,7 +1469,7 @@ class CGClassFinalizeHook(CGAbstractClassHook):
'void', args)
def generate_code(self):
return indent(finalizeHook(self.descriptor, self.name, self.args[0].name).define())
return finalizeHook(self.descriptor, self.name, self.args[0].name).define()
class CGClassConstructor(CGAbstractStaticMethod):
@ -1531,7 +1541,7 @@ class CGClassConstructor(CGAbstractStaticMethod):
callGenerator = CGMethodCall(nativeName, True, self.descriptor,
self._ctor, isConstructor=True,
constructorName=ctorName)
return indent(preamble) + callGenerator.define()
return preamble + callGenerator.define()
# Encapsulate the constructor in a helper method to share genConstructorBody with CGJSImplMethod.
@ -1548,7 +1558,7 @@ class CGConstructNavigatorObjectHelper(CGAbstractStaticMethod):
CGAbstractStaticMethod.__init__(self, descriptor, name, rtype, args)
def definition_body(self):
return indent(genConstructorBody(self.descriptor))
return genConstructorBody(self.descriptor)
class CGConstructNavigatorObject(CGAbstractMethod):
@ -1564,7 +1574,7 @@ class CGConstructNavigatorObject(CGAbstractMethod):
if not self.descriptor.interface.isJSImplemented():
raise TypeError("Only JS-implemented classes are currently supported "
"on navigator. See bug 856820.")
return indent(fill(
return fill(
"""
GlobalObject global(aCx, aObj);
if (global.Failed()) {
@ -1585,7 +1595,7 @@ class CGConstructNavigatorObject(CGAbstractMethod):
}
return &v.toObject();
""",
descriptorName=self.descriptor.name))
descriptorName=self.descriptor.name)
class CGClassConstructHookHolder(CGGeneric):
@ -1684,7 +1694,7 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod):
JS::Rooted<JSObject*> instance(cx, &vp.toObject());
""")
if self.descriptor.interface.hasInterfacePrototypeObject():
return indent(
return (
header +
fill(
"""
@ -1736,7 +1746,7 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod):
name=iface.identifier.name,
setBp=setBp)
hasInstanceCode += "return true;\n"
return indent(header + hasInstanceCode)
return header + hasInstanceCode
def isChromeOnly(m):
@ -2524,11 +2534,10 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
name=self.descriptor.name))
else:
setUnforgeableHolder = None
functionBody = CGList(
return CGList(
[CGGeneric(getParentProto), CGGeneric(getConstructorProto), initIds,
prefCache, createUnforgeableHolder, CGGeneric(call), setUnforgeableHolder],
"\n")
return CGIndenter(functionBody).define()
"\n").define()
class CGGetPerInterfaceObject(CGAbstractMethod):
@ -2546,7 +2555,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
def definition_body(self):
# BOGUS extra blank line at the beginning of the code below
# BOGUS - should be a blank line between an if-block and following comment below
return indent(fill(
return fill(
"""
/* Make sure our global is sane. Hopefully we can remove this sometime */
@ -2568,7 +2577,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
*/
return JS::Handle<JSObject*>::fromMarkedLocation(protoAndIfaceCache.EntrySlotMustExist(${id}).address());
""",
id=self.id))
id=self.id)
class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
@ -2581,12 +2590,12 @@ class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
def definition_body(self):
# BOGUS extra blank line at start of method
return indent(dedent("""
return dedent("""
/* Get the interface prototype object for this class. This will create the
object as needed. */
bool aDefineOnGlobal = true;
""")) + CGGetPerInterfaceObject.definition_body(self)
""") + CGGetPerInterfaceObject.definition_body(self)
class CGGetConstructorObjectMethod(CGGetPerInterfaceObject):
@ -2601,11 +2610,11 @@ class CGGetConstructorObjectMethod(CGGetPerInterfaceObject):
def definition_body(self):
# BOGUS extra blank line at start of method
return indent(dedent("""
return dedent("""
/* Get the interface object for this class. This will create the object as
needed. */
""")) + CGGetPerInterfaceObject.definition_body(self)
""") + CGGetPerInterfaceObject.definition_body(self)
class CGDefineDOMInterfaceMethod(CGAbstractMethod):
@ -2632,7 +2641,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
def definition_body(self):
if len(self.descriptor.interface.namedConstructors) > 0:
getConstructor = indent(dedent("""
getConstructor = dedent("""
JSObject* interfaceObject = GetConstructorObject(aCx, aGlobal, aDefineOnGlobal);
if (!interfaceObject) {
return nullptr;
@ -2644,9 +2653,9 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
}
}
return interfaceObject;
"""))
""")
else:
getConstructor = " return GetConstructorObject(aCx, aGlobal, aDefineOnGlobal);\n"
getConstructor = "return GetConstructorObject(aCx, aGlobal, aDefineOnGlobal);\n"
return getConstructor
@ -2680,10 +2689,9 @@ class CGConstructorEnabled(CGAbstractMethod):
conditions.append("%s(aCx, aObj)" % availableIn)
# We should really have some conditions
assert len(conditions)
body = CGWrapper(CGList((CGGeneric(cond) for cond in conditions),
return CGWrapper(CGList((CGGeneric(cond) for cond in conditions),
" &&\n"),
pre="return ", post=";\n", reindent=True)
return CGIndenter(body).define()
pre="return ", post=";\n", reindent=True).define()
def CreateBindingJSObject(descriptor, properties, parent):
@ -2797,11 +2805,11 @@ def AssertInheritanceChain(descriptor):
while iface:
desc = descriptor.getDescriptor(iface.identifier.name)
asserts += (
" MOZ_ASSERT(static_cast<%s*>(aObject) == \n"
" reinterpret_cast<%s*>(aObject));\n" %
"MOZ_ASSERT(static_cast<%s*>(aObject) == \n"
" reinterpret_cast<%s*>(aObject));\n" %
(desc.nativeType, desc.nativeType))
iface = iface.parent
asserts += " MOZ_ASSERT(ToSupportsIsCorrect(aObject));\n"
asserts += "MOZ_ASSERT(ToSupportsIsCorrect(aObject));\n"
return asserts
@ -2843,41 +2851,42 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
def definition_body(self):
return fill(
"""
${assertion}
MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
"nsISupports must be on our primary inheritance chain");
$*{assertion}
JS::Rooted<JSObject*> parent(aCx,
GetRealParentObject(aObject,
WrapNativeParent(aCx, aObject->GetParentObject())));
if (!parent) {
return nullptr;
MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
"nsISupports must be on our primary inheritance chain");
JS::Rooted<JSObject*> parent(aCx,
GetRealParentObject(aObject,
WrapNativeParent(aCx, aObject->GetParentObject())));
if (!parent) {
return nullptr;
}
// That might have ended up wrapping us already, due to the wonders
// of XBL. Check for that, and bail out as needed. Scope so we don't
// collide with the "obj" we declare in CreateBindingJSObject.
{
JSObject* obj = aCache->GetWrapper();
if (obj) {
return obj;
}
}
// That might have ended up wrapping us already, due to the wonders
// of XBL. Check for that, and bail out as needed. Scope so we don't
// collide with the "obj" we declare in CreateBindingJSObject.
{
JSObject* obj = aCache->GetWrapper();
if (obj) {
return obj;
}
}
JSAutoCompartment ac(aCx, parent);
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, parent));
JS::Handle<JSObject*> proto = GetProtoObject(aCx, global);
if (!proto) {
return nullptr;
}
JSAutoCompartment ac(aCx, parent);
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, parent));
JS::Handle<JSObject*> proto = GetProtoObject(aCx, global);
if (!proto) {
return nullptr;
}
$*{parent}
$*{parent}
$*{unforgeable}
$*{unforgeable}
aCache->SetWrapper(obj);
$*{slots}
return obj;
aCache->SetWrapper(obj);
$*{slots}
return obj;
""",
assertion=AssertInheritanceChain(self.descriptor),
parent=CreateBindingJSObject(self.descriptor, self.properties,
@ -2896,7 +2905,7 @@ class CGWrapMethod(CGAbstractMethod):
inline=True, templateArgs=["class T"])
def definition_body(self):
return " return Wrap(aCx, aObject, aObject);\n"
return "return Wrap(aCx, aObject, aObject);\n"
class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
@ -2919,19 +2928,20 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
def definition_body(self):
return fill(
"""
${assertions}
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
JS::Handle<JSObject*> proto = GetProtoObject(aCx, global);
if (!proto) {
return nullptr;
}
$*{assertions}
$*{global_}
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
JS::Handle<JSObject*> proto = GetProtoObject(aCx, global);
if (!proto) {
return nullptr;
}
$*{unforgeable}
$*{global_}
$*{slots}
return obj;
$*{unforgeable}
$*{slots}
return obj;
""",
assertions=AssertInheritanceChain(self.descriptor),
global_=CreateBindingJSObject(self.descriptor, self.properties,
@ -2978,36 +2988,36 @@ class CGWrapGlobalMethod(CGAbstractMethod):
return fill(
"""
${assertions}
MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
"nsISupports must be on our primary inheritance chain");
$*{assertions}
MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
"nsISupports must be on our primary inheritance chain");
JS::Rooted<JSObject*> obj(aCx);
CreateGlobal<${nativeType}, GetProtoObject>(aCx,
aObject,
aCache,
Class.ToJSClass(),
aOptions,
aPrincipal,
aInitStandardClasses,
&obj);
if (!obj) {
return nullptr;
}
JS::Rooted<JSObject*> obj(aCx);
CreateGlobal<${nativeType}, GetProtoObject>(aCx,
aObject,
aCache,
Class.ToJSClass(),
aOptions,
aPrincipal,
aInitStandardClasses,
&obj);
if (!obj) {
return nullptr;
}
// obj is a new global, so has a new compartment. Enter it
// before doing anything with it.
JSAutoCompartment ac(aCx, obj);
// obj is a new global, so has a new compartment. Enter it
// before doing anything with it.
JSAutoCompartment ac(aCx, obj);
if (!DefineProperties(aCx, obj, ${properties}, ${chromeProperties})) {
return nullptr;
}
$*{unforgeable}
if (!DefineProperties(aCx, obj, ${properties}, ${chromeProperties})) {
return nullptr;
}
$*{unforgeable}
$*{slots}
$*{fireOnNewGlobal}
$*{slots}
$*{fireOnNewGlobal}
return obj;
return obj;
""",
assertions=AssertInheritanceChain(self.descriptor),
nativeType=self.descriptor.nativeType,
@ -3045,7 +3055,7 @@ class CGUpdateMemberSlotsMethod(CGAbstractStaticMethod):
member=m.identifier.name)
body += "\nreturn true;\n"
return indent(body)
return body
class CGClearCachedValueMethod(CGAbstractMethod):
@ -3092,7 +3102,7 @@ class CGClearCachedValueMethod(CGAbstractMethod):
saveMember = ""
regetMember = ""
return indent(fill(
return fill(
"""
$*{declObj}
obj = aObject->GetWrapper();
@ -3107,7 +3117,7 @@ class CGClearCachedValueMethod(CGAbstractMethod):
noopRetval=noopRetval,
saveMember=saveMember,
slotIndex=slotIndex,
regetMember=regetMember))
regetMember=regetMember)
class CGIsPermittedMethod(CGAbstractMethod):
@ -3149,7 +3159,7 @@ class CGIsPermittedMethod(CGAbstractMethod):
for firstLetter in sorted(cases.keys()):
caseList.append(CGCase("'%s'" % firstLetter, cases[firstLetter]))
switch = CGSwitch("propFirstChar", caseList)
return indent(switch.define() + "\nreturn false;\n")
return switch.define() + "\nreturn false;\n"
builtinNames = {
IDLType.Tags.bool: 'bool',
@ -6115,11 +6125,11 @@ class CGMethodCall(CGThing):
# here for our one signature and not worry about switching
# on anything.
signature = signatures[0]
self.cgRoot = CGList([CGIndenter(getPerSignatureCall(signature))])
self.cgRoot = CGList([getPerSignatureCall(signature)])
requiredArgs = requiredArgCount(signature)
if requiredArgs > 0:
code = indent(fill( # BOGUS extra blank line
code = fill( # BOGUS extra blank line
"""
if (args.length() < ${requiredArgs}) {
@ -6127,7 +6137,7 @@ class CGMethodCall(CGThing):
}
""",
requiredArgs=requiredArgs,
methodName=methodName))
methodName=methodName)
self.cgRoot.prepend(CGGeneric(code))
return
@ -6470,8 +6480,7 @@ class CGMethodCall(CGThing):
overloadCGThings.append(
CGGeneric('MOZ_CRASH("We have an always-returning default case");\n'
'return false;\n'))
self.cgRoot = CGWrapper(CGIndenter(CGList(overloadCGThings)),
pre="\n")
self.cgRoot = CGWrapper(CGList(overloadCGThings), pre="\n")
def define(self):
return self.cgRoot.define()
@ -6612,7 +6621,7 @@ class CGAbstractBindingMethod(CGAbstractStaticMethod):
"obj", "self", self.unwrapFailureCode,
allowCrossOriginObj=self.allowCrossOriginThis))
return indent(body) + self.generate_code().define()
return body + self.generate_code().define()
def generate_code(self):
assert False # Override me
@ -6635,11 +6644,11 @@ class CGAbstractStaticBindingMethod(CGAbstractStaticMethod):
def definition_body(self):
# Make sure that "obj" is in the same compartment as "cx", since we'll
# later use it to wrap return values.
unwrap = indent(dedent("""
unwrap = dedent("""
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
"""))
""")
return unwrap + self.generate_code().define()
def generate_code(self):
@ -6671,7 +6680,7 @@ class CGGenericMethod(CGAbstractBindingMethod):
allowCrossOriginThis=allowCrossOriginThis)
def generate_code(self):
return CGGeneric(indent(dedent("""
return CGGeneric(dedent("""
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(args.calleev());
MOZ_ASSERT(info->type() == JSJitInfo::Method);
JSJitMethodOp method = info->method;
@ -6682,7 +6691,7 @@ class CGGenericMethod(CGAbstractBindingMethod):
}
#endif
return ok;
""")))
"""))
class CGSpecializedMethod(CGAbstractStaticMethod):
@ -6723,7 +6732,7 @@ class CGMethodPromiseWrapper(CGAbstractStaticMethod):
CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args)
def definition_body(self):
return indent(fill(
return fill(
"""
// Make sure to save the callee before someone maybe messes
// with rval().
@ -6736,7 +6745,7 @@ class CGMethodPromiseWrapper(CGAbstractStaticMethod):
args.rval());
""",
methodName=self.method.name,
args=", ".join(arg.name for arg in self.args)))
args=", ".join(arg.name for arg in self.args))
@staticmethod
def makeName(methodName):
@ -6773,7 +6782,7 @@ class CGJsonifierMethod(CGSpecializedMethod):
ret += ('args.rval().setObject(*result);\n'
'return true;\n')
return indent(ret)
return ret
class CGLegacyCallHook(CGAbstractBindingMethod):
@ -6819,7 +6828,7 @@ class CGNewResolveHook(CGAbstractBindingMethod):
args, getThisObj="", callArgs="")
def generate_code(self):
return CGGeneric(indent(dedent("""
return CGGeneric(dedent("""
JS::Rooted<JSPropertyDescriptor> desc(cx);
if (!self->DoNewResolve(cx, obj, id, &desc)) {
return false;
@ -6838,12 +6847,12 @@ class CGNewResolveHook(CGAbstractBindingMethod):
}
objp.set(obj);
return true;
""")))
"""))
def definition_body(self):
if self.descriptor.interface.getExtendedAttribute("Global"):
# Resolve standard classes
prefix = indent(dedent("""
prefix = dedent("""
if (!ResolveGlobal(cx, obj, id, objp)) {
return false;
}
@ -6851,7 +6860,7 @@ class CGNewResolveHook(CGAbstractBindingMethod):
return true;
}
"""))
""")
else:
prefix = ""
return prefix + CGAbstractBindingMethod.definition_body(self)
@ -6872,7 +6881,7 @@ class CGEnumerateHook(CGAbstractBindingMethod):
args, getThisObj="", callArgs="")
def generate_code(self):
return CGGeneric(indent(dedent("""
return CGGeneric(dedent("""
nsAutoTArray<nsString, 8> names;
ErrorResult rv;
self->GetOwnPropertyNames(cx, names, rv);
@ -6887,17 +6896,17 @@ class CGEnumerateHook(CGAbstractBindingMethod):
}
}
return true;
""")))
"""))
def definition_body(self):
if self.descriptor.interface.getExtendedAttribute("Global"):
# Enumerate standard classes
prefix = indent(dedent("""
prefix = dedent("""
if (!EnumerateGlobal(cx, obj)) {
return false;
}
"""))
""")
else:
prefix = ""
return prefix + CGAbstractBindingMethod.definition_body(self)
@ -6975,7 +6984,7 @@ class CGGenericGetter(CGAbstractBindingMethod):
allowCrossOriginThis=allowCrossOriginThis)
def generate_code(self):
return CGGeneric(indent(dedent("""
return CGGeneric(dedent("""
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(args.calleev());
MOZ_ASSERT(info->type() == JSJitInfo::Getter);
JSJitGetterOp getter = info->getter;
@ -6986,7 +6995,7 @@ class CGGenericGetter(CGAbstractBindingMethod):
}
#endif
return ok;
""")))
"""))
class CGSpecializedGetter(CGAbstractStaticMethod):
@ -7016,7 +7025,7 @@ class CGSpecializedGetter(CGAbstractStaticMethod):
"can't use our slot for property '%s'!" %
(self.descriptor.interface.identifier.name,
self.attr.identifier.name))
prefix = indent(fill(
prefix = fill(
"""
// Have to either root across the getter call or reget after.
JS::Rooted<JSObject*> reflector(cx);
@ -7037,13 +7046,13 @@ class CGSpecializedGetter(CGAbstractStaticMethod):
""",
slot=memberReservedSlot(self.attr),
maybeWrap=getMaybeWrapValueFuncForType(self.attr.type)))
maybeWrap=getMaybeWrapValueFuncForType(self.attr.type))
else:
prefix = ""
return (prefix +
indent(CGGetterCall(self.attr.type, nativeName,
self.descriptor, self.attr).define()))
CGGetterCall(self.attr.type, nativeName,
self.descriptor, self.attr).define())
@staticmethod
def makeNativeName(descriptor, attr):
@ -7072,8 +7081,8 @@ class CGStaticGetter(CGAbstractStaticBindingMethod):
def generate_code(self):
nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
self.attr)
return CGIndenter(CGGetterCall(self.attr.type, nativeName,
self.descriptor, self.attr))
return CGGetterCall(self.attr.type, nativeName, self.descriptor,
self.attr)
class CGGenericSetter(CGAbstractBindingMethod):
@ -7108,7 +7117,7 @@ class CGGenericSetter(CGAbstractBindingMethod):
allowCrossOriginThis=allowCrossOriginThis)
def generate_code(self):
return CGGeneric(indent(fill(
return CGGeneric(fill(
"""
if (args.length() == 0) {
return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "${name} attribute setter");
@ -7125,7 +7134,7 @@ class CGGenericSetter(CGAbstractBindingMethod):
#endif
return true;
""",
name=self.descriptor.interface.identifier.name)))
name=self.descriptor.interface.identifier.name))
class CGSpecializedSetter(CGAbstractStaticMethod):
@ -7145,8 +7154,8 @@ class CGSpecializedSetter(CGAbstractStaticMethod):
def definition_body(self):
nativeName = CGSpecializedSetter.makeNativeName(self.descriptor,
self.attr)
return CGIndenter(CGSetterCall(self.attr.type, nativeName,
self.descriptor, self.attr)).define()
return CGSetterCall(self.attr.type, nativeName, self.descriptor,
self.attr).define()
@staticmethod
def makeNativeName(descriptor, attr):
@ -7175,7 +7184,7 @@ class CGStaticSetter(CGAbstractStaticBindingMethod):
name=self.attr.identifier.name))
call = CGSetterCall(self.attr.type, nativeName, self.descriptor,
self.attr)
return CGIndenter(CGList([checkForArg, call]))
return CGList([checkForArg, call])
class CGSpecializedForwardingSetter(CGSpecializedSetter):
@ -7192,7 +7201,7 @@ class CGSpecializedForwardingSetter(CGSpecializedSetter):
# JS_GetProperty and JS_SetProperty can only deal with ASCII
assert all(ord(c) < 128 for c in attrName)
assert all(ord(c) < 128 for c in forwardToAttrName)
return indent(fill(
return fill(
"""
JS::Rooted<JS::Value> v(cx);
if (!JS_GetProperty(cx, obj, "${attr}", &v)) {
@ -7208,7 +7217,7 @@ class CGSpecializedForwardingSetter(CGSpecializedSetter):
""",
attr=attrName,
interface=self.descriptor.interface.identifier.name,
forwardToAttrName=forwardToAttrName))
forwardToAttrName=forwardToAttrName)
class CGSpecializedReplaceableSetter(CGSpecializedSetter):
@ -7223,8 +7232,8 @@ class CGSpecializedReplaceableSetter(CGSpecializedSetter):
attrName = self.attr.identifier.name
# JS_DefineProperty can only deal with ASCII
assert all(ord(c) < 128 for c in attrName)
return indent('return JS_DefineProperty(cx, obj, "%s", args[0], JSPROP_ENUMERATE);\n' %
attrName)
return ('return JS_DefineProperty(cx, obj, "%s", args[0], JSPROP_ENUMERATE);\n' %
attrName)
def memberReturnsNewObject(member):
@ -8709,7 +8718,7 @@ class CGResolveOwnProperty(CGAbstractStaticMethod):
def definition_body(self):
# BOGUS extra blank line at end of function
return " return js::GetProxyHandler(obj)->getOwnPropertyDescriptor(cx, wrapper, id, desc);\n\n"
return "return js::GetProxyHandler(obj)->getOwnPropertyDescriptor(cx, wrapper, id, desc);\n\n"
class CGResolveOwnPropertyViaNewresolve(CGAbstractBindingMethod):
@ -8729,7 +8738,7 @@ class CGResolveOwnPropertyViaNewresolve(CGAbstractBindingMethod):
callArgs="")
def generate_code(self):
return CGGeneric(indent(dedent("""
return CGGeneric(dedent("""
{
// Since we're dealing with an Xray, do the resolve on the
// underlying object first. That gives it a chance to
@ -8754,7 +8763,7 @@ class CGResolveOwnPropertyViaNewresolve(CGAbstractBindingMethod):
}
}
return self->DoNewResolve(cx, wrapper, id, desc);
""")))
"""))
class CGEnumerateOwnProperties(CGAbstractStaticMethod):
@ -8768,7 +8777,7 @@ class CGEnumerateOwnProperties(CGAbstractStaticMethod):
def definition_body(self):
# BOGUS extra newline
return " return js::GetProxyHandler(obj)->getOwnPropertyNames(cx, wrapper, props);\n\n"
return "return js::GetProxyHandler(obj)->getOwnPropertyNames(cx, wrapper, props);\n\n"
class CGEnumerateOwnPropertiesViaGetOwnPropertyNames(CGAbstractBindingMethod):
@ -8787,7 +8796,7 @@ class CGEnumerateOwnPropertiesViaGetOwnPropertyNames(CGAbstractBindingMethod):
callArgs="")
def generate_code(self):
return CGIndenter(CGGeneric(dedent("""
return CGGeneric(dedent("""
nsAutoTArray<nsString, 8> names;
ErrorResult rv;
self->GetOwnPropertyNames(cx, names, rv);
@ -8798,7 +8807,7 @@ class CGEnumerateOwnPropertiesViaGetOwnPropertyNames(CGAbstractBindingMethod):
// OK to pass null as "proxy" because it's ignored if
// shadowPrototypeProperties is true
return AppendNamedPropertyIds(cx, JS::NullPtr(), names, true, props);
""")))
"""))
class CGPrototypeTraitsClass(CGClass):
@ -9097,7 +9106,7 @@ class CGProxyIsProxy(CGAbstractMethod):
return ""
def definition_body(self):
return " return js::IsProxy(obj) && js::GetProxyHandler(obj) == DOMProxyHandler::getInstance();\n"
return "return js::IsProxy(obj) && js::GetProxyHandler(obj) == DOMProxyHandler::getInstance();\n"
class CGProxyUnwrap(CGAbstractMethod):
@ -9109,7 +9118,7 @@ class CGProxyUnwrap(CGAbstractMethod):
return ""
def definition_body(self):
return indent(fill(
return fill(
"""
MOZ_ASSERT(js::IsProxy(obj));
if (js::GetProxyHandler(obj) != DOMProxyHandler::getInstance()) {
@ -9119,7 +9128,7 @@ class CGProxyUnwrap(CGAbstractMethod):
MOZ_ASSERT(IsProxy(obj));
return static_cast<${type}*>(js::GetProxyPrivate(obj).toPrivate());
""",
type=self.descriptor.nativeType))
type=self.descriptor.nativeType)
class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod):
@ -10806,6 +10815,10 @@ class CGRegisterProtos(CGAbstractMethod):
lines.append('REGISTER_NAVIGATOR_CONSTRUCTOR("%s", %s, %s);\n' % (propName, desc.name, getCheck(desc)))
return ''.join(lines)
def indent_body(self, body):
# Don't indent the body of this method, as it's all preprocessor gunk.
return body
def definition_body(self):
return "\n" + self._defineMacro() + "\n" + self._registerProtos() + "\n" + self._undefineMacro()

View File

@ -489,6 +489,7 @@ DataStoreServiceChild.prototype = {
debug("DataStoreServiceChild init");
this._successCb = aSuccessCb;
this._errorCb = aErrorCb;
this._name = aName;
this.initDOMRequestHelper(aWindow, [ "DataStore:Get:Return:OK",
"DataStore:Get:Return:KO" ]);
@ -500,6 +501,10 @@ DataStoreServiceChild.prototype = {
receiveMessage: function(aMessage) {
debug("DataStoreServiceChild receiveMessage");
if (aMessage.data.name != this._name) {
return;
}
switch (aMessage.name) {
case 'DataStore:Get:Return:OK':
this.destroyDOMRequestHelper();

View File

@ -0,0 +1,46 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for DataStore - bug 1008044</title>
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
function ok(a, msg) {
alert((!!a ? 'OK' : 'KO') + ' ' + msg)
}
function cbError() {
alert('KO error');
}
function finish() {
alert('DONE');
}
navigator.getDataStores('foo').then(function(stores) {
if (stores[0].name != 'foo') {
ok(false, "Wrong name is received! Expected 'foo'");
}
runTest();
});
navigator.getDataStores('bar').then(function(stores) {
if (stores[0].name != 'bar') {
ok(false, "Wrong name is received! Expected 'bar'");
}
runTest();
});
var pending = 2;
function runTest() {
if (--pending == 0) {
ok(true, "Test passed!");
finish();
}
}
</script>
</body>
</html>

View File

@ -28,6 +28,7 @@ support-files =
file_transactions.html
file_basic_common.js
file_sync_common.js
file_bug1008044.html
[test_app_install.html]
[test_readonly.html]
@ -52,3 +53,4 @@ skip-if = (toolkit == 'gonk' && debug) #debug-only failure; time out
[test_bug986056.html]
[test_oop_events.html]
[test_transactions.html]
[test_bug1008044.html]

View File

@ -0,0 +1,128 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for DataStore - bug 1008044</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
var gHostedManifestURL = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_bug1008044.html';
var gApp;
function cbError() {
ok(false, "Error callback invoked");
finish();
}
function installApp() {
var request = navigator.mozApps.install(gHostedManifestURL);
request.onerror = cbError;
request.onsuccess = function() {
gApp = request.result;
runTest();
}
}
function uninstallApp() {
// Uninstall the app.
var request = navigator.mozApps.mgmt.uninstall(gApp);
request.onerror = cbError;
request.onsuccess = function() {
// All done.
info("All done");
runTest();
}
}
function testApp() {
var ifr = document.createElement('iframe');
ifr.setAttribute('mozbrowser', 'true');
ifr.setAttribute('mozapp', gApp.manifestURL);
ifr.setAttribute('src', gApp.manifest.launch_path);
var domParent = document.getElementById('container');
// Set us up to listen for messages from the app.
var listener = function(e) {
var message = e.detail.message;
if (/^OK/.exec(message)) {
ok(true, "Message from app: " + message);
} else if (/KO/.exec(message)) {
ok(false, "Message from app: " + message);
} else if (/DONE/.exec(message)) {
ok(true, "Messaging from app complete");
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
domParent.removeChild(ifr);
runTest();
}
}
// This event is triggered when the app calls "alert".
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
domParent.appendChild(ifr);
}
var tests = [
// Permissions
function() {
SpecialPowers.pushPermissions(
[{ "type": "browser", "allow": 1, "context": document },
{ "type": "embed-apps", "allow": 1, "context": document },
{ "type": "webapps-manage", "allow": 1, "context": document }], runTest);
},
// Preferences
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true],
["dom.ipc.browser_frames.oop_by_default", true],
["dom.testing.ignore_ipc_principal", true],
["dom.testing.datastore_enabled_for_hosted_apps", true]]}, runTest);
},
function() {
SpecialPowers.setAllAppsLaunchable(true);
SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
runTest();
},
// No confirmation needed when an app is installed
function() {
SpecialPowers.autoConfirmAppInstall(runTest);
},
// Installing the app
installApp,
// Run tests in app
testApp,
// Uninstall the app
uninstallApp
];
function runTest() {
if (!tests.length) {
finish();
return;
}
var test = tests.shift();
test();
}
function finish() {
SimpleTest.finish();
}
if (SpecialPowers.isMainProcess()) {
SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
}
SimpleTest.waitForExplicitFinish();
runTest();
</script>
</body>
</html>

View File

@ -18,6 +18,7 @@
#include "nsDOMJSUtils.h"
#include "WorkerPrivate.h"
#include "mozilla/ContentEvents.h"
#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/JSEventHandler.h"
#include "mozilla/Likely.h"
#include "mozilla/dom/ErrorEvent.h"
@ -35,6 +36,14 @@ JSEventHandler::JSEventHandler(nsISupports* aTarget,
{
nsCOMPtr<nsISupports> base = do_QueryInterface(aTarget);
mTarget = base.get();
// Note, we call HoldJSObjects to get CanSkip called before CC.
HoldJSObjects(this);
}
JSEventHandler::~JSEventHandler()
{
NS_ASSERTION(!mTarget, "Should have called Disconnect()!");
DropJSObjects(this);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(JSEventHandler)

View File

@ -181,10 +181,7 @@ public:
JSEventHandler(nsISupports* aTarget, nsIAtom* aType,
const TypedEventHandler& aTypedHandler);
virtual ~JSEventHandler()
{
NS_ASSERTION(!mTarget, "Should have called Disconnect()!");
}
virtual ~JSEventHandler();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS

View File

@ -37,25 +37,6 @@ RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
AppendRectToCoordArray(mTexCoords, tx0, ty0, tx1, ty1);
}
bool
RectTriangles::isSimpleQuad(gfx3DMatrix& aOutTextureTransform) const
{
if (mVertexCoords.Length() == 6 &&
mVertexCoords[0].x == 0.0f &&
mVertexCoords[0].y == 0.0f &&
mVertexCoords[5].x == 1.0f &&
mVertexCoords[5].y == 1.0f)
{
GLfloat tx0 = mTexCoords[0].x;
GLfloat ty0 = mTexCoords[0].y;
GLfloat tx1 = mTexCoords[5].x;
GLfloat ty1 = mTexCoords[5].y;
aOutTextureTransform = gfx3DMatrix::From2D(gfxMatrix(tx1 - tx0, 0, 0, ty1 - ty0, tx0, ty0));
return true;
}
return false;
}
static GLfloat
WrapTexCoord(GLfloat v)
{

View File

@ -28,13 +28,6 @@ public:
GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
bool flip_y = false);
// Returns whether this object is made of only one rect that can be drawn
// with a pre-buffered unity quad which has 0,0,1,1 as both vertex
// positions and texture coordinates.
// aOutTextureTransform returns the transform that maps 0,0,1,1 texture
// coordinates to the correct ones.
bool isSimpleQuad(gfx3DMatrix& aOutTextureTransform) const;
/**
* these return a float pointer to the start of each array respectively.
* Use it for glVertexAttribPointer calls.

View File

@ -43,12 +43,12 @@
#include "nsCocoaFeatures.h"
#endif
using namespace mozilla::gfx;
using namespace mozilla::layers;
namespace mozilla {
namespace gl {
using namespace mozilla::gfx;
using namespace mozilla::layers;
#ifdef DEBUG
unsigned GLContext::sCurrentGLContextTLS = -1;
#endif

View File

@ -16,11 +16,11 @@
#include "GeckoProfiler.h"
#include "mozilla/gfx/MacIOSurface.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace gl {
using namespace mozilla::gfx;
static bool gUseDoubleBufferedWindows = true;
class CGLLibrary

View File

@ -37,11 +37,11 @@
#include "gfxPlatformGtk.h"
#endif
using namespace mozilla::gfx;
namespace mozilla {
namespace gl {
using namespace mozilla::gfx;
GLXLibrary sGLXLibrary;
// Check that we have at least version aMajor.aMinor .

View File

@ -17,11 +17,11 @@
#include "mozilla/Preferences.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace gl {
using namespace mozilla::gfx;
WGLLibrary sWGLLib;
HWND

View File

@ -14,11 +14,11 @@
#include "mozilla/gfx/2D.h"
#include "gfx2DGlue.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace gl {
using namespace mozilla::gfx;
GLReadTexImageHelper::GLReadTexImageHelper(GLContext* gl)
: mGL(gl)
{

View File

@ -22,11 +22,11 @@
#include "ScopedGLHelpers.h"
#include "gfx2DGlue.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace gl {
using namespace mozilla::gfx;
GLScreenBuffer*
GLScreenBuffer::Create(GLContext* gl,
const gfx::IntSize& size,

View File

@ -7,11 +7,11 @@
#include "GLContextEGL.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace gl {
using namespace mozilla::gfx;
SurfaceFactory_ANGLEShareHandle*
SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl,
ID3D10Device1* d3d,

View File

@ -29,10 +29,11 @@
#define DEBUG_PRINT(...) do { } while (0)
#endif
using namespace mozilla;
namespace mozilla {
namespace gl {
using namespace mozilla::gfx;
using namespace gl;
using namespace layers;
using namespace mozilla::layers;
using namespace android;
SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL,
@ -211,3 +212,6 @@ SharedSurface_Gralloc::WaitForBufferOwnership()
{
mTextureClient->WaitReleaseFence();
}
}
}

View File

@ -24,12 +24,12 @@
#include "nsSize.h" // for nsIntSize
#include "gfxUtils.h"
using namespace mozilla::gfx;
using namespace mozilla::gl;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
using namespace mozilla::gl;
CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData) :
CanvasLayer(aLayerManager, aImplData)
, mStream(nullptr)

View File

@ -36,14 +36,12 @@
#include "D3D9SurfaceImage.h"
#endif
using namespace mozilla::ipc;
using namespace android;
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::ipc;
using namespace android;
using namespace mozilla::gfx;
Atomic<int32_t> Image::sSerialCounter(0);

View File

@ -23,11 +23,11 @@
#include "limits.h"
#include "mozilla/Assertions.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
enum LayerSortOrder {
Undefined,
ABeforeB,

View File

@ -33,22 +33,21 @@
#include "nsStyleStruct.h" // for nsTimingFunction, etc
#include "gfxPrefs.h"
using namespace mozilla::layers;
using namespace mozilla::gfx;
typedef FrameMetrics::ViewID ViewID;
const ViewID FrameMetrics::NULL_SCROLL_ID = 0;
uint8_t gLayerManagerLayerBuilder;
namespace mozilla {
namespace layers {
FILE*
FILEOrDefault(FILE* aFile)
{
return aFile ? aFile : stderr;
}
namespace mozilla {
namespace layers {
typedef FrameMetrics::ViewID ViewID;
const ViewID FrameMetrics::NULL_SCROLL_ID = 0;
using namespace mozilla::gfx;
//--------------------------------------------------
// LayerManager
@ -1347,7 +1346,7 @@ Layer::PrintInfo(nsACString& aTo, const char* aPrefix)
aTo += aPrefix;
aTo += nsPrintfCString("%s%s (0x%p)", mManager->Name(), Name(), this);
::PrintInfo(aTo, AsLayerComposite());
layers::PrintInfo(aTo, AsLayerComposite());
if (mUseClipRect) {
AppendToString(aTo, mClipRect, " [clip=", "]");

View File

@ -126,11 +126,11 @@ WidgetModifiersToDOMModifiers(mozilla::Modifiers aModifiers)
}
using namespace mozilla::css;
namespace mozilla {
namespace layers {
using namespace mozilla::css;
typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior;
typedef GeckoContentController::APZStateChange APZStateChange;

View File

@ -51,12 +51,11 @@
class nsIWidget;
using namespace mozilla::dom;
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
/**
* Clips to the smallest device-pixel-aligned rectangle containing aRect
* in user space.

View File

@ -13,11 +13,11 @@
#include "mozilla/layers/ISurfaceAllocator.h"
#include "AutoMaskData.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
bool
GetMaskData(Layer* aMaskLayer,
const Point& aDeviceOffset,

View File

@ -28,11 +28,11 @@
#include "AutoMaskData.h"
#include "gfx2DGlue.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
static nsIntRegion
IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext)
{

View File

@ -8,8 +8,9 @@
#include "gfxXlibSurface.h"
#include "gfx2DGlue.h"
using namespace mozilla;
using namespace mozilla::layers;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
X11TextureSourceBasic::X11TextureSourceBasic(BasicCompositor* aCompositor, gfxXlibSurface* aSurface)
@ -67,3 +68,6 @@ X11TextureSourceBasic::ContentTypeToSurfaceFormat(gfxContentType aType)
return SurfaceFormat::UNKNOWN;
}
}
}
}

View File

@ -13,11 +13,11 @@
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
#include "nsRegion.h" // for nsIntRegion
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
class ClientColorLayer : public ColorLayer,
public ClientLayer {
public:

View File

@ -18,11 +18,11 @@
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
#include "nsRegion.h" // for nsIntRegion
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
class ClientImageLayer : public ImageLayer,
public ClientLayer {
public:

View File

@ -32,12 +32,11 @@
#include "AndroidBridge.h"
#endif
using namespace mozilla::dom;
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
: mPhase(PHASE_NONE)
, mWidget(aWidget)
@ -131,8 +130,8 @@ ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
// If the last transaction was incomplete (a failed DoEmptyTransaction),
// don't signal a new transaction to ShadowLayerForwarder. Carry on adding
// to the previous transaction.
ScreenOrientation orientation;
if (TabChild* window = mWidget->GetOwningTabChild()) {
dom::ScreenOrientation orientation;
if (dom::TabChild* window = mWidget->GetOwningTabChild()) {
orientation = window->GetOrientation();
} else {
hal::ScreenConfiguration currentConfig;
@ -150,7 +149,7 @@ ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
// a chance to repaint, so we have to ensure that it's all valid
// and not rotated.
if (mWidget) {
if (TabChild* window = mWidget->GetOwningTabChild()) {
if (dom::TabChild* window = mWidget->GetOwningTabChild()) {
mCompositorMightResample = window->IsAsyncPanZoomEnabled();
}
}

View File

@ -25,11 +25,11 @@
#include "nsRect.h" // for nsIntRect
#include "gfx2DGlue.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
void
ClientThebesLayer::PaintThebes()
{

View File

@ -18,11 +18,11 @@
#include "mozilla/layers/TextureD3D9.h"
#endif
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
/**
* IPDL actor used by CompositableClient to match with its corresponding
* CompositableHost on the compositor side.

View File

@ -36,11 +36,11 @@
#include "GrallocImages.h"
#endif
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
/**
* Handle RemoveTextureFromCompositableAsync() transaction.
*/

View File

@ -32,11 +32,11 @@
#define ALOG(...) __android_log_print(ANDROID_LOG_INFO, "SimpleTiles", __VA_ARGS__)
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
void
SimpleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
const nsIntRegion& aPaintRegion,

View File

@ -58,12 +58,13 @@
#define RECYCLE_LOG(...) do { } while (0)
#endif
using namespace mozilla::gl;
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::ipc;
using namespace mozilla::gl;
using namespace mozilla::gfx;
/**
* TextureChild is the content-side incarnation of the PTexture IPDL actor.
*
@ -439,7 +440,7 @@ bool
ShmemTextureClient::Allocate(uint32_t aSize)
{
MOZ_ASSERT(mValid);
ipc::SharedMemory::SharedMemoryType memType = OptimalShmemType();
SharedMemory::SharedMemoryType memType = OptimalShmemType();
mAllocated = GetAllocator()->AllocUnsafeShmem(aSize, memType, &mShmem);
return mAllocated;
}

View File

@ -41,19 +41,18 @@
struct nsCSSValueSharedList;
using namespace mozilla::dom;
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
enum Op { Resolve, Detach };
static bool
IsSameDimension(ScreenOrientation o1, ScreenOrientation o2)
IsSameDimension(dom::ScreenOrientation o1, dom::ScreenOrientation o2)
{
bool isO1portrait = (o1 == eScreenOrientation_PortraitPrimary || o1 == eScreenOrientation_PortraitSecondary);
bool isO2portrait = (o2 == eScreenOrientation_PortraitPrimary || o2 == eScreenOrientation_PortraitSecondary);
bool isO1portrait = (o1 == dom::eScreenOrientation_PortraitPrimary || o1 == dom::eScreenOrientation_PortraitSecondary);
bool isO2portrait = (o2 == dom::eScreenOrientation_PortraitPrimary || o2 == dom::eScreenOrientation_PortraitSecondary);
return !(isO1portrait ^ isO2portrait);
}
@ -73,8 +72,8 @@ WalkTheTree(Layer* aLayer,
if (const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(ref->GetReferentId())) {
if (Layer* referent = state->mRoot) {
if (!ref->GetVisibleRegion().IsEmpty()) {
ScreenOrientation chromeOrientation = aTargetConfig.orientation();
ScreenOrientation contentOrientation = state->mTargetConfig.orientation();
dom::ScreenOrientation chromeOrientation = aTargetConfig.orientation();
dom::ScreenOrientation contentOrientation = state->mTargetConfig.orientation();
if (!IsSameDimension(chromeOrientation, contentOrientation) &&
ContentMightReflowOnOrientationChange(aTargetConfig.clientBounds())) {
aReady = false;

View File

@ -20,8 +20,9 @@
#include "nsPoint.h" // for nsIntPoint
#include "nsString.h" // for nsAutoCString
using namespace mozilla;
using namespace mozilla::layers;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
CanvasLayerComposite::CanvasLayerComposite(LayerManagerComposite* aManager)
@ -144,3 +145,5 @@ CanvasLayerComposite::PrintInfo(nsACString& aTo, const char* aPrefix)
return aTo;
}
}
}

View File

@ -25,11 +25,11 @@
#include "nsRect.h" // for nsIntRect
#include "nsString.h" // for nsAutoCString
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
ImageLayerComposite::ImageLayerComposite(LayerManagerComposite* aManager)
: ImageLayer(aManager, nullptr)
, LayerComposite(aManager)

View File

@ -13,8 +13,9 @@
#include "gfxXlibSurface.h"
#include "gfx2DGlue.h"
using namespace mozilla;
using namespace mozilla::layers;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
X11TextureHost::X11TextureHost(TextureFlags aFlags,
@ -84,3 +85,6 @@ X11TextureHost::GetSize() const
{
return ToIntSize(mSurface->GetSize());
}
}
}

View File

@ -15,12 +15,12 @@
#include "GLContext.h"
#include "gfxPrefs.h"
using namespace mozilla::gl;
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gl;
using namespace mozilla::gfx;
CanvasLayerD3D10::CanvasLayerD3D10(LayerManagerD3D10 *aManager)
: CanvasLayer(aManager, nullptr)
, LayerD3D10(aManager)

View File

@ -14,11 +14,11 @@
#include "gfxWindowsPlatform.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
static already_AddRefed<ID3D10Texture2D>
DataToTexture(ID3D10Device *aDevice,
unsigned char *data,

View File

@ -31,13 +31,12 @@
#include "DXGI1_2.h"
#endif
using namespace std;
using namespace mozilla::dom;
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace std;
using namespace mozilla::gfx;
struct Vertex
{
float position[2];

View File

@ -26,11 +26,11 @@
#include "mozilla/Preferences.h"
#include "mozilla/gfx/2D.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
ThebesLayerD3D10::ThebesLayerD3D10(LayerManagerD3D10 *aManager)
: ThebesLayer(aManager, nullptr)
, LayerD3D10(aManager)

View File

@ -17,11 +17,11 @@
#include "mozilla/layers/LayerManagerComposite.h"
#include "gfxPrefs.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
CompositorD3D9::CompositorD3D9(PCompositorParent* aParent, nsIWidget *aWidget)
: Compositor(aParent)
, mWidget(aWidget)

View File

@ -18,11 +18,11 @@
#include "TextureD3D9.h"
#include "mozilla/gfx/Point.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
const LPCWSTR kClassName = L"D3D9WindowClass";
#define USE_D3D9EX

View File

@ -54,15 +54,14 @@
#include "mozilla/Hal.h"
#include "mozilla/HalTypes.h"
namespace mozilla {
namespace layers {
using namespace base;
using namespace mozilla;
using namespace mozilla::ipc;
using namespace mozilla::gfx;
using namespace std;
namespace mozilla {
namespace layers {
CompositorParent::LayerTreeState::LayerTreeState()
: mParent(nullptr)
, mLayerManager(nullptr)

View File

@ -41,11 +41,6 @@
struct nsIntRect;
using base::Thread;
using base::ProcessHandle;
using namespace mozilla::ipc;
using namespace mozilla::gfx;
namespace mozilla {
namespace ipc {
class Shmem;
@ -53,6 +48,11 @@ class Shmem;
namespace layers {
using base::Thread;
using base::ProcessHandle;
using namespace mozilla::ipc;
using namespace mozilla::gfx;
typedef std::vector<CompositableOperation> OpVector;
struct CompositableTransaction

View File

@ -35,12 +35,12 @@
#include "mozilla/layers/TextureHost.h"
#include "nsThreadUtils.h"
using namespace mozilla::ipc;
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::ipc;
using namespace mozilla::gfx;
ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop, Transport* aTransport)
: mMessageLoop(aLoop)
, mTransport(aTransport)

View File

@ -36,10 +36,6 @@
struct nsIntPoint;
using namespace mozilla::ipc;
using namespace mozilla::gl;
using namespace mozilla::dom;
namespace mozilla {
namespace ipc {
class Shmem;
@ -47,6 +43,9 @@ class Shmem;
namespace layers {
using namespace mozilla::ipc;
using namespace mozilla::gl;
class ClientTiledLayerBuffer;
typedef nsTArray<SurfaceDescriptor> BufferArray;
@ -64,7 +63,7 @@ public:
{}
void Begin(const nsIntRect& aTargetBounds, ScreenRotation aRotation,
const nsIntRect& aClientBounds, ScreenOrientation aOrientation)
const nsIntRect& aClientBounds, dom::ScreenOrientation aOrientation)
{
mOpen = true;
mTargetBounds = aTargetBounds;
@ -142,7 +141,7 @@ public:
nsIntRect mTargetBounds;
ScreenRotation mTargetRotation;
nsIntRect mClientBounds;
ScreenOrientation mTargetOrientation;
dom::ScreenOrientation mTargetOrientation;
bool mSwapRequired;
private:
@ -187,7 +186,7 @@ void
ShadowLayerForwarder::BeginTransaction(const nsIntRect& aTargetBounds,
ScreenRotation aRotation,
const nsIntRect& aClientBounds,
ScreenOrientation aOrientation)
dom::ScreenOrientation aOrientation)
{
NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to");
NS_ABORT_IF_FALSE(mTxn->Finished(), "uncommitted txn?");

View File

@ -22,11 +22,11 @@
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "SBMChild", ## args)
#endif
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
// Singleton
SharedBufferManagerChild* SharedBufferManagerChild::sSharedBufferManagerChildSingleton = nullptr;
SharedBufferManagerParent* SharedBufferManagerChild::sSharedBufferManagerParentSingleton = nullptr;

View File

@ -8,10 +8,11 @@
#include "GLReadTexImageHelper.h"
#include "mozilla/gfx/2D.h"
using namespace mozilla;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
using namespace mozilla::gl;
using namespace mozilla::layers;
CompositingRenderTargetOGL::~CompositingRenderTargetOGL()
{
@ -100,3 +101,6 @@ CompositingRenderTargetOGL::InitializeImpl()
mInitParams.mStatus = InitParams::INITIALIZED;
}
}
}

View File

@ -40,7 +40,6 @@
#include "nsRect.h" // for nsIntRect
#include "nsServiceManagerUtils.h" // for do_GetService
#include "nsString.h" // for nsString, nsAutoCString, etc
#include "DecomposeIntoNoRepeatTriangles.h"
#include "ScopedGLHelpers.h"
#include "GLReadTexImageHelper.h"
#include "TiledLayerBuffer.h" // for TiledLayerComposer
@ -82,65 +81,6 @@ BindMaskForProgram(ShaderProgramOGL* aProgram, TextureSourceOGL* aSourceMask,
aProgram->SetMaskLayerTransform(aTransform);
}
// Draw the given quads with the already selected shader. Texture coordinates
// are supplied if the shader requires them.
static void
DrawQuads(GLContext *aGLContext,
VBOArena &aVBOs,
ShaderProgramOGL *aProg,
GLenum aMode,
RectTriangles &aRects)
{
NS_ASSERTION(aProg->HasInitialized(), "Shader program not correctly initialized");
GLuint vertAttribIndex =
aProg->AttribLocation(ShaderProgramOGL::VertexCoordAttrib);
GLuint texCoordAttribIndex =
aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib);
bool texCoords = (texCoordAttribIndex != GLuint(-1));
GLsizei bytes = aRects.elements() * 2 * sizeof(GLfloat);
GLsizei total = bytes;
if (texCoords) {
total *= 2;
}
aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER,
aVBOs.Allocate(aGLContext));
aGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER,
total,
nullptr,
LOCAL_GL_STREAM_DRAW);
aGLContext->fBufferSubData(LOCAL_GL_ARRAY_BUFFER,
0,
bytes,
aRects.vertCoords().Elements());
aGLContext->fEnableVertexAttribArray(vertAttribIndex);
aGLContext->fVertexAttribPointer(vertAttribIndex,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, BUFFER_OFFSET(0));
if (texCoords) {
aGLContext->fBufferSubData(LOCAL_GL_ARRAY_BUFFER,
bytes,
bytes,
aRects.texCoords().Elements());
aGLContext->fEnableVertexAttribArray(texCoordAttribIndex);
aGLContext->fVertexAttribPointer(texCoordAttribIndex,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, BUFFER_OFFSET(bytes));
} else {
aGLContext->fDisableVertexAttribArray(texCoordAttribIndex);
}
aGLContext->fDrawArrays(aMode, 0, aRects.elements());
aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
CompositorOGL::CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth,
int aSurfaceHeight, bool aUseExternalSurfaceSize)
: mWidget(aWidget)
@ -407,52 +347,45 @@ CompositorOGL::Initialize()
return true;
}
// |aTextureTransform| is the texture transform that will be set on
// aProg, possibly multiplied with another texture transform of our
// own.
// |aTexCoordRect| is the rectangle from the texture that we want to
// draw using the given program. The program already has a necessary
// offset and scale, so the geometry that needs to be drawn is a unit
// square from 0,0 to 1,1.
//
// |aTexture| is the texture we are drawing. Its actual size can be
// larger than the rectangle given by |aTexCoordRect|.
void
CompositorOGL::BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg,
const Rect& aRect,
const gfx3DMatrix& aTextureTransform,
const Rect& aTexCoordRect,
TextureSource *aTexture)
static GLfloat
WrapTexCoord(GLfloat v)
{
// Given what we know about these textures and coordinates, we can
// compute fmod(t, 1.0f) to get the same texture coordinate out. If
// the texCoordRect dimension is < 0 or > width/height, then we have
// wraparound that we need to deal with by drawing multiple quads,
// because we can't rely on full non-power-of-two texture support
// (which is required for the REPEAT wrap mode).
// fmodf gives negative results for negative numbers;
// that is, fmodf(0.75, 1.0) == 0.75, but
// fmodf(-0.75, 1.0) == -0.75. For the negative case,
// the result we need is 0.25, so we add 1.0f.
if (v < 0.0f) {
return 1.0f + fmodf(v, 1.0f);
}
RectTriangles rects;
return fmodf(v, 1.0f);
}
GLenum wrapMode = aTexture->AsSourceOGL()->GetWrapMode();
IntSize realTexSize = aTexture->GetSize();
if (!CanUploadNonPowerOfTwo(mGLContext)) {
realTexSize = IntSize(NextPowerOfTwo(realTexSize.width),
NextPowerOfTwo(realTexSize.height));
static void
SetRects(int n,
Rect* aLayerRects,
Rect* aTextureRects,
GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
bool flip_y /* = false */)
{
if (flip_y) {
std::swap(ty0, ty1);
}
aLayerRects[n] = Rect(x0, y0, x1 - x0, y1 - y0);
aTextureRects[n] = Rect(tx0, ty0, tx1 - tx0, ty1 - ty0);
}
// We need to convert back to actual texels here to get proper behaviour with
// our GL helper functions. Should fix this sometime.
// I want to vomit.
IntRect texCoordRect = IntRect(NS_roundf(aTexCoordRect.x * aTexture->GetSize().width),
NS_roundf(aTexCoordRect.y * aTexture->GetSize().height),
NS_roundf(aTexCoordRect.width * aTexture->GetSize().width),
NS_roundf(aTexCoordRect.height * aTexture->GetSize().height));
static int
DecomposeIntoNoRepeatRects(const Rect& aRect,
const Rect& aTexCoordRect,
Rect* aLayerRects,
Rect* aTextureRects)
{
Rect texCoordRect = aTexCoordRect;
// This is fairly disgusting - if the texture should be flipped it will have a
// negative height, in which case we un-invert the texture coords and pass the
// flipped 'flag' to the functions below. We can't just use the inverted coords
// because our GL funtions use an explicit flag.
// If the texture should be flipped, it will have negative height. Detect that
// here and compensate for it. We will flip each rect as we emit it.
bool flipped = false;
if (texCoordRect.height < 0) {
flipped = true;
@ -460,35 +393,131 @@ CompositorOGL::BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg,
texCoordRect.height = -texCoordRect.height;
}
if (wrapMode == LOCAL_GL_REPEAT) {
rects.addRect(/* dest rectangle */
0.0f, 0.0f, 1.0f, 1.0f,
/* tex coords */
texCoordRect.x / GLfloat(realTexSize.width),
texCoordRect.y / GLfloat(realTexSize.height),
texCoordRect.XMost() / GLfloat(realTexSize.width),
texCoordRect.YMost() / GLfloat(realTexSize.height),
flipped);
} else {
nsIntRect tcRect(texCoordRect.x, texCoordRect.y,
texCoordRect.width, texCoordRect.height);
DecomposeIntoNoRepeatTriangles(tcRect,
nsIntSize(realTexSize.width, realTexSize.height),
rects, flipped);
Point tl = texCoordRect.TopLeft();
Point br = texCoordRect.BottomRight();
// Chen check if we wrap in either the x or y axis; if we do,
// then also use fmod to figure out the "true" non-wrapping
// texture coordinates.
bool xwrap = false, ywrap = false;
if (texCoordRect.x < 0 ||
texCoordRect.x > 1.0f ||
texCoordRect.XMost() < 0 ||
texCoordRect.XMost() > 1.0f) {
xwrap = true;
tl = Point(WrapTexCoord(tl.x), tl.y);
br = Point(WrapTexCoord(br.x), br.y);
}
gfx3DMatrix textureTransform;
if (rects.isSimpleQuad(textureTransform)) {
Matrix4x4 transform;
ToMatrix4x4(aTextureTransform * textureTransform, transform);
aProg->SetTextureTransform(transform);
BindAndDrawQuad(aProg, aRect);
} else {
Matrix4x4 transform;
ToMatrix4x4(aTextureTransform, transform);
aProg->SetTextureTransform(transform);
aProg->SetLayerQuadRect(aRect);
DrawQuads(mGLContext, mVBOs, aProg, LOCAL_GL_TRIANGLES, rects);
if (texCoordRect.y < 0 ||
texCoordRect.y > 1.0f ||
texCoordRect.YMost() < 0 ||
texCoordRect.YMost() > 1.0f) {
ywrap = true;
tl = Point(tl.x, WrapTexCoord(tl.y));
br = Point(br.x, WrapTexCoord(br.y));
}
NS_ASSERTION(tl.x >= 0.0f && tl.x <= 1.0f &&
tl.y >= 0.0f && tl.y <= 1.0f &&
br.x >= 0.0f && br.x <= 1.0f &&
br.y >= 0.0f && br.y <= 1.0f,
"Somehow generated invalid texture coordinates");
// If xwrap is false, the texture will be sampled from tl.x
// .. br.x. If xwrap is true, then it will be split into tl.x
// .. 1.0, and 0.0 .. br.x. Same for the Y axis. The
// destination rectangle is also split appropriately, according
// to the calculated xmid/ymid values.
// There isn't a 1:1 mapping between tex coords and destination coords;
// when computing midpoints, we have to take that into account. We
// need to map the texture coords, which are (in the wrap case):
// |tl->1| and |0->br| to the |0->1| range of the vertex coords. So
// we have the length (1-tl)+(br) that needs to map into 0->1.
// These are only valid if there is wrap involved, they won't be used
// otherwise.
GLfloat xlen = (1.0f - tl.x) + br.x;
GLfloat ylen = (1.0f - tl.y) + br.y;
NS_ASSERTION(!xwrap || xlen > 0.0f, "xlen isn't > 0, what's going on?");
NS_ASSERTION(!ywrap || ylen > 0.0f, "ylen isn't > 0, what's going on?");
if (!xwrap && !ywrap) {
SetRects(0, aLayerRects, aTextureRects,
aRect.x, aRect.y, aRect.XMost(), aRect.YMost(),
tl.x, tl.y, br.x, br.y,
flipped);
return 1;
}
GLfloat xmid = aRect.x + (1.0f - tl.x) / xlen * aRect.width;
GLfloat ymid = aRect.y + (1.0f - tl.y) / ylen * aRect.height;
if (!xwrap && ywrap) {
SetRects(0, aLayerRects, aTextureRects,
aRect.x, aRect.y, aRect.XMost(), ymid,
tl.x, tl.y, br.x, 1.0f,
flipped);
SetRects(1, aLayerRects, aTextureRects,
aRect.x, ymid, aRect.XMost(), aRect.YMost(),
tl.x, 0.0f, br.x, br.y,
flipped);
return 2;
}
if (xwrap && !ywrap) {
SetRects(0, aLayerRects, aTextureRects,
aRect.x, aRect.y, xmid, aRect.YMost(),
tl.x, tl.y, 1.0f, br.y,
flipped);
SetRects(1, aLayerRects, aTextureRects,
xmid, aRect.y, aRect.XMost(), aRect.YMost(),
0.0f, tl.y, br.x, br.y,
flipped);
return 2;
}
SetRects(0, aLayerRects, aTextureRects,
aRect.x, aRect.y, xmid, ymid,
tl.x, tl.y, 1.0f, 1.0f,
flipped);
SetRects(1, aLayerRects, aTextureRects,
xmid, aRect.y, aRect.XMost(), ymid,
0.0f, tl.y, br.x, 1.0f,
flipped);
SetRects(2, aLayerRects, aTextureRects,
aRect.x, ymid, xmid, aRect.YMost(),
tl.x, 0.0f, 1.0f, br.y,
flipped);
SetRects(3, aLayerRects, aTextureRects,
xmid, ymid, aRect.XMost(), aRect.YMost(),
0.0f, 0.0f, br.x, br.y,
flipped);
return 4;
}
// |aRect| is the rectangle we want to draw to. We will draw it with
// up to 4 draw commands if necessary to avoid wrapping.
// |aTexCoordRect| is the rectangle from the texture that we want to
// draw using the given program.
// |aTexture| is the texture we are drawing. Its actual size can be
// larger than the rectangle given by |texCoordRect|.
void
CompositorOGL::BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg,
const Rect& aRect,
const Rect& aTexCoordRect,
TextureSource *aTexture)
{
Rect layerRects[4];
Rect textureRects[4];
int rects = DecomposeIntoNoRepeatRects(aRect,
aTexCoordRect,
layerRects,
textureRects);
for (int n = 0; n < rects; ++n) {
BindAndDrawQuad(aProg, layerRects[n], textureRects[n]);
}
}
@ -1055,13 +1084,15 @@ CompositorOGL::DrawQuad(const Rect& aRect,
source->AsSourceOGL()->BindTexture(LOCAL_GL_TEXTURE0, filter);
program->SetTextureUnit(0);
Matrix4x4 transform;
ToMatrix4x4(textureTransform, transform);
program->SetTextureTransform(transform);
if (maskType != MaskType::MaskNone) {
BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE1, maskQuadTransform);
}
BindAndDrawQuadWithTextureRect(program, aRect, textureTransform,
texturedEffect->mTextureCoords, source);
BindAndDrawQuadWithTextureRect(program, aRect, texturedEffect->mTextureCoords, source);
}
break;
case EffectTypes::YCBCR: {
@ -1083,6 +1114,7 @@ CompositorOGL::DrawQuad(const Rect& aRect,
sourceCr->BindTexture(LOCAL_GL_TEXTURE2, effectYCbCr->mFilter);
program->SetYCbCrTextureUnits(Y, Cb, Cr);
program->SetTextureTransform(Matrix4x4());
if (maskType != MaskType::MaskNone) {
BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE3, maskQuadTransform);
@ -1090,7 +1122,6 @@ CompositorOGL::DrawQuad(const Rect& aRect,
didSetBlendMode = SetBlendMode(gl(), blendMode);
BindAndDrawQuadWithTextureRect(program,
aRect,
gfx3DMatrix(),
effectYCbCr->mTextureCoords,
sourceYCbCr->GetSubSource(Y));
}
@ -1148,7 +1179,7 @@ CompositorOGL::DrawQuad(const Rect& aRect,
program->SetBlackTextureUnit(0);
program->SetWhiteTextureUnit(1);
program->SetTextureTransform(gfx::Matrix4x4());
program->SetTextureTransform(Matrix4x4());
if (maskType != MaskType::MaskNone) {
BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE2, maskQuadTransform);
@ -1159,7 +1190,6 @@ CompositorOGL::DrawQuad(const Rect& aRect,
program->SetTexturePass2(false);
BindAndDrawQuadWithTextureRect(program,
aRect,
gfx3DMatrix(),
effectComponentAlpha->mTextureCoords,
effectComponentAlpha->mOnBlack);
@ -1169,7 +1199,6 @@ CompositorOGL::DrawQuad(const Rect& aRect,
program->SetTexturePass2(true);
BindAndDrawQuadWithTextureRect(program,
aRect,
gfx3DMatrix(),
effectComponentAlpha->mTextureCoords,
effectComponentAlpha->mOnBlack);
@ -1466,11 +1495,13 @@ CompositorOGL::QuadVBOTexCoordsAttrib(GLuint aAttribIndex) {
}
void
CompositorOGL::BindAndDrawQuad(ShaderProgramOGL *aProg, const Rect& aRect)
CompositorOGL::BindAndDrawQuad(ShaderProgramOGL *aProg,
const Rect& aLayerRect,
const Rect& aTextureRect)
{
NS_ASSERTION(aProg->HasInitialized(), "Shader program not correctly initialized");
aProg->SetLayerQuadRect(aRect);
aProg->SetLayerRect(aLayerRect);
GLuint vertAttribIndex = aProg->AttribLocation(ShaderProgramOGL::VertexCoordAttrib);
GLuint texCoordAttribIndex = aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib);
@ -1481,6 +1512,8 @@ CompositorOGL::BindAndDrawQuad(ShaderProgramOGL *aProg, const Rect& aRect)
if (texCoordAttribIndex != GLuint(-1)) {
QuadVBOTexCoordsAttrib(texCoordAttribIndex);
mGLContext->fEnableVertexAttribArray(texCoordAttribIndex);
aProg->SetTextureRect(aTextureRect);
}
mGLContext->fEnableVertexAttribArray(vertAttribIndex);

View File

@ -369,10 +369,10 @@ private:
void QuadVBOVerticesAttrib(GLuint aAttribIndex);
void QuadVBOTexCoordsAttrib(GLuint aAttribIndex);
void BindAndDrawQuad(ShaderProgramOGL *aProg,
const gfx::Rect& aRect);
const gfx::Rect& aLayerRect,
const gfx::Rect& aTextureRect = gfx::Rect(0.0f, 0.0f, 1.0f, 1.0f));
void BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg,
const gfx::Rect& aRect,
const gfx3DMatrix& aTextureTransform,
const gfx::Rect& aTexCoordRect,
TextureSource *aTexture);

View File

@ -43,9 +43,11 @@ public:
return mImpl->GetProjMatrix();
}
virtual void BindAndDrawQuad(ShaderProgramOGL *aProg, const gfx::Rect& aRect) MOZ_OVERRIDE
virtual void BindAndDrawQuad(ShaderProgramOGL *aProg,
const gfx::Rect& aLayerRect,
const gfx::Rect& aTextureRect) MOZ_OVERRIDE
{
mImpl->BindAndDrawQuad(aProg, aRect);
mImpl->BindAndDrawQuad(aProg, aLayerRect, aTextureRect);
}
private:

View File

@ -33,7 +33,8 @@ public:
virtual gl::GLContext* gl() const = 0;
virtual ShaderProgramOGL* GetProgram(GLenum aTarget, gfx::SurfaceFormat aFormat) = 0;
virtual const gfx::Matrix4x4& GetProjMatrix() const = 0;
virtual void BindAndDrawQuad(ShaderProgramOGL *aProg, const gfx::Rect& aRect) = 0;
virtual void BindAndDrawQuad(ShaderProgramOGL *aProg, const gfx::Rect& aLayerRect,
const gfx::Rect& aTextureRect) = 0;
};
}

View File

@ -31,10 +31,11 @@ AddUniforms(ProgramProfileOGL& aProfile)
{
static const char *sKnownUniformNames[] = {
"uLayerTransform",
"uMaskQuadTransform",
"uLayerQuadRect",
"uMaskTransform",
"uLayerRect",
"uMatrixProj",
"uTextureTransform",
"uTextureRect",
"uRenderTargetOffset",
"uLayerOpacity",
"uTexture",
@ -145,7 +146,7 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
AddUniforms(result);
vs << "uniform mat4 uMatrixProj;" << endl;
vs << "uniform vec4 uLayerQuadRect;" << endl;
vs << "uniform vec4 uLayerRect;" << endl;
vs << "uniform mat4 uLayerTransform;" << endl;
vs << "uniform vec4 uRenderTargetOffset;" << endl;
@ -153,28 +154,29 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
vs << "uniform mat4 uTextureTransform;" << endl;
vs << "uniform vec4 uTextureRect;" << endl;
vs << "attribute vec2 aTexCoord;" << endl;
vs << "varying vec2 vTexCoord;" << endl;
}
if (aConfig.mFeatures & ENABLE_MASK_2D ||
aConfig.mFeatures & ENABLE_MASK_3D) {
vs << "uniform mat4 uMaskQuadTransform;" << endl;
vs << "uniform mat4 uMaskTransform;" << endl;
vs << "varying vec3 vMaskCoord;" << endl;
}
vs << "void main() {" << endl;
vs << " vec4 finalPosition = vec4(aVertexCoord.xy * uLayerQuadRect.zw + uLayerQuadRect.xy, 0.0, 1.0);" << endl;
vs << " vec4 finalPosition = vec4(aVertexCoord.xy * uLayerRect.zw + uLayerRect.xy, 0.0, 1.0);" << endl;
vs << " finalPosition = uLayerTransform * finalPosition;" << endl;
vs << " finalPosition.xyz /= finalPosition.w;" << endl;
if (aConfig.mFeatures & ENABLE_MASK_3D) {
vs << " vMaskCoord.xy = (uMaskQuadTransform * vec4(finalPosition.xyz, 1.0)).xy;" << endl;
vs << " vMaskCoord.xy = (uMaskTransform * vec4(finalPosition.xyz, 1.0)).xy;" << endl;
// correct for perspective correct interpolation, see comment in D3D10 shader
vs << " vMaskCoord.z = 1.0;" << endl;
vs << " vMaskCoord *= finalPosition.w;" << endl;
} else if (aConfig.mFeatures & ENABLE_MASK_2D) {
vs << " vMaskCoord.xy = (uMaskQuadTransform * finalPosition).xy;" << endl;
vs << " vMaskCoord.xy = (uMaskTransform * finalPosition).xy;" << endl;
}
vs << " finalPosition = finalPosition - uRenderTargetOffset;" << endl;
@ -182,7 +184,8 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
vs << " finalPosition = uMatrixProj * finalPosition;" << endl;
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
vs << " vTexCoord = (uTextureTransform * vec4(aTexCoord.x, aTexCoord.y, 0.0, 1.0)).xy;" << endl;
vs << " vec2 texCoord = aTexCoord * uTextureRect.zw + uTextureRect.xy;" << endl;
vs << " vTexCoord = (uTextureTransform * vec4(texCoord, 0.0, 1.0)).xy;" << endl;
}
vs << " gl_Position = finalPosition;" << endl;

View File

@ -51,10 +51,11 @@ public:
NotAKnownUniform = -1,
LayerTransform = 0,
MaskQuadTransform,
LayerQuadRect,
MaskTransform,
LayerRect,
MatrixProj,
TextureTransform,
TextureRect,
RenderTargetOffset,
LayerOpacity,
Texture,
@ -318,12 +319,12 @@ public:
}
void SetMaskLayerTransform(const gfx::Matrix4x4& aMatrix) {
SetMatrixUniform(KnownUniform::MaskQuadTransform, aMatrix);
SetMatrixUniform(KnownUniform::MaskTransform, aMatrix);
}
void SetLayerQuadRect(const gfx::Rect& aRect) {
void SetLayerRect(const gfx::Rect& aRect) {
float vals[4] = { float(aRect.x), float(aRect.y), float(aRect.width), float(aRect.height) };
SetUniform(KnownUniform::LayerQuadRect, 4, vals);
SetUniform(KnownUniform::LayerRect, 4, vals);
}
void SetProjectionMatrix(const gfx::Matrix4x4& aMatrix) {
@ -335,6 +336,11 @@ public:
SetMatrixUniform(KnownUniform::TextureTransform, aMatrix);
}
void SetTextureRect(const gfx::Rect& aRect) {
float vals[4] = { float(aRect.x), float(aRect.y), float(aRect.width), float(aRect.height) };
SetUniform(KnownUniform::TextureRect, 4, vals);
}
void SetRenderOffset(const nsIntPoint& aOffset) {
float vals[4] = { float(aOffset.x), float(aOffset.y), 0.0f, 0.0f };
SetUniform(KnownUniform::RenderTargetOffset, 4, vals);

View File

@ -10,8 +10,9 @@
#include "gfxXlibSurface.h"
#include "gfx2DGlue.h"
using namespace mozilla;
using namespace mozilla::layers;
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
X11TextureSourceOGL::X11TextureSourceOGL(CompositorOGL* aCompositor, gfxXlibSurface* aSurface)
@ -102,3 +103,6 @@ X11TextureSourceOGL::ContentTypeToSurfaceFormat(gfxContentType aType)
}
#endif
}
}

View File

@ -313,6 +313,11 @@ void nsRegion::SimplifyOutwardByArea(uint32_t aThreshold)
pixman_box32_t *boxes;
int n;
boxes = pixman_region32_rectangles(&mImpl, &n);
// if we have no rectangles then we're done
if (!n)
return;
pixman_box32_t *end = boxes + n;
pixman_box32_t *topRectsEnd = boxes+1;
pixman_box32_t *topRects = boxes;

View File

@ -276,5 +276,10 @@ TEST(Gfx, RegionSimplify) {
"regions not merged";
}
{ // empty region
// just make sure this doesn't crash.
nsRegion r;
r.SimplifyOutwardByArea(100);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<body>
<img src="downscale-1-smallimage.png">
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 B

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<html class="reftest-wait">
<head>
<script>
function snapshot() {
document.documentElement.removeAttribute('class');
}
</script>
</head>
<!-- NOTE: Using setTimeout to wait for high-quality downscaled version of
image to be ready, because there's nothing better we can do. If we fix
Bug 1006883, we can do away with this setTimeout.
For now, the setTimeout is just here to increase the likelihood that we
actually test the high-quality downscaled version of the image. If the
setTimeout happens to fire before the high-quality downscaled rendering is
ready, then this the test will pass without testing what it's trying to
test, which is fine as long as that's rare. -->
<body onload="setTimeout(snapshot, 50)">
<img src="downscale-1-bigimage.png" style="height: 20px; width: 20px">
</body>
</html>

View File

@ -0,0 +1,28 @@
# Reftests for downscaling
#
# Downscaling can be a lossy process, so a bit of mismatch is acceptable here,
# as long as it's barely noticable visually. When necessary, this can be
# explicitly allowed via 'fuzzy'/'fuzzy-if' annotations.
#
# IMPORTANT: For robustness, each test should be listed *twice* in this
# manifest -- once with the high quality downscaling pref disabled, and once
# with this pref enabled. The pref is set via "default-preferences", so
# simply appending a new test to the lists below each of those lines should be
# sufficient.
#
# Also note that Mac OS X has its own system-level downscaling algorithm, so
# tests here may need Mac-specific "fuzzy-if(cocoaWidget,...)" annotations.
# RUN TESTS WITH HIGH QUALITY DOWNSCALING DISABLED:
# =================================================
default-preferences pref(image.high_quality_downscaling.enabled,false)
fuzzy-if(cocoaWidget,106,31) == downscale-1.html downscale-1-ref.html
# RUN TESTS WITH HIGH QUALITY DOWNSCALING ENABLED:
# ================================================
# High-quality downscaling enabled:
default-preferences pref(image.high_quality_downscaling.enabled,true)
fuzzy(31,127) == downscale-1.html downscale-1-ref.html

View File

@ -43,5 +43,8 @@ include generic/reftest.list
# Color management test
include color-management/reftest.list
# Downscaling tests
include downscaling/reftest.list
# Lossless encoders
skip-if(Android||B2G) include encoders-lossless/reftest.list # bug 783621

View File

@ -1622,6 +1622,26 @@ DumpObject(JSContext *cx, unsigned argc, jsval *vp)
}
#endif
static bool
ReportOutOfMemory(JSContext *cx, unsigned argc, jsval *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JS_ReportOutOfMemory(cx);
cx->clearPendingException();
args.rval().setUndefined();
return true;
}
static bool
ReportLargeAllocationFailure(JSContext *cx, unsigned argc, jsval *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
void *buf = cx->runtime()->onOutOfMemoryCanGC(NULL, JSRuntime::LARGE_ALLOCATION);
js_free(buf);
args.rval().setUndefined();
return true;
}
static const JSFunctionSpecWithHelp TestingFunctions[] = {
JS_FN_HELP("gc", ::GC, 0, 0,
"gc([obj] | 'compartment')",
@ -1892,6 +1912,16 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = {
"stopTraceLogger()",
" Stop logging the mainThread."),
JS_FN_HELP("reportOutOfMemory", ReportOutOfMemory, 0, 0,
"reportOutOfMemory()",
" Report OOM, then clear the exception and return undefined. For crash testing."),
JS_FN_HELP("reportLargeAllocationFailure", ReportLargeAllocationFailure, 0, 0,
"reportLargeAllocationFailure()",
" Call the large allocation failure callback, as though a large malloc call failed,\n"
" then return undefined. In Gecko, this sends a memory pressure notification, which\n"
" can free up some memory."),
#ifdef DEBUG
JS_FN_HELP("dumpObject", DumpObject, 1, 0,
"dumpObject()",

View File

@ -11,10 +11,9 @@ mozilla.prettyprinters.clear_module_printers(__name__)
class JSStringTypeCache(object):
def __init__(self, cache):
dummy = gdb.Value(0).cast(cache.JSString_ptr_t)
self.LENGTH_SHIFT = dummy['LENGTH_SHIFT']
self.FLAGS_MASK = dummy['FLAGS_MASK']
self.ROPE_FLAGS = dummy['ROPE_FLAGS']
self.ATOM_BIT = dummy['ATOM_BIT']
self.ROPE_FLAGS = dummy['ROPE_FLAGS']
self.ATOM_BIT = dummy['ATOM_BIT']
self.INLINE_CHARS_BIT = dummy['INLINE_CHARS_BIT']
class Common(mozilla.prettyprinters.Pointer):
def __init__(self, value, cache):
@ -30,16 +29,20 @@ class JSStringPtr(Common):
def jschars(self):
d = self.value['d']
lengthAndFlags = d['lengthAndFlags']
length = lengthAndFlags >> self.stc.LENGTH_SHIFT
is_rope = (lengthAndFlags & self.stc.FLAGS_MASK) == self.stc.ROPE_FLAGS
length = d['u1']['length']
flags = d['u1']['flags']
is_rope = (flags == self.stc.ROPE_FLAGS)
if is_rope:
for c in JSStringPtr(d['u1']['left'], self.cache).jschars():
for c in JSStringPtr(d['s']['u2']['left'], self.cache).jschars():
yield c
for c in JSStringPtr(d['s']['u2']['right'], self.cache).jschars():
for c in JSStringPtr(d['s']['u3']['right'], self.cache).jschars():
yield c
else:
chars = d['u1']['chars']
is_inline = (flags & self.stc.INLINE_CHARS_BIT) != 0
if is_inline:
chars = d['inlineStorage']
else:
chars = d['s']['u2']['nonInlineChars']
for i in xrange(length):
yield chars[i]

View File

@ -449,8 +449,9 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext *cx)
LabelPatch &v = labelPatches[i];
JS_ASSERT(!v.label);
v.patchOffset.fixup(&masm);
uintptr_t offset = masm.actualOffset(v.labelOffset);
Assembler::patchDataWithValueCheck(CodeLocationLabel(code, v.patchOffset),
ImmPtr(code->raw() + v.labelOffset),
ImmPtr(code->raw() + offset),
ImmPtr(0));
}

View File

@ -0,0 +1,59 @@
setJitCompilerOption("baseline.usecount.trigger", 10);
setJitCompilerOption("ion.usecount.trigger", 20);
//var log = print;
var log = function(x){}
function ceil(x) {
// A nice but not always efficient polyfill.
return -Math.floor(-x);
}
function doubleCheck(g) {
for (var j = 0; j < 200; j++) {
var i = j;
assertEq(g(i), i);
assertEq(g(i+.5), i+1);
assertEq(g(-i), -i);
assertEq(g(-i-.5), -i);
}
}
function floatCheck(g, val) {
for (var j = 0; j < 200; j++) {
var i = Math.fround(j);
assertEq(g(i), i);
assertEq(g(i+.5), i+1);
assertEq(g(-i), -i);
assertEq(g(-i-.5), -i);
}
}
function testBailout(value) {
var dceil = eval('(function(x) { return Math.ceil(x) })');
log('start double');
doubleCheck(dceil);
log('bailout');
// At this point, the compiled code should bailout, if 'value' is in the
// edge case set.
assertEq(dceil(value), ceil(value));
var fceil = eval('(function(x) { return Math.ceil(Math.fround(x)) })');
log('start float');
floatCheck(fceil, value);
log('bailout');
assertEq(fceil(Math.fround(value)), ceil(Math.fround(value)));
}
var INT_MAX = Math.pow(2, 31) - 1;
var INT_MIN = INT_MAX + 1 | 0;
// Values in ]-1; -0]
testBailout(-0);
testBailout(-.5);
// Values outside the INT32 range, when represented in either double or
// single precision
testBailout(INT_MAX + .5);
testBailout(INT_MIN - 129);
// BatNaN
testBailout(NaN);

View File

@ -78,8 +78,14 @@ class BaselineFrame
protected: // Silence Clang warning about unused private fields.
// We need to split the Value into 2 fields of 32 bits, otherwise the C++
// compiler may add some padding between the fields.
uint32_t loScratchValue_;
uint32_t hiScratchValue_;
union {
struct {
uint32_t loScratchValue_;
uint32_t hiScratchValue_;
};
BaselineDebugModeOSRInfo *debugModeOSRInfo_;
};
uint32_t loReturnValue_; // If HAS_RVAL, the frame's return value.
uint32_t hiReturnValue_;
uint32_t frameSize_;
@ -311,7 +317,7 @@ class BaselineFrame
BaselineDebugModeOSRInfo *debugModeOSRInfo() {
MOZ_ASSERT(flags_ & HAS_DEBUG_MODE_OSR_INFO);
return *reinterpret_cast<BaselineDebugModeOSRInfo **>(&loScratchValue_);
return debugModeOSRInfo_;
}
BaselineDebugModeOSRInfo *getDebugModeOSRInfo() {
@ -322,7 +328,7 @@ class BaselineFrame
void setDebugModeOSRInfo(BaselineDebugModeOSRInfo *info) {
flags_ |= HAS_DEBUG_MODE_OSR_INFO;
*reinterpret_cast<BaselineDebugModeOSRInfo **>(&loScratchValue_) = info;
debugModeOSRInfo_ = info;
}
void deleteDebugModeOSRInfo();

View File

@ -3116,11 +3116,13 @@ IonBuilder::filterTypesAtTest(MTest *test)
return false;
replace = ensureDefiniteTypeSet(subject, type);
// Make sure we don't hoist it above the MTest, we can use the
// 'dependency' of an MInstruction. This is normally used by
// Alias Analysis, but won't get overwritten, since this
// instruction doesn't have an AliasSet.
replace->setDependency(test);
if (replace != subject) {
// Make sure we don't hoist it above the MTest, we can use the
// 'dependency' of an MInstruction. This is normally used by
// Alias Analysis, but won't get overwritten, since this
// instruction doesn't have an AliasSet.
replace->setDependency(test);
}
}
current->setSlot(i, replace);
@ -6408,6 +6410,12 @@ IonBuilder::ensureDefiniteTypeSet(MDefinition *def, types::TemporaryTypeSet *typ
return replace;
}
// Don't replace if input type is more accurate than given typeset.
if (def->type() != types->getKnownMIRType()) {
MOZ_ASSERT(types->getKnownMIRType() == MIRType_Value);
return def;
}
// Create a NOP mir instruction to filter the typeset.
MFilterTypeSet *filter = MFilterTypeSet::New(alloc(), def, types);
current->add(filter);

View File

@ -4812,6 +4812,28 @@ class LFloorF : public LInstructionHelper<1, 1, 0>
}
};
// Take the ceiling of a double precision number. Implements Math.ceil().
class LCeil : public LInstructionHelper<1, 1, 0>
{
public:
LIR_HEADER(Ceil)
LCeil(const LAllocation &num) {
setOperand(0, num);
}
};
// Take the ceiling of a single precision number. Implements Math.ceil().
class LCeilF : public LInstructionHelper<1, 1, 0>
{
public:
LIR_HEADER(CeilF)
LCeilF(const LAllocation &num) {
setOperand(0, num);
}
};
// Round a double precision number. Implements Math.round().
class LRound : public LInstructionHelper<1, 1, 1>
{

View File

@ -234,7 +234,7 @@
_(CallInitElementArray) \
_(CallSetProperty) \
_(CallDeleteProperty) \
_(CallDeleteElement) \
_(CallDeleteElement) \
_(SetPropertyCacheV) \
_(SetPropertyCacheT) \
_(SetElementCacheV) \
@ -265,6 +265,8 @@
_(ToIdV) \
_(Floor) \
_(FloorF) \
_(Ceil) \
_(CeilF) \
_(Round) \
_(RoundF) \
_(In) \
@ -281,7 +283,7 @@
_(CallDOMNative) \
_(IsCallable) \
_(HaveSameClass) \
_(HasClass) \
_(HasClass) \
_(AsmJSLoadHeap) \
_(AsmJSStoreHeap) \
_(AsmJSLoadGlobalVar) \

View File

@ -1188,6 +1188,25 @@ LIRGenerator::visitFloor(MFloor *ins)
return define(lir, ins);
}
bool
LIRGenerator::visitCeil(MCeil *ins)
{
MIRType type = ins->num()->type();
JS_ASSERT(IsFloatingPointType(type));
if (type == MIRType_Double) {
LCeil *lir = new(alloc()) LCeil(useRegister(ins->num()));
if (!assignSnapshot(lir))
return false;
return define(lir, ins);
}
LCeilF *lir = new(alloc()) LCeilF(useRegister(ins->num()));
if (!assignSnapshot(lir))
return false;
return define(lir, ins);
}
bool
LIRGenerator::visitRound(MRound *ins)
{

View File

@ -119,6 +119,7 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitRsh(MRsh *ins);
bool visitUrsh(MUrsh *ins);
bool visitFloor(MFloor *ins);
bool visitCeil(MCeil *ins);
bool visitRound(MRound *ins);
bool visitMinMax(MMinMax *ins);
bool visitAbs(MAbs *ins);

View File

@ -707,6 +707,14 @@ IonBuilder::inlineMathCeil(CallInfo &callInfo)
return InliningStatus_Inlined;
}
if (IsFloatingPointType(argType) && returnType == MIRType_Int32) {
callInfo.setImplicitlyUsedUnchecked();
MCeil *ins = MCeil::New(alloc(), callInfo.getArg(0));
current->add(ins);
current->push(ins);
return InliningStatus_Inlined;
}
if (IsFloatingPointType(argType) && returnType == MIRType_Double) {
callInfo.setImplicitlyUsedUnchecked();
MMathFunction *ins = MMathFunction::New(alloc(), callInfo.getArg(0), MMathFunction::Ceil, nullptr);

View File

@ -815,36 +815,40 @@ MStringLength::foldsTo(TempAllocator &alloc, bool useValueNumbers)
return this;
}
static bool
EnsureFloatInputOrConvert(MUnaryInstruction *owner, TempAllocator &alloc)
{
MDefinition *input = owner->input();
if (!input->canProduceFloat32()) {
if (input->type() == MIRType_Float32)
ConvertDefinitionToDouble<0>(alloc, input, owner);
return false;
}
return true;
}
void
MFloor::trySpecializeFloat32(TempAllocator &alloc)
{
// No need to look at the output, as it's an integer (see IonBuilder::inlineMathFloor)
if (!input()->canProduceFloat32()) {
if (input()->type() == MIRType_Float32)
ConvertDefinitionToDouble<0>(alloc, input(), this);
return;
}
JS_ASSERT(type() == MIRType_Int32);
if (EnsureFloatInputOrConvert(this, alloc))
setPolicyType(MIRType_Float32);
}
if (type() == MIRType_Double)
setResultType(MIRType_Float32);
setPolicyType(MIRType_Float32);
void
MCeil::trySpecializeFloat32(TempAllocator &alloc)
{
JS_ASSERT(type() == MIRType_Int32);
if (EnsureFloatInputOrConvert(this, alloc))
setPolicyType(MIRType_Float32);
}
void
MRound::trySpecializeFloat32(TempAllocator &alloc)
{
// No need to look at the output, as it's an integer (unique way to have
// this instruction in IonBuilder::inlineMathRound)
JS_ASSERT(type() == MIRType_Int32);
if (!input()->canProduceFloat32()) {
if (input()->type() == MIRType_Float32)
ConvertDefinitionToDouble<0>(alloc, input(), this);
return;
}
setPolicyType(MIRType_Float32);
if (EnsureFloatInputOrConvert(this, alloc))
setPolicyType(MIRType_Float32);
}
MCompare *
@ -940,34 +944,21 @@ MPhi::removeAllOperands()
inputs_.clear();
}
MDefinition *
MPhi::operandIfRedundant()
{
JS_ASSERT(inputs_.length() != 0);
// If this phi is redundant (e.g., phi(a,a) or b=phi(a,this)),
// returns the operand that it will always be equal to (a, in
// those two cases).
MDefinition *first = getOperand(0);
for (size_t i = 1, e = numOperands(); i < e; i++) {
// Phis need dominator information to fold based on value numbers. For
// simplicity, we only compare SSA names right now (bug 714727).
if (!EqualValues(false, getOperand(i), first) &&
!EqualValues(false, getOperand(i), this))
{
return nullptr;
}
}
return first;
}
MDefinition *
MPhi::foldsTo(TempAllocator &alloc, bool useValueNumbers)
{
if (MDefinition *def = operandIfRedundant())
return def;
JS_ASSERT(!inputs_.empty());
return this;
MDefinition *first = getOperand(0);
for (size_t i = 1; i < inputs_.length(); i++) {
// Phis need dominator information to fold based on value numbers. For
// simplicity, we only compare SSA names right now (bug 714727).
if (!EqualValues(false, getOperand(i), first))
return this;
}
return first;
}
bool

View File

@ -4892,7 +4892,17 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode<MPhi>
}
void computeRange(TempAllocator &alloc);
MDefinition *operandIfRedundant();
MDefinition *operandIfRedundant() {
// If this phi is redundant (e.g., phi(a,a) or b=phi(a,this)),
// returns the operand that it will always be equal to (a, in
// those two cases).
MDefinition *first = getOperand(0);
for (size_t i = 1, e = numOperands(); i < e; i++) {
if (getOperand(i) != first && getOperand(i) != this)
return nullptr;
}
return first;
}
bool canProduceFloat32() const {
return canProduceFloat32_;
@ -8775,6 +8785,50 @@ class MFloor
return new(alloc) MFloor(num);
}
MDefinition *num() const {
return getOperand(0);
}
AliasSet getAliasSet() const {
return AliasSet::None();
}
TypePolicy *typePolicy() {
return this;
}
bool isFloat32Commutative() const {
return true;
}
void trySpecializeFloat32(TempAllocator &alloc);
#ifdef DEBUG
bool isConsistentFloat32Use(MUse *use) const {
return true;
}
#endif
bool congruentTo(const MDefinition *ins) const {
return congruentIfOperandsEqual(ins);
}
void computeRange(TempAllocator &alloc);
};
// Inlined version of Math.ceil().
class MCeil
: public MUnaryInstruction,
public FloatingPointPolicy<0>
{
MCeil(MDefinition *num)
: MUnaryInstruction(num)
{
setResultType(MIRType_Int32);
setPolicyType(MIRType_Double);
setMovable();
}
public:
INSTRUCTION_HEADER(Ceil)
static MCeil *New(TempAllocator &alloc, MDefinition *num) {
return new(alloc) MCeil(num);
}
MDefinition *num() const {
return getOperand(0);
}
@ -9346,7 +9400,8 @@ class MFilterTypeSet
MFilterTypeSet(MDefinition *def, types::TemporaryTypeSet *types)
: MUnaryInstruction(def)
{
JS_ASSERT(!types->unknown());
MOZ_ASSERT(!types->unknown());
MOZ_ASSERT(def->type() == types->getKnownMIRType());
setResultType(types->getKnownMIRType());
setResultTypeSet(types);
}

View File

@ -185,6 +185,7 @@ namespace jit {
_(RunOncePrologue) \
_(Rest) \
_(Floor) \
_(Ceil) \
_(Round) \
_(In) \
_(InstanceOf) \
@ -196,7 +197,7 @@ namespace jit {
_(SetDOMProperty) \
_(IsCallable) \
_(HaveSameClass) \
_(HasClass) \
_(HasClass) \
_(AsmJSNeg) \
_(AsmJSUnsignedToDouble) \
_(AsmJSUnsignedToFloat32) \

View File

@ -271,6 +271,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
CUSTOM_OP(Rest)
SAFE_OP(RestPar)
SAFE_OP(Floor)
SAFE_OP(Ceil)
SAFE_OP(Round)
UNSAFE_OP(InstanceOf)
CUSTOM_OP(InterruptCheck)

View File

@ -1175,6 +1175,15 @@ MAbs::computeRange(TempAllocator &alloc)
setRange(next);
}
void
MFloor::computeRange(TempAllocator &alloc)
{
Range other(getOperand(0));
Range *copy = new(alloc) Range(other);
copy->resetFractionalPart();
setRange(copy);
}
void
MMinMax::computeRange(TempAllocator &alloc)
{

View File

@ -588,6 +588,11 @@ class Range : public TempObject {
void setSymbolicUpper(SymbolicBound *bound) {
symbolicUpper_ = bound;
}
void resetFractionalPart() {
canHaveFractionalPart_ = false;
optimize();
}
};
} // namespace jit

View File

@ -1238,6 +1238,30 @@ CodeGeneratorARM::visitFloorF(LFloorF *lir)
return true;
}
bool
CodeGeneratorARM::visitCeil(LCeil *lir)
{
FloatRegister input = ToFloatRegister(lir->input());
Register output = ToRegister(lir->output());
Label bail;
masm.ceil(input, output, &bail);
if (!bailoutFrom(&bail, lir->snapshot()))
return false;
return true;
}
bool
CodeGeneratorARM::visitCeilF(LCeilF *lir)
{
FloatRegister input = ToFloatRegister(lir->input());
Register output = ToRegister(lir->output());
Label bail;
masm.ceilf(input, output, &bail);
if (!bailoutFrom(&bail, lir->snapshot()))
return false;
return true;
}
bool
CodeGeneratorARM::visitRound(LRound *lir)
{

View File

@ -145,6 +145,8 @@ class CodeGeneratorARM : public CodeGeneratorShared
virtual bool visitMathF(LMathF *math);
virtual bool visitFloor(LFloor *lir);
virtual bool visitFloorF(LFloorF *lir);
virtual bool visitCeil(LCeil *lir);
virtual bool visitCeilF(LCeilF *lir);
virtual bool visitRound(LRound *lir);
virtual bool visitRoundF(LRoundF *lir);
virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins);

View File

@ -4199,6 +4199,108 @@ MacroAssemblerARMCompat::floorf(FloatRegister input, Register output, Label *bai
bind(&fin);
}
void
MacroAssemblerARMCompat::ceil(FloatRegister input, Register output, Label *bail)
{
Label handleZero;
Label handlePos;
Label fin;
compareDouble(input, InvalidFloatReg);
// NaN is always a bail condition, just bail directly.
ma_b(bail, Assembler::Overflow);
ma_b(&handleZero, Assembler::Equal);
ma_b(&handlePos, Assembler::NotSigned);
// We are in the ]-Inf; 0[ range
// If we are in the ]-1; 0[ range => bailout
ma_vimm(-1.0, ScratchFloatReg);
compareDouble(input, ScratchFloatReg);
ma_b(bail, Assembler::GreaterThan);
// We are in the ]-Inf; -1] range: ceil(x) == -floor(-x) and floor can
// be computed with direct truncation here (x > 0).
ma_vneg(input, ScratchFloatReg);
ma_vcvt_F64_U32(ScratchFloatReg, ScratchFloatReg);
ma_vxfer(VFPRegister(ScratchFloatReg).uintOverlay(), output);
ma_neg(output, output, SetCond);
ma_b(bail, NotSigned);
ma_b(&fin);
// Test for 0.0 / -0.0: if the top word of the input double is not zero,
// then it was -0 and we need to bail out.
bind(&handleZero);
as_vxfer(output, InvalidReg, input, FloatToCore, Always, 1);
ma_cmp(output, Imm32(0));
ma_b(bail, NonZero);
ma_b(&fin);
// We are in the ]0; +inf] range: truncate integer values, maybe add 1 for
// non integer values, maybe bail if overflow.
bind(&handlePos);
ma_vcvt_F64_U32(input, ScratchFloatReg);
ma_vxfer(VFPRegister(ScratchFloatReg).uintOverlay(), output);
ma_vcvt_U32_F64(ScratchFloatReg, ScratchFloatReg);
compareDouble(ScratchFloatReg, input);
ma_add(output, Imm32(1), output, NoSetCond, NotEqual);
// Bail out if the add overflowed or the result is negative
ma_mov(output, output, SetCond);
ma_b(bail, Signed);
bind(&fin);
}
void
MacroAssemblerARMCompat::ceilf(FloatRegister input, Register output, Label *bail)
{
Label handleZero;
Label handlePos;
Label fin;
compareFloat(input, InvalidFloatReg);
// NaN is always a bail condition, just bail directly.
ma_b(bail, Assembler::Overflow);
ma_b(&handleZero, Assembler::Equal);
ma_b(&handlePos, Assembler::NotSigned);
// We are in the ]-Inf; 0[ range
// If we are in the ]-1; 0[ range => bailout
ma_vimm_f32(-1.f, ScratchFloatReg);
compareFloat(input, ScratchFloatReg);
ma_b(bail, Assembler::GreaterThan);
// We are in the ]-Inf; -1] range: ceil(x) == -floor(-x) and floor can
// be computed with direct truncation here (x > 0).
ma_vneg_f32(input, ScratchFloatReg);
ma_vcvt_F32_U32(ScratchFloatReg, ScratchFloatReg);
ma_vxfer(VFPRegister(ScratchFloatReg).uintOverlay(), output);
ma_neg(output, output, SetCond);
ma_b(bail, NotSigned);
ma_b(&fin);
// Test for 0.0 / -0.0: if the top word of the input double is not zero,
// then it was -0 and we need to bail out.
bind(&handleZero);
as_vxfer(output, InvalidReg, VFPRegister(input).singleOverlay(), FloatToCore, Always, 0);
ma_cmp(output, Imm32(0));
ma_b(bail, NonZero);
ma_b(&fin);
// We are in the ]0; +inf] range: truncate integer values, maybe add 1 for
// non integer values, maybe bail if overflow.
bind(&handlePos);
ma_vcvt_F32_U32(input, ScratchFloatReg);
ma_vxfer(VFPRegister(ScratchFloatReg).uintOverlay(), output);
ma_vcvt_U32_F32(ScratchFloatReg, ScratchFloatReg);
compareFloat(ScratchFloatReg, input);
ma_add(output, Imm32(1), output, NoSetCond, NotEqual);
// Bail out if the add overflowed or the result is negative
ma_mov(output, output, SetCond);
ma_b(bail, Signed);
bind(&fin);
}
CodeOffsetLabel
MacroAssemblerARMCompat::toggledJump(Label *label)
{

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