Merge m-i to m-c.
@ -1,12 +1,16 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.reset();
|
||||
|
||||
/**
|
||||
* TestCase for bug 564387
|
||||
* <https://bugzilla.mozilla.org/show_bug.cgi?id=564387>
|
||||
*/
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
var fileName;
|
||||
|
||||
gBrowser.loadURI("http://mochi.test:8888/browser/browser/base/content/test/bug564387.html");
|
||||
|
||||
@ -35,17 +39,22 @@ function test() {
|
||||
|
||||
// Create the folder the video will be saved into.
|
||||
var destDir = createTemporarySaveDirectory();
|
||||
var destFile = destDir.clone();
|
||||
|
||||
mockFilePickerSettings.destDir = destDir;
|
||||
mockFilePickerSettings.filterIndex = 1; // kSaveAsType_URL
|
||||
mockFilePickerRegisterer.register();
|
||||
MockFilePicker.displayDirectory = destDir;
|
||||
MockFilePicker.showCallback = function(fp) {
|
||||
fileName = fp.defaultString;
|
||||
destFile.append (fileName);
|
||||
MockFilePicker.returnFiles = [destFile];
|
||||
MockFilePicker.filterIndex = 1; // kSaveAsType_URL
|
||||
};
|
||||
|
||||
mockTransferCallback = onTransferComplete;
|
||||
mockTransferRegisterer.register();
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
mockTransferRegisterer.unregister();
|
||||
mockFilePickerRegisterer.unregister();
|
||||
MockFilePicker.reset();
|
||||
destDir.remove(true);
|
||||
});
|
||||
|
||||
@ -59,9 +68,6 @@ function test() {
|
||||
function onTransferComplete(downloadSuccess) {
|
||||
ok(downloadSuccess, "Video file should have been downloaded successfully");
|
||||
|
||||
// Read the name of the saved file.
|
||||
var fileName = mockFilePickerResults.selectedFile.leafName;
|
||||
|
||||
is(fileName, "Bug564387-expectedName.ogv",
|
||||
"Video file name is correctly retrieved from Content-Disposition http header");
|
||||
|
||||
@ -74,11 +80,6 @@ Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.loadSubScript("chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockTransfer.js",
|
||||
this);
|
||||
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockFilePicker.js",
|
||||
this);
|
||||
|
||||
function createTemporarySaveDirectory() {
|
||||
var saveDir = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties)
|
||||
|
@ -45,7 +45,9 @@ include $(DEPTH)/config/autoconf.mk
|
||||
MODULE = browserdir
|
||||
LIBRARY_NAME = browserdir_s
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS = tests
|
||||
endif
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
FORCE_USE_PIC = 1
|
||||
|
@ -3192,6 +3192,7 @@ SessionStoreService.prototype = {
|
||||
shEntry.postData = stream;
|
||||
}
|
||||
|
||||
let childDocIdents = {};
|
||||
if (aEntry.docIdentifier) {
|
||||
// If we have a serialized document identifier, try to find an SHEntry
|
||||
// which matches that doc identifier and adopt that SHEntry's
|
||||
@ -3199,10 +3200,12 @@ SessionStoreService.prototype = {
|
||||
// for the document identifier.
|
||||
let matchingEntry = aDocIdentMap[aEntry.docIdentifier];
|
||||
if (!matchingEntry) {
|
||||
aDocIdentMap[aEntry.docIdentifier] = shEntry;
|
||||
matchingEntry = {shEntry: shEntry, childDocIdents: childDocIdents};
|
||||
aDocIdentMap[aEntry.docIdentifier] = matchingEntry;
|
||||
}
|
||||
else {
|
||||
shEntry.adoptBFCacheEntry(matchingEntry);
|
||||
shEntry.adoptBFCacheEntry(matchingEntry.shEntry);
|
||||
childDocIdents = matchingEntry.childDocIdents;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3224,8 +3227,24 @@ SessionStoreService.prototype = {
|
||||
//XXXzpao Wallpaper patch for bug 514751
|
||||
if (!aEntry.children[i].url)
|
||||
continue;
|
||||
|
||||
// We're getting sessionrestore.js files with a cycle in the
|
||||
// doc-identifier graph, likely due to bug 698656. (That is, we have
|
||||
// an entry where doc identifier A is an ancestor of doc identifier B,
|
||||
// and another entry where doc identifier B is an ancestor of A.)
|
||||
//
|
||||
// If we were to respect these doc identifiers, we'd create a cycle in
|
||||
// the SHEntries themselves, which causes the docshell to loop forever
|
||||
// when it looks for the root SHEntry.
|
||||
//
|
||||
// So as a hack to fix this, we restrict the scope of a doc identifier
|
||||
// to be a node's siblings and cousins, and pass childDocIdents, not
|
||||
// aDocIdents, to _deserializeHistoryEntry. That is, we say that two
|
||||
// SHEntries with the same doc identifier have the same document iff
|
||||
// they have the same parent or their parents have the same document.
|
||||
|
||||
shEntry.AddChild(this._deserializeHistoryEntry(aEntry.children[i], aIdMap,
|
||||
aDocIdentMap), i);
|
||||
childDocIdents), i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,6 +154,8 @@ _BROWSER_TEST_FILES = \
|
||||
browser_662812.js \
|
||||
browser_665702-state_session.js \
|
||||
browser_682507.js \
|
||||
browser_687710.js \
|
||||
browser_687710_2.js \
|
||||
browser_694378.js \
|
||||
$(NULL)
|
||||
|
||||
|
@ -0,0 +1,44 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that sessionrestore handles cycles in the shentry graph properly.
|
||||
//
|
||||
// These cycles shouldn't be there in the first place, but they cause hangs
|
||||
// when they mysteriously appear (bug 687710). Docshell code assumes this
|
||||
// graph is a tree and tires to walk to the root. But if there's a cycle,
|
||||
// there is no root, and we loop forever.
|
||||
|
||||
let stateBackup = ss.getBrowserState();
|
||||
|
||||
let state = {windows:[{tabs:[{entries:[
|
||||
{
|
||||
docIdentifier: 1,
|
||||
url: "http://example.com",
|
||||
children: [
|
||||
{
|
||||
docIdentifier: 2,
|
||||
url: "http://example.com"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
docIdentifier: 2,
|
||||
url: "http://example.com",
|
||||
children: [
|
||||
{
|
||||
docIdentifier: 1,
|
||||
url: "http://example.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
]}]}]}
|
||||
|
||||
function test() {
|
||||
registerCleanupFunction(function () {
|
||||
ss.setBrowserState(stateBackup);
|
||||
});
|
||||
|
||||
/* This test fails by hanging. */
|
||||
ss.setBrowserState(JSON.stringify(state));
|
||||
ok(true, "Didn't hang!");
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that the fix for bug 687710 isn't too aggressive -- shentries which are
|
||||
// cousins should be able to share bfcache entries.
|
||||
|
||||
let stateBackup = ss.getBrowserState();
|
||||
|
||||
let state = {entries:[
|
||||
{
|
||||
docIdentifier: 1,
|
||||
url: "http://example.com?1",
|
||||
children: [{ docIdentifier: 10,
|
||||
url: "http://example.com?10" }]
|
||||
},
|
||||
{
|
||||
docIdentifier: 1,
|
||||
url: "http://example.com?1#a",
|
||||
children: [{ docIdentifier: 10,
|
||||
url: "http://example.com?10#aa" }]
|
||||
}
|
||||
]};
|
||||
|
||||
function test()
|
||||
{
|
||||
registerCleanupFunction(function () {
|
||||
ss.setBrowserState(stateBackup);
|
||||
});
|
||||
|
||||
let tab = gBrowser.addTab("about:blank");
|
||||
ss.setTabState(tab, JSON.stringify(state));
|
||||
let history = tab.linkedBrowser.webNavigation.sessionHistory;
|
||||
|
||||
is(history.count, 2, "history.count");
|
||||
for (let i = 0; i < history.count; i++) {
|
||||
for (let j = 0; j < history.count; j++) {
|
||||
compareEntries(i, j, history);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function compareEntries(i, j, history)
|
||||
{
|
||||
let e1 = history.getEntryAtIndex(i, false)
|
||||
.QueryInterface(Ci.nsISHEntry)
|
||||
.QueryInterface(Ci.nsISHContainer);
|
||||
|
||||
let e2 = history.getEntryAtIndex(j, false)
|
||||
.QueryInterface(Ci.nsISHEntry)
|
||||
.QueryInterface(Ci.nsISHContainer);
|
||||
|
||||
ok(e1.sharesDocumentWith(e2),
|
||||
i + ' should share doc with ' + j);
|
||||
is(e1.childCount, e2.childCount,
|
||||
'Child count mismatch (' + i + ', ' + j + ')');
|
||||
|
||||
for (let c = 0; c < e1.childCount; c++) {
|
||||
let c1 = e1.GetChildAt(c);
|
||||
let c2 = e2.GetChildAt(c);
|
||||
|
||||
ok(c1.sharesDocumentWith(c2),
|
||||
'Cousins should share documents. (' + i + ', ' + j + ', ' + c + ')');
|
||||
}
|
||||
}
|
@ -57,6 +57,8 @@
|
||||
%define forwardTransitionLength 150ms
|
||||
%define conditionalForwardWithUrlbar window:not([chromehidden~=toolbar]) :-moz-any(#nav-bar[currentset*="unified-back-forward-button,urlbar-container"][mode=icons], #nav-bar:not([currentset])[mode=icons]) > #unified-back-forward-button
|
||||
%define conditionalForwardWithUrlbar_small window:not([chromehidden~=toolbar]) :-moz-any(#nav-bar[currentset*="unified-back-forward-button,urlbar-container"][mode=icons][iconsize=small],#nav-bar:not([currentset])[mode=icons][iconsize=small]) > #unified-back-forward-button
|
||||
%define conditionalForwardWithUrlbarWidth 32
|
||||
%define conditionalForwardWithUrlbarWidth_small 24
|
||||
|
||||
#menubar-items {
|
||||
-moz-box-orient: vertical; /* for flex hack */
|
||||
@ -630,18 +632,6 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
@conditionalForwardWithUrlbar@ > #forward-button[disabled]:-moz-locale-dir(ltr) {
|
||||
margin-left: -36px;
|
||||
}
|
||||
@conditionalForwardWithUrlbar@ > #forward-button[disabled]:-moz-locale-dir(rtl) {
|
||||
margin-right: -36px;
|
||||
}
|
||||
@conditionalForwardWithUrlbar_small@ > #forward-button[disabled]:-moz-locale-dir(ltr) {
|
||||
margin-left: -28px;
|
||||
}
|
||||
@conditionalForwardWithUrlbar_small@ > #forward-button[disabled]:-moz-locale-dir(rtl) {
|
||||
margin-right: -28px;
|
||||
}
|
||||
|
||||
#reload-button {
|
||||
list-style-image: url("moz-icon://stock/gtk-refresh?size=toolbar");
|
||||
@ -965,6 +955,40 @@ toolbar[iconsize="small"] #feed-button {
|
||||
-moz-box-align: stretch;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ + #urlbar-container {
|
||||
-moz-padding-start: @conditionalForwardWithUrlbarWidth@px;
|
||||
-moz-margin-start: -@conditionalForwardWithUrlbarWidth@px;
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar_small@ + #urlbar-container {
|
||||
-moz-padding-start: @conditionalForwardWithUrlbarWidth_small@px;
|
||||
-moz-margin-start: -@conditionalForwardWithUrlbarWidth_small@px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not([switchingtabs]) + #urlbar-container > #urlbar {
|
||||
-moz-transition: margin-left @forwardTransitionLength@ ease-out,
|
||||
margin-right @forwardTransitionLength@ ease-out;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar:-moz-locale-dir(ltr) {
|
||||
margin-left: -@conditionalForwardWithUrlbarWidth@px;
|
||||
}
|
||||
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar:-moz-locale-dir(rtl) {
|
||||
margin-right: -@conditionalForwardWithUrlbarWidth@px;
|
||||
}
|
||||
@conditionalForwardWithUrlbar_small@[forwarddisabled] + #urlbar-container > #urlbar:-moz-locale-dir(ltr) {
|
||||
margin-left: -@conditionalForwardWithUrlbarWidth_small@px;
|
||||
}
|
||||
@conditionalForwardWithUrlbar_small@[forwarddisabled] + #urlbar-container > #urlbar:-moz-locale-dir(rtl) {
|
||||
margin-right: -@conditionalForwardWithUrlbarWidth_small@px;
|
||||
}
|
||||
|
||||
#urlbar-icons {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
@ -743,13 +743,13 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
||||
self.haveDumpedScreen = True;
|
||||
|
||||
# Need to figure out what tool and whether it write to a file or stdout
|
||||
if UNIXISH:
|
||||
if self.UNIXISH:
|
||||
utility = [os.path.join(utilityPath, "screentopng")]
|
||||
imgoutput = 'stdout'
|
||||
elif IS_MAC:
|
||||
elif self.IS_MAC:
|
||||
utility = ['/usr/sbin/screencapture', '-C', '-x', '-t', 'png']
|
||||
imgoutput = 'file'
|
||||
elif IS_WIN32:
|
||||
elif self.IS_WIN32:
|
||||
self.log.info("If you fixed bug 589668, you'd get a screenshot here")
|
||||
return
|
||||
|
||||
|
@ -42,6 +42,7 @@ interface nsIChannel;
|
||||
interface nsIStreamListener;
|
||||
interface nsIURI;
|
||||
interface nsIDocument;
|
||||
interface nsIFrame;
|
||||
|
||||
/**
|
||||
* This interface represents a content node that loads images. The interface
|
||||
@ -65,7 +66,7 @@ interface nsIDocument;
|
||||
* sufficient, when combined with the imageBlockingStatus information.)
|
||||
*/
|
||||
|
||||
[scriptable, uuid(95c74255-df9a-4060-b5a0-0d111fcafe08)]
|
||||
[scriptable, uuid(f7debb84-2854-4731-a57b-1bd752ad71f8)]
|
||||
interface nsIImageLoadingContent : imgIDecoderObserver
|
||||
{
|
||||
/**
|
||||
@ -128,6 +129,18 @@ interface nsIImageLoadingContent : imgIDecoderObserver
|
||||
*/
|
||||
imgIRequest getRequest(in long aRequestType);
|
||||
|
||||
/**
|
||||
* Used to notify the image loading content node that a frame has been
|
||||
* created.
|
||||
*/
|
||||
[notxpcom] void frameCreated(in nsIFrame aFrame);
|
||||
|
||||
/**
|
||||
* Used to notify the image loading content node that a frame has been
|
||||
* destroyed.
|
||||
*/
|
||||
[notxpcom] void frameDestroyed(in nsIFrame aFrame);
|
||||
|
||||
/**
|
||||
* Used to find out what type of request one is dealing with (eg
|
||||
* which request got passed through to the imgIDecoderObserver
|
||||
|
@ -3225,6 +3225,7 @@ nsDocument::DeleteShell()
|
||||
if (IsEventHandlingEnabled()) {
|
||||
RevokeAnimationFrameNotifications();
|
||||
}
|
||||
|
||||
mPresShell = nsnull;
|
||||
}
|
||||
|
||||
@ -8359,32 +8360,15 @@ nsIDocument::SizeOf() const
|
||||
return size;
|
||||
}
|
||||
|
||||
class nsDispatchFullScreenChange : public nsRunnable
|
||||
static void
|
||||
DispatchFullScreenChange(nsINode* aTarget)
|
||||
{
|
||||
public:
|
||||
nsDispatchFullScreenChange(nsIDocument *aDoc, nsINode* aElement)
|
||||
: mDoc(aDoc),
|
||||
mTarget(aElement ? aElement : aDoc) {}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsContentUtils::DispatchTrustedEvent(mDoc,
|
||||
mTarget,
|
||||
NS_LITERAL_STRING("mozfullscreenchange"),
|
||||
true,
|
||||
false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> mDoc;
|
||||
nsCOMPtr<nsISupports> mTarget;
|
||||
};
|
||||
|
||||
static void DispatchFullScreenChange(nsIDocument* aDocument, Element* aElement)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> event(
|
||||
new nsDispatchFullScreenChange(aDocument, aElement));
|
||||
NS_DispatchToCurrentThread(event);
|
||||
nsRefPtr<nsPLDOMEvent> e =
|
||||
new nsPLDOMEvent(aTarget,
|
||||
NS_LITERAL_STRING("mozfullscreenchange"),
|
||||
true,
|
||||
false);
|
||||
e->PostDOMEvent();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -8470,7 +8454,7 @@ nsDocument::CancelFullScreen()
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryReferent(sFullScreenDoc));
|
||||
while (doc != nsnull) {
|
||||
if (::SetFullScreenState(doc, nsnull, false)) {
|
||||
DispatchFullScreenChange(doc, nsnull);
|
||||
DispatchFullScreenChange(doc);
|
||||
}
|
||||
doc = doc->GetParentDocument();
|
||||
}
|
||||
@ -8523,6 +8507,14 @@ void
|
||||
nsDocument::RequestFullScreen(Element* aElement)
|
||||
{
|
||||
if (!aElement || !nsContentUtils::IsFullScreenApiEnabled() || !GetWindow()) {
|
||||
if (aElement) {
|
||||
nsRefPtr<nsPLDOMEvent> e =
|
||||
new nsPLDOMEvent(aElement,
|
||||
NS_LITERAL_STRING("mozfullscreenerror"),
|
||||
true,
|
||||
false);
|
||||
e->PostDOMEvent();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -8538,7 +8530,7 @@ nsDocument::RequestFullScreen(Element* aElement)
|
||||
nsIDocument* doc = fullScreenDoc;
|
||||
while (doc != commonAncestor) {
|
||||
if (::SetFullScreenState(doc, nsnull, false)) {
|
||||
DispatchFullScreenChange(doc, nsnull);
|
||||
DispatchFullScreenChange(doc);
|
||||
}
|
||||
doc = doc->GetParentDocument();
|
||||
}
|
||||
@ -8553,7 +8545,7 @@ nsDocument::RequestFullScreen(Element* aElement)
|
||||
// element, and the full-screen-ancestor styles on ancestors of the element
|
||||
// in this document.
|
||||
if (SetFullScreenState(aElement, true)) {
|
||||
DispatchFullScreenChange(this, aElement);
|
||||
DispatchFullScreenChange(aElement);
|
||||
}
|
||||
|
||||
// Propagate up the document hierarchy, setting the full-screen element as
|
||||
@ -8566,7 +8558,7 @@ nsDocument::RequestFullScreen(Element* aElement)
|
||||
while ((parent = child->GetParentDocument())) {
|
||||
Element* element = parent->FindContentForSubDocument(child)->AsElement();
|
||||
if (::SetFullScreenState(parent, element, true)) {
|
||||
DispatchFullScreenChange(parent, element);
|
||||
DispatchFullScreenChange(element);
|
||||
}
|
||||
child = parent;
|
||||
}
|
||||
@ -8616,7 +8608,8 @@ nsDocument::GetMozFullScreenEnabled(bool *aFullScreen)
|
||||
*aFullScreen = false;
|
||||
|
||||
if (!nsContentUtils::IsFullScreenApiEnabled() ||
|
||||
nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
|
||||
nsContentUtils::HasPluginWithUncontrolledEventDispatch(this) ||
|
||||
!IsVisible()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -589,6 +589,7 @@ GK_ATOM(mouseover, "mouseover")
|
||||
GK_ATOM(mousethrough, "mousethrough")
|
||||
GK_ATOM(mouseup, "mouseup")
|
||||
GK_ATOM(mozfullscreenchange, "mozfullscreenchange")
|
||||
GK_ATOM(mozfullscreenerror, "mozfullscreenerror")
|
||||
GK_ATOM(moz_opaque, "moz-opaque")
|
||||
GK_ATOM(moz_action_hint, "mozactionhint")
|
||||
GK_ATOM(x_moz_errormessage, "x-moz-errormessage")
|
||||
@ -707,6 +708,7 @@ GK_ATOM(onmouseup, "onmouseup")
|
||||
GK_ATOM(onMozAfterPaint, "onMozAfterPaint")
|
||||
GK_ATOM(onMozBeforePaint, "onMozBeforePaint")
|
||||
GK_ATOM(onmozfullscreenchange, "onmozfullscreenchange")
|
||||
GK_ATOM(onmozfullscreenerror, "onmozfullscreenerror")
|
||||
GK_ATOM(onMozMousePixelScroll, "onMozMousePixelScroll")
|
||||
GK_ATOM(onMozScrolledAreaChanged, "onMozScrolledAreaChanged")
|
||||
GK_ATOM(ononline, "ononline")
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include "nsIDOMNode.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
@ -115,7 +116,9 @@ nsImageLoadingContent::nsImageLoadingContent()
|
||||
mNewRequestsWillNeedAnimationReset(false),
|
||||
mPendingRequestNeedsResetAnimation(false),
|
||||
mCurrentRequestNeedsResetAnimation(false),
|
||||
mStateChangerDepth(0)
|
||||
mStateChangerDepth(0),
|
||||
mCurrentRequestRegistered(false),
|
||||
mPendingRequestRegistered(false)
|
||||
{
|
||||
if (!nsContentUtils::GetImgLoader()) {
|
||||
mLoadingEnabled = false;
|
||||
@ -196,7 +199,16 @@ nsImageLoadingContent::OnStartDecode(imgIRequest* aRequest)
|
||||
SetBlockingOnload(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool* requestFlag = GetRegisteredFlagForRequest(aRequest);
|
||||
if (requestFlag) {
|
||||
nsLayoutUtils::RegisterImageRequest(GetFramePresContext(), aRequest,
|
||||
requestFlag);
|
||||
} else {
|
||||
NS_ERROR("Starting to decode an image other than our current/pending "
|
||||
"request?");
|
||||
}
|
||||
|
||||
LOOP_OVER_OBSERVERS(OnStartDecode(aRequest));
|
||||
return NS_OK;
|
||||
}
|
||||
@ -329,6 +341,13 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
|
||||
nsIPresShell* shell = doc ? doc->GetShell() : nsnull;
|
||||
if (shell) {
|
||||
|
||||
// Make sure that our image requests are deregistered from the refresh
|
||||
// driver if they aren't animated. Note that this must be mCurrentRequest,
|
||||
// or we would have aborted up above.
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(GetFramePresContext(),
|
||||
mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
|
||||
// We need to figure out whether to kick off decoding
|
||||
bool doRequestDecode = false;
|
||||
|
||||
@ -501,6 +520,44 @@ nsImageLoadingContent::GetRequest(PRInt32 aRequestType,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsImageLoadingContent::FrameCreated(nsIFrame* aFrame)
|
||||
{
|
||||
NS_ASSERTION(aFrame, "aFrame is null");
|
||||
|
||||
// We need to make sure that our image request is registered.
|
||||
nsPresContext* presContext = aFrame->PresContext();
|
||||
|
||||
if (mCurrentRequest) {
|
||||
nsLayoutUtils::RegisterImageRequest(presContext, mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(presContext,
|
||||
mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
} else if (mPendingRequest) {
|
||||
// We don't need to do the same check for animation, because this will be
|
||||
// done when decoding is finished.
|
||||
nsLayoutUtils::RegisterImageRequest(presContext, mPendingRequest,
|
||||
&mPendingRequestRegistered);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsImageLoadingContent::FrameDestroyed(nsIFrame* aFrame)
|
||||
{
|
||||
NS_ASSERTION(aFrame, "aFrame is null");
|
||||
|
||||
// We need to make sure that our image request is deregistered.
|
||||
if (mCurrentRequest) {
|
||||
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(),
|
||||
mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
} else if (mPendingRequest) {
|
||||
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(),
|
||||
mPendingRequest,
|
||||
&mPendingRequestRegistered);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoadingContent::GetRequestType(imgIRequest* aRequest,
|
||||
@ -867,6 +924,23 @@ nsImageLoadingContent::GetOurDocument()
|
||||
return thisContent->OwnerDoc();
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsImageLoadingContent::GetOurPrimaryFrame()
|
||||
{
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
|
||||
return thisContent->GetPrimaryFrame();
|
||||
}
|
||||
|
||||
nsPresContext* nsImageLoadingContent::GetFramePresContext()
|
||||
{
|
||||
nsIFrame* frame = GetOurPrimaryFrame();
|
||||
if (!frame) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return frame->PresContext();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImageLoadingContent::StringToURI(const nsAString& aSpec,
|
||||
nsIDocument* aDocument,
|
||||
@ -986,6 +1060,16 @@ nsImageLoadingContent::ClearCurrentRequest(nsresult aReason)
|
||||
NS_ABORT_IF_FALSE(!mCurrentURI,
|
||||
"Shouldn't have both mCurrentRequest and mCurrentURI!");
|
||||
|
||||
// Deregister this image from the refresh driver so it no longer receives
|
||||
// notifications.
|
||||
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
|
||||
// Deregister this image from the refresh driver so it no longer receives
|
||||
// notifications.
|
||||
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
|
||||
// Clean up the request.
|
||||
UntrackImage(mCurrentRequest);
|
||||
mCurrentRequest->CancelAndForgetObserver(aReason);
|
||||
@ -1009,12 +1093,29 @@ nsImageLoadingContent::ClearPendingRequest(nsresult aReason)
|
||||
nsCxPusher pusher;
|
||||
pusher.PushNull();
|
||||
|
||||
// Deregister this image from the refresh driver so it no longer receives
|
||||
// notifications.
|
||||
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mPendingRequest,
|
||||
&mPendingRequestRegistered);
|
||||
|
||||
UntrackImage(mPendingRequest);
|
||||
mPendingRequest->CancelAndForgetObserver(aReason);
|
||||
mPendingRequest = nsnull;
|
||||
mPendingRequestNeedsResetAnimation = false;
|
||||
}
|
||||
|
||||
bool*
|
||||
nsImageLoadingContent::GetRegisteredFlagForRequest(imgIRequest* aRequest)
|
||||
{
|
||||
if (aRequest == mCurrentRequest) {
|
||||
return &mCurrentRequestRegistered;
|
||||
} else if (aRequest == mPendingRequest) {
|
||||
return &mPendingRequestRegistered;
|
||||
} else {
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsImageLoadingContent::HaveSize(imgIRequest *aImage)
|
||||
{
|
||||
|
@ -146,6 +146,24 @@ protected:
|
||||
*/
|
||||
nsIDocument* GetOurDocument();
|
||||
|
||||
/**
|
||||
* Helper function to get the frame associated with this content. Not named
|
||||
* GetPrimaryFrame to prevent ambiguous method names in subclasses.
|
||||
*
|
||||
* @return The frame which we belong to, or nsnull if it doesn't exist.
|
||||
*/
|
||||
nsIFrame* GetOurPrimaryFrame();
|
||||
|
||||
/**
|
||||
* Helper function to get the PresContext associated with this content's
|
||||
* frame. Not named GetPresContext to prevent ambiguous method names in
|
||||
* subclasses.
|
||||
*
|
||||
* @return The nsPresContext associated with our frame, or nsnull if either
|
||||
* the frame doesn't exist, or the frame's prescontext doesn't exist.
|
||||
*/
|
||||
nsPresContext* GetFramePresContext();
|
||||
|
||||
/**
|
||||
* CancelImageRequests is called by subclasses when they want to
|
||||
* cancel all image requests (for example when the subclass is
|
||||
@ -302,6 +320,16 @@ protected:
|
||||
void ClearCurrentRequest(nsresult aReason);
|
||||
void ClearPendingRequest(nsresult aReason);
|
||||
|
||||
/**
|
||||
* Retrieve a pointer to the 'registered with the refresh driver' flag for
|
||||
* which a particular image request corresponds.
|
||||
*
|
||||
* @returns A pointer to the boolean flag for a given image request, or
|
||||
* |nsnull| if the request is not either |mPendingRequest| or
|
||||
* |mCurrentRequest|.
|
||||
*/
|
||||
bool* GetRegisteredFlagForRequest(imgIRequest* aRequest);
|
||||
|
||||
/**
|
||||
* Static helper method to tell us if we have the size of a request. The
|
||||
* image may be null.
|
||||
@ -382,6 +410,11 @@ private:
|
||||
|
||||
/* The number of nested AutoStateChangers currently tracking our state. */
|
||||
PRUint8 mStateChangerDepth;
|
||||
|
||||
// Flags to indicate whether each of the current and pending requests are
|
||||
// registered with the refresh driver.
|
||||
bool mCurrentRequestRegistered;
|
||||
bool mPendingRequestRegistered;
|
||||
};
|
||||
|
||||
#endif // nsImageLoadingContent_h__
|
||||
|
@ -36,7 +36,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=430050
|
||||
document.getElementById('b').loadURI('data:text/plain,succeeded',
|
||||
null,
|
||||
'UTF-8');
|
||||
setTimeout(endTest, 0);
|
||||
document.getElementById('b').addEventListener("load", endTest);
|
||||
}
|
||||
}, true);
|
||||
document.documentElement.setAttribute("foo", "bar");
|
||||
|
@ -271,6 +271,10 @@ EVENT(mozfullscreenchange,
|
||||
NS_FULLSCREENCHANGE,
|
||||
EventNameType_HTML,
|
||||
NS_EVENT_NULL)
|
||||
EVENT(mozfullscreenerror,
|
||||
NS_FULLSCREENERROR,
|
||||
EventNameType_HTML,
|
||||
NS_EVENT_NULL)
|
||||
// Not supported yet; probably never because "wheel" is a better idea.
|
||||
// EVENT(mousewheel)
|
||||
EVENT(pause,
|
||||
|
@ -98,6 +98,7 @@ static const char* const sEventNames[] = {
|
||||
"MozBeforePaint",
|
||||
"MozBeforeResize",
|
||||
"mozfullscreenchange",
|
||||
"mozfullscreenerror",
|
||||
"MozSwipeGesture",
|
||||
"MozMagnifyGestureStart",
|
||||
"MozMagnifyGestureUpdate",
|
||||
@ -1384,6 +1385,8 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
|
||||
return sEventNames[eDOMEvents_deviceorientation];
|
||||
case NS_FULLSCREENCHANGE:
|
||||
return sEventNames[eDOMEvents_mozfullscreenchange];
|
||||
case NS_FULLSCREENERROR:
|
||||
return sEventNames[eDOMEvents_mozfullscreenerror];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -181,6 +181,7 @@ public:
|
||||
eDOMEvents_beforepaint,
|
||||
eDOMEvents_beforeresize,
|
||||
eDOMEvents_mozfullscreenchange,
|
||||
eDOMEvents_mozfullscreenerror,
|
||||
eDOMEvents_MozSwipeGesture,
|
||||
eDOMEvents_MozMagnifyGestureStart,
|
||||
eDOMEvents_MozMagnifyGestureUpdate,
|
||||
|
@ -117,6 +117,7 @@
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsHTMLFieldSetElement.h"
|
||||
#include "nsHTMLMenuElement.h"
|
||||
#include "nsPLDOMEvent.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
@ -3403,17 +3404,29 @@ nsresult nsGenericHTMLElement::MozRequestFullScreen()
|
||||
// This stops the full-screen from being abused similar to the popups of old,
|
||||
// and it also makes it harder for bad guys' script to go full-screen and
|
||||
// spoof the browser chrome/window and phish logins etc.
|
||||
nsIDocument* doc = OwnerDoc();
|
||||
if (!nsContentUtils::IsRequestFullScreenAllowed() ||
|
||||
!IsInDoc()) {
|
||||
nsRefPtr<nsPLDOMEvent> e =
|
||||
new nsPLDOMEvent(this,
|
||||
NS_LITERAL_STRING("mozfullscreenerror"),
|
||||
true,
|
||||
false);
|
||||
e->PostDOMEvent();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument* doc = OwnerDoc();
|
||||
nsCOMPtr<nsIDOMDocument> domDocument(do_QueryInterface(doc));
|
||||
NS_ENSURE_STATE(domDocument);
|
||||
bool fullScreenEnabled;
|
||||
domDocument->GetMozFullScreenEnabled(&fullScreenEnabled);
|
||||
if (!fullScreenEnabled) {
|
||||
nsRefPtr<nsPLDOMEvent> e =
|
||||
new nsPLDOMEvent(this,
|
||||
NS_LITERAL_STRING("mozfullscreenerror"),
|
||||
true,
|
||||
false);
|
||||
e->PostDOMEvent();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -283,6 +283,7 @@ _TEST_FILES = \
|
||||
test_fullscreen-api.html \
|
||||
file_fullscreen-plugins.html \
|
||||
file_fullscreen-denied.html \
|
||||
file_fullscreen-hidden.html \
|
||||
test_li_attributes_reflection.html \
|
||||
test_ol_attributes_reflection.html \
|
||||
test_bug651956.html \
|
||||
|
@ -43,8 +43,10 @@ var outOfDocElement = null;
|
||||
var inDocElement = null;
|
||||
var container = null;
|
||||
var button = null;
|
||||
|
||||
var fullScreenChangeCount = 0;
|
||||
var fullscreendenied = false;
|
||||
|
||||
document.addEventListener("mozfullscreenerror", function(){fullscreendenied=true;}, false);
|
||||
|
||||
function sendMouseClick(element) {
|
||||
synthesizeMouseAtCenter(element, {});
|
||||
@ -153,13 +155,18 @@ function fullScreenChange(event) {
|
||||
case 5: {
|
||||
ok(!document.mozFullScreen, "Should be back in non-full-screen mode (third time)");
|
||||
setRequireTrustedContext(true);
|
||||
fullscreendenied = false;
|
||||
fullScreenElement().mozRequestFullScreen();
|
||||
ok(!document.mozFullScreen, "Should still be in normal mode, because calling context isn't trusted.");
|
||||
|
||||
button = document.createElement("button");
|
||||
button.onclick = function(){fullScreenElement().mozRequestFullScreen();}
|
||||
fullScreenElement().appendChild(button);
|
||||
sendMouseClick(button);
|
||||
setTimeout(
|
||||
function() {
|
||||
ok(fullscreendenied, "Request for fullscreen should have been denied because calling context isn't trusted");
|
||||
button = document.createElement("button");
|
||||
button.onclick = function(){fullScreenElement().mozRequestFullScreen();}
|
||||
fullScreenElement().appendChild(button);
|
||||
sendMouseClick(button);
|
||||
}, 0);
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
@ -176,22 +183,26 @@ function fullScreenChange(event) {
|
||||
|
||||
SpecialPowers.setBoolPref("full-screen-api.enabled", false);
|
||||
is(document.mozFullScreenEnabled, false, "document.mozFullScreenEnabled should be false if full-screen-api.enabled is false");
|
||||
fullscreendenied = false;
|
||||
fullScreenElement().mozRequestFullScreen();
|
||||
ok(!document.mozFullScreen, "Should still be in normal mode, because pref is not enabled.");
|
||||
setTimeout(
|
||||
function() {
|
||||
ok(!document.mozFullScreen, "Should still be in normal mode, because pref is not enabled.");
|
||||
|
||||
SpecialPowers.setBoolPref("full-screen-api.enabled", true);
|
||||
is(document.mozFullScreenEnabled, true, "document.mozFullScreenEnabled should be true if full-screen-api.enabled is true");
|
||||
SpecialPowers.setBoolPref("full-screen-api.enabled", true);
|
||||
is(document.mozFullScreenEnabled, true, "document.mozFullScreenEnabled should be true if full-screen-api.enabled is true");
|
||||
|
||||
iframe = document.createElement("iframe");
|
||||
fullScreenElement().appendChild(iframe);
|
||||
iframe.src = iframeContents;
|
||||
ok(!document.mozFullScreen, "Should still be in normal mode, because iframe did not have mozallowfullscreen attribute.");
|
||||
fullScreenElement().removeChild(iframe);
|
||||
iframe = null;
|
||||
iframe = document.createElement("iframe");
|
||||
fullScreenElement().appendChild(iframe);
|
||||
iframe.src = iframeContents;
|
||||
ok(!document.mozFullScreen, "Should still be in normal mode, because iframe did not have mozallowfullscreen attribute.");
|
||||
fullScreenElement().removeChild(iframe);
|
||||
iframe = null;
|
||||
|
||||
// Set timeout for calling finish(), so that any pending "mozfullscreenchange" events
|
||||
// would have a chance to fire.
|
||||
setTimeout(function(){opener.nextTest();}, 0);
|
||||
// Set timeout for calling finish(), so that any pending "mozfullscreenchange" events
|
||||
// would have a chance to fire.
|
||||
setTimeout(function(){opener.nextTest();}, 0);
|
||||
}, 0);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -37,6 +37,9 @@ function is(a, b, msg) {
|
||||
*/
|
||||
var requestFullScreenContents = "data:text/html;charset=utf-8,<html>%0D%0A <body onload%3D'document.body.mozRequestFullScreen()%3B'>%0D%0A <%2Fbody>%0D%0A<%2Fhtml>";
|
||||
|
||||
var fullscreendenied = false;
|
||||
|
||||
document.addEventListener("mozfullscreenerror", function(){fullscreendenied=true;}, false);
|
||||
|
||||
var gotFullScreenChange = false;
|
||||
|
||||
@ -52,12 +55,16 @@ function run() {
|
||||
// generated event!).
|
||||
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", true);
|
||||
document.body.mozRequestFullScreen();
|
||||
ok(!document.mozFullScreen, "Should not grant request in non-truested context");
|
||||
|
||||
// Test requesting full-screen mode in a long-running user-generated event handler.
|
||||
// The request in the key handler should not be granted.
|
||||
window.addEventListener("keypress", keyHandler, false);
|
||||
synthesizeKey("VK_A", {});
|
||||
fullscreendenied = false;
|
||||
setTimeout(
|
||||
function() {
|
||||
ok(!document.mozFullScreen, "Should not grant request in non-truested context");
|
||||
ok(fullscreendenied, "Request in non-trusted event handler should be denied");
|
||||
// Test requesting full-screen mode in a long-running user-generated event handler.
|
||||
// The request in the key handler should not be granted.
|
||||
window.addEventListener("keypress", keyHandler, false);
|
||||
synthesizeKey("VK_A", {});
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function keyHandler(event) {
|
||||
@ -69,23 +76,29 @@ function keyHandler(event) {
|
||||
while ((new Date()).getTime() < end) {
|
||||
; // Wait...
|
||||
}
|
||||
fullscreendenied = false;
|
||||
document.body.mozRequestFullScreen();
|
||||
ok(!document.mozFullScreen, "Should not grant request in long-running event handler.");
|
||||
|
||||
// Disable the requirement for trusted contexts only, so the tests are easier
|
||||
// to write.
|
||||
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
|
||||
|
||||
// Create an iframe without a mozallowfullscreen sttribute, whose contents requests
|
||||
// full-screen. The request should be denied.
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = requestFullScreenContents;
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
setTimeout(
|
||||
function() {
|
||||
ok(!gotFullScreenChange, "Should not ever grant a fullscreen request in this doc.");
|
||||
opener.nextTest();
|
||||
ok(fullscreendenied, "Request in long running event handler should be denied");
|
||||
ok(!document.mozFullScreen, "Should not grant request in long-running event handler.");
|
||||
|
||||
// Disable the requirement for trusted contexts only, so the tests are easier
|
||||
// to write.
|
||||
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
|
||||
|
||||
// Create an iframe without a mozallowfullscreen sttribute, whose contents requests
|
||||
// full-screen. The request should be denied, and we should not receive a fullscreenchange
|
||||
// event in this document.
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = requestFullScreenContents;
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
setTimeout(
|
||||
function() {
|
||||
ok(!gotFullScreenChange, "Should not ever grant a fullscreen request in this doc.");
|
||||
opener.nextTest();
|
||||
}, 0);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
|
50
content/html/content/test/file_fullscreen-hidden.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=697636
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 697636</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onload="boom();">
|
||||
|
||||
<iframe id="f" src="data:text/html,<body text=green>1" mozallowfullscreen></iframe>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=697636">Mozilla Bug 697636</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 697636 **/
|
||||
|
||||
var frameWin;
|
||||
var e1;
|
||||
|
||||
function boom()
|
||||
{
|
||||
frameWin = document.getElementById("f").contentWindow;
|
||||
e1 = frameWin.document.documentElement;
|
||||
frameWin.location = "data:text/html,<body text=blue onload='parent.b2()'>2";
|
||||
}
|
||||
|
||||
function b2()
|
||||
{
|
||||
try { e1.mozRequestFullScreen(); } catch(e) { opener.ok(false, "Should not enter full-screen"); }
|
||||
setTimeout(done, 0);
|
||||
}
|
||||
|
||||
function done() {
|
||||
opener.ok(!document.mozFullScreen, "Should not have entered full-screen mode in hidden document.");
|
||||
opener.ok(!e1.ownerDocument.mozFullScreen, "Requesting owner should not have entered full-screen mode.");
|
||||
opener.nextTest();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -7,7 +7,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=500885
|
||||
<title>Test for Bug 500885</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/mockObjects.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
|
||||
</head>
|
||||
@ -18,81 +17,42 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=500885
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var Cu = Components.utils;
|
||||
var Ci = Components.interfaces;
|
||||
var Cr = Components.results;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function MockFilePicker() { };
|
||||
MockFilePicker.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFilePicker]),
|
||||
init: function(aParent, aTitle, aMode) { },
|
||||
appendFilters: function(aFilterMask) { },
|
||||
appendFilter: function(aTitle, aFilter) { },
|
||||
defaultString: "",
|
||||
defaultExtension: "",
|
||||
filterIndex: 0,
|
||||
displayDirectory: null,
|
||||
file: null,
|
||||
get fileURL() {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
get files() {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
show: function MFP_show() {
|
||||
return Ci.nsIFilePicker.returnOK;
|
||||
}
|
||||
};
|
||||
|
||||
var mockFilePickerRegisterer =
|
||||
new MockObjectRegisterer("@mozilla.org/filepicker;1",MockFilePicker);
|
||||
var MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.reset();
|
||||
MockFilePicker.returnValue = MockFilePicker.returnOK;
|
||||
|
||||
function test() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var wu = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
// SpecialPowers.DOMWindowUtils doesn't appear to fire mouseEvents correctly
|
||||
var wu = SpecialPowers.getDOMWindowUtils(window);
|
||||
|
||||
mockFilePickerRegisterer.register();
|
||||
try {
|
||||
var domActivateEvents;
|
||||
var fileInput = document.getElementById("file");
|
||||
var rect = fileInput.getBoundingClientRect();
|
||||
|
||||
fileInput.addEventListener ("DOMActivate", function (e) {
|
||||
ok("detail" in e, "DOMActivate should have .detail!");
|
||||
is(e.detail, 1, "detail should be 1!");
|
||||
ok("detail" in e, "DOMActivate should have .detail");
|
||||
is(e.detail, 1, ".detail should be 1");
|
||||
domActivateEvents++;
|
||||
}, false);
|
||||
|
||||
domActivateEvents = 0;
|
||||
wu.sendMouseEvent("mousedown", rect.left + 5, rect.top + 5, 0, 1, 0);
|
||||
wu.sendMouseEvent("mouseup", rect.left + 5, rect.top + 5, 0, 1, 0);
|
||||
is(domActivateEvents, 1, "click on text field should only fire 1 DOMActivate event");
|
||||
is(domActivateEvents, 1, "click on text field should fire 1 DOMActivate event");
|
||||
|
||||
domActivateEvents = 0;
|
||||
wu.sendMouseEvent("mousedown", rect.right - 5, rect.top + 5, 0, 1, 0);
|
||||
wu.sendMouseEvent("mouseup", rect.right - 5, rect.top + 5, 0, 1, 0);
|
||||
is(domActivateEvents, 1, "click on button should only fire 1 DOMActivate event");
|
||||
is(domActivateEvents, 1, "click on button should fire 1 DOMActivate event");
|
||||
|
||||
} finally {
|
||||
SimpleTest.executeSoon(unregister);
|
||||
|
||||
SimpleTest.executeSoon(SimpleTest.finish);
|
||||
}
|
||||
}
|
||||
|
||||
function unregister()
|
||||
{
|
||||
mockFilePickerRegisterer.unregister();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
setTimeout(test, 0);
|
||||
};
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(test);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -7,7 +7,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=592802
|
||||
<title>Test for Bug 592802</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/mockObjects.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
@ -26,129 +25,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=592802
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
var Cu = Components.utils;
|
||||
var Ci = Components.interfaces;
|
||||
var Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function simpleEnumerator(items)
|
||||
{
|
||||
this._items = items;
|
||||
this._nextIndex = 0;
|
||||
}
|
||||
|
||||
simpleEnumerator.prototype = {
|
||||
QueryInterface: function(aIID)
|
||||
{
|
||||
if (Ci.nsISimpleEnumerator.equals(aIID) ||
|
||||
Ci.nsISupports.equals(aIID)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
hasMoreElements: function()
|
||||
{
|
||||
return this._nextIndex < this._items.length;
|
||||
},
|
||||
|
||||
getNext: function()
|
||||
{
|
||||
if (!this.hasMoreElements()) {
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return this._items[this._nextIndex++];
|
||||
}
|
||||
};
|
||||
|
||||
function MockFilePicker()
|
||||
{
|
||||
}
|
||||
|
||||
MockFilePicker.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFilePicker]),
|
||||
|
||||
// Constants
|
||||
returnOK: 0, // the user hits OK (select a file)
|
||||
returnCancel: 1, // the user cancel the file selection
|
||||
returnReplace: 2, // the user replace the selection
|
||||
|
||||
// Properties
|
||||
defaultExtension: "",
|
||||
defaultString: "",
|
||||
get displayDirectory() { return null; },
|
||||
set displayDirectory(val) { },
|
||||
get fileURL() { return null; },
|
||||
filterIndex: 0,
|
||||
|
||||
get file() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var fileName = "592808_file";
|
||||
var fileData = "file content";
|
||||
|
||||
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties);
|
||||
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
|
||||
testFile.append(fileName);
|
||||
var outStream = Components.
|
||||
classes["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||
0666, 0);
|
||||
outStream.write(fileData, fileData.length);
|
||||
outStream.close();
|
||||
|
||||
return testFile;
|
||||
},
|
||||
|
||||
get files() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var fileName = "592808_file";
|
||||
var fileData = "file content";
|
||||
|
||||
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties);
|
||||
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
|
||||
testFile.append(fileName);
|
||||
var outStream = Components.
|
||||
classes["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||
0666, 0);
|
||||
outStream.write(fileData, fileData.length);
|
||||
outStream.close();
|
||||
|
||||
return new simpleEnumerator([testFile]);
|
||||
},
|
||||
|
||||
appendFilter: function(val) {},
|
||||
|
||||
appendFilters: function(val) {},
|
||||
|
||||
init: function() {},
|
||||
|
||||
show: function()
|
||||
{
|
||||
if (firstFilePickerShow) {
|
||||
firstFilePickerShow = false;
|
||||
return this.returnCancel;
|
||||
} else {
|
||||
return this.returnOK;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var mockFilePickerRegisterer =
|
||||
new MockObjectRegisterer("@mozilla.org/filepicker;1",MockFilePicker);
|
||||
|
||||
mockFilePickerRegisterer.register();
|
||||
var MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.reset();
|
||||
|
||||
var testData = [
|
||||
/* visibility | display | multiple */
|
||||
@ -163,26 +41,27 @@ var testData = [
|
||||
var testCounter = 0;
|
||||
var testNb = testData.length;
|
||||
|
||||
var firstFilePickerShow = true;
|
||||
|
||||
function finished()
|
||||
{
|
||||
mockFilePickerRegisterer.unregister();
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
// mockFilePicker will simulate a cancel for the first time the file picker will be shown.
|
||||
MockFilePicker.returnValue = MockFilePicker.returnCancel;
|
||||
|
||||
var b2 = document.getElementById('b2');
|
||||
b2.focus(); // Be sure the element is visible.
|
||||
document.getElementById('b2').addEventListener("change", function(aEvent) {
|
||||
aEvent.target.removeEventListener("change", arguments.callee, false);
|
||||
ok(false, "When cancel is received, change should not fire");
|
||||
}, false);
|
||||
synthesizeMouse(b2, 2, 2, {});
|
||||
b2.click();
|
||||
|
||||
// Now, we can launch tests when file picker isn't canceled.
|
||||
MockFilePicker.useAnyFile();
|
||||
MockFilePicker.returnValue = MockFilePicker.returnOK;
|
||||
|
||||
var b = document.getElementById('b');
|
||||
b.focus(); // Be sure the element is visible.
|
||||
|
||||
@ -203,12 +82,12 @@ SimpleTest.waitForFocus(function() {
|
||||
a.multiple = data[2];
|
||||
|
||||
SimpleTest.executeSoon(function() {
|
||||
synthesizeMouse(b, 2, 2, {});
|
||||
b.click();
|
||||
});
|
||||
}
|
||||
}, false);
|
||||
|
||||
synthesizeMouse(b, 2, 2, {});
|
||||
b.click();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -39,7 +39,8 @@ var gTestWindows = [
|
||||
"file_fullscreen-denied.html",
|
||||
"file_fullscreen-api.html",
|
||||
"file_fullscreen-api-keys.html",
|
||||
"file_fullscreen-plugins.html"
|
||||
"file_fullscreen-plugins.html",
|
||||
"file_fullscreen-hidden.html"
|
||||
];
|
||||
|
||||
var testWindow = null;
|
||||
|
@ -141,6 +141,7 @@
|
||||
#include "prprf.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsMimeTypes.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -162,6 +163,7 @@ const PRInt32 kBackward = 1;
|
||||
//#define DEBUG_charset
|
||||
|
||||
#define NS_USE_NEW_VIEW_SOURCE 1
|
||||
#define NS_USE_NEW_PLAIN_TEXT 1
|
||||
|
||||
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
|
||||
|
||||
@ -652,17 +654,30 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
|
||||
bool aReset,
|
||||
nsIContentSink* aSink)
|
||||
{
|
||||
nsCAutoString contentType;
|
||||
aChannel->GetContentType(contentType);
|
||||
|
||||
bool viewSource = aCommand && !nsCRT::strcmp(aCommand, "view-source") &&
|
||||
NS_USE_NEW_VIEW_SOURCE;
|
||||
bool loadAsHtml5 = nsHtml5Module::sEnabled || viewSource;
|
||||
bool plainText = (contentType.EqualsLiteral(TEXT_PLAIN) ||
|
||||
contentType.EqualsLiteral(TEXT_CSS) ||
|
||||
contentType.EqualsLiteral(APPLICATION_JAVASCRIPT) ||
|
||||
contentType.EqualsLiteral(APPLICATION_XJAVASCRIPT) ||
|
||||
contentType.EqualsLiteral(TEXT_ECMASCRIPT) ||
|
||||
contentType.EqualsLiteral(APPLICATION_ECMASCRIPT) ||
|
||||
contentType.EqualsLiteral(TEXT_JAVASCRIPT));
|
||||
bool loadAsHtml5 = nsHtml5Module::sEnabled || viewSource || plainText;
|
||||
if (!NS_USE_NEW_PLAIN_TEXT && !viewSource) {
|
||||
plainText = false;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!(plainText && aSink),
|
||||
"Someone tries to load plain text into a custom sink.");
|
||||
|
||||
if (aSink) {
|
||||
loadAsHtml5 = false;
|
||||
}
|
||||
|
||||
nsCAutoString contentType;
|
||||
aChannel->GetContentType(contentType);
|
||||
|
||||
if (contentType.Equals("application/xhtml+xml") && !viewSource) {
|
||||
// We're parsing XHTML as XML, remember that.
|
||||
|
||||
@ -677,7 +692,8 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (loadAsHtml5 && !viewSource && !(contentType.EqualsLiteral("text/html") &&
|
||||
if (loadAsHtml5 && !viewSource &&
|
||||
(!(contentType.EqualsLiteral("text/html") || plainText) &&
|
||||
aCommand && !nsCRT::strcmp(aCommand, "view"))) {
|
||||
loadAsHtml5 = false;
|
||||
}
|
||||
@ -731,9 +747,13 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
|
||||
if (needsParser) {
|
||||
if (loadAsHtml5) {
|
||||
mParser = nsHtml5Module::NewHtml5Parser();
|
||||
mParser->MarkAsNotScriptCreated((viewSource &&
|
||||
!contentType.EqualsLiteral("text/html")) ?
|
||||
"view-source-xml": aCommand);
|
||||
if (plainText) {
|
||||
mParser->MarkAsNotScriptCreated("plain-text");
|
||||
} else if (viewSource && !contentType.EqualsLiteral("text/html")) {
|
||||
mParser->MarkAsNotScriptCreated("view-source-xml");
|
||||
} else {
|
||||
mParser->MarkAsNotScriptCreated(aCommand);
|
||||
}
|
||||
} else {
|
||||
mParser = do_CreateInstance(kCParserCID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -113,13 +113,6 @@ nsSVGClass::ToDOMAnimatedString(nsIDOMSVGAnimatedString **aResult,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_SMIL
|
||||
nsISMILAttr*
|
||||
nsSVGClass::ToSMILAttr(nsSVGStylableElement *aSVGElement)
|
||||
{
|
||||
return new SMILString(this, aSVGElement);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGClass::DOMAnimatedString::GetAnimVal(nsAString& aResult)
|
||||
{
|
||||
@ -130,6 +123,13 @@ nsSVGClass::DOMAnimatedString::GetAnimVal(nsAString& aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_SMIL
|
||||
nsISMILAttr*
|
||||
nsSVGClass::ToSMILAttr(nsSVGStylableElement *aSVGElement)
|
||||
{
|
||||
return new SMILString(this, aSVGElement);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGClass::SMILString::ValueFromString(const nsAString& aStr,
|
||||
const nsISMILAnimationElement* /*aSrcElement*/,
|
||||
|
@ -41,9 +41,12 @@
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsString.h"
|
||||
#include "nsISMILAttr.h"
|
||||
#include "nsDOMError.h"
|
||||
|
||||
#ifdef MOZ_SMIL
|
||||
#include "nsISMILAttr.h"
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
class nsSVGStylableElement;
|
||||
|
||||
class nsSVGClass
|
||||
|
@ -149,6 +149,7 @@ nsSVGStylableElement::DidAnimateClass()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_SMIL
|
||||
nsISMILAttr*
|
||||
nsSVGStylableElement::GetAnimatedAttr(PRInt32 aNamespaceID, nsIAtom* aName)
|
||||
{
|
||||
@ -158,3 +159,4 @@ nsSVGStylableElement::GetAnimatedAttr(PRInt32 aNamespaceID, nsIAtom* aName)
|
||||
}
|
||||
return nsSVGStylableElementBase::GetAnimatedAttr(aNamespaceID, aName);
|
||||
}
|
||||
#endif // MOZ_SMIL
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include "jspubtd.h"
|
||||
%}
|
||||
|
||||
[scriptable, uuid(4e9d7d5e-72c3-4fa3-94f9-55eac5a5996b)]
|
||||
[scriptable, uuid(5b3f9656-9d81-40e4-85ba-01f302177815)]
|
||||
interface nsIInlineEventHandlers : nsISupports
|
||||
{
|
||||
[implicit_jscontext] attribute jsval onabort;
|
||||
@ -81,6 +81,7 @@ interface nsIInlineEventHandlers : nsISupports
|
||||
// Not supported yet
|
||||
// [implicit_jscontext] attribute jsval onmousewheel;
|
||||
[implicit_jscontext] attribute jsval onmozfullscreenchange;
|
||||
[implicit_jscontext] attribute jsval onmozfullscreenerror;
|
||||
[implicit_jscontext] attribute jsval onpause;
|
||||
[implicit_jscontext] attribute jsval onplay;
|
||||
[implicit_jscontext] attribute jsval onplaying;
|
||||
|
@ -126,7 +126,7 @@ CSRCS = \
|
||||
tokens.c \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -DANGLE_USE_NSPR -DANGLE_BUILD
|
||||
DEFINES += -DANGLE_USE_NSPR -DANGLE_BUILD -DCOMPILER_IMPLEMENTATION
|
||||
|
||||
#these defines are from ANGLE's build_angle.gyp
|
||||
DEFINES += -DANGLE_DISABLE_TRACE
|
||||
|
@ -1,6 +1,6 @@
|
||||
This is the ANGLE project, from http://code.google.com/p/angleproject/
|
||||
|
||||
Current revision: r802
|
||||
Current revision: r809
|
||||
|
||||
== Applied local patches ==
|
||||
|
||||
|
@ -1,40 +1,5 @@
|
||||
# HG changeset patch
|
||||
# Parent cf38970fcf3b4bee12f09b3747b7b7711bc77ad8
|
||||
diff --git a/gfx/angle/angle-renaming-debug.patch b/gfx/angle/angle-renaming-debug.patch
|
||||
--- a/gfx/angle/angle-renaming-debug.patch
|
||||
+++ b/gfx/angle/angle-renaming-debug.patch
|
||||
@@ -1,11 +1,10 @@
|
||||
# HG changeset patch
|
||||
-# Parent 96359f46b01fdb37e791f564495e8b2755a05233
|
||||
-
|
||||
+# Parent 70640278da97b0ca49e21c4bb52766b8af7db4db
|
||||
diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
|
||||
--- a/gfx/angle/Makefile.in
|
||||
+++ b/gfx/angle/Makefile.in
|
||||
@@ -73,17 +73,17 @@ CPPSRCS = \
|
||||
parseConst.cpp \
|
||||
ParseHelper.cpp \
|
||||
PoolAlloc.cpp \
|
||||
QualifierAlive.cpp \
|
||||
@@ -129,17 +128,17 @@ diff --git a/gfx/angle/src/compiler/comp
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define TRACE_ENABLED // define to enable debug message tracing
|
||||
diff --git a/gfx/angle/src/compiler/osinclude.h b/gfx/angle/src/compiler/osinclude.h
|
||||
--- a/gfx/angle/src/compiler/osinclude.h
|
||||
+++ b/gfx/angle/src/compiler/osinclude.h
|
||||
-@@ -32,17 +32,17 @@
|
||||
+@@ -30,17 +30,17 @@
|
||||
#include <windows.h>
|
||||
#elif defined(ANGLE_OS_POSIX)
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <errno.h>
|
||||
#endif // ANGLE_USE_NSPR
|
||||
|
||||
|
||||
# Parent b5604c321da4e3b5d6b0a940d18022a827061579
|
||||
diff --git a/gfx/angle/src/libGLESv2/Texture.cpp b/gfx/angle/src/libGLESv2/Texture.cpp
|
||||
--- a/gfx/angle/src/libGLESv2/Texture.cpp
|
||||
+++ b/gfx/angle/src/libGLESv2/Texture.cpp
|
||||
|
@ -1,15 +1,36 @@
|
||||
# HG changeset patch
|
||||
# Parent f9415c10c3ebd27856500cca7a0ee0f28a16f53c
|
||||
diff --git a/gfx/angle/src/compiler/preprocessor/scanner.h b/gfx/angle/src/compiler/preprocessor/scanner.h
|
||||
--- a/gfx/angle/src/compiler/preprocessor/scanner.h
|
||||
+++ b/gfx/angle/src/compiler/preprocessor/scanner.h
|
||||
@@ -44,17 +44,19 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILI
|
||||
//
|
||||
// scanner.h
|
||||
//
|
||||
# Parent e8b87ef36a1dae3bbd7abb13c4bb0a0bb8f5b58c
|
||||
diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla
|
||||
--- a/gfx/angle/README.mozilla
|
||||
+++ b/gfx/angle/README.mozilla
|
||||
@@ -2,16 +2,17 @@ This is the ANGLE project, from http://c
|
||||
|
||||
#if !defined(__SCANNER_H)
|
||||
#define __SCANNER_H 1
|
||||
Current revision: r802
|
||||
|
||||
== Applied local patches ==
|
||||
|
||||
In this order:
|
||||
angle-renaming-debug.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
|
||||
angle-intrinsic-msvc2005.patch - work around a MSVC 2005 compile error
|
||||
+ angle-limit-identifiers-to-250-chars.patch - see bug 675625
|
||||
|
||||
In addition to these patches, the Makefile.in files are ours, they're not present in upsteam ANGLE.
|
||||
|
||||
== How to update this ANGLE copy ==
|
||||
|
||||
1. Unapply patches
|
||||
2. Apply diff with new ANGLE version
|
||||
3. Reapply patches.
|
||||
diff --git a/gfx/angle/src/compiler/preprocessor/length_limits.h b/gfx/angle/src/compiler/preprocessor/length_limits.h
|
||||
--- a/gfx/angle/src/compiler/preprocessor/length_limits.h
|
||||
+++ b/gfx/angle/src/compiler/preprocessor/length_limits.h
|
||||
@@ -10,12 +10,14 @@
|
||||
|
||||
#if !defined(__LENGTH_LIMITS_H)
|
||||
#define __LENGTH_LIMITS_H 1
|
||||
|
||||
// These constants are factored out from the rest of the headers to
|
||||
// make it easier to reference them from the compiler sources.
|
||||
|
||||
// These lengths do not include the NULL terminator.
|
||||
-#define MAX_SYMBOL_NAME_LEN 256
|
||||
@ -18,9 +39,4 @@ diff --git a/gfx/angle/src/compiler/preprocessor/scanner.h b/gfx/angle/src/compi
|
||||
+#define MAX_SYMBOL_NAME_LEN 250
|
||||
#define MAX_STRING_LEN 511
|
||||
|
||||
#include "compiler/preprocessor/parser.h"
|
||||
|
||||
// Not really atom table stuff but needed first...
|
||||
|
||||
typedef struct SourceLoc_Rec {
|
||||
unsigned short file, line;
|
||||
#endif // !(defined(__LENGTH_LIMITS_H)
|
||||
|
@ -1,5 +1,5 @@
|
||||
# HG changeset patch
|
||||
# Parent 70640278da97b0ca49e21c4bb52766b8af7db4db
|
||||
# Parent 0239f15c7212413b5cffe66aee9ae5a4feb28f16
|
||||
diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
|
||||
--- a/gfx/angle/Makefile.in
|
||||
+++ b/gfx/angle/Makefile.in
|
||||
|
@ -17,6 +17,9 @@
|
||||
'.',
|
||||
'../include',
|
||||
],
|
||||
'defines': [
|
||||
'COMPILER_IMPLEMENTATION',
|
||||
],
|
||||
'sources': [
|
||||
'compiler/BaseTypes.h',
|
||||
'compiler/BuiltInFunctionEmulator.cpp',
|
||||
@ -60,7 +63,6 @@
|
||||
'compiler/QualifierAlive.h',
|
||||
'compiler/RemoveTree.cpp',
|
||||
'compiler/RemoveTree.h',
|
||||
'compiler/ShaderLang.cpp',
|
||||
'compiler/ShHandle.h',
|
||||
'compiler/SymbolTable.cpp',
|
||||
'compiler/SymbolTable.h',
|
||||
@ -77,6 +79,7 @@
|
||||
'compiler/preprocessor/cpp.c',
|
||||
'compiler/preprocessor/cpp.h',
|
||||
'compiler/preprocessor/cppstruct.c',
|
||||
'compiler/preprocessor/length_limits.h',
|
||||
'compiler/preprocessor/memory.c',
|
||||
'compiler/preprocessor/memory.h',
|
||||
'compiler/preprocessor/parser.h',
|
||||
@ -99,12 +102,15 @@
|
||||
},
|
||||
{
|
||||
'target_name': 'translator_glsl',
|
||||
'type': 'static_library',
|
||||
'type': '<(component)',
|
||||
'dependencies': ['translator_common'],
|
||||
'include_dirs': [
|
||||
'.',
|
||||
'../include',
|
||||
],
|
||||
'defines': [
|
||||
'COMPILER_IMPLEMENTATION',
|
||||
],
|
||||
'sources': [
|
||||
'compiler/CodeGenGLSL.cpp',
|
||||
'compiler/OutputESSL.cpp',
|
||||
@ -113,6 +119,7 @@
|
||||
'compiler/OutputGLSLBase.h',
|
||||
'compiler/OutputGLSL.cpp',
|
||||
'compiler/OutputGLSL.h',
|
||||
'compiler/ShaderLang.cpp',
|
||||
'compiler/TranslatorESSL.cpp',
|
||||
'compiler/TranslatorESSL.h',
|
||||
'compiler/TranslatorGLSL.cpp',
|
||||
@ -123,13 +130,17 @@
|
||||
},
|
||||
{
|
||||
'target_name': 'translator_hlsl',
|
||||
'type': 'static_library',
|
||||
'type': '<(component)',
|
||||
'dependencies': ['translator_common'],
|
||||
'include_dirs': [
|
||||
'.',
|
||||
'../include',
|
||||
],
|
||||
'defines': [
|
||||
'COMPILER_IMPLEMENTATION',
|
||||
],
|
||||
'sources': [
|
||||
'compiler/ShaderLang.cpp',
|
||||
'compiler/CodeGenHLSL.cpp',
|
||||
'compiler/OutputHLSL.cpp',
|
||||
'compiler/OutputHLSL.h',
|
||||
|
@ -1,7 +1,7 @@
|
||||
#define MAJOR_VERSION 0
|
||||
#define MINOR_VERSION 0
|
||||
#define BUILD_VERSION 0
|
||||
#define BUILD_REVISION 802
|
||||
#define BUILD_REVISION 809
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define MACRO_STRINGIFY(x) STRINGIFY(x)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
|
||||
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
@ -252,7 +252,7 @@ void TCompiler::mapLongVariableNames(TIntermNode* root)
|
||||
|
||||
int TCompiler::getMappedNameMaxLength() const
|
||||
{
|
||||
return MAX_IDENTIFIER_NAME_SIZE + 1;
|
||||
return MAX_SHORTENED_IDENTIFIER_SIZE + 1;
|
||||
}
|
||||
|
||||
const TExtensionBehavior& TCompiler::getExtensionBehavior() const
|
||||
|
@ -10,13 +10,13 @@ namespace {
|
||||
|
||||
TString mapLongName(int id, const TString& name, bool isVarying)
|
||||
{
|
||||
ASSERT(name.size() > MAX_IDENTIFIER_NAME_SIZE);
|
||||
ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE);
|
||||
TStringStream stream;
|
||||
stream << "webgl_";
|
||||
if (isVarying)
|
||||
stream << "v";
|
||||
stream << id << "_";
|
||||
stream << name.substr(0, MAX_IDENTIFIER_NAME_SIZE - stream.str().size());
|
||||
stream << name.substr(0, MAX_SHORTENED_IDENTIFIER_SIZE - stream.str().size());
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ MapLongVariableNames::MapLongVariableNames(
|
||||
void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol)
|
||||
{
|
||||
ASSERT(symbol != NULL);
|
||||
if (symbol->getSymbol().size() > MAX_IDENTIFIER_NAME_SIZE) {
|
||||
if (symbol->getSymbol().size() > MAX_SHORTENED_IDENTIFIER_SIZE) {
|
||||
switch (symbol->getQualifier()) {
|
||||
case EvqVaryingIn:
|
||||
case EvqVaryingOut:
|
||||
|
@ -13,10 +13,10 @@
|
||||
#include "compiler/VariableInfo.h"
|
||||
|
||||
// This size does not include '\0' in the end.
|
||||
#define MAX_IDENTIFIER_NAME_SIZE 32
|
||||
#define MAX_SHORTENED_IDENTIFIER_SIZE 32
|
||||
|
||||
// Traverses intermediate tree to map attributes and uniforms names that are
|
||||
// longer than MAX_IDENTIFIER_NAME_SIZE to MAX_IDENTIFIER_NAME_SIZE.
|
||||
// longer than MAX_SHORTENED_IDENTIFIER_SIZE to MAX_SHORTENED_IDENTIFIER_SIZE.
|
||||
class MapLongVariableNames : public TIntermTraverser {
|
||||
public:
|
||||
MapLongVariableNames(std::map<std::string, std::string>& varyingLongNameMap);
|
||||
|
@ -1425,6 +1425,53 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n
|
||||
return typedNode;
|
||||
}
|
||||
|
||||
bool TParseContext::enterStructDeclaration(int line, const TString& identifier)
|
||||
{
|
||||
++structNestingLevel;
|
||||
|
||||
// Embedded structure definitions are not supported per GLSL ES spec.
|
||||
// They aren't allowed in GLSL either, but we need to detect this here
|
||||
// so we don't rely on the GLSL compiler to catch it.
|
||||
if (structNestingLevel > 1) {
|
||||
error(line, "", "Embedded struct definitions are not allowed", "");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void TParseContext::exitStructDeclaration()
|
||||
{
|
||||
--structNestingLevel;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const int kWebGLMaxStructNesting = 4;
|
||||
|
||||
} // namespace
|
||||
|
||||
bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType)
|
||||
{
|
||||
if (shaderSpec != SH_WEBGL_SPEC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fieldType.getBasicType() != EbtStruct) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We're already inside a structure definition at this point, so add
|
||||
// one to the field's struct nesting.
|
||||
if (1 + fieldType.getDeepestStructNesting() >= kWebGLMaxStructNesting) {
|
||||
error(line, "", "", "Reference of struct type %s exceeds maximum struct nesting of %d",
|
||||
fieldType.getTypeName().c_str(), kWebGLMaxStructNesting);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse an array of strings using yyparse.
|
||||
//
|
||||
|
@ -31,9 +31,25 @@ struct TPragma {
|
||||
//
|
||||
struct TParseContext {
|
||||
TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) :
|
||||
intermediate(interm), symbolTable(symt), extensionBehavior(ext), infoSink(is), shaderType(type), shaderSpec(spec), compileOptions(options), checksPrecisionErrors(checksPrecErrors), sourcePath(sourcePath), treeRoot(0),
|
||||
numErrors(0), lexAfterType(false), loopNestingLevel(0),
|
||||
inTypeParen(false), contextPragma(true, false), scanner(NULL) { }
|
||||
intermediate(interm),
|
||||
symbolTable(symt),
|
||||
extensionBehavior(ext),
|
||||
infoSink(is),
|
||||
shaderType(type),
|
||||
shaderSpec(spec),
|
||||
compileOptions(options),
|
||||
sourcePath(sourcePath),
|
||||
treeRoot(0),
|
||||
numErrors(0),
|
||||
lexAfterType(false),
|
||||
loopNestingLevel(0),
|
||||
structNestingLevel(0),
|
||||
inTypeParen(false),
|
||||
currentFunctionType(NULL),
|
||||
functionReturnsValue(false),
|
||||
checksPrecisionErrors(checksPrecErrors),
|
||||
contextPragma(true, false),
|
||||
scanner(NULL) { }
|
||||
TIntermediate& intermediate; // to hold and build a parse tree
|
||||
TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed
|
||||
TExtensionBehavior& extensionBehavior; // mapping between supported extensions and current behavior.
|
||||
@ -46,6 +62,7 @@ struct TParseContext {
|
||||
int numErrors;
|
||||
bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
|
||||
int loopNestingLevel; // 0 if outside all loops
|
||||
int structNestingLevel; // incremented while parsing a struct declaration
|
||||
bool inTypeParen; // true if in parentheses, looking only for an identifier
|
||||
const TType* currentFunctionType; // the return type of the function that's currently being parsed
|
||||
bool functionReturnsValue; // true if a non-void function has a return
|
||||
@ -105,6 +122,14 @@ struct TParseContext {
|
||||
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
|
||||
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
|
||||
TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
|
||||
|
||||
// Performs an error check for embedded struct declarations.
|
||||
// Returns true if an error was raised due to the declaration of
|
||||
// this struct.
|
||||
bool enterStructDeclaration(TSourceLoc line, const TString& identifier);
|
||||
void exitStructDeclaration();
|
||||
|
||||
bool structNestingErrorCheck(TSourceLoc line, const TType& fieldType);
|
||||
};
|
||||
|
||||
int PaParseStrings(int count, const char* const string[], const int length[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
|
||||
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
@ -12,6 +12,7 @@
|
||||
#include "GLSLANG/ShaderLang.h"
|
||||
|
||||
#include "compiler/InitializeDll.h"
|
||||
#include "compiler/preprocessor/length_limits.h"
|
||||
#include "compiler/ShHandle.h"
|
||||
|
||||
//
|
||||
@ -19,16 +20,21 @@
|
||||
// and the shading language compiler.
|
||||
//
|
||||
|
||||
static int getVariableMaxLength(const TVariableInfoList& varList)
|
||||
static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle,
|
||||
int expectedValue)
|
||||
{
|
||||
TString::size_type maxLen = 0;
|
||||
for (TVariableInfoList::const_iterator i = varList.begin();
|
||||
i != varList.end(); ++i)
|
||||
{
|
||||
maxLen = std::max(maxLen, i->name.size());
|
||||
}
|
||||
// Add 1 to include null-termination character.
|
||||
return static_cast<int>(maxLen) + 1;
|
||||
int activeUniformLimit = 0;
|
||||
ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
|
||||
int activeAttribLimit = 0;
|
||||
ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
|
||||
return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit);
|
||||
}
|
||||
|
||||
static bool checkMappedNameMaxLength(const ShHandle handle, int expectedValue)
|
||||
{
|
||||
int mappedNameMaxLength = 0;
|
||||
ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
|
||||
return (expectedValue == mappedNameMaxLength);
|
||||
}
|
||||
|
||||
static void getVariableInfo(ShShaderInfo varType,
|
||||
@ -59,9 +65,20 @@ static void getVariableInfo(ShShaderInfo varType,
|
||||
if (length) *length = varInfo.name.size();
|
||||
*size = varInfo.size;
|
||||
*type = varInfo.type;
|
||||
strcpy(name, varInfo.name.c_str());
|
||||
if (mappedName)
|
||||
strcpy(mappedName, varInfo.mappedName.c_str());
|
||||
|
||||
// This size must match that queried by
|
||||
// SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH
|
||||
// in ShGetInfo, below.
|
||||
int activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN;
|
||||
ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength));
|
||||
strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength);
|
||||
if (mappedName) {
|
||||
// This size must match that queried by
|
||||
// SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
|
||||
int maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
|
||||
ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
|
||||
strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -191,16 +208,18 @@ void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params)
|
||||
*params = compiler->getUniforms().size();
|
||||
break;
|
||||
case SH_ACTIVE_UNIFORM_MAX_LENGTH:
|
||||
*params = getVariableMaxLength(compiler->getUniforms());
|
||||
*params = 1 + MAX_SYMBOL_NAME_LEN;
|
||||
break;
|
||||
case SH_ACTIVE_ATTRIBUTES:
|
||||
*params = compiler->getAttribs().size();
|
||||
break;
|
||||
case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
|
||||
*params = getVariableMaxLength(compiler->getAttribs());
|
||||
*params = 1 + MAX_SYMBOL_NAME_LEN;
|
||||
break;
|
||||
case SH_MAPPED_NAME_MAX_LENGTH:
|
||||
*params = compiler->getMappedNameMaxLength();
|
||||
// Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
|
||||
// handle array and struct dereferences.
|
||||
*params = 1 + MAX_SYMBOL_NAME_LEN;
|
||||
break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
//
|
||||
// TType helper function needs a place to live.
|
||||
//
|
||||
@ -71,6 +73,20 @@ int TType::getStructSize() const
|
||||
return structureSize;
|
||||
}
|
||||
|
||||
void TType::computeDeepestStructNesting()
|
||||
{
|
||||
if (!getStruct()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int maxNesting = 0;
|
||||
for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
|
||||
maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
|
||||
}
|
||||
|
||||
deepestStructNesting = 1 + maxNesting;
|
||||
}
|
||||
|
||||
//
|
||||
// Dump functions.
|
||||
//
|
||||
|
@ -85,21 +85,22 @@ public:
|
||||
TType() {}
|
||||
TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
|
||||
type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
|
||||
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), fieldName(0), mangled(0), typeName(0)
|
||||
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
|
||||
{
|
||||
}
|
||||
explicit TType(const TPublicType &p) :
|
||||
type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
|
||||
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), fieldName(0), mangled(0), typeName(0)
|
||||
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
|
||||
{
|
||||
if (p.userDef) {
|
||||
structure = p.userDef->getStruct();
|
||||
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
|
||||
computeDeepestStructNesting();
|
||||
}
|
||||
}
|
||||
TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
|
||||
type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
|
||||
maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), fieldName(0), mangled(0)
|
||||
maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0)
|
||||
{
|
||||
typeName = NewPoolTString(n.c_str());
|
||||
}
|
||||
@ -144,6 +145,7 @@ public:
|
||||
|
||||
structureSize = copyOf.structureSize;
|
||||
maxArraySize = copyOf.maxArraySize;
|
||||
deepestStructNesting = copyOf.deepestStructNesting;
|
||||
assert(copyOf.arrayInformationType == 0);
|
||||
arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level
|
||||
}
|
||||
@ -202,7 +204,7 @@ public:
|
||||
bool isScalar() const { return size == 1 && !matrix && !structure; }
|
||||
|
||||
TTypeList* getStruct() const { return structure; }
|
||||
void setStruct(TTypeList* s) { structure = s; }
|
||||
void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
|
||||
|
||||
const TString& getTypeName() const
|
||||
{
|
||||
@ -268,9 +270,24 @@ public:
|
||||
const char* getQualifierString() const { return ::getQualifierString(qualifier); }
|
||||
TString getCompleteString() const;
|
||||
|
||||
// If this type is a struct, returns the deepest struct nesting of
|
||||
// any field in the struct. For example:
|
||||
// struct nesting1 {
|
||||
// vec4 position;
|
||||
// };
|
||||
// struct nesting2 {
|
||||
// nesting1 field1;
|
||||
// vec4 field2;
|
||||
// };
|
||||
// For type "nesting2", this method would return 2 -- the number
|
||||
// of structures through which indirection must occur to reach the
|
||||
// deepest field (nesting2.field1.position).
|
||||
int getDeepestStructNesting() const { return deepestStructNesting; }
|
||||
|
||||
protected:
|
||||
void buildMangledName(TString&);
|
||||
int getStructSize() const;
|
||||
void computeDeepestStructNesting();
|
||||
|
||||
TBasicType type : 6;
|
||||
TPrecision precision;
|
||||
@ -284,6 +301,7 @@ protected:
|
||||
|
||||
TTypeList* structure; // 0 unless this is a struct
|
||||
mutable int structureSize;
|
||||
int deepestStructNesting;
|
||||
|
||||
TString *fieldName; // for structure field names
|
||||
TString *mangled;
|
||||
|
@ -1642,11 +1642,11 @@ type_specifier_nonarray
|
||||
;
|
||||
|
||||
struct_specifier
|
||||
: STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
|
||||
: STRUCT IDENTIFIER LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
|
||||
if (context->reservedErrorCheck($2.line, *$2.string))
|
||||
context->recover();
|
||||
|
||||
TType* structure = new TType($4, *$2.string);
|
||||
TType* structure = new TType($5, *$2.string);
|
||||
TVariable* userTypeDef = new TVariable($2.string, *structure, true);
|
||||
if (! context->symbolTable.insert(*userTypeDef)) {
|
||||
context->error($2.line, "redefinition", $2.string->c_str(), "struct");
|
||||
@ -1654,11 +1654,13 @@ struct_specifier
|
||||
}
|
||||
$$.setBasic(EbtStruct, EvqTemporary, $1.line);
|
||||
$$.userDef = structure;
|
||||
context->exitStructDeclaration();
|
||||
}
|
||||
| STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE {
|
||||
TType* structure = new TType($3, TString(""));
|
||||
| STRUCT LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
|
||||
TType* structure = new TType($4, TString(""));
|
||||
$$.setBasic(EbtStruct, EvqTemporary, $1.line);
|
||||
$$.userDef = structure;
|
||||
context->exitStructDeclaration();
|
||||
}
|
||||
;
|
||||
|
||||
@ -1708,6 +1710,10 @@ struct_declaration
|
||||
type->setStruct($1.userDef->getStruct());
|
||||
type->setTypeName($1.userDef->getTypeName());
|
||||
}
|
||||
|
||||
if (context->structNestingErrorCheck($1.line, *type)) {
|
||||
context->recover();
|
||||
}
|
||||
}
|
||||
}
|
||||
;
|
||||
|
23
gfx/angle/src/compiler/preprocessor/length_limits.h
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
//
|
||||
// length_limits.h
|
||||
//
|
||||
|
||||
#if !defined(__LENGTH_LIMITS_H)
|
||||
#define __LENGTH_LIMITS_H 1
|
||||
|
||||
// These constants are factored out from the rest of the headers to
|
||||
// make it easier to reference them from the compiler sources.
|
||||
|
||||
// These lengths do not include the NULL terminator.
|
||||
// see bug 675625: NVIDIA driver crash with lengths >= 253
|
||||
// this is only an interim fix, the real fix is name mapping, see ANGLE bug 144 / r619
|
||||
#define MAX_SYMBOL_NAME_LEN 250
|
||||
#define MAX_STRING_LEN 511
|
||||
|
||||
#endif // !(defined(__LENGTH_LIMITS_H)
|
@ -48,12 +48,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#if !defined(__SCANNER_H)
|
||||
#define __SCANNER_H 1
|
||||
|
||||
// These lengths do not include the NULL terminator.
|
||||
// see bug 675625: NVIDIA driver crash with lengths >= 253
|
||||
// this is only an interim fix, the real fix is name mapping, see ANGLE bug 144 / r619
|
||||
#define MAX_SYMBOL_NAME_LEN 250
|
||||
#define MAX_STRING_LEN 511
|
||||
|
||||
#include "compiler/preprocessor/length_limits.h"
|
||||
#include "compiler/preprocessor/parser.h"
|
||||
|
||||
// Not really atom table stuff but needed first...
|
||||
|
@ -40,6 +40,9 @@ namespace gl
|
||||
{
|
||||
Context::Context(const egl::Config *config, const gl::Context *shareContext) : mConfig(config)
|
||||
{
|
||||
mDisplay = NULL;
|
||||
mDevice = NULL;
|
||||
|
||||
mFenceHandleAllocator.setBaseHandle(0);
|
||||
|
||||
setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
@ -234,19 +237,20 @@ Context::~Context()
|
||||
|
||||
void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
|
||||
{
|
||||
IDirect3DDevice9 *device = display->getDevice();
|
||||
mDisplay = display;
|
||||
mDevice = mDisplay->getDevice();
|
||||
|
||||
if (!mHasBeenCurrent)
|
||||
{
|
||||
mDeviceCaps = display->getDeviceCaps();
|
||||
mDeviceCaps = mDisplay->getDeviceCaps();
|
||||
|
||||
mVertexDataManager = new VertexDataManager(this, device);
|
||||
mIndexDataManager = new IndexDataManager(this, device);
|
||||
mVertexDataManager = new VertexDataManager(this, mDevice);
|
||||
mIndexDataManager = new IndexDataManager(this, mDevice);
|
||||
mBlit = new Blit(this);
|
||||
|
||||
mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
|
||||
mSupportsVertexTexture = display->getVertexTextureSupport();
|
||||
mSupportsNonPower2Texture = display->getNonPower2TextureSupport();
|
||||
mSupportsVertexTexture = mDisplay->getVertexTextureSupport();
|
||||
mSupportsNonPower2Texture = mDisplay->getNonPower2TextureSupport();
|
||||
|
||||
mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight),
|
||||
(int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
|
||||
@ -268,7 +272,7 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
|
||||
for (int i = 0; i < sizeof(renderBufferFormats) / sizeof(D3DFORMAT); ++i)
|
||||
{
|
||||
bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
|
||||
display->getMultiSampleSupport(renderBufferFormats[i], multisampleArray);
|
||||
mDisplay->getMultiSampleSupport(renderBufferFormats[i], multisampleArray);
|
||||
mMultiSampleSupport[renderBufferFormats[i]] = multisampleArray;
|
||||
|
||||
for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
|
||||
@ -282,14 +286,14 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
|
||||
|
||||
mMaxSupportedSamples = max;
|
||||
|
||||
mSupportsEventQueries = display->getEventQuerySupport();
|
||||
mSupportsDXT1Textures = display->getDXT1TextureSupport();
|
||||
mSupportsDXT3Textures = display->getDXT3TextureSupport();
|
||||
mSupportsDXT5Textures = display->getDXT5TextureSupport();
|
||||
mSupportsFloatTextures = display->getFloatTextureSupport(&mSupportsFloatLinearFilter, &mSupportsFloatRenderableTextures);
|
||||
mSupportsHalfFloatTextures = display->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter, &mSupportsHalfFloatRenderableTextures);
|
||||
mSupportsLuminanceTextures = display->getLuminanceTextureSupport();
|
||||
mSupportsLuminanceAlphaTextures = display->getLuminanceAlphaTextureSupport();
|
||||
mSupportsEventQueries = mDisplay->getEventQuerySupport();
|
||||
mSupportsDXT1Textures = mDisplay->getDXT1TextureSupport();
|
||||
mSupportsDXT3Textures = mDisplay->getDXT3TextureSupport();
|
||||
mSupportsDXT5Textures = mDisplay->getDXT5TextureSupport();
|
||||
mSupportsFloatTextures = mDisplay->getFloatTextureSupport(&mSupportsFloatLinearFilter, &mSupportsFloatRenderableTextures);
|
||||
mSupportsHalfFloatTextures = mDisplay->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter, &mSupportsHalfFloatRenderableTextures);
|
||||
mSupportsLuminanceTextures = mDisplay->getLuminanceTextureSupport();
|
||||
mSupportsLuminanceAlphaTextures = mDisplay->getLuminanceAlphaTextureSupport();
|
||||
|
||||
mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16);
|
||||
|
||||
@ -1620,8 +1624,6 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
|
||||
// scissor rectangle to the Direct3D 9 device
|
||||
bool Context::applyRenderTarget(bool ignoreViewport)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
|
||||
Framebuffer *framebufferObject = getDrawFramebuffer();
|
||||
|
||||
if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
|
||||
@ -1642,7 +1644,7 @@ bool Context::applyRenderTarget(bool ignoreViewport)
|
||||
{
|
||||
return false; // Context must be lost
|
||||
}
|
||||
device->SetRenderTarget(0, renderTarget);
|
||||
mDevice->SetRenderTarget(0, renderTarget);
|
||||
mAppliedRenderTargetSerial = renderTargetSerial;
|
||||
mScissorStateDirty = true; // Scissor area must be clamped to render target's size-- this is different for different render targets.
|
||||
renderTargetChanged = true;
|
||||
@ -1677,7 +1679,7 @@ bool Context::applyRenderTarget(bool ignoreViewport)
|
||||
stencilbufferSerial != mAppliedStencilbufferSerial ||
|
||||
!mDepthStencilInitialized)
|
||||
{
|
||||
device->SetDepthStencilSurface(depthStencil);
|
||||
mDevice->SetDepthStencilSurface(depthStencil);
|
||||
mAppliedDepthbufferSerial = depthbufferSerial;
|
||||
mAppliedStencilbufferSerial = stencilbufferSerial;
|
||||
mDepthStencilInitialized = true;
|
||||
@ -1730,7 +1732,7 @@ bool Context::applyRenderTarget(bool ignoreViewport)
|
||||
|
||||
if (!mViewportInitialized || memcmp(&viewport, &mSetViewport, sizeof mSetViewport) != 0)
|
||||
{
|
||||
device->SetViewport(&viewport);
|
||||
mDevice->SetViewport(&viewport);
|
||||
mSetViewport = viewport;
|
||||
mViewportInitialized = true;
|
||||
mDxUniformsDirty = true;
|
||||
@ -1745,12 +1747,12 @@ bool Context::applyRenderTarget(bool ignoreViewport)
|
||||
rect.top = clamp(rect.top, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
|
||||
rect.right = clamp(rect.right, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
|
||||
rect.bottom = clamp(rect.bottom, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
|
||||
device->SetScissorRect(&rect);
|
||||
device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
mDevice->SetScissorRect(&rect);
|
||||
mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
mScissorStateDirty = false;
|
||||
@ -1786,7 +1788,6 @@ bool Context::applyRenderTarget(bool ignoreViewport)
|
||||
// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
|
||||
void Context::applyState(GLenum drawMode)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
Program *programObject = getCurrentProgram();
|
||||
|
||||
Framebuffer *framebufferObject = getDrawFramebuffer();
|
||||
@ -1801,8 +1802,7 @@ void Context::applyState(GLenum drawMode)
|
||||
GLint alwaysFront = !isTriangleMode(drawMode);
|
||||
programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
|
||||
|
||||
egl::Display *display = getDisplay();
|
||||
D3DADAPTER_IDENTIFIER9 *identifier = display->getAdapterIdentifier();
|
||||
D3DADAPTER_IDENTIFIER9 *identifier = mDisplay->getAdapterIdentifier();
|
||||
bool zeroColorMaskAllowed = identifier->VendorId != 0x1002;
|
||||
// Apparently some ATI cards have a bug where a draw with a zero color
|
||||
// write mask can cause later draws to have incorrect results. Instead,
|
||||
@ -1814,11 +1814,11 @@ void Context::applyState(GLenum drawMode)
|
||||
{
|
||||
if (mState.cullFace)
|
||||
{
|
||||
device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, adjustedFrontFace));
|
||||
mDevice->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, adjustedFrontFace));
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
}
|
||||
|
||||
mCullStateDirty = false;
|
||||
@ -1828,12 +1828,12 @@ void Context::applyState(GLenum drawMode)
|
||||
{
|
||||
if (mState.depthTest)
|
||||
{
|
||||
device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
|
||||
device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
|
||||
mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
|
||||
mDevice->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
|
||||
mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
|
||||
}
|
||||
|
||||
mDepthStateDirty = false;
|
||||
@ -1849,43 +1849,43 @@ void Context::applyState(GLenum drawMode)
|
||||
{
|
||||
if (mState.blend)
|
||||
{
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
|
||||
if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
|
||||
mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
|
||||
{
|
||||
device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
|
||||
mDevice->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
|
||||
mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
|
||||
unorm<8>(mState.blendColor.alpha),
|
||||
unorm<8>(mState.blendColor.alpha),
|
||||
unorm<8>(mState.blendColor.alpha)));
|
||||
}
|
||||
|
||||
device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
|
||||
device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
|
||||
device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
|
||||
mDevice->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
|
||||
mDevice->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
|
||||
mDevice->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
|
||||
|
||||
if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
|
||||
mState.destBlendRGB != mState.destBlendAlpha ||
|
||||
mState.blendEquationRGB != mState.blendEquationAlpha)
|
||||
{
|
||||
device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
||||
|
||||
device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
|
||||
device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
|
||||
device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
|
||||
mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
|
||||
mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
|
||||
mDevice->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
|
||||
mBlendStateDirty = false;
|
||||
@ -1895,8 +1895,8 @@ void Context::applyState(GLenum drawMode)
|
||||
{
|
||||
if (mState.stencilTest && framebufferObject->hasStencil())
|
||||
{
|
||||
device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
|
||||
device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
|
||||
|
||||
// FIXME: Unsupported by D3D9
|
||||
const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
|
||||
@ -1914,37 +1914,37 @@ void Context::applyState(GLenum drawMode)
|
||||
gl::DepthStencilbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
|
||||
GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
|
||||
|
||||
device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
|
||||
device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
|
||||
es2dx::ConvertComparison(mState.stencilFunc));
|
||||
|
||||
device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
|
||||
device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
|
||||
|
||||
device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
|
||||
es2dx::ConvertStencilOp(mState.stencilFail));
|
||||
device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
|
||||
es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
|
||||
device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
|
||||
es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
|
||||
|
||||
device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
|
||||
device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
|
||||
es2dx::ConvertComparison(mState.stencilBackFunc));
|
||||
|
||||
device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
|
||||
device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
|
||||
|
||||
device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
|
||||
es2dx::ConvertStencilOp(mState.stencilBackFail));
|
||||
device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
|
||||
es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
|
||||
device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
|
||||
es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
}
|
||||
|
||||
mStencilStateDirty = false;
|
||||
@ -1958,18 +1958,18 @@ void Context::applyState(GLenum drawMode)
|
||||
if (colorMask == 0 && !zeroColorMaskAllowed)
|
||||
{
|
||||
// Enable green channel, but set blending so nothing will be drawn.
|
||||
device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
|
||||
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
|
||||
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
|
||||
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
|
||||
device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
|
||||
mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
|
||||
mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
|
||||
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
|
||||
}
|
||||
device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
|
||||
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
|
||||
|
||||
mMaskStateDirty = false;
|
||||
}
|
||||
@ -1981,15 +1981,15 @@ void Context::applyState(GLenum drawMode)
|
||||
gl::DepthStencilbuffer *depthbuffer = framebufferObject->getDepthbuffer();
|
||||
if (depthbuffer)
|
||||
{
|
||||
device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
|
||||
mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
|
||||
float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
|
||||
device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
|
||||
mDevice->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
|
||||
device->SetRenderState(D3DRS_DEPTHBIAS, 0);
|
||||
mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
|
||||
mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
|
||||
}
|
||||
|
||||
mPolygonOffsetStateDirty = false;
|
||||
@ -2002,7 +2002,7 @@ void Context::applyState(GLenum drawMode)
|
||||
FIXME("Sample alpha to coverage is unimplemented.");
|
||||
}
|
||||
|
||||
device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
|
||||
if (mState.sampleCoverage)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
@ -2027,11 +2027,11 @@ void Context::applyState(GLenum drawMode)
|
||||
mask = ~mask;
|
||||
}
|
||||
|
||||
device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask);
|
||||
mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
|
||||
mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
mSampleStateDirty = false;
|
||||
@ -2039,7 +2039,7 @@ void Context::applyState(GLenum drawMode)
|
||||
|
||||
if (mDitherStateDirty)
|
||||
{
|
||||
device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
|
||||
mDevice->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
|
||||
|
||||
mDitherStateDirty = false;
|
||||
}
|
||||
@ -2055,20 +2055,19 @@ GLenum Context::applyVertexBuffer(GLint first, GLsizei count)
|
||||
return err;
|
||||
}
|
||||
|
||||
return mVertexDeclarationCache.applyDeclaration(attributes, getCurrentProgram());
|
||||
return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, getCurrentProgram());
|
||||
}
|
||||
|
||||
// Applies the indices and element array bindings to the Direct3D 9 device
|
||||
GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
|
||||
|
||||
if (err == GL_NO_ERROR)
|
||||
{
|
||||
if (indexInfo->serial != mAppliedIBSerial)
|
||||
{
|
||||
device->SetIndices(indexInfo->indexBuffer);
|
||||
mDevice->SetIndices(indexInfo->indexBuffer);
|
||||
mAppliedIBSerial = indexInfo->serial;
|
||||
}
|
||||
}
|
||||
@ -2079,15 +2078,14 @@ GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode
|
||||
// Applies the shaders and shader constants to the Direct3D 9 device
|
||||
void Context::applyShaders()
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
Program *programObject = getCurrentProgram();
|
||||
if (programObject->getSerial() != mAppliedProgramSerial)
|
||||
{
|
||||
IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
|
||||
IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
|
||||
|
||||
device->SetPixelShader(pixelShader);
|
||||
device->SetVertexShader(vertexShader);
|
||||
mDevice->SetPixelShader(pixelShader);
|
||||
mDevice->SetVertexShader(vertexShader);
|
||||
programObject->dirtyAllUniforms();
|
||||
mAppliedProgramSerial = programObject->getSerial();
|
||||
}
|
||||
@ -2111,7 +2109,6 @@ void Context::applyTextures()
|
||||
// and sets the texture and its addressing/filtering state (or NULL when inactive).
|
||||
void Context::applyTextures(SamplerType type)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
Program *programObject = getCurrentProgram();
|
||||
|
||||
int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; // Range of Direct3D 9 samplers of given sampler type
|
||||
@ -2143,24 +2140,24 @@ void Context::applyTextures(SamplerType type)
|
||||
GLenum minFilter = texture->getMinFilter();
|
||||
GLenum magFilter = texture->getMagFilter();
|
||||
|
||||
device->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
|
||||
device->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
|
||||
mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
|
||||
mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
|
||||
|
||||
device->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
|
||||
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
|
||||
D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
|
||||
es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
|
||||
device->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
|
||||
device->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
|
||||
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
|
||||
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
|
||||
}
|
||||
|
||||
if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyImage())
|
||||
{
|
||||
device->SetTexture(d3dSampler, d3dTexture);
|
||||
mDevice->SetTexture(d3dSampler, d3dTexture);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetTexture(d3dSampler, getIncompleteTexture(textureType)->getTexture());
|
||||
mDevice->SetTexture(d3dSampler, getIncompleteTexture(textureType)->getTexture());
|
||||
}
|
||||
|
||||
appliedTextureSerial[samplerIndex] = texture->getSerial();
|
||||
@ -2171,7 +2168,7 @@ void Context::applyTextures(SamplerType type)
|
||||
{
|
||||
if (appliedTextureSerial[samplerIndex] != 0)
|
||||
{
|
||||
device->SetTexture(d3dSampler, NULL);
|
||||
mDevice->SetTexture(d3dSampler, NULL);
|
||||
appliedTextureSerial[samplerIndex] = 0;
|
||||
}
|
||||
}
|
||||
@ -2181,7 +2178,7 @@ void Context::applyTextures(SamplerType type)
|
||||
{
|
||||
if (appliedTextureSerial[samplerIndex] != 0)
|
||||
{
|
||||
device->SetTexture(samplerIndex + d3dSamplerOffset, NULL);
|
||||
mDevice->SetTexture(samplerIndex + d3dSamplerOffset, NULL);
|
||||
appliedTextureSerial[samplerIndex] = 0;
|
||||
}
|
||||
}
|
||||
@ -2208,13 +2205,11 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
||||
return; // Context must be lost, return silently
|
||||
}
|
||||
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
renderTarget->GetDesc(&desc);
|
||||
|
||||
IDirect3DSurface9 *systemSurface;
|
||||
HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
|
||||
HRESULT result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
@ -2228,7 +2223,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
result = device->GetRenderTargetData(renderTarget, systemSurface);
|
||||
result = mDevice->GetRenderTargetData(renderTarget, systemSurface);
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
@ -2457,8 +2452,6 @@ void Context::clear(GLbitfield mask)
|
||||
return error(GL_INVALID_FRAMEBUFFER_OPERATION);
|
||||
}
|
||||
|
||||
egl::Display *display = getDisplay();
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
DWORD flags = 0;
|
||||
|
||||
if (mask & GL_COLOR_BUFFER_BIT)
|
||||
@ -2550,32 +2543,32 @@ void Context::clear(GLbitfield mask)
|
||||
HRESULT hr;
|
||||
if (mMaskedClearSavedState == NULL)
|
||||
{
|
||||
hr = device->BeginStateBlock();
|
||||
hr = mDevice->BeginStateBlock();
|
||||
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
|
||||
|
||||
device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
|
||||
device->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
||||
device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
|
||||
device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
||||
device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
device->SetPixelShader(NULL);
|
||||
device->SetVertexShader(NULL);
|
||||
device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
|
||||
device->SetStreamSource(0, NULL, 0, 0);
|
||||
device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
||||
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
|
||||
device->SetRenderState(D3DRS_TEXTUREFACTOR, color);
|
||||
device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
|
||||
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
|
||||
mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
||||
mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
|
||||
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
||||
mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
mDevice->SetPixelShader(NULL);
|
||||
mDevice->SetVertexShader(NULL);
|
||||
mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
|
||||
mDevice->SetStreamSource(0, NULL, 0, 0);
|
||||
mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
||||
mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||||
mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
|
||||
mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
|
||||
mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
|
||||
mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
|
||||
|
||||
hr = device->EndStateBlock(&mMaskedClearSavedState);
|
||||
hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
|
||||
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
|
||||
}
|
||||
|
||||
@ -2587,51 +2580,51 @@ void Context::clear(GLbitfield mask)
|
||||
ASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
|
||||
device->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
||||
device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
|
||||
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
|
||||
mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
||||
mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
|
||||
|
||||
if (flags & D3DCLEAR_TARGET)
|
||||
{
|
||||
device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha));
|
||||
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
||||
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
||||
}
|
||||
|
||||
if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
|
||||
{
|
||||
device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
|
||||
device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
|
||||
device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
|
||||
device->SetRenderState(D3DRS_STENCILREF, stencil);
|
||||
device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
|
||||
device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
|
||||
device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
|
||||
device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
|
||||
mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
|
||||
mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
|
||||
mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
|
||||
mStencilStateDirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
}
|
||||
|
||||
device->SetPixelShader(NULL);
|
||||
device->SetVertexShader(NULL);
|
||||
device->SetFVF(D3DFVF_XYZRHW);
|
||||
device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
||||
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
|
||||
device->SetRenderState(D3DRS_TEXTUREFACTOR, color);
|
||||
device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
|
||||
mDevice->SetPixelShader(NULL);
|
||||
mDevice->SetVertexShader(NULL);
|
||||
mDevice->SetFVF(D3DFVF_XYZRHW);
|
||||
mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
||||
mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||||
mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
|
||||
mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
|
||||
mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
|
||||
mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
|
||||
|
||||
float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges
|
||||
quad[0][0] = -0.5f;
|
||||
@ -2654,14 +2647,14 @@ void Context::clear(GLbitfield mask)
|
||||
quad[3][2] = 0.0f;
|
||||
quad[3][3] = 1.0f;
|
||||
|
||||
display->startScene();
|
||||
device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
|
||||
mDisplay->startScene();
|
||||
mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
|
||||
|
||||
if (flags & D3DCLEAR_ZBUFFER)
|
||||
{
|
||||
device->SetRenderState(D3DRS_ZENABLE, TRUE);
|
||||
device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
|
||||
device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
|
||||
mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
|
||||
mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
|
||||
}
|
||||
|
||||
if (mMaskedClearSavedState != NULL)
|
||||
@ -2671,7 +2664,7 @@ void Context::clear(GLbitfield mask)
|
||||
}
|
||||
else if (flags)
|
||||
{
|
||||
device->Clear(0, NULL, flags, color, depth, stencil);
|
||||
mDevice->Clear(0, NULL, flags, color, depth, stencil);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2682,8 +2675,6 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
|
||||
return error(GL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
egl::Display *display = getDisplay();
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
D3DPRIMITIVETYPE primitiveType;
|
||||
int primitiveCount;
|
||||
|
||||
@ -2718,9 +2709,9 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
|
||||
|
||||
if (!cullSkipsDraw(mode))
|
||||
{
|
||||
display->startScene();
|
||||
mDisplay->startScene();
|
||||
|
||||
device->DrawPrimitive(primitiveType, 0, primitiveCount);
|
||||
mDevice->DrawPrimitive(primitiveType, 0, primitiveCount);
|
||||
|
||||
if (mode == GL_LINE_LOOP) // Draw the last segment separately
|
||||
{
|
||||
@ -2741,8 +2732,6 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *
|
||||
return error(GL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
egl::Display *display = getDisplay();
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
D3DPRIMITIVETYPE primitiveType;
|
||||
int primitiveCount;
|
||||
|
||||
@ -2785,9 +2774,9 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *
|
||||
|
||||
if (!cullSkipsDraw(mode))
|
||||
{
|
||||
display->startScene();
|
||||
mDisplay->startScene();
|
||||
|
||||
device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount);
|
||||
mDevice->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount);
|
||||
|
||||
if (mode == GL_LINE_LOOP) // Draw the last segment separately
|
||||
{
|
||||
@ -2796,92 +2785,13 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *
|
||||
}
|
||||
}
|
||||
|
||||
void Context::finish()
|
||||
// Implements glFlush when block is false, glFinish when block is true
|
||||
void Context::sync(bool block)
|
||||
{
|
||||
egl::Display *display = getDisplay();
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
IDirect3DQuery9 *occlusionQuery = NULL;
|
||||
HRESULT result;
|
||||
|
||||
result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
|
||||
if (FAILED(result))
|
||||
{
|
||||
ERR("CreateQuery failed hr=%x\n", result);
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
{
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
IDirect3DStateBlock9 *savedState = NULL;
|
||||
result = device->CreateStateBlock(D3DSBT_ALL, &savedState);
|
||||
if (FAILED(result))
|
||||
{
|
||||
ERR("CreateStateBlock failed hr=%x\n", result);
|
||||
occlusionQuery->Release();
|
||||
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
{
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
result = occlusionQuery->Issue(D3DISSUE_BEGIN);
|
||||
if (FAILED(result))
|
||||
{
|
||||
ERR("occlusionQuery->Issue(BEGIN) failed hr=%x\n", result);
|
||||
occlusionQuery->Release();
|
||||
savedState->Release();
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Render something outside the render target
|
||||
device->SetPixelShader(NULL);
|
||||
device->SetVertexShader(NULL);
|
||||
device->SetFVF(D3DFVF_XYZRHW);
|
||||
float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
|
||||
display->startScene();
|
||||
device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
|
||||
|
||||
result = occlusionQuery->Issue(D3DISSUE_END);
|
||||
if (FAILED(result))
|
||||
{
|
||||
ERR("occlusionQuery->Issue(END) failed hr=%x\n", result);
|
||||
occlusionQuery->Release();
|
||||
savedState->Apply();
|
||||
savedState->Release();
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((result = occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH)) == S_FALSE)
|
||||
{
|
||||
// Keep polling, but allow other threads to do something useful first
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
occlusionQuery->Release();
|
||||
savedState->Apply();
|
||||
savedState->Release();
|
||||
|
||||
if (result == D3DERR_DEVICELOST)
|
||||
{
|
||||
error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
void Context::flush()
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
IDirect3DQuery9 *eventQuery = NULL;
|
||||
HRESULT result;
|
||||
|
||||
result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
|
||||
result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
|
||||
if (FAILED(result))
|
||||
{
|
||||
ERR("CreateQuery failed hr=%x\n", result);
|
||||
@ -2902,7 +2812,18 @@ void Context::flush()
|
||||
return;
|
||||
}
|
||||
|
||||
result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
|
||||
do
|
||||
{
|
||||
result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
|
||||
|
||||
if(block && result == S_FALSE)
|
||||
{
|
||||
// Keep polling, but allow other threads to do something useful first
|
||||
Sleep(0);
|
||||
}
|
||||
}
|
||||
while(block && result == S_FALSE);
|
||||
|
||||
eventQuery->Release();
|
||||
|
||||
if (result == D3DERR_DEVICELOST)
|
||||
@ -2913,7 +2834,6 @@ void Context::flush()
|
||||
|
||||
void Context::drawClosingLine(unsigned int first, unsigned int last)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
IDirect3DIndexBuffer9 *indexBuffer = NULL;
|
||||
bool succeeded = false;
|
||||
UINT offset;
|
||||
@ -2924,7 +2844,7 @@ void Context::drawClosingLine(unsigned int first, unsigned int last)
|
||||
|
||||
if (!mClosingIB)
|
||||
{
|
||||
mClosingIB = new StreamingIndexBuffer(device, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
|
||||
mClosingIB = new StreamingIndexBuffer(mDevice, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
|
||||
}
|
||||
|
||||
mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
|
||||
@ -2945,7 +2865,7 @@ void Context::drawClosingLine(unsigned int first, unsigned int last)
|
||||
|
||||
if (!mClosingIB)
|
||||
{
|
||||
mClosingIB = new StreamingIndexBuffer(device, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
|
||||
mClosingIB = new StreamingIndexBuffer(mDevice, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
|
||||
}
|
||||
|
||||
mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
|
||||
@ -2963,10 +2883,10 @@ void Context::drawClosingLine(unsigned int first, unsigned int last)
|
||||
|
||||
if (succeeded)
|
||||
{
|
||||
device->SetIndices(mClosingIB->getBuffer());
|
||||
mDevice->SetIndices(mClosingIB->getBuffer());
|
||||
mAppliedIBSerial = mClosingIB->getSerial();
|
||||
|
||||
device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, last, offset, 1);
|
||||
mDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, last, offset, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3493,8 +3413,7 @@ const char *Context::getExtensionString() const
|
||||
|
||||
void Context::initRendererString()
|
||||
{
|
||||
egl::Display *display = getDisplay();
|
||||
D3DADAPTER_IDENTIFIER9 *identifier = display->getAdapterIdentifier();
|
||||
D3DADAPTER_IDENTIFIER9 *identifier = mDisplay->getAdapterIdentifier();
|
||||
|
||||
mRendererString = "ANGLE (";
|
||||
mRendererString += identifier->Description;
|
||||
@ -3510,8 +3429,6 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
|
||||
Framebuffer *readFramebuffer = getReadFramebuffer();
|
||||
Framebuffer *drawFramebuffer = getDrawFramebuffer();
|
||||
|
||||
@ -3752,12 +3669,11 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
|
||||
|
||||
if (blitRenderTarget || blitDepthStencil)
|
||||
{
|
||||
egl::Display *display = getDisplay();
|
||||
display->endScene();
|
||||
mDisplay->endScene();
|
||||
|
||||
if (blitRenderTarget)
|
||||
{
|
||||
HRESULT result = device->StretchRect(readFramebuffer->getRenderTarget(), &sourceTrimmedRect,
|
||||
HRESULT result = mDevice->StretchRect(readFramebuffer->getRenderTarget(), &sourceTrimmedRect,
|
||||
drawFramebuffer->getRenderTarget(), &destTrimmedRect, D3DTEXF_NONE);
|
||||
|
||||
if (FAILED(result))
|
||||
@ -3769,7 +3685,7 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
|
||||
|
||||
if (blitDepthStencil)
|
||||
{
|
||||
HRESULT result = device->StretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, D3DTEXF_NONE);
|
||||
HRESULT result = mDevice->StretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, D3DTEXF_NONE);
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
@ -3800,10 +3716,8 @@ VertexDeclarationCache::~VertexDeclarationCache()
|
||||
}
|
||||
}
|
||||
|
||||
GLenum VertexDeclarationCache::applyDeclaration(TranslatedAttribute attributes[], Program *program)
|
||||
GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], Program *program)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
|
||||
D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS + 1];
|
||||
D3DVERTEXELEMENT9 *element = &elements[0];
|
||||
|
||||
|
@ -228,7 +228,7 @@ class VertexDeclarationCache
|
||||
VertexDeclarationCache();
|
||||
~VertexDeclarationCache();
|
||||
|
||||
GLenum applyDeclaration(TranslatedAttribute attributes[], Program *program);
|
||||
GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], Program *program);
|
||||
|
||||
void markStateDirty();
|
||||
|
||||
@ -421,8 +421,7 @@ class Context
|
||||
void clear(GLbitfield mask);
|
||||
void drawArrays(GLenum mode, GLint first, GLsizei count);
|
||||
void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
void finish();
|
||||
void flush();
|
||||
void sync(bool block); // flush/finish
|
||||
|
||||
// Draw the last segment of a line loop
|
||||
void drawClosingLine(unsigned int first, unsigned int last);
|
||||
@ -497,6 +496,8 @@ class Context
|
||||
void initRendererString();
|
||||
|
||||
const egl::Config *const mConfig;
|
||||
egl::Display *mDisplay;
|
||||
IDirect3DDevice9 *mDevice;
|
||||
|
||||
State mState;
|
||||
|
||||
|
@ -59,6 +59,7 @@ UniformLocation::UniformLocation(const std::string &_name, unsigned int element,
|
||||
|
||||
Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle), mSerial(issueSerial())
|
||||
{
|
||||
mDevice = getDevice();
|
||||
mFragmentShader = NULL;
|
||||
mVertexShader = NULL;
|
||||
|
||||
@ -1675,9 +1676,8 @@ void Program::link()
|
||||
|
||||
if (vertexBinary && pixelBinary)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
HRESULT vertexResult = device->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
|
||||
HRESULT pixelResult = device->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
|
||||
HRESULT vertexResult = mDevice->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
|
||||
HRESULT pixelResult = mDevice->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
|
||||
|
||||
if (vertexResult == D3DERR_OUTOFVIDEOMEMORY || vertexResult == E_OUTOFMEMORY || pixelResult == D3DERR_OUTOFVIDEOMEMORY || pixelResult == E_OUTOFMEMORY)
|
||||
{
|
||||
@ -2051,8 +2051,6 @@ std::string Program::undecorateUniform(const std::string &_name)
|
||||
|
||||
void Program::applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
|
||||
float *vector = NULL;
|
||||
BOOL *boolVector = NULL;
|
||||
|
||||
@ -2091,11 +2089,11 @@ void Program::applyUniformnbv(Uniform *targetUniform, GLsizei count, int width,
|
||||
{
|
||||
if (targetUniform->ps.registerSet == D3DXRS_FLOAT4)
|
||||
{
|
||||
device->SetPixelShaderConstantF(targetUniform->ps.registerIndex, vector, targetUniform->ps.registerCount);
|
||||
mDevice->SetPixelShaderConstantF(targetUniform->ps.registerIndex, vector, targetUniform->ps.registerCount);
|
||||
}
|
||||
else if (targetUniform->ps.registerSet == D3DXRS_BOOL)
|
||||
{
|
||||
device->SetPixelShaderConstantB(targetUniform->ps.registerIndex, boolVector, targetUniform->ps.registerCount);
|
||||
mDevice->SetPixelShaderConstantB(targetUniform->ps.registerIndex, boolVector, targetUniform->ps.registerCount);
|
||||
}
|
||||
else UNREACHABLE();
|
||||
}
|
||||
@ -2104,11 +2102,11 @@ void Program::applyUniformnbv(Uniform *targetUniform, GLsizei count, int width,
|
||||
{
|
||||
if (targetUniform->vs.registerSet == D3DXRS_FLOAT4)
|
||||
{
|
||||
device->SetVertexShaderConstantF(targetUniform->vs.registerIndex, vector, targetUniform->vs.registerCount);
|
||||
mDevice->SetVertexShaderConstantF(targetUniform->vs.registerIndex, vector, targetUniform->vs.registerCount);
|
||||
}
|
||||
else if (targetUniform->vs.registerSet == D3DXRS_BOOL)
|
||||
{
|
||||
device->SetVertexShaderConstantB(targetUniform->vs.registerIndex, boolVector, targetUniform->vs.registerCount);
|
||||
mDevice->SetVertexShaderConstantB(targetUniform->vs.registerIndex, boolVector, targetUniform->vs.registerCount);
|
||||
}
|
||||
else UNREACHABLE();
|
||||
}
|
||||
@ -2119,16 +2117,14 @@ void Program::applyUniformnbv(Uniform *targetUniform, GLsizei count, int width,
|
||||
|
||||
bool Program::applyUniformnfv(Uniform *targetUniform, const GLfloat *v)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
|
||||
if (targetUniform->ps.registerCount)
|
||||
{
|
||||
device->SetPixelShaderConstantF(targetUniform->ps.registerIndex, v, targetUniform->ps.registerCount);
|
||||
mDevice->SetPixelShaderConstantF(targetUniform->ps.registerIndex, v, targetUniform->ps.registerCount);
|
||||
}
|
||||
|
||||
if (targetUniform->vs.registerCount)
|
||||
{
|
||||
device->SetVertexShaderConstantF(targetUniform->vs.registerIndex, v, targetUniform->vs.registerCount);
|
||||
mDevice->SetVertexShaderConstantF(targetUniform->vs.registerIndex, v, targetUniform->vs.registerCount);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -2143,8 +2139,6 @@ bool Program::applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint
|
||||
vector[i] = D3DXVECTOR4((float)v[i], 0, 0, 0);
|
||||
}
|
||||
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
|
||||
if (targetUniform->ps.registerCount)
|
||||
{
|
||||
if (targetUniform->ps.registerSet == D3DXRS_SAMPLER)
|
||||
@ -2165,7 +2159,7 @@ bool Program::applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint
|
||||
else
|
||||
{
|
||||
ASSERT(targetUniform->ps.registerSet == D3DXRS_FLOAT4);
|
||||
device->SetPixelShaderConstantF(targetUniform->ps.registerIndex, (const float*)vector, targetUniform->ps.registerCount);
|
||||
mDevice->SetPixelShaderConstantF(targetUniform->ps.registerIndex, (const float*)vector, targetUniform->ps.registerCount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2189,7 +2183,7 @@ bool Program::applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint
|
||||
else
|
||||
{
|
||||
ASSERT(targetUniform->vs.registerSet == D3DXRS_FLOAT4);
|
||||
device->SetVertexShaderConstantF(targetUniform->vs.registerIndex, (const float *)vector, targetUniform->vs.registerCount);
|
||||
mDevice->SetVertexShaderConstantF(targetUniform->vs.registerIndex, (const float *)vector, targetUniform->vs.registerCount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2254,18 +2248,16 @@ bool Program::applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint
|
||||
|
||||
void Program::applyUniformniv(Uniform *targetUniform, GLsizei count, const D3DXVECTOR4 *vector)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
|
||||
if (targetUniform->ps.registerCount)
|
||||
{
|
||||
ASSERT(targetUniform->ps.registerSet == D3DXRS_FLOAT4);
|
||||
device->SetPixelShaderConstantF(targetUniform->ps.registerIndex, (const float *)vector, targetUniform->ps.registerCount);
|
||||
mDevice->SetPixelShaderConstantF(targetUniform->ps.registerIndex, (const float *)vector, targetUniform->ps.registerCount);
|
||||
}
|
||||
|
||||
if (targetUniform->vs.registerCount)
|
||||
{
|
||||
ASSERT(targetUniform->vs.registerSet == D3DXRS_FLOAT4);
|
||||
device->SetVertexShaderConstantF(targetUniform->vs.registerIndex, (const float *)vector, targetUniform->vs.registerCount);
|
||||
mDevice->SetVertexShaderConstantF(targetUniform->vs.registerIndex, (const float *)vector, targetUniform->vs.registerCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,6 +172,7 @@ class Program
|
||||
|
||||
static unsigned int issueSerial();
|
||||
|
||||
IDirect3DDevice9 *mDevice;
|
||||
FragmentShader *mFragmentShader;
|
||||
VertexShader *mVertexShader;
|
||||
|
||||
|
@ -1951,7 +1951,7 @@ void __stdcall glFinish(void)
|
||||
|
||||
if (context)
|
||||
{
|
||||
context->finish();
|
||||
context->sync(true);
|
||||
}
|
||||
}
|
||||
catch(std::bad_alloc&)
|
||||
@ -1970,7 +1970,7 @@ void __stdcall glFlush(void)
|
||||
|
||||
if (context)
|
||||
{
|
||||
context->flush();
|
||||
context->sync(false);
|
||||
}
|
||||
}
|
||||
catch(std::bad_alloc&)
|
||||
|
@ -794,12 +794,10 @@ CairoImageOGL::SetData(const CairoImage::Data &aData)
|
||||
}
|
||||
#endif
|
||||
|
||||
InitTexture(gl, tex, LOCAL_GL_RGBA, mSize);
|
||||
|
||||
mLayerProgram =
|
||||
gl->UploadSurfaceToTexture(aData.mSurface,
|
||||
nsIntRect(0,0, mSize.width, mSize.height),
|
||||
tex);
|
||||
tex, true);
|
||||
}
|
||||
|
||||
void CairoImageOGL::SetTiling(bool aTiling)
|
||||
|
@ -56,6 +56,10 @@ interface imgIDecoderObserver;
|
||||
#include "limits.h"
|
||||
|
||||
class nsIFrame;
|
||||
|
||||
namespace mozilla {
|
||||
class TimeStamp;
|
||||
}
|
||||
%}
|
||||
|
||||
[ptr] native gfxImageSurface(gfxImageSurface);
|
||||
@ -68,6 +72,7 @@ native gfxGraphicsFilter(gfxPattern::GraphicsFilter);
|
||||
[ref] native nsIntRect(nsIntRect);
|
||||
[ref] native nsIntSize(nsIntSize);
|
||||
[ptr] native nsIFrame(nsIFrame);
|
||||
[ref] native TimeStamp(mozilla::TimeStamp);
|
||||
|
||||
/**
|
||||
* imgIContainer is the interface that represents an image. It allows
|
||||
@ -261,6 +266,13 @@ interface imgIContainer : nsISupports
|
||||
*/
|
||||
void unlockImage();
|
||||
|
||||
/**
|
||||
* Indicates that this imgIContainer has been triggered to update
|
||||
* its internal animation state. Likely this should only be called
|
||||
* from within nsImageFrame or objects of similar type.
|
||||
*/
|
||||
[notxpcom] void requestRefresh([const] in TimeStamp aTime);
|
||||
|
||||
/**
|
||||
* Animation mode Constants
|
||||
* 0 = normal
|
||||
|
@ -173,10 +173,10 @@ namespace mozilla {
|
||||
namespace imagelib {
|
||||
|
||||
#ifndef DEBUG
|
||||
NS_IMPL_ISUPPORTS4(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
|
||||
NS_IMPL_ISUPPORTS3(RasterImage, imgIContainer, nsIProperties,
|
||||
nsISupportsWeakReference)
|
||||
#else
|
||||
NS_IMPL_ISUPPORTS5(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
|
||||
NS_IMPL_ISUPPORTS4(RasterImage, imgIContainer, nsIProperties,
|
||||
imgIContainerDebug, nsISupportsWeakReference)
|
||||
#endif
|
||||
|
||||
@ -313,6 +313,169 @@ RasterImage::Init(imgIDecoderObserver *aObserver,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
RasterImage::AdvanceFrame(TimeStamp aTime, nsIntRect* aDirtyRect)
|
||||
{
|
||||
NS_ASSERTION(aTime <= TimeStamp::Now(),
|
||||
"Given time appears to be in the future");
|
||||
|
||||
imgFrame* nextFrame = nsnull;
|
||||
PRUint32 currentFrameIndex = mAnim->currentAnimationFrameIndex;
|
||||
PRUint32 nextFrameIndex = mAnim->currentAnimationFrameIndex + 1;
|
||||
PRUint32 timeout = 0;
|
||||
|
||||
// Figure out if we have the next full frame. This is more complicated than
|
||||
// just checking for mFrames.Length() because decoders append their frames
|
||||
// before they're filled in.
|
||||
NS_ABORT_IF_FALSE(mDecoder || nextFrameIndex <= mFrames.Length(),
|
||||
"How did we get 2 indices too far by incrementing?");
|
||||
|
||||
// If we don't have a decoder, we know we've got everything we're going to
|
||||
// get. If we do, we only display fully-downloaded frames; everything else
|
||||
// gets delayed.
|
||||
bool haveFullNextFrame = !mDecoder ||
|
||||
nextFrameIndex < mDecoder->GetCompleteFrameCount();
|
||||
|
||||
// If we're done decoding the next frame, go ahead and display it now and
|
||||
// reinit with the next frame's delay time.
|
||||
if (haveFullNextFrame) {
|
||||
if (mFrames.Length() == nextFrameIndex) {
|
||||
// End of Animation, unless we are looping forever
|
||||
|
||||
// If animation mode is "loop once", it's time to stop animating
|
||||
if (mAnimationMode == kLoopOnceAnimMode || mLoopCount == 0) {
|
||||
mAnimationFinished = PR_TRUE;
|
||||
EvaluateAnimation();
|
||||
}
|
||||
|
||||
// We may have used compositingFrame to build a frame, and then copied
|
||||
// it back into mFrames[..]. If so, delete composite to save memory
|
||||
if (mAnim->compositingFrame && mAnim->lastCompositedFrameIndex == -1) {
|
||||
mAnim->compositingFrame = nsnull;
|
||||
}
|
||||
|
||||
nextFrameIndex = 0;
|
||||
|
||||
if (mLoopCount > 0) {
|
||||
mLoopCount--;
|
||||
}
|
||||
|
||||
if (!mAnimating) {
|
||||
// break out early if we are actually done animating
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(nextFrame = mFrames[nextFrameIndex])) {
|
||||
// something wrong with the next frame, skip it
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
return false;
|
||||
}
|
||||
|
||||
timeout = nextFrame->GetTimeout();
|
||||
|
||||
} else {
|
||||
// Uh oh, the frame we want to show is currently being decoded (partial)
|
||||
// Wait until the next refresh driver tick and try again
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(timeout > 0)) {
|
||||
mAnimationFinished = PR_TRUE;
|
||||
EvaluateAnimation();
|
||||
}
|
||||
|
||||
imgFrame *frameToUse = nsnull;
|
||||
|
||||
if (nextFrameIndex == 0) {
|
||||
frameToUse = nextFrame;
|
||||
*aDirtyRect = mAnim->firstFrameRefreshArea;
|
||||
} else {
|
||||
imgFrame *curFrame = mFrames[currentFrameIndex];
|
||||
|
||||
if (!curFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change frame
|
||||
if (NS_FAILED(DoComposite(aDirtyRect, curFrame,
|
||||
nextFrame, nextFrameIndex))) {
|
||||
// something went wrong, move on to next
|
||||
NS_WARNING("RasterImage::AdvanceFrame(): Compositing of frame failed");
|
||||
nextFrame->SetCompositingFailed(PR_TRUE);
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
mAnim->currentAnimationFrameTime = aTime;
|
||||
return false;
|
||||
}
|
||||
|
||||
nextFrame->SetCompositingFailed(PR_FALSE);
|
||||
}
|
||||
|
||||
// Set currentAnimationFrameIndex at the last possible moment
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
mAnim->currentAnimationFrameTime = aTime;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// [notxpcom] void requestRefresh ([const] in TimeStamp aTime);
|
||||
NS_IMETHODIMP_(void)
|
||||
RasterImage::RequestRefresh(const mozilla::TimeStamp& aTime)
|
||||
{
|
||||
if (!mAnimating || !ShouldAnimate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureAnimExists();
|
||||
|
||||
// only advance the frame if the current time is greater than or
|
||||
// equal to the current frame's end time.
|
||||
TimeStamp currentFrameEndTime = GetCurrentImgFrameEndTime();
|
||||
bool frameAdvanced = false;
|
||||
|
||||
// The dirtyRect variable will contain an accumulation of the sub-rectangles
|
||||
// that are dirty for each frame we advance in AdvanceFrame().
|
||||
nsIntRect dirtyRect;
|
||||
|
||||
while (currentFrameEndTime <= aTime) {
|
||||
TimeStamp oldFrameEndTime = currentFrameEndTime;
|
||||
nsIntRect frameDirtyRect;
|
||||
bool didAdvance = AdvanceFrame(aTime, &frameDirtyRect);
|
||||
frameAdvanced = frameAdvanced || didAdvance;
|
||||
currentFrameEndTime = GetCurrentImgFrameEndTime();
|
||||
|
||||
// Accumulate the dirty area.
|
||||
dirtyRect = dirtyRect.Union(frameDirtyRect);
|
||||
|
||||
// if we didn't advance a frame, and our frame end time didn't change,
|
||||
// then we need to break out of this loop & wait for the frame(s)
|
||||
// to finish downloading
|
||||
if (!frameAdvanced && (currentFrameEndTime == oldFrameEndTime)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (frameAdvanced) {
|
||||
nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver));
|
||||
|
||||
if (!observer) {
|
||||
NS_ERROR("Refreshing image after its imgRequest is gone");
|
||||
StopAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify listeners that our frame has actually changed, but do this only
|
||||
// once for all frames that we've now passed (if AdvanceFrame() was called
|
||||
// more than once).
|
||||
#ifdef DEBUG
|
||||
mFramesNotified++;
|
||||
#endif
|
||||
|
||||
observer->FrameChanged(this, &dirtyRect);
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
/* [noscript] imgIContainer extractFrame(PRUint32 aWhichFrame,
|
||||
* [const] in nsIntRect aRegion,
|
||||
@ -494,6 +657,27 @@ RasterImage::GetCurrentImgFrameIndex() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
RasterImage::GetCurrentImgFrameEndTime() const
|
||||
{
|
||||
imgFrame* currentFrame = mFrames[mAnim->currentAnimationFrameIndex];
|
||||
TimeStamp currentFrameTime = mAnim->currentAnimationFrameTime;
|
||||
PRInt64 timeout = currentFrame->GetTimeout();
|
||||
|
||||
if (timeout < 0) {
|
||||
// We need to return a sentinel value in this case, because our logic
|
||||
// doesn't work correctly if we have a negative timeout value. The reason
|
||||
// this positive infinity was chosen was because it works with the loop in
|
||||
// RequestRefresh() above.
|
||||
return TimeStamp() + TimeDuration::FromMilliseconds(UINT64_MAX_VAL);
|
||||
}
|
||||
|
||||
TimeDuration durationOfTimeout = TimeDuration::FromMilliseconds(timeout);
|
||||
TimeStamp currentFrameEndTime = currentFrameTime + durationOfTimeout;
|
||||
|
||||
return currentFrameEndTime;
|
||||
}
|
||||
|
||||
imgFrame*
|
||||
RasterImage::GetCurrentImgFrame()
|
||||
{
|
||||
@ -1138,25 +1322,18 @@ RasterImage::StartAnimation()
|
||||
|
||||
EnsureAnimExists();
|
||||
|
||||
NS_ABORT_IF_FALSE(mAnim && !mAnim->timer, "Anim must exist and not have a timer yet");
|
||||
|
||||
// Default timeout to 100: the timer notify code will do the right
|
||||
// thing, so just get that started.
|
||||
PRInt32 timeout = 100;
|
||||
imgFrame *currentFrame = GetCurrentImgFrame();
|
||||
imgFrame* currentFrame = GetCurrentImgFrame();
|
||||
if (currentFrame) {
|
||||
timeout = currentFrame->GetTimeout();
|
||||
if (timeout < 0) { // -1 means display this frame forever
|
||||
if (currentFrame->GetTimeout() < 0) { // -1 means display this frame forever
|
||||
mAnimationFinished = true;
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
// We need to set the time that this initial frame was first displayed, as
|
||||
// this is used in AdvanceFrame().
|
||||
mAnim->currentAnimationFrameTime = TimeStamp::Now();
|
||||
}
|
||||
|
||||
mAnim->timer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
NS_ENSURE_TRUE(mAnim->timer, NS_ERROR_OUT_OF_MEMORY);
|
||||
mAnim->timer->InitWithCallback(static_cast<nsITimerCallback*>(this),
|
||||
timeout, nsITimer::TYPE_REPEATING_SLACK);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1170,11 +1347,6 @@ RasterImage::StopAnimation()
|
||||
if (mError)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mAnim->timer) {
|
||||
mAnim->timer->Cancel();
|
||||
mAnim->timer = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1430,127 +1602,6 @@ RasterImage::SetSourceSizeHint(PRUint32 sizeHint)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
/* void notify(in nsITimer timer); */
|
||||
NS_IMETHODIMP
|
||||
RasterImage::Notify(nsITimer *timer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mFramesNotified++;
|
||||
#endif
|
||||
|
||||
// This should never happen since the timer is only set up in StartAnimation()
|
||||
// after mAnim is checked to exist.
|
||||
NS_ABORT_IF_FALSE(mAnim, "Need anim for Notify()");
|
||||
NS_ABORT_IF_FALSE(timer, "Need timer for Notify()");
|
||||
NS_ABORT_IF_FALSE(mAnim->timer == timer,
|
||||
"RasterImage::Notify() called with incorrect timer");
|
||||
|
||||
if (!mAnimating || !ShouldAnimate())
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver));
|
||||
if (!observer) {
|
||||
// the imgRequest that owns us is dead, we should die now too.
|
||||
NS_ABORT_IF_FALSE(mAnimationConsumers == 0,
|
||||
"If no observer, should have no consumers");
|
||||
if (mAnimating)
|
||||
StopAnimation();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mFrames.Length() == 0)
|
||||
return NS_OK;
|
||||
|
||||
imgFrame *nextFrame = nsnull;
|
||||
PRInt32 previousFrameIndex = mAnim->currentAnimationFrameIndex;
|
||||
PRUint32 nextFrameIndex = mAnim->currentAnimationFrameIndex + 1;
|
||||
PRInt32 timeout = 0;
|
||||
|
||||
// Figure out if we have the next full frame. This is more complicated than
|
||||
// just checking for mFrames.Length() because decoders append their frames
|
||||
// before they're filled in.
|
||||
NS_ABORT_IF_FALSE(mDecoder || nextFrameIndex <= mFrames.Length(),
|
||||
"How did we get 2 indicies too far by incrementing?");
|
||||
|
||||
// If we don't have a decoder, we know we've got everything we're going to get.
|
||||
// If we do, we only display fully-downloaded frames; everything else gets delayed.
|
||||
bool haveFullNextFrame = !mDecoder || nextFrameIndex < mDecoder->GetCompleteFrameCount();
|
||||
|
||||
// If we're done decoding the next frame, go ahead and display it now and
|
||||
// reinit the timer with the next frame's delay time.
|
||||
if (haveFullNextFrame) {
|
||||
if (mFrames.Length() == nextFrameIndex) {
|
||||
// End of Animation
|
||||
|
||||
// If animation mode is "loop once", it's time to stop animating
|
||||
if (mAnimationMode == kLoopOnceAnimMode || mLoopCount == 0) {
|
||||
mAnimationFinished = true;
|
||||
EvaluateAnimation();
|
||||
return NS_OK;
|
||||
} else {
|
||||
// We may have used compositingFrame to build a frame, and then copied
|
||||
// it back into mFrames[..]. If so, delete composite to save memory
|
||||
if (mAnim->compositingFrame && mAnim->lastCompositedFrameIndex == -1)
|
||||
mAnim->compositingFrame = nsnull;
|
||||
}
|
||||
|
||||
nextFrameIndex = 0;
|
||||
if (mLoopCount > 0)
|
||||
mLoopCount--;
|
||||
}
|
||||
|
||||
if (!(nextFrame = mFrames[nextFrameIndex])) {
|
||||
// something wrong with the next frame, skip it
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
mAnim->timer->SetDelay(100);
|
||||
return NS_OK;
|
||||
}
|
||||
timeout = nextFrame->GetTimeout();
|
||||
|
||||
} else {
|
||||
// Uh oh, the frame we want to show is currently being decoded (partial)
|
||||
// Wait a bit and try again
|
||||
mAnim->timer->SetDelay(100);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (timeout > 0)
|
||||
mAnim->timer->SetDelay(timeout);
|
||||
else {
|
||||
mAnimationFinished = true;
|
||||
EvaluateAnimation();
|
||||
}
|
||||
|
||||
nsIntRect dirtyRect;
|
||||
|
||||
if (nextFrameIndex == 0) {
|
||||
dirtyRect = mAnim->firstFrameRefreshArea;
|
||||
} else {
|
||||
imgFrame *prevFrame = mFrames[previousFrameIndex];
|
||||
if (!prevFrame)
|
||||
return NS_OK;
|
||||
|
||||
// Change frame and announce it
|
||||
if (NS_FAILED(DoComposite(&dirtyRect, prevFrame,
|
||||
nextFrame, nextFrameIndex))) {
|
||||
// something went wrong, move on to next
|
||||
NS_WARNING("RasterImage::Notify(): Composing Frame Failed\n");
|
||||
nextFrame->SetCompositingFailed(true);
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
return NS_OK;
|
||||
} else {
|
||||
nextFrame->SetCompositingFailed(false);
|
||||
}
|
||||
}
|
||||
// Set currentAnimationFrameIndex at the last possible moment
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
// Refreshes the screen
|
||||
observer->FrameChanged(this, &dirtyRect);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// DoComposite gets called when the timer for animation get fired and we have to
|
||||
// update the composited frame of the animation.
|
||||
|
@ -71,6 +71,7 @@
|
||||
#endif
|
||||
|
||||
class imgIDecoder;
|
||||
class imgIContainerObserver;
|
||||
class nsIInputStream;
|
||||
|
||||
#define NS_RASTERIMAGE_CID \
|
||||
@ -81,6 +82,12 @@ class nsIInputStream;
|
||||
{0xb1, 0x43, 0x33, 0x40, 0xc0, 0x01, 0x12, 0xf7} \
|
||||
}
|
||||
|
||||
/**
|
||||
* It would be nice if we had a macro for this in prtypes.h.
|
||||
* TODO: Place this macro in prtypes.h as PR_UINT64_MAX.
|
||||
*/
|
||||
#define UINT64_MAX_VAL PRUint64(-1)
|
||||
|
||||
/**
|
||||
* Handles static and animated image containers.
|
||||
*
|
||||
@ -88,15 +95,27 @@ class nsIInputStream;
|
||||
* @par A Quick Walk Through
|
||||
* The decoder initializes this class and calls AppendFrame() to add a frame.
|
||||
* Once RasterImage detects more than one frame, it starts the animation
|
||||
* with StartAnimation().
|
||||
* with StartAnimation(). Note that the invalidation events for RasterImage are
|
||||
* generated automatically using nsRefreshDriver.
|
||||
*
|
||||
* @par
|
||||
* StartAnimation() creates a timer. The timer calls Notify when the
|
||||
* specified frame delay time is up.
|
||||
* StartAnimation() initializes the animation helper object and sets the time
|
||||
* the first frame was displayed to the current clock time.
|
||||
*
|
||||
* @par
|
||||
* Notify() moves on to the next frame, sets up the new timer delay, destroys
|
||||
* the old frame, and forces a redraw via observer->FrameChanged().
|
||||
* When the refresh driver corresponding to the imgIContainer that this image is
|
||||
* a part of notifies the RasterImage that it's time to invalidate,
|
||||
* RequestRefresh() is called with a given TimeStamp to advance to. As long as
|
||||
* the timeout of the given frame (the frame's "delay") plus the time that frame
|
||||
* was first displayed is less than or equal to the TimeStamp given,
|
||||
* RequestRefresh() calls AdvanceFrame().
|
||||
*
|
||||
* @par
|
||||
* AdvanceFrame() is responsible for advancing a single frame of the animation.
|
||||
* It can return true, meaning that the frame advanced, or false, meaning that
|
||||
* the frame failed to advance (usually because the next frame hasn't been
|
||||
* decoded yet). It is also responsible for performing the final animation stop
|
||||
* procedure if the final frame of a non-looping animation is reached.
|
||||
*
|
||||
* @par
|
||||
* Each frame can have a different method of removing itself. These are
|
||||
@ -151,7 +170,6 @@ class imgDecodeWorker;
|
||||
class Decoder;
|
||||
|
||||
class RasterImage : public Image
|
||||
, public nsITimerCallback
|
||||
, public nsIProperties
|
||||
, public nsSupportsWeakReference
|
||||
#ifdef DEBUG
|
||||
@ -160,7 +178,6 @@ class RasterImage : public Image
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
NS_DECL_NSIPROPERTIES
|
||||
#ifdef DEBUG
|
||||
NS_DECL_IMGICONTAINERDEBUG
|
||||
@ -183,6 +200,7 @@ public:
|
||||
NS_SCRIPTABLE NS_IMETHOD LockImage(void);
|
||||
NS_SCRIPTABLE NS_IMETHOD UnlockImage(void);
|
||||
NS_SCRIPTABLE NS_IMETHOD ResetAnimation(void);
|
||||
NS_IMETHOD_(void) RequestRefresh(const mozilla::TimeStamp& aTime);
|
||||
// END NS_DECL_IMGICONTAINER
|
||||
|
||||
RasterImage(imgStatusTracker* aStatusTracker = nsnull);
|
||||
@ -334,6 +352,10 @@ private:
|
||||
//! Area of the first frame that needs to be redrawn on subsequent loops.
|
||||
nsIntRect firstFrameRefreshArea;
|
||||
PRUint32 currentAnimationFrameIndex; // 0 to numFrames-1
|
||||
|
||||
// the time that the animation advanced to the current frame
|
||||
TimeStamp currentAnimationFrameTime;
|
||||
|
||||
//! Track the last composited frame for Optimizations (See DoComposite code)
|
||||
PRInt32 lastCompositedFrameIndex;
|
||||
/** For managing blending of frames
|
||||
@ -352,23 +374,33 @@ private:
|
||||
* when it's done with the current frame.
|
||||
*/
|
||||
nsAutoPtr<imgFrame> compositingPrevFrame;
|
||||
//! Timer to animate multiframed images
|
||||
nsCOMPtr<nsITimer> timer;
|
||||
|
||||
Anim() :
|
||||
firstFrameRefreshArea(),
|
||||
currentAnimationFrameIndex(0),
|
||||
lastCompositedFrameIndex(-1)
|
||||
{
|
||||
;
|
||||
}
|
||||
~Anim()
|
||||
{
|
||||
if (timer)
|
||||
timer->Cancel();
|
||||
}
|
||||
lastCompositedFrameIndex(-1) {}
|
||||
~Anim() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Advances the animation. Typically, this will advance a single frame, but it
|
||||
* may advance multiple frames. This may happen if we have infrequently
|
||||
* "ticking" refresh drivers (e.g. in background tabs), or extremely short-
|
||||
* lived animation frames.
|
||||
*
|
||||
* @param aTime the time that the animation should advance to. This will
|
||||
* typically be <= TimeStamp::Now().
|
||||
*
|
||||
* @param [out] aDirtyRect a pointer to an nsIntRect which encapsulates the
|
||||
* area to be repainted after the frame is advanced.
|
||||
*
|
||||
* @returns true, if the frame was successfully advanced, false if it was not
|
||||
* able to be advanced (e.g. the frame to which we want to advance is
|
||||
* still decoding). Note: If false is returned, then aDirtyRect will
|
||||
* remain unmodified.
|
||||
*/
|
||||
bool AdvanceFrame(mozilla::TimeStamp aTime, nsIntRect* aDirtyRect);
|
||||
|
||||
/**
|
||||
* Deletes and nulls out the frame in mFrames[framenum].
|
||||
*
|
||||
@ -385,6 +417,7 @@ private:
|
||||
imgFrame* GetCurrentImgFrame();
|
||||
imgFrame* GetCurrentDrawableImgFrame();
|
||||
PRUint32 GetCurrentImgFrameIndex() const;
|
||||
mozilla::TimeStamp GetCurrentImgFrameEndTime() const;
|
||||
|
||||
inline void EnsureAnimExists()
|
||||
{
|
||||
@ -405,7 +438,7 @@ private:
|
||||
LockImage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Function for doing the frame compositing of animations
|
||||
*
|
||||
* @param aDirtyRect Area that the display will need to update
|
||||
@ -417,7 +450,7 @@ private:
|
||||
imgFrame* aPrevFrame,
|
||||
imgFrame* aNextFrame,
|
||||
PRInt32 aNextFrameIndex);
|
||||
|
||||
|
||||
/** Clears an area of <aFrame> with transparent black.
|
||||
*
|
||||
* @param aFrame Target Frame
|
||||
@ -425,7 +458,7 @@ private:
|
||||
* @note Does also clears the transparancy mask
|
||||
*/
|
||||
static void ClearFrame(imgFrame* aFrame);
|
||||
|
||||
|
||||
//! @overload
|
||||
static void ClearFrame(imgFrame* aFrame, nsIntRect &aRect);
|
||||
|
||||
|
@ -172,7 +172,6 @@ SVGDrawingCallback::operator()(gfxContext* aContext,
|
||||
gfxContextMatrixAutoSaveRestore contextMatrixRestorer(aContext);
|
||||
aContext->Multiply(gfxMatrix(aTransform).Invert());
|
||||
|
||||
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
NS_ABORT_IF_FALSE(presContext, "pres shell w/out pres context");
|
||||
|
||||
@ -330,6 +329,14 @@ VectorImage::GetWidth(PRInt32* aWidth)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
/* [notxpcom] void requestRefresh ([const] in TimeStamp aTime); */
|
||||
NS_IMETHODIMP_(void)
|
||||
VectorImage::RequestRefresh(const mozilla::TimeStamp& aTime)
|
||||
{
|
||||
// TODO: Implement for b666446.
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
/* readonly attribute PRInt32 height; */
|
||||
NS_IMETHODIMP
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "Image.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
class imgIDecoderObserver;
|
||||
|
||||
@ -76,6 +77,7 @@ public:
|
||||
NS_SCRIPTABLE NS_IMETHOD LockImage(void);
|
||||
NS_SCRIPTABLE NS_IMETHOD UnlockImage(void);
|
||||
NS_SCRIPTABLE NS_IMETHOD ResetAnimation(void);
|
||||
NS_IMETHOD_(void) RequestRefresh(const mozilla::TimeStamp& aTime);
|
||||
// END NS_DECL_IMGICONTAINER
|
||||
|
||||
VectorImage(imgStatusTracker* aStatusTracker = nsnull);
|
||||
|
@ -93,8 +93,27 @@ _TEST_FILES = imgutils.js \
|
||||
# test_bug478398.html disabled - See bug 579139
|
||||
|
||||
_CHROME_FILES = imgutils.js \
|
||||
animationPolling.js \
|
||||
lime-anim-100x100.svg \
|
||||
animation.svg \
|
||||
test_animSVGImage.html \
|
||||
test_animation.html \
|
||||
animated-gif-finalframe.gif \
|
||||
animated-gif.gif \
|
||||
animated-gif2.gif \
|
||||
purple.gif \
|
||||
test_svg_animatedGIF.html \
|
||||
test_bullet_animation.html \
|
||||
test_background_image_anim.html \
|
||||
filter.svg \
|
||||
filter-final.svg \
|
||||
test_svg_filter_animation.html \
|
||||
test_xultree_animation.xhtml \
|
||||
test_changeOfSource.html \
|
||||
test_changeOfSource2.html \
|
||||
test_undisplayed_iframe.html \
|
||||
iframe.html \
|
||||
ref-iframe.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
BIN
image/test/mochitest/animated-gif-finalframe.gif
Normal file
After Width: | Height: | Size: 72 B |
BIN
image/test/mochitest/animated-gif.gif
Normal file
After Width: | Height: | Size: 146 B |
BIN
image/test/mochitest/animated-gif2.gif
Normal file
After Width: | Height: | Size: 165 B |
5
image/test/mochitest/animation.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<image id="anim" xlink:href="animated-gif.gif" width="40" height="40"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 170 B |
395
image/test/mochitest/animationPolling.js
Normal file
@ -0,0 +1,395 @@
|
||||
var currentTest;
|
||||
var gIsImageLoaded = false;
|
||||
var gIsRefImageLoaded = false;
|
||||
|
||||
function pollForSuccess ()
|
||||
{
|
||||
if (!currentTest.isTestFinished) {
|
||||
if (!currentTest.reusingReferenceImage || (currentTest.reusingReferenceImage
|
||||
&& gRefImageLoaded)) {
|
||||
currentTest.checkImage();
|
||||
}
|
||||
|
||||
setTimeout(pollForSuccess, currentTest.pollFreq);
|
||||
}
|
||||
};
|
||||
|
||||
function imageLoadCallback()
|
||||
{
|
||||
gIsImageLoaded = true;
|
||||
}
|
||||
|
||||
function referencePoller()
|
||||
{
|
||||
currentTest.takeReferenceSnapshot();
|
||||
}
|
||||
|
||||
function reuseImageCallback()
|
||||
{
|
||||
gIsRefImageLoaded = true;
|
||||
}
|
||||
|
||||
function failTest ()
|
||||
{
|
||||
if (currentTest.isTestFinished || currentTest.closeFunc) {
|
||||
return;
|
||||
}
|
||||
|
||||
ok(false, "timing out after " + currentTest.timeout + "ms. "
|
||||
+ "Animated image still doesn't look correct, " + "after call #"
|
||||
+ currentTest.onStopFrameCounter + " to onStopFrame");
|
||||
currentTest.wereFailures = true;
|
||||
|
||||
currentTest.enableDisplay(document.getElementById(currentTest.debugElementId));
|
||||
|
||||
currentTest.cleanUpAndFinish();
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new AnimationTest object.
|
||||
*
|
||||
* @param pollFreq The amount of time (in ms) to wait between consecutive
|
||||
* snapshots if the reference image and the test image don't match.
|
||||
* @param timeout The total amount of time (in ms) to wait before declaring the
|
||||
* test as failed.
|
||||
* @param referenceElementId The id attribute of the reference image element, or
|
||||
* the source of the image to change to, once the reference snapshot has
|
||||
* been successfully taken. This latter option could be used if you don't
|
||||
* want the image to become invisible at any time during the test.
|
||||
* @param imageElementId The id attribute of the test image element.
|
||||
* @param debugElementId The id attribute of the div where links should be
|
||||
* appended if the test fails.
|
||||
* @param cleanId The id attribute of the div or element to use as the 'clean'
|
||||
* test. This element is only enabled when we are testing to verify that
|
||||
* the reference image has been loaded. It can be undefined.
|
||||
* @param srcAttr The location of the source of the image, for preloading. This
|
||||
* is usually not required, but it useful for preloading reference
|
||||
* images.
|
||||
* @param xulTest A boolean value indicating whether or not this is a XUL test
|
||||
* (uses hidden=true/false rather than display: none to hide/show
|
||||
* elements).
|
||||
* @param closeFunc A function that should be called when this test is finished.
|
||||
* If null, then cleanUpAndFinish() will be called. This can be used to
|
||||
* chain tests together, so they are all finished exactly once.
|
||||
* @returns {AnimationTest}
|
||||
*/
|
||||
function AnimationTest(pollFreq, timeout, referenceElementId, imageElementId,
|
||||
debugElementId, cleanId, srcAttr, xulTest, closeFunc)
|
||||
{
|
||||
// We want to test the cold loading behavior, so clear cache in case an
|
||||
// earlier test got our image in there already.
|
||||
clearImageCache();
|
||||
|
||||
this.wereFailures = false;
|
||||
this.pollFreq = pollFreq;
|
||||
this.timeout = timeout;
|
||||
this.imageElementId = imageElementId;
|
||||
this.referenceElementId = referenceElementId;
|
||||
|
||||
if (!document.getElementById(referenceElementId)) {
|
||||
// In this case, we're assuming the user passed in a string that
|
||||
// indicates the source of the image they want to change to,
|
||||
// after the reference image has been taken.
|
||||
this.reusingImageAsReference = true;
|
||||
}
|
||||
|
||||
this.srcAttr = srcAttr;
|
||||
this.debugElementId = debugElementId;
|
||||
this.referenceSnapshot = ""; // value will be set in takeReferenceSnapshot()
|
||||
this.onStopFrameCounter = 0;
|
||||
this.isTestFinished = false;
|
||||
this.numRefsTaken = 0;
|
||||
this.blankWaitTime = 0;
|
||||
|
||||
this.cleanId = cleanId ? cleanId : '';
|
||||
this.xulTest = xulTest ? xulTest : '';
|
||||
this.closeFunc = closeFunc ? closeFunc : '';
|
||||
|
||||
if (this.srcAttr) {
|
||||
this.myImage = new Image();
|
||||
this.myImage.onload = imageLoadCallback;
|
||||
this.myImage.src = this.srcAttr;
|
||||
} else {
|
||||
gIsImageLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
AnimationTest.prototype.outputDebugInfo = function(message, id, dataUri)
|
||||
{
|
||||
var debugElement = document.getElementById(this.debugElementId);
|
||||
var newDataUriElement = document.createElement("a");
|
||||
newDataUriElement.setAttribute("id", id);
|
||||
newDataUriElement.setAttribute("href", dataUri);
|
||||
newDataUriElement.appendChild(document.createTextNode(message));
|
||||
debugElement.appendChild(newDataUriElement);
|
||||
var brElement = document.createElement("br");
|
||||
debugElement.appendChild(brElement);
|
||||
};
|
||||
|
||||
AnimationTest.prototype.isFinished = function()
|
||||
{
|
||||
return this.isTestFinished;
|
||||
};
|
||||
|
||||
AnimationTest.prototype.takeCleanSnapshot = function()
|
||||
{
|
||||
var cleanElement;
|
||||
if (this.cleanId) {
|
||||
cleanElement = document.getElementById(this.cleanId);
|
||||
}
|
||||
|
||||
// Enable clean page comparison element
|
||||
if (cleanElement) {
|
||||
this.enableDisplay(cleanElement);
|
||||
}
|
||||
|
||||
// Take a snapshot of the initial (clean) page
|
||||
this.cleanSnapshot = snapshotWindow(window, false);
|
||||
|
||||
// Disable the clean page comparison element
|
||||
if (cleanElement) {
|
||||
this.disableDisplay(cleanElement);
|
||||
}
|
||||
|
||||
var dataString1 = "Clean Snapshot";
|
||||
this.outputDebugInfo(dataString1, 'cleanSnap',
|
||||
this.cleanSnapshot.toDataURL());
|
||||
};
|
||||
|
||||
AnimationTest.prototype.takeBlankSnapshot = function()
|
||||
{
|
||||
// Take a snapshot of the initial (essentially blank) page
|
||||
this.blankSnapshot = snapshotWindow(window, false);
|
||||
|
||||
var dataString1 = "Initial Blank Snapshot";
|
||||
this.outputDebugInfo(dataString1, 'blank1Snap',
|
||||
this.blankSnapshot.toDataURL());
|
||||
};
|
||||
|
||||
/**
|
||||
* Begin the AnimationTest. This will utilize the information provided in the
|
||||
* constructor to invoke a mochitest on animated images. It will automatically
|
||||
* fail if allowed to run past the timeout.
|
||||
*/
|
||||
AnimationTest.prototype.beginTest = function ()
|
||||
{
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
currentTest = this;
|
||||
|
||||
this.takeReferenceSnapshot();
|
||||
|
||||
// In case something goes wrong, fail earlier than mochitest timeout,
|
||||
// and with more information.
|
||||
setTimeout(failTest, this.timeout);
|
||||
|
||||
if (!this.reusingImageAsReference) {
|
||||
this.disableDisplay(document.getElementById(this.imageElementId));
|
||||
}
|
||||
|
||||
this.setupPolledImage();
|
||||
setTimeout(pollForSuccess, 10);
|
||||
};
|
||||
|
||||
AnimationTest.prototype.setupPolledImage = function ()
|
||||
{
|
||||
// Make sure the image is visible
|
||||
if (!this.reusingImageAsReference) {
|
||||
this.enableDisplay(document.getElementById(this.imageElementId));
|
||||
var currentSnapshot = snapshotWindow(window, false);
|
||||
var result = compareSnapshots(currentSnapshot, this.referenceSnapshot, true);
|
||||
|
||||
var dataString = "Snapshot #" + this.onStopFrameCounter;
|
||||
this.outputDebugInfo(dataString, 'snap' + this.onStopFrameCounter,
|
||||
currentSnapshot.toDataURL());
|
||||
|
||||
if (result[0]) {
|
||||
// SUCCESS!
|
||||
ok(true, "Animated image looks correct, " + "at call #"
|
||||
+ this.onStopFrameCounter + " to onStopFrame");
|
||||
|
||||
this.cleanUpAndFinish();
|
||||
}
|
||||
} else {
|
||||
if (!gIsRefImageLoaded) {
|
||||
this.myImage = new Image();
|
||||
this.myImage.onload = reuseImageCallback;
|
||||
document.getElementById(this.imageElementId).setAttribute('src',
|
||||
this.referenceElementId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AnimationTest.prototype.checkImage = function ()
|
||||
{
|
||||
if (this.isTestFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.onStopFrameCounter++;
|
||||
|
||||
// We need this for some tests, because we need to force the
|
||||
// test image to be visible.
|
||||
if (!this.reusingImageAsReference) {
|
||||
this.enableDisplay(document.getElementById(this.imageElementId));
|
||||
}
|
||||
|
||||
var currentSnapshot = snapshotWindow(window, false);
|
||||
var result = compareSnapshots(currentSnapshot, this.referenceSnapshot, true);
|
||||
|
||||
var dataString = "Snapshot #" + this.onStopFrameCounter;
|
||||
this.outputDebugInfo(dataString, 'snap' + this.onStopFrameCounter,
|
||||
currentSnapshot.toDataURL());
|
||||
|
||||
if (result[0]) {
|
||||
// SUCCESS!
|
||||
ok(true, "Animated image looks correct, " + "at call #"
|
||||
+ this.onStopFrameCounter + " to onStopFrame");
|
||||
|
||||
this.cleanUpAndFinish();
|
||||
}
|
||||
};
|
||||
|
||||
AnimationTest.prototype.takeReferenceSnapshot = function ()
|
||||
{
|
||||
this.numRefsTaken++;
|
||||
|
||||
// Test to make sure the reference image doesn't match a clean snapshot
|
||||
if (!this.cleanSnapshot) {
|
||||
this.takeCleanSnapshot();
|
||||
}
|
||||
|
||||
// Used later to verify that the reference div disappeared
|
||||
if (!this.blankSnapshot) {
|
||||
this.takeBlankSnapshot();
|
||||
}
|
||||
|
||||
if (this.reusingImageAsReference) {
|
||||
// Show reference div, & take a snapshot
|
||||
var referenceDiv = document.getElementById(this.imageElementId);
|
||||
this.enableDisplay(referenceDiv);
|
||||
|
||||
this.referenceSnapshot = snapshotWindow(window, false);
|
||||
var snapResult = compareSnapshots(this.cleanSnapshot, this.referenceSnapshot,
|
||||
false);
|
||||
if (!snapResult[0]) {
|
||||
if (this.blankWaitTime > 2000) {
|
||||
// if it took longer than two seconds to load the image, we probably
|
||||
// have a problem.
|
||||
this.wereFailures = true;
|
||||
ok(snapResult[0],
|
||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
||||
} else {
|
||||
this.blankWaitTime += 20;
|
||||
// let's wait a bit and see if it clears up
|
||||
setTimeout(referencePoller, 20);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ok(snapResult[0],
|
||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
||||
|
||||
var dataString = "Reference Snapshot #" + this.numRefsTaken;
|
||||
this.outputDebugInfo(dataString, 'refSnapId',
|
||||
this.referenceSnapshot.toDataURL());
|
||||
} else {
|
||||
// Make sure the animation section is hidden
|
||||
this.disableDisplay(document.getElementById(this.imageElementId));
|
||||
|
||||
// Show reference div, & take a snapshot
|
||||
var referenceDiv = document.getElementById(this.referenceElementId);
|
||||
this.enableDisplay(referenceDiv);
|
||||
|
||||
this.referenceSnapshot = snapshotWindow(window, false);
|
||||
var snapResult = compareSnapshots(this.cleanSnapshot, this.referenceSnapshot, false);
|
||||
if (!snapResult[0]) {
|
||||
if (this.blankWaitTime > 2000) {
|
||||
// if it took longer than two seconds to load the image, we probably
|
||||
// have a problem.
|
||||
this.wereFailures = true;
|
||||
ok(snapResult[0],
|
||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
||||
} else {
|
||||
this.blankWaitTime += 20;
|
||||
// let's wait a bit and see if it clears up
|
||||
setTimeout(referencePoller, 20);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ok(snapResult[0],
|
||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
||||
|
||||
var dataString = "Reference Snapshot #" + this.numRefsTaken;
|
||||
this.outputDebugInfo(dataString, 'refSnapId',
|
||||
this.referenceSnapshot.toDataURL());
|
||||
|
||||
// Re-hide reference div, and take another snapshot to be sure it's gone
|
||||
this.disableDisplay(referenceDiv);
|
||||
this.testBlankCameBack();
|
||||
}
|
||||
};
|
||||
|
||||
AnimationTest.prototype.enableDisplay = function(element)
|
||||
{
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.xulTest) {
|
||||
element.style.display = '';
|
||||
} else {
|
||||
element.setAttribute('hidden', 'false');
|
||||
}
|
||||
};
|
||||
|
||||
AnimationTest.prototype.disableDisplay = function(element)
|
||||
{
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.xulTest) {
|
||||
element.style.display = 'none';
|
||||
} else {
|
||||
element.setAttribute('hidden', 'true');
|
||||
}
|
||||
};
|
||||
|
||||
AnimationTest.prototype.testBlankCameBack = function()
|
||||
{
|
||||
var blankSnapshot2 = snapshotWindow(window, false);
|
||||
var result = compareSnapshots(this.blankSnapshot, blankSnapshot2, true);
|
||||
ok(result[0], "Reference image should disappear when it becomes display:none");
|
||||
|
||||
if (!result[0]) {
|
||||
this.wereFailures = true;
|
||||
var dataString = "Second Blank Snapshot";
|
||||
this.outputDebugInfo(dataString, 'blank2SnapId', result[2]);
|
||||
}
|
||||
};
|
||||
|
||||
AnimationTest.prototype.cleanUpAndFinish = function ()
|
||||
{
|
||||
// On the off chance that failTest and checkImage are triggered
|
||||
// back-to-back, use a flag to prevent multiple calls to SimpleTest.finish.
|
||||
if (this.isTestFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isTestFinished = true;
|
||||
|
||||
// Call our closing function, if one exists
|
||||
if (this.closeFunc) {
|
||||
this.closeFunc();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.wereFailures) {
|
||||
document.getElementById(this.debugElementId).style.display = 'block';
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
document.getElementById(this.debugElementId).style.display = "";
|
||||
};
|
9
image/test/mochitest/filter-final.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<filter id="filter1" x="0%" y="0%" width="100%" height="100%">
|
||||
<feImage xlink:href="animated-gif-finalframe.gif"/>
|
||||
</filter>
|
||||
<g>
|
||||
<rect x="0" y="0" width="100%" height="100%" filter="url(#filter1)"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 299 B |
9
image/test/mochitest/filter.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<filter id="filter1" x="0%" y="0%" width="100%" height="100%">
|
||||
<feImage xlink:href="animated-gif.gif"/>
|
||||
</filter>
|
||||
<g>
|
||||
<rect x="0" y="0" width="100%" height="100%" filter="url(#filter1)"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 288 B |
5
image/test/mochitest/iframe.html
Normal file
@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body bgcolor="gray">
|
||||
<img src="animated-gif.gif">
|
||||
</body>
|
||||
</html>
|
BIN
image/test/mochitest/purple.gif
Normal file
After Width: | Height: | Size: 86 B |
6
image/test/mochitest/ref-iframe.html
Normal file
@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<body bgcolor="gray">
|
||||
<div id="referenceImage"
|
||||
style="height: 40px; width: 40px; background: #2aff00"></div>
|
||||
</body>
|
||||
</html>
|
46
image/test/mochitest/test_animation.html
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - General Animated GIF Test</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
<div id="referenceDiv" style="height: 40px; width: 40px;
|
||||
display: none; background: #2aff00"></div>
|
||||
<div id="animatedImage">
|
||||
<img id="animatedGif" src="animated-gif.gif" style="display: none;">
|
||||
<div id="text-descr"></div>
|
||||
</div>
|
||||
<div id="debug" style="display:none">
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main()
|
||||
{
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'animatedGif', 'debug');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
44
image/test/mochitest/test_background_image_anim.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Animated Background Images</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<div id="referenceDiv" style="height: 140px; width: 140px;
|
||||
display: none; background: #2aff00"></div>
|
||||
<div id="bgImage" style="height: 140px; width: 140px; background-image: url(animated-gif.gif); display: none;">
|
||||
</div>
|
||||
</div>
|
||||
<div id="debug" style="display:none"></div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 666446 nsImageLoader/RasterImage**/
|
||||
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main() {
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'bgImage', 'debug');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
57
image/test/mochitest/test_bullet_animation.html
Normal file
@ -0,0 +1,57 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Animated Bullets</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
<div id="cleanDiv" style="display: none;">
|
||||
<ul>
|
||||
<li>Test 1</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="referenceDiv" style="display: none;">
|
||||
<ul>
|
||||
<li style="list-style-image: url(animated-gif-finalframe.gif);">Test 1</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="animatedImage" style="display: none;">
|
||||
<ul>
|
||||
<li style="list-style-image: url(animated-gif.gif);">Test 1</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="text-descr"></div>
|
||||
<div id="debug" style="display:none">
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main()
|
||||
{
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'animatedImage', 'debug', 'cleanDiv',
|
||||
'animated-gif-finalframe.gif');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
63
image/test/mochitest/test_changeOfSource.html
Normal file
@ -0,0 +1,63 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Change of Source (1st Version)</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
<div id="referenceDiv" style="height: 40px; width: 40px;
|
||||
display: none; background: #2aff00;">
|
||||
</div>
|
||||
<div id="animatedImage">
|
||||
<img id='animatedGif' src="animated-gif.gif" style="display: none;">
|
||||
</div>
|
||||
<div id="text-descr"></div>
|
||||
<div id="debug" style="display:none">
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
var gAnimTest;
|
||||
var gIntervalId;
|
||||
|
||||
function initSecondTest() {
|
||||
document.getElementById('debug').style.display = 'none';
|
||||
document.getElementById('referenceDiv').style.background = "#9600ff";
|
||||
document.getElementById('animatedGif').setAttribute('src',
|
||||
'animated-gif2.gif');
|
||||
document.getElementById('animatedGif').style.display = 'none';
|
||||
var secondTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'animatedGif', 'debug', '', '', false);
|
||||
secondTest.beginTest();
|
||||
}
|
||||
|
||||
function main()
|
||||
{
|
||||
gAnimTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'animatedGif', 'debug', '', '', false,
|
||||
initSecondTest);
|
||||
gAnimTest.beginTest();
|
||||
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
48
image/test/mochitest/test_changeOfSource2.html
Normal file
@ -0,0 +1,48 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 691792 - Change of Source (2nd Version)</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=691792">
|
||||
Mozilla Bug 691792: Change of src attribute for animated gifs no longer works as expected
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
<div id="animatedImage">
|
||||
<img id='animatedGif' src="purple.gif" style="display: none;">
|
||||
</div>
|
||||
<div id="text-descr"></div>
|
||||
<div id="debug" style="display:none">
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
var gAnimTest;
|
||||
var gIntervalId;
|
||||
|
||||
function main()
|
||||
{
|
||||
gAnimTest = new AnimationTest(20, FAILURE_TIMEOUT, 'animated-gif2.gif',
|
||||
'animatedGif', 'debug', '', 'animated-gif2.gif',
|
||||
false);
|
||||
gAnimTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
52
image/test/mochitest/test_svg_animatedGIF.html
Normal file
@ -0,0 +1,52 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Animated Raster Images inside of SVG Frames</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
|
||||
<!-- Make sure embed element is snapped to an exact pixel. -->
|
||||
<div class="bug-header" style="height: 100px;">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<div id="referenceDiv" style="height: 40px; width: 40px;
|
||||
display: none; background: #2aff00"></div>
|
||||
<!--
|
||||
We use <embed> here instead of <img> because the <img> tag utilizes
|
||||
the VectorImage class for SVG, whereas in this test, we are testing
|
||||
RasterImage.
|
||||
-->
|
||||
<embed id="embeddedSVG" src="animation.svg" type="image/svg+xml" style="display: none;"/>
|
||||
</div>
|
||||
<div id="debug" style="display:none"></div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 666446 nsSVGImageFrame/RasterImage**/
|
||||
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main() {
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'embeddedSVG', 'debug', '', 'src');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
42
image/test/mochitest/test_svg_filter_animation.html
Normal file
@ -0,0 +1,42 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Animated Images within SVG Filters</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<embed id="referenceImage" src="filter-final.svg" type="image/svg+xml" style="display: none;"/>
|
||||
<embed id="embeddedSVGFilt" src="filter.svg" type="image/svg+xml" style="display: none;"/>
|
||||
</div>
|
||||
<div id="debug" style="display:none"></div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 666446 nsSVGFEImageElement/RasterImage**/
|
||||
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main() {
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceImage',
|
||||
'embeddedSVGFilt', 'debug', '', 'src');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
48
image/test/mochitest/test_undisplayed_iframe.html
Normal file
@ -0,0 +1,48 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Test for Animated Gif within IFRAME</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
<div id="referenceDiv" style="display:none;">
|
||||
<iframe id="referenceIFrame" src="ref-iframe.html" width="50%" height="100">
|
||||
Browser does not support iframes.
|
||||
</iframe>
|
||||
</div>
|
||||
<div id="animatedImage">
|
||||
<iframe id="imageIFrame" src="iframe.html" width="50%" height="100" style="display: none;">
|
||||
Browser does not support iframes.
|
||||
</iframe>
|
||||
</div>
|
||||
<div id="debug" style="display: none"></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main()
|
||||
{
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'imageIFrame', 'debug');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
67
image/test/mochitest/test_xultree_animation.xhtml
Normal file
@ -0,0 +1,67 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xml:lang="en" lang="en">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Animated Images within SVG Filters</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<xul:caption label="Bug 666446 - XULTree Test" />
|
||||
<xul:separator />
|
||||
<br />
|
||||
<xul:window id="main" title="Bug 666446: XUL Tree Testing" width="100" height="100">
|
||||
<xul:tree flex="1">
|
||||
<xul:treecols>
|
||||
<xul:treecol id="icon" label="Icon" flex="1" />
|
||||
</xul:treecols>
|
||||
|
||||
<xul:treechildren>
|
||||
<xul:treeitem id="referenceItem" hidden="true">
|
||||
<xul:treerow>
|
||||
<xul:treecell src="animated-gif-finalframe.gif" width="40" height="40" />
|
||||
</xul:treerow>
|
||||
</xul:treeitem>
|
||||
<xul:treeitem id="imageItem" hidden="true">
|
||||
<xul:treerow>
|
||||
<xul:treecell src="animated-gif.gif" width="40" height="40" />
|
||||
</xul:treerow>
|
||||
</xul:treeitem>
|
||||
</xul:treechildren>
|
||||
</xul:tree>
|
||||
</xul:window>
|
||||
</div>
|
||||
<div id="debug" style="display:none"></div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 666446 nsSVGFEImageElement/RasterImage**/
|
||||
|
||||
const FAILURE_TIMEOUT = 5000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main() {
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceItem',
|
||||
'imageItem', 'debug', '',
|
||||
'animated-gif-finalframe.gif', true);
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -417,11 +417,6 @@ class HashTable : private AllocPolicy
|
||||
destroyTable(*this, table, tableCapacity);
|
||||
}
|
||||
|
||||
size_t allocatedSize() const
|
||||
{
|
||||
return sizeof(Entry) * tableCapacity;
|
||||
}
|
||||
|
||||
private:
|
||||
static HashNumber hash1(HashNumber hash0, uint32 shift) {
|
||||
return hash0 >> shift;
|
||||
@ -1135,9 +1130,6 @@ class HashMap
|
||||
*/
|
||||
unsigned generation() const { return impl.generation(); }
|
||||
|
||||
/* Number of bytes of heap data allocated by this table. */
|
||||
size_t allocatedSize() const { return impl.allocatedSize(); }
|
||||
|
||||
/* Shorthand operations: */
|
||||
|
||||
bool has(const Lookup &l) const {
|
||||
@ -1338,9 +1330,6 @@ class HashSet
|
||||
*/
|
||||
unsigned generation() const { return impl.generation(); }
|
||||
|
||||
/* Number of bytes of heap data allocated by this table. */
|
||||
size_t allocatedSize() const { return impl.allocatedSize(); }
|
||||
|
||||
/* Shorthand operations: */
|
||||
|
||||
bool has(const Lookup &l) const {
|
||||
|
@ -74,10 +74,10 @@ AlignPtr(void *orig)
|
||||
/* Header for a chunk of memory wrangled by the LifoAlloc. */
|
||||
class BumpChunk
|
||||
{
|
||||
char *bump;
|
||||
char *limit;
|
||||
BumpChunk *next_;
|
||||
size_t bumpSpaceSize;
|
||||
char *bump; /* start of the available data */
|
||||
char *limit; /* end of the data */
|
||||
BumpChunk *next_; /* the next BumpChunk */
|
||||
size_t bumpSpaceSize; /* size of the data area */
|
||||
|
||||
char *headerBase() { return reinterpret_cast<char *>(this); }
|
||||
char *bumpBase() const { return limit - bumpSpaceSize; }
|
||||
@ -111,6 +111,10 @@ class BumpChunk
|
||||
void setNext(BumpChunk *succ) { next_ = succ; }
|
||||
|
||||
size_t used() const { return bump - bumpBase(); }
|
||||
size_t sizeOf(JSUsableSizeFun usf) {
|
||||
size_t usable = usf((void*)this);
|
||||
return usable ? usable : limit - headerBase();
|
||||
}
|
||||
|
||||
void resetBump() {
|
||||
setBump(headerBase() + sizeof(BumpChunk));
|
||||
@ -290,6 +294,22 @@ class LifoAlloc
|
||||
return accum;
|
||||
}
|
||||
|
||||
/* Get the total size of the arena chunks (including unused space), plus,
|
||||
* if |countMe| is true, the size of the LifoAlloc itself. */
|
||||
size_t sizeOf(JSUsableSizeFun usf, bool countMe) const {
|
||||
size_t accum = 0;
|
||||
if (countMe) {
|
||||
size_t usable = usf((void*)this);
|
||||
accum += usable ? usable : sizeof(LifoAlloc);
|
||||
}
|
||||
BumpChunk *it = first;
|
||||
while (it) {
|
||||
accum += it->sizeOf(usf);
|
||||
it = it->next();
|
||||
}
|
||||
return accum;
|
||||
}
|
||||
|
||||
/* Doesn't perform construction; useful for lazily-initialized POD types. */
|
||||
template <typename T>
|
||||
JS_ALWAYS_INLINE
|
||||
|
@ -2878,17 +2878,8 @@ EmitPropOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce,
|
||||
op = JSOP_CALLPROP;
|
||||
} else if (op == JSOP_GETPROP && pn->isKind(TOK_DOT)) {
|
||||
if (pn2->isKind(TOK_NAME)) {
|
||||
/*
|
||||
* Try to optimize arguments.length into JSOP_ARGCNT. If type
|
||||
* inference is enabled this is optimized separately.
|
||||
*/
|
||||
if (!BindNameToSlot(cx, bce, pn2))
|
||||
return false;
|
||||
if (!cx->typeInferenceEnabled() &&
|
||||
pn->pn_atom == cx->runtime->atomState.lengthAtom) {
|
||||
if (pn2->isOp(JSOP_ARGUMENTS))
|
||||
return Emit1(cx, bce, JSOP_ARGCNT) >= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3066,124 +3057,51 @@ EmitNameIncDec(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
|
||||
static JSBool
|
||||
EmitElemOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
|
||||
{
|
||||
ptrdiff_t top;
|
||||
ParseNode *left, *right, *next;
|
||||
int32_t slot;
|
||||
ParseNode *left, *right;
|
||||
|
||||
top = bce->offset();
|
||||
if (pn->isArity(PN_LIST)) {
|
||||
/* Left-associative operator chain to avoid too much recursion. */
|
||||
JS_ASSERT(pn->isOp(JSOP_GETELEM));
|
||||
JS_ASSERT(pn->pn_count >= 3);
|
||||
left = pn->pn_head;
|
||||
right = pn->last();
|
||||
next = left->pn_next;
|
||||
JS_ASSERT(next != right);
|
||||
ptrdiff_t top = bce->offset();
|
||||
|
||||
if (pn->isArity(PN_NAME)) {
|
||||
/*
|
||||
* Try to optimize arguments[0][j]... into JSOP_ARGSUB<0> followed by
|
||||
* one or more index expression and JSOP_GETELEM op pairs. If type
|
||||
* inference is enabled this is optimized separately.
|
||||
* Set left and right so pn appears to be a TOK_LB node, instead
|
||||
* of a TOK_DOT node. See the TOK_FOR/IN case in EmitTree, and
|
||||
* EmitDestructuringOps nearer below. In the destructuring case,
|
||||
* the base expression (pn_expr) of the name may be null, which
|
||||
* means we have to emit a JSOP_BINDNAME.
|
||||
*/
|
||||
if (left->isKind(TOK_NAME) && next->isKind(TOK_NUMBER)) {
|
||||
if (!BindNameToSlot(cx, bce, left))
|
||||
left = pn->maybeExpr();
|
||||
if (!left) {
|
||||
left = NullaryNode::create(bce);
|
||||
if (!left)
|
||||
return false;
|
||||
if (left->isOp(JSOP_ARGUMENTS) &&
|
||||
JSDOUBLE_IS_INT32(next->pn_dval, &slot) &&
|
||||
jsuint(slot) < JS_BIT(16) &&
|
||||
!cx->typeInferenceEnabled() &&
|
||||
(!bce->inStrictMode() ||
|
||||
(!bce->mutatesParameter() && !bce->callsEval()))) {
|
||||
/*
|
||||
* arguments[i]() requires arguments object as "this".
|
||||
* Check that we never generates list for that usage.
|
||||
*/
|
||||
JS_ASSERT(op != JSOP_CALLELEM || next->pn_next);
|
||||
left->pn_offset = next->pn_offset = top;
|
||||
EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot);
|
||||
left = next;
|
||||
next = left->pn_next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether we generated JSOP_ARGSUB, just above, and have only
|
||||
* one more index expression to emit. Given arguments[0][j], we must
|
||||
* skip the while loop altogether, falling through to emit code for j
|
||||
* (in the subtree referenced by right), followed by the annotated op,
|
||||
* at the bottom of this function.
|
||||
*/
|
||||
JS_ASSERT(next != right || pn->pn_count == 3);
|
||||
if (left == pn->pn_head) {
|
||||
if (!EmitTree(cx, bce, left))
|
||||
return false;
|
||||
}
|
||||
while (next != right) {
|
||||
if (!EmitTree(cx, bce, next))
|
||||
return false;
|
||||
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - top) < 0)
|
||||
return false;
|
||||
if (!EmitElemOpBase(cx, bce, JSOP_GETELEM))
|
||||
return false;
|
||||
next = next->pn_next;
|
||||
left->setKind(TOK_STRING);
|
||||
left->setOp(JSOP_BINDNAME);
|
||||
left->pn_pos = pn->pn_pos;
|
||||
left->pn_atom = pn->pn_atom;
|
||||
}
|
||||
right = NullaryNode::create(bce);
|
||||
if (!right)
|
||||
return false;
|
||||
right->setKind(TOK_STRING);
|
||||
right->setOp(IsIdentifier(pn->pn_atom) ? JSOP_QNAMEPART : JSOP_STRING);
|
||||
right->pn_pos = pn->pn_pos;
|
||||
right->pn_atom = pn->pn_atom;
|
||||
} else {
|
||||
if (pn->isArity(PN_NAME)) {
|
||||
/*
|
||||
* Set left and right so pn appears to be a TOK_LB node, instead
|
||||
* of a TOK_DOT node. See the TOK_FOR/IN case in EmitTree, and
|
||||
* EmitDestructuringOps nearer below. In the destructuring case,
|
||||
* the base expression (pn_expr) of the name may be null, which
|
||||
* means we have to emit a JSOP_BINDNAME.
|
||||
*/
|
||||
left = pn->maybeExpr();
|
||||
if (!left) {
|
||||
left = NullaryNode::create(bce);
|
||||
if (!left)
|
||||
return false;
|
||||
left->setKind(TOK_STRING);
|
||||
left->setOp(JSOP_BINDNAME);
|
||||
left->pn_pos = pn->pn_pos;
|
||||
left->pn_atom = pn->pn_atom;
|
||||
}
|
||||
right = NullaryNode::create(bce);
|
||||
if (!right)
|
||||
return false;
|
||||
right->setKind(TOK_STRING);
|
||||
right->setOp(IsIdentifier(pn->pn_atom) ? JSOP_QNAMEPART : JSOP_STRING);
|
||||
right->pn_pos = pn->pn_pos;
|
||||
right->pn_atom = pn->pn_atom;
|
||||
} else {
|
||||
JS_ASSERT(pn->isArity(PN_BINARY));
|
||||
left = pn->pn_left;
|
||||
right = pn->pn_right;
|
||||
}
|
||||
JS_ASSERT(pn->isArity(PN_BINARY));
|
||||
left = pn->pn_left;
|
||||
right = pn->pn_right;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to optimize arguments[0] (e.g.) into JSOP_ARGSUB<0>. If type
|
||||
* inference is enabled this is optimized separately.
|
||||
*/
|
||||
if (op == JSOP_GETELEM &&
|
||||
left->isKind(TOK_NAME) &&
|
||||
right->isKind(TOK_NUMBER)) {
|
||||
if (!BindNameToSlot(cx, bce, left))
|
||||
return false;
|
||||
if (left->isOp(JSOP_ARGUMENTS) &&
|
||||
JSDOUBLE_IS_INT32(right->pn_dval, &slot) &&
|
||||
jsuint(slot) < JS_BIT(16) &&
|
||||
!cx->typeInferenceEnabled() &&
|
||||
(!bce->inStrictMode() ||
|
||||
(!bce->mutatesParameter() && !bce->callsEval()))) {
|
||||
left->pn_offset = right->pn_offset = top;
|
||||
EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EmitTree(cx, bce, left))
|
||||
if (op == JSOP_GETELEM &&
|
||||
left->isKind(TOK_NAME) &&
|
||||
right->isKind(TOK_NUMBER)) {
|
||||
if (!BindNameToSlot(cx, bce, left))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EmitTree(cx, bce, left))
|
||||
return false;
|
||||
|
||||
/* The right side of the descendant operator is implicitly quoted. */
|
||||
JS_ASSERT(op != JSOP_DESCENDANTS || !right->isKind(TOK_STRING) ||
|
||||
right->isOp(JSOP_QNAMEPART));
|
||||
|
@ -550,8 +550,6 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
case JSOP_LAMBDA_FC:
|
||||
case JSOP_GETFCSLOT:
|
||||
case JSOP_CALLFCSLOT:
|
||||
case JSOP_ARGSUB:
|
||||
case JSOP_ARGCNT:
|
||||
case JSOP_DEBUGGER:
|
||||
case JSOP_FUNCALL:
|
||||
case JSOP_FUNAPPLY:
|
||||
|
@ -616,14 +616,13 @@ class Chars {
|
||||
JSContext *cx;
|
||||
jschar *p;
|
||||
public:
|
||||
Chars() : p(NULL) {}
|
||||
Chars(JSContext *cx) : cx(cx), p(NULL) {}
|
||||
~Chars() { if (p) cx->free_(p); }
|
||||
|
||||
bool allocate(JSContext *cx, size_t len) {
|
||||
bool allocate(size_t len) {
|
||||
JS_ASSERT(!p);
|
||||
// We're going to null-terminate!
|
||||
p = (jschar *) cx->malloc_((len + 1) * sizeof(jschar));
|
||||
this->cx = cx;
|
||||
if (p) {
|
||||
p[len] = jschar(0);
|
||||
return true;
|
||||
@ -642,8 +641,8 @@ JSStructuredCloneReader::readString(uint32_t nchars)
|
||||
"string length");
|
||||
return NULL;
|
||||
}
|
||||
Chars chars;
|
||||
if (!chars.allocate(context(), nchars) || !in.readChars(chars.get(), nchars))
|
||||
Chars chars(context());
|
||||
if (!chars.allocate(nchars) || !in.readChars(chars.get(), nchars))
|
||||
return NULL;
|
||||
JSString *str = js_NewString(context(), chars.get(), nchars);
|
||||
if (str)
|
||||
|
@ -109,11 +109,13 @@ typedef struct TypeInferenceMemoryStats
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
|
||||
TypeInferenceMemoryStats *stats);
|
||||
TypeInferenceMemoryStats *stats,
|
||||
JSUsableSizeFun usf);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
JS_GetTypeInferenceObjectStats(/*TypeObject*/ void *object,
|
||||
TypeInferenceMemoryStats *stats);
|
||||
TypeInferenceMemoryStats *stats,
|
||||
JSUsableSizeFun usf);
|
||||
|
||||
extern JS_FRIEND_API(JSPrincipals *)
|
||||
JS_GetCompartmentPrincipals(JSCompartment *compartment);
|
||||
|
@ -124,69 +124,6 @@ js_GetArgsValue(JSContext *cx, StackFrame *fp, Value *vp)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_GetArgsProperty(JSContext *cx, StackFrame *fp, jsid id, Value *vp)
|
||||
{
|
||||
JS_ASSERT(fp->isFunctionFrame());
|
||||
|
||||
if (fp->hasOverriddenArgs()) {
|
||||
JS_ASSERT(fp->hasCallObj());
|
||||
|
||||
Value v;
|
||||
if (!fp->callObj().getProperty(cx, cx->runtime->atomState.argumentsAtom, &v))
|
||||
return false;
|
||||
|
||||
JSObject *obj;
|
||||
if (v.isPrimitive()) {
|
||||
obj = js_ValueToNonNullObject(cx, v);
|
||||
if (!obj)
|
||||
return false;
|
||||
} else {
|
||||
obj = &v.toObject();
|
||||
}
|
||||
return obj->getGeneric(cx, id, vp);
|
||||
}
|
||||
|
||||
vp->setUndefined();
|
||||
if (JSID_IS_INT(id)) {
|
||||
uint32 arg = uint32(JSID_TO_INT(id));
|
||||
ArgumentsObject *argsobj = fp->maybeArgsObj();
|
||||
if (arg < fp->numActualArgs()) {
|
||||
if (argsobj) {
|
||||
const Value &v = argsobj->element(arg);
|
||||
if (v.isMagic(JS_ARGS_HOLE))
|
||||
return argsobj->getGeneric(cx, id, vp);
|
||||
if (fp->functionScript()->strictModeCode) {
|
||||
*vp = v;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*vp = fp->canonicalActualArg(arg);
|
||||
} else {
|
||||
/*
|
||||
* Per ECMA-262 Ed. 3, 10.1.8, last bulleted item, do not share
|
||||
* storage between the formal parameter and arguments[k] for all
|
||||
* fp->argc <= k && k < fp->fun->nargs. For example, in
|
||||
*
|
||||
* function f(x) { x = 42; return arguments[0]; }
|
||||
* f();
|
||||
*
|
||||
* the call to f should return undefined, not 42. If fp->argsobj
|
||||
* is null at this point, as it would be in the example, return
|
||||
* undefined in *vp.
|
||||
*/
|
||||
if (argsobj)
|
||||
return argsobj->getGeneric(cx, id, vp);
|
||||
}
|
||||
} else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
|
||||
ArgumentsObject *argsobj = fp->maybeArgsObj();
|
||||
if (argsobj && argsobj->hasOverriddenLength())
|
||||
return argsobj->getGeneric(cx, id, vp);
|
||||
vp->setInt32(fp->numActualArgs());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
js::ArgumentsObject *
|
||||
ArgumentsObject::create(JSContext *cx, uint32 argc, JSObject &callee)
|
||||
{
|
||||
|
@ -536,9 +536,6 @@ SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp
|
||||
extern JSBool
|
||||
js_GetArgsValue(JSContext *cx, js::StackFrame *fp, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetArgsProperty(JSContext *cx, js::StackFrame *fp, jsid id, js::Value *vp);
|
||||
|
||||
/*
|
||||
* Get the arguments object for the given frame. If the frame is strict mode
|
||||
* code, its current arguments will be copied into the arguments object.
|
||||
|
@ -6106,7 +6106,11 @@ TypeScript::destroy()
|
||||
inline size_t
|
||||
TypeSet::dynamicSize()
|
||||
{
|
||||
/* Get the amount of memory allocated from the analysis pool for this set. */
|
||||
/*
|
||||
* This memory is allocated within the temp pool (but accounted for
|
||||
* elsewhere) so we can't use a JSUsableSizeFun to measure it. We must do
|
||||
* it analytically.
|
||||
*/
|
||||
uint32 count = baseObjectCount();
|
||||
if (count >= 2)
|
||||
return HashSetCapacity(count) * sizeof(TypeObject *);
|
||||
@ -6116,6 +6120,11 @@ TypeSet::dynamicSize()
|
||||
inline size_t
|
||||
TypeObject::dynamicSize()
|
||||
{
|
||||
/*
|
||||
* This memory is allocated within the temp pool (but accounted for
|
||||
* elsewhere) so we can't use a JSUsableSizeFun to measure it. We must do
|
||||
* it analytically.
|
||||
*/
|
||||
size_t bytes = 0;
|
||||
|
||||
uint32 count = basePropertyCount();
|
||||
@ -6133,26 +6142,40 @@ TypeObject::dynamicSize()
|
||||
}
|
||||
|
||||
static void
|
||||
GetScriptMemoryStats(JSScript *script, TypeInferenceMemoryStats *stats)
|
||||
GetScriptMemoryStats(JSScript *script, TypeInferenceMemoryStats *stats, JSUsableSizeFun usf)
|
||||
{
|
||||
if (!script->types)
|
||||
TypeScript *typeScript = script->types;
|
||||
if (!typeScript)
|
||||
return;
|
||||
|
||||
size_t usable;
|
||||
|
||||
/* If TI is disabled, a single TypeScript is still present. */
|
||||
if (!script->compartment()->types.inferenceEnabled) {
|
||||
stats->scripts += sizeof(TypeScript);
|
||||
usable = usf(typeScript);
|
||||
stats->scripts += usable ? usable : sizeof(TypeScript);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned count = TypeScript::NumTypeSets(script);
|
||||
stats->scripts += sizeof(TypeScript) + count * sizeof(TypeSet);
|
||||
usable = usf(typeScript->nesting);
|
||||
stats->scripts += usable ? usable : sizeof(TypeScriptNesting);
|
||||
|
||||
TypeResult *result = script->types->dynamicList;
|
||||
unsigned count = TypeScript::NumTypeSets(script);
|
||||
usable = usf(typeScript);
|
||||
stats->scripts += usable ? usable : sizeof(TypeScript) + count * sizeof(TypeSet);
|
||||
|
||||
TypeResult *result = typeScript->dynamicList;
|
||||
while (result) {
|
||||
stats->scripts += sizeof(TypeResult);
|
||||
usable = usf(result);
|
||||
stats->scripts += usable ? usable : sizeof(TypeResult);
|
||||
result = result->next;
|
||||
}
|
||||
|
||||
TypeSet *typeArray = script->types->typeArray();
|
||||
/*
|
||||
* This counts memory that is in the temp pool but gets attributed
|
||||
* elsewhere. See JS_GetTypeInferenceMemoryStats for more details.
|
||||
*/
|
||||
TypeSet *typeArray = typeScript->typeArray();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
size_t bytes = typeArray[i].dynamicSize();
|
||||
stats->scripts += bytes;
|
||||
@ -6162,44 +6185,54 @@ GetScriptMemoryStats(JSScript *script, TypeInferenceMemoryStats *stats)
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
|
||||
TypeInferenceMemoryStats *stats)
|
||||
TypeInferenceMemoryStats *stats, JSUsableSizeFun usf)
|
||||
{
|
||||
/*
|
||||
* Note: not all data in the pool is temporary, and some will survive GCs
|
||||
* by being copied to the replacement pool. This memory will be counted too
|
||||
* and deducted from the amount of temporary data.
|
||||
* by being copied to the replacement pool. This memory will be counted
|
||||
* elsewhere and deducted from the amount of temporary data.
|
||||
*/
|
||||
stats->temporary += compartment->typeLifoAlloc.used();
|
||||
stats->temporary += compartment->typeLifoAlloc.sizeOf(usf, /* countMe = */false);
|
||||
|
||||
/* Pending arrays are cleared on GC along with the analysis pool. */
|
||||
stats->temporary += sizeof(TypeCompartment::PendingWork) * compartment->types.pendingCapacity;
|
||||
size_t usable = usf(compartment->types.pendingArray);
|
||||
stats->temporary +=
|
||||
usable ? usable
|
||||
: sizeof(TypeCompartment::PendingWork) * compartment->types.pendingCapacity;
|
||||
|
||||
/* TypeCompartment::pendingRecompiles is non-NULL only while inference code is running. */
|
||||
JS_ASSERT(!compartment->types.pendingRecompiles);
|
||||
|
||||
for (gc::CellIter i(cx, compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next())
|
||||
GetScriptMemoryStats(i.get<JSScript>(), stats);
|
||||
GetScriptMemoryStats(i.get<JSScript>(), stats, usf);
|
||||
|
||||
if (compartment->types.allocationSiteTable)
|
||||
stats->tables += compartment->types.allocationSiteTable->allocatedSize();
|
||||
stats->tables += compartment->types.allocationSiteTable->sizeOf(usf, /* countMe = */true);
|
||||
|
||||
if (compartment->types.arrayTypeTable)
|
||||
stats->tables += compartment->types.arrayTypeTable->allocatedSize();
|
||||
stats->tables += compartment->types.arrayTypeTable->sizeOf(usf, /* countMe = */true);
|
||||
|
||||
if (compartment->types.objectTypeTable) {
|
||||
stats->tables += compartment->types.objectTypeTable->allocatedSize();
|
||||
stats->tables += compartment->types.objectTypeTable->sizeOf(usf, /* countMe = */true);
|
||||
|
||||
for (ObjectTypeTable::Enum e(*compartment->types.objectTypeTable);
|
||||
!e.empty();
|
||||
e.popFront()) {
|
||||
e.popFront())
|
||||
{
|
||||
const ObjectTableKey &key = e.front().key;
|
||||
stats->tables += key.nslots * (sizeof(jsid) + sizeof(Type));
|
||||
const ObjectTableEntry &value = e.front().value;
|
||||
|
||||
/* key.ids and values.types have the same length. */
|
||||
usable = usf(key.ids) + usf(value.types);
|
||||
stats->tables += usable ? usable : key.nslots * (sizeof(jsid) + sizeof(Type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS_GetTypeInferenceObjectStats(void *object_, TypeInferenceMemoryStats *stats)
|
||||
JS_GetTypeInferenceObjectStats(void *object_, TypeInferenceMemoryStats *stats, JSUsableSizeFun usf)
|
||||
{
|
||||
TypeObject *object = (TypeObject *) object_;
|
||||
stats->objects += sizeof(TypeObject);
|
||||
|
||||
if (object->singleton) {
|
||||
/*
|
||||
@ -6212,18 +6245,30 @@ JS_GetTypeInferenceObjectStats(void *object_, TypeInferenceMemoryStats *stats)
|
||||
}
|
||||
|
||||
if (object->newScript) {
|
||||
size_t length = 0;
|
||||
for (TypeNewScript::Initializer *init = object->newScript->initializerList;; init++) {
|
||||
length++;
|
||||
if (init->kind == TypeNewScript::Initializer::DONE)
|
||||
break;
|
||||
/* The initializerList is tacked onto the end of the TypeNewScript. */
|
||||
size_t usable = usf(object->newScript);
|
||||
if (usable) {
|
||||
stats->objects += usable;
|
||||
} else {
|
||||
stats->objects += sizeof(TypeNewScript);
|
||||
for (TypeNewScript::Initializer *init = object->newScript->initializerList; ; init++) {
|
||||
stats->objects += sizeof(TypeNewScript::Initializer);
|
||||
if (init->kind == TypeNewScript::Initializer::DONE)
|
||||
break;
|
||||
}
|
||||
}
|
||||
stats->objects += sizeof(TypeNewScript) + (length * sizeof(TypeNewScript::Initializer));
|
||||
}
|
||||
|
||||
if (object->emptyShapes)
|
||||
stats->emptyShapes += sizeof(EmptyShape*) * gc::FINALIZE_FUNCTION_AND_OBJECT_LAST;
|
||||
if (object->emptyShapes) {
|
||||
size_t usable = usf(object->emptyShapes);
|
||||
stats->emptyShapes +=
|
||||
usable ? usable : sizeof(EmptyShape*) * gc::FINALIZE_FUNCTION_AND_OBJECT_LAST;
|
||||
}
|
||||
|
||||
/*
|
||||
* This counts memory that is in the temp pool but gets attributed
|
||||
* elsewhere. See JS_GetTypeInferenceMemoryStats for more details.
|
||||
*/
|
||||
size_t bytes = object->dynamicSize();
|
||||
stats->objects += bytes;
|
||||
stats->temporary -= bytes;
|
||||
|
@ -1022,11 +1022,11 @@ class TypeScript
|
||||
/* Global object for the script, if compileAndGo. */
|
||||
js::GlobalObject *global;
|
||||
|
||||
public:
|
||||
|
||||
/* Nesting state for outer or inner function scripts. */
|
||||
TypeScriptNesting *nesting;
|
||||
|
||||
public:
|
||||
|
||||
/* Dynamic types generated at points within this script. */
|
||||
TypeResult *dynamicList;
|
||||
|
||||
|
@ -4397,26 +4397,6 @@ BEGIN_CASE(JSOP_ARGUMENTS)
|
||||
}
|
||||
END_CASE(JSOP_ARGUMENTS)
|
||||
|
||||
BEGIN_CASE(JSOP_ARGSUB)
|
||||
{
|
||||
jsid id = INT_TO_JSID(GET_ARGNO(regs.pc));
|
||||
Value rval;
|
||||
if (!js_GetArgsProperty(cx, regs.fp(), id, &rval))
|
||||
goto error;
|
||||
PUSH_COPY(rval);
|
||||
}
|
||||
END_CASE(JSOP_ARGSUB)
|
||||
|
||||
BEGIN_CASE(JSOP_ARGCNT)
|
||||
{
|
||||
jsid id = ATOM_TO_JSID(rt->atomState.lengthAtom);
|
||||
Value rval;
|
||||
if (!js_GetArgsProperty(cx, regs.fp(), id, &rval))
|
||||
goto error;
|
||||
PUSH_COPY(rval);
|
||||
}
|
||||
END_CASE(JSOP_ARGCNT)
|
||||
|
||||
BEGIN_CASE(JSOP_GETARG)
|
||||
BEGIN_CASE(JSOP_CALLARG)
|
||||
{
|
||||
|
@ -3974,17 +3974,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||
rval);
|
||||
break;
|
||||
|
||||
case JSOP_ARGSUB:
|
||||
i = (jsint) GET_ARGNO(pc);
|
||||
todo = Sprint(&ss->sprinter, "%s[%d]",
|
||||
js_arguments_str, (int) i);
|
||||
break;
|
||||
|
||||
case JSOP_ARGCNT:
|
||||
todo = Sprint(&ss->sprinter, dot_format,
|
||||
js_arguments_str, js_length_str);
|
||||
break;
|
||||
|
||||
case JSOP_CALLARG:
|
||||
case JSOP_GETARG:
|
||||
i = GET_ARGNO(pc);
|
||||
|
@ -373,82 +373,74 @@ OPDEF(JSOP_FINALLY, 135,"finally", NULL, 1, 0, 2, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_GETFCSLOT, 136,"getfcslot", NULL, 3, 0, 1, 19, JOF_UINT16|JOF_NAME|JOF_TYPESET)
|
||||
OPDEF(JSOP_CALLFCSLOT, 137,"callfcslot", NULL, 3, 0, 2, 19, JOF_UINT16|JOF_NAME|JOF_TYPESET|JOF_CALLOP)
|
||||
|
||||
/*
|
||||
* Bytecodes that avoid making an arguments object in most cases:
|
||||
* JSOP_ARGSUB gets arguments[i] from fp->argv, iff i is in [0, fp->argc-1].
|
||||
* JSOP_ARGCNT returns fp->argc.
|
||||
*/
|
||||
OPDEF(JSOP_ARGSUB, 138,"argsub", NULL, 3, 0, 1, 18, JOF_QARG |JOF_NAME)
|
||||
OPDEF(JSOP_ARGCNT, 139,"argcnt", NULL, 1, 0, 1, 18, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* Define a local function object as a local variable.
|
||||
* The local variable's slot number is the first immediate two-byte operand.
|
||||
* The function object's atom index is the second immediate operand.
|
||||
*/
|
||||
OPDEF(JSOP_DEFLOCALFUN, 140,"deflocalfun",NULL, 5, 0, 0, 0, JOF_SLOTOBJECT|JOF_DECLARING|JOF_TMPSLOT)
|
||||
OPDEF(JSOP_DEFLOCALFUN, 138,"deflocalfun",NULL, 5, 0, 0, 0, JOF_SLOTOBJECT|JOF_DECLARING|JOF_TMPSLOT)
|
||||
|
||||
/* Extended jumps. */
|
||||
OPDEF(JSOP_GOTOX, 141,"gotox", NULL, 5, 0, 0, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_IFEQX, 142,"ifeqx", NULL, 5, 1, 0, 4, JOF_JUMPX|JOF_DETECTING)
|
||||
OPDEF(JSOP_IFNEX, 143,"ifnex", NULL, 5, 1, 0, 0, JOF_JUMPX|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_ORX, 144,"orx", NULL, 5, 1, 0, 5, JOF_JUMPX|JOF_DETECTING)
|
||||
OPDEF(JSOP_ANDX, 145,"andx", NULL, 5, 1, 0, 6, JOF_JUMPX|JOF_DETECTING)
|
||||
OPDEF(JSOP_GOSUBX, 146,"gosubx", NULL, 5, 0, 0, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_CASEX, 147,"casex", NULL, 5, 2, 1, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_DEFAULTX, 148,"defaultx", NULL, 5, 1, 0, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_TABLESWITCHX, 149,"tableswitchx",NULL, -1, 1, 0, 0, JOF_TABLESWITCHX|JOF_DETECTING|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_LOOKUPSWITCHX, 150,"lookupswitchx",NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCHX|JOF_DETECTING|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_GOTOX, 139,"gotox", NULL, 5, 0, 0, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_IFEQX, 140,"ifeqx", NULL, 5, 1, 0, 4, JOF_JUMPX|JOF_DETECTING)
|
||||
OPDEF(JSOP_IFNEX, 141,"ifnex", NULL, 5, 1, 0, 0, JOF_JUMPX|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_ORX, 142,"orx", NULL, 5, 1, 0, 5, JOF_JUMPX|JOF_DETECTING)
|
||||
OPDEF(JSOP_ANDX, 143,"andx", NULL, 5, 1, 0, 6, JOF_JUMPX|JOF_DETECTING)
|
||||
OPDEF(JSOP_GOSUBX, 144,"gosubx", NULL, 5, 0, 0, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_CASEX, 145,"casex", NULL, 5, 2, 1, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_DEFAULTX, 146,"defaultx", NULL, 5, 1, 0, 0, JOF_JUMPX)
|
||||
OPDEF(JSOP_TABLESWITCHX, 147,"tableswitchx",NULL, -1, 1, 0, 0, JOF_TABLESWITCHX|JOF_DETECTING|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_LOOKUPSWITCHX, 148,"lookupswitchx",NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCHX|JOF_DETECTING|JOF_PARENHEAD)
|
||||
|
||||
/* Placeholders for a real jump opcode set during backpatch chain fixup. */
|
||||
OPDEF(JSOP_BACKPATCH, 151,"backpatch",NULL, 3, 0, 0, 0, JOF_JUMP|JOF_BACKPATCH)
|
||||
OPDEF(JSOP_BACKPATCH_POP, 152,"backpatch_pop",NULL, 3, 1, 0, 0, JOF_JUMP|JOF_BACKPATCH)
|
||||
OPDEF(JSOP_BACKPATCH, 149,"backpatch",NULL, 3, 0, 0, 0, JOF_JUMP|JOF_BACKPATCH)
|
||||
OPDEF(JSOP_BACKPATCH_POP, 150,"backpatch_pop",NULL, 3, 1, 0, 0, JOF_JUMP|JOF_BACKPATCH)
|
||||
|
||||
/* Set pending exception from the stack, to trigger rethrow. */
|
||||
OPDEF(JSOP_THROWING, 153,"throwing", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_THROWING, 151,"throwing", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
|
||||
/* Set and get return value pseudo-register in stack frame. */
|
||||
OPDEF(JSOP_SETRVAL, 154,"setrval", NULL, 1, 1, 0, 2, JOF_BYTE)
|
||||
OPDEF(JSOP_RETRVAL, 155,"retrval", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_SETRVAL, 152,"setrval", NULL, 1, 1, 0, 2, JOF_BYTE)
|
||||
OPDEF(JSOP_RETRVAL, 153,"retrval", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/* Free variable references that must either be found on the global or a ReferenceError */
|
||||
OPDEF(JSOP_GETGNAME, 156,"getgname", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_GNAME)
|
||||
OPDEF(JSOP_SETGNAME, 157,"setgname", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_GNAME)
|
||||
OPDEF(JSOP_INCGNAME, 158,"incgname", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_DECGNAME, 159,"decgname", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_GNAMEINC, 160,"gnameinc", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_GNAMEDEC, 161,"gnamedec", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_GETGNAME, 154,"getgname", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_GNAME)
|
||||
OPDEF(JSOP_SETGNAME, 155,"setgname", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_GNAME)
|
||||
OPDEF(JSOP_INCGNAME, 156,"incgname", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_DECGNAME, 157,"decgname", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_GNAMEINC, 158,"gnameinc", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_GNAMEDEC, 159,"gnamedec", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
|
||||
|
||||
/* Regular expression literal requiring special "fork on exec" handling. */
|
||||
OPDEF(JSOP_REGEXP, 162,"regexp", NULL, 3, 0, 1, 19, JOF_REGEXP)
|
||||
OPDEF(JSOP_REGEXP, 160,"regexp", NULL, 3, 0, 1, 19, JOF_REGEXP)
|
||||
|
||||
/* XML (ECMA-357, a.k.a. "E4X") support. */
|
||||
OPDEF(JSOP_DEFXMLNS, 163,"defxmlns", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_ANYNAME, 164,"anyname", NULL, 1, 0, 1, 19, JOF_BYTE|JOF_XMLNAME)
|
||||
OPDEF(JSOP_QNAMEPART, 165,"qnamepart", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_XMLNAME)
|
||||
OPDEF(JSOP_QNAMECONST, 166,"qnameconst", NULL, 3, 1, 1, 19, JOF_ATOM|JOF_XMLNAME)
|
||||
OPDEF(JSOP_QNAME, 167,"qname", NULL, 1, 2, 1, 0, JOF_BYTE|JOF_XMLNAME)
|
||||
OPDEF(JSOP_TOATTRNAME, 168,"toattrname", NULL, 1, 1, 1, 19, JOF_BYTE|JOF_XMLNAME)
|
||||
OPDEF(JSOP_TOATTRVAL, 169,"toattrval", NULL, 1, 1, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_ADDATTRNAME, 170,"addattrname",NULL, 1, 2, 1, 13, JOF_BYTE)
|
||||
OPDEF(JSOP_ADDATTRVAL, 171,"addattrval", NULL, 1, 2, 1, 13, JOF_BYTE)
|
||||
OPDEF(JSOP_BINDXMLNAME, 172,"bindxmlname",NULL, 1, 1, 2, 3, JOF_BYTE|JOF_SET)
|
||||
OPDEF(JSOP_SETXMLNAME, 173,"setxmlname", NULL, 1, 3, 1, 3, JOF_BYTE|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_XMLNAME, 174,"xmlname", NULL, 1, 1, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_DESCENDANTS, 175,"descendants",NULL, 1, 2, 1, 18, JOF_BYTE)
|
||||
OPDEF(JSOP_FILTER, 176,"filter", NULL, 3, 1, 1, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_ENDFILTER, 177,"endfilter", NULL, 3, 2, 1, 18, JOF_JUMP)
|
||||
OPDEF(JSOP_TOXML, 178,"toxml", NULL, 1, 1, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_TOXMLLIST, 179,"toxmllist", NULL, 1, 1, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_XMLTAGEXPR, 180,"xmltagexpr", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_XMLELTEXPR, 181,"xmleltexpr", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_NOTRACE, 182,"notrace", NULL, 3, 0, 0, 0, JOF_UINT16)
|
||||
OPDEF(JSOP_XMLCDATA, 183,"xmlcdata", NULL, 3, 0, 1, 19, JOF_ATOM)
|
||||
OPDEF(JSOP_XMLCOMMENT, 184,"xmlcomment", NULL, 3, 0, 1, 19, JOF_ATOM)
|
||||
OPDEF(JSOP_XMLPI, 185,"xmlpi", NULL, 3, 1, 1, 19, JOF_ATOM)
|
||||
OPDEF(JSOP_DELDESC, 186,"deldesc", NULL, 1, 2, 1, 15, JOF_BYTE|JOF_ELEM|JOF_DEL)
|
||||
OPDEF(JSOP_DEFXMLNS, 161,"defxmlns", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_ANYNAME, 162,"anyname", NULL, 1, 0, 1, 19, JOF_BYTE|JOF_XMLNAME)
|
||||
OPDEF(JSOP_QNAMEPART, 163,"qnamepart", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_XMLNAME)
|
||||
OPDEF(JSOP_QNAMECONST, 164,"qnameconst", NULL, 3, 1, 1, 19, JOF_ATOM|JOF_XMLNAME)
|
||||
OPDEF(JSOP_QNAME, 165,"qname", NULL, 1, 2, 1, 0, JOF_BYTE|JOF_XMLNAME)
|
||||
OPDEF(JSOP_TOATTRNAME, 166,"toattrname", NULL, 1, 1, 1, 19, JOF_BYTE|JOF_XMLNAME)
|
||||
OPDEF(JSOP_TOATTRVAL, 167,"toattrval", NULL, 1, 1, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_ADDATTRNAME, 168,"addattrname",NULL, 1, 2, 1, 13, JOF_BYTE)
|
||||
OPDEF(JSOP_ADDATTRVAL, 169,"addattrval", NULL, 1, 2, 1, 13, JOF_BYTE)
|
||||
OPDEF(JSOP_BINDXMLNAME, 170,"bindxmlname",NULL, 1, 1, 2, 3, JOF_BYTE|JOF_SET)
|
||||
OPDEF(JSOP_SETXMLNAME, 171,"setxmlname", NULL, 1, 3, 1, 3, JOF_BYTE|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_XMLNAME, 172,"xmlname", NULL, 1, 1, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_DESCENDANTS, 173,"descendants",NULL, 1, 2, 1, 18, JOF_BYTE)
|
||||
OPDEF(JSOP_FILTER, 174,"filter", NULL, 3, 1, 1, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_ENDFILTER, 175,"endfilter", NULL, 3, 2, 1, 18, JOF_JUMP)
|
||||
OPDEF(JSOP_TOXML, 176,"toxml", NULL, 1, 1, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_TOXMLLIST, 177,"toxmllist", NULL, 1, 1, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_XMLTAGEXPR, 178,"xmltagexpr", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_XMLELTEXPR, 179,"xmleltexpr", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_NOTRACE, 180,"notrace", NULL, 3, 0, 0, 0, JOF_UINT16)
|
||||
OPDEF(JSOP_XMLCDATA, 181,"xmlcdata", NULL, 3, 0, 1, 19, JOF_ATOM)
|
||||
OPDEF(JSOP_XMLCOMMENT, 182,"xmlcomment", NULL, 3, 0, 1, 19, JOF_ATOM)
|
||||
OPDEF(JSOP_XMLPI, 183,"xmlpi", NULL, 3, 1, 1, 19, JOF_ATOM)
|
||||
OPDEF(JSOP_DELDESC, 184,"deldesc", NULL, 1, 2, 1, 15, JOF_BYTE|JOF_ELEM|JOF_DEL)
|
||||
|
||||
OPDEF(JSOP_CALLPROP, 187,"callprop", NULL, 3, 1, 2, 18, JOF_ATOM|JOF_PROP|JOF_TYPESET|JOF_CALLOP|JOF_TMPSLOT3)
|
||||
OPDEF(JSOP_CALLPROP, 185,"callprop", NULL, 3, 1, 2, 18, JOF_ATOM|JOF_PROP|JOF_TYPESET|JOF_CALLOP|JOF_TMPSLOT3)
|
||||
|
||||
/*
|
||||
* These opcodes contain a reference to the current blockChain object.
|
||||
@ -457,13 +449,13 @@ OPDEF(JSOP_CALLPROP, 187,"callprop", NULL, 3, 1, 2, 18, JOF_ATOM|J
|
||||
* does not permit NULL object references, since it stores an index into a table of
|
||||
* objects.
|
||||
*/
|
||||
OPDEF(JSOP_BLOCKCHAIN, 188,"blockchain", NULL, 3, 0, 0, 0, JOF_OBJECT)
|
||||
OPDEF(JSOP_NULLBLOCKCHAIN,189,"nullblockchain",NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_BLOCKCHAIN, 186,"blockchain", NULL, 3, 0, 0, 0, JOF_OBJECT)
|
||||
OPDEF(JSOP_NULLBLOCKCHAIN,187,"nullblockchain",NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* Opcode to hold 24-bit immediate integer operands.
|
||||
*/
|
||||
OPDEF(JSOP_UINT24, 190,"uint24", NULL, 4, 0, 1, 16, JOF_UINT24)
|
||||
OPDEF(JSOP_UINT24, 188,"uint24", NULL, 4, 0, 1, 16, JOF_UINT24)
|
||||
|
||||
/*
|
||||
* Opcodes to allow 24-bit atom or object indexes. Whenever an index exceeds
|
||||
@ -471,126 +463,126 @@ OPDEF(JSOP_UINT24, 190,"uint24", NULL, 4, 0, 1, 16, JOF_UINT24
|
||||
* JSOP_INDEXBASE and JSOP_RESETBASE to provide the upper bits of the index.
|
||||
* See jsemit.c, EmitIndexOp.
|
||||
*/
|
||||
OPDEF(JSOP_INDEXBASE, 191,"indexbase", NULL, 2, 0, 0, 0, JOF_UINT8|JOF_INDEXBASE)
|
||||
OPDEF(JSOP_RESETBASE, 192,"resetbase", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_RESETBASE0, 193,"resetbase0", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_INDEXBASE, 189,"indexbase", NULL, 2, 0, 0, 0, JOF_UINT8|JOF_INDEXBASE)
|
||||
OPDEF(JSOP_RESETBASE, 190,"resetbase", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_RESETBASE0, 191,"resetbase0", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* Opcodes to help the decompiler deal with XML.
|
||||
*/
|
||||
OPDEF(JSOP_STARTXML, 194,"startxml", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_STARTXMLEXPR, 195,"startxmlexpr",NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_STARTXML, 192,"startxml", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_STARTXMLEXPR, 193,"startxmlexpr",NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
OPDEF(JSOP_CALLELEM, 196, "callelem", NULL, 1, 2, 2, 18, JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC|JOF_CALLOP)
|
||||
OPDEF(JSOP_CALLELEM, 194, "callelem", NULL, 1, 2, 2, 18, JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC|JOF_CALLOP)
|
||||
|
||||
/*
|
||||
* Stop interpretation, emitted at end of script to save the threaded bytecode
|
||||
* interpreter an extra branch test on every DO_NEXT_OP (see jsinterp.c).
|
||||
*/
|
||||
OPDEF(JSOP_STOP, 197,"stop", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_STOP, 195,"stop", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* Get an extant property value, throwing ReferenceError if the identified
|
||||
* property does not exist.
|
||||
*/
|
||||
OPDEF(JSOP_GETXPROP, 198,"getxprop", NULL, 3, 1, 1, 18, JOF_ATOM|JOF_PROP|JOF_TYPESET)
|
||||
OPDEF(JSOP_GETXPROP, 196,"getxprop", NULL, 3, 1, 1, 18, JOF_ATOM|JOF_PROP|JOF_TYPESET)
|
||||
|
||||
OPDEF(JSOP_CALLXMLNAME, 199, "callxmlname", NULL, 1, 1, 2, 19, JOF_BYTE|JOF_CALLOP)
|
||||
OPDEF(JSOP_CALLXMLNAME, 197, "callxmlname", NULL, 1, 1, 2, 19, JOF_BYTE|JOF_CALLOP)
|
||||
|
||||
/*
|
||||
* Specialized JSOP_TYPEOF to avoid reporting undefined for typeof(0, undef).
|
||||
*/
|
||||
OPDEF(JSOP_TYPEOFEXPR, 200,"typeofexpr", NULL, 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING)
|
||||
OPDEF(JSOP_TYPEOFEXPR, 198,"typeofexpr", NULL, 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING)
|
||||
|
||||
/*
|
||||
* Block-local scope support.
|
||||
*/
|
||||
OPDEF(JSOP_ENTERBLOCK, 201,"enterblock", NULL, 3, 0, -1, 0, JOF_OBJECT)
|
||||
OPDEF(JSOP_LEAVEBLOCK, 202,"leaveblock", NULL, 5, -1, 0, 0, JOF_UINT16)
|
||||
OPDEF(JSOP_ENTERBLOCK, 199,"enterblock", NULL, 3, 0, -1, 0, JOF_OBJECT)
|
||||
OPDEF(JSOP_LEAVEBLOCK, 200,"leaveblock", NULL, 5, -1, 0, 0, JOF_UINT16)
|
||||
|
||||
/* Jump to target if top of stack value isn't callable. */
|
||||
OPDEF(JSOP_IFCANTCALLTOP, 203,"ifcantcalltop",NULL, 3, 1, 1, 0, JOF_JUMP|JOF_DETECTING)
|
||||
OPDEF(JSOP_IFCANTCALLTOP, 201,"ifcantcalltop",NULL, 3, 1, 1, 0, JOF_JUMP|JOF_DETECTING)
|
||||
|
||||
/* Throws a TypeError if the value at the top of the stack is not primitive. */
|
||||
OPDEF(JSOP_PRIMTOP, 204,"primtop", NULL, 2, 1, 1, 0, JOF_INT8)
|
||||
OPDEF(JSOP_PRIMTOP, 202,"primtop", NULL, 2, 1, 1, 0, JOF_INT8)
|
||||
|
||||
/*
|
||||
* Generator and array comprehension support.
|
||||
*/
|
||||
OPDEF(JSOP_GENERATOR, 205,"generator", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_YIELD, 206,"yield", NULL, 1, 1, 1, 1, JOF_BYTE)
|
||||
OPDEF(JSOP_ARRAYPUSH, 207,"arraypush", NULL, 3, 1, 0, 3, JOF_LOCAL)
|
||||
OPDEF(JSOP_GENERATOR, 203,"generator", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_YIELD, 204,"yield", NULL, 1, 1, 1, 1, JOF_BYTE)
|
||||
OPDEF(JSOP_ARRAYPUSH, 205,"arraypush", NULL, 3, 1, 0, 3, JOF_LOCAL)
|
||||
|
||||
/*
|
||||
* Get the built-in function::foo namespace and push it.
|
||||
*/
|
||||
OPDEF(JSOP_GETFUNNS, 208,"getfunns", NULL, 1, 0, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_GETFUNNS, 206,"getfunns", NULL, 1, 0, 1, 19, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* Variant of JSOP_ENUMELEM for destructuring const (const [a, b] = ...).
|
||||
*/
|
||||
OPDEF(JSOP_ENUMCONSTELEM, 209,"enumconstelem",NULL, 1, 3, 0, 3, JOF_BYTE|JOF_SET)
|
||||
OPDEF(JSOP_ENUMCONSTELEM, 207,"enumconstelem",NULL, 1, 3, 0, 3, JOF_BYTE|JOF_SET)
|
||||
|
||||
/*
|
||||
* Variant of JSOP_LEAVEBLOCK has a result on the stack above the locals,
|
||||
* which must be moved down when the block pops.
|
||||
*/
|
||||
OPDEF(JSOP_LEAVEBLOCKEXPR,210,"leaveblockexpr",NULL, 5, -1, 1, 3, JOF_UINT16)
|
||||
OPDEF(JSOP_LEAVEBLOCKEXPR,208,"leaveblockexpr",NULL, 5, -1, 1, 3, JOF_UINT16)
|
||||
\
|
||||
/*
|
||||
* Optimize atom segments 1-3. These must be followed by JSOP_RESETBASE0 after
|
||||
* the opcode that they prefix.
|
||||
*/
|
||||
OPDEF(JSOP_INDEXBASE1, 211,"indexbase1", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
|
||||
OPDEF(JSOP_INDEXBASE2, 212,"indexbase2", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
|
||||
OPDEF(JSOP_INDEXBASE3, 213,"indexbase3", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
|
||||
OPDEF(JSOP_INDEXBASE1, 209,"indexbase1", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
|
||||
OPDEF(JSOP_INDEXBASE2, 210,"indexbase2", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
|
||||
OPDEF(JSOP_INDEXBASE3, 211,"indexbase3", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
|
||||
|
||||
OPDEF(JSOP_CALLGNAME, 214, "callgname", NULL, 3, 0, 2, 19, JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_CALLOP|JOF_GNAME)
|
||||
OPDEF(JSOP_CALLLOCAL, 215, "calllocal", NULL, 3, 0, 2, 19, JOF_LOCAL|JOF_NAME|JOF_CALLOP)
|
||||
OPDEF(JSOP_CALLARG, 216, "callarg", NULL, 3, 0, 2, 19, JOF_QARG |JOF_NAME|JOF_CALLOP)
|
||||
OPDEF(JSOP_BINDGNAME, 217, "bindgname", NULL, 3, 0, 1, 0, JOF_ATOM|JOF_NAME|JOF_SET|JOF_GNAME)
|
||||
OPDEF(JSOP_CALLGNAME, 212, "callgname", NULL, 3, 0, 2, 19, JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_CALLOP|JOF_GNAME)
|
||||
OPDEF(JSOP_CALLLOCAL, 213, "calllocal", NULL, 3, 0, 2, 19, JOF_LOCAL|JOF_NAME|JOF_CALLOP)
|
||||
OPDEF(JSOP_CALLARG, 214, "callarg", NULL, 3, 0, 2, 19, JOF_QARG |JOF_NAME|JOF_CALLOP)
|
||||
OPDEF(JSOP_BINDGNAME, 215, "bindgname", NULL, 3, 0, 1, 0, JOF_ATOM|JOF_NAME|JOF_SET|JOF_GNAME)
|
||||
|
||||
/*
|
||||
* Opcodes to hold 8-bit and 32-bit immediate integer operands.
|
||||
*/
|
||||
OPDEF(JSOP_INT8, 218, "int8", NULL, 2, 0, 1, 16, JOF_INT8)
|
||||
OPDEF(JSOP_INT32, 219, "int32", NULL, 5, 0, 1, 16, JOF_INT32)
|
||||
OPDEF(JSOP_INT8, 216, "int8", NULL, 2, 0, 1, 16, JOF_INT8)
|
||||
OPDEF(JSOP_INT32, 217, "int32", NULL, 5, 0, 1, 16, JOF_INT32)
|
||||
|
||||
/*
|
||||
* Get the value of the 'length' property from a stacked object.
|
||||
*/
|
||||
OPDEF(JSOP_LENGTH, 220, "length", NULL, 3, 1, 1, 18, JOF_ATOM|JOF_PROP|JOF_TYPESET)
|
||||
OPDEF(JSOP_LENGTH, 218, "length", NULL, 3, 1, 1, 18, JOF_ATOM|JOF_PROP|JOF_TYPESET)
|
||||
|
||||
/*
|
||||
* Push a JSVAL_HOLE value onto the stack, representing an omitted property in
|
||||
* an array literal (e.g. property 0 in the array [, 1]). This opcode is used
|
||||
* with the JSOP_NEWARRAY opcode.
|
||||
*/
|
||||
OPDEF(JSOP_HOLE, 221, "hole", NULL, 1, 0, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_HOLE, 219, "hole", NULL, 1, 0, 1, 0, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* Variants of JSOP_{DEF{,LOCAL}FUN,LAMBDA} optimized for the flat closure case.
|
||||
*/
|
||||
OPDEF(JSOP_DEFFUN_FC, 222,"deffun_fc", NULL, 3, 0, 0, 0, JOF_OBJECT|JOF_DECLARING)
|
||||
OPDEF(JSOP_DEFLOCALFUN_FC,223,"deflocalfun_fc",NULL, 5, 0, 0, 0, JOF_SLOTOBJECT|JOF_DECLARING|JOF_TMPSLOT)
|
||||
OPDEF(JSOP_LAMBDA_FC, 224,"lambda_fc", NULL, 3, 0, 1, 19, JOF_OBJECT)
|
||||
OPDEF(JSOP_DEFFUN_FC, 220,"deffun_fc", NULL, 3, 0, 0, 0, JOF_OBJECT|JOF_DECLARING)
|
||||
OPDEF(JSOP_DEFLOCALFUN_FC,221,"deflocalfun_fc",NULL, 5, 0, 0, 0, JOF_SLOTOBJECT|JOF_DECLARING|JOF_TMPSLOT)
|
||||
OPDEF(JSOP_LAMBDA_FC, 222,"lambda_fc", NULL, 3, 0, 1, 19, JOF_OBJECT)
|
||||
|
||||
/*
|
||||
* Ensure that the value on the top of the stack is an object. The one
|
||||
* argument is an error message, defined in js.msg, that takes one parameter
|
||||
* (the decompilation of the primitive value).
|
||||
*/
|
||||
OPDEF(JSOP_OBJTOP, 225,"objtop", NULL, 3, 0, 0, 0, JOF_UINT16)
|
||||
OPDEF(JSOP_OBJTOP, 223,"objtop", NULL, 3, 0, 0, 0, JOF_UINT16)
|
||||
|
||||
/*
|
||||
* Joined function object as method optimization support.
|
||||
*/
|
||||
OPDEF(JSOP_SETMETHOD, 226,"setmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_INITMETHOD, 227,"initmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_UNBRAND, 228,"unbrand", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNBRANDTHIS, 229,"unbrandthis", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_SETMETHOD, 224,"setmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_INITMETHOD, 225,"initmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_UNBRAND, 226,"unbrand", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNBRANDTHIS, 227,"unbrandthis", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
OPDEF(JSOP_SHARPINIT, 230,"sharpinit", NULL, 3, 0, 0, 0, JOF_UINT16|JOF_SHARPSLOT)
|
||||
OPDEF(JSOP_SHARPINIT, 228,"sharpinit", NULL, 3, 0, 0, 0, JOF_UINT16|JOF_SHARPSLOT)
|
||||
|
||||
/* Pop the stack, convert to a jsid (int or string), and push back. */
|
||||
OPDEF(JSOP_TOID, 231, "toid", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_TOID, 229, "toid", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
|
@ -15427,28 +15427,6 @@ TraceRecorder::record_JSOP_NOP()
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::record_JSOP_ARGSUB()
|
||||
{
|
||||
StackFrame* const fp = cx->fp();
|
||||
|
||||
/*
|
||||
* The arguments object or its absence in the frame is part of the typemap,
|
||||
* so a record-time check suffices here. We don't bother tracing ARGSUB in
|
||||
* the case of an arguments object exising, because ARGSUB and to a lesser
|
||||
* extent ARGCNT are emitted to avoid arguments object creation.
|
||||
*/
|
||||
if (!fp->hasArgsObj() && !fp->fun()->isHeavyweight()) {
|
||||
uintN slot = GET_ARGNO(cx->regs().pc);
|
||||
if (slot >= fp->numActualArgs())
|
||||
RETURN_STOP_A("can't trace out-of-range arguments");
|
||||
|
||||
stack(0, get(&cx->fp()->canonicalActualArg(slot)));
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
RETURN_STOP_A("can't trace JSOP_ARGSUB hard case");
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK LIns*
|
||||
TraceRecorder::guardArgsLengthNotAssigned(LIns* argsobj_ins)
|
||||
{
|
||||
@ -15460,33 +15438,6 @@ TraceRecorder::guardArgsLengthNotAssigned(LIns* argsobj_ins)
|
||||
return len_ins;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::record_JSOP_ARGCNT()
|
||||
{
|
||||
StackFrame * const fp = cx->fp();
|
||||
|
||||
if (fp->fun()->flags & JSFUN_HEAVYWEIGHT)
|
||||
RETURN_STOP_A("can't trace heavyweight JSOP_ARGCNT");
|
||||
|
||||
// argc is fixed on trace, so ideally we would simply generate LIR for
|
||||
// constant argc. But the user can mutate arguments.length in the
|
||||
// interpreter, so we have to check for that in the trace entry frame.
|
||||
// We also have to check that arguments.length has not been mutated
|
||||
// at record time, because if so we will generate incorrect constant
|
||||
// LIR, which will assert in tryToDemote().
|
||||
if (fp->hasArgsObj() && fp->argsObj().hasOverriddenLength())
|
||||
RETURN_STOP_A("can't trace JSOP_ARGCNT if arguments.length has been modified");
|
||||
LIns *a_ins = getFrameObjPtr(fp->addressOfArgs());
|
||||
if (callDepth == 0) {
|
||||
if (MaybeBranch mbr = w.jt(w.eqp0(a_ins))) {
|
||||
guardArgsLengthNotAssigned(a_ins);
|
||||
w.label(mbr);
|
||||
}
|
||||
}
|
||||
stack(0, w.immd(fp->numActualArgs()));
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::record_DefLocalFunSetSlot(uint32 slot, JSObject* obj)
|
||||
{
|
||||
@ -16107,7 +16058,7 @@ TraceRecorder::record_JSOP_LENGTH()
|
||||
// We must both check at record time and guard at run time that
|
||||
// arguments.length has not been reassigned, redefined or deleted.
|
||||
if (obj->asArguments()->hasOverriddenLength())
|
||||
RETURN_STOP_A("can't trace JSOP_ARGCNT if arguments.length has been modified");
|
||||
RETURN_STOP_A("can't trace arguments.length if it has been modified");
|
||||
LIns* slot_ins = guardArgsLengthNotAssigned(obj_ins);
|
||||
|
||||
// slot_ins is the value from the slot; right-shift to get the length;
|
||||
|
@ -222,7 +222,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
|
||||
* before deserialization of bytecode. If the saved version does not match
|
||||
* the current version, abort deserialization and invalidate the file.
|
||||
*/
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 95)
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 96)
|
||||
|
||||
/*
|
||||
* Library-private functions.
|
||||
|
@ -2624,23 +2624,6 @@ mjit::Compiler::generateMethod()
|
||||
}
|
||||
END_CASE(JSOP_CALLFCSLOT)
|
||||
|
||||
BEGIN_CASE(JSOP_ARGSUB)
|
||||
{
|
||||
prepareStubCall(Uses(0));
|
||||
masm.move(Imm32(GET_ARGNO(PC)), Registers::ArgReg1);
|
||||
INLINE_STUBCALL(stubs::ArgSub, REJOIN_FALLTHROUGH);
|
||||
pushSyncedEntry(0);
|
||||
}
|
||||
END_CASE(JSOP_ARGSUB)
|
||||
|
||||
BEGIN_CASE(JSOP_ARGCNT)
|
||||
{
|
||||
prepareStubCall(Uses(0));
|
||||
INLINE_STUBCALL(stubs::ArgCnt, REJOIN_FALLTHROUGH);
|
||||
pushSyncedEntry(0);
|
||||
}
|
||||
END_CASE(JSOP_ARGCNT)
|
||||
|
||||
BEGIN_CASE(JSOP_DEFLOCALFUN)
|
||||
{
|
||||
uint32 slot = GET_SLOTNO(PC);
|
||||
|
@ -1942,19 +1942,6 @@ stubs::FastInstanceOf(VMFrame &f)
|
||||
f.regs.sp[-3].setBoolean(js_IsDelegate(f.cx, &lref.toObject(), f.regs.sp[-3]));
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::ArgCnt(VMFrame &f)
|
||||
{
|
||||
JSContext *cx = f.cx;
|
||||
JSRuntime *rt = cx->runtime;
|
||||
StackFrame *fp = f.fp();
|
||||
|
||||
jsid id = ATOM_TO_JSID(rt->atomState.lengthAtom);
|
||||
f.regs.sp++;
|
||||
if (!js_GetArgsProperty(cx, fp, id, &f.regs.sp[-1]))
|
||||
THROW();
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::EnterBlock(VMFrame &f, JSObject *obj)
|
||||
{
|
||||
@ -2183,16 +2170,6 @@ stubs::Pos(VMFrame &f)
|
||||
TypeScript::MonitorOverflow(f.cx, f.script(), f.pc());
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::ArgSub(VMFrame &f, uint32 n)
|
||||
{
|
||||
jsid id = INT_TO_JSID(n);
|
||||
Value rval;
|
||||
if (!js_GetArgsProperty(f.cx, f.fp(), id, &rval))
|
||||
THROW();
|
||||
f.regs.sp[0] = rval;
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::DelName(VMFrame &f, JSAtom *atom)
|
||||
{
|
||||
|
@ -155,7 +155,6 @@ JSObject * JS_FASTCALL LambdaJoinableForCall(VMFrame &f, JSFunction *fun);
|
||||
JSObject * JS_FASTCALL LambdaJoinableForNull(VMFrame &f, JSFunction *fun);
|
||||
JSObject * JS_FASTCALL FlatLambda(VMFrame &f, JSFunction *fun);
|
||||
void JS_FASTCALL Arguments(VMFrame &f);
|
||||
void JS_FASTCALL ArgSub(VMFrame &f, uint32 n);
|
||||
void JS_FASTCALL EnterBlock(VMFrame &f, JSObject *obj);
|
||||
void JS_FASTCALL LeaveBlock(VMFrame &f, JSObject *blockChain);
|
||||
|
||||
@ -193,7 +192,6 @@ JSBool JS_FASTCALL ValueToBoolean(VMFrame &f);
|
||||
JSString * JS_FASTCALL TypeOf(VMFrame &f);
|
||||
JSBool JS_FASTCALL InstanceOf(VMFrame &f);
|
||||
void JS_FASTCALL FastInstanceOf(VMFrame &f);
|
||||
void JS_FASTCALL ArgCnt(VMFrame &f);
|
||||
void JS_FASTCALL Unbrand(VMFrame &f);
|
||||
void JS_FASTCALL UnbrandThis(VMFrame &f);
|
||||
|
||||
|
@ -1280,7 +1280,8 @@ CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
||||
curr->tjitDataAllocatorsReserve = GetCompartmentTjitDataAllocatorsReserveSize(compartment);
|
||||
curr->tjitDataNonAllocators = GetCompartmentTjitDataTraceMonitorSize(compartment);
|
||||
#endif
|
||||
JS_GetTypeInferenceMemoryStats(cx, compartment, &curr->typeInferenceMemory);
|
||||
JS_GetTypeInferenceMemoryStats(cx, compartment, &curr->typeInferenceMemory,
|
||||
moz_malloc_usable_size);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1352,7 +1353,7 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
||||
{
|
||||
js::types::TypeObject *obj = static_cast<js::types::TypeObject *>(thing);
|
||||
curr->gcHeapTypeObjects += thingSize;
|
||||
JS_GetTypeInferenceObjectStats(obj, &curr->typeInferenceMemory);
|
||||
JS_GetTypeInferenceObjectStats(obj, &curr->typeInferenceMemory, moz_malloc_usable_size);
|
||||
break;
|
||||
}
|
||||
case JSTRACE_XML:
|
||||
|
@ -57,6 +57,7 @@
|
||||
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
||||
// Paint forcing
|
||||
#include "prenv.h"
|
||||
@ -67,17 +68,14 @@ nsImageLoader::nsImageLoader(nsIFrame *aFrame, PRUint32 aActions,
|
||||
nsImageLoader *aNextLoader)
|
||||
: mFrame(aFrame),
|
||||
mActions(aActions),
|
||||
mNextLoader(aNextLoader)
|
||||
mNextLoader(aNextLoader),
|
||||
mRequestRegistered(false)
|
||||
{
|
||||
}
|
||||
|
||||
nsImageLoader::~nsImageLoader()
|
||||
{
|
||||
mFrame = nsnull;
|
||||
|
||||
if (mRequest) {
|
||||
mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
}
|
||||
Destroy();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsImageLoader>
|
||||
@ -105,12 +103,15 @@ nsImageLoader::Destroy()
|
||||
todestroy->Destroy();
|
||||
}
|
||||
|
||||
mFrame = nsnull;
|
||||
if (mRequest && mFrame) {
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
|
||||
if (mRequest) {
|
||||
nsLayoutUtils::DeregisterImageRequest(presContext, mRequest,
|
||||
&mRequestRegistered);
|
||||
mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
mFrame = nsnull;
|
||||
mRequest = nsnull;
|
||||
}
|
||||
|
||||
@ -127,17 +128,31 @@ nsImageLoader::Load(imgIRequest *aImage)
|
||||
if (!aImage)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Deregister mRequest from the refresh driver, since it is no longer
|
||||
// going to be managed by this nsImageLoader.
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
|
||||
nsLayoutUtils::DeregisterImageRequest(presContext, mRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
// Make sure to clone into a temporary, then set mRequest, since
|
||||
// cloning may notify and we don't want to trigger paints from this
|
||||
// code.
|
||||
nsCOMPtr<imgIRequest> newRequest;
|
||||
nsresult rv = aImage->Clone(this, getter_AddRefs(newRequest));
|
||||
mRequest.swap(newRequest);
|
||||
|
||||
// Re-register mRequest with the refresh driver, but immediately deregister
|
||||
// if it isn't animated.
|
||||
nsLayoutUtils::RegisterImageRequest(presContext, mRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(presContext, mRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP nsImageLoader::OnStartContainer(imgIRequest *aRequest,
|
||||
imgIContainer *aImage)
|
||||
{
|
||||
@ -269,3 +284,35 @@ nsImageLoader::DoRedraw(const nsRect* aDamageRect)
|
||||
mFrame->Invalidate(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoader::OnStartDecode(imgIRequest *aRequest)
|
||||
{
|
||||
// Register our image request with the refresh driver.
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
if (!presContext) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mRequest == aRequest) {
|
||||
nsLayoutUtils::RegisterImageRequest(presContext, mRequest,
|
||||
&mRequestRegistered);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoader::OnStopDecode(imgIRequest *aRequest, nsresult status,
|
||||
const PRUnichar *statusArg)
|
||||
{
|
||||
if (mRequest == aRequest) {
|
||||
// Deregister the imgIRequest with the refresh driver if the
|
||||
// image is not animated.
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(mFrame->PresContext(),
|
||||
mRequest,
|
||||
&mRequestRegistered);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|