diff --git a/b2g/chrome/content/settings.js b/b2g/chrome/content/settings.js index a3684f95f65..6e5f25e5655 100644 --- a/b2g/chrome/content/settings.js +++ b/b2g/chrome/content/settings.js @@ -14,6 +14,13 @@ const Cr = Components.results; Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import('resource://gre/modules/Services.jsm'); +#ifdef MOZ_WIDGET_GONK +XPCOMUtils.defineLazyGetter(this, "libcutils", function () { + Cu.import("resource://gre/modules/systemlibs.js"); + return libcutils; +}); +#endif + // Once Bug 731746 - Allow chrome JS object to implement nsIDOMEventTarget // is resolved this helper could be removed. var SettingsListener = { @@ -174,27 +181,10 @@ Components.utils.import('resource://gre/modules/ctypes.jsm'); // Get the hardware info and firmware revision from device properties. let hardware_info = null; let firmware_revision = null; - try { - let cutils = ctypes.open('libcutils.so'); - let cbuf = ctypes.char.array(128)(); - let c_property_get = cutils.declare('property_get', ctypes.default_abi, - ctypes.int, // return value: length - ctypes.char.ptr, // key - ctypes.char.ptr, // value - ctypes.char.ptr); // default - let property_get = function (key, defaultValue) { - if (defaultValue === undefined) { - defaultValue = null; - } - c_property_get(key, cbuf, defaultValue); - return cbuf.readString(); - } - hardware_info = property_get('ro.hardware'); - firmware_revision = property_get('ro.firmware_revision'); - cutils.close(); - } catch(e) { - // Error. - } +#ifdef MOZ_WIDGET_GONK + hardware_info = libcutils.property_get('ro.hardware'); + firmware_revision = libcutils.property_get('ro.firmware_revision'); +#endif lock.set('deviceinfo.hardware', hardware_info, null, null); lock.set('deviceinfo.firmware_revision', firmware_revision, null, null); })(); @@ -205,6 +195,19 @@ SettingsListener.observe('devtools.debugger.remote-enabled', false, function(val // This preference is consulted during startup Services.prefs.savePrefFile(null); value ? RemoteDebugger.start() : RemoteDebugger.stop(); + +#ifdef MOZ_WIDGET_GONK + // Configure adb. + try { + let current = libcutils.property_get("persist.sys.usb.config"); + let prefix = current.replace(/,adb/, ""); + libcutils.property_set("persist.sys.usb.config", + prefix + (value ? ",adb" : "")); + current = libcutils.property_get("persist.sys.usb.config"); + } catch(e) { + dump("Error configuring adb: " + e); + } +#endif }); SettingsListener.observe('debug.log-animations.enabled', false, function(value) { diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css index f14829d8f06..3e6278c191b 100644 --- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -52,6 +52,14 @@ tabbrowser { opacity 50ms ease-out 180ms /* hide the tab for the last 20ms of the max-width transition */; } +.tabbrowser-tabs[dontresize] > .tabbrowser-tab[fadein]:not([pinned]) { + /* controlled in tabbrowser.xml */ +} + +.tabbrowser-tabs[dontanimate] > .tabbrowser-tab { + transition: none !important; +} + .tab-throbber:not([fadein]):not([pinned]), .tab-label:not([fadein]):not([pinned]), .tab-icon-image:not([fadein]):not([pinned]), diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 9f6fe17ca48..1dea8f5699c 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1265,7 +1265,7 @@ var gBrowserInit = { gBrowser.addEventListener("pageshow", function(event) { // Filter out events that are not about the document load we are interested in - if (content && event.target == content.document) + if (event.target == content.document) setTimeout(pageShowEventHandlers, 0, event); }, true); diff --git a/browser/base/content/tabbrowser.css b/browser/base/content/tabbrowser.css index 2dd6a05297c..9f1b8a91f44 100644 --- a/browser/base/content/tabbrowser.css +++ b/browser/base/content/tabbrowser.css @@ -47,11 +47,12 @@ tabpanels { } .closing-tabs-spacer { + min-width: 0; pointer-events: none; } .tabbrowser-tabs:not(:hover) > .tabbrowser-arrowscrollbox > .closing-tabs-spacer { - transition: width .15s ease-out; + transition: min-width 150ms ease-out; } /** diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 59bbaedee45..62e887dae38 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1584,7 +1584,6 @@ aTab._animStartTime = Date.now(); this._blurTab(aTab); - aTab.style.maxWidth = ""; // ensure that fade-out transition happens aTab.removeAttribute("fadein"); setTimeout(function (tab, tabbrowser) { @@ -1781,10 +1780,6 @@ // update tab close buttons state this.tabContainer.adjustTabstrip(); - - setTimeout(function(tabs) { - tabs._lastTabClosedByMouse = false; - }, 0, this.tabContainer); } // update first-tab/last-tab/beforeselected/afterselected attributes @@ -2829,10 +2824,13 @@ return; // Ignore vertical events var tabs = document.getBindingParent(this); - tabs.removeAttribute("overflow"); - if (tabs._lastTabClosedByMouse) - tabs._expandSpacerBy(this._scrollButtonDown.clientWidth); + if (tabs.hasAttribute("dontresize") || tabs.hasAttribute("using-closing-tabs-spacer")) { + tabs.mTabstrip._scrollButtonUp.style.visibility = "hidden"; + tabs.mTabstrip._scrollButtonDown.style.visibility = "hidden"; + } else { + tabs.removeAttribute("overflow"); + } tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser.removeTab, tabs.tabbrowser); @@ -2877,8 +2875,7 @@ command="cmd_newNavigatorTab" onclick="checkForMiddleClick(this, event);" tooltiptext="&newTabButton.tooltip;"/> - + @@ -3075,9 +3072,16 @@ document.getAnonymousElementByAttribute(this, "anonid", "closing-tabs-spacer"); - NaN - false - false + .tabbrowser-tab[fadein]:not([pinned])"; + + // XXX: document.styleSheets is not iterable (see bug 738196) + for (let sheet of Array.slice(document.styleSheets)) + if (sheet.href == href) + for (let rule of Array.slice(sheet.cssRules)) + if (rule.selectorText == selector) { rule; break; } + ]]> @@ -3090,62 +3094,48 @@ var isEndTab = (aTab._tPos > tabs[tabs.length-1]._tPos); var tabWidth = aTab.getBoundingClientRect().width; - if (!this._tabDefaultMaxWidth) - this._tabDefaultMaxWidth = - parseFloat(window.getComputedStyle(aTab).maxWidth); - this._lastTabClosedByMouse = true; + // Locking is neither in effect nor needed, so let tabs expand normally. + if (isEndTab && !this.hasAttribute("dontresize")) + return; - if (this.getAttribute("overflow") == "true") { - // Don't need to do anything if we're in overflow mode and aren't scrolled - // all the way to the right, or if we're closing the last tab. - if (isEndTab || !this.mTabstrip._scrollButtonDown.disabled) - return; + // Let spacer grow to the maximum and lock it, then let tabs expand normally + if (isEndTab) { + let spacer = this._closingTabsSpacer; + spacer.style.MozBoxFlex = 1; + spacer.style.minWidth = getComputedStyle(spacer).width; + spacer.style.MozBoxFlex = ""; - // If the tab has an owner that will become the active tab, the owner will - // be to the left of it, so we actually want the left tab to slide over. - // This can't be done as easily in non-overflow mode, so we don't bother. - if (aTab.owner) - return; - - this._expandSpacerBy(tabWidth); - } else { // non-overflow mode - // Locking is neither in effect nor needed, so let tabs expand normally. - if (isEndTab && !this._hasTabTempMaxWidth) - return; - - let numPinned = this.tabbrowser._numPinnedTabs; - // Force tabs to stay the same width, unless we're closing the last tab, - // which case we need to let them expand just enough so that the overall - // tabbar width is the same. - if (isEndTab) { - let numNormalTabs = tabs.length - numPinned; - tabWidth = tabWidth * (numNormalTabs + 1) / numNormalTabs; - if (tabWidth > this._tabDefaultMaxWidth) - tabWidth = this._tabDefaultMaxWidth; - } - tabWidth += "px"; - for (let i = numPinned; i < tabs.length; i++) { - let tab = tabs[i]; - tab.style.setProperty("max-width", tabWidth, "important"); - if (!isEndTab) { // keep tabs the same width - tab.style.transition = "none"; - tab.clientTop; // flush styles to skip animation; see bug 649247 - tab.style.transition = ""; - } - } - this._hasTabTempMaxWidth = true; - this.tabbrowser.addEventListener("mousemove", this, false); - window.addEventListener("mouseout", this, false); + this.setAttribute("dontanimate", "true"); + this.removeAttribute("dontresize"); + this.clientTop; + this.removeAttribute("dontanimate"); + return; + } + + if (!this.hasAttribute("dontresize")) { + this._delayResizingRule.style.setProperty("max-width", tabWidth + "px", "important"); + this.setAttribute("dontanimate", "true"); + this.setAttribute("dontresize", "true"); + this.clientTop; // flush styles to skip animation; see bug 649247 + this.removeAttribute("dontanimate"); + } + + if (!this.mTabstrip._scrollButtonUp.disabled) { + let spacer = this._closingTabsSpacer; + let width = parseFloat(spacer.style.minWidth) || 0; + width += tabWidth; + + if (!this.mTabstrip._scrollButtonDown.disabled) { + let scrollbox = this.mTabstrip._scrollbox; + width -= scrollbox.scrollLeftMax - scrollbox.scrollLeft; + } + + if (width >= 0) { + spacer.style.minWidth = width + "px"; + this.setAttribute("using-closing-tabs-spacer", "true"); + } } - ]]> - - - - @@ -3156,16 +3146,14 @@ this.tabbrowser.removeEventListener("mousemove", this, false); window.removeEventListener("mouseout", this, false); - if (this._hasTabTempMaxWidth) { - this._hasTabTempMaxWidth = false; - let tabs = this.tabbrowser.visibleTabs; - for (let i = 0; i < tabs.length; i++) - tabs[i].style.maxWidth = ""; - } + this._closingTabsSpacer.style.minWidth = ""; + this.removeAttribute("using-closing-tabs-spacer"); + this.removeAttribute("dontresize"); - if (this.hasAttribute("using-closing-tabs-spacer")) { - this.removeAttribute("using-closing-tabs-spacer"); - this._closingTabsSpacer.style.width = 0; + if (this.hasAttribute("overflow") && this.mTabstrip._scrollbox.scrollWidth <= this.mTabstrip._scrollbox.clientWidth) { + this.mTabstrip._scrollButtonUp.style.visibility = ""; + this.mTabstrip._scrollButtonDown.style.visibility = ""; + this.removeAttribute("overflow"); } ]]> diff --git a/browser/components/places/content/controller.js b/browser/components/places/content/controller.js index 34f0bfa9b41..18a08360173 100644 --- a/browser/components/places/content/controller.js +++ b/browser/components/places/content/controller.js @@ -460,7 +460,6 @@ PlacesController.prototype = { break; case Ci.nsINavHistoryResultNode.RESULT_TYPE_URI: case Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT: - case Ci.nsINavHistoryResultNode.RESULT_TYPE_FULL_VISIT: nodeData["link"] = true; uri = NetUtil.newURI(node.uri); if (PlacesUtils.nodeIsBookmark(node)) { diff --git a/browser/locales/en-US/chrome/browser/browser.properties b/browser/locales/en-US/chrome/browser/browser.properties index 0d377686d6f..7d2a78bf021 100644 --- a/browser/locales/en-US/chrome/browser/browser.properties +++ b/browser/locales/en-US/chrome/browser/browser.properties @@ -426,6 +426,8 @@ identity.loggedIn.signOut.accessKey = O getUserMedia.shareCamera.message = Would you like to share your camera with %S? getUserMedia.shareMicrophone.message = Would you like to share your microphone with %S? getUserMedia.shareCameraAndMicrophone.message = Would you like to share your camera and microphone with %S? +getUserMedia.noVideo.label = No Video +getUserMedia.noAudio.label = No Audio getUserMedia.shareSelectedDevices.label = Share Selected Device;Share Selected Devices getUserMedia.shareSelectedDevices.accesskey = S getUserMedia.denyRequest.label = Don't Share diff --git a/browser/modules/webrtcUI.jsm b/browser/modules/webrtcUI.jsm index c84347bf51e..53733d1f3a3 100644 --- a/browser/modules/webrtcUI.jsm +++ b/browser/modules/webrtcUI.jsm @@ -118,19 +118,30 @@ function prompt(aBrowser, aCallID, aAudioRequested, aVideoRequested, aDevices) { let deviceIndex = 0; for (let device of devices) { - let menuitem = chromeDoc.createElement("menuitem"); - menuitem.setAttribute("value", deviceIndex); - menuitem.setAttribute("label", device.name); - menuitem.setAttribute("tooltiptext", device.name); - menupopup.appendChild(menuitem); + addDeviceToList(menupopup, device.name, deviceIndex); deviceIndex++; } } + function addDeviceToList(menupopup, deviceName, deviceIndex) { + let menuitem = chromeDoc.createElement("menuitem"); + menuitem.setAttribute("value", deviceIndex); + menuitem.setAttribute("label", deviceName); + menuitem.setAttribute("tooltiptext", deviceName); + menupopup.appendChild(menuitem); + } + chromeDoc.getElementById("webRTC-selectCamera").hidden = !videoDevices.length; chromeDoc.getElementById("webRTC-selectMicrophone").hidden = !audioDevices.length; - listDevices(chromeDoc.getElementById("webRTC-selectCamera-menupopup"), videoDevices); - listDevices(chromeDoc.getElementById("webRTC-selectMicrophone-menupopup"), audioDevices); + + let camMenupopup = chromeDoc.getElementById("webRTC-selectCamera-menupopup"); + let micMenupopup = chromeDoc.getElementById("webRTC-selectMicrophone-menupopup"); + listDevices(camMenupopup, videoDevices); + listDevices(micMenupopup, audioDevices); + if (requestType == "CameraAndMicrophone") { + addDeviceToList(camMenupopup, stringBundle.getString("getUserMedia.noVideo.label"), "-1"); + addDeviceToList(micMenupopup, stringBundle.getString("getUserMedia.noAudio.label"), "-1"); + } let mainAction = { label: PluralForm.get(requestType == "CameraAndMicrophone" ? 2 : 1, @@ -141,12 +152,20 @@ function prompt(aBrowser, aCallID, aAudioRequested, aVideoRequested, aDevices) { .createInstance(Ci.nsISupportsArray); if (videoDevices.length) { let videoDeviceIndex = chromeDoc.getElementById("webRTC-selectCamera-menulist").value; - allowedDevices.AppendElement(videoDevices[videoDeviceIndex]); + if (videoDeviceIndex != "-1") + allowedDevices.AppendElement(videoDevices[videoDeviceIndex]); } if (audioDevices.length) { let audioDeviceIndex = chromeDoc.getElementById("webRTC-selectMicrophone-menulist").value; - allowedDevices.AppendElement(audioDevices[audioDeviceIndex]); + if (audioDeviceIndex != "-1") + allowedDevices.AppendElement(audioDevices[audioDeviceIndex]); } + + if (allowedDevices.Count() == 0) { + Services.obs.notifyObservers(null, "getUserMedia:response:deny", aCallID); + return; + } + Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", aCallID); // Show browser-specific indicator for the active camera/mic access. diff --git a/configure.in b/configure.in index 4cdc011c866..d01f8102980 100644 --- a/configure.in +++ b/configure.in @@ -1436,6 +1436,7 @@ if test "$GNU_CC"; then _DEFINES_CFLAGS='-include $(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT' _USE_CPP_INCLUDE_FLAG=1 + ASFLAGS="$ASFLAGS $_DEFINES_CFLAGS" elif test "$SOLARIS_SUNPRO_CC"; then DSO_CFLAGS='' @@ -6180,7 +6181,7 @@ if test "$OS_ARCH" = "WINNT"; then if test -n "$MAKENSISU" -a "$MAKENSISU" != ":"; then AC_MSG_RESULT([yes]) changequote(,) - MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'` + MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\).*\-Unicode$/\1/g'` changequote([,]) if test ! "$MAKENSISU_VER" = ""; then MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'` diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 5b8f6ba3745..8cee0f3d5b9 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -34,6 +34,7 @@ class nsDOMNavigationTiming; class nsEventStates; class nsFrameLoader; class nsHTMLCSSStyleSheet; +class nsHTMLDocument; class nsHTMLStyleSheet; class nsIAtom; class nsIBFCacheEntry; @@ -1974,6 +1975,8 @@ public: already_AddRefed CreateTouchList(const mozilla::dom::Sequence >& aTouches); + nsHTMLDocument* AsHTMLDocument(); + private: uint64_t mWarnedAbout; diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index f533c87f7ac..a65505092f9 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -388,7 +388,6 @@ protected: virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap) { - MOZ_ASSERT(!IsDOMBinding(), "Someone forgot to override WrapNode"); *aTriedToWrap = false; return nullptr; } @@ -1551,9 +1550,9 @@ public: already_AddRefed CloneNode(bool aDeep, mozilla::ErrorResult& aError); bool IsEqualNode(nsINode* aNode); bool IsSupported(const nsAString& aFeature, const nsAString& aVersion); - void GetNamespaceURI(nsAString& aNamespaceURI, mozilla::ErrorResult& aError) const + void GetNamespaceURI(nsAString& aNamespaceURI) const { - aError = mNodeInfo->GetNamespaceURI(aNamespaceURI); + mNodeInfo->GetNamespaceURI(aNamespaceURI); } #ifdef MOZILLA_INTERNAL_API void GetPrefix(nsAString& aPrefix) @@ -2001,9 +2000,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsINode, NS_INODE_IID) } \ NS_IMETHOD GetNamespaceURI(nsAString& aNamespaceURI) __VA_ARGS__ \ { \ - mozilla::ErrorResult rv; \ - nsINode::GetNamespaceURI(aNamespaceURI, rv); \ - return rv.ErrorCode(); \ + nsINode::GetNamespaceURI(aNamespaceURI); \ + return NS_OK; \ } \ NS_IMETHOD GetPrefix(nsAString& aPrefix) __VA_ARGS__ \ { \ diff --git a/content/base/public/nsINodeInfo.h b/content/base/public/nsINodeInfo.h index dc7fbc05361..d7dc1d6db6d 100644 --- a/content/base/public/nsINodeInfo.h +++ b/content/base/public/nsINodeInfo.h @@ -132,7 +132,7 @@ public: /* * Get the namespace URI for a node, if the node has a namespace URI. */ - virtual nsresult GetNamespaceURI(nsAString& aNameSpaceURI) const = 0; + virtual void GetNamespaceURI(nsAString& aNameSpaceURI) const = 0; /* * Get the namespace ID for a node if the node has a namespace, if not this diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 0a1ef143f1c..e8469423188 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1850,6 +1850,12 @@ nsDocument::Init() return NS_OK; } +nsHTMLDocument* +nsIDocument::AsHTMLDocument() +{ + return IsHTML() ? static_cast(this) : nullptr; +} + void nsIDocument::DeleteAllProperties() { diff --git a/content/base/src/nsNodeInfo.cpp b/content/base/src/nsNodeInfo.cpp index 78f6c8dd380..4ff1ed65cc5 100644 --- a/content/base/src/nsNodeInfo.cpp +++ b/content/base/src/nsNodeInfo.cpp @@ -208,19 +208,20 @@ NS_INTERFACE_MAP_END // nsINodeInfo -nsresult +void nsNodeInfo::GetNamespaceURI(nsAString& aNameSpaceURI) const { - nsresult rv = NS_OK; - if (mInner.mNamespaceID > 0) { - rv = nsContentUtils::NameSpaceManager()->GetNameSpaceURI(mInner.mNamespaceID, - aNameSpaceURI); + nsresult rv = + nsContentUtils::NameSpaceManager()->GetNameSpaceURI(mInner.mNamespaceID, + aNameSpaceURI); + // How can we possibly end up with a bogus namespace ID here? + if (NS_FAILED(rv)) { + MOZ_CRASH(); + } } else { SetDOMStringToNull(aNameSpaceURI); } - - return rv; } diff --git a/content/base/src/nsNodeInfo.h b/content/base/src/nsNodeInfo.h index 0384e6896b1..4a9905d587a 100644 --- a/content/base/src/nsNodeInfo.h +++ b/content/base/src/nsNodeInfo.h @@ -29,7 +29,7 @@ public: NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(nsNodeInfo) // nsINodeInfo - virtual nsresult GetNamespaceURI(nsAString& aNameSpaceURI) const; + virtual void GetNamespaceURI(nsAString& aNameSpaceURI) const; virtual bool NamespaceEquals(const nsAString& aNamespaceURI) const; // nsNodeInfo diff --git a/content/canvas/src/CanvasRenderingContext2D.cpp b/content/canvas/src/CanvasRenderingContext2D.cpp index bfcd4c4e922..abe77e2f634 100644 --- a/content/canvas/src/CanvasRenderingContext2D.cpp +++ b/content/canvas/src/CanvasRenderingContext2D.cpp @@ -6,7 +6,7 @@ #include "base/basictypes.h" #include "CanvasRenderingContext2D.h" -#include "nsXULElement.h" +#include "nsIDOMXULElement.h" #include "prenv.h" @@ -3234,7 +3234,7 @@ CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* window, double x, } void -CanvasRenderingContext2D::AsyncDrawXULElement(nsXULElement& elem, +CanvasRenderingContext2D::AsyncDrawXULElement(nsIDOMXULElement* elem, double x, double y, double w, double h, const nsAString& bgColor, @@ -3255,7 +3255,7 @@ CanvasRenderingContext2D::AsyncDrawXULElement(nsXULElement& elem, } #if 0 - nsCOMPtr loaderOwner = do_QueryInterface(&elem); + nsCOMPtr loaderOwner = do_QueryInterface(elem); if (!loaderOwner) { error.Throw(NS_ERROR_FAILURE); return; diff --git a/content/canvas/src/CanvasRenderingContext2D.h b/content/canvas/src/CanvasRenderingContext2D.h index 90a3e903f80..67f8630abee 100644 --- a/content/canvas/src/CanvasRenderingContext2D.h +++ b/content/canvas/src/CanvasRenderingContext2D.h @@ -24,7 +24,7 @@ #define NS_CANVASPATTERNAZURE_PRIVATE_IID \ {0xc9bacc25, 0x28da, 0x421e, {0x9a, 0x4b, 0xbb, 0xd6, 0x93, 0x05, 0x12, 0xbc}} -class nsXULElement; +class nsIDOMXULElement; namespace mozilla { namespace gfx { @@ -438,7 +438,7 @@ public: void DrawWindow(nsIDOMWindow* window, double x, double y, double w, double h, const nsAString& bgColor, uint32_t flags, mozilla::ErrorResult& error); - void AsyncDrawXULElement(nsXULElement& elem, double x, double y, double w, + void AsyncDrawXULElement(nsIDOMXULElement* elem, double x, double y, double w, double h, const nsAString& bgColor, uint32_t flags, mozilla::ErrorResult& error); diff --git a/content/canvas/src/Makefile.in b/content/canvas/src/Makefile.in index b46aefec544..b8029ec8e9e 100644 --- a/content/canvas/src/Makefile.in +++ b/content/canvas/src/Makefile.in @@ -68,7 +68,6 @@ CPPSRCS += \ LOCAL_INCLUDES += \ -I$(topsrcdir)/js/xpconnect/wrappers \ - -I$(topsrcdir)/content/xul/content/src \ $(NULL) else diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index b001fa08420..92da4527aa9 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -120,7 +120,6 @@ public: virtual void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, - bool aHasVideo, const MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE; // Called by the video decoder object, on the main thread, @@ -476,12 +475,6 @@ protected: */ void QueueSelectResourceTask(); - /** - * When loading a new source on an existing media element, make sure to reset - * everything that is accessible using the media element API. - */ - void ResetState(); - /** * The resource-fetch algorithm step of the load algorithm. */ diff --git a/content/html/content/src/nsHTMLAudioElement.cpp b/content/html/content/src/nsHTMLAudioElement.cpp index a4ec0cbc171..4b4aff120e0 100644 --- a/content/html/content/src/nsHTMLAudioElement.cpp +++ b/content/html/content/src/nsHTMLAudioElement.cpp @@ -123,7 +123,7 @@ nsHTMLAudioElement::MozSetup(uint32_t aChannels, uint32_t aRate) return rv; } - MetadataLoaded(aChannels, aRate, true, false, nullptr); + MetadataLoaded(aChannels, aRate, true, nullptr); mAudioStream->SetVolume(mVolume); return NS_OK; diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 0acf162cb08..224abd7c498 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -733,20 +733,10 @@ NS_IMETHODIMP nsHTMLMediaElement::Load() AbortExistingLoads(); SetPlaybackRate(mDefaultPlaybackRate); QueueSelectResourceTask(); - ResetState(); mIsRunningLoadMethod = false; return NS_OK; } -void nsHTMLMediaElement::ResetState() -{ - mMediaSize = nsIntSize(-1, -1); - VideoFrameContainer* container = GetVideoFrameContainer(); - if (container) { - container->Reset(); - } -} - static bool HasSourceChildren(nsIContent *aElement) { for (nsIContent* child = aElement->GetFirstChild(); @@ -2607,7 +2597,6 @@ void nsHTMLMediaElement::ProcessMediaFragmentURI() void nsHTMLMediaElement::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, - bool aHasVideo, const MetadataTags* aTags) { mChannels = aChannels; @@ -2621,13 +2610,6 @@ void nsHTMLMediaElement::MetadataLoaded(int aChannels, ProcessMediaFragmentURI(); mDecoder->SetFragmentEndTime(mFragmentEnd); } - - // If this element had a video track, but consists only of an audio track now, - // delete the VideoFrameContainer. This happens when the src is changed to an - // audio only file. - if (!aHasVideo) { - mVideoFrameContainer = nullptr; - } } void nsHTMLMediaElement::FirstFrameLoaded(bool aResourceFullyLoaded) @@ -2971,14 +2953,6 @@ void nsHTMLMediaElement::NotifyAutoplayDataReady() VideoFrameContainer* nsHTMLMediaElement::GetVideoFrameContainer() { - // If we have loaded the metadata, and the size of the video is still - // (-1, -1), the media has no video. Don't go a create a video frame - // container. - if (mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA && - mMediaSize == nsIntSize(-1, -1)) { - return nullptr; - } - if (mVideoFrameContainer) return mVideoFrameContainer; diff --git a/content/media/AbstractMediaDecoder.h b/content/media/AbstractMediaDecoder.h index f08d1a8856d..a06c0bdcd02 100644 --- a/content/media/AbstractMediaDecoder.h +++ b/content/media/AbstractMediaDecoder.h @@ -81,8 +81,8 @@ public: // Return true if the transport layer supports seeking. virtual bool IsMediaSeekable() = 0; - virtual void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) = 0; - virtual void QueueMetadata(int64_t aTime, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) = 0; + virtual void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags) = 0; + virtual void QueueMetadata(int64_t aTime, int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags) = 0; // Set the media end time in microseconds virtual void SetMediaEndTime(int64_t aTime) = 0; @@ -119,25 +119,23 @@ class AudioMetadataEventRunner : public nsRunnable private: nsRefPtr mDecoder; public: - AudioMetadataEventRunner(AbstractMediaDecoder* aDecoder, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) + AudioMetadataEventRunner(AbstractMediaDecoder* aDecoder, int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags) : mDecoder(aDecoder), mChannels(aChannels), mRate(aRate), mHasAudio(aHasAudio), - mHasVideo(aHasVideo), mTags(aTags) {} NS_IMETHOD Run() { - mDecoder->MetadataLoaded(mChannels, mRate, mHasAudio, mHasVideo, mTags); + mDecoder->MetadataLoaded(mChannels, mRate, mHasAudio, mTags); return NS_OK; } int mChannels; int mRate; bool mHasAudio; - bool mHasVideo; MetadataTags* mTags; }; diff --git a/content/media/MediaDecoder.cpp b/content/media/MediaDecoder.cpp index 2b8ed741a2d..8c0b6aa623b 100644 --- a/content/media/MediaDecoder.cpp +++ b/content/media/MediaDecoder.cpp @@ -188,14 +188,18 @@ void MediaDecoder::DestroyDecodedStream() // All streams are having their SourceMediaStream disconnected, so they // need to be explicitly blocked again. - for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) { + for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) { OutputStreamData& os = mOutputStreams[i]; // During cycle collection, nsDOMMediaStream can be destroyed and send // its Destroy message before this decoder is destroyed. So we have to // be careful not to send any messages after the Destroy(). - if (!os.mStream->IsDestroyed()) { - os.mStream->ChangeExplicitBlockerCount(1); + if (os.mStream->IsDestroyed()) { + // Probably the DOM MediaStream was GCed. Clean up. + os.mPort->Destroy(); + mOutputStreams.RemoveElementAt(i); + continue; } + os.mStream->ChangeExplicitBlockerCount(1); // Explicitly remove all existing ports. This is not strictly necessary but it's // good form. os.mPort->Destroy(); @@ -220,8 +224,15 @@ void MediaDecoder::RecreateDecodedStream(int64_t aStartTimeUSecs) // Note that the delay between removing ports in DestroyDecodedStream // and adding new ones won't cause a glitch since all graph operations // between main-thread stable states take effect atomically. - for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) { - ConnectDecodedStreamToOutputStream(&mOutputStreams[i]); + for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) { + OutputStreamData& os = mOutputStreams[i]; + if (os.mStream->IsDestroyed()) { + // Probably the DOM MediaStream was GCed. Clean up. + // No need to destroy the port; all ports have been destroyed here. + mOutputStreams.RemoveElementAt(i); + continue; + } + ConnectDecodedStreamToOutputStream(&os); } mDecodedStream->mHaveBlockedForPlayState = mPlayState != PLAY_STATE_PLAYING; @@ -244,7 +255,7 @@ void MediaDecoder::NotifyDecodedStreamMainThreadStateChanged() } void MediaDecoder::AddOutputStream(ProcessedMediaStream* aStream, - bool aFinishWhenEnded) + bool aFinishWhenEnded) { MOZ_ASSERT(NS_IsMainThread()); LOG(PR_LOG_DEBUG, ("MediaDecoder::AddOutputStream this=%p aStream=%p!", @@ -641,13 +652,12 @@ void MediaDecoder::QueueMetadata(int64_t aPublishTime, int aChannels, int aRate, bool aHasAudio, - bool aHasVideo, MetadataTags* aTags) { NS_ASSERTION(mDecoderStateMachine->OnDecodeThread(), "Should be on decode thread."); GetReentrantMonitor().AssertCurrentThreadIn(); - mDecoderStateMachine->QueueMetadata(aPublishTime, aChannels, aRate, aHasAudio, aHasVideo, aTags); + mDecoderStateMachine->QueueMetadata(aPublishTime, aChannels, aRate, aHasAudio, aTags); } bool @@ -660,7 +670,7 @@ MediaDecoder::IsDataCachedToEndOfResource() mResource->IsDataCachedToEndOfResource(mDecoderPosition)); } -void MediaDecoder::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) +void MediaDecoder::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags) { MOZ_ASSERT(NS_IsMainThread()); if (mShuttingDown) { @@ -682,7 +692,7 @@ void MediaDecoder::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool // Make sure the element and the frame (if any) are told about // our new size. Invalidate(); - mOwner->MetadataLoaded(aChannels, aRate, aHasAudio, aHasVideo, aTags); + mOwner->MetadataLoaded(aChannels, aRate, aHasAudio, aTags); } if (!mCalledResourceLoaded) { @@ -811,12 +821,17 @@ void MediaDecoder::PlaybackEnded() for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) { OutputStreamData& os = mOutputStreams[i]; + if (os.mStream->IsDestroyed()) { + // Probably the DOM MediaStream was GCed. Clean up. + os.mPort->Destroy(); + mOutputStreams.RemoveElementAt(i); + continue; + } if (os.mFinishWhenEnded) { // Shouldn't really be needed since mDecodedStream should already have // finished, but doesn't hurt. os.mStream->Finish(); os.mPort->Destroy(); - os.mPort = nullptr; // Not really needed but it keeps the invariant that a stream not // connected to mDecodedStream is explicity blocked. os.mStream->ChangeExplicitBlockerCount(1); diff --git a/content/media/MediaDecoder.h b/content/media/MediaDecoder.h index d727be273d3..f3ddc2e799b 100644 --- a/content/media/MediaDecoder.h +++ b/content/media/MediaDecoder.h @@ -658,7 +658,6 @@ public: int aChannels, int aRate, bool aHasAudio, - bool aHasVideo, MetadataTags* aTags); /****** @@ -677,7 +676,7 @@ public: // Called when the metadata from the media file has been loaded by the // state machine. Call on the main thread only. - void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags); + void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags); // Called when the first frame has been loaded. // Call on the main thread only. diff --git a/content/media/MediaDecoderOwner.h b/content/media/MediaDecoderOwner.h index 03f148ac681..ed68963cea5 100644 --- a/content/media/MediaDecoderOwner.h +++ b/content/media/MediaDecoderOwner.h @@ -56,7 +56,6 @@ public: virtual void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, - bool aHasVideo, const MetadataTags* aTags) = 0; // Called by the video decoder object, on the main thread, diff --git a/content/media/MediaDecoderStateMachine.cpp b/content/media/MediaDecoderStateMachine.cpp index 9ca480adc6d..457afc2f156 100644 --- a/content/media/MediaDecoderStateMachine.cpp +++ b/content/media/MediaDecoderStateMachine.cpp @@ -506,7 +506,8 @@ void MediaDecoderStateMachine::SendStreamAudio(AudioData* aAudio, DecodedStreamData* aStream, AudioSegment* aOutput) { - NS_ASSERTION(OnDecodeThread(), "Should be on decode thread."); + NS_ASSERTION(OnDecodeThread() || + OnStateMachineThread(), "Should be on decode thread or state machine thread"); mDecoder->GetReentrantMonitor().AssertCurrentThreadIn(); if (aAudio->mTime <= aStream->mLastAudioPacketTime) { @@ -1210,7 +1211,7 @@ uint32_t MediaDecoderStateMachine::PlaySilence(uint32_t aFrames, } uint32_t MediaDecoderStateMachine::PlayFromAudioQueue(uint64_t aFrameOffset, - uint32_t aChannels) + uint32_t aChannels) { NS_ASSERTION(OnAudioThread(), "Only call on audio thread."); NS_ASSERTION(!mAudioStream->IsPaused(), "Don't play when paused"); @@ -1218,7 +1219,6 @@ uint32_t MediaDecoderStateMachine::PlayFromAudioQueue(uint64_t aFrameOffset, { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); NS_WARN_IF_FALSE(IsPlaying(), "Should be playing"); - NS_ASSERTION(!mAudioCaptured, "Audio cannot be captured here!"); // Awaken the decode loop if it's waiting for space to free up in the // audio queue. mDecoder->GetReentrantMonitor().NotifyAll(); @@ -1861,7 +1861,6 @@ nsresult MediaDecoderStateMachine::DecodeMetadata() mInfo.mAudioChannels, mInfo.mAudioRate, HasAudio(), - HasVideo(), tags); NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL); @@ -2787,12 +2786,7 @@ bool MediaDecoderStateMachine::IsShutdown() return GetState() == DECODER_STATE_SHUTDOWN; } -void MediaDecoderStateMachine::QueueMetadata(int64_t aPublishTime, - int aChannels, - int aRate, - bool aHasAudio, - bool aHasVideo, - MetadataTags* aTags) +void MediaDecoderStateMachine::QueueMetadata(int64_t aPublishTime, int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags) { NS_ASSERTION(OnDecodeThread(), "Should be on decode thread."); mDecoder->GetReentrantMonitor().AssertCurrentThreadIn(); diff --git a/content/media/MediaDecoderStateMachine.h b/content/media/MediaDecoderStateMachine.h index 86c1dd40d51..a6505ebf526 100644 --- a/content/media/MediaDecoderStateMachine.h +++ b/content/media/MediaDecoderStateMachine.h @@ -319,7 +319,7 @@ public: // shutting down. The decoder monitor must be held while calling this. bool IsShutdown(); - void QueueMetadata(int64_t aPublishTime, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags); + void QueueMetadata(int64_t aPublishTime, int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags); protected: virtual uint32_t GetAmpleVideoFrames() { return mAmpleVideoFrames; } diff --git a/content/media/MediaMetadataManager.h b/content/media/MediaMetadataManager.h index e718f22d38a..5a37ffdb63f 100644 --- a/content/media/MediaMetadataManager.h +++ b/content/media/MediaMetadataManager.h @@ -28,8 +28,6 @@ namespace mozilla { int mChannels; // True if this media has an audio track. bool mHasAudio; - // True if this media has a video track. - bool mHasVideo; }; // This class encapsulate the logic to give the metadata from the reader to @@ -55,7 +53,6 @@ namespace mozilla { metadata->mChannels, metadata->mRate, metadata->mHasAudio, - metadata->mHasVideo, metadata->mTags.forget()); NS_DispatchToMainThread(metadataUpdatedEvent, NS_DISPATCH_NORMAL); mMetadataQueue.popFirst(); diff --git a/content/media/VideoFrameContainer.cpp b/content/media/VideoFrameContainer.cpp index b89e99efbbc..5789cb4d733 100644 --- a/content/media/VideoFrameContainer.cpp +++ b/content/media/VideoFrameContainer.cpp @@ -67,15 +67,7 @@ void VideoFrameContainer::SetCurrentFrame(const gfxIntSize& aIntrinsicSize, mPaintTarget = aTargetTime; } -void VideoFrameContainer::Reset() -{ - ClearCurrentFrame(true); - Invalidate(); - mPaintDelay = TimeDuration(); - mImageContainer->ResetPaintCount(); -} - -void VideoFrameContainer::ClearCurrentFrame(bool aResetSize) +void VideoFrameContainer::ClearCurrentFrame() { MutexAutoLock lock(mMutex); @@ -84,7 +76,6 @@ void VideoFrameContainer::ClearCurrentFrame(bool aResetSize) nsRefPtr kungFuDeathGrip; kungFuDeathGrip = mImageContainer->LockCurrentImage(); mImageContainer->UnlockCurrentImage(); - mImageSizeChanged = aResetSize; mImageContainer->SetCurrentImage(nullptr); diff --git a/content/media/VideoFrameContainer.h b/content/media/VideoFrameContainer.h index fc2f719b165..14f3bc06f3b 100644 --- a/content/media/VideoFrameContainer.h +++ b/content/media/VideoFrameContainer.h @@ -46,9 +46,7 @@ public: // Call on any thread void SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage, TimeStamp aTargetTime); - void ClearCurrentFrame(bool aResetSize = false); - // Reset the VideoFrameContainer - void Reset(); + void ClearCurrentFrame(); // Time in seconds by which the last painted video frame was late by. // E.g. if the last painted frame should have been painted at time t, // but was actually painted at t+n, this returns n in seconds. Threadsafe. diff --git a/content/media/ogg/OggReader.cpp b/content/media/ogg/OggReader.cpp index 3ab829ee5ef..7e3854a43e6 100644 --- a/content/media/ogg/OggReader.cpp +++ b/content/media/ogg/OggReader.cpp @@ -732,7 +732,6 @@ bool OggReader::ReadOggChain() channels, rate, HasAudio(), - HasVideo(), tags); } return true; diff --git a/content/media/test/Makefile.in b/content/media/test/Makefile.in index d0919c76750..d19837cd6a7 100644 --- a/content/media/test/Makefile.in +++ b/content/media/test/Makefile.in @@ -133,7 +133,7 @@ MOCHITEST_FILES = \ test_media_sniffer.html \ contentType.sjs \ test_streams_srcObject.html \ - test_reset_src.html \ + test_streams_gc.html \ $(filter disabled-for-intermittent-failures--bug-608634, test_error_in_video_document.html) \ $(NULL) diff --git a/content/media/test/test_reset_src.html b/content/media/test/test_reset_src.html deleted file mode 100644 index afc1e010c2d..00000000000 --- a/content/media/test/test_reset_src.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - Test for bug 804875 - - - - - -Mozilla Bug 804875 - - - - -
-
-
- - diff --git a/content/media/test/test_streams_gc.html b/content/media/test/test_streams_gc.html new file mode 100644 index 00000000000..545b0c19286 --- /dev/null +++ b/content/media/test/test_streams_gc.html @@ -0,0 +1,45 @@ + + + + Test garbage collection of captured stream (bug 806754) + + + + + + +
+
+
+ + diff --git a/content/media/webrtc/MediaEngine.h b/content/media/webrtc/MediaEngine.h index ce66ba11aa0..f4c7eed3783 100644 --- a/content/media/webrtc/MediaEngine.h +++ b/content/media/webrtc/MediaEngine.h @@ -89,6 +89,11 @@ public: /* Stop the device and release the corresponding MediaStream */ virtual nsresult Stop(SourceMediaStream *aSource, TrackID aID) = 0; + /* Change device configuration. */ + virtual nsresult Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) = 0; + /* Return false if device is currently allocated or started */ bool IsAvailable() { if (mState == kAllocated || mState == kStarted) { diff --git a/content/media/webrtc/MediaEngineDefault.h b/content/media/webrtc/MediaEngineDefault.h index e34b7b1b95d..bd1149adf4e 100644 --- a/content/media/webrtc/MediaEngineDefault.h +++ b/content/media/webrtc/MediaEngineDefault.h @@ -44,6 +44,9 @@ public: virtual nsresult Start(SourceMediaStream*, TrackID); virtual nsresult Stop(SourceMediaStream*, TrackID); virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile); + virtual nsresult Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) { return NS_OK; }; virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime); virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, @@ -86,6 +89,9 @@ public: virtual nsresult Start(SourceMediaStream*, TrackID); virtual nsresult Stop(SourceMediaStream*, TrackID); virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile); + virtual nsresult Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) { return NS_OK; }; virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime); virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, diff --git a/content/media/webrtc/MediaEngineWebRTC.h b/content/media/webrtc/MediaEngineWebRTC.h index 34ac056a078..8f553befec1 100644 --- a/content/media/webrtc/MediaEngineWebRTC.h +++ b/content/media/webrtc/MediaEngineWebRTC.h @@ -35,6 +35,7 @@ #include "voice_engine/include/voe_audio_processing.h" #include "voice_engine/include/voe_volume_control.h" #include "voice_engine/include/voe_external_media.h" +#include "voice_engine/include/voe_audio_processing.h" // Video Engine #include "video_engine/include/vie_base.h" @@ -90,6 +91,9 @@ public: virtual nsresult Start(SourceMediaStream*, TrackID); virtual nsresult Stop(SourceMediaStream*, TrackID); virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile); + virtual nsresult Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) { return NS_OK; }; virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, TrackID aId, @@ -177,6 +181,10 @@ public: , mCapIndex(aIndex) , mChannel(-1) , mInitDone(false) + , mEchoOn(false), mAgcOn(false), mNoiseOn(false) + , mEchoCancel(webrtc::kEcDefault) + , mAGC(webrtc::kAgcDefault) + , mNoiseSuppress(webrtc::kNsDefault) , mNullTransport(nullptr) { MOZ_ASSERT(aVoiceEnginePtr); mState = kReleased; @@ -194,6 +202,10 @@ public: virtual nsresult Start(SourceMediaStream*, TrackID); virtual nsresult Stop(SourceMediaStream*, TrackID); virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile); + virtual nsresult Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise); + virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, TrackID aId, @@ -218,6 +230,7 @@ private: webrtc::VoEBase* mVoEBase; webrtc::VoEExternalMedia* mVoERender; webrtc::VoENetwork* mVoENetwork; + webrtc::VoEAudioProcessing *mVoEProcessing; // mMonitor protects mSources[] access/changes, and transitions of mState // from kStarted to kStopped (which are combined with EndTrack()). @@ -233,6 +246,11 @@ private: nsString mDeviceName; nsString mDeviceUUID; + bool mEchoOn, mAgcOn, mNoiseOn; + webrtc::EcModes mEchoCancel; + webrtc::AgcModes mAGC; + webrtc::NsModes mNoiseSuppress; + NullTransport *mNullTransport; }; diff --git a/content/media/webrtc/MediaEngineWebRTCAudio.cpp b/content/media/webrtc/MediaEngineWebRTCAudio.cpp index 85981ca6da2..4da1e2af56a 100644 --- a/content/media/webrtc/MediaEngineWebRTCAudio.cpp +++ b/content/media/webrtc/MediaEngineWebRTCAudio.cpp @@ -46,6 +46,60 @@ MediaEngineWebRTCAudioSource::GetUUID(nsAString& aUUID) return; } +nsresult +MediaEngineWebRTCAudioSource::Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) +{ + LOG(("Audio config: aec: %d, agc: %d, noise: %d", + aEchoOn ? aEcho : -1, + aAgcOn ? aAGC : -1, + aNoiseOn ? aNoise : -1)); + + bool update_agc = (mAgcOn == aAgcOn); + bool update_noise = (mNoiseOn == aNoiseOn); + mAgcOn = aAgcOn; + mNoiseOn = aNoiseOn; + + if ((webrtc::AgcModes) aAGC != webrtc::kAgcUnchanged) { + if (mAGC != (webrtc::AgcModes) aAGC) { + update_agc = true; + mAGC = (webrtc::AgcModes) aAGC; + } + } + if ((webrtc::NsModes) aNoise != webrtc::kNsUnchanged) { + if (mNoiseSuppress != (webrtc::NsModes) aNoise) { + update_noise = true; + mNoiseSuppress = (webrtc::NsModes) aNoise; + } + } + + if (mInitDone) { + int error; +#if 0 + // Until we can support feeding our full output audio from the browser + // through the MediaStream, this won't work. Or we need to move AEC to + // below audio input and output, perhaps invoked from here. + mEchoOn = aEchoOn; + if ((webrtc::EcModes) aEcho != webrtc::kEcUnchanged) + mEchoCancel = (webrtc::EcModes) aEcho; + mVoEProcessing->SetEcStatus(mEchoOn, aEcho); +#else + (void) aEcho; (void) aEchoOn; // suppress warnings +#endif + + if (update_agc && + 0 != (error = mVoEProcessing->SetAgcStatus(mAgcOn, (webrtc::AgcModes) aAGC))) { + LOG(("%s Error setting AGC Status: %d ",__FUNCTION__, error)); + } + if (update_noise && + 0 != (error = mVoEProcessing->SetNsStatus(mNoiseOn, (webrtc::NsModes) aNoise))) { + LOG(("%s Error setting NoiseSuppression Status: %d ",__FUNCTION__, error)); + } + } + return NS_OK; +} + nsresult MediaEngineWebRTCAudioSource::Allocate() { @@ -106,6 +160,11 @@ MediaEngineWebRTCAudioSource::Start(SourceMediaStream* aStream, TrackID aID) } mState = kStarted; + // Configure audio processing in webrtc code + Config(mEchoOn, webrtc::kEcUnchanged, + mAgcOn, webrtc::kAgcUnchanged, + mNoiseOn, webrtc::kNsUnchanged); + if (mVoEBase->StartReceive(mChannel)) { return NS_ERROR_FAILURE; } @@ -192,6 +251,11 @@ MediaEngineWebRTCAudioSource::Init() return; } + mVoEProcessing = webrtc::VoEAudioProcessing::GetInterface(mVoiceEngine); + if (!mVoEProcessing) { + return; + } + mChannel = mVoEBase->CreateChannel(); if (mChannel < 0) { return; diff --git a/content/svg/content/src/DOMSVGTests.cpp b/content/svg/content/src/DOMSVGTests.cpp index 12c23186749..7f9af2a57a3 100644 --- a/content/svg/content/src/DOMSVGTests.cpp +++ b/content/svg/content/src/DOMSVGTests.cpp @@ -13,7 +13,7 @@ using namespace mozilla; -NS_IMPL_ISUPPORTS1(DOMSVGTests, nsIDOMSVGTests) +NS_IMPL_ISUPPORTS0(DOMSVGTests) nsIAtom** DOMSVGTests::sStringListNames[3] = { @@ -27,14 +27,6 @@ DOMSVGTests::DOMSVGTests() mStringListAttributes[LANGUAGE].SetIsCommaSeparated(true); } -/* readonly attribute nsIDOMSVGStringList requiredFeatures; */ -NS_IMETHODIMP -DOMSVGTests::GetRequiredFeatures(nsIDOMSVGStringList * *aRequiredFeatures) -{ - *aRequiredFeatures = RequiredFeatures().get(); - return NS_OK; -} - already_AddRefed DOMSVGTests::RequiredFeatures() { @@ -43,14 +35,6 @@ DOMSVGTests::RequiredFeatures() &mStringListAttributes[FEATURES], element, true, FEATURES).get(); } -/* readonly attribute nsIDOMSVGStringList requiredExtensions; */ -NS_IMETHODIMP -DOMSVGTests::GetRequiredExtensions(nsIDOMSVGStringList * *aRequiredExtensions) -{ - *aRequiredExtensions = RequiredExtensions().get(); - return NS_OK; -} - already_AddRefed DOMSVGTests::RequiredExtensions() { @@ -59,14 +43,6 @@ DOMSVGTests::RequiredExtensions() &mStringListAttributes[EXTENSIONS], element, true, EXTENSIONS).get(); } -/* readonly attribute nsIDOMSVGStringList systemLanguage; */ -NS_IMETHODIMP -DOMSVGTests::GetSystemLanguage(nsIDOMSVGStringList * *aSystemLanguage) -{ - *aSystemLanguage = SystemLanguage().get(); - return NS_OK; -} - already_AddRefed DOMSVGTests::SystemLanguage() { @@ -75,14 +51,6 @@ DOMSVGTests::SystemLanguage() &mStringListAttributes[LANGUAGE], element, true, LANGUAGE).get(); } -/* boolean hasExtension (in DOMString extension); */ -NS_IMETHODIMP -DOMSVGTests::HasExtension(const nsAString & extension, bool *_retval) -{ - *_retval = HasExtension(extension); - return NS_OK; -} - bool DOMSVGTests::HasExtension(const nsAString& aExtension) { diff --git a/content/svg/content/src/DOMSVGTests.h b/content/svg/content/src/DOMSVGTests.h index 4add8b70e28..2f07c1a20d1 100644 --- a/content/svg/content/src/DOMSVGTests.h +++ b/content/svg/content/src/DOMSVGTests.h @@ -6,24 +6,28 @@ #ifndef MOZILLA_DOMSVGTESTS_H__ #define MOZILLA_DOMSVGTESTS_H__ -#include "nsIDOMSVGTests.h" #include "nsStringFwd.h" #include "SVGStringList.h" #include "nsCOMPtr.h" class nsAttrValue; class nsIAtom; +class nsIDOMSVGStringList; class nsString; namespace mozilla { class DOMSVGStringList; } -class DOMSVGTests : public nsIDOMSVGTests +#define MOZILLA_DOMSVGTESTS_IID \ + { 0x92370da8, 0xda28, 0x4895, \ + {0x9b, 0x1b, 0xe0, 0x06, 0x0d, 0xb7, 0x3f, 0xc3 } } + +class DOMSVGTests : public nsISupports { public: + NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGTESTS_IID) NS_DECL_ISUPPORTS - NS_DECL_NSIDOMSVGTESTS DOMSVGTests(); virtual ~DOMSVGTests() {} @@ -97,4 +101,6 @@ private: static nsIAtom** sStringListNames[3]; }; +NS_DEFINE_STATIC_IID_ACCESSOR(DOMSVGTests, MOZILLA_DOMSVGTESTS_IID) + #endif // MOZILLA_DOMSVGTESTS_H__ diff --git a/content/svg/content/src/Makefile.in b/content/svg/content/src/Makefile.in index 04fd7cf1584..6f4868c3cda 100644 --- a/content/svg/content/src/Makefile.in +++ b/content/svg/content/src/Makefile.in @@ -49,7 +49,6 @@ CPPSRCS = \ nsSVGInteger.cpp \ nsSVGIntegerPair.cpp \ nsSVGLength2.cpp \ - nsSVGMarkerElement.cpp \ nsSVGNumber2.cpp \ nsSVGNumberPair.cpp \ nsSVGPathDataParser.cpp \ @@ -94,6 +93,7 @@ CPPSRCS = \ SVGLengthListSMILType.cpp \ SVGLineElement.cpp \ SVGLocatableElement.cpp \ + SVGMarkerElement.cpp \ SVGMaskElement.cpp \ SVGMatrix.cpp \ SVGMetadataElement.cpp \ @@ -177,6 +177,7 @@ EXPORTS_mozilla/dom = \ SVGImageElement.h \ SVGLineElement.h \ SVGLocatableElement.h \ + SVGMarkerElement.h \ SVGMaskElement.h \ SVGMatrix.h \ SVGMetadataElement.h \ diff --git a/content/svg/content/src/SVGAnimatedAngle.cpp b/content/svg/content/src/SVGAnimatedAngle.cpp index 726acc3a544..ce5bd10fd54 100644 --- a/content/svg/content/src/SVGAnimatedAngle.cpp +++ b/content/svg/content/src/SVGAnimatedAngle.cpp @@ -30,16 +30,12 @@ SVGAnimatedAngle::WrapObject(JSContext* aCx, JSObject* aScope, bool* aTriedToWra already_AddRefed SVGAnimatedAngle::BaseVal() { - nsRefPtr angle; - mVal->ToDOMBaseVal(getter_AddRefs(angle), mSVGElement); - return angle.forget(); + return mVal->ToDOMBaseVal(mSVGElement); } already_AddRefed SVGAnimatedAngle::AnimVal() { - nsRefPtr angle; - mVal->ToDOMAnimVal(getter_AddRefs(angle), mSVGElement); - return angle.forget(); + return mVal->ToDOMAnimVal(mSVGElement); } diff --git a/content/svg/content/src/SVGAnimatedAngle.h b/content/svg/content/src/SVGAnimatedAngle.h index 965fbb62a08..63324d07f28 100644 --- a/content/svg/content/src/SVGAnimatedAngle.h +++ b/content/svg/content/src/SVGAnimatedAngle.h @@ -29,12 +29,6 @@ public: } ~SVGAnimatedAngle(); - NS_IMETHOD GetBaseVal(nsISupports **aBaseVal) - { *aBaseVal = BaseVal().get(); return NS_OK; } - - NS_IMETHOD GetAnimVal(nsISupports **aAnimVal) - { *aAnimVal = AnimVal().get(); return NS_OK; } - // WebIDL nsSVGElement* GetParentObject() { return mSVGElement; } virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap); diff --git a/content/svg/content/src/SVGAnimationElement.cpp b/content/svg/content/src/SVGAnimationElement.cpp index a9ca16eef74..06c2863ec7c 100644 --- a/content/svg/content/src/SVGAnimationElement.cpp +++ b/content/svg/content/src/SVGAnimationElement.cpp @@ -23,7 +23,7 @@ NS_IMPL_RELEASE_INHERITED(SVGAnimationElement, SVGAnimationElementBase) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SVGAnimationElement) NS_INTERFACE_MAP_ENTRY(nsISMILAnimationElement) NS_INTERFACE_MAP_ENTRY(nsIDOMElementTimeControl) - NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTests) + NS_INTERFACE_MAP_ENTRY(DOMSVGTests) NS_INTERFACE_MAP_END_INHERITING(SVGAnimationElementBase) // Cycle collection magic -- based on nsSVGUseElement diff --git a/content/svg/content/src/SVGGraphicsElement.cpp b/content/svg/content/src/SVGGraphicsElement.cpp index a8308e80ad8..b014d40a6df 100644 --- a/content/svg/content/src/SVGGraphicsElement.cpp +++ b/content/svg/content/src/SVGGraphicsElement.cpp @@ -16,7 +16,7 @@ NS_IMPL_ADDREF_INHERITED(SVGGraphicsElement, SVGGraphicsElementBase) NS_IMPL_RELEASE_INHERITED(SVGGraphicsElement, SVGGraphicsElementBase) NS_INTERFACE_MAP_BEGIN(SVGGraphicsElement) - NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTests) + NS_INTERFACE_MAP_ENTRY(DOMSVGTests) NS_INTERFACE_MAP_END_INHERITING(SVGGraphicsElementBase) //---------------------------------------------------------------------- diff --git a/content/svg/content/src/nsSVGMarkerElement.cpp b/content/svg/content/src/SVGMarkerElement.cpp similarity index 60% rename from content/svg/content/src/nsSVGMarkerElement.cpp rename to content/svg/content/src/SVGMarkerElement.cpp index 51f56351105..21839e33a07 100644 --- a/content/svg/content/src/nsSVGMarkerElement.cpp +++ b/content/svg/content/src/SVGMarkerElement.cpp @@ -9,16 +9,29 @@ #include "nsCOMPtr.h" #include "SVGAnimatedPreserveAspectRatio.h" #include "nsError.h" -#include "nsSVGMarkerElement.h" +#include "mozilla/dom/SVGAngle.h" +#include "mozilla/dom/SVGAnimatedAngle.h" +#include "mozilla/dom/SVGAnimatedLength.h" +#include "mozilla/dom/SVGMarkerElement.h" +#include "mozilla/dom/SVGMarkerElementBinding.h" #include "gfxMatrix.h" #include "nsContentUtils.h" // NS_ENSURE_FINITE #include "SVGContentUtils.h" -#include "SVGAngle.h" -using namespace mozilla; -using namespace mozilla::dom; +NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Marker) -nsSVGElement::LengthInfo nsSVGMarkerElement::sLengthInfo[4] = +DOMCI_NODE_DATA(SVGMarkerElement, mozilla::dom::SVGMarkerElement) + +namespace mozilla { +namespace dom { + +JSObject* +SVGMarkerElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap) +{ + return SVGMarkerElementBinding::Wrap(aCx, aScope, this, aTriedToWrap); +} + +nsSVGElement::LengthInfo SVGMarkerElement::sLengthInfo[4] = { { &nsGkAtoms::refX, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X }, { &nsGkAtoms::refY, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y }, @@ -26,13 +39,13 @@ nsSVGElement::LengthInfo nsSVGMarkerElement::sLengthInfo[4] = { &nsGkAtoms::markerHeight, 3, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y }, }; -nsSVGEnumMapping nsSVGMarkerElement::sUnitsMap[] = { +nsSVGEnumMapping SVGMarkerElement::sUnitsMap[] = { {&nsGkAtoms::strokeWidth, nsIDOMSVGMarkerElement::SVG_MARKERUNITS_STROKEWIDTH}, {&nsGkAtoms::userSpaceOnUse, nsIDOMSVGMarkerElement::SVG_MARKERUNITS_USERSPACEONUSE}, {nullptr, 0} }; -nsSVGElement::EnumInfo nsSVGMarkerElement::sEnumInfo[1] = +nsSVGElement::EnumInfo SVGMarkerElement::sEnumInfo[1] = { { &nsGkAtoms::markerUnits, sUnitsMap, @@ -40,13 +53,11 @@ nsSVGElement::EnumInfo nsSVGMarkerElement::sEnumInfo[1] = } }; -nsSVGElement::AngleInfo nsSVGMarkerElement::sAngleInfo[1] = +nsSVGElement::AngleInfo SVGMarkerElement::sAngleInfo[1] = { { &nsGkAtoms::orient, 0, SVG_ANGLETYPE_UNSPECIFIED } }; -NS_IMPL_NS_NEW_SVG_ELEMENT(Marker) - //---------------------------------------------------------------------- // nsISupports methods @@ -61,17 +72,15 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGOrientType::DOMAnimatedEnum) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedEnumeration) NS_INTERFACE_MAP_END -NS_IMPL_ADDREF_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase) +NS_IMPL_ADDREF_INHERITED(SVGMarkerElement,SVGMarkerElementBase) +NS_IMPL_RELEASE_INHERITED(SVGMarkerElement,SVGMarkerElementBase) -DOMCI_NODE_DATA(SVGMarkerElement, nsSVGMarkerElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGMarkerElement) - NS_NODE_INTERFACE_TABLE5(nsSVGMarkerElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, nsIDOMSVGFitToViewBox, +NS_INTERFACE_TABLE_HEAD(SVGMarkerElement) + NS_NODE_INTERFACE_TABLE4(SVGMarkerElement, nsIDOMNode, nsIDOMElement, + nsIDOMSVGElement, nsIDOMSVGMarkerElement) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGMarkerElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGMarkerElementBase) +NS_INTERFACE_MAP_END_INHERITING(SVGMarkerElementBase) //---------------------------------------------------------------------- // Implementation @@ -93,95 +102,139 @@ nsSVGOrientType::SetBaseValue(uint16_t aValue, return NS_ERROR_DOM_SYNTAX_ERR; } -nsresult -nsSVGOrientType::ToDOMAnimatedEnum(nsIDOMSVGAnimatedEnumeration **aResult, - nsSVGElement *aSVGElement) +already_AddRefed +nsSVGOrientType::ToDOMAnimatedEnum(nsSVGElement *aSVGElement) { - *aResult = new DOMAnimatedEnum(this, aSVGElement); - if (!*aResult) - return NS_ERROR_OUT_OF_MEMORY; - - NS_ADDREF(*aResult); - return NS_OK; + nsCOMPtr toReturn = + new DOMAnimatedEnum(this, aSVGElement); + return toReturn.forget(); } -nsSVGMarkerElement::nsSVGMarkerElement(already_AddRefed aNodeInfo) - : nsSVGMarkerElementBase(aNodeInfo), mCoordCtx(nullptr) +SVGMarkerElement::SVGMarkerElement(already_AddRefed aNodeInfo) + : SVGMarkerElementBase(aNodeInfo), mCoordCtx(nullptr) { + SetIsDOMBinding(); } //---------------------------------------------------------------------- // nsIDOMNode methods -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGMarkerElement) +NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGMarkerElement) //---------------------------------------------------------------------- -// nsIDOMSVGFitToViewBox methods -/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ - NS_IMETHODIMP nsSVGMarkerElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) +already_AddRefed +SVGMarkerElement::ViewBox() { - return mViewBox.ToDOMAnimatedRect(aViewBox, this); + nsCOMPtr rect; + mViewBox.ToDOMAnimatedRect(getter_AddRefs(rect), this); + return rect.forget(); } -/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ -NS_IMETHODIMP -nsSVGMarkerElement::GetPreserveAspectRatio(nsISupports - **aPreserveAspectRatio) +already_AddRefed +SVGMarkerElement::PreserveAspectRatio() { nsRefPtr ratio; mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(getter_AddRefs(ratio), this); - ratio.forget(aPreserveAspectRatio); - return NS_OK; + return ratio.forget(); } //---------------------------------------------------------------------- // nsIDOMSVGMarkerElement methods /* readonly attribute nsIDOMSVGAnimatedLength refX; */ -NS_IMETHODIMP nsSVGMarkerElement::GetRefX(nsIDOMSVGAnimatedLength * *aRefX) +NS_IMETHODIMP SVGMarkerElement::GetRefX(nsIDOMSVGAnimatedLength * *aRefX) { - return mLengthAttributes[REFX].ToDOMAnimatedLength(aRefX, this); + *aRefX = RefX().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::RefX() +{ + return mLengthAttributes[REFX].ToDOMAnimatedLength(this); } /* readonly attribute nsIDOMSVGAnimatedLength refY; */ -NS_IMETHODIMP nsSVGMarkerElement::GetRefY(nsIDOMSVGAnimatedLength * *aRefY) +NS_IMETHODIMP SVGMarkerElement::GetRefY(nsIDOMSVGAnimatedLength * *aRefY) { - return mLengthAttributes[REFY].ToDOMAnimatedLength(aRefY, this); + *aRefY = RefY().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::RefY() +{ + return mLengthAttributes[REFY].ToDOMAnimatedLength(this); } /* readonly attribute nsIDOMSVGAnimatedEnumeration markerUnits; */ -NS_IMETHODIMP nsSVGMarkerElement::GetMarkerUnits(nsIDOMSVGAnimatedEnumeration * *aMarkerUnits) +NS_IMETHODIMP SVGMarkerElement::GetMarkerUnits(nsIDOMSVGAnimatedEnumeration * *aMarkerUnits) { - return mEnumAttributes[MARKERUNITS].ToDOMAnimatedEnum(aMarkerUnits, this); + *aMarkerUnits = MarkerUnits().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::MarkerUnits() +{ + return mEnumAttributes[MARKERUNITS].ToDOMAnimatedEnum(this); } /* readonly attribute nsIDOMSVGAnimatedLength markerWidth; */ -NS_IMETHODIMP nsSVGMarkerElement::GetMarkerWidth(nsIDOMSVGAnimatedLength * *aMarkerWidth) +NS_IMETHODIMP SVGMarkerElement::GetMarkerWidth(nsIDOMSVGAnimatedLength * *aMarkerWidth) { - return mLengthAttributes[MARKERWIDTH].ToDOMAnimatedLength(aMarkerWidth, this); + *aMarkerWidth = MarkerWidth().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::MarkerWidth() +{ + return mLengthAttributes[MARKERWIDTH].ToDOMAnimatedLength(this); } /* readonly attribute nsIDOMSVGAnimatedLength markerHeight; */ -NS_IMETHODIMP nsSVGMarkerElement::GetMarkerHeight(nsIDOMSVGAnimatedLength * *aMarkerHeight) +NS_IMETHODIMP SVGMarkerElement::GetMarkerHeight(nsIDOMSVGAnimatedLength * *aMarkerHeight) { - return mLengthAttributes[MARKERHEIGHT].ToDOMAnimatedLength(aMarkerHeight, this); + *aMarkerHeight = MarkerHeight().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::MarkerHeight() +{ + return mLengthAttributes[MARKERHEIGHT].ToDOMAnimatedLength(this); } /* readonly attribute nsIDOMSVGAnimatedEnumeration orientType; */ -NS_IMETHODIMP nsSVGMarkerElement::GetOrientType(nsIDOMSVGAnimatedEnumeration * *aOrientType) +NS_IMETHODIMP SVGMarkerElement::GetOrientType(nsIDOMSVGAnimatedEnumeration * *aOrientType) { - return mOrientType.ToDOMAnimatedEnum(aOrientType, this); + *aOrientType = OrientType().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::OrientType() +{ + return mOrientType.ToDOMAnimatedEnum(this); } /* readonly attribute SVGAnimatedAngle orientAngle; */ -NS_IMETHODIMP nsSVGMarkerElement::GetOrientAngle(nsISupports * *aOrientAngle) +NS_IMETHODIMP SVGMarkerElement::GetOrientAngle(nsISupports * *aOrientAngle) { - return mAngleAttributes[ORIENT].ToDOMAnimatedAngle(aOrientAngle, this); + *aOrientAngle = OrientAngle().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::OrientAngle() +{ + return mAngleAttributes[ORIENT].ToDOMAnimatedAngle(this); } /* void setOrientToAuto (); */ -NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAuto() +NS_IMETHODIMP SVGMarkerElement::SetOrientToAuto() { SetAttr(kNameSpaceID_None, nsGkAtoms::orient, nullptr, NS_LITERAL_STRING("auto"), true); @@ -189,24 +242,33 @@ NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAuto() } /* void setOrientToAngle (in SVGAngle angle); */ -NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAngle(nsISupports *aAngle) +NS_IMETHODIMP SVGMarkerElement::SetOrientToAngle(nsISupports *aAngle) { nsCOMPtr angle = do_QueryInterface(aAngle); if (!angle) return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR; - float f = angle->Value(); - NS_ENSURE_FINITE(f, NS_ERROR_DOM_SVG_WRONG_TYPE_ERR); - mAngleAttributes[ORIENT].SetBaseValue(f, this, true); + ErrorResult rv; + SetOrientToAngle(*angle, rv); + return rv.ErrorCode(); +} - return NS_OK; +void +SVGMarkerElement::SetOrientToAngle(SVGAngle& angle, ErrorResult& rv) +{ + float f = angle.Value(); + if (!NS_finite(f)) { + rv.Throw(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR); + return; + } + mAngleAttributes[ORIENT].SetBaseValue(f, this, true); } //---------------------------------------------------------------------- // nsIContent methods NS_IMETHODIMP_(bool) -nsSVGMarkerElement::IsAttributeMapped(const nsIAtom* name) const +SVGMarkerElement::IsAttributeMapped(const nsIAtom* name) const { static const MappedAttributeEntry* const map[] = { sFEFloodMap, @@ -216,19 +278,22 @@ nsSVGMarkerElement::IsAttributeMapped(const nsIAtom* name) const sLightingEffectsMap, sMarkersMap, sTextContentElementsMap, - sViewportsMap + sViewportsMap, + sColorMap, + sFillStrokeMap, + sGraphicsMap }; return FindAttributeDependence(name, map) || - nsSVGMarkerElementBase::IsAttributeMapped(name); + SVGMarkerElementBase::IsAttributeMapped(name); } //---------------------------------------------------------------------- // nsSVGElement methods bool -nsSVGMarkerElement::GetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAString &aResult) const +SVGMarkerElement::GetAttr(int32_t aNameSpaceID, nsIAtom* aName, + nsAString &aResult) const { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::orient && @@ -236,13 +301,13 @@ nsSVGMarkerElement::GetAttr(int32_t aNameSpaceID, nsIAtom* aName, aResult.AssignLiteral("auto"); return true; } - return nsSVGMarkerElementBase::GetAttr(aNameSpaceID, aName, aResult); + return SVGMarkerElementBase::GetAttr(aNameSpaceID, aName, aResult); } bool -nsSVGMarkerElement::ParseAttribute(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, - nsAttrValue& aResult) +SVGMarkerElement::ParseAttribute(int32_t aNameSpaceID, nsIAtom* aName, + const nsAString& aValue, + nsAttrValue& aResult) { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::orient) { if (aValue.EqualsLiteral("auto")) { @@ -252,13 +317,13 @@ nsSVGMarkerElement::ParseAttribute(int32_t aNameSpaceID, nsIAtom* aName, } mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE); } - return nsSVGMarkerElementBase::ParseAttribute(aNameSpaceID, aName, - aValue, aResult); + return SVGMarkerElementBase::ParseAttribute(aNameSpaceID, aName, + aValue, aResult); } nsresult -nsSVGMarkerElement::UnsetAttr(int32_t aNamespaceID, nsIAtom* aName, - bool aNotify) +SVGMarkerElement::UnsetAttr(int32_t aNamespaceID, nsIAtom* aName, + bool aNotify) { if (aNamespaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::orient) { @@ -273,14 +338,14 @@ nsSVGMarkerElement::UnsetAttr(int32_t aNamespaceID, nsIAtom* aName, // nsSVGElement methods void -nsSVGMarkerElement::SetParentCoordCtxProvider(SVGSVGElement *aContext) +SVGMarkerElement::SetParentCoordCtxProvider(SVGSVGElement *aContext) { mCoordCtx = aContext; mViewBoxToViewportTransform = nullptr; } /* virtual */ bool -nsSVGMarkerElement::HasValidDimensions() const +SVGMarkerElement::HasValidDimensions() const { return (!mLengthAttributes[MARKERWIDTH].IsExplicitlySet() || mLengthAttributes[MARKERWIDTH].GetAnimValInSpecifiedUnits() > 0) && @@ -289,34 +354,34 @@ nsSVGMarkerElement::HasValidDimensions() const } nsSVGElement::LengthAttributesInfo -nsSVGMarkerElement::GetLengthInfo() +SVGMarkerElement::GetLengthInfo() { return LengthAttributesInfo(mLengthAttributes, sLengthInfo, ArrayLength(sLengthInfo)); } nsSVGElement::AngleAttributesInfo -nsSVGMarkerElement::GetAngleInfo() +SVGMarkerElement::GetAngleInfo() { return AngleAttributesInfo(mAngleAttributes, sAngleInfo, ArrayLength(sAngleInfo)); } nsSVGElement::EnumAttributesInfo -nsSVGMarkerElement::GetEnumInfo() +SVGMarkerElement::GetEnumInfo() { return EnumAttributesInfo(mEnumAttributes, sEnumInfo, ArrayLength(sEnumInfo)); } nsSVGViewBox * -nsSVGMarkerElement::GetViewBox() +SVGMarkerElement::GetViewBox() { return &mViewBox; } SVGAnimatedPreserveAspectRatio * -nsSVGMarkerElement::GetPreserveAspectRatio() +SVGMarkerElement::GetPreserveAspectRatio() { return &mPreserveAspectRatio; } @@ -325,8 +390,8 @@ nsSVGMarkerElement::GetPreserveAspectRatio() // public helpers gfxMatrix -nsSVGMarkerElement::GetMarkerTransform(float aStrokeWidth, - float aX, float aY, float aAutoAngle) +SVGMarkerElement::GetMarkerTransform(float aStrokeWidth, + float aX, float aY, float aAutoAngle) { gfxFloat scale = mEnumAttributes[MARKERUNITS].GetAnimValue() == SVG_MARKERUNITS_STROKEWIDTH ? aStrokeWidth : 1.0; @@ -341,7 +406,7 @@ nsSVGMarkerElement::GetMarkerTransform(float aStrokeWidth, } nsSVGViewBoxRect -nsSVGMarkerElement::GetViewBoxRect() +SVGMarkerElement::GetViewBoxRect() { if (mViewBox.IsExplicitlySet()) { return mViewBox.GetAnimValue(); @@ -353,7 +418,7 @@ nsSVGMarkerElement::GetViewBoxRect() } gfxMatrix -nsSVGMarkerElement::GetViewBoxTransform() +SVGMarkerElement::GetViewBoxTransform() { if (!mViewBoxToViewportTransform) { float viewportWidth = @@ -386,4 +451,5 @@ nsSVGMarkerElement::GetViewBoxTransform() return *mViewBoxToViewportTransform; } - +} // namespace dom +} // namespace mozilla diff --git a/content/svg/content/src/nsSVGMarkerElement.h b/content/svg/content/src/SVGMarkerElement.h similarity index 71% rename from content/svg/content/src/nsSVGMarkerElement.h rename to content/svg/content/src/SVGMarkerElement.h index 50fc788c40c..d99b7284c8b 100644 --- a/content/svg/content/src/nsSVGMarkerElement.h +++ b/content/svg/content/src/SVGMarkerElement.h @@ -3,20 +3,27 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef __NS_SVGMARKERELEMENT_H__ -#define __NS_SVGMARKERELEMENT_H__ +#ifndef mozilla_dom_SVGMarkerElement_h +#define mozilla_dom_SVGMarkerElement_h #include "gfxMatrix.h" -#include "nsIDOMSVGFitToViewBox.h" #include "nsIDOMSVGMarkerElement.h" #include "nsSVGAngle.h" #include "nsSVGEnum.h" #include "nsSVGLength2.h" #include "nsSVGViewBox.h" #include "SVGAnimatedPreserveAspectRatio.h" -#include "SVGGraphicsElement.h" +#include "nsSVGElement.h" #include "mozilla/Attributes.h" +class nsSVGMarkerFrame; + +nsresult NS_NewSVGMarkerElement(nsIContent **aResult, + already_AddRefed aNodeInfo); + +namespace mozilla { +namespace dom { + class nsSVGOrientType { public: @@ -40,8 +47,8 @@ public: uint16_t GetAnimValue() const { return mAnimVal; } - nsresult ToDOMAnimatedEnum(nsIDOMSVGAnimatedEnumeration **aResult, - nsSVGElement* aSVGElement); + already_AddRefed + ToDOMAnimatedEnum(nsSVGElement* aSVGElement); private: nsSVGEnumValue mAnimVal; @@ -68,27 +75,24 @@ private: }; }; -typedef mozilla::dom::SVGGraphicsElement nsSVGMarkerElementBase; +typedef nsSVGElement SVGMarkerElementBase; -class nsSVGMarkerElement : public nsSVGMarkerElementBase, - public nsIDOMSVGMarkerElement, - public nsIDOMSVGFitToViewBox +class SVGMarkerElement : public SVGMarkerElementBase, + public nsIDOMSVGMarkerElement { - friend class nsSVGMarkerFrame; + friend class ::nsSVGMarkerFrame; protected: - friend nsresult NS_NewSVGMarkerElement(nsIContent **aResult, - already_AddRefed aNodeInfo); - nsSVGMarkerElement(already_AddRefed aNodeInfo); + friend nsresult (::NS_NewSVGMarkerElement(nsIContent **aResult, + already_AddRefed aNodeInfo)); + SVGMarkerElement(already_AddRefed aNodeInfo); + virtual JSObject* WrapNode(JSContext *cx, JSObject *scope, bool *triedToWrap) MOZ_OVERRIDE; public: - typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio; - // interfaces: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMSVGMARKERELEMENT - NS_DECL_NSIDOMSVGFITTOVIEWBOX // xxx I wish we could use virtual inheritance NS_FORWARD_NSIDOMNODE_TO_NSINODE @@ -119,13 +123,27 @@ public: virtual nsXPCClassInfo* GetClassInfo(); virtual nsIDOMNode* AsDOMNode() { return this; } + + // WebIDL + already_AddRefed ViewBox(); + already_AddRefed PreserveAspectRatio(); + already_AddRefed RefX(); + already_AddRefed RefY(); + already_AddRefed MarkerUnits(); + already_AddRefed MarkerWidth(); + already_AddRefed MarkerHeight(); + already_AddRefed OrientType(); + already_AddRefed OrientAngle(); + // We can use the XPIDL SetOrientToAuto + void SetOrientToAngle(SVGAngle& angle, ErrorResult& rv); + protected: virtual bool ParseAttribute(int32_t aNameSpaceID, nsIAtom* aName, const nsAString& aValue, nsAttrValue& aResult); - void SetParentCoordCtxProvider(mozilla::dom::SVGSVGElement *aContext); + void SetParentCoordCtxProvider(SVGSVGElement *aContext); virtual LengthAttributesInfo GetLengthInfo(); virtual AngleAttributesInfo GetAngleInfo(); @@ -152,8 +170,11 @@ protected: // derived properties (from 'orient') handled separately nsSVGOrientType mOrientType; - mozilla::dom::SVGSVGElement *mCoordCtx; + SVGSVGElement *mCoordCtx; nsAutoPtr mViewBoxToViewportTransform; }; -#endif +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_SVGMarkerElement_h diff --git a/content/svg/content/src/SVGPatternElement.cpp b/content/svg/content/src/SVGPatternElement.cpp index 62a03cf2175..fb2c56ff4e2 100644 --- a/content/svg/content/src/SVGPatternElement.cpp +++ b/content/svg/content/src/SVGPatternElement.cpp @@ -60,9 +60,9 @@ NS_IMPL_ADDREF_INHERITED(SVGPatternElement,SVGPatternElementBase) NS_IMPL_RELEASE_INHERITED(SVGPatternElement,SVGPatternElementBase) NS_INTERFACE_TABLE_HEAD(SVGPatternElement) - NS_NODE_INTERFACE_TABLE7(SVGPatternElement, nsIDOMNode, nsIDOMElement, + NS_NODE_INTERFACE_TABLE6(SVGPatternElement, nsIDOMNode, nsIDOMElement, nsIDOMSVGElement, - nsIDOMSVGFitToViewBox, nsIDOMSVGURIReference, + nsIDOMSVGURIReference, nsIDOMSVGPatternElement, nsIDOMSVGUnitTypes) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPatternElement) NS_INTERFACE_MAP_END_INHERITING(SVGPatternElementBase) @@ -82,14 +82,6 @@ SVGPatternElement::SVGPatternElement(already_AddRefed aNodeInfo) NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGPatternElement) //---------------------------------------------------------------------- -// nsIDOMSVGFitToViewBox methods - -/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ -NS_IMETHODIMP SVGPatternElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) -{ - *aViewBox = ViewBox().get(); - return NS_OK; -} already_AddRefed SVGPatternElement::ViewBox() @@ -99,14 +91,6 @@ SVGPatternElement::ViewBox() return rect.forget(); } -/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ -NS_IMETHODIMP -SVGPatternElement::GetPreserveAspectRatio(nsISupports **aPreserveAspectRatio) -{ - *aPreserveAspectRatio = PreserveAspectRatio().get(); - return NS_OK; -} - already_AddRefed SVGPatternElement::PreserveAspectRatio() { diff --git a/content/svg/content/src/SVGPatternElement.h b/content/svg/content/src/SVGPatternElement.h index f4a34be5b61..2b70b1c857c 100644 --- a/content/svg/content/src/SVGPatternElement.h +++ b/content/svg/content/src/SVGPatternElement.h @@ -6,7 +6,6 @@ #ifndef mozilla_dom_SVGPatternElement_h #define mozilla_dom_SVGPatternElement_h -#include "nsIDOMSVGFitToViewBox.h" #include "nsIDOMSVGPatternElement.h" #include "nsIDOMSVGUnitTypes.h" #include "nsIDOMSVGURIReference.h" @@ -33,7 +32,6 @@ typedef nsSVGElement SVGPatternElementBase; class SVGPatternElement MOZ_FINAL : public SVGPatternElementBase, public nsIDOMSVGPatternElement, public nsIDOMSVGURIReference, - public nsIDOMSVGFitToViewBox, public nsIDOMSVGUnitTypes { friend class ::nsSVGPatternFrame; @@ -56,9 +54,6 @@ public: // URI Reference NS_DECL_NSIDOMSVGURIREFERENCE - // FitToViewbox - NS_DECL_NSIDOMSVGFITTOVIEWBOX - NS_FORWARD_NSIDOMNODE_TO_NSINODE NS_FORWARD_NSIDOMELEMENT_TO_GENERIC NS_FORWARD_NSIDOMSVGELEMENT(nsSVGElement::) @@ -117,7 +112,7 @@ protected: nsSVGString mStringAttributes[1]; static StringInfo sStringInfo[1]; - // nsIDOMSVGFitToViewbox properties + // SVGFitToViewbox properties nsSVGViewBox mViewBox; SVGAnimatedPreserveAspectRatio mPreserveAspectRatio; }; diff --git a/content/svg/content/src/SVGSVGElement.cpp b/content/svg/content/src/SVGSVGElement.cpp index bd8a20292d8..a4964781813 100644 --- a/content/svg/content/src/SVGSVGElement.cpp +++ b/content/svg/content/src/SVGSVGElement.cpp @@ -146,10 +146,9 @@ NS_IMPL_ADDREF_INHERITED(SVGSVGElement,SVGSVGElementBase) NS_IMPL_RELEASE_INHERITED(SVGSVGElement,SVGSVGElementBase) NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(SVGSVGElement) - NS_NODE_INTERFACE_TABLE5(SVGSVGElement, nsIDOMNode, nsIDOMElement, + NS_NODE_INTERFACE_TABLE4(SVGSVGElement, nsIDOMNode, nsIDOMElement, nsIDOMSVGElement, - nsIDOMSVGSVGElement, - nsIDOMSVGFitToViewBox) + nsIDOMSVGSVGElement) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGSVGElement) NS_INTERFACE_MAP_END_INHERITING(SVGSVGElementBase) @@ -675,15 +674,6 @@ SVGSVGElement::GetElementById(const nsAString& elementId, ErrorResult& rv) } //---------------------------------------------------------------------- -// nsIDOMSVGFitToViewBox methods - -/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ -NS_IMETHODIMP -SVGSVGElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) -{ - *aViewBox = ViewBox().get(); - return NS_OK; -} already_AddRefed SVGSVGElement::ViewBox() @@ -693,15 +683,6 @@ SVGSVGElement::ViewBox() return rect.forget(); } -/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ -NS_IMETHODIMP -SVGSVGElement::GetPreserveAspectRatio(nsISupports - **aPreserveAspectRatio) -{ - *aPreserveAspectRatio = PreserveAspectRatio().get(); - return NS_OK; -} - already_AddRefed SVGSVGElement::PreserveAspectRatio() { diff --git a/content/svg/content/src/SVGSVGElement.h b/content/svg/content/src/SVGSVGElement.h index d184569f9f9..d1b4b157c18 100644 --- a/content/svg/content/src/SVGSVGElement.h +++ b/content/svg/content/src/SVGSVGElement.h @@ -7,7 +7,6 @@ #define mozilla_dom_SVGSVGElement_h #include "mozilla/dom/FromParser.h" -#include "nsIDOMSVGFitToViewBox.h" #include "nsISVGPoint.h" #include "nsIDOMSVGSVGElement.h" #include "nsSVGEnum.h" @@ -80,8 +79,7 @@ public: typedef SVGGraphicsElement SVGSVGElementBase; class SVGSVGElement MOZ_FINAL : public SVGSVGElementBase, - public nsIDOMSVGSVGElement, - public nsIDOMSVGFitToViewBox + public nsIDOMSVGSVGElement { friend class ::nsSVGOuterSVGFrame; friend class ::nsSVGInnerSVGFrame; @@ -101,7 +99,6 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGSVGElement, SVGSVGElementBase) NS_DECL_NSIDOMSVGSVGELEMENT - NS_DECL_NSIDOMSVGFITTOVIEWBOX // xxx I wish we could use virtual inheritance NS_FORWARD_NSIDOMNODE_TO_NSINODE diff --git a/content/svg/content/src/SVGSymbolElement.cpp b/content/svg/content/src/SVGSymbolElement.cpp index b34ce9a5f69..38741eacbbd 100644 --- a/content/svg/content/src/SVGSymbolElement.cpp +++ b/content/svg/content/src/SVGSymbolElement.cpp @@ -26,9 +26,9 @@ NS_IMPL_ADDREF_INHERITED(SVGSymbolElement,SVGSymbolElementBase) NS_IMPL_RELEASE_INHERITED(SVGSymbolElement,SVGSymbolElementBase) NS_INTERFACE_TABLE_HEAD(SVGSymbolElement) - NS_NODE_INTERFACE_TABLE6(SVGSymbolElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, nsIDOMSVGFitToViewBox, - nsIDOMSVGSymbolElement, nsIDOMSVGTests) + NS_NODE_INTERFACE_TABLE5(SVGSymbolElement, nsIDOMNode, nsIDOMElement, + nsIDOMSVGElement, + nsIDOMSVGSymbolElement, DOMSVGTests) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGSymbolElement) NS_INTERFACE_MAP_END_INHERITING(SVGSymbolElementBase) @@ -48,14 +48,6 @@ SVGSymbolElement::SVGSymbolElement(already_AddRefed aNodeInfo) NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGSymbolElement) //---------------------------------------------------------------------- -// nsIDOMSVGFitToViewBox methods - -/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ -NS_IMETHODIMP SVGSymbolElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) -{ - *aViewBox = ViewBox().get(); - return NS_OK; -} already_AddRefed SVGSymbolElement::ViewBox() @@ -65,15 +57,6 @@ SVGSymbolElement::ViewBox() return rect.forget(); } -/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ -NS_IMETHODIMP -SVGSymbolElement::GetPreserveAspectRatio(nsISupports - **aPreserveAspectRatio) -{ - *aPreserveAspectRatio = PreserveAspectRatio().get(); - return NS_OK; -} - already_AddRefed SVGSymbolElement::PreserveAspectRatio() { diff --git a/content/svg/content/src/SVGSymbolElement.h b/content/svg/content/src/SVGSymbolElement.h index f016bc88353..95b7a3690a1 100644 --- a/content/svg/content/src/SVGSymbolElement.h +++ b/content/svg/content/src/SVGSymbolElement.h @@ -11,7 +11,6 @@ #include "nsSVGElement.h" #include "nsSVGViewBox.h" #include "SVGAnimatedPreserveAspectRatio.h" -#include "nsIDOMSVGFitToViewBox.h" #include "nsGkAtoms.h" nsresult NS_NewSVGSymbolElement(nsIContent **aResult, @@ -24,8 +23,7 @@ typedef nsSVGElement SVGSymbolElementBase; class SVGSymbolElement MOZ_FINAL : public SVGSymbolElementBase, public nsIDOMSVGSymbolElement, - public DOMSVGTests, - public nsIDOMSVGFitToViewBox + public DOMSVGTests { protected: friend nsresult (::NS_NewSVGSymbolElement(nsIContent **aResult, @@ -38,7 +36,6 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMSVGSYMBOLELEMENT - NS_DECL_NSIDOMSVGFITTOVIEWBOX // xxx I wish we could use virtual inheritance NS_FORWARD_NSIDOMNODE_TO_NSINODE diff --git a/content/svg/content/src/SVGViewElement.cpp b/content/svg/content/src/SVGViewElement.cpp index 303dbeb931a..07acc04bcba 100644 --- a/content/svg/content/src/SVGViewElement.cpp +++ b/content/svg/content/src/SVGViewElement.cpp @@ -46,9 +46,8 @@ NS_IMPL_ADDREF_INHERITED(SVGViewElement,SVGViewElementBase) NS_IMPL_RELEASE_INHERITED(SVGViewElement,SVGViewElementBase) NS_INTERFACE_TABLE_HEAD(SVGViewElement) - NS_NODE_INTERFACE_TABLE5(SVGViewElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, nsIDOMSVGViewElement, - nsIDOMSVGFitToViewBox) + NS_NODE_INTERFACE_TABLE4(SVGViewElement, nsIDOMNode, nsIDOMElement, + nsIDOMSVGElement, nsIDOMSVGViewElement) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGViewElement) NS_INTERFACE_MAP_END_INHERITING(SVGViewElementBase) @@ -78,15 +77,6 @@ SVGViewElement::SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv) } //---------------------------------------------------------------------- -// nsIDOMSVGFitToViewBox methods - -/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ -NS_IMETHODIMP -SVGViewElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) -{ - *aViewBox = ViewBox().get(); - return NS_OK; -} already_AddRefed SVGViewElement::ViewBox() @@ -96,15 +86,6 @@ SVGViewElement::ViewBox() return box.forget(); } -/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ -NS_IMETHODIMP -SVGViewElement::GetPreserveAspectRatio(nsISupports - **aPreserveAspectRatio) -{ - *aPreserveAspectRatio = PreserveAspectRatio().get(); - return NS_OK; -} - already_AddRefed SVGViewElement::PreserveAspectRatio() { diff --git a/content/svg/content/src/SVGViewElement.h b/content/svg/content/src/SVGViewElement.h index abdd8485bbf..dd0526c8e04 100644 --- a/content/svg/content/src/SVGViewElement.h +++ b/content/svg/content/src/SVGViewElement.h @@ -7,7 +7,6 @@ #define mozilla_dom_SVGViewElement_h #include "nsIDOMSVGViewElement.h" -#include "nsIDOMSVGFitToViewBox.h" #include "nsSVGElement.h" #include "nsSVGEnum.h" #include "nsSVGViewBox.h" @@ -32,8 +31,7 @@ namespace dom { class SVGSVGElement; class SVGViewElement : public SVGViewElementBase, - public nsIDOMSVGViewElement, - public nsIDOMSVGFitToViewBox + public nsIDOMSVGViewElement { protected: friend class mozilla::SVGFragmentIdentifier; @@ -49,7 +47,6 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMSVGVIEWELEMENT - NS_DECL_NSIDOMSVGFITTOVIEWBOX // xxx If xpcom allowed virtual inheritance we wouldn't need to // forward here :-( diff --git a/content/svg/content/src/crashtests/831561.html b/content/svg/content/src/crashtests/831561.html new file mode 100644 index 00000000000..d86a8cb5bd6 --- /dev/null +++ b/content/svg/content/src/crashtests/831561.html @@ -0,0 +1,10 @@ + + + + + + diff --git a/content/svg/content/src/crashtests/crashtests.list b/content/svg/content/src/crashtests/crashtests.list index ee12a17d40e..c27bb832d91 100644 --- a/content/svg/content/src/crashtests/crashtests.list +++ b/content/svg/content/src/crashtests/crashtests.list @@ -61,3 +61,4 @@ load zero-size-image.svg load 723441-1.html load 751515-1.svg load 761507-1.svg +load 831561.html diff --git a/content/svg/content/src/nsSVGAngle.cpp b/content/svg/content/src/nsSVGAngle.cpp index a67899b884e..9e6c371c633 100644 --- a/content/svg/content/src/nsSVGAngle.cpp +++ b/content/svg/content/src/nsSVGAngle.cpp @@ -9,7 +9,7 @@ #include "prdtoa.h" #include "nsTextFormatter.h" #include "nsSVGAttrTearoffTable.h" -#include "nsSVGMarkerElement.h" +#include "mozilla/dom/SVGMarkerElement.h" #include "nsMathUtils.h" #include "nsContentUtils.h" // NS_ENSURE_FINITE #include "nsSMILValue.h" @@ -217,8 +217,8 @@ nsSVGAngle::NewValueSpecifiedUnits(uint16_t unitType, return NS_OK; } -nsresult -nsSVGAngle::ToDOMBaseVal(SVGAngle **aResult, nsSVGElement *aSVGElement) +already_AddRefed +nsSVGAngle::ToDOMBaseVal(nsSVGElement *aSVGElement) { nsRefPtr domBaseVal = sBaseSVGAngleTearoffTable.GetTearoff(this); @@ -227,12 +227,11 @@ nsSVGAngle::ToDOMBaseVal(SVGAngle **aResult, nsSVGElement *aSVGElement) sBaseSVGAngleTearoffTable.AddTearoff(this, domBaseVal); } - domBaseVal.forget(aResult); - return NS_OK; + return domBaseVal.forget(); } -nsresult -nsSVGAngle::ToDOMAnimVal(SVGAngle **aResult, nsSVGElement *aSVGElement) +already_AddRefed +nsSVGAngle::ToDOMAnimVal(nsSVGElement *aSVGElement) { nsRefPtr domAnimVal = sAnimSVGAngleTearoffTable.GetTearoff(this); @@ -241,8 +240,7 @@ nsSVGAngle::ToDOMAnimVal(SVGAngle **aResult, nsSVGElement *aSVGElement) sAnimSVGAngleTearoffTable.AddTearoff(this, domAnimVal); } - domAnimVal.forget(aResult); - return NS_OK; + return domAnimVal.forget(); } SVGAngle::~SVGAngle() @@ -342,9 +340,8 @@ nsSVGAngle::SetAnimValue(float aValue, uint8_t aUnit, nsSVGElement *aSVGElement) aSVGElement->DidAnimateAngle(mAttrEnum); } -nsresult -nsSVGAngle::ToDOMAnimatedAngle(nsISupports **aResult, - nsSVGElement *aSVGElement) +already_AddRefed +nsSVGAngle::ToDOMAnimatedAngle(nsSVGElement *aSVGElement) { nsRefPtr domAnimatedAngle = sSVGAnimatedAngleTearoffTable.GetTearoff(this); @@ -353,8 +350,7 @@ nsSVGAngle::ToDOMAnimatedAngle(nsISupports **aResult, sSVGAnimatedAngleTearoffTable.AddTearoff(this, domAnimatedAngle); } - domAnimatedAngle.forget(aResult); - return NS_OK; + return domAnimatedAngle.forget(); } SVGAnimatedAngle::~SVGAnimatedAngle() @@ -366,7 +362,7 @@ nsISMILAttr* nsSVGAngle::ToSMILAttr(nsSVGElement *aSVGElement) { if (aSVGElement->NodeInfo()->Equals(nsGkAtoms::marker, kNameSpaceID_SVG)) { - nsSVGMarkerElement *marker = static_cast(aSVGElement); + SVGMarkerElement *marker = static_cast(aSVGElement); return new SMILOrient(marker->GetOrientType(), this, aSVGElement); } // SMILOrient would not be useful for general angle attributes (also, diff --git a/content/svg/content/src/nsSVGAngle.h b/content/svg/content/src/nsSVGAngle.h index 6a9bd5c887e..9a9dc3fc9ac 100644 --- a/content/svg/content/src/nsSVGAngle.h +++ b/content/svg/content/src/nsSVGAngle.h @@ -16,7 +16,6 @@ class nsISMILAnimationElement; class nsSMILValue; -class nsSVGOrientType; namespace mozilla { @@ -28,6 +27,7 @@ static const unsigned short SVG_ANGLETYPE_RAD = 3; static const unsigned short SVG_ANGLETYPE_GRAD = 4; namespace dom { +class nsSVGOrientType; class SVGAngle; class SVGAnimatedAngle; } @@ -68,8 +68,8 @@ public: float GetAnimValInSpecifiedUnits() const { return mAnimVal; } static nsresult ToDOMSVGAngle(nsISupports **aResult); - nsresult ToDOMAnimatedAngle(nsISupports **aResult, - nsSVGElement* aSVGElement); + already_AddRefed + ToDOMAnimatedAngle(nsSVGElement* aSVGElement); // Returns a new nsISMILAttr object that the caller must delete nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement); @@ -88,8 +88,8 @@ private: nsresult NewValueSpecifiedUnits(uint16_t aUnitType, float aValue, nsSVGElement *aSVGElement); nsresult ConvertToSpecifiedUnits(uint16_t aUnitType, nsSVGElement *aSVGElement); - nsresult ToDOMBaseVal(mozilla::dom::SVGAngle **aResult, nsSVGElement* aSVGElement); - nsresult ToDOMAnimVal(mozilla::dom::SVGAngle **aResult, nsSVGElement* aSVGElement); + already_AddRefed ToDOMBaseVal(nsSVGElement* aSVGElement); + already_AddRefed ToDOMAnimVal(nsSVGElement* aSVGElement); public: // We do not currently implemente a SMILAngle struct because in SVG 1.1 the @@ -100,7 +100,7 @@ public: struct SMILOrient MOZ_FINAL : public nsISMILAttr { public: - SMILOrient(nsSVGOrientType* aOrientType, + SMILOrient(mozilla::dom::nsSVGOrientType* aOrientType, nsSVGAngle* aAngle, nsSVGElement* aSVGElement) : mOrientType(aOrientType) @@ -111,7 +111,7 @@ public: // These will stay alive because a nsISMILAttr only lives as long // as the Compositing step, and DOM elements don't get a chance to // die during that. - nsSVGOrientType* mOrientType; + mozilla::dom::nsSVGOrientType* mOrientType; nsSVGAngle* mAngle; nsSVGElement* mSVGElement; diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index b0dd707c8dd..0f18a707614 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -104,9 +104,8 @@ #include "nsCCUncollectableMarker.h" #include "nsICSSDeclaration.h" -#include "mozilla/dom/XULElementBinding.h" - -using namespace mozilla; +namespace css = mozilla::css; +namespace dom = mozilla::dom; //---------------------------------------------------------------------- @@ -167,8 +166,6 @@ nsXULElement::nsXULElement(already_AddRefed aNodeInfo) { XUL_PROTOTYPE_ATTRIBUTE_METER(gNumElements); - SetIsDOMBinding(); - // We may be READWRITE by default; check. if (IsReadWriteTextElement()) { AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE); @@ -402,18 +399,12 @@ NS_IMETHODIMP nsXULElement::GetElementsByAttribute(const nsAString& aAttribute, const nsAString& aValue, nsIDOMNodeList** aReturn) -{ - *aReturn = GetElementsByAttribute(aAttribute, aValue).get(); - return NS_OK; -} - -already_AddRefed -nsXULElement::GetElementsByAttribute(const nsAString& aAttribute, - const nsAString& aValue) { nsCOMPtr attrAtom(do_GetAtom(aAttribute)); + NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY); void* attrValue = new nsString(aValue); - nsRefPtr list = + NS_ENSURE_TRUE(attrValue, NS_ERROR_OUT_OF_MEMORY); + nsContentList *list = new nsContentList(this, nsXULDocument::MatchAttribute, nsContentUtils::DestroyMatchString, @@ -421,7 +412,10 @@ nsXULElement::GetElementsByAttribute(const nsAString& aAttribute, true, attrAtom, kNameSpaceID_Unknown); - return list.forget(); + NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); + + NS_ADDREF(*aReturn = list); + return NS_OK; } NS_IMETHODIMP @@ -429,33 +423,22 @@ nsXULElement::GetElementsByAttributeNS(const nsAString& aNamespaceURI, const nsAString& aAttribute, const nsAString& aValue, nsIDOMNodeList** aReturn) -{ - ErrorResult rv; - *aReturn = - GetElementsByAttributeNS(aNamespaceURI, aAttribute, aValue, rv).get(); - return rv.ErrorCode(); -} - -already_AddRefed -nsXULElement::GetElementsByAttributeNS(const nsAString& aNamespaceURI, - const nsAString& aAttribute, - const nsAString& aValue, - ErrorResult& rv) { nsCOMPtr attrAtom(do_GetAtom(aAttribute)); + NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY); int32_t nameSpaceId = kNameSpaceID_Wildcard; if (!aNamespaceURI.EqualsLiteral("*")) { - rv = + nsresult rv = nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI, nameSpaceId); - if (rv.Failed()) { - return nullptr; - } + NS_ENSURE_SUCCESS(rv, rv); } void* attrValue = new nsString(aValue); - nsRefPtr list = + NS_ENSURE_TRUE(attrValue, NS_ERROR_OUT_OF_MEMORY); + + nsContentList *list = new nsContentList(this, nsXULDocument::MatchAttribute, nsContentUtils::DestroyMatchString, @@ -463,8 +446,10 @@ nsXULElement::GetElementsByAttributeNS(const nsAString& aNamespaceURI, true, attrAtom, nameSpaceId); + NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); - return list.forget(); + NS_ADDREF(*aReturn = list); + return NS_OK; } nsEventListenerManager* @@ -1190,14 +1175,6 @@ nsXULElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor) // XXX This _should_ be an implementation method, _not_ publicly exposed :-( NS_IMETHODIMP nsXULElement::GetResource(nsIRDFResource** aResource) -{ - ErrorResult rv; - *aResource = GetResource(rv).get(); - return rv.ErrorCode(); -} - -already_AddRefed -nsXULElement::GetResource(ErrorResult& rv) { nsAutoString id; GetAttr(kNameSpaceID_None, nsGkAtoms::ref, id); @@ -1205,57 +1182,44 @@ nsXULElement::GetResource(ErrorResult& rv) GetAttr(kNameSpaceID_None, nsGkAtoms::id, id); } - if (id.IsEmpty()) { - return nullptr; + if (!id.IsEmpty()) { + return nsXULContentUtils::RDFService()-> + GetUnicodeResource(id, aResource); } + *aResource = nullptr; - nsCOMPtr resource; - rv = nsXULContentUtils::RDFService()-> - GetUnicodeResource(id, getter_AddRefs(resource)); - return resource.forget(); + return NS_OK; } + NS_IMETHODIMP nsXULElement::GetDatabase(nsIRDFCompositeDataSource** aDatabase) { - *aDatabase = GetDatabase().get(); + nsCOMPtr builder; + GetBuilder(getter_AddRefs(builder)); + + if (builder) + builder->GetDatabase(aDatabase); + else + *aDatabase = nullptr; + return NS_OK; } -already_AddRefed -nsXULElement::GetDatabase() -{ - nsCOMPtr builder = GetBuilder(); - if (!builder) { - return nullptr; - } - - nsCOMPtr database; - builder->GetDatabase(getter_AddRefs(database)); - return database.forget(); -} - NS_IMETHODIMP nsXULElement::GetBuilder(nsIXULTemplateBuilder** aBuilder) { - *aBuilder = GetBuilder().get(); + *aBuilder = nullptr; + + // XXX sXBL/XBL2 issue! Owner or current document? + nsCOMPtr xuldoc = do_QueryInterface(GetCurrentDoc()); + if (xuldoc) + xuldoc->GetTemplateBuilderFor(this, aBuilder); + return NS_OK; } -already_AddRefed -nsXULElement::GetBuilder() -{ - // XXX sXBL/XBL2 issue! Owner or current document? - nsCOMPtr xuldoc = do_QueryInterface(GetCurrentDoc()); - if (!xuldoc) { - return nullptr; - } - - nsCOMPtr builder; - xuldoc->GetTemplateBuilderFor(this, getter_AddRefs(builder)); - return builder.forget(); -} //---------------------------------------------------------------------- // Implementation methods @@ -1304,46 +1268,30 @@ nsXULElement::IsAttributeMapped(const nsIAtom* aAttribute) const // Controllers Methods NS_IMETHODIMP nsXULElement::GetControllers(nsIControllers** aResult) -{ - ErrorResult rv; - NS_IF_ADDREF(*aResult = GetControllers(rv)); - return rv.ErrorCode(); -} - -nsIControllers* -nsXULElement::GetControllers(ErrorResult& rv) { if (! Controllers()) { nsDOMSlots* slots = DOMSlots(); + nsresult rv; rv = NS_NewXULControllers(nullptr, NS_GET_IID(nsIControllers), reinterpret_cast(&slots->mControllers)); - NS_ASSERTION(NS_SUCCEEDED(rv.ErrorCode()), - "unable to create a controllers"); - if (rv.Failed()) { - return nullptr; - } + NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a controllers"); + if (NS_FAILED(rv)) return rv; } - return Controllers(); + *aResult = Controllers(); + NS_IF_ADDREF(*aResult); + return NS_OK; } NS_IMETHODIMP nsXULElement::GetBoxObject(nsIBoxObject** aResult) { - ErrorResult rv; - *aResult = GetBoxObject(rv).get(); - return rv.ErrorCode(); -} + *aResult = nullptr; -already_AddRefed -nsXULElement::GetBoxObject(ErrorResult& rv) -{ - nsCOMPtr boxObject; - // XXX sXBL/XBL2 issue! Owner or current document? - rv = OwnerDoc()->GetBoxObjectFor(this, getter_AddRefs(boxObject)); - return boxObject.forget(); + // XXX sXBL/XBL2 issue! Owner or current document? + return OwnerDoc()->GetBoxObjectFor(this, aResult); } // Methods for setting/getting attributes from nsIDOMXULElement @@ -1363,19 +1311,26 @@ nsXULElement::GetBoxObject(ErrorResult& rv) #define NS_IMPL_XUL_BOOL_ATTR(_method, _atom) \ NS_IMETHODIMP \ - nsXULElement::Get##_method(bool* aResult) \ + nsXULElement::Get##_method(bool* aResult) \ { \ - *aResult = _method(); \ + *aResult = BoolAttrIsTrue(nsGkAtoms::_atom); \ + \ return NS_OK; \ } \ NS_IMETHODIMP \ - nsXULElement::Set##_method(bool aValue) \ + nsXULElement::Set##_method(bool aValue) \ { \ - SetXULBoolAttr(nsGkAtoms::_atom, aValue); \ - return NS_OK; \ + if (aValue) \ + SetAttr(kNameSpaceID_None, nsGkAtoms::_atom, \ + NS_LITERAL_STRING("true"), true); \ + else \ + UnsetAttr(kNameSpaceID_None, nsGkAtoms::_atom, true); \ + \ + return NS_OK; \ } +NS_IMPL_XUL_STRING_ATTR(Id, id) NS_IMPL_XUL_STRING_ATTR(ClassName, _class) NS_IMPL_XUL_STRING_ATTR(Align, align) NS_IMPL_XUL_STRING_ATTR(Dir, dir) @@ -1463,32 +1418,24 @@ nsXULElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner) nsXULElement* otherEl = FromContent(otherContent); NS_ENSURE_TRUE(otherEl, NS_ERROR_NOT_IMPLEMENTED); - ErrorResult rv; - SwapFrameLoaders(*otherEl, rv); - return rv.ErrorCode(); -} - -void -nsXULElement::SwapFrameLoaders(nsXULElement& aOtherElement, ErrorResult& rv) -{ - if (&aOtherElement == this) { + if (otherEl == this) { // nothing to do - return; + return NS_OK; } nsXULSlots *ourSlots = static_cast(GetExistingDOMSlots()); nsXULSlots *otherSlots = - static_cast(aOtherElement.GetExistingDOMSlots()); + static_cast(otherEl->GetExistingDOMSlots()); if (!ourSlots || !ourSlots->mFrameLoader || !otherSlots || !otherSlots->mFrameLoader) { // Can't handle swapping when there is nothing to swap... yet. - rv.Throw(NS_ERROR_NOT_IMPLEMENTED); - return; + return NS_ERROR_NOT_IMPLEMENTED; } - rv = ourSlots->mFrameLoader->SwapWithOtherLoader(otherSlots->mFrameLoader, - ourSlots->mFrameLoader, - otherSlots->mFrameLoader); + return + ourSlots->mFrameLoader->SwapWithOtherLoader(otherSlots->mFrameLoader, + ourSlots->mFrameLoader, + otherSlots->mFrameLoader); } NS_IMETHODIMP @@ -1511,45 +1458,27 @@ nsXULElement::GetParentTree(nsIDOMXULMultiSelectControlElement** aTreeElement) NS_IMETHODIMP nsXULElement::Focus() -{ - ErrorResult rv; - Focus(rv); - return rv.ErrorCode(); -} - -void -nsXULElement::Focus(ErrorResult& rv) { nsIFocusManager* fm = nsFocusManager::GetFocusManager(); nsCOMPtr elem = do_QueryObject(this); - if (fm) { - rv = fm->SetFocus(this, 0); - } + return fm ? fm->SetFocus(this, 0) : NS_OK; } NS_IMETHODIMP nsXULElement::Blur() -{ - ErrorResult rv; - Blur(rv); - return rv.ErrorCode(); -} - -void -nsXULElement::Blur(ErrorResult& rv) { if (!ShouldBlur(this)) - return; + return NS_OK; nsIDocument* doc = GetCurrentDoc(); if (!doc) - return; + return NS_OK; nsIDOMWindow* win = doc->GetWindow(); nsIFocusManager* fm = nsFocusManager::GetFocusManager(); - if (win && fm) { - rv = fm->ClearFocus(win); - } + if (win && fm) + return fm->ClearFocus(win); + return NS_OK; } NS_IMETHODIMP @@ -1558,12 +1487,6 @@ nsXULElement::Click() return ClickWithInputSource(nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN); } -void -nsXULElement::Click(ErrorResult& rv) -{ - rv = Click(); -} - nsresult nsXULElement::ClickWithInputSource(uint16_t aInputSource) { @@ -1869,7 +1792,7 @@ nsXULElement::ResetChromeMargins() } bool -nsXULElement::BoolAttrIsTrue(nsIAtom* aName) const +nsXULElement::BoolAttrIsTrue(nsIAtom* aName) { const nsAttrValue* attr = GetAttrInfo(kNameSpaceID_None, aName).mValue; @@ -1907,12 +1830,6 @@ nsXULElement::IsEventAttributeName(nsIAtom *aName) return nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL); } -JSObject* -nsXULElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap) -{ - return dom::XULElementBinding::Wrap(aCx, aScope, this, aTriedToWrap); -} - NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULPrototypeNode) if (tmp->mType == nsXULPrototypeNode::eType_Element) { static_cast(tmp)->Unlink(); diff --git a/content/xul/content/src/nsXULElement.h b/content/xul/content/src/nsXULElement.h index c8d08481aa0..9c8baa38f43 100644 --- a/content/xul/content/src/nsXULElement.h +++ b/content/xul/content/src/nsXULElement.h @@ -37,8 +37,6 @@ #include "nsDOMScriptObjectHolder.h" #include "nsIFrameLoader.h" #include "jspubtd.h" -#include "nsGenericHTMLElement.h" -#include "nsFrameLoader.h" class nsIDocument; class nsString; @@ -395,9 +393,6 @@ public: // nsIDOMNode NS_FORWARD_NSIDOMNODE_TO_NSINODE - // And since that shadowed GetParentElement with the XPCOM - // signature, pull in the one we care about. - using nsStyledElement::GetParentElement; // nsIDOMElement NS_FORWARD_NSIDOMELEMENT_TO_GENERIC @@ -409,6 +404,7 @@ public: virtual nsEventStates IntrinsicState() const; nsresult GetFrameLoader(nsIFrameLoader** aFrameLoader); + already_AddRefed GetFrameLoader(); nsresult SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner); virtual void RecompileScriptEventListeners(); @@ -427,169 +423,6 @@ public: virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE; - void SetXULAttr(nsIAtom* aName, const nsAString& aValue, - mozilla::ErrorResult& aError) - { - aError = SetAttr(kNameSpaceID_None, aName, aValue, true); - } - void SetXULBoolAttr(nsIAtom* aName, bool aValue) - { - if (aValue) { - SetAttr(kNameSpaceID_None, aName, NS_LITERAL_STRING("true"), true); - } else { - UnsetAttr(kNameSpaceID_None, aName, true); - } - } - - // WebIDL API - // The XPCOM getter is fine for our string attributes. - // The XPCOM setter is fine for our bool attributes. - void SetClassName(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::_class, aValue, rv); - } - void SetAlign(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::align, aValue, rv); - } - void SetDir(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::dir, aValue, rv); - } - void SetFlex(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::flex, aValue, rv); - } - void SetFlexGroup(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::flexgroup, aValue, rv); - } - void SetOrdinal(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::ordinal, aValue, rv); - } - void SetOrient(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::orient, aValue, rv); - } - void SetPack(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::pack, aValue, rv); - } - bool Hidden() const - { - return BoolAttrIsTrue(nsGkAtoms::hidden); - } - bool Collapsed() const - { - return BoolAttrIsTrue(nsGkAtoms::collapsed); - } - void SetObserves(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::observes, aValue, rv); - } - void SetMenu(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::menu, aValue, rv); - } - void SetContextMenu(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::contextmenu, aValue, rv); - } - void SetTooltip(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::tooltip, aValue, rv); - } - void SetWidth(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::width, aValue, rv); - } - void SetHeight(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::height, aValue, rv); - } - void SetMinWidth(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::minwidth, aValue, rv); - } - void SetMinHeight(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::minheight, aValue, rv); - } - void SetMaxWidth(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::maxwidth, aValue, rv); - } - void SetMaxHeight(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::maxheight, aValue, rv); - } - void SetPersist(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::persist, aValue, rv); - } - void SetLeft(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::left, aValue, rv); - } - void SetTop(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::top, aValue, rv); - } - void SetDatasources(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::datasources, aValue, rv); - } - void SetRef(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::ref, aValue, rv); - } - void SetTooltipText(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::tooltiptext, aValue, rv); - } - void SetStatusText(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::statustext, aValue, rv); - } - bool AllowEvents() const - { - return BoolAttrIsTrue(nsGkAtoms::allowevents); - } - already_AddRefed GetDatabase(); - already_AddRefed GetBuilder(); - already_AddRefed GetResource(mozilla::ErrorResult& rv); - nsIControllers* GetControllers(mozilla::ErrorResult& rv); - already_AddRefed GetBoxObject(mozilla::ErrorResult& rv); - void Focus(mozilla::ErrorResult& rv); - void Blur(mozilla::ErrorResult& rv); - void Click(mozilla::ErrorResult& rv); - // The XPCOM DoCommand never fails, so it's OK for us. - already_AddRefed - GetElementsByAttribute(const nsAString& aAttribute, - const nsAString& aValue); - already_AddRefed - GetElementsByAttributeNS(const nsAString& aNamespaceURI, - const nsAString& aAttribute, - const nsAString& aValue, - mozilla::ErrorResult& rv); - // Style() inherited from nsStyledElement - already_AddRefed GetFrameLoader(); - void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& rv); - - // For XUL, the parent is the parent element, if any - nsINode* GetParentObject() const - { - Element* parent = GetParentElement(); - if (parent) { - return parent; - } - return nsStyledElement::GetParentObject(); - } - static bool PrefEnabled() - { - return nsGenericHTMLElement::PrefEnabled(); - } protected: // This can be removed if EnsureContentsGenerated dies. @@ -678,7 +511,7 @@ protected: } void UnregisterAccessKey(const nsAString& aOldValue); - bool BoolAttrIsTrue(nsIAtom* aName) const; + bool BoolAttrIsTrue(nsIAtom* aName); friend nsresult NS_NewXULElement(nsIContent** aResult, nsINodeInfo *aNodeInfo); @@ -697,9 +530,6 @@ protected: (tag == nsGkAtoms::textbox || tag == nsGkAtoms::textarea) && !HasAttr(kNameSpaceID_None, nsGkAtoms::readonly); } - - virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope, - bool *aTriedToWrap) MOZ_OVERRIDE; }; #endif // nsXULElement_h__ diff --git a/content/xul/document/src/nsXULPrototypeDocument.cpp b/content/xul/document/src/nsXULPrototypeDocument.cpp index e480f997c3f..cb55bc251e9 100644 --- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -478,10 +478,7 @@ nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream) NS_ENSURE_TRUE(nodeInfo, NS_ERROR_FAILURE); nsAutoString namespaceURI; - tmp = nodeInfo->GetNamespaceURI(namespaceURI); - if (NS_FAILED(tmp)) { - rv = tmp; - } + nodeInfo->GetNamespaceURI(namespaceURI); tmp = aStream->WriteWStringZ(namespaceURI.get()); if (NS_FAILED(tmp)) { rv = tmp; diff --git a/dom/apps/src/FreeSpaceWatcher.jsm b/dom/apps/src/FreeSpaceWatcher.jsm index b9b3f98895c..cfe95b58b6b 100644 --- a/dom/apps/src/FreeSpaceWatcher.jsm +++ b/dom/apps/src/FreeSpaceWatcher.jsm @@ -44,13 +44,13 @@ this.FreeSpaceWatcher = { try { let deviceStorage = Services.wm.getMostRecentWindow("navigator:browser") .navigator.getDeviceStorage("apps"); - let req = deviceStorage.stat(); + let req = deviceStorage.freeSpace(); req.onsuccess = req.onerror = function statResult(e) { if (!e.target.result) { return; } - let freeBytes = e.target.result.freeBytes; + let freeBytes = e.target.result; debug("Free bytes: " + freeBytes); let newStatus = freeBytes > aThreshold; if (newStatus != callback.currentStatus) { diff --git a/dom/apps/src/Webapps.jsm b/dom/apps/src/Webapps.jsm index e72a0ac4c14..e71bd2b9562 100644 --- a/dom/apps/src/Webapps.jsm +++ b/dom/apps/src/Webapps.jsm @@ -2265,7 +2265,7 @@ this.DOMApplicationRegistry = { let deviceStorage = Services.wm.getMostRecentWindow("navigator:browser") .navigator.getDeviceStorage("apps"); - let req = deviceStorage.stat(); + let req = deviceStorage.freeSpace(); req.onsuccess = req.onerror = function statResult(e) { // Even if we could not retrieve the device storage free space, we try // to download the package. @@ -2274,7 +2274,7 @@ this.DOMApplicationRegistry = { return; } - let freeBytes = e.target.result.freeBytes; + let freeBytes = e.target.result; if (freeBytes) { debug("Free storage: " + freeBytes + ". Download size: " + aApp.downloadSize); @@ -2298,8 +2298,10 @@ this.DOMApplicationRegistry = { dump("-- webapps.js uninstall " + app.manifestURL + "\n"); - if (!app.removable) - return; + if (!app.removable) { + debug("Error: cannot unintall a non-removable app."); + break; + } // Check if we are downloading something for this app, and cancel the // download if needed. @@ -2343,6 +2345,9 @@ this.DOMApplicationRegistry = { return; } + // Fall-through, fails to uninstall the desired app because: + // - we cannot find the app to be uninstalled. + // - the app to be uninstalled is not removable. aMm.sendAsyncMessage("Webapps:Uninstall:Return:KO", aData); }, diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index a6eda9a3591..6f8868923c9 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -335,7 +335,6 @@ #include "nsIDOMSVGEvent.h" #include "nsIDOMSVGFilterElement.h" #include "nsIDOMSVGFilters.h" -#include "nsIDOMSVGFitToViewBox.h" #include "nsIDOMSVGForeignObjectElem.h" #include "nsIDOMSVGGElement.h" #include "nsIDOMSVGGradientElement.h" @@ -358,7 +357,6 @@ #include "nsIDOMSVGSVGElement.h" #include "nsIDOMSVGSwitchElement.h" #include "nsIDOMSVGSymbolElement.h" -#include "nsIDOMSVGTests.h" #include "nsIDOMSVGTextElement.h" #include "nsIDOMSVGTextPathElement.h" #include "nsIDOMSVGTitleElement.h" @@ -2947,7 +2945,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(XULTreeBuilder, nsIXULTreeBuilder) DOM_CLASSINFO_MAP_ENTRY(nsIXULTreeBuilder) - DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder) DOM_CLASSINFO_MAP_ENTRY(nsITreeView) DOM_CLASSINFO_MAP_END #endif @@ -2992,7 +2989,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES #define DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES \ - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) \ DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES // XXX - the proto chain stuff is sort of hackish, because of the MI in @@ -3026,7 +3022,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGAnimateElement, nsIDOMSVGAnimateElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES @@ -3035,7 +3030,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGAnimateTransformElement, nsIDOMSVGAnimateTransformElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateTransformElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES @@ -3044,7 +3038,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGAnimateMotionElement, nsIDOMSVGAnimateMotionElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateMotionElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES @@ -3053,7 +3046,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGSetElement, nsIDOMSVGSetElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSetElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES @@ -3271,7 +3263,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGMarkerElement, nsIDOMSVGMarkerElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGMarkerElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END @@ -3293,7 +3284,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGPatternElement, nsIDOMSVGPatternElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGPatternElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUnitTypes) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES @@ -3341,7 +3331,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGSVGElement, nsIDOMSVGSVGElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSVGElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END @@ -3353,8 +3342,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGSymbolElement, nsIDOMSVGSymbolElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSymbolElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END @@ -3390,7 +3377,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(SVGViewElement, nsIDOMSVGViewElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END diff --git a/dom/base/nsWrapperCache.h b/dom/base/nsWrapperCache.h index 452ab1e05e2..44e358a1cc4 100644 --- a/dom/base/nsWrapperCache.h +++ b/dom/base/nsWrapperCache.h @@ -7,7 +7,6 @@ #define nsWrapperCache_h___ #include "nsCycleCollectionParticipant.h" -#include "mozilla/Assertions.h" class JSObject; struct JSContext; @@ -162,7 +161,6 @@ public: virtual JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap) { - MOZ_ASSERT(!IsDOMBinding(), "Someone forgot to override WrapObject"); *triedToWrap = false; return nullptr; } diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index aee9594ebb1..3971fc40cb3 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -575,9 +575,9 @@ QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp) return Throw(cx, NS_ERROR_XPC_BAD_CONVERT_JS); } - nsIJSID* iid; + nsIJSIID* iid; xpc_qsSelfRef iidRef; - if (NS_FAILED(xpc_qsUnwrapArg(cx, argv[0], &iid, &iidRef.ptr, + if (NS_FAILED(xpc_qsUnwrapArg(cx, argv[0], &iid, &iidRef.ptr, &argv[0]))) { return Throw(cx, NS_ERROR_XPC_BAD_CONVERT_JS); } diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 58044c17bb8..39a8ea13106 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -562,6 +562,7 @@ DOMInterfaces = { 'PaintRequest': { 'nativeType': 'nsPaintRequest', + 'prefable': True }, 'PaintRequestList': { @@ -612,6 +613,7 @@ DOMInterfaces = { 'Screen': { 'nativeType': 'nsScreen', + 'prefable': True, }, 'SVGAElement': { @@ -1011,12 +1013,6 @@ DOMInterfaces = { 'wrapperCache': False }, -'XULElement': { - 'nativeType': 'nsXULElement', - 'resultNotAddRefed': [ 'controllers', 'style' ], - 'hasInstanceInterface': 'nsIDOMXULElement', -}, - #################################### # Test Interfaces of various sorts # #################################### @@ -1220,13 +1216,6 @@ addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserve addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True) addExternalIface('LockedFile') addExternalIface('MediaStream') -addExternalIface('MozBoxObject', nativeType='nsIBoxObject') -addExternalIface('MozControllers', nativeType='nsIControllers') -addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True) -addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource', - notflattened=True) -addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True) -addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder') addExternalIface('NamedNodeMap') addExternalIface('NodeIterator') addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True) @@ -1255,3 +1244,4 @@ addExternalIface('WindowProxy', nativeType='nsIDOMWindow') addExternalIface('XPathResult', nativeType='nsISupports') addExternalIface('XPathExpression') addExternalIface('XPathNSResolver') +addExternalIface('XULElement') diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 4eb8cca1e47..acf9fb2193c 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -1825,13 +1825,18 @@ builtinNames = { IDLType.Tags.double: 'double' } -numericTags = [ - IDLType.Tags.int8, IDLType.Tags.uint8, - IDLType.Tags.int16, IDLType.Tags.uint16, - IDLType.Tags.int32, IDLType.Tags.uint32, - IDLType.Tags.int64, IDLType.Tags.uint64, - IDLType.Tags.float, IDLType.Tags.double - ] +numericSuffixes = { + IDLType.Tags.int8: '', + IDLType.Tags.uint8: '', + IDLType.Tags.int16: '', + IDLType.Tags.uint16: '', + IDLType.Tags.int32: '', + IDLType.Tags.uint32: 'U', + IDLType.Tags.int64: 'LL', + IDLType.Tags.uint64: 'ULL', + IDLType.Tags.float: 'F', + IDLType.Tags.double: 'D' +} class CastableObjectUnwrapper(): """ @@ -2987,8 +2992,9 @@ for (uint32_t i = 0; i < length; ++i) { # We already handled IDLNullValue, so just deal with the other ones not isinstance(defaultValue, IDLNullValue)): tag = defaultValue.type.tag() - if tag in numericTags: - defaultStr = defaultValue.value + if tag in numericSuffixes: + # Some numeric literals require a suffix to compile without warnings + defaultStr = "%s%s" % (defaultValue.value, numericSuffixes[tag]) else: assert(tag == IDLType.Tags.bool) defaultStr = toStringBool(defaultValue.value) @@ -3093,9 +3099,9 @@ def convertConstIDLValueToJSVal(value): IDLType.Tags.uint16, IDLType.Tags.int32]: return "INT_TO_JSVAL(%s)" % (value.value) if tag == IDLType.Tags.uint32: - return "UINT_TO_JSVAL(%s)" % (value.value) + return "UINT_TO_JSVAL(%sU)" % (value.value) if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]: - return "DOUBLE_TO_JSVAL(%s)" % (value.value) + return "DOUBLE_TO_JSVAL(%s%s)" % (value.value, numericSuffixes[tag]) if tag == IDLType.Tags.bool: return "JSVAL_TRUE" if value.value else "JSVAL_FALSE" if tag in [IDLType.Tags.float, IDLType.Tags.double]: @@ -4547,11 +4553,13 @@ class CGMemberJITInfo(CGThing): return "" def defineJitInfo(self, infoName, opName, opType, infallible, constant, - returnTypes): + pure, returnTypes): + assert(not constant or pure) # constants are always pure protoID = "prototypes::id::%s" % self.descriptor.name depth = "PrototypeTraits<%s>::Depth" % protoID failstr = toStringBool(infallible) conststr = toStringBool(constant) + purestr = toStringBool(pure) returnType = reduce(CGMemberJITInfo.getSingleReturnType, returnTypes, "") return ("\n" @@ -4562,26 +4570,30 @@ class CGMemberJITInfo(CGThing): " JSJitInfo::%s,\n" " %s, /* isInfallible. False in setters. */\n" " %s, /* isConstant. Only relevant for getters. */\n" + " %s, /* isPure. Only relevant for getters. */\n" " %s /* returnType. Only relevant for getters/methods. */\n" "};\n" % (infoName, opName, protoID, depth, opType, failstr, - conststr, returnType)) + conststr, purestr, returnType)) def define(self): if self.member.isAttr(): getterinfo = ("%s_getterinfo" % self.member.identifier.name) getter = ("(JSJitPropertyOp)get_%s" % self.member.identifier.name) getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True) - getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor) getterconst = self.member.getExtendedAttribute("Constant") + getterpure = getterconst or self.member.getExtendedAttribute("Pure") + assert (getterinfal or (not getterconst and not getterpure)) + + getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor) result = self.defineJitInfo(getterinfo, getter, "Getter", - getterinfal, getterconst, + getterinfal, getterconst, getterpure, [self.member.type]) if not self.member.readonly or self.member.getExtendedAttribute("PutForwards") is not None: setterinfo = ("%s_setterinfo" % self.member.identifier.name) setter = ("(JSJitPropertyOp)set_%s" % self.member.identifier.name) # Setters are always fallible, since they have to do a typed unwrap. result += self.defineJitInfo(setterinfo, setter, "Setter", - False, False, + False, False, False, [BuiltinTypes[IDLBuiltinType.Types.void]]) return result if self.member.isMethod(): @@ -4593,18 +4605,22 @@ class CGMemberJITInfo(CGThing): # Methods are infallible if they are infallible, have no arguments # to unwrap, and have a return type that's infallible to wrap up for # return. - methodInfal = False sigs = self.member.signatures() - if len(sigs) == 1: - # Don't handle overloading. If there's more than one signature, + if len(sigs) != 1: + # Don't handle overloading. If there's more than one signature, # one of them must take arguments. + methodInfal = False + else: sig = sigs[0] - if len(sig[1]) == 0 and infallibleForMember(self.member, sig[0], self.descriptor): - # No arguments and infallible return boxing - methodInfal = True + if (len(sig[1]) != 0 or + not infallibleForMember(self.member, sig[0], self.descriptor)): + # We have arguments or our return-value boxing can fail + methodInfal = False + else: + methodInfal = "infallible" in self.descriptor.getExtendedAttributes(self.member) result = self.defineJitInfo(methodinfo, method, "Method", - methodInfal, False, + methodInfal, False, False, [s[0] for s in sigs]) return result raise TypeError("Illegal member type to CGPropertyJITInfo") diff --git a/dom/bindings/Makefile.in b/dom/bindings/Makefile.in index ca93381593f..e6d52c46cc7 100644 --- a/dom/bindings/Makefile.in +++ b/dom/bindings/Makefile.in @@ -12,6 +12,7 @@ LIBRARY_NAME = dombindings_s LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 EXPORT_LIBRARY = 1 +FAIL_ON_WARNINGS := 1 include $(topsrcdir)/config/config.mk include $(topsrcdir)/ipc/chromium/chromium-config.mk @@ -86,7 +87,6 @@ LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src \ -I$(topsrcdir)/content/xslt/src/base \ -I$(topsrcdir)/content/xslt/src/xpath \ -I$(topsrcdir)/content/xml/content/src \ - -I$(topsrcdir)/content/xul/content/src \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index 825eb83e4dc..90c3da15560 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -2194,6 +2194,14 @@ class IDLAttribute(IDLInterfaceMember): raise WebIDLError("Readonly attributes must not be flagged as " "[SetterThrows]", [self.location]) + elif (((identifier == "Throws" or identifier == "GetterThrows") and + (self.getExtendedAttribute("Pure") or + self.getExtendedAttribute("Constant"))) or + ((identifier == "Pure" or identifier == "Constant") and + (self.getExtendedAttribute("Throws") or + self.getExtendedAttribute("GetterThrows")))): + raise WebIDLError("Throwing things can't be [Pure] or [Constant]", + [attr.location]) elif identifier == "LenientThis": if not attr.noArguments(): raise WebIDLError("[LenientThis] must take no arguments", @@ -2736,8 +2744,11 @@ class IDLMethod(IDLInterfaceMember, IDLScope): "[Unforgeable]", [attr.location, self.location]) elif identifier == "Constant": - raise WebIDLError("Methods must not be flagged as " - "[Constant]", + raise WebIDLError("Methods must not be flagged as [Constant]", + [attr.location, self.location]); + elif identifier == "Pure": + raise WebIDLError("Methods must not be flagged as [Pure] and if " + "that changes, don't forget to check for [Throws]", [attr.location, self.location]); elif identifier == "PutForwards": raise WebIDLError("Only attributes support [PutForwards]", diff --git a/dom/bluetooth/BluetoothHfpManager.cpp b/dom/bluetooth/BluetoothHfpManager.cpp index c33aa57adb9..1b4d1804a9f 100644 --- a/dom/bluetooth/BluetoothHfpManager.cpp +++ b/dom/bluetooth/BluetoothHfpManager.cpp @@ -671,7 +671,7 @@ BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage) { MOZ_ASSERT(NS_IsMainThread()); - nsAutoCString msg((const char*)aMessage->mData.get()); + nsAutoCString msg((const char*)aMessage->mData.get(), aMessage->mSize); msg.StripWhitespace(); nsTArray atCommandValues; @@ -679,7 +679,7 @@ BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage) // For more information, please refer to 4.34.1 "Bluetooth Defined AT // Capabilities" in Bluetooth hands-free profile 1.6 if (msg.Find("AT+BRSF=") != -1) { - SendCommand("+BRSF: ", 33); + SendCommand("+BRSF: ", 97); } else if (msg.Find("AT+CIND=?") != -1) { // Asking for CIND range SendCommand("+CIND: ", 0); diff --git a/dom/bluetooth/BluetoothUtils.cpp b/dom/bluetooth/BluetoothUtils.cpp index 9fe6e7a9c35..5c14c3d395d 100644 --- a/dom/bluetooth/BluetoothUtils.cpp +++ b/dom/bluetooth/BluetoothUtils.cpp @@ -48,7 +48,7 @@ SetJsObject(JSContext* aContext, JS_NewStringCopyN(aContext, NS_ConvertUTF16toUTF8(v.get_nsString()).get(), v.get_nsString().Length()); - NS_ENSURE_TRUE(JsData, NS_ERROR_FAILURE); + NS_ENSURE_TRUE(JsData, false); val = STRING_TO_JSVAL(JsData); break; case BluetoothValue::Tuint32_t: @@ -66,7 +66,7 @@ SetJsObject(JSContext* aContext, NS_ConvertUTF16toUTF8(arr[i].name()).get(), &val)) { NS_WARNING("Failed to set property"); - return NS_ERROR_FAILURE; + return false; } } } else { diff --git a/dom/icc/interfaces/SimToolKit.idl b/dom/icc/interfaces/SimToolKit.idl index fc3de08df49..f80071a7fec 100644 --- a/dom/icc/interfaces/SimToolKit.idl +++ b/dom/icc/interfaces/SimToolKit.idl @@ -592,14 +592,31 @@ dictionary MozStkLocalInfo DOMString language; }; +dictionary MozStkLanguageSelectionEvent +{ + /** + * The type of this event. + * It shall be nsIDOMMozIccManager.STK_EVENT_TYPE_LANGUAGE_SELECTION. + */ + unsigned short eventType; + + /** + * Language Information + * + * @see ISO 639-1, Alpha-2 code + * "de" for German, "en" for English, "zh" for Chinese, etc. + */ + DOMString language; +}; + dictionary MozStkGeneralEvent { /** * The type of this event, MozStkGeneralEvent can be used for all Stk Event * requires no more parameter than event type, including - * nsIDOMMozIccManager.STK_EVENT_TYPE_USER_ACTIVITY - * nsIDOMMozIccManager.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE - * HCI Connectivity Event(Not defined in interface yet) + * nsIDOMMozIccManager.STK_EVENT_TYPE_USER_ACTIVITY. + * nsIDOMMozIccManager.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE. + * HCI Connectivity Event(Not defined in interface yet). */ unsigned short eventType; }; diff --git a/dom/icc/interfaces/nsIDOMIccManager.idl b/dom/icc/interfaces/nsIDOMIccManager.idl index 2c040acedfb..51bbb2724ea 100644 --- a/dom/icc/interfaces/nsIDOMIccManager.idl +++ b/dom/icc/interfaces/nsIDOMIccManager.idl @@ -256,6 +256,8 @@ interface nsIDOMMozIccManager : nsIDOMEventTarget * one of events below: * - MozStkLocationEvent * - MozStkCallEvent + * - MozStkLanguageSelectionEvent + * - MozStkGeneralEvent */ void sendStkEventDownload(in jsval event); diff --git a/dom/interfaces/svg/Makefile.in b/dom/interfaces/svg/Makefile.in index 5249d1b865e..cf25cab7192 100644 --- a/dom/interfaces/svg/Makefile.in +++ b/dom/interfaces/svg/Makefile.in @@ -39,7 +39,6 @@ XPIDLSRCS = \ nsIDOMSVGEvent.idl \ nsIDOMSVGFilterElement.idl \ nsIDOMSVGFilters.idl \ - nsIDOMSVGFitToViewBox.idl \ nsIDOMSVGForeignObjectElem.idl \ nsIDOMSVGGElement.idl \ nsIDOMSVGGradientElement.idl \ @@ -65,7 +64,6 @@ XPIDLSRCS = \ nsIDOMSVGStyleElement.idl \ nsIDOMSVGSwitchElement.idl \ nsIDOMSVGSymbolElement.idl \ - nsIDOMSVGTests.idl \ nsIDOMSVGTextContentElement.idl \ nsIDOMSVGTextElement.idl \ nsIDOMSVGTextPathElement.idl \ diff --git a/dom/interfaces/svg/nsIDOMSVGFitToViewBox.idl b/dom/interfaces/svg/nsIDOMSVGFitToViewBox.idl deleted file mode 100644 index bf5f87e7caf..00000000000 --- a/dom/interfaces/svg/nsIDOMSVGFitToViewBox.idl +++ /dev/null @@ -1,15 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "domstubs.idl" - -interface nsIDOMSVGAnimatedRect; - -[scriptable, uuid(089410F3-9777-44f1-A882-AB4225696434)] -interface nsIDOMSVGFitToViewBox : nsISupports -{ - readonly attribute nsIDOMSVGAnimatedRect viewBox; - readonly attribute nsISupports preserveAspectRatio; -}; diff --git a/dom/interfaces/svg/nsIDOMSVGTests.idl b/dom/interfaces/svg/nsIDOMSVGTests.idl deleted file mode 100644 index 0dd35852010..00000000000 --- a/dom/interfaces/svg/nsIDOMSVGTests.idl +++ /dev/null @@ -1,17 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsIDOMSVGStringList.idl" - -[scriptable, uuid(b6186ed0-0861-11e1-be50-0800200c9a66)] -interface nsIDOMSVGTests : nsISupports -{ - readonly attribute nsIDOMSVGStringList requiredFeatures; - readonly attribute nsIDOMSVGStringList requiredExtensions; - readonly attribute nsIDOMSVGStringList systemLanguage; - - boolean hasExtension(in DOMString extension); -}; - diff --git a/dom/interfaces/xul/nsIDOMXULElement.idl b/dom/interfaces/xul/nsIDOMXULElement.idl index de52acc82d5..dffd1ac1468 100644 --- a/dom/interfaces/xul/nsIDOMXULElement.idl +++ b/dom/interfaces/xul/nsIDOMXULElement.idl @@ -12,9 +12,10 @@ interface nsIControllers; interface nsIBoxObject; -[scriptable, uuid(bece5b0b-6e59-4de5-98d0-088adfd1cadc)] +[scriptable, uuid(3a07dead-39e5-4dad-bc68-6ef369994126)] interface nsIDOMXULElement : nsIDOMElement { + attribute DOMString id; attribute DOMString className; // Layout properties diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 97a6c1eeed0..e85d1dfe970 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -11,6 +11,8 @@ #include "nsIScriptGlobalObject.h" #include "nsIPopupWindowManager.h" #include "nsISupportsArray.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" // For PR_snprintf #include "prprf.h" @@ -382,6 +384,33 @@ public: mAudioSource, mVideoSource, false)); mediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); +#ifdef MOZ_WEBRTC + // Right now these configs are only of use if webrtc is available + nsresult rv; + nsCOMPtr prefs = do_GetService("@mozilla.org/preferences-service;1", &rv); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr branch = do_QueryInterface(prefs); + + if (branch) { + int32_t aec = (int32_t) webrtc::kEcUnchanged; + int32_t agc = (int32_t) webrtc::kAgcUnchanged; + int32_t noise = (int32_t) webrtc::kNsUnchanged; + bool aec_on = false, agc_on = false, noise_on = false; + + branch->GetBoolPref("media.peerconnection.aec_enabled", &aec_on); + branch->GetIntPref("media.peerconnection.aec", &aec); + branch->GetBoolPref("media.peerconnection.agc_enabled", &agc_on); + branch->GetIntPref("media.peerconnection.agc", &agc); + branch->GetBoolPref("media.peerconnection.noise_enabled", &noise_on); + branch->GetIntPref("media.peerconnection.noise", &noise); + + mListener->AudioConfig(aec_on, (uint32_t) aec, + agc_on, (uint32_t) agc, + noise_on, (uint32_t) noise); + } + } +#endif + // We're in the main thread, so no worries here either. nsCOMPtr success(mSuccess); nsCOMPtr error(mError); diff --git a/dom/media/MediaManager.h b/dom/media/MediaManager.h index fc1263d8a25..74795b02f3b 100644 --- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -21,6 +21,10 @@ #include "mozilla/StaticPtr.h" #include "prlog.h" +#ifdef MOZ_WEBRTC +#include "mtransport/runnable_utils.h" +#endif + namespace mozilla { #ifdef PR_LOGGING @@ -128,6 +132,23 @@ public: // Can be invoked from EITHER MainThread or MSG thread void Invalidate(); + void + AudioConfig(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) + { + if (mAudioSource) { +#ifdef MOZ_WEBRTC + // Right now these configs are only of use if webrtc is available + RUN_ON_THREAD(mMediaThread, + WrapRunnable(nsRefPtr(mAudioSource), // threadsafe + &MediaEngineSource::Config, + aEchoOn, aEcho, aAgcOn, aAGC, aNoiseOn, aNoise), + NS_DISPATCH_NORMAL); +#endif + } + } + void Remove() { diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index b6d118ef0b0..6c680d7bd9b 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -1237,8 +1237,12 @@ RadioInterfaceLayer.prototype = { call.isActive = false; if (this._activeCall && this._activeCall.callIndex == call.callIndex) { - // Previously active call is not active now. Disable audio. + // Previously active call is not active now. this._activeCall = null; + } + + if (!this._activeCall) { + // No active call. Disable the audio. gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL; debug("No active call, put audio system into PHONE_STATE_NORMAL: " + gAudioManager.phoneState); diff --git a/dom/system/gonk/ril_consts.js b/dom/system/gonk/ril_consts.js index 155c39cc80a..c26b4457cf7 100644 --- a/dom/system/gonk/ril_consts.js +++ b/dom/system/gonk/ril_consts.js @@ -907,6 +907,11 @@ this.STK_TERMINAL_SUPPORT_EVENT_USER_ACTIVITY = 0; this.STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE = 1; this.STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS = 0; +this.STK_TERMINAL_SUPPORT_EVENT_LANGUAGE_SELECTION = 1; +this.STK_TERMINAL_SUPPORT_EVENT_BROWSER_TERMINATION = 0; +this.STK_TERMINAL_SUPPORT_EVENT_DATA_AVAILABLE = 0; +this.STK_TERMINAL_SUPPORT_EVENT_CHANNEL_STATUS = 0; + this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP = 1; this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT = 1; this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_DATE = 1; @@ -925,6 +930,11 @@ this.STK_TERMINAL_SUPPORT_PROACTIVE_LANGUAGE_NOTIFICATION = 0; this.STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER = 1; this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH = 0; +/** + * SAT profile + * + * @see ETSI TS 101.267, section 5.2. + */ this.STK_TERMINAL_PROFILE_DOWNLOAD = (STK_TERMINAL_SUPPORT_PROFILE_DOWNLOAD << 0) | (STK_TERMINAL_SUPPORT_SMS_PP_DOWNLOAD << 1) | @@ -975,6 +985,12 @@ this.STK_TERMINAL_PROFILE_EVENT = (STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE << 6) | (STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS << 7); +this.STK_TERMINAL_PROFILE_EVENT_EXT = + (STK_TERMINAL_SUPPORT_EVENT_LANGUAGE_SELECTION << 0) | + (STK_TERMINAL_SUPPORT_EVENT_BROWSER_TERMINATION << 1) | + (STK_TERMINAL_SUPPORT_EVENT_DATA_AVAILABLE << 2) | + (STK_TERMINAL_SUPPORT_EVENT_CHANNEL_STATUS << 3); + this.STK_TERMINAL_PROFILE_PROACTIVE_3 = (STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP << 0) | (STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT << 1) | @@ -1001,7 +1017,7 @@ this.STK_SUPPORTED_TERMINAL_PROFILE = [ STK_TERMINAL_PROFILE_PROACTIVE_1, STK_TERMINAL_PROFILE_PROACTIVE_2, STK_TERMINAL_PROFILE_EVENT, - 0x00, // Event extension + STK_TERMINAL_PROFILE_EVENT_EXT, // Event extension 0x00, // Multiple card proactive commands STK_TERMINAL_PROFILE_PROACTIVE_3, STK_TERMINAL_PROFILE_PROACTIVE_4, diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index ca304107fae..534f3b347e6 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -2608,6 +2608,13 @@ let RIL = { destinationId: STK_DEVICE_ID_SIM }; break; + case STK_EVENT_TYPE_LANGUAGE_SELECTION: + command.deviceId = { + sourceId: STK_DEVICE_ID_ME, + destinationId: STK_DEVICE_ID_SIM + }; + command.language = command.event.language; + break; } this.sendICCEnvelopeCommand(command); }, @@ -2729,6 +2736,11 @@ let RIL = { ComprehensionTlvHelper.writeTimerValueTlv(options.timerValue, true); } + // Language + if (options.language) { + ComprehensionTlvHelper.writeLanguageTlv(options.language); + } + // Calculate and write BER length to 2nd mark Buf.stopCalOutgoingSize(); diff --git a/dom/system/gonk/tests/test_ril_worker_icc.js b/dom/system/gonk/tests/test_ril_worker_icc.js index b8ceafcb33a..d7fc994ea49 100644 --- a/dom/system/gonk/tests/test_ril_worker_icc.js +++ b/dom/system/gonk/tests/test_ril_worker_icc.js @@ -1514,6 +1514,64 @@ add_test(function test_stk_terminal_response() { worker.RIL.sendStkTerminalResponse(response); }); +/** + * Verify Event Download Command : Language Selection + */ +add_test(function test_stk_event_download_language_selection() { + let worker = newUint8SupportOutgoingIndexWorker(); + let buf = worker.Buf; + let pduHelper = worker.GsmPDUHelper; + + buf.sendParcel = function () { + // Type + do_check_eq(this.readUint32(), REQUEST_STK_SEND_ENVELOPE_COMMAND) + + // Token : we don't care + this.readUint32(); + + // Data Size, 26 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) + + // TLV_EVENT_LIST_SIZE(3) + + // TLV_LANGUAGE(4)) + do_check_eq(this.readUint32(), 26); + + // BER tag + do_check_eq(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG); + + // BER length, 19 = TLV_DEVICE_ID_SIZE(4) + + // TLV_EVENT_LIST_SIZE(3) + + // TLV_LANGUAGE(4) + do_check_eq(pduHelper.readHexOctet(), 11); + + // Device Identifies, Type-Length-Value(Source ID-Destination ID) + do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID | + COMPREHENSIONTLV_FLAG_CR); + do_check_eq(pduHelper.readHexOctet(), 2); + do_check_eq(pduHelper.readHexOctet(), STK_DEVICE_ID_ME); + do_check_eq(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM); + + // Event List, Type-Length-Value + do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST | + COMPREHENSIONTLV_FLAG_CR); + do_check_eq(pduHelper.readHexOctet(), 1); + do_check_eq(pduHelper.readHexOctet(), STK_EVENT_TYPE_LANGUAGE_SELECTION); + + // Language, Type-Length-Value + do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_LANGUAGE); + do_check_eq(pduHelper.readHexOctet(), 2); + do_check_eq(pduHelper.read8BitUnpackedToString(2), "zh"); + + run_next_test(); + }; + + let event = { + eventType: STK_EVENT_TYPE_LANGUAGE_SELECTION, + language: "zh" + }; + worker.RIL.sendStkEventDownload({ + event: event + }); +}); + /** * Verify Event Download Command : Idle Screen Available */ diff --git a/dom/tests/mochitest/webapps/Makefile.in b/dom/tests/mochitest/webapps/Makefile.in index 5cd517b9ec6..8ca51182ac6 100644 --- a/dom/tests/mochitest/webapps/Makefile.in +++ b/dom/tests/mochitest/webapps/Makefile.in @@ -28,6 +28,7 @@ MOCHITEST_CHROME_FILES = \ test_install_receipts.xul \ test_getNotInstalled.xul \ test_launch_paths.xul \ + test_uninstall_errors.xul \ $(NULL) MOCHITEST_FILES = \ diff --git a/dom/tests/mochitest/webapps/test_uninstall_errors.xul b/dom/tests/mochitest/webapps/test_uninstall_errors.xul new file mode 100644 index 00000000000..c537b7394a8 --- /dev/null +++ b/dom/tests/mochitest/webapps/test_uninstall_errors.xul @@ -0,0 +1,82 @@ + + + + + + + + + + diff --git a/dom/webidl/CanvasRenderingContext2D.webidl b/dom/webidl/CanvasRenderingContext2D.webidl index 8711b330a83..046952ceb54 100644 --- a/dom/webidl/CanvasRenderingContext2D.webidl +++ b/dom/webidl/CanvasRenderingContext2D.webidl @@ -18,6 +18,7 @@ interface HTMLCanvasElement; interface HTMLVideoElement; interface TextMetrics; interface Window; +interface XULElement; enum CanvasWindingRule { "nonzero", "evenodd" }; diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index d3b17a3f8fc..9412209d1af 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -31,7 +31,7 @@ enum VisibilityState { "hidden", "visible" }; /* http://dom.spec.whatwg.org/#interface-document */ [Constructor] interface Document : Node { - [Throws, Constant] + [Throws] readonly attribute DOMImplementation implementation; readonly attribute DOMString URL; readonly attribute DOMString documentURI; diff --git a/dom/webidl/Element.webidl b/dom/webidl/Element.webidl index 9469c40a6af..43c267a76a9 100644 --- a/dom/webidl/Element.webidl +++ b/dom/webidl/Element.webidl @@ -26,8 +26,10 @@ interface Element : Node { readonly attribute DOMString localName; */ // Not [Constant] because it depends on which document we're in + [Pure] readonly attribute DOMString tagName; + [Pure] attribute DOMString id; /* FIXME Bug 810677 Move className from HTMLElement to Element @@ -57,10 +59,15 @@ interface Element : Node { [Constant] readonly attribute HTMLCollection children; + [Pure] readonly attribute Element? firstElementChild; + [Pure] readonly attribute Element? lastElementChild; + [Pure] readonly attribute Element? previousElementSibling; + [Pure] readonly attribute Element? nextElementSibling; + [Pure] readonly attribute unsigned long childElementCount; // NEW @@ -148,6 +155,7 @@ partial interface Element { // scrolling void scrollIntoView(optional boolean top = true); + // None of the CSSOM attributes are [Pure], because they flush attribute long scrollTop; // scroll on setting attribute long scrollLeft; // scroll on setting readonly attribute long scrollWidth; diff --git a/dom/webidl/HTMLElement.webidl b/dom/webidl/HTMLElement.webidl index 96be9ec85dd..d03d897187c 100644 --- a/dom/webidl/HTMLElement.webidl +++ b/dom/webidl/HTMLElement.webidl @@ -15,23 +15,22 @@ interface DOMStringMap; interface HTMLMenuElement; -// Hack to make sure that we initialize the touch prefs properly [PrefControlled] interface HTMLElement : Element { // metadata attributes attribute DOMString title; attribute DOMString lang; // attribute boolean translate; - [SetterThrows] + [SetterThrows, Pure] attribute DOMString dir; [Constant] readonly attribute DOMStringMap dataset; // microdata - [SetterThrows] + [SetterThrows, Pure] attribute boolean itemScope; [PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemType; - [SetterThrows] + [SetterThrows, Pure] attribute DOMString itemId; [PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemRef; [PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemProp; @@ -41,28 +40,31 @@ interface HTMLElement : Element { attribute any itemValue; // user interaction - [SetterThrows] + [SetterThrows, Pure] attribute boolean hidden; void click(); - [SetterThrows] + [SetterThrows, Pure] attribute long tabIndex; [Throws] void focus(); [Throws] void blur(); - [SetterThrows] + [SetterThrows, Pure] attribute DOMString accessKey; + [Pure] readonly attribute DOMString accessKeyLabel; - [SetterThrows] + [SetterThrows, Pure] attribute boolean draggable; //[PutForwards=value] readonly attribute DOMSettableTokenList dropzone; - [SetterThrows] + [SetterThrows, Pure] attribute DOMString contentEditable; + [Pure] readonly attribute boolean isContentEditable; + [Pure] readonly attribute HTMLMenuElement? contextMenu; //[SetterThrows] // attribute HTMLMenuElement? contextMenu; - [SetterThrows] + [SetterThrows, Pure] attribute boolean spellcheck; // command API @@ -81,25 +83,6 @@ interface HTMLElement : Element { // FIXME Bug 810677 Move className from HTMLElement to Element attribute DOMString className; - [SetterThrows] - attribute EventHandler oncopy; - [SetterThrows] - attribute EventHandler oncut; - [SetterThrows] - attribute EventHandler onpaste; -}; - -// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-htmlelement-interface -partial interface HTMLElement { - readonly attribute Element? offsetParent; - readonly attribute long offsetTop; - readonly attribute long offsetLeft; - readonly attribute long offsetWidth; - readonly attribute long offsetHeight; -}; - -[NoInterfaceObject] -interface TouchEventHandlers { [SetterThrows,Pref="dom.w3c_touch_events.expose"] attribute EventHandler ontouchstart; [SetterThrows,Pref="dom.w3c_touch_events.expose"] @@ -112,10 +95,26 @@ interface TouchEventHandlers { attribute EventHandler ontouchleave; [SetterThrows,Pref="dom.w3c_touch_events.expose"] attribute EventHandler ontouchcancel; + + [SetterThrows] + attribute EventHandler oncopy; + [SetterThrows] + attribute EventHandler oncut; + [SetterThrows] + attribute EventHandler onpaste; +}; + +// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-htmlelement-interface +partial interface HTMLElement { + // CSSOM things are not [Pure] because they can flush + readonly attribute Element? offsetParent; + readonly attribute long offsetTop; + readonly attribute long offsetLeft; + readonly attribute long offsetWidth; + readonly attribute long offsetHeight; }; HTMLElement implements GlobalEventHandlers; HTMLElement implements NodeEventHandlers; -HTMLElement implements TouchEventHandlers; interface HTMLUnknownElement : HTMLElement {}; diff --git a/dom/webidl/Node.webidl b/dom/webidl/Node.webidl index f86c04930ef..89613b165ee 100644 --- a/dom/webidl/Node.webidl +++ b/dom/webidl/Node.webidl @@ -30,24 +30,33 @@ interface Node : EventTarget { const unsigned short NOTATION_NODE = 12; // historical [Constant] readonly attribute unsigned short nodeType; + [Pure] readonly attribute DOMString nodeName; + [Pure] readonly attribute DOMString? baseURI; + [Pure] readonly attribute Document? ownerDocument; + [Pure] readonly attribute Node? parentNode; + [Pure] readonly attribute Element? parentElement; boolean hasChildNodes(); [Constant] readonly attribute NodeList childNodes; + [Pure] readonly attribute Node? firstChild; + [Pure] readonly attribute Node? lastChild; + [Pure] readonly attribute Node? previousSibling; + [Pure] readonly attribute Node? nextSibling; - [SetterThrows] + [SetterThrows, Pure] attribute DOMString? nodeValue; - [SetterThrows] + [SetterThrows, Pure] attribute DOMString? textContent; [Throws] Node insertBefore(Node node, Node? child); @@ -82,7 +91,7 @@ interface Node : EventTarget { readonly attribute NamedNodeMap? attributes; // If we move namespaceURI, prefix and localName to Element they should return // a non-nullable type. - [Throws, Constant] + [Constant] readonly attribute DOMString? namespaceURI; [Constant] readonly attribute DOMString? prefix; diff --git a/dom/webidl/SVGClipPathElement.webidl b/dom/webidl/SVGClipPathElement.webidl index 0a207df1204..aba8f52fbf6 100644 --- a/dom/webidl/SVGClipPathElement.webidl +++ b/dom/webidl/SVGClipPathElement.webidl @@ -12,8 +12,9 @@ interface SVGAnimatedEnumeration; -interface SVGClipPathElement : SVGTransformableElement { +interface SVGClipPathElement : SVGElement { readonly attribute SVGAnimatedEnumeration clipPathUnits; + readonly attribute SVGAnimatedTransformList transform; }; SVGClipPathElement implements SVGUnitTypes; diff --git a/dom/webidl/SVGElement.webidl b/dom/webidl/SVGElement.webidl index 4afdd550803..fe7a522e4fe 100644 --- a/dom/webidl/SVGElement.webidl +++ b/dom/webidl/SVGElement.webidl @@ -34,6 +34,19 @@ interface SVGElement : Element { readonly attribute SVGSVGElement? ownerSVGElement; readonly attribute SVGElement? viewportElement; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchstart; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchend; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchmove; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchenter; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchleave; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchcancel; + [SetterThrows] attribute EventHandler oncopy; [SetterThrows] @@ -44,4 +57,3 @@ interface SVGElement : Element { SVGElement implements GlobalEventHandlers; SVGElement implements NodeEventHandlers; -SVGElement implements TouchEventHandlers; diff --git a/dom/webidl/SVGMarkerElement.webidl b/dom/webidl/SVGMarkerElement.webidl new file mode 100644 index 00000000000..f80ef0d159c --- /dev/null +++ b/dom/webidl/SVGMarkerElement.webidl @@ -0,0 +1,41 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * http://www.w3.org/TR/SVG2/ + * + * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * liability, trademark and document use rules apply. + */ + +interface SVGAnimatedEnumeration; + +interface SVGMarkerElement : SVGElement { + + // Marker Unit Types + const unsigned short SVG_MARKERUNITS_UNKNOWN = 0; + const unsigned short SVG_MARKERUNITS_USERSPACEONUSE = 1; + const unsigned short SVG_MARKERUNITS_STROKEWIDTH = 2; + + // Marker Orientation Types + const unsigned short SVG_MARKER_ORIENT_UNKNOWN = 0; + const unsigned short SVG_MARKER_ORIENT_AUTO = 1; + const unsigned short SVG_MARKER_ORIENT_ANGLE = 2; + + readonly attribute SVGAnimatedLength refX; + readonly attribute SVGAnimatedLength refY; + readonly attribute SVGAnimatedEnumeration markerUnits; + readonly attribute SVGAnimatedLength markerWidth; + readonly attribute SVGAnimatedLength markerHeight; + readonly attribute SVGAnimatedEnumeration orientType; + readonly attribute SVGAnimatedAngle orientAngle; + + void setOrientToAuto(); + [Throws] + void setOrientToAngle(SVGAngle angle); +}; + +SVGMarkerElement implements SVGFitToViewBox; + diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 7cc3d220d2e..1971d5ef667 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -133,6 +133,7 @@ webidl_files = \ SVGLinearGradientElement.webidl \ SVGLineElement.webidl \ SVGLocatableElement.webidl \ + SVGMarkerElement.webidl \ SVGMaskElement.webidl \ SVGMatrix.webidl \ SVGMetadataElement.webidl \ @@ -184,7 +185,6 @@ webidl_files = \ XMLHttpRequestUpload.webidl \ XMLSerializer.webidl \ XPathEvaluator.webidl \ - XULElement.webidl \ $(NULL) ifdef MOZ_WEBGL diff --git a/dom/webidl/XULElement.webidl b/dom/webidl/XULElement.webidl deleted file mode 100644 index 9288a4a00a7..00000000000 --- a/dom/webidl/XULElement.webidl +++ /dev/null @@ -1,134 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -interface MozBoxObject; -interface MozControllers; -interface MozFrameLoader; -interface MozRDFCompositeDataSource; -interface MozRDFResource; -interface MozXULTemplateBuilder; - -// Hack to make sure that we initialize the touch prefs properly -[PrefControlled] -interface XULElement : Element { - [SetterThrows] - attribute DOMString className; - - // Layout properties - [SetterThrows] - attribute DOMString align; - [SetterThrows] - attribute DOMString dir; - [SetterThrows] - attribute DOMString flex; - [SetterThrows] - attribute DOMString flexGroup; - [SetterThrows] - attribute DOMString ordinal; - [SetterThrows] - attribute DOMString orient; - [SetterThrows] - attribute DOMString pack; - - // Properties for hiding elements. - attribute boolean hidden; - attribute boolean collapsed; - - // Property for hooking up to broadcasters - [SetterThrows] - attribute DOMString observes; - - // Properties for hooking up to popups - [SetterThrows] - attribute DOMString menu; - [SetterThrows] - attribute DOMString contextMenu; - [SetterThrows] - attribute DOMString tooltip; - - // Width/height properties - [SetterThrows] - attribute DOMString width; - [SetterThrows] - attribute DOMString height; - [SetterThrows] - attribute DOMString minWidth; - [SetterThrows] - attribute DOMString minHeight; - [SetterThrows] - attribute DOMString maxWidth; - [SetterThrows] - attribute DOMString maxHeight; - - // Persistence - [SetterThrows] - attribute DOMString persist; - - // Position properties for - // * popups - these are screen coordinates - // * other elements - these are client coordinates relative to parent stack. - [SetterThrows] - attribute DOMString left; - [SetterThrows] - attribute DOMString top; - - // XUL Template Builder - [SetterThrows] - attribute DOMString datasources; - [SetterThrows] - attribute DOMString ref; - - // Tooltip and status info - [SetterThrows] - attribute DOMString tooltipText; - [SetterThrows] - attribute DOMString statusText; - - attribute boolean allowEvents; - - readonly attribute MozRDFCompositeDataSource? database; - readonly attribute MozXULTemplateBuilder? builder; - [Throws] - readonly attribute MozRDFResource? resource; - [Throws] - readonly attribute MozControllers controllers; - [Throws] - readonly attribute MozBoxObject? boxObject; - - [Throws] - void focus(); - [Throws] - void blur(); - [Throws] - void click(); - void doCommand(); - - // XXXbz this isn't really a nodelist! See bug 818548 - NodeList getElementsByAttribute(DOMString name, - DOMString value); - // XXXbz this isn't really a nodelist! See bug 818548 - [Throws] - NodeList getElementsByAttributeNS(DOMString namespaceURI, - DOMString name, - DOMString value); - [Constant] - readonly attribute CSSStyleDeclaration style; -}; - -// And the things from nsIFrameLoaderOwner -[NoInterfaceObject] -interface MozFrameLoaderOwner { - [ChromeOnly] - readonly attribute MozFrameLoader? frameLoader; - - [ChromeOnly, Throws] - void swapFrameLoaders(XULElement aOtherOwner); -}; - -XULElement implements GlobalEventHandlers; -XULElement implements NodeEventHandlers; -XULElement implements TouchEventHandlers; -XULElement implements MozFrameLoaderOwner; diff --git a/gfx/cairo/libpixman/src/Makefile.in b/gfx/cairo/libpixman/src/Makefile.in index 9b4873ede42..fcb0369cf61 100644 --- a/gfx/cairo/libpixman/src/Makefile.in +++ b/gfx/cairo/libpixman/src/Makefile.in @@ -83,29 +83,34 @@ endif CSRCS = \ pixman-access.c \ pixman-access-accessors.c \ + pixman-arm.c \ pixman-bits-image.c \ pixman.c \ pixman-combine16.c \ pixman-combine32.c \ pixman-combine64.c \ pixman-conical-gradient.c \ - pixman-cpu.c \ pixman-edge.c \ pixman-edge-accessors.c \ pixman-fast-path.c \ pixman-general.c \ pixman-gradient-walker.c \ + pixman-glyph.c \ pixman-image.c \ pixman-implementation.c \ pixman-linear-gradient.c \ pixman-matrix.c \ + pixman-mips.c \ pixman-noop.c \ + pixman-ppc.c \ pixman-radial-gradient.c \ pixman-region16.c \ pixman-region32.c \ pixman-solid-fill.c \ + pixman-srgb.c \ pixman-trap.c \ pixman-utils.c \ + pixman-x86.c \ $(NULL) ifdef USE_MMX diff --git a/gfx/cairo/libpixman/src/pixman-access.c b/gfx/cairo/libpixman/src/pixman-access.c index 91ce793cacc..521ad405742 100644 --- a/gfx/cairo/libpixman/src/pixman-access.c +++ b/gfx/cairo/libpixman/src/pixman-access.c @@ -32,8 +32,8 @@ #include #include -#include "pixman-private.h" #include "pixman-accessor.h" +#include "pixman-private.h" #define CONVERT_RGB24_TO_Y15(s) \ (((((s) >> 16) & 0xff) * 153 + \ @@ -210,6 +210,7 @@ get_shifts (pixman_format_code_t format, break; case PIXMAN_TYPE_ARGB: + case PIXMAN_TYPE_ARGB_SRGB: *b = 0; *g = *b + PIXMAN_FORMAT_B (format); *r = *g + PIXMAN_FORMAT_G (format); @@ -1065,6 +1066,130 @@ fetch_pixel_generic_64 (bits_image_t *image, return result; } +/* The 32_sRGB paths should be deleted after narrow processing + * is no longer invoked for formats that are considered wide. + * (Also see fetch_pixel_generic_lossy_32) */ +static void +fetch_scanline_a8r8g8b8_32_sRGB (pixman_image_t *image, + int x, + int y, + int width, + uint32_t *buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + uint32_t tmp; + + while (pixel < end) + { + tmp = READ (image, pixel++); + *buffer++ = (tmp >> 24) << 24 + | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16 + | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8 + | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0; + } +} + +static void +fetch_scanline_a8r8g8b8_64_sRGB (pixman_image_t *image, + int x, + int y, + int width, + uint32_t *b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + uint64_t *buffer = (uint64_t *)b; + uint32_t tmp; + + while (pixel < end) + { + tmp = READ (image, pixel++); + *buffer++ = (uint64_t) ((tmp >> 24) * 257) << 48 + | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32 + | (uint64_t) srgb_to_linear[(tmp >> 8) & 0xff] << 16 + | (uint64_t) srgb_to_linear[(tmp >> 0) & 0xff] << 0; + } +} + +static uint32_t +fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t tmp = READ (image, bits + offset); + return (tmp >> 24) << 24 + | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16 + | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8 + | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0; +} + +static uint64_t +fetch_pixel_a8r8g8b8_64_sRGB (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t tmp = READ (image, bits + offset); + return (uint64_t) ((tmp >> 24) * 257) << 48 + | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32 + | (uint64_t) srgb_to_linear[(tmp >> 8) & 0xff] << 16 + | (uint64_t) srgb_to_linear[(tmp >> 0) & 0xff] << 0; +} + +static void +store_scanline_a8r8g8b8_32_sRGB (bits_image_t *image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint64_t *values = (uint64_t *)v; + uint32_t *pixel = bits + x; + uint64_t tmp; + int i; + + for (i = 0; i < width; ++i) + { + tmp = values[i]; + WRITE (image, pixel++, + ((uint32_t) (tmp >> 24 ) << 24) + | (linear_to_srgb[(tmp >> 16 << 4) & 0xfff] << 16) + | (linear_to_srgb[(tmp >> 8 << 4) & 0xfff] << 8) + | (linear_to_srgb[(tmp >> 0 << 4) & 0xfff] << 0)); + } +} + +static void +store_scanline_a8r8g8b8_64_sRGB (bits_image_t *image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint64_t *values = (uint64_t *)v; + uint32_t *pixel = bits + x; + uint64_t tmp; + int i; + + for (i = 0; i < width; ++i) + { + tmp = values[i]; + WRITE (image, pixel++, + ((uint32_t) (tmp >> 56) << 24) + | (linear_to_srgb[(tmp >> 36) & 0xfff] << 16) + | (linear_to_srgb[(tmp >> 20) & 0xfff] << 8) + | (linear_to_srgb[(tmp >> 4) & 0xfff] << 0)); + } +} + /* * XXX: The transformed fetch path only works at 32-bpp so far. When all * paths have wide versions, this can be removed. @@ -1132,6 +1257,13 @@ static const format_info_t accessors[] = FORMAT_INFO (r8g8b8x8), FORMAT_INFO (x14r6g6b6), +/* sRGB formats */ + { PIXMAN_a8r8g8b8_sRGB, + fetch_scanline_a8r8g8b8_32_sRGB, + fetch_scanline_a8r8g8b8_64_sRGB, + fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_64_sRGB, + store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_64_sRGB }, + /* 24bpp formats */ FORMAT_INFO (r8g8b8), FORMAT_INFO (b8g8r8), diff --git a/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S b/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S index f7913adb71b..e37b5c298e4 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S +++ b/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S @@ -64,6 +64,7 @@ .altmacro .p2align 2 +#include "pixman-private.h" #include "pixman-arm-neon-asm.h" /* @@ -488,12 +489,12 @@ fname: vmull.u8 q1, d0, d28 vmlal.u8 q1, d1, d29 /* 5 cycles bubble */ - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 /* 5 cycles bubble */ bilinear_duplicate_mask mask_fmt, 1, d4 - vshrn.u32 d0, q0, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) /* 3 cycles bubble */ vmovn.u16 d0, q0 /* 1 cycle bubble */ @@ -514,16 +515,16 @@ fname: q1, q11, d0, d1, d20, d21, d22, d23 bilinear_load_mask mask_fmt, 2, d4 bilinear_load_dst dst_fmt, op, 2, d18, d19, q9 - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #8 + vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q10, d22, d31 vmlal.u16 q10, d23, d31 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q10, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) bilinear_duplicate_mask mask_fmt, 2, d4 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vmovn.u16 d0, q0 bilinear_interleave_src_dst \ @@ -544,29 +545,29 @@ fname: q3, q9, d4, d5, d16, d17, d18, d19 pld [TMP1, PF_OFFS] sub TMP1, TMP1, STRIDE - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #8 + vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q10, d22, d31 vmlal.u16 q10, d23, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d6, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d6, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d6, d30 vmlal.u16 q2, d7, d30 - vshll.u16 q8, d18, #8 + vshll.u16 q8, d18, #BILINEAR_INTERPOLATION_BITS bilinear_load_mask mask_fmt, 4, d22 bilinear_load_dst dst_fmt, op, 4, d2, d3, q1 pld [TMP1, PF_OFFS] vmlsl.u16 q8, d18, d31 vmlal.u16 q8, d19, d31 vadd.u16 q12, q12, q13 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q10, #16 - vshrn.u32 d4, q2, #16 - vshrn.u32 d5, q8, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d5, q8, #(2 * BILINEAR_INTERPOLATION_BITS) bilinear_duplicate_mask mask_fmt, 4, d22 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vmovn.u16 d0, q0 vmovn.u16 d1, q2 vadd.u16 q12, q12, q13 @@ -694,13 +695,13 @@ pixman_asm_function fname blt 0f tst OUT, #(1 << dst_bpp_shift) beq 0f - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 bilinear_process_last_pixel sub WIDTH, WIDTH, #1 0: vadd.u16 q13, q13, q13 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 cmp WIDTH, #2 @@ -921,7 +922,7 @@ pixman_asm_function fname vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -932,27 +933,27 @@ pixman_asm_function fname vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 .endm .macro bilinear_over_8888_8888_process_pixblock_tail - vshll.u16 q2, d20, #8 + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d2, d3}, [OUT, :128] pld [OUT, #(prefetch_offset * 4)] - vshrn.u32 d4, q2, #16 - vshr.u16 q15, q12, #8 - vshrn.u32 d5, q3, #16 + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vmovn.u16 d6, q0 vmovn.u16 d7, q2 vuzp.8 d6, d7 @@ -975,7 +976,7 @@ pixman_asm_function fname .endm .macro bilinear_over_8888_8888_process_pixblock_tail_head - vshll.u16 q2, d20, #8 + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS mov TMP1, X, asr #16 add X, X, UX add TMP1, TOP, TMP1, asl #2 @@ -984,21 +985,21 @@ pixman_asm_function fname add X, X, UX add TMP2, TOP, TMP2, asl #2 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vld1.32 {d20}, [TMP1], STRIDE vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vld1.32 {d21}, [TMP1] vmull.u8 q8, d20, d28 vmlal.u8 q8, d21, d29 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d2, d3}, [OUT, :128] pld [OUT, PF_OFFS] - vshrn.u32 d4, q2, #16 - vshr.u16 q15, q12, #8 + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d22}, [TMP2], STRIDE - vshrn.u32 d5, q3, #16 + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vmovn.u16 d6, q0 vld1.32 {d23}, [TMP2] vmull.u8 q9, d22, d28 @@ -1022,7 +1023,7 @@ pixman_asm_function fname vmlal.u8 q10, d23, d29 vmull.u8 q11, d2, d4 vmull.u8 q2, d3, d4 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d16, d30 vrshr.u16 q1, q11, #8 vmlal.u16 q0, d17, d30 @@ -1037,12 +1038,12 @@ pixman_asm_function fname vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 vuzp.8 d6, d7 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vuzp.8 d6, d7 vmlsl.u16 q1, d18, d31 vadd.u16 q12, q12, q13 vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vst1.32 {d6, d7}, [OUT, :128]! .endm @@ -1081,14 +1082,14 @@ pixman_asm_function fname vmull.u8 q3, d2, d28 vmlal.u8 q2, d1, d29 vmlal.u8 q3, d3, d29 - vshll.u16 q0, d4, #8 - vshll.u16 q1, d6, #8 + vshll.u16 q0, d4, #BILINEAR_INTERPOLATION_BITS + vshll.u16 q1, d6, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d4, d30 vmlsl.u16 q1, d6, d31 vmlal.u16 q0, d5, d30 vmlal.u16 q1, d7, d31 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d2}, [TMP3], STRIDE vld1.32 {d3}, [TMP3] pld [TMP4, PF_OFFS] @@ -1099,7 +1100,7 @@ pixman_asm_function fname vmlal.u8 q3, d3, d29 vmull.u8 q1, d4, d28 vmlal.u8 q1, d5, d29 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d22[0]}, [MASK]! pld [MASK, #prefetch_offset] vadd.u16 q12, q12, q13 @@ -1107,17 +1108,17 @@ pixman_asm_function fname .endm .macro bilinear_over_8888_8_8888_process_pixblock_tail - vshll.u16 q9, d6, #8 - vshll.u16 q10, d2, #8 + vshll.u16 q9, d6, #BILINEAR_INTERPOLATION_BITS + vshll.u16 q10, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q9, d6, d30 vmlsl.u16 q10, d2, d31 vmlal.u16 q9, d7, d30 vmlal.u16 q10, d3, d31 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vdup.32 d22, d22[0] - vshrn.u32 d18, q9, #16 - vshrn.u32 d19, q10, #16 + vshrn.u32 d18, q9, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d19, q10, #(2 * BILINEAR_INTERPOLATION_BITS) vmovn.u16 d17, q9 vld1.32 {d18, d19}, [OUT, :128] pld [OUT, PF_OFFS] @@ -1146,11 +1147,11 @@ pixman_asm_function fname .endm .macro bilinear_over_8888_8_8888_process_pixblock_tail_head - vshll.u16 q9, d6, #8 + vshll.u16 q9, d6, #BILINEAR_INTERPOLATION_BITS mov TMP1, X, asr #16 add X, X, UX add TMP1, TOP, TMP1, asl #2 - vshll.u16 q10, d2, #8 + vshll.u16 q10, d2, #BILINEAR_INTERPOLATION_BITS vld1.32 {d0}, [TMP1], STRIDE mov TMP2, X, asr #16 add X, X, UX @@ -1167,12 +1168,12 @@ pixman_asm_function fname mov TMP4, X, asr #16 add X, X, UX add TMP4, TOP, TMP4, asl #2 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vld1.32 {d3}, [TMP2] vdup.32 d22, d22[0] - vshrn.u32 d18, q9, #16 - vshrn.u32 d19, q10, #16 + vshrn.u32 d18, q9, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d19, q10, #(2 * BILINEAR_INTERPOLATION_BITS) vmull.u8 q2, d0, d28 vmull.u8 q3, d2, d28 vmovn.u16 d17, q9 @@ -1182,8 +1183,8 @@ pixman_asm_function fname vmlal.u8 q3, d3, d29 vuzp.8 d16, d17 vuzp.8 d18, d19 - vshll.u16 q0, d4, #8 - vshll.u16 q1, d6, #8 + vshll.u16 q0, d4, #BILINEAR_INTERPOLATION_BITS + vshll.u16 q1, d6, #BILINEAR_INTERPOLATION_BITS vuzp.8 d16, d17 vuzp.8 d18, d19 vmlsl.u16 q0, d4, d30 @@ -1194,8 +1195,8 @@ pixman_asm_function fname vmlal.u16 q1, d7, d31 vrsra.u16 q10, q10, #8 vrsra.u16 q11, q11, #8 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) vrshrn.u16 d16, q10, #8 vrshrn.u16 d17, q11, #8 vld1.32 {d2}, [TMP3], STRIDE @@ -1216,7 +1217,7 @@ pixman_asm_function fname vraddhn.u16 d18, q9, q10 vraddhn.u16 d19, q15, q11 vmlal.u8 q1, d5, d29 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vqadd.u8 q9, q8, q9 vld1.32 {d22[0]}, [MASK]! vuzp.8 d18, d19 diff --git a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S index 87aae1d552d..187197dc31d 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S +++ b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S @@ -49,6 +49,7 @@ .altmacro .p2align 2 +#include "pixman-private.h" #include "pixman-arm-neon-asm.h" /* Global configuration options and preferences */ @@ -2986,11 +2987,11 @@ fname: vmull.u8 q1, d0, d28 vmlal.u8 q1, d1, d29 /* 5 cycles bubble */ - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 /* 5 cycles bubble */ - vshrn.u32 d0, q0, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) /* 3 cycles bubble */ vmovn.u16 d0, q0 /* 1 cycle bubble */ @@ -3000,15 +3001,15 @@ fname: .macro bilinear_interpolate_two_pixels src_fmt, dst_fmt bilinear_load_and_vertical_interpolate_two_&src_fmt \ q1, q11, d0, d1, d20, d21, d22, d23 - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #8 + vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q10, d22, d31 vmlal.u16 q10, d23, d31 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q10, #16 - vshr.u16 q15, q12, #8 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vmovn.u16 d0, q0 bilinear_store_&dst_fmt 2, q2, q3 @@ -3020,26 +3021,26 @@ fname: q3, q9, d4, d5, d16, d17, d18, d19 pld [TMP1, PF_OFFS] sub TMP1, TMP1, STRIDE - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #8 + vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q10, d22, d31 vmlal.u16 q10, d23, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d6, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d6, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d6, d30 vmlal.u16 q2, d7, d30 - vshll.u16 q8, d18, #8 + vshll.u16 q8, d18, #BILINEAR_INTERPOLATION_BITS pld [TMP2, PF_OFFS] vmlsl.u16 q8, d18, d31 vmlal.u16 q8, d19, d31 vadd.u16 q12, q12, q13 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q10, #16 - vshrn.u32 d4, q2, #16 - vshrn.u32 d5, q8, #16 - vshr.u16 q15, q12, #8 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d5, q8, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vmovn.u16 d0, q0 vmovn.u16 d1, q2 vadd.u16 q12, q12, q13 @@ -3158,13 +3159,13 @@ pixman_asm_function fname blt 0f tst OUT, #(1 << dst_bpp_shift) beq 0f - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 bilinear_interpolate_last_pixel src_fmt, dst_fmt sub WIDTH, WIDTH, #1 0: vadd.u16 q13, q13, q13 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 cmp WIDTH, #2 @@ -3282,7 +3283,7 @@ pixman_asm_function fname vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -3293,25 +3294,25 @@ pixman_asm_function fname vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 .endm .macro bilinear_interpolate_four_pixels_8888_8888_tail vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d20, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vadd.u16 q12, q12, q13 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 - vshrn.u32 d4, q2, #16 - vshr.u16 q15, q12, #8 - vshrn.u32 d5, q3, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vmovn.u16 d6, q0 vmovn.u16 d7, q2 vadd.u16 q12, q12, q13 @@ -3326,22 +3327,22 @@ pixman_asm_function fname add X, X, UX add TMP2, TOP, TMP2, asl #2 vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d20, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vld1.32 {d20}, [TMP1], STRIDE vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vld1.32 {d21}, [TMP1] vmull.u8 q8, d20, d28 vmlal.u8 q8, d21, d29 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 - vshrn.u32 d4, q2, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d22}, [TMP2], STRIDE - vshrn.u32 d5, q3, #16 + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vld1.32 {d23}, [TMP2] vmull.u8 q9, d22, d28 @@ -3353,12 +3354,12 @@ pixman_asm_function fname add TMP4, TOP, TMP4, asl #2 vmlal.u8 q9, d23, d29 vld1.32 {d22}, [TMP3], STRIDE - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d23}, [TMP3] vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 vmovn.u16 d6, q0 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmovn.u16 d7, q2 vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -3370,7 +3371,7 @@ pixman_asm_function fname vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 vst1.32 {d6, d7}, [OUT, :128]! - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 .endm @@ -3403,7 +3404,7 @@ pixman_asm_function fname vld1.32 {d23}, [TMP3] vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 pld [TMP4, PF_OFFS] @@ -3412,7 +3413,7 @@ pixman_asm_function fname pld [TMP4, PF_OFFS] vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 mov TMP1, X, asr #16 @@ -3422,22 +3423,22 @@ pixman_asm_function fname add X, X, UX add TMP2, TOP, TMP2, asl #2 vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d20, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vld1.32 {d20}, [TMP1], STRIDE vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vld1.32 {d21}, [TMP1] vmull.u8 q8, d20, d28 vmlal.u8 q8, d21, d29 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 - vshrn.u32 d4, q2, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d22}, [TMP2], STRIDE - vshrn.u32 d5, q3, #16 + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vld1.32 {d23}, [TMP2] vmull.u8 q9, d22, d28 @@ -3449,12 +3450,12 @@ pixman_asm_function fname add TMP4, TOP, TMP4, asl #2 vmlal.u8 q9, d23, d29 vld1.32 {d22}, [TMP3], STRIDE - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d23}, [TMP3] vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 vmovn.u16 d8, q0 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmovn.u16 d9, q2 vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -3465,25 +3466,25 @@ pixman_asm_function fname pld [TMP4, PF_OFFS] vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 .endm .macro bilinear_interpolate_eight_pixels_8888_0565_tail vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d20, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vadd.u16 q12, q12, q13 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 - vshrn.u32 d4, q2, #16 - vshr.u16 q15, q12, #8 - vshrn.u32 d5, q3, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vmovn.u16 d10, q0 vmovn.u16 d11, q2 vadd.u16 q12, q12, q13 @@ -3508,23 +3509,23 @@ pixman_asm_function fname add X, X, UX add TMP2, TOP, TMP2, asl #2 vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vuzp.u8 d8, d9 - vshll.u16 q2, d20, #8 + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vld1.32 {d20}, [TMP1], STRIDE vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vld1.32 {d21}, [TMP1] vmull.u8 q8, d20, d28 vmlal.u8 q8, d21, d29 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 - vshrn.u32 d4, q2, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d22}, [TMP2], STRIDE - vshrn.u32 d5, q3, #16 + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vld1.32 {d23}, [TMP2] vmull.u8 q9, d22, d28 @@ -3536,12 +3537,12 @@ pixman_asm_function fname add TMP4, TOP, TMP4, asl #2 vmlal.u8 q9, d23, d29 vld1.32 {d22}, [TMP3], STRIDE - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d23}, [TMP3] vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 vmovn.u16 d10, q0 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmovn.u16 d11, q2 vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -3553,7 +3554,7 @@ pixman_asm_function fname vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 vuzp.u8 d10, d11 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 mov TMP1, X, asr #16 @@ -3564,12 +3565,12 @@ pixman_asm_function fname add TMP2, TOP, TMP2, asl #2 vmlal.u16 q1, d19, d31 vuzp.u8 d9, d11 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d20, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vuzp.u8 d8, d10 vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vld1.32 {d20}, [TMP1], STRIDE vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 @@ -3579,13 +3580,13 @@ pixman_asm_function fname vshll.u8 q6, d9, #8 vshll.u8 q5, d10, #8 vshll.u8 q7, d8, #8 - vshrn.u32 d0, q0, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) vsri.u16 q5, q6, #5 - vshrn.u32 d1, q1, #16 + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) vsri.u16 q5, q7, #11 - vshrn.u32 d4, q2, #16 + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d22}, [TMP2], STRIDE - vshrn.u32 d5, q3, #16 + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vld1.32 {d23}, [TMP2] vmull.u8 q9, d22, d28 @@ -3597,12 +3598,12 @@ pixman_asm_function fname add TMP4, TOP, TMP4, asl #2 vmlal.u8 q9, d23, d29 vld1.32 {d22}, [TMP3], STRIDE - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d23}, [TMP3] vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 vmovn.u16 d8, q0 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmovn.u16 d9, q2 vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -3613,7 +3614,7 @@ pixman_asm_function fname pld [TMP4, PF_OFFS] vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vst1.32 {d10, d11}, [OUT, :128]! vmlsl.u16 q1, d18, d31 .endm diff --git a/gfx/cairo/libpixman/src/pixman-arm.c b/gfx/cairo/libpixman/src/pixman-arm.c new file mode 100644 index 00000000000..145bd9050b7 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-arm.c @@ -0,0 +1,229 @@ +/* + * Copyright © 2000 SuSE, Inc. + * Copyright © 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" + +typedef enum +{ + ARM_V7 = (1 << 0), + ARM_V6 = (1 << 1), + ARM_VFP = (1 << 2), + ARM_NEON = (1 << 3), + ARM_IWMMXT = (1 << 4) +} arm_cpu_features_t; + +#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT) + +#if defined(_MSC_VER) + +/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */ +#include + +extern int pixman_msvc_try_arm_neon_op (); +extern int pixman_msvc_try_arm_simd_op (); + +static arm_cpu_features_t +detect_cpu_features (void) +{ + arm_cpu_features_t features = 0; + + __try + { + pixman_msvc_try_arm_simd_op (); + features |= ARM_V6; + } + __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) + { + } + + __try + { + pixman_msvc_try_arm_neon_op (); + features |= ARM_NEON; + } + __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) + { + } + + return features; +} + +#elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) /* iOS */ + +#include "TargetConditionals.h" + +static arm_cpu_features_t +detect_cpu_features (void) +{ + arm_cpu_features_t features = 0; + + features |= ARM_V6; + + /* Detection of ARM NEON on iOS is fairly simple because iOS binaries + * contain separate executable images for each processor architecture. + * So all we have to do is detect the armv7 architecture build. The + * operating system automatically runs the armv7 binary for armv7 devices + * and the armv6 binary for armv6 devices. + */ +#if defined(__ARM_NEON__) + features |= ARM_NEON; +#endif + + return features; +} + +#elif defined(__ANDROID__) || defined(ANDROID) /* Android */ + +static arm_cpu_features_t +detect_cpu_features (void) +{ + arm_cpu_features_t features = 0; + char buf[1024]; + char* pos; + const char* ver_token = "CPU architecture: "; + FILE* f = fopen("/proc/cpuinfo", "r"); + if (!f) { + return features; + } + + fread(buf, sizeof(char), sizeof(buf), f); + fclose(f); + pos = strstr(buf, ver_token); + if (pos) { + char vchar = *(pos + strlen(ver_token)); + if (vchar >= '0' && vchar <= '9') { + int ver = vchar - '0'; + if (ver >= 7) + features |= ARM_V7; + } + } + if (strstr(buf, "neon") != NULL) + features |= ARM_NEON; + if (strstr(buf, "vfp") != NULL) + features |= ARM_VFP; + + return features; +} + +#elif defined (__linux__) /* linux ELF */ + +#include +#include +#include +#include +#include +#include +#include + +static arm_cpu_features_t +detect_cpu_features (void) +{ + arm_cpu_features_t features = 0; + Elf32_auxv_t aux; + int fd; + + fd = open ("/proc/self/auxv", O_RDONLY); + if (fd >= 0) + { + while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) + { + if (aux.a_type == AT_HWCAP) + { + uint32_t hwcap = aux.a_un.a_val; + + /* hardcode these values to avoid depending on specific + * versions of the hwcap header, e.g. HWCAP_NEON + */ + if ((hwcap & 64) != 0) + features |= ARM_VFP; + if ((hwcap & 512) != 0) + features |= ARM_IWMMXT; + /* this flag is only present on kernel 2.6.29 */ + if ((hwcap & 4096) != 0) + features |= ARM_NEON; + } + else if (aux.a_type == AT_PLATFORM) + { + const char *plat = (const char*) aux.a_un.a_val; + + if (strncmp (plat, "v7l", 3) == 0) + features |= (ARM_V7 | ARM_V6); + else if (strncmp (plat, "v6l", 3) == 0) + features |= ARM_V6; + } + } + close (fd); + } + + return features; +} + +#else /* Unknown */ + +static arm_cpu_features_t +detect_cpu_features (void) +{ + return 0; +} + +#endif /* Linux elf */ + +static pixman_bool_t +have_feature (arm_cpu_features_t feature) +{ + static pixman_bool_t initialized; + static arm_cpu_features_t features; + + if (!initialized) + { + features = detect_cpu_features(); + initialized = TRUE; + } + + return (features & feature) == feature; +} + +#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */ + +pixman_implementation_t * +_pixman_arm_get_implementations (pixman_implementation_t *imp) +{ +#ifdef USE_ARM_SIMD + if (!_pixman_disabled ("arm-simd") && have_feature (ARM_V6)) + imp = _pixman_implementation_create_arm_simd (imp); +#endif + +#ifdef USE_ARM_IWMMXT + if (!_pixman_disabled ("arm-iwmmxt") && have_feature (ARM_IWMMXT)) + imp = _pixman_implementation_create_mmx (imp); +#endif + +#ifdef USE_ARM_NEON + if (!_pixman_disabled ("arm-neon") && have_feature (ARM_NEON)) + imp = _pixman_implementation_create_arm_neon (imp); +#endif + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman-bits-image.c b/gfx/cairo/libpixman/src/pixman-bits-image.c index 61f1c485c2b..c859b69a577 100644 --- a/gfx/cairo/libpixman/src/pixman-bits-image.c +++ b/gfx/cairo/libpixman/src/pixman-bits-image.c @@ -42,14 +42,14 @@ * we could produce smoother gradients by evaluating them at higher color * depth, but that's a project for the future. */ -static void -_pixman_image_get_scanline_generic_64 (pixman_image_t * image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t * mask) +static uint32_t * +_pixman_image_get_scanline_generic_64 (pixman_iter_t * iter, + const uint32_t *mask) { + int width = iter->width; + uint32_t * buffer = iter->buffer; + + pixman_iter_get_scanline_t fetch_32 = iter->data; uint32_t *mask8 = NULL; /* Contract the mask image, if one exists, so that the 32-bit fetch @@ -59,18 +59,20 @@ _pixman_image_get_scanline_generic_64 (pixman_image_t * image, { mask8 = pixman_malloc_ab (width, sizeof(uint32_t)); if (!mask8) - return; + return buffer; pixman_contract (mask8, (uint64_t *)mask, width); } /* Fetch the source image into the first half of buffer. */ - image->bits.get_scanline_32 (image, x, y, width, (uint32_t*)buffer, mask8); + fetch_32 (iter, mask8); /* Expand from 32bpp to 64bpp in place. */ pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, width); free (mask8); + + return buffer; } /* Fetch functions */ @@ -129,8 +131,8 @@ bits_image_fetch_pixel_bilinear (bits_image_t *image, x1 = x - pixman_fixed_1 / 2; y1 = y - pixman_fixed_1 / 2; - distx = interpolation_coord(x1); - disty = interpolation_coord(y1); + distx = pixman_fixed_to_bilinear_weight (x1); + disty = pixman_fixed_to_bilinear_weight (y1); x1 = pixman_fixed_to_int (x1); y1 = pixman_fixed_to_int (y1); @@ -160,14 +162,17 @@ bits_image_fetch_pixel_bilinear (bits_image_t *image, return bilinear_interpolation (tl, tr, bl, br, distx, disty); } -static void -bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, - int offset, - int line, - int width, - uint32_t * buffer, - const uint32_t * mask) +static uint32_t * +bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter, + const uint32_t *mask) { + + pixman_image_t * ima = iter->image; + int offset = iter->x; + int line = iter->y++; + int width = iter->width; + uint32_t * buffer = iter->buffer; + bits_image_t *bits = &ima->bits; pixman_fixed_t x_top, x_bottom, x; pixman_fixed_t ux_top, ux_bottom, ux; @@ -189,13 +194,13 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, v.vector[2] = pixman_fixed_1; if (!pixman_transform_point_3d (bits->common.transform, &v)) - return; + return iter->buffer; ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0]; x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2; y = v.vector[1] - pixman_fixed_1/2; - disty = interpolation_coord(y); + disty = pixman_fixed_to_bilinear_weight (y); /* Load the pointers to the first and second lines from the source * image that bilinear code must read. @@ -256,7 +261,7 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, if (top_row == zero && bottom_row == zero) { memset (buffer, 0, width * sizeof (uint32_t)); - return; + return iter->buffer; } else if (bits->format == PIXMAN_x8r8g8b8) { @@ -304,7 +309,7 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask; br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; - distx = interpolation_coord(x); + distx = pixman_fixed_to_bilinear_weight (x); *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty); @@ -329,7 +334,7 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; - distx = interpolation_coord(x); + distx = pixman_fixed_to_bilinear_weight (x); *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty); } @@ -353,7 +358,7 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, tl = top_row [pixman_fixed_to_int (x_top)] | top_mask; bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; - distx = interpolation_coord(x); + distx = pixman_fixed_to_bilinear_weight (x); *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty); } @@ -368,6 +373,8 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, /* Zero fill to the left of the image */ while (buffer < end) *buffer++ = 0; + + return iter->buffer; } static force_inline uint32_t @@ -381,11 +388,11 @@ bits_image_fetch_pixel_convolution (bits_image_t *image, int y_off = (params[1] - pixman_fixed_1) >> 1; int32_t cwidth = pixman_fixed_to_int (params[0]); int32_t cheight = pixman_fixed_to_int (params[1]); - int32_t srtot, sgtot, sbtot, satot; int32_t i, j, x1, x2, y1, y2; pixman_repeat_t repeat_mode = image->common.repeat; int width = image->width; int height = image->height; + int srtot, sgtot, sbtot, satot; params += 2; @@ -421,10 +428,10 @@ bits_image_fetch_pixel_convolution (bits_image_t *image, pixel = get_pixel (image, rx, ry, TRUE); } - srtot += RED_8 (pixel) * f; - sgtot += GREEN_8 (pixel) * f; - sbtot += BLUE_8 (pixel) * f; - satot += ALPHA_8 (pixel) * f; + srtot += (int)RED_8 (pixel) * f; + sgtot += (int)GREEN_8 (pixel) * f; + sbtot += (int)BLUE_8 (pixel) * f; + satot += (int)ALPHA_8 (pixel) * f; } params++; @@ -474,14 +481,16 @@ bits_image_fetch_pixel_filtered (bits_image_t *image, return 0; } -static void -bits_image_fetch_affine_no_alpha (pixman_image_t * image, - int offset, - int line, - int width, - uint32_t * buffer, +static uint32_t * +bits_image_fetch_affine_no_alpha (pixman_iter_t * iter, const uint32_t * mask) { + pixman_image_t *image = iter->image; + int offset = iter->x; + int line = iter->y++; + int width = iter->width; + uint32_t * buffer = iter->buffer; + pixman_fixed_t x, y; pixman_fixed_t ux, uy; pixman_vector_t v; @@ -495,7 +504,7 @@ bits_image_fetch_affine_no_alpha (pixman_image_t * image, if (image->common.transform) { if (!pixman_transform_point_3d (image->common.transform, &v)) - return; + return iter->buffer; ux = image->common.transform->matrix[0][0]; uy = image->common.transform->matrix[1][0]; @@ -520,6 +529,8 @@ bits_image_fetch_affine_no_alpha (pixman_image_t * image, x += ux; y += uy; } + + return buffer; } /* General fetcher */ @@ -563,14 +574,16 @@ fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_boun return pixel; } -static void -bits_image_fetch_general (pixman_image_t * image, - int offset, - int line, - int width, - uint32_t * buffer, - const uint32_t * mask) +static uint32_t * +bits_image_fetch_general (pixman_iter_t *iter, + const uint32_t *mask) { + pixman_image_t *image = iter->image; + int offset = iter->x; + int line = iter->y++; + int width = iter->width; + uint32_t * buffer = iter->buffer; + pixman_fixed_t x, y, w; pixman_fixed_t ux, uy, uw; pixman_vector_t v; @@ -584,7 +597,7 @@ bits_image_fetch_general (pixman_image_t * image, if (image->common.transform) { if (!pixman_transform_point_3d (image->common.transform, &v)) - return; + return buffer; ux = image->common.transform->matrix[0][0]; uy = image->common.transform->matrix[1][0]; @@ -626,6 +639,8 @@ bits_image_fetch_general (pixman_image_t * image, y += uy; w += uw; } + + return buffer; } static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -680,8 +695,8 @@ bits_image_fetch_bilinear_affine (pixman_image_t * image, x1 = x - pixman_fixed_1 / 2; y1 = y - pixman_fixed_1 / 2; - distx = interpolation_coord(x1); - disty = interpolation_coord(y1); + distx = pixman_fixed_to_bilinear_weight (x1); + disty = pixman_fixed_to_bilinear_weight (y1); y1 = pixman_fixed_to_int (y1); y2 = y1 + 1; @@ -882,35 +897,33 @@ convert_r5g6b5 (const uint8_t *row, int x) } #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \ - static void \ - bits_image_fetch_bilinear_affine_ ## name (pixman_image_t *image, \ - int offset, \ - int line, \ - int width, \ - uint32_t * buffer, \ + static uint32_t * \ + bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t *iter, \ const uint32_t * mask) \ { \ - bits_image_fetch_bilinear_affine (image, offset, line, \ - width, buffer, mask, \ + bits_image_fetch_bilinear_affine (iter->image, \ + iter->x, iter->y++, \ + iter->width, \ + iter->buffer, mask, \ convert_ ## format, \ PIXMAN_ ## format, \ repeat_mode); \ + return iter->buffer; \ } #define MAKE_NEAREST_FETCHER(name, format, repeat_mode) \ - static void \ - bits_image_fetch_nearest_affine_ ## name (pixman_image_t *image, \ - int offset, \ - int line, \ - int width, \ - uint32_t * buffer, \ + static uint32_t * \ + bits_image_fetch_nearest_affine_ ## name (pixman_iter_t *iter, \ const uint32_t * mask) \ { \ - bits_image_fetch_nearest_affine (image, offset, line, \ - width, buffer, mask, \ + bits_image_fetch_nearest_affine (iter->image, \ + iter->x, iter->y++, \ + iter->width, \ + iter->buffer, mask, \ convert_ ## format, \ PIXMAN_ ## format, \ repeat_mode); \ + return iter->buffer; \ } #define MAKE_FETCHERS(name, format, repeat_mode) \ @@ -1059,14 +1072,16 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, } } -static void -bits_image_fetch_untransformed_32 (pixman_image_t * image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t * mask) +static uint32_t * +bits_image_fetch_untransformed_32 (pixman_iter_t * iter, + const uint32_t *mask) { + pixman_image_t *image = iter->image; + int x = iter->x; + int y = iter->y; + int width = iter->width; + uint32_t * buffer = iter->buffer; + if (image->common.repeat == PIXMAN_REPEAT_NONE) { bits_image_fetch_untransformed_repeat_none ( @@ -1077,16 +1092,22 @@ bits_image_fetch_untransformed_32 (pixman_image_t * image, bits_image_fetch_untransformed_repeat_normal ( &image->bits, FALSE, x, y, width, buffer); } + + iter->y++; + return buffer; } -static void -bits_image_fetch_untransformed_64 (pixman_image_t * image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t * unused) +static uint32_t * +bits_image_fetch_untransformed_64 (pixman_iter_t * iter, + const uint32_t *mask) + { + pixman_image_t *image = iter->image; + int x = iter->x; + int y = iter->y; + int width = iter->width; + uint32_t * buffer = iter->buffer; + if (image->common.repeat == PIXMAN_REPEAT_NONE) { bits_image_fetch_untransformed_repeat_none ( @@ -1097,14 +1118,21 @@ bits_image_fetch_untransformed_64 (pixman_image_t * image, bits_image_fetch_untransformed_repeat_normal ( &image->bits, TRUE, x, y, width, buffer); } + + iter->y++; + return buffer; } +static uint32_t * +_pixman_image_get_scanline_generic_64 (pixman_iter_t *iter, + const uint32_t * mask); + typedef struct { pixman_format_code_t format; uint32_t flags; - fetch_scanline_t fetch_32; - fetch_scanline_t fetch_64; + pixman_iter_get_scanline_t get_scanline_32; + pixman_iter_get_scanline_t get_scanline_64; } fetcher_info_t; static const fetcher_info_t fetcher_info[] = @@ -1206,53 +1234,36 @@ static const fetcher_info_t fetcher_info[] = static void bits_image_property_changed (pixman_image_t *image) { - uint32_t flags = image->common.flags; - pixman_format_code_t format = image->common.extended_format_code; - const fetcher_info_t *info; - _pixman_bits_image_setup_accessors (&image->bits); - - info = fetcher_info; - while (info->format != PIXMAN_null) - { - if ((info->format == format || info->format == PIXMAN_any) && - (info->flags & flags) == info->flags) - { - image->bits.get_scanline_32 = info->fetch_32; - image->bits.get_scanline_64 = info->fetch_64; - break; - } - - info++; - } -} - -static uint32_t * -src_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) -{ - iter->image->bits.get_scanline_32 ( - iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask); - - return iter->buffer; -} - -static uint32_t * -src_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) -{ - iter->image->bits.get_scanline_64 ( - iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask); - - return iter->buffer; } void _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter) { - if (iter->flags & ITER_NARROW) - iter->get_scanline = src_get_scanline_narrow; - else - iter->get_scanline = src_get_scanline_wide; + pixman_format_code_t format = image->common.extended_format_code; + uint32_t flags = image->common.flags; + const fetcher_info_t *info; + for (info = fetcher_info; info->format != PIXMAN_null; ++info) + { + if ((info->format == format || info->format == PIXMAN_any) && + (info->flags & flags) == info->flags) + { + if (iter->iter_flags & ITER_NARROW) + { + iter->get_scanline = info->get_scanline_32; + } + else + { + iter->data = info->get_scanline_32; + iter->get_scanline = info->get_scanline_64; + } + return; + } + } + + /* Just in case we somehow didn't find a scanline function */ + iter->get_scanline = _pixman_iter_get_scanline_noop; } static uint32_t * @@ -1409,9 +1420,9 @@ dest_write_back_wide (pixman_iter_t *iter) void _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter) { - if (iter->flags & ITER_16) + if (iter->iter_flags & ITER_16) { - if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == + if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) { iter->get_scanline = _pixman_iter_get_scanline_noop; @@ -1422,9 +1433,9 @@ _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter) } iter->write_back = dest_write_back_16; } - else if (iter->flags & ITER_NARROW) + else if (iter->iter_flags & ITER_NARROW) { - if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == + if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) { iter->get_scanline = _pixman_iter_get_scanline_noop; diff --git a/gfx/cairo/libpixman/src/pixman-combine32.c b/gfx/cairo/libpixman/src/pixman-combine32.c index d98d3f8383d..c23f49df9f0 100644 --- a/gfx/cairo/libpixman/src/pixman-combine32.c +++ b/gfx/cairo/libpixman/src/pixman-combine32.c @@ -441,7 +441,7 @@ combine_saturate_u (pixman_implementation_t *imp, * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an * argument. Note that this implementation operates on premultiplied colors, * while the PDF specification does not. Therefore the code uses the formula - * ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) + * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) */ /* @@ -526,7 +526,7 @@ combine_multiply_ca (pixman_implementation_t *imp, UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida); \ \ *(dest + i) = result + \ - (DIV_ONE_UN8 (sa * da) << A_SHIFT) + \ + (DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) + \ (blend_ ## name (RED_8 (d), da, RED_8 (s), sa) << R_SHIFT) + \ (blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), sa) << G_SHIFT) + \ (blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), sa)); \ @@ -556,7 +556,7 @@ combine_multiply_ca (pixman_implementation_t *imp, UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (result, ~m, s, ida); \ \ result += \ - (DIV_ONE_UN8 (ALPHA_8 (m) * da) << A_SHIFT) + \ + (DIV_ONE_UN8 (ALPHA_8 (m) * (uint32_t)da) << A_SHIFT) + \ (blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m)) << R_SHIFT) + \ (blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)) << G_SHIFT) + \ (blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), BLUE_8 (m))); \ @@ -853,7 +853,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) * * r * set_sat (C, s) = set_sat (x * C, r * s) * - * The above holds for all non-zero x, because they x'es in the fraction for + * The above holds for all non-zero x, because the x'es in the fraction for * C_mid cancel out. Specifically, it holds for x = r: * * r * set_sat (C, s) = set_sat (r_c, rs) @@ -889,8 +889,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) * * a_s * a_d * B(s, d) * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1) - * = a_s * a_d * set_lum (set_sat (a_d * S, a_s * SAT (D)), - * a_s * LUM (D), a_s * a_d) + * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d) * */ @@ -931,7 +930,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) blend_ ## name (c, dc, da, sc, sa); \ \ *(dest + i) = result + \ - (DIV_ONE_UN8 (sa * da) << A_SHIFT) + \ + (DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) + \ (DIV_ONE_UN8 (c[0]) << R_SHIFT) + \ (DIV_ONE_UN8 (c[1]) << G_SHIFT) + \ (DIV_ONE_UN8 (c[2])); \ @@ -1148,9 +1147,7 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity) #undef CH_MIN #undef PDF_NON_SEPARABLE_BLEND_MODE -/* Overlay - * - * All of the disjoint composing functions +/* All of the disjoint/conjoint composing functions * * The four entries in the first column indicate what source contributions * come from each of the four areas of the picture -- areas covered by neither @@ -1171,6 +1168,9 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity) * (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0) * (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b) * (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0) + * + * See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more + * information about these operators. */ #define COMBINE_A_OUT 1 diff --git a/gfx/cairo/libpixman/src/pixman-combine32.h b/gfx/cairo/libpixman/src/pixman-combine32.h index 68bde4281a9..b5e157a1de3 100644 --- a/gfx/cairo/libpixman/src/pixman-combine32.h +++ b/gfx/cairo/libpixman/src/pixman-combine32.h @@ -29,10 +29,10 @@ */ #define MUL_UN8(a, b, t) \ - ((t) = (a) * (b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT )) + ((t) = (a) * (uint16_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT )) #define DIV_UN8(a, b) \ - (((uint16_t) (a) * MASK) / (b)) + (((uint16_t) (a) * MASK + ((b) / 2)) / (b)) #define ADD_UN8(x, y, t) \ ((t) = (x) + (y), \ diff --git a/gfx/cairo/libpixman/src/pixman-combine64.c b/gfx/cairo/libpixman/src/pixman-combine64.c index 850afba6ad1..1c85af8eec6 100644 --- a/gfx/cairo/libpixman/src/pixman-combine64.c +++ b/gfx/cairo/libpixman/src/pixman-combine64.c @@ -441,7 +441,7 @@ combine_saturate_u (pixman_implementation_t *imp, * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an * argument. Note that this implementation operates on premultiplied colors, * while the PDF specification does not. Therefore the code uses the formula - * ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) + * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) */ /* @@ -526,7 +526,7 @@ combine_multiply_ca (pixman_implementation_t *imp, UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16 (result, isa, s, ida); \ \ *(dest + i) = result + \ - (DIV_ONE_UN16 (sa * da) << A_SHIFT) + \ + (DIV_ONE_UN16 (sa * (uint64_t)da) << A_SHIFT) + \ (blend_ ## name (RED_16 (d), da, RED_16 (s), sa) << R_SHIFT) + \ (blend_ ## name (GREEN_16 (d), da, GREEN_16 (s), sa) << G_SHIFT) + \ (blend_ ## name (BLUE_16 (d), da, BLUE_16 (s), sa)); \ @@ -556,7 +556,7 @@ combine_multiply_ca (pixman_implementation_t *imp, UN16x4_MUL_UN16x4_ADD_UN16x4_MUL_UN16 (result, ~m, s, ida); \ \ result += \ - (DIV_ONE_UN16 (ALPHA_16 (m) * da) << A_SHIFT) + \ + (DIV_ONE_UN16 (ALPHA_16 (m) * (uint64_t)da) << A_SHIFT) + \ (blend_ ## name (RED_16 (d), da, RED_16 (s), RED_16 (m)) << R_SHIFT) + \ (blend_ ## name (GREEN_16 (d), da, GREEN_16 (s), GREEN_16 (m)) << G_SHIFT) + \ (blend_ ## name (BLUE_16 (d), da, BLUE_16 (s), BLUE_16 (m))); \ @@ -853,7 +853,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) * * r * set_sat (C, s) = set_sat (x * C, r * s) * - * The above holds for all non-zero x, because they x'es in the fraction for + * The above holds for all non-zero x, because the x'es in the fraction for * C_mid cancel out. Specifically, it holds for x = r: * * r * set_sat (C, s) = set_sat (r_c, rs) @@ -889,8 +889,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) * * a_s * a_d * B(s, d) * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1) - * = a_s * a_d * set_lum (set_sat (a_d * S, a_s * SAT (D)), - * a_s * LUM (D), a_s * a_d) + * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d) * */ @@ -931,7 +930,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) blend_ ## name (c, dc, da, sc, sa); \ \ *(dest + i) = result + \ - (DIV_ONE_UN16 (sa * da) << A_SHIFT) + \ + (DIV_ONE_UN16 (sa * (uint64_t)da) << A_SHIFT) + \ (DIV_ONE_UN16 (c[0]) << R_SHIFT) + \ (DIV_ONE_UN16 (c[1]) << G_SHIFT) + \ (DIV_ONE_UN16 (c[2])); \ @@ -1148,9 +1147,7 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity) #undef CH_MIN #undef PDF_NON_SEPARABLE_BLEND_MODE -/* Overlay - * - * All of the disjoint composing functions +/* All of the disjoint/conjoint composing functions * * The four entries in the first column indicate what source contributions * come from each of the four areas of the picture -- areas covered by neither @@ -1171,6 +1168,9 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity) * (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0) * (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b) * (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0) + * + * See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more + * information about these operators. */ #define COMBINE_A_OUT 1 diff --git a/gfx/cairo/libpixman/src/pixman-combine64.h b/gfx/cairo/libpixman/src/pixman-combine64.h index ed9ffebf6c3..00413a85f6a 100644 --- a/gfx/cairo/libpixman/src/pixman-combine64.h +++ b/gfx/cairo/libpixman/src/pixman-combine64.h @@ -29,10 +29,10 @@ */ #define MUL_UN16(a, b, t) \ - ((t) = (a) * (b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT )) + ((t) = (a) * (uint32_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT )) #define DIV_UN16(a, b) \ - (((uint32_t) (a) * MASK) / (b)) + (((uint32_t) (a) * MASK + ((b) / 2)) / (b)) #define ADD_UN16(x, y, t) \ ((t) = (x) + (y), \ diff --git a/gfx/cairo/libpixman/src/pixman-compiler.h b/gfx/cairo/libpixman/src/pixman-compiler.h index 81be529a891..adcd777af3a 100644 --- a/gfx/cairo/libpixman/src/pixman-compiler.h +++ b/gfx/cairo/libpixman/src/pixman-compiler.h @@ -96,6 +96,10 @@ #endif +/* member offsets */ +#define CONTAINER_OF(type, member, data) \ + ((type *)(((uint8_t *)data) - offsetof (type, member))) + /* TLS */ #if defined(PIXMAN_NO_TLS) diff --git a/gfx/cairo/libpixman/src/pixman-conical-gradient.c b/gfx/cairo/libpixman/src/pixman-conical-gradient.c index 791d4f34402..8b52176e4fb 100644 --- a/gfx/cairo/libpixman/src/pixman-conical-gradient.c +++ b/gfx/cairo/libpixman/src/pixman-conical-gradient.c @@ -173,7 +173,7 @@ conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) void _pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) { - if (iter->flags & ITER_NARROW) + if (iter->iter_flags & ITER_NARROW) iter->get_scanline = conical_get_scanline_narrow; else iter->get_scanline = conical_get_scanline_wide; diff --git a/gfx/cairo/libpixman/src/pixman-fast-path.c b/gfx/cairo/libpixman/src/pixman-fast-path.c index b5198e048a9..bcf43d7feaa 100644 --- a/gfx/cairo/libpixman/src/pixman-fast-path.c +++ b/gfx/cairo/libpixman/src/pixman-fast-path.c @@ -809,6 +809,48 @@ fast_composite_add_8_8 (pixman_implementation_t *imp, } } +static void +fast_composite_add_0565_0565 (pixman_implementation_t *imp, + pixman_composite_info_t *info) +{ + PIXMAN_COMPOSITE_ARGS (info); + uint16_t *dst_line, *dst; + uint32_t d; + uint16_t *src_line, *src; + uint32_t s; + int dst_stride, src_stride; + int32_t w; + + PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint16_t, src_stride, src_line, 1); + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); + + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + src = src_line; + src_line += src_stride; + w = width; + + while (w--) + { + s = *src++; + if (s) + { + d = *dst; + s = CONVERT_0565_TO_8888 (s); + if (d) + { + d = CONVERT_0565_TO_8888 (d); + UN8x4_ADD_UN8x4 (s, d); + } + *dst = CONVERT_8888_TO_0565 (s); + } + dst++; + } + } +} + static void fast_composite_add_8888_8888 (pixman_implementation_t *imp, pixman_composite_info_t *info) @@ -1215,8 +1257,8 @@ scaled_bilinear_scanline_8888_565_OVER (uint16_t * dst, d = *dst; src = bilinear_interpolation (tl, tr, bl, br, - interpolation_coord(vx), - wb >> (8 - INTERPOLATION_PRECISION_BITS)); + pixman_fixed_to_bilinear_weight(vx), + wb); vx += unit_x; result = over (src, CONVERT_0565_TO_0888 (d)); *dst++ = CONVERT_8888_TO_0565(result); @@ -1248,8 +1290,8 @@ scaled_bilinear_scanline_8888_8888_OVER (uint32_t * dst, d = *dst; src = bilinear_interpolation (tl, tr, bl, br, - interpolation_coord(vx), - wb >> (8 - INTERPOLATION_PRECISION_BITS)); + pixman_fixed_to_bilinear_weight(vx), + wb); vx += unit_x; *dst++ = over (src, d); } @@ -1281,8 +1323,8 @@ scaled_bilinear_scanline_565_565_SRC (uint16_t * dst, CONVERT_0565_TO_8888(tr), CONVERT_0565_TO_8888(bl), CONVERT_0565_TO_8888(br), - interpolation_coord(vx), - wb >> (8 - INTERPOLATION_PRECISION_BITS)); + pixman_fixed_to_bilinear_weight(vx), + wb); vx += unit_x; *dst++ = CONVERT_8888_TO_0565(d); } @@ -1352,7 +1394,9 @@ scaled_bilinear_scanline_565_565_SRC (uint16_t * dst, uint16_t bl = src_bottom [pixman_fixed_to_int (vx)]; uint16_t br = src_bottom [pixman_fixed_to_int (vx) + 1]; - uint16_t d = bilinear_interpolation_565 (tl, tr, bl, br, (vx >> 12) & 0xf, wb >> 4); + uint16_t d = bilinear_interpolation_565 (tl, tr, bl, br, + pixman_fixed_to_bilinear_weight(vx), + wb); vx += unit_x; *dst++ = d; } @@ -1458,8 +1502,9 @@ fast_composite_tiled_repeat (pixman_implementation_t *imp, src_bpp = PIXMAN_FORMAT_BPP (src_image->bits.format); - if (src_image->bits.width < REPEAT_MIN_WIDTH && - (src_bpp == 32 || src_bpp == 16 || src_bpp == 8)) + if (src_image->bits.width < REPEAT_MIN_WIDTH && + (src_bpp == 32 || src_bpp == 16 || src_bpp == 8) && + !src_image->bits.indexed) { sx = src_x; sx = MOD (sx, src_image->bits.width); @@ -2056,6 +2101,8 @@ static const pixman_fast_path_t c_fast_paths[] = PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, fast_composite_over_8888_8888), PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, fast_composite_over_8888_8888), PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, fast_composite_over_8888_0565), + PIXMAN_STD_FAST_PATH (ADD, r5g6b5, null, r5g6b5, fast_composite_add_0565_0565), + PIXMAN_STD_FAST_PATH (ADD, b5g6r5, null, b5g6r5, fast_composite_add_0565_0565), PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, fast_composite_add_8888_8888), PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, fast_composite_add_8888_8888), PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, fast_composite_add_8_8), diff --git a/gfx/cairo/libpixman/src/pixman-general.c b/gfx/cairo/libpixman/src/pixman-general.c index 013609995f8..b6b68789883 100644 --- a/gfx/cairo/libpixman/src/pixman-general.c +++ b/gfx/cairo/libpixman/src/pixman-general.c @@ -110,7 +110,7 @@ general_composite_rect (pixman_implementation_t *imp, pixman_iter_t src_iter, mask_iter, dest_iter; pixman_combine_32_func_t compose; pixman_bool_t component_alpha; - iter_flags_t narrow, src_flags; + iter_flags_t narrow, src_iter_flags; iter_flags_t rgb16; int Bpp; int i; @@ -155,14 +155,14 @@ general_composite_rect (pixman_implementation_t *imp, dest_buffer = mask_buffer + width * Bpp; /* src iter */ - src_flags = narrow | op_flags[op].src | rgb16; + src_iter_flags = narrow | op_flags[op].src | rgb16; _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image, src_x, src_y, width, height, - src_buffer, src_flags); + src_buffer, src_iter_flags, info->src_flags); /* mask iter */ - if ((src_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == + if ((src_iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) { /* If it doesn't matter what the source is, then it doesn't matter @@ -179,12 +179,12 @@ general_composite_rect (pixman_implementation_t *imp, _pixman_implementation_src_iter_init ( imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height, - mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB)); + mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB), info->mask_flags); /* dest iter */ _pixman_implementation_dest_iter_init ( imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height, - dest_buffer, narrow | op_flags[op].dst | rgb16); + dest_buffer, narrow | op_flags[op].dst | rgb16, info->dest_flags); compose = _pixman_implementation_lookup_combiner ( imp->toplevel, op, component_alpha, narrow, !!rgb16); diff --git a/gfx/cairo/libpixman/src/pixman-glyph.c b/gfx/cairo/libpixman/src/pixman-glyph.c new file mode 100644 index 00000000000..cbc3637fa9d --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-glyph.c @@ -0,0 +1,676 @@ +/* + * Copyright 2010, 2012, Soren Sandmann + * Copyright 2010, 2011, 2012, Red Hat, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Soren Sandmann + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "pixman-private.h" + +#include + +typedef struct glyph_metrics_t glyph_metrics_t; +typedef struct glyph_t glyph_t; + +#define TOMBSTONE ((glyph_t *)0x1) + +/* XXX: These numbers are arbitrary---we've never done any measurements. + */ +#define N_GLYPHS_HIGH_WATER (16384) +#define N_GLYPHS_LOW_WATER (8192) +#define HASH_SIZE (2 * N_GLYPHS_HIGH_WATER) +#define HASH_MASK (HASH_SIZE - 1) + +struct glyph_t +{ + void * font_key; + void * glyph_key; + int origin_x; + int origin_y; + pixman_image_t * image; + pixman_link_t mru_link; +}; + +struct pixman_glyph_cache_t +{ + int n_glyphs; + int n_tombstones; + int freeze_count; + pixman_list_t mru; + glyph_t * glyphs[HASH_SIZE]; +}; + +static void +free_glyph (glyph_t *glyph) +{ + pixman_list_unlink (&glyph->mru_link); + pixman_image_unref (glyph->image); + free (glyph); +} + +static unsigned int +hash (const void *font_key, const void *glyph_key) +{ + size_t key = (size_t)font_key + (size_t)glyph_key; + + /* This hash function is based on one found on Thomas Wang's + * web page at + * + * http://www.concentric.net/~Ttwang/tech/inthash.htm + * + */ + key = (key << 15) - key - 1; + key = key ^ (key >> 12); + key = key + (key << 2); + key = key ^ (key >> 4); + key = key + (key << 3) + (key << 11); + key = key ^ (key >> 16); + + return key; +} + +static glyph_t * +lookup_glyph (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key) +{ + unsigned idx; + glyph_t *g; + + idx = hash (font_key, glyph_key); + while ((g = cache->glyphs[idx++ & HASH_MASK])) + { + if (g != TOMBSTONE && + g->font_key == font_key && + g->glyph_key == glyph_key) + { + return g; + } + } + + return NULL; +} + +static void +insert_glyph (pixman_glyph_cache_t *cache, + glyph_t *glyph) +{ + unsigned idx; + glyph_t **loc; + + idx = hash (glyph->font_key, glyph->glyph_key); + + /* Note: we assume that there is room in the table. If there isn't, + * this will be an infinite loop. + */ + do + { + loc = &cache->glyphs[idx++ & HASH_MASK]; + } while (*loc && *loc != TOMBSTONE); + + if (*loc == TOMBSTONE) + cache->n_tombstones--; + cache->n_glyphs++; + + *loc = glyph; +} + +static void +remove_glyph (pixman_glyph_cache_t *cache, + glyph_t *glyph) +{ + unsigned idx; + + idx = hash (glyph->font_key, glyph->glyph_key); + while (cache->glyphs[idx & HASH_MASK] != glyph) + idx++; + + cache->glyphs[idx & HASH_MASK] = TOMBSTONE; + cache->n_tombstones++; + cache->n_glyphs--; + + /* Eliminate tombstones if possible */ + if (cache->glyphs[(idx + 1) & HASH_MASK] == NULL) + { + while (cache->glyphs[idx & HASH_MASK] == TOMBSTONE) + { + cache->glyphs[idx & HASH_MASK] = NULL; + cache->n_tombstones--; + idx--; + } + } +} + +static void +clear_table (pixman_glyph_cache_t *cache) +{ + int i; + + for (i = 0; i < HASH_SIZE; ++i) + { + glyph_t *glyph = cache->glyphs[i]; + + if (glyph && glyph != TOMBSTONE) + free_glyph (glyph); + + cache->glyphs[i] = NULL; + } + + cache->n_glyphs = 0; + cache->n_tombstones = 0; +} + +PIXMAN_EXPORT pixman_glyph_cache_t * +pixman_glyph_cache_create (void) +{ + pixman_glyph_cache_t *cache; + + if (!(cache = malloc (sizeof *cache))) + return NULL; + + memset (cache->glyphs, 0, sizeof (cache->glyphs)); + cache->n_glyphs = 0; + cache->n_tombstones = 0; + cache->freeze_count = 0; + + pixman_list_init (&cache->mru); + + return cache; +} + +PIXMAN_EXPORT void +pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache) +{ + return_if_fail (cache->freeze_count == 0); + + clear_table (cache); + + free (cache); +} + +PIXMAN_EXPORT void +pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache) +{ + cache->freeze_count++; +} + +PIXMAN_EXPORT void +pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache) +{ + if (--cache->freeze_count == 0 && + cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER) + { + if (cache->n_tombstones > N_GLYPHS_HIGH_WATER) + { + /* More than half the entries are + * tombstones. Just dump the whole table. + */ + clear_table (cache); + } + + while (cache->n_glyphs > N_GLYPHS_LOW_WATER) + { + glyph_t *glyph = CONTAINER_OF (glyph_t, mru_link, cache->mru.tail); + + remove_glyph (cache, glyph); + free_glyph (glyph); + } + } +} + +PIXMAN_EXPORT const void * +pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key) +{ + return lookup_glyph (cache, font_key, glyph_key); +} + +PIXMAN_EXPORT const void * +pixman_glyph_cache_insert (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key, + int origin_x, + int origin_y, + pixman_image_t *image) +{ + glyph_t *glyph; + int32_t width, height; + + return_val_if_fail (cache->freeze_count > 0, NULL); + return_val_if_fail (image->type == BITS, NULL); + + width = image->bits.width; + height = image->bits.height; + + if (cache->n_glyphs >= HASH_SIZE) + return NULL; + + if (!(glyph = malloc (sizeof *glyph))) + return NULL; + + glyph->font_key = font_key; + glyph->glyph_key = glyph_key; + glyph->origin_x = origin_x; + glyph->origin_y = origin_y; + + if (!(glyph->image = pixman_image_create_bits ( + image->bits.format, width, height, NULL, -1))) + { + free (glyph); + return NULL; + } + + pixman_image_composite32 (PIXMAN_OP_SRC, + image, NULL, glyph->image, 0, 0, 0, 0, 0, 0, + width, height); + + if (PIXMAN_FORMAT_A (glyph->image->bits.format) != 0 && + PIXMAN_FORMAT_RGB (glyph->image->bits.format) != 0) + { + pixman_image_set_component_alpha (glyph->image, TRUE); + } + + pixman_list_prepend (&cache->mru, &glyph->mru_link); + + _pixman_image_validate (glyph->image); + insert_glyph (cache, glyph); + + return glyph; +} + +PIXMAN_EXPORT void +pixman_glyph_cache_remove (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key) +{ + glyph_t *glyph; + + if ((glyph = lookup_glyph (cache, font_key, glyph_key))) + { + remove_glyph (cache, glyph); + + free_glyph (glyph); + } +} + +PIXMAN_EXPORT void +pixman_glyph_get_extents (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs, + pixman_box32_t *extents) +{ + int i; + + extents->x1 = extents->y1 = INT32_MAX; + extents->x2 = extents->y2 = INT32_MIN; + + for (i = 0; i < n_glyphs; ++i) + { + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; + int x1, y1, x2, y2; + + x1 = glyphs[i].x - glyph->origin_x; + y1 = glyphs[i].y - glyph->origin_y; + x2 = glyphs[i].x - glyph->origin_x + glyph->image->bits.width; + y2 = glyphs[i].y - glyph->origin_y + glyph->image->bits.height; + + if (x1 < extents->x1) + extents->x1 = x1; + if (y1 < extents->y1) + extents->y1 = y1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y2 > extents->y2) + extents->y2 = y2; + } +} + +/* This function returns a format that is suitable for use as a mask for the + * set of glyphs in question. + */ +PIXMAN_EXPORT pixman_format_code_t +pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t * glyphs) +{ + pixman_format_code_t format = PIXMAN_a1; + int i; + + for (i = 0; i < n_glyphs; ++i) + { + const glyph_t *glyph = glyphs[i].glyph; + pixman_format_code_t glyph_format = glyph->image->bits.format; + + if (PIXMAN_FORMAT_TYPE (glyph_format) == PIXMAN_TYPE_A) + { + if (PIXMAN_FORMAT_A (glyph_format) > PIXMAN_FORMAT_A (format)) + format = glyph_format; + } + else + { + return PIXMAN_a8r8g8b8; + } + } + + return format; +} + +static pixman_bool_t +box32_intersect (pixman_box32_t *dest, + const pixman_box32_t *box1, + const pixman_box32_t *box2) +{ + dest->x1 = MAX (box1->x1, box2->x1); + dest->y1 = MAX (box1->y1, box2->y1); + dest->x2 = MIN (box1->x2, box2->x2); + dest->y2 = MIN (box1->y2, box2->y2); + + return dest->x2 > dest->x1 && dest->y2 > dest->y1; +} + +PIXMAN_EXPORT void +pixman_composite_glyphs_no_mask (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + int32_t src_x, + int32_t src_y, + int32_t dest_x, + int32_t dest_y, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs) +{ + pixman_region32_t region; + pixman_format_code_t glyph_format = PIXMAN_null; + uint32_t glyph_flags = 0; + pixman_format_code_t dest_format; + uint32_t dest_flags; + pixman_composite_func_t func = NULL; + pixman_implementation_t *implementation = NULL; + pixman_composite_info_t info; + int i; + + _pixman_image_validate (src); + _pixman_image_validate (dest); + + dest_format = dest->common.extended_format_code; + dest_flags = dest->common.flags; + + pixman_region32_init (®ion); + if (!_pixman_compute_composite_region32 ( + ®ion, + src, NULL, dest, + src_x - dest_x, src_y - dest_y, 0, 0, 0, 0, + dest->bits.width, dest->bits.height)) + { + goto out; + } + + info.op = op; + info.src_image = src; + info.dest_image = dest; + info.src_flags = src->common.flags; + info.dest_flags = dest->common.flags; + + for (i = 0; i < n_glyphs; ++i) + { + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; + pixman_image_t *glyph_img = glyph->image; + pixman_box32_t glyph_box; + pixman_box32_t *pbox; + uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; + pixman_box32_t composite_box; + int n; + + glyph_box.x1 = dest_x + glyphs[i].x - glyph->origin_x; + glyph_box.y1 = dest_y + glyphs[i].y - glyph->origin_y; + glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; + glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; + + pbox = pixman_region32_rectangles (®ion, &n); + + info.mask_image = glyph_img; + + while (n--) + { + if (box32_intersect (&composite_box, pbox, &glyph_box)) + { + if (glyph_img->common.extended_format_code != glyph_format || + glyph_img->common.flags != glyph_flags) + { + glyph_format = glyph_img->common.extended_format_code; + glyph_flags = glyph_img->common.flags; + + _pixman_lookup_composite_function ( + get_implementation(), op, + src->common.extended_format_code, src->common.flags, + glyph_format, glyph_flags | extra, + dest_format, dest_flags, + &implementation, &func); + + if (!func) + goto out; + } + + info.src_x = src_x + composite_box.x1 - dest_x; + info.src_y = src_y + composite_box.y1 - dest_y; + info.mask_x = composite_box.x1 - (dest_x + glyphs[i].x - glyph->origin_x); + info.mask_y = composite_box.y1 - (dest_y + glyphs[i].y - glyph->origin_y); + info.dest_x = composite_box.x1; + info.dest_y = composite_box.y1; + info.width = composite_box.x2 - composite_box.x1; + info.height = composite_box.y2 - composite_box.y1; + + info.mask_flags = glyph_flags; + + func (implementation, &info); + } + + pbox++; + } + pixman_list_move_to_front (&cache->mru, &glyph->mru_link); + } + +out: + pixman_region32_fini (®ion); +} + +static void +add_glyphs (pixman_glyph_cache_t *cache, + pixman_image_t *dest, + int off_x, int off_y, + int n_glyphs, pixman_glyph_t *glyphs) +{ + pixman_format_code_t glyph_format = PIXMAN_null; + uint32_t glyph_flags = 0; + pixman_composite_func_t func = NULL; + pixman_implementation_t *implementation = NULL; + uint32_t dest_format; + uint32_t dest_flags; + pixman_box32_t dest_box; + pixman_composite_info_t info; + pixman_image_t *white_img = NULL; + pixman_bool_t white_src = FALSE; + int i; + + _pixman_image_validate (dest); + + dest_format = dest->common.extended_format_code; + dest_flags = dest->common.flags; + + info.op = PIXMAN_OP_ADD; + info.dest_image = dest; + info.src_x = 0; + info.src_y = 0; + info.dest_flags = dest_flags; + + dest_box.x1 = 0; + dest_box.y1 = 0; + dest_box.x2 = dest->bits.width; + dest_box.y2 = dest->bits.height; + + for (i = 0; i < n_glyphs; ++i) + { + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; + pixman_image_t *glyph_img = glyph->image; + pixman_box32_t glyph_box; + pixman_box32_t composite_box; + + if (glyph_img->common.extended_format_code != glyph_format || + glyph_img->common.flags != glyph_flags) + { + pixman_format_code_t src_format, mask_format; + + glyph_format = glyph_img->common.extended_format_code; + glyph_flags = glyph_img->common.flags; + + if (glyph_format == dest->bits.format) + { + src_format = glyph_format; + mask_format = PIXMAN_null; + info.src_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; + info.mask_flags = FAST_PATH_IS_OPAQUE; + info.mask_image = NULL; + white_src = FALSE; + } + else + { + if (!white_img) + { + pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff }; + + if (!(white_img = pixman_image_create_solid_fill (&white))) + goto out; + + _pixman_image_validate (white_img); + } + + src_format = PIXMAN_solid; + mask_format = glyph_format; + info.src_flags = white_img->common.flags; + info.mask_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; + info.src_image = white_img; + white_src = TRUE; + } + + _pixman_lookup_composite_function ( + get_implementation(), PIXMAN_OP_ADD, + src_format, info.src_flags, + mask_format, info.mask_flags, + dest_format, dest_flags, + &implementation, &func); + + if (!func) + goto out; + } + + glyph_box.x1 = glyphs[i].x - glyph->origin_x + off_x; + glyph_box.y1 = glyphs[i].y - glyph->origin_y + off_y; + glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; + glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; + + if (box32_intersect (&composite_box, &glyph_box, &dest_box)) + { + int src_x = composite_box.x1 - glyph_box.x1; + int src_y = composite_box.y1 - glyph_box.y1; + + if (white_src) + info.mask_image = glyph_img; + else + info.src_image = glyph_img; + + info.mask_x = info.src_x = src_x; + info.mask_y = info.src_y = src_y; + info.dest_x = composite_box.x1; + info.dest_y = composite_box.y1; + info.width = composite_box.x2 - composite_box.x1; + info.height = composite_box.y2 - composite_box.y1; + + func (implementation, &info); + + pixman_list_move_to_front (&cache->mru, &glyph->mru_link); + } + } + +out: + if (white_img) + pixman_image_unref (white_img); +} + +/* Conceptually, for each glyph, (white IN glyph) is PIXMAN_OP_ADDed to an + * infinitely big mask image at the position such that the glyph origin point + * is positioned at the (glyphs[i].x, glyphs[i].y) point. + * + * Then (mask_x, mask_y) in the infinite mask and (src_x, src_y) in the source + * image are both aligned with (dest_x, dest_y) in the destination image. Then + * these three images are composited within the + * + * (dest_x, dest_y, dst_x + width, dst_y + height) + * + * rectangle. + * + * TODO: + * - Trim the mask to the destination clip/image? + * - Trim composite region based on sources, when the op ignores 0s. + */ +PIXMAN_EXPORT void +pixman_composite_glyphs (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + pixman_format_code_t mask_format, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs) +{ + pixman_image_t *mask; + + if (!(mask = pixman_image_create_bits (mask_format, width, height, NULL, -1))) + return; + + if (PIXMAN_FORMAT_A (mask_format) != 0 && + PIXMAN_FORMAT_RGB (mask_format) != 0) + { + pixman_image_set_component_alpha (mask, TRUE); + } + + add_glyphs (cache, mask, - mask_x, - mask_y, n_glyphs, glyphs); + + pixman_image_composite32 (op, src, mask, dest, + src_x, src_y, + 0, 0, + dest_x, dest_y, + width, height); + + pixman_image_unref (mask); +} diff --git a/gfx/cairo/libpixman/src/pixman-image.c b/gfx/cairo/libpixman/src/pixman-image.c index 97421c498f9..d2e75978c2d 100644 --- a/gfx/cairo/libpixman/src/pixman-image.c +++ b/gfx/cairo/libpixman/src/pixman-image.c @@ -883,16 +883,38 @@ _pixman_image_get_solid (pixman_implementation_t *imp, pixman_format_code_t format) { uint32_t result; - pixman_iter_t iter; - _pixman_implementation_src_iter_init ( - imp, &iter, image, 0, 0, 1, 1, - (uint8_t *)&result, ITER_NARROW); + if (image->type == SOLID) + { + result = image->solid.color_32; + } + else if (image->type == BITS) + { + if (image->bits.format == PIXMAN_a8r8g8b8) + result = image->bits.bits[0]; + else if (image->bits.format == PIXMAN_x8r8g8b8) + result = image->bits.bits[0] | 0xff000000; + else if (image->bits.format == PIXMAN_a8) + result = (*(uint8_t *)image->bits.bits) << 24; + else + goto otherwise; + } + else + { + pixman_iter_t iter; - result = *iter.get_scanline (&iter, NULL); + otherwise: + _pixman_implementation_src_iter_init ( + imp, &iter, image, 0, 0, 1, 1, + (uint8_t *)&result, + ITER_NARROW, image->common.flags); + + result = *iter.get_scanline (&iter, NULL); + } /* If necessary, convert RGB <--> BGR. */ - if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB) + if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB + && PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB) { result = (((result & 0xff000000) >> 0) | ((result & 0x00ff0000) >> 16) | diff --git a/gfx/cairo/libpixman/src/pixman-implementation.c b/gfx/cairo/libpixman/src/pixman-implementation.c index 7d6103dd4fb..887a149ef72 100644 --- a/gfx/cairo/libpixman/src/pixman-implementation.c +++ b/gfx/cairo/libpixman/src/pixman-implementation.c @@ -191,7 +191,8 @@ _pixman_implementation_src_iter_init (pixman_implementation_t *imp, int width, int height, uint8_t *buffer, - iter_flags_t flags) + iter_flags_t iter_flags, + uint32_t image_flags) { iter->image = image; iter->buffer = (uint32_t *)buffer; @@ -199,7 +200,8 @@ _pixman_implementation_src_iter_init (pixman_implementation_t *imp, iter->y = y; iter->width = width; iter->height = height; - iter->flags = flags; + iter->iter_flags = iter_flags; + iter->image_flags = image_flags; (*imp->src_iter_init) (imp, iter); } @@ -213,7 +215,8 @@ _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, int width, int height, uint8_t *buffer, - iter_flags_t flags) + iter_flags_t iter_flags, + uint32_t image_flags) { iter->image = image; iter->buffer = (uint32_t *)buffer; @@ -221,7 +224,59 @@ _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, iter->y = y; iter->width = width; iter->height = height; - iter->flags = flags; + iter->iter_flags = iter_flags; + iter->image_flags = image_flags; (*imp->dest_iter_init) (imp, iter); } + +pixman_bool_t +_pixman_disabled (const char *name) +{ + const char *env; + + if ((env = getenv ("PIXMAN_DISABLE"))) + { + do + { + const char *end; + int len; + + if ((end = strchr (env, ' '))) + len = end - env; + else + len = strlen (env); + + if (strlen (name) == len && strncmp (name, env, len) == 0) + { + printf ("pixman: Disabled %s implementation\n", name); + return TRUE; + } + + env += len; + } + while (*env++); + } + + return FALSE; +} + +pixman_implementation_t * +_pixman_choose_implementation (void) +{ + pixman_implementation_t *imp; + + imp = _pixman_implementation_create_general(); + + if (!_pixman_disabled ("fast")) + imp = _pixman_implementation_create_fast_path (imp); + + imp = _pixman_x86_get_implementations (imp); + imp = _pixman_arm_get_implementations (imp); + imp = _pixman_ppc_get_implementations (imp); + imp = _pixman_mips_get_implementations (imp); + + imp = _pixman_implementation_create_noop (imp); + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman-inlines.h b/gfx/cairo/libpixman/src/pixman-inlines.h index 6790f0fa2ec..a9a65812dec 100644 --- a/gfx/cairo/libpixman/src/pixman-inlines.h +++ b/gfx/cairo/libpixman/src/pixman-inlines.h @@ -81,27 +81,13 @@ repeat (pixman_repeat_t repeat, int *c, int size) return TRUE; } -#ifdef MOZ_GFX_OPTIMIZE_MOBILE -#define LOW_QUALITY_INTERPOLATION -#define LOWER_QUALITY_INTERPOLATION -#endif - -#ifdef LOW_QUALITY_INTERPOLATION -#define INTERPOLATION_PRECISION_BITS 4 -#else -#define INTERPOLATION_PRECISION_BITS 8 -#endif -static force_inline int32_t -interpolation_coord(pixman_fixed_t t) +static force_inline int +pixman_fixed_to_bilinear_weight (pixman_fixed_t x) { -#ifdef LOW_QUALITY_INTERPOLATION - return (t >> 12) & 0xf; -#else - return (t >> 8) & 0xff; -#endif + return (x >> (16 - BILINEAR_INTERPOLATION_BITS)) & + ((1 << BILINEAR_INTERPOLATION_BITS) - 1); } - #if SIZEOF_LONG > 4 static force_inline uint32_t @@ -113,6 +99,9 @@ bilinear_interpolation (uint32_t tl, uint32_t tr, uint64_t tl64, tr64, bl64, br64; uint64_t f, r; + distx <<= (8 - BILINEAR_INTERPOLATION_BITS); + disty <<= (8 - BILINEAR_INTERPOLATION_BITS); + distxy = distx * disty; distxiy = distx * (256 - disty); distixy = (256 - distx) * disty; @@ -184,6 +173,9 @@ bilinear_interpolation (uint32_t tl, uint32_t tr, int distxy, distxiy, distixy, distixiy; uint32_t f, r; + distx <<= (8 - BILINEAR_INTERPOLATION_BITS); + disty <<= (8 - BILINEAR_INTERPOLATION_BITS); + distxy = distx * disty; distxiy = (distx << 8) - distxy; /* distx * (256 - disty) */ distixy = (disty << 8) - distxy; /* disty * (256 - distx) */ @@ -814,12 +806,14 @@ bilinear_pad_repeat_get_scanline_bounds (int32_t source_image_width, * all source pixels are fetched from zero padding * zone for NONE repeat * - * Note: normally the sum of 'weight_top' and 'weight_bottom' is equal to 256, - * but sometimes it may be less than that for NONE repeat when handling - * fuzzy antialiased top or bottom image edges. Also both top and - * bottom weight variables are guaranteed to have value in 0-255 - * range and can fit into unsigned byte or be used with 8-bit SIMD - * multiplication instructions. + * Note: normally the sum of 'weight_top' and 'weight_bottom' is equal to + * BILINEAR_INTERPOLATION_RANGE, but sometimes it may be less than that + * for NONE repeat when handling fuzzy antialiased top or bottom image + * edges. Also both top and bottom weight variables are guaranteed to + * have value, which is less than BILINEAR_INTERPOLATION_RANGE. + * For example, the weights can fit into unsigned byte or be used + * with 8-bit SIMD multiplication instructions for 8-bit interpolation + * precision. */ /* Replace a single "scanline_func" with "fetch_func" & "op_func" to allow optional @@ -974,18 +968,18 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp, } \ \ y1 = pixman_fixed_to_int (vy); \ - weight2 = (vy >> 8) & 0xff; \ + weight2 = pixman_fixed_to_bilinear_weight (vy); \ if (weight2) \ { \ - /* normal case, both row weights are in 0-255 range and fit unsigned byte */ \ + /* both weight1 and weight2 are smaller than BILINEAR_INTERPOLATION_RANGE */ \ y2 = y1 + 1; \ - weight1 = 256 - weight2; \ + weight1 = BILINEAR_INTERPOLATION_RANGE - weight2; \ } \ else \ { \ - /* set both top and bottom row to the same scanline, and weights to 128+128 */ \ + /* set both top and bottom row to the same scanline and tweak weights */ \ y2 = y1; \ - weight1 = weight2 = 128; \ + weight1 = weight2 = BILINEAR_INTERPOLATION_RANGE / 2; \ } \ vy += unit_y; \ if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \ diff --git a/gfx/cairo/libpixman/src/pixman-linear-gradient.c b/gfx/cairo/libpixman/src/pixman-linear-gradient.c index 20f94f7934c..148f6a30d7f 100644 --- a/gfx/cairo/libpixman/src/pixman-linear-gradient.c +++ b/gfx/cairo/libpixman/src/pixman-linear-gradient.c @@ -398,9 +398,9 @@ _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) if (0 && linear_gradient_is_horizontal ( iter->image, iter->x, iter->y, iter->width, iter->height)) { - if (iter->flags & ITER_16) + if (iter->iter_flags & ITER_16) linear_get_scanline_16 (iter, NULL); - else if (iter->flags & ITER_NARROW) + else if (iter->iter_flags & ITER_NARROW) linear_get_scanline_narrow (iter, NULL); else linear_get_scanline_wide (iter, NULL); @@ -409,9 +409,9 @@ _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) } else { - if (iter->flags & ITER_16) + if (iter->iter_flags & ITER_16) iter->get_scanline = linear_get_scanline_16; - else if (iter->flags & ITER_NARROW) + else if (iter->iter_flags & ITER_NARROW) iter->get_scanline = linear_get_scanline_narrow; else iter->get_scanline = linear_get_scanline_wide; diff --git a/gfx/cairo/libpixman/src/pixman-matrix.c b/gfx/cairo/libpixman/src/pixman-matrix.c index 8d0d9732533..a029ab75753 100644 --- a/gfx/cairo/libpixman/src/pixman-matrix.c +++ b/gfx/cairo/libpixman/src/pixman-matrix.c @@ -25,7 +25,7 @@ */ #ifdef HAVE_CONFIG_H -#include "config.h" +#include #endif #include @@ -471,8 +471,8 @@ pixman_f_transform_invert (struct pixman_f_transform * dst, { double det; int i, j; - static int a[3] = { 2, 2, 1 }; - static int b[3] = { 1, 0, 0 }; + static const int a[3] = { 2, 2, 1 }; + static const int b[3] = { 1, 0, 0 }; det = 0; for (i = 0; i < 3; i++) diff --git a/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S b/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S new file mode 100644 index 00000000000..a8fccd5ad7a --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S @@ -0,0 +1,1521 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nemanja Lukic (nlukic@mips.com) + */ + +#include "pixman-private.h" +#include "pixman-mips-dspr2-asm.h" + +LEAF_MIPS_DSPR2(pixman_fill_buff16_mips) +/* + * a0 - *dest + * a1 - count (bytes) + * a2 - value to fill buffer with + */ + + beqz a1, 3f + andi t1, a0, 0x0002 + beqz t1, 0f /* check if address is 4-byte aligned */ + nop + sh a2, 0(a0) + addiu a0, a0, 2 + addiu a1, a1, -2 +0: + srl t1, a1, 5 /* t1 how many multiples of 32 bytes */ + replv.ph a2, a2 /* replicate fill value (16bit) in a2 */ + beqz t1, 2f + nop +1: + addiu t1, t1, -1 + beqz t1, 11f + addiu a1, a1, -32 + pref 30, 32(a0) + sw a2, 0(a0) + sw a2, 4(a0) + sw a2, 8(a0) + sw a2, 12(a0) + sw a2, 16(a0) + sw a2, 20(a0) + sw a2, 24(a0) + sw a2, 28(a0) + b 1b + addiu a0, a0, 32 +11: + sw a2, 0(a0) + sw a2, 4(a0) + sw a2, 8(a0) + sw a2, 12(a0) + sw a2, 16(a0) + sw a2, 20(a0) + sw a2, 24(a0) + sw a2, 28(a0) + addiu a0, a0, 32 +2: + blez a1, 3f + addiu a1, a1, -2 + sh a2, 0(a0) + b 2b + addiu a0, a0, 2 +3: + jr ra + nop + +END(pixman_fill_buff16_mips) + +LEAF_MIPS32R2(pixman_fill_buff32_mips) +/* + * a0 - *dest + * a1 - count (bytes) + * a2 - value to fill buffer with + */ + + beqz a1, 3f + nop + srl t1, a1, 5 /* t1 how many multiples of 32 bytes */ + beqz t1, 2f + nop +1: + addiu t1, t1, -1 + beqz t1, 11f + addiu a1, a1, -32 + pref 30, 32(a0) + sw a2, 0(a0) + sw a2, 4(a0) + sw a2, 8(a0) + sw a2, 12(a0) + sw a2, 16(a0) + sw a2, 20(a0) + sw a2, 24(a0) + sw a2, 28(a0) + b 1b + addiu a0, a0, 32 +11: + sw a2, 0(a0) + sw a2, 4(a0) + sw a2, 8(a0) + sw a2, 12(a0) + sw a2, 16(a0) + sw a2, 20(a0) + sw a2, 24(a0) + sw a2, 28(a0) + addiu a0, a0, 32 +2: + blez a1, 3f + addiu a1, a1, -4 + sw a2, 0(a0) + b 2b + addiu a0, a0, 4 +3: + jr ra + nop + +END(pixman_fill_buff32_mips) + +LEAF_MIPS_DSPR2(pixman_composite_src_8888_0565_asm_mips) +/* + * a0 - dst (r5g6b5) + * a1 - src (a8r8g8b8) + * a2 - w + */ + + beqz a2, 3f + nop + addiu t1, a2, -1 + beqz t1, 2f + nop + li t4, 0xf800f800 + li t5, 0x07e007e0 + li t6, 0x001f001f +1: + lw t0, 0(a1) + lw t1, 4(a1) + addiu a1, a1, 8 + addiu a2, a2, -2 + + CONVERT_2x8888_TO_2x0565 t0, t1, t2, t3, t4, t5, t6, t7, t8 + + sh t2, 0(a0) + sh t3, 2(a0) + + addiu t2, a2, -1 + bgtz t2, 1b + addiu a0, a0, 4 +2: + beqz a2, 3f + nop + lw t0, 0(a1) + + CONVERT_1x8888_TO_1x0565 t0, t1, t2, t3 + + sh t1, 0(a0) +3: + j ra + nop + +END(pixman_composite_src_8888_0565_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_src_0565_8888_asm_mips) +/* + * a0 - dst (a8r8g8b8) + * a1 - src (r5g6b5) + * a2 - w + */ + + beqz a2, 3f + nop + addiu t1, a2, -1 + beqz t1, 2f + nop + li t4, 0x07e007e0 + li t5, 0x001F001F +1: + lhu t0, 0(a1) + lhu t1, 2(a1) + addiu a1, a1, 4 + addiu a2, a2, -2 + + CONVERT_2x0565_TO_2x8888 t0, t1, t2, t3, t4, t5, t6, t7, t8, t9 + + sw t2, 0(a0) + sw t3, 4(a0) + + addiu t2, a2, -1 + bgtz t2, 1b + addiu a0, a0, 8 +2: + beqz a2, 3f + nop + lhu t0, 0(a1) + + CONVERT_1x0565_TO_1x8888 t0, t1, t2, t3 + + sw t1, 0(a0) +3: + j ra + nop + +END(pixman_composite_src_0565_8888_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_src_x888_8888_asm_mips) +/* + * a0 - dst (a8r8g8b8) + * a1 - src (x8r8g8b8) + * a2 - w + */ + + beqz a2, 4f + nop + li t9, 0xff000000 + srl t8, a2, 3 /* t1 = how many multiples of 8 src pixels */ + beqz t8, 3f /* branch if less than 8 src pixels */ + nop +1: + addiu t8, t8, -1 + beqz t8, 2f + addiu a2, a2, -8 + pref 0, 32(a1) + lw t0, 0(a1) + lw t1, 4(a1) + lw t2, 8(a1) + lw t3, 12(a1) + lw t4, 16(a1) + lw t5, 20(a1) + lw t6, 24(a1) + lw t7, 28(a1) + addiu a1, a1, 32 + or t0, t0, t9 + or t1, t1, t9 + or t2, t2, t9 + or t3, t3, t9 + or t4, t4, t9 + or t5, t5, t9 + or t6, t6, t9 + or t7, t7, t9 + pref 30, 32(a0) + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + b 1b + addiu a0, a0, 32 +2: + lw t0, 0(a1) + lw t1, 4(a1) + lw t2, 8(a1) + lw t3, 12(a1) + lw t4, 16(a1) + lw t5, 20(a1) + lw t6, 24(a1) + lw t7, 28(a1) + addiu a1, a1, 32 + or t0, t0, t9 + or t1, t1, t9 + or t2, t2, t9 + or t3, t3, t9 + or t4, t4, t9 + or t5, t5, t9 + or t6, t6, t9 + or t7, t7, t9 + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + beqz a2, 4f + addiu a0, a0, 32 +3: + lw t0, 0(a1) + addiu a1, a1, 4 + addiu a2, a2, -1 + or t1, t0, t9 + sw t1, 0(a0) + bnez a2, 3b + addiu a0, a0, 4 +4: + jr ra + nop + +END(pixman_composite_src_x888_8888_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_over_n_8888_8888_ca_asm_mips) +/* + * a0 - dst (a8r8g8b8) + * a1 - src (32bit constant) + * a2 - mask (a8r8g8b8) + * a3 - w + */ + + SAVE_REGS_ON_STACK 8, s0, s1, s2, s3, s4, s5 + beqz a3, 4f + nop + li t6, 0xff + addiu t7, zero, -1 /* t7 = 0xffffffff */ + srl t8, a1, 24 /* t8 = srca */ + li t9, 0x00ff00ff + addiu t1, a3, -1 + beqz t1, 3f /* last pixel */ + nop + beq t8, t6, 2f /* if (srca == 0xff) */ + nop +1: + /* a1 = src */ + lw t0, 0(a2) /* t0 = mask */ + lw t1, 4(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 12f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 8 + and t3, t0, t1 + move t4, a1 /* t4 = src */ + move t5, a1 /* t5 = src */ + lw t2, 0(a0) /* t2 = dst */ + beq t3, t7, 11f /* if (t0 == 0xffffffff) && (t1 == 0xffffffff) */ + lw t3, 4(a0) /* t3 = dst */ + MIPS_2xUN8x4_MUL_2xUN8x4 a1, a1, t0, t1, t4, t5, t9, s0, s1, s2, s3, s4, s5 + MIPS_2xUN8x4_MUL_2xUN8 t0, t1, t8, t8, t0, t1, t9, s0, s1, s2, s3, s4, s5 +11: + not t0, t0 + not t1, t1 + MIPS_2xUN8x4_MUL_2xUN8x4 t2, t3, t0, t1, t2, t3, t9, s0, s1, s2, s3, s4, s5 + addu_s.qb t2, t4, t2 + addu_s.qb t3, t5, t3 + sw t2, 0(a0) + sw t3, 4(a0) +12: + addiu a3, a3, -2 + addiu t1, a3, -1 + bgtz t1, 1b + addiu a0, a0, 8 + b 3f + nop +2: + /* a1 = src */ + lw t0, 0(a2) /* t0 = mask */ + lw t1, 4(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 22f /* if (t0 == 0) & (t1 == 0) */ + addiu a2, a2, 8 + and t2, t0, t1 + move t4, a1 + beq t2, t7, 21f /* if (t0 == 0xffffffff) && (t1 == 0xffffffff) */ + move t5, a1 + lw t2, 0(a0) /* t2 = dst */ + lw t3, 4(a0) /* t3 = dst */ + MIPS_2xUN8x4_MUL_2xUN8x4 a1, a1, t0, t1, t4, t5, t9, s0, s1, s2, s3, s4, s5 + not t0, t0 + not t1, t1 + MIPS_2xUN8x4_MUL_2xUN8x4 t2, t3, t0, t1, t2, t3, t9, s0, s1, s2, s3, s4, s5 + addu_s.qb t4, t4, t2 + addu_s.qb t5, t5, t3 +21: + sw t4, 0(a0) + sw t5, 4(a0) +22: + addiu a3, a3, -2 + addiu t1, a3, -1 + bgtz t1, 2b + addiu a0, a0, 8 +3: + blez a3, 4f + nop + /* a1 = src */ + lw t1, 0(a2) /* t1 = mask */ + beqz t1, 4f + nop + move t2, a1 /* t2 = src */ + beq t1, t7, 31f + lw t0, 0(a0) /* t0 = dst */ + + MIPS_UN8x4_MUL_UN8x4 a1, t1, t2, t9, t3, t4, t5, t6 + MIPS_UN8x4_MUL_UN8 t1, t8, t1, t9, t3, t4, t5 +31: + not t1, t1 + MIPS_UN8x4_MUL_UN8x4 t0, t1, t0, t9, t3, t4, t5, t6 + addu_s.qb t0, t2, t0 + sw t0, 0(a0) +4: + RESTORE_REGS_FROM_STACK 8, s0, s1, s2, s3, s4, s5 + j ra + nop + +END(pixman_composite_over_n_8888_8888_ca_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_over_n_8888_0565_ca_asm_mips) +/* + * a0 - dst (r5g6b5) + * a1 - src (32bit constant) + * a2 - mask (a8r8g8b8) + * a3 - w + */ + + SAVE_REGS_ON_STACK 20, s0, s1, s2, s3, s4, s5, s6, s7, s8 + beqz a3, 4f + nop + li t5, 0xf800f800 + li t6, 0x07e007e0 + li t7, 0x001F001F + li t9, 0x00ff00ff + + srl t8, a1, 24 /* t8 = srca */ + addiu t1, a3, -1 + beqz t1, 3f /* last pixel */ + nop + li s0, 0xff /* s0 = 0xff */ + addiu s1, zero, -1 /* s1 = 0xffffffff */ + + beq t8, s0, 2f /* if (srca == 0xff) */ + nop +1: + /* a1 = src */ + lw t0, 0(a2) /* t0 = mask */ + lw t1, 4(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 12f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 8 + and t3, t0, t1 + move s2, a1 /* s2 = src */ + move s3, a1 /* s3 = src */ + lhu t2, 0(a0) /* t2 = dst */ + beq t3, s1, 11f /* if (t0 == 0xffffffff) && (t1 == 0xffffffff) */ + lhu t3, 2(a0) /* t3 = dst */ + MIPS_2xUN8x4_MUL_2xUN8x4 a1, a1, t0, t1, s2, s3, t9, t4, s4, s5, s6, s7, s8 + MIPS_2xUN8x4_MUL_2xUN8 t0, t1, t8, t8, t0, t1, t9, t4, s4, s5, s6, s7, s8 +11: + not t0, t0 + not t1, t1 + CONVERT_2x0565_TO_2x8888 t2, t3, s4, s5, t6, t7, t4, s6, s7, s8 + MIPS_2xUN8x4_MUL_2xUN8x4 s4, s5, t0, t1, s4, s5, t9, t4, s6, s7, s8, t0, t1 + addu_s.qb s2, s2, s4 + addu_s.qb s3, s3, s5 + CONVERT_2x8888_TO_2x0565 s2, s3, t2, t3, t5, t6, t7, s4, s5 + sh t2, 0(a0) + sh t3, 2(a0) +12: + addiu a3, a3, -2 + addiu t1, a3, -1 + bgtz t1, 1b + addiu a0, a0, 4 + b 3f + nop +2: + /* a1 = src */ + lw t0, 0(a2) /* t0 = mask */ + lw t1, 4(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 22f /* if (t0 == 0) & (t1 == 0) */ + addiu a2, a2, 8 + and t3, t0, t1 + move t2, a1 + beq t3, s1, 21f /* if (t0 == 0xffffffff) && (t1 == 0xffffffff) */ + move t3, a1 + lhu t2, 0(a0) /* t2 = dst */ + lhu t3, 2(a0) /* t3 = dst */ + MIPS_2xUN8x4_MUL_2xUN8x4 a1, a1, t0, t1, s2, s3, t9, t4, s4, s5, s6, s7, s8 + not t0, t0 + not t1, t1 + CONVERT_2x0565_TO_2x8888 t2, t3, s4, s5, t6, t7, t4, s6, s7, s8 + MIPS_2xUN8x4_MUL_2xUN8x4 s4, s5, t0, t1, s4, s5, t9, t4, s6, s7, s8, t2, t3 + addu_s.qb t2, s2, s4 + addu_s.qb t3, s3, s5 +21: + CONVERT_2x8888_TO_2x0565 t2, t3, t0, t1, t5, t6, t7, s2, s3 + sh t0, 0(a0) + sh t1, 2(a0) +22: + addiu a3, a3, -2 + addiu t1, a3, -1 + bgtz t1, 2b + addiu a0, a0, 4 +3: + blez a3, 4f + nop + /* a1 = src */ + lw t1, 0(a2) /* t1 = mask */ + beqz t1, 4f + nop + move t2, a1 /* t2 = src */ + beq t1, t7, 31f + lhu t0, 0(a0) /* t0 = dst */ + + MIPS_UN8x4_MUL_UN8x4 a1, t1, t2, t9, t3, t4, t5, t6 + MIPS_UN8x4_MUL_UN8 t1, t8, t1, t9, t3, t4, t5 +31: + not t1, t1 + CONVERT_1x0565_TO_1x8888 t0, s1, s2, s3 + MIPS_UN8x4_MUL_UN8x4 s1, t1, t3, t9, t4, t5, t6, t7 + addu_s.qb t0, t2, t3 + CONVERT_1x8888_TO_1x0565 t0, s1, s2, s3 + sh s1, 0(a0) +4: + RESTORE_REGS_FROM_STACK 20, s0, s1, s2, s3, s4, s5, s6, s7, s8 + j ra + nop + +END(pixman_composite_over_n_8888_0565_ca_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_over_n_8_8888_asm_mips) +/* + * a0 - dst (a8r8g8b8) + * a1 - src (32bit constant) + * a2 - mask (a8) + * a3 - w + */ + + SAVE_REGS_ON_STACK 4, s0, s1, s2, s3, s4 + beqz a3, 4f + nop + li t4, 0x00ff00ff + li t5, 0xff + addiu t0, a3, -1 + beqz t0, 3f /* last pixel */ + srl t6, a1, 24 /* t6 = srca */ + not s4, a1 + beq t5, t6, 2f /* if (srca == 0xff) */ + srl s4, s4, 24 +1: + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + lbu t1, 1(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 111f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 2 + and t3, t0, t1 + + lw t2, 0(a0) /* t2 = dst */ + beq t3, t5, 11f /* if (t0 == 0xff) && (t1 == 0xff) */ + lw t3, 4(a0) /* t3 = dst */ + + MIPS_2xUN8x4_MUL_2xUN8 a1, a1, t0, t1, s0, s1, t4, t6, t7, t8, t9, s2, s3 + not s2, s0 + not s3, s1 + srl s2, s2, 24 + srl s3, s3, 24 + MIPS_2xUN8x4_MUL_2xUN8 t2, t3, s2, s3, t2, t3, t4, t0, t1, t6, t7, t8, t9 + addu_s.qb s2, t2, s0 + addu_s.qb s3, t3, s1 + sw s2, 0(a0) + b 111f + sw s3, 4(a0) +11: + MIPS_2xUN8x4_MUL_2xUN8 t2, t3, s4, s4, t2, t3, t4, t0, t1, t6, t7, t8, t9 + addu_s.qb s2, t2, a1 + addu_s.qb s3, t3, a1 + sw s2, 0(a0) + sw s3, 4(a0) + +111: + addiu a3, a3, -2 + addiu t0, a3, -1 + bgtz t0, 1b + addiu a0, a0, 8 + b 3f + nop +2: + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + lbu t1, 1(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 222f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 2 + and t3, t0, t1 + beq t3, t5, 22f /* if (t0 == 0xff) && (t1 == 0xff) */ + nop + lw t2, 0(a0) /* t2 = dst */ + lw t3, 4(a0) /* t3 = dst */ + + OVER_2x8888_2x8_2x8888 a1, a1, t0, t1, t2, t3, \ + t6, t7, t4, t8, t9, s0, s1, s2, s3 + sw t6, 0(a0) + b 222f + sw t7, 4(a0) +22: + sw a1, 0(a0) + sw a1, 4(a0) +222: + addiu a3, a3, -2 + addiu t0, a3, -1 + bgtz t0, 2b + addiu a0, a0, 8 +3: + blez a3, 4f + nop + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + beqz t0, 4f /* if (t0 == 0) */ + addiu a2, a2, 1 + move t3, a1 + beq t0, t5, 31f /* if (t0 == 0xff) */ + lw t1, 0(a0) /* t1 = dst */ + + MIPS_UN8x4_MUL_UN8 a1, t0, t3, t4, t6, t7, t8 +31: + not t2, t3 + srl t2, t2, 24 + MIPS_UN8x4_MUL_UN8 t1, t2, t1, t4, t6, t7, t8 + addu_s.qb t2, t1, t3 + sw t2, 0(a0) +4: + RESTORE_REGS_FROM_STACK 4, s0, s1, s2, s3, s4 + j ra + nop + +END(pixman_composite_over_n_8_8888_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_over_n_8_0565_asm_mips) +/* + * a0 - dst (r5g6b5) + * a1 - src (32bit constant) + * a2 - mask (a8) + * a3 - w + */ + SAVE_REGS_ON_STACK 24, v0, s0, s1, s2, s3, s4, s5, s6, s7, s8 + beqz a3, 4f + nop + li t4, 0x00ff00ff + li t5, 0xff + li t6, 0xf800f800 + li t7, 0x07e007e0 + li t8, 0x001F001F + addiu t1, a3, -1 + beqz t1, 3f /* last pixel */ + srl t0, a1, 24 /* t0 = srca */ + not v0, a1 + beq t0, t5, 2f /* if (srca == 0xff) */ + srl v0, v0, 24 +1: + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + lbu t1, 1(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 111f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 2 + lhu t2, 0(a0) /* t2 = dst */ + lhu t3, 2(a0) /* t3 = dst */ + CONVERT_2x0565_TO_2x8888 t2, t3, s0, s1, t7, t8, t9, s2, s3, s4 + and t9, t0, t1 + beq t9, t5, 11f /* if (t0 == 0xff) && (t1 == 0xff) */ + nop + + MIPS_2xUN8x4_MUL_2xUN8 a1, a1, t0, t1, s2, s3, t4, t9, s4, s5, s6, s7, s8 + not s4, s2 + not s5, s3 + srl s4, s4, 24 + srl s5, s5, 24 + MIPS_2xUN8x4_MUL_2xUN8 s0, s1, s4, s5, s0, s1, t4, t9, t0, t1, s6, s7, s8 + addu_s.qb s4, s2, s0 + addu_s.qb s5, s3, s1 + CONVERT_2x8888_TO_2x0565 s4, s5, t2, t3, t6, t7, t8, s0, s1 + sh t2, 0(a0) + b 111f + sh t3, 2(a0) +11: + MIPS_2xUN8x4_MUL_2xUN8 s0, s1, v0, v0, s0, s1, t4, t9, t0, t1, s6, s7, s8 + addu_s.qb s4, a1, s0 + addu_s.qb s5, a1, s1 + CONVERT_2x8888_TO_2x0565 s4, s5, t2, t3, t6, t7, t8, s0, s1 + sh t2, 0(a0) + sh t3, 2(a0) +111: + addiu a3, a3, -2 + addiu t0, a3, -1 + bgtz t0, 1b + addiu a0, a0, 4 + b 3f + nop +2: + CONVERT_1x8888_TO_1x0565 a1, s0, s1, s2 +21: + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + lbu t1, 1(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 222f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 2 + and t9, t0, t1 + move s2, s0 + beq t9, t5, 22f /* if (t0 == 0xff) && (t2 == 0xff) */ + move s3, s0 + lhu t2, 0(a0) /* t2 = dst */ + lhu t3, 2(a0) /* t3 = dst */ + + CONVERT_2x0565_TO_2x8888 t2, t3, s2, s3, t7, t8, s4, s5, s6, s7 + OVER_2x8888_2x8_2x8888 a1, a1, t0, t1, s2, s3, \ + t2, t3, t4, t9, s4, s5, s6, s7, s8 + CONVERT_2x8888_TO_2x0565 t2, t3, s2, s3, t6, t7, t8, s4, s5 +22: + sh s2, 0(a0) + sh s3, 2(a0) +222: + addiu a3, a3, -2 + addiu t0, a3, -1 + bgtz t0, 21b + addiu a0, a0, 4 +3: + blez a3, 4f + nop + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + beqz t0, 4f /* if (t0 == 0) */ + nop + lhu t1, 0(a0) /* t1 = dst */ + CONVERT_1x0565_TO_1x8888 t1, t2, t3, t7 + beq t0, t5, 31f /* if (t0 == 0xff) */ + move t3, a1 + + MIPS_UN8x4_MUL_UN8 a1, t0, t3, t4, t7, t8, t9 +31: + not t6, t3 + srl t6, t6, 24 + MIPS_UN8x4_MUL_UN8 t2, t6, t2, t4, t7, t8, t9 + addu_s.qb t1, t2, t3 + CONVERT_1x8888_TO_1x0565 t1, t2, t3, t7 + sh t2, 0(a0) +4: + RESTORE_REGS_FROM_STACK 24, v0, s0, s1, s2, s3, s4, s5, s6, s7, s8 + j ra + nop + +END(pixman_composite_over_n_8_0565_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 + + lw s0, 36(sp) /* s0 = wt */ + lw s1, 40(sp) /* s1 = wb */ + lw s2, 44(sp) /* s2 = vx */ + lw s3, 48(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a1) /* t0 = tl */ + lwx t1, t8(a1) /* t1 = tr */ + addiu a3, a3, -1 + lwx t2, t9(a2) /* t2 = bl */ + lwx t3, t8(a2) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez a3, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_0565_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 + + lw s0, 36(sp) /* s0 = wt */ + lw s1, 40(sp) /* s1 = wb */ + lw s2, 44(sp) /* s2 = vx */ + lw s3, 48(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a1) /* t0 = tl */ + lwx t1, t8(a1) /* t1 = tr */ + addiu a3, a3, -1 + lwx t2, t9(a2) /* t2 = bl */ + lwx t3, t8(a2) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + CONVERT_1x8888_TO_1x0565 t0, t1, t2, t3 + + addu s2, s2, s3 /* vx += unit_x; */ + sh t1, 0(a0) + bnez a3, 0b + addiu a0, a0, 2 + + RESTORE_REGS_FROM_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_0565_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_0565_8888_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li v1, 0x07e007e0 + li s8, 0x001f001f + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 1 + addiu t8, t9, 2 + lhx t0, t9(a1) /* t0 = tl */ + lhx t1, t8(a1) /* t1 = tr */ + andi t1, t1, 0xffff + addiu a3, a3, -1 + lhx t2, t9(a2) /* t2 = bl */ + lhx t3, t8(a2) /* t3 = br */ + andi t3, t3, 0xffff + + CONVERT_2x0565_TO_2x8888 t0, t1, t0, t1, v1, s8, t4, t5, t6, t7 + CONVERT_2x0565_TO_2x8888 t2, t3, t2, t3, v1, s8, t4, t5, t6, t7 + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez a3, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_0565_8888_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_0565_0565_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li v1, 0x07e007e0 + li s8, 0x001f001f + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 1 + addiu t8, t9, 2 + lhx t0, t9(a1) /* t0 = tl */ + lhx t1, t8(a1) /* t1 = tr */ + andi t1, t1, 0xffff + addiu a3, a3, -1 + lhx t2, t9(a2) /* t2 = bl */ + lhx t3, t8(a2) /* t3 = br */ + andi t3, t3, 0xffff + + CONVERT_2x0565_TO_2x8888 t0, t1, t0, t1, v1, s8, t4, t5, t6, t7 + CONVERT_2x0565_TO_2x8888 t2, t3, t2, t3, v1, s8, t4, t5, t6, t7 + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + CONVERT_1x8888_TO_1x0565 t0, t1, t2, t3 + + addu s2, s2, s3 /* vx += unit_x; */ + sh t1, 0(a0) + bnez a3, 0b + addiu a0, a0, 2 + + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_0565_0565_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8888_OVER_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 24, v0, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 40(sp) /* s0 = wt */ + lw s1, 44(sp) /* s1 = wb */ + lw s2, 48(sp) /* s2 = vx */ + lw s3, 52(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li s8, 0x00ff00ff + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a1) /* t0 = tl */ + lwx t1, t8(a1) /* t1 = tr */ + addiu a3, a3, -1 + lwx t2, t9(a2) /* t2 = bl */ + lwx t3, t8(a2) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lw t1, 0(a0) /* t1 = dest */ + OVER_8888_8888 t0, t1, t2, s8, t3, t4, t5, t6 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t2, 0(a0) + bnez a3, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 24, v0, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8888_OVER_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8888_ADD_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 + + lw s0, 36(sp) /* s0 = wt */ + lw s1, 40(sp) /* s1 = wb */ + lw s2, 44(sp) /* s2 = vx */ + lw s3, 48(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a1) /* t0 = tl */ + lwx t1, t8(a1) /* t1 = tr */ + addiu a3, a3, -1 + lwx t2, t9(a2) /* t2 = bl */ + lwx t3, t8(a2) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lw t1, 0(a0) + addu_s.qb t2, t0, t1 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t2, 0(a0) + bnez a3, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8888_ADD_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8_8888_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *mask + * a2 - *src_top + * a3 - *src_bottom + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + lw v1, 32(sp) + beqz v1, 1f + nop + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li s8, 0x00ff00ff + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a2) /* t0 = tl */ + lwx t1, t8(a2) /* t1 = tr */ + addiu v1, v1, -1 + lwx t2, t9(a3) /* t2 = bl */ + lwx t3, t8(a3) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + addiu a1, a1, 1 + MIPS_UN8x4_MUL_UN8 t0, t1, t0, s8, t2, t3, t4 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez v1, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8_8888_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8_0565_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *mask + * a2 - *src_top + * a3 - *src_bottom + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + lw v1, 32(sp) + beqz v1, 1f + nop + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li s8, 0x00ff00ff + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a2) /* t0 = tl */ + lwx t1, t8(a2) /* t1 = tr */ + addiu v1, v1, -1 + lwx t2, t9(a3) /* t2 = bl */ + lwx t3, t8(a3) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + addiu a1, a1, 1 + MIPS_UN8x4_MUL_UN8 t0, t1, t0, s8, t2, t3, t4 + CONVERT_1x8888_TO_1x0565 t0, t1, t2, t3 + + addu s2, s2, s3 /* vx += unit_x; */ + sh t1, 0(a0) + bnez v1, 0b + addiu a0, a0, 2 + + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8_0565_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_0565_8_x888_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *mask + * a2 - *src_top + * a3 - *src_bottom + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + lw t0, 32(sp) + beqz t0, 1f + nop + + SAVE_REGS_ON_STACK 32, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8, ra + + lw s0, 48(sp) /* s0 = wt */ + lw s1, 52(sp) /* s1 = wb */ + lw s2, 56(sp) /* s2 = vx */ + lw s3, 60(sp) /* s3 = unit_x */ + lw ra, 64(sp) /* ra = w */ + li v0, 0x00ff00ff + li v1, 0x07e007e0 + li s8, 0x001f001f + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + li t5, BILINEAR_INTERPOLATION_RANGE + subu t5, t5, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 1 + addiu t8, t9, 2 + lhx t0, t9(a2) /* t0 = tl */ + lhx t1, t8(a2) /* t1 = tr */ + andi t1, t1, 0xffff + addiu ra, ra, -1 + lhx t2, t9(a3) /* t2 = bl */ + lhx t3, t8(a3) /* t3 = br */ + andi t3, t3, 0xffff + + CONVERT_2x0565_TO_2x8888 t0, t1, t0, t1, v1, s8, t4, t5, t6, t7 + CONVERT_2x0565_TO_2x8888 t2, t3, t2, t3, v1, s8, t4, t5, t6, t7 + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + addiu a1, a1, 1 + MIPS_UN8x4_MUL_UN8 t0, t1, t0, v0, t2, t3, t4 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez ra, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 32, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8, ra +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_0565_8_x888_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_0565_8_0565_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *mask + * a2 - *src_top + * a3 - *src_bottom + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + lw t0, 32(sp) + beqz t0, 1f + nop + + SAVE_REGS_ON_STACK 32, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8, ra + + lw s0, 48(sp) /* s0 = wt */ + lw s1, 52(sp) /* s1 = wb */ + lw s2, 56(sp) /* s2 = vx */ + lw s3, 60(sp) /* s3 = unit_x */ + lw ra, 64(sp) /* ra = w */ + li v0, 0x00ff00ff + li v1, 0x07e007e0 + li s8, 0x001f001f + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + li t5, BILINEAR_INTERPOLATION_RANGE + subu t5, t5, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 1 + addiu t8, t9, 2 + lhx t0, t9(a2) /* t0 = tl */ + lhx t1, t8(a2) /* t1 = tr */ + andi t1, t1, 0xffff + addiu ra, ra, -1 + lhx t2, t9(a3) /* t2 = bl */ + lhx t3, t8(a3) /* t3 = br */ + andi t3, t3, 0xffff + + CONVERT_2x0565_TO_2x8888 t0, t1, t0, t1, v1, s8, t4, t5, t6, t7 + CONVERT_2x0565_TO_2x8888 t2, t3, t2, t3, v1, s8, t4, t5, t6, t7 + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + addiu a1, a1, 1 + MIPS_UN8x4_MUL_UN8 t0, t1, t0, v0, t2, t3, t4 + CONVERT_1x8888_TO_1x0565 t0, t1, t2, t3 + + addu s2, s2, s3 /* vx += unit_x; */ + sh t1, 0(a0) + bnez ra, 0b + addiu a0, a0, 2 + + RESTORE_REGS_FROM_STACK 32, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8, ra +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_0565_8_0565_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8_8888_OVER_asm_mips) +/* + * a0 - dst (a8r8g8b8) + * a1 - mask (a8) + * a2 - src_top (a8r8g8b8) + * a3 - src_bottom (a8r8g8b8) + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw v1, 60(sp) /* v1 = w(sp + 32 + 28 save regs stack offset)*/ + beqz v1, 1f + nop + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li s8, 0x00ff00ff + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a2) /* t0 = tl */ + lwx t1, t8(a2) /* t1 = tr */ + addiu v1, v1, -1 + lwx t2, t9(a3) /* t2 = bl */ + lwx t3, t8(a3) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, \ + t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + lw t2, 0(a0) /* t2 = dst */ + addiu a1, a1, 1 + OVER_8888_8_8888 t0, t1, t2, t0, s8, t3, t4, t5, t6 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez v1, 0b + addiu a0, a0, 4 + +1: + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8_8888_OVER_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8_8888_ADD_asm_mips) +/* + * a0 - *dst + * a1 - *mask + * a2 - *src_top + * a3 - *src_bottom + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + lw v1, 32(sp) + beqz v1, 1f + nop + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li s8, 0x00ff00ff + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a2) /* t0 = tl */ + lwx t1, t8(a2) /* t1 = tr */ + addiu v1, v1, -1 + lwx t2, t9(a3) /* t2 = bl */ + lwx t3, t8(a3) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + lw t2, 0(a0) /* t2 = dst */ + addiu a1, a1, 1 + MIPS_UN8x4_MUL_UN8_ADD_UN8x4 t0, t1, t2, t0, s8, t3, t4, t5 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez v1, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8_8888_ADD_asm_mips) diff --git a/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h b/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h new file mode 100644 index 00000000000..7327dc6dc01 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h @@ -0,0 +1,659 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nemanja Lukic (nlukic@mips.com) + */ + +#ifndef PIXMAN_MIPS_DSPR2_ASM_H +#define PIXMAN_MIPS_DSPR2_ASM_H + +#define zero $0 +#define AT $1 +#define v0 $2 +#define v1 $3 +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 +#define t9 $25 +#define k0 $26 +#define k1 $27 +#define gp $28 +#define sp $29 +#define fp $30 +#define s8 $30 +#define ra $31 + +/* + * LEAF_MIPS32R2 - declare leaf routine for MIPS32r2 + */ +#define LEAF_MIPS32R2(symbol) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ + .ent symbol, 0; \ +symbol: .frame sp, 0, ra; \ + .set push; \ + .set arch=mips32r2; \ + .set noreorder; \ + .set noat; + +/* + * LEAF_MIPS32R2 - declare leaf routine for MIPS DSPr2 + */ +#define LEAF_MIPS_DSPR2(symbol) \ +LEAF_MIPS32R2(symbol) \ + .set dspr2; + +/* + * END - mark end of function + */ +#define END(function) \ + .set pop; \ + .end function; \ + .size function,.-function + +/* + * Checks if stack offset is big enough for storing/restoring regs_num + * number of register to/from stack. Stack offset must be greater than + * or equal to the number of bytes needed for storing registers (regs_num*4). + * Since MIPS ABI allows usage of first 16 bytes of stack frame (this is + * preserved for input arguments of the functions, already stored in a0-a3), + * stack size can be further optimized by utilizing this space. + */ +.macro CHECK_STACK_OFFSET regs_num, stack_offset +.if \stack_offset < \regs_num * 4 - 16 +.error "Stack offset too small." +.endif +.endm + +/* + * Saves set of registers on stack. Maximum number of registers that + * can be saved on stack is limitted to 14 (a0-a3, v0-v1 and s0-s7). + * Stack offset is number of bytes that are added to stack pointer (sp) + * before registers are pushed in order to provide enough space on stack + * (offset must be multiple of 4, and must be big enough, as described by + * CHECK_STACK_OFFSET macro). This macro is intended to be used in + * combination with RESTORE_REGS_FROM_STACK macro. Example: + * SAVE_REGS_ON_STACK 4, v0, v1, s0, s1 + * RESTORE_REGS_FROM_STACK 4, v0, v1, s0, s1 + */ +.macro SAVE_REGS_ON_STACK stack_offset = 0, r1, \ + r2 = 0, r3 = 0, r4 = 0, \ + r5 = 0, r6 = 0, r7 = 0, \ + r8 = 0, r9 = 0, r10 = 0, \ + r11 = 0, r12 = 0, r13 = 0, \ + r14 = 0 + .if (\stack_offset < 0) || (\stack_offset - (\stack_offset / 4) * 4) + .error "Stack offset must be pozitive and multiple of 4." + .endif + .if \stack_offset != 0 + addiu sp, sp, -\stack_offset + .endif + sw \r1, 0(sp) + .if \r2 != 0 + sw \r2, 4(sp) + .endif + .if \r3 != 0 + sw \r3, 8(sp) + .endif + .if \r4 != 0 + sw \r4, 12(sp) + .endif + .if \r5 != 0 + CHECK_STACK_OFFSET 5, \stack_offset + sw \r5, 16(sp) + .endif + .if \r6 != 0 + CHECK_STACK_OFFSET 6, \stack_offset + sw \r6, 20(sp) + .endif + .if \r7 != 0 + CHECK_STACK_OFFSET 7, \stack_offset + sw \r7, 24(sp) + .endif + .if \r8 != 0 + CHECK_STACK_OFFSET 8, \stack_offset + sw \r8, 28(sp) + .endif + .if \r9 != 0 + CHECK_STACK_OFFSET 9, \stack_offset + sw \r9, 32(sp) + .endif + .if \r10 != 0 + CHECK_STACK_OFFSET 10, \stack_offset + sw \r10, 36(sp) + .endif + .if \r11 != 0 + CHECK_STACK_OFFSET 11, \stack_offset + sw \r11, 40(sp) + .endif + .if \r12 != 0 + CHECK_STACK_OFFSET 12, \stack_offset + sw \r12, 44(sp) + .endif + .if \r13 != 0 + CHECK_STACK_OFFSET 13, \stack_offset + sw \r13, 48(sp) + .endif + .if \r14 != 0 + CHECK_STACK_OFFSET 14, \stack_offset + sw \r14, 52(sp) + .endif +.endm + +/* + * Restores set of registers from stack. Maximum number of registers that + * can be restored from stack is limitted to 14 (a0-a3, v0-v1 and s0-s7). + * Stack offset is number of bytes that are added to stack pointer (sp) + * after registers are restored (offset must be multiple of 4, and must + * be big enough, as described by CHECK_STACK_OFFSET macro). This macro is + * intended to be used in combination with RESTORE_REGS_FROM_STACK macro. + * Example: + * SAVE_REGS_ON_STACK 4, v0, v1, s0, s1 + * RESTORE_REGS_FROM_STACK 4, v0, v1, s0, s1 + */ +.macro RESTORE_REGS_FROM_STACK stack_offset = 0, r1, \ + r2 = 0, r3 = 0, r4 = 0, \ + r5 = 0, r6 = 0, r7 = 0, \ + r8 = 0, r9 = 0, r10 = 0, \ + r11 = 0, r12 = 0, r13 = 0, \ + r14 = 0 + .if (\stack_offset < 0) || (\stack_offset - (\stack_offset/4)*4) + .error "Stack offset must be pozitive and multiple of 4." + .endif + lw \r1, 0(sp) + .if \r2 != 0 + lw \r2, 4(sp) + .endif + .if \r3 != 0 + lw \r3, 8(sp) + .endif + .if \r4 != 0 + lw \r4, 12(sp) + .endif + .if \r5 != 0 + CHECK_STACK_OFFSET 5, \stack_offset + lw \r5, 16(sp) + .endif + .if \r6 != 0 + CHECK_STACK_OFFSET 6, \stack_offset + lw \r6, 20(sp) + .endif + .if \r7 != 0 + CHECK_STACK_OFFSET 7, \stack_offset + lw \r7, 24(sp) + .endif + .if \r8 != 0 + CHECK_STACK_OFFSET 8, \stack_offset + lw \r8, 28(sp) + .endif + .if \r9 != 0 + CHECK_STACK_OFFSET 9, \stack_offset + lw \r9, 32(sp) + .endif + .if \r10 != 0 + CHECK_STACK_OFFSET 10, \stack_offset + lw \r10, 36(sp) + .endif + .if \r11 != 0 + CHECK_STACK_OFFSET 11, \stack_offset + lw \r11, 40(sp) + .endif + .if \r12 != 0 + CHECK_STACK_OFFSET 12, \stack_offset + lw \r12, 44(sp) + .endif + .if \r13 != 0 + CHECK_STACK_OFFSET 13, \stack_offset + lw \r13, 48(sp) + .endif + .if \r14 != 0 + CHECK_STACK_OFFSET 14, \stack_offset + lw \r14, 52(sp) + .endif + .if \stack_offset != 0 + addiu sp, sp, \stack_offset + .endif +.endm + +/* + * Conversion of single r5g6b5 pixel (in_565) to single a8r8g8b8 pixel + * returned in (out_8888) register. Requires two temporary registers + * (scratch1 and scratch2). + */ +.macro CONVERT_1x0565_TO_1x8888 in_565, \ + out_8888, \ + scratch1, scratch2 + lui \out_8888, 0xff00 + sll \scratch1, \in_565, 0x3 + andi \scratch2, \scratch1, 0xff + ext \scratch1, \in_565, 0x2, 0x3 + or \scratch1, \scratch2, \scratch1 + or \out_8888, \out_8888, \scratch1 + + sll \scratch1, \in_565, 0x5 + andi \scratch1, \scratch1, 0xfc00 + srl \scratch2, \in_565, 0x1 + andi \scratch2, \scratch2, 0x300 + or \scratch2, \scratch1, \scratch2 + or \out_8888, \out_8888, \scratch2 + + andi \scratch1, \in_565, 0xf800 + srl \scratch2, \scratch1, 0x5 + andi \scratch2, \scratch2, 0xff00 + or \scratch1, \scratch1, \scratch2 + sll \scratch1, \scratch1, 0x8 + or \out_8888, \out_8888, \scratch1 +.endm + +/* + * Conversion of two r5g6b5 pixels (in1_565 and in2_565) to two a8r8g8b8 pixels + * returned in (out1_8888 and out2_8888) registers. Requires four scratch + * registers (scratch1 ... scratch4). It also requires maskG and maskB for + * color component extractions. These masks must have following values: + * li maskG, 0x07e007e0 + * li maskB, 0x001F001F + */ +.macro CONVERT_2x0565_TO_2x8888 in1_565, in2_565, \ + out1_8888, out2_8888, \ + maskG, maskB, \ + scratch1, scratch2, scratch3, scratch4 + sll \scratch1, \in1_565, 16 + or \scratch1, \scratch1, \in2_565 + lui \out2_8888, 0xff00 + ori \out2_8888, \out2_8888, 0xff00 + shrl.ph \scratch2, \scratch1, 11 + and \scratch3, \scratch1, \maskG + shra.ph \scratch4, \scratch2, 2 + shll.ph \scratch2, \scratch2, 3 + shll.ph \scratch3, \scratch3, 5 + or \scratch2, \scratch2, \scratch4 + shrl.qb \scratch4, \scratch3, 6 + or \out2_8888, \out2_8888, \scratch2 + or \scratch3, \scratch3, \scratch4 + and \scratch1, \scratch1, \maskB + shll.ph \scratch2, \scratch1, 3 + shra.ph \scratch4, \scratch1, 2 + or \scratch2, \scratch2, \scratch4 + or \scratch3, \scratch2, \scratch3 + precrq.ph.w \out1_8888, \out2_8888, \scratch3 + precr_sra.ph.w \out2_8888, \scratch3, 0 +.endm + +/* + * Conversion of single a8r8g8b8 pixel (in_8888) to single r5g6b5 pixel + * returned in (out_565) register. Requires two temporary registers + * (scratch1 and scratch2). + */ +.macro CONVERT_1x8888_TO_1x0565 in_8888, \ + out_565, \ + scratch1, scratch2 + ext \out_565, \in_8888, 0x3, 0x5 + srl \scratch1, \in_8888, 0x5 + andi \scratch1, \scratch1, 0x07e0 + srl \scratch2, \in_8888, 0x8 + andi \scratch2, \scratch2, 0xf800 + or \out_565, \out_565, \scratch1 + or \out_565, \out_565, \scratch2 +.endm + +/* + * Conversion of two a8r8g8b8 pixels (in1_8888 and in2_8888) to two r5g6b5 + * pixels returned in (out1_565 and out2_565) registers. Requires two temporary + * registers (scratch1 and scratch2). It also requires maskR, maskG and maskB + * for color component extractions. These masks must have following values: + * li maskR, 0xf800f800 + * li maskG, 0x07e007e0 + * li maskB, 0x001F001F + * Value of input register in2_8888 is lost. + */ +.macro CONVERT_2x8888_TO_2x0565 in1_8888, in2_8888, \ + out1_565, out2_565, \ + maskR, maskG, maskB, \ + scratch1, scratch2 + precrq.ph.w \scratch1, \in2_8888, \in1_8888 + precr_sra.ph.w \in2_8888, \in1_8888, 0 + shll.ph \scratch1, \scratch1, 8 + srl \in2_8888, \in2_8888, 3 + and \scratch2, \in2_8888, \maskB + and \scratch1, \scratch1, \maskR + srl \in2_8888, \in2_8888, 2 + and \out2_565, \in2_8888, \maskG + or \out2_565, \out2_565, \scratch2 + or \out1_565, \out2_565, \scratch1 + srl \out2_565, \out1_565, 16 +.endm + +/* + * Multiply pixel (a8) with single pixel (a8r8g8b8). It requires maskLSR needed + * for rounding process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ +.macro MIPS_UN8x4_MUL_UN8 s_8888, \ + m_8, \ + d_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3 + replv.ph \m_8, \m_8 /* 0 | M | 0 | M */ + muleu_s.ph.qbl \scratch1, \s_8888, \m_8 /* A*M | R*M */ + muleu_s.ph.qbr \scratch2, \s_8888, \m_8 /* G*M | B*M */ + shra_r.ph \scratch3, \scratch1, 8 + shra_r.ph \d_8888, \scratch2, 8 + and \scratch3, \scratch3, \maskLSR /* 0 |A*M| 0 |R*M */ + and \d_8888, \d_8888, \maskLSR /* 0 |G*M| 0 |B*M */ + addq.ph \scratch1, \scratch1, \scratch3 /* A*M+A*M | R*M+R*M */ + addq.ph \scratch2, \scratch2, \d_8888 /* G*M+G*M | B*M+B*M */ + shra_r.ph \scratch1, \scratch1, 8 + shra_r.ph \scratch2, \scratch2, 8 + precr.qb.ph \d_8888, \scratch1, \scratch2 +.endm + +/* + * Multiply two pixels (a8) with two pixels (a8r8g8b8). It requires maskLSR + * needed for rounding process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ +.macro MIPS_2xUN8x4_MUL_2xUN8 s1_8888, \ + s2_8888, \ + m1_8, \ + m2_8, \ + d1_8888, \ + d2_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, \ + scratch4, scratch5, scratch6 + replv.ph \m1_8, \m1_8 /* 0 | M1 | 0 | M1 */ + replv.ph \m2_8, \m2_8 /* 0 | M2 | 0 | M2 */ + muleu_s.ph.qbl \scratch1, \s1_8888, \m1_8 /* A1*M1 | R1*M1 */ + muleu_s.ph.qbr \scratch2, \s1_8888, \m1_8 /* G1*M1 | B1*M1 */ + muleu_s.ph.qbl \scratch3, \s2_8888, \m2_8 /* A2*M2 | R2*M2 */ + muleu_s.ph.qbr \scratch4, \s2_8888, \m2_8 /* G2*M2 | B2*M2 */ + shra_r.ph \scratch5, \scratch1, 8 + shra_r.ph \d1_8888, \scratch2, 8 + shra_r.ph \scratch6, \scratch3, 8 + shra_r.ph \d2_8888, \scratch4, 8 + and \scratch5, \scratch5, \maskLSR /* 0 |A1*M1| 0 |R1*M1 */ + and \d1_8888, \d1_8888, \maskLSR /* 0 |G1*M1| 0 |B1*M1 */ + and \scratch6, \scratch6, \maskLSR /* 0 |A2*M2| 0 |R2*M2 */ + and \d2_8888, \d2_8888, \maskLSR /* 0 |G2*M2| 0 |B2*M2 */ + addq.ph \scratch1, \scratch1, \scratch5 + addq.ph \scratch2, \scratch2, \d1_8888 + addq.ph \scratch3, \scratch3, \scratch6 + addq.ph \scratch4, \scratch4, \d2_8888 + shra_r.ph \scratch1, \scratch1, 8 + shra_r.ph \scratch2, \scratch2, 8 + shra_r.ph \scratch3, \scratch3, 8 + shra_r.ph \scratch4, \scratch4, 8 + precr.qb.ph \d1_8888, \scratch1, \scratch2 + precr.qb.ph \d2_8888, \scratch3, \scratch4 +.endm + +/* + * Multiply pixel (a8r8g8b8) with single pixel (a8r8g8b8). It requires maskLSR + * needed for rounding process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ +.macro MIPS_UN8x4_MUL_UN8x4 s_8888, \ + m_8888, \ + d_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, scratch4 + preceu.ph.qbl \scratch1, \m_8888 /* 0 | A | 0 | R */ + preceu.ph.qbr \scratch2, \m_8888 /* 0 | G | 0 | B */ + muleu_s.ph.qbl \scratch3, \s_8888, \scratch1 /* A*A | R*R */ + muleu_s.ph.qbr \scratch4, \s_8888, \scratch2 /* G*G | B*B */ + shra_r.ph \scratch1, \scratch3, 8 + shra_r.ph \scratch2, \scratch4, 8 + and \scratch1, \scratch1, \maskLSR /* 0 |A*A| 0 |R*R */ + and \scratch2, \scratch2, \maskLSR /* 0 |G*G| 0 |B*B */ + addq.ph \scratch1, \scratch1, \scratch3 + addq.ph \scratch2, \scratch2, \scratch4 + shra_r.ph \scratch1, \scratch1, 8 + shra_r.ph \scratch2, \scratch2, 8 + precr.qb.ph \d_8888, \scratch1, \scratch2 +.endm + +/* + * Multiply two pixels (a8r8g8b8) with two pixels (a8r8g8b8). It requires + * maskLSR needed for rounding process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ + +.macro MIPS_2xUN8x4_MUL_2xUN8x4 s1_8888, \ + s2_8888, \ + m1_8888, \ + m2_8888, \ + d1_8888, \ + d2_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, \ + scratch4, scratch5, scratch6 + preceu.ph.qbl \scratch1, \m1_8888 /* 0 | A | 0 | R */ + preceu.ph.qbr \scratch2, \m1_8888 /* 0 | G | 0 | B */ + preceu.ph.qbl \scratch3, \m2_8888 /* 0 | A | 0 | R */ + preceu.ph.qbr \scratch4, \m2_8888 /* 0 | G | 0 | B */ + muleu_s.ph.qbl \scratch5, \s1_8888, \scratch1 /* A*A | R*R */ + muleu_s.ph.qbr \scratch6, \s1_8888, \scratch2 /* G*G | B*B */ + muleu_s.ph.qbl \scratch1, \s2_8888, \scratch3 /* A*A | R*R */ + muleu_s.ph.qbr \scratch2, \s2_8888, \scratch4 /* G*G | B*B */ + shra_r.ph \scratch3, \scratch5, 8 + shra_r.ph \scratch4, \scratch6, 8 + shra_r.ph \d1_8888, \scratch1, 8 + shra_r.ph \d2_8888, \scratch2, 8 + and \scratch3, \scratch3, \maskLSR /* 0 |A*A| 0 |R*R */ + and \scratch4, \scratch4, \maskLSR /* 0 |G*G| 0 |B*B */ + and \d1_8888, \d1_8888, \maskLSR /* 0 |A*A| 0 |R*R */ + and \d2_8888, \d2_8888, \maskLSR /* 0 |G*G| 0 |B*B */ + addq.ph \scratch3, \scratch3, \scratch5 + addq.ph \scratch4, \scratch4, \scratch6 + addq.ph \d1_8888, \d1_8888, \scratch1 + addq.ph \d2_8888, \d2_8888, \scratch2 + shra_r.ph \scratch3, \scratch3, 8 + shra_r.ph \scratch4, \scratch4, 8 + shra_r.ph \scratch5, \d1_8888, 8 + shra_r.ph \scratch6, \d2_8888, 8 + precr.qb.ph \d1_8888, \scratch3, \scratch4 + precr.qb.ph \d2_8888, \scratch5, \scratch6 +.endm + +/* + * OVER operation on single a8r8g8b8 source pixel (s_8888) and single a8r8g8b8 + * destination pixel (d_8888) using a8 mask (m_8). It also requires maskLSR + * needed for rounding process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ +.macro OVER_8888_8_8888 s_8888, \ + m_8, \ + d_8888, \ + out_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, scratch4 + MIPS_UN8x4_MUL_UN8 \s_8888, \m_8, \ + \scratch1, \maskLSR, \ + \scratch2, \scratch3, \scratch4 + + not \scratch2, \scratch1 + srl \scratch2, \scratch2, 24 + + MIPS_UN8x4_MUL_UN8 \d_8888, \scratch2, \ + \d_8888, \maskLSR, \ + \scratch3, \scratch4, \out_8888 + + addu_s.qb \out_8888, \d_8888, \scratch1 +.endm + +/* + * OVER operation on two a8r8g8b8 source pixels (s1_8888 and s2_8888) and two + * a8r8g8b8 destination pixels (d1_8888 and d2_8888) using a8 masks (m1_8 and + * m2_8). It also requires maskLSR needed for rounding process. maskLSR must + * have following value: + * li maskLSR, 0x00ff00ff + */ +.macro OVER_2x8888_2x8_2x8888 s1_8888, \ + s2_8888, \ + m1_8, \ + m2_8, \ + d1_8888, \ + d2_8888, \ + out1_8888, \ + out2_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, \ + scratch4, scratch5, scratch6 + MIPS_2xUN8x4_MUL_2xUN8 \s1_8888, \s2_8888, \ + \m1_8, \m2_8, \ + \scratch1, \scratch2, \ + \maskLSR, \ + \scratch3, \scratch4, \out1_8888, \ + \out2_8888, \scratch5, \scratch6 + + not \scratch3, \scratch1 + srl \scratch3, \scratch3, 24 + not \scratch4, \scratch2 + srl \scratch4, \scratch4, 24 + + MIPS_2xUN8x4_MUL_2xUN8 \d1_8888, \d2_8888, \ + \scratch3, \scratch4, \ + \d1_8888, \d2_8888, \ + \maskLSR, \ + \scratch5, \scratch6, \out1_8888, \ + \out2_8888, \scratch3, \scratch4 + + addu_s.qb \out1_8888, \d1_8888, \scratch1 + addu_s.qb \out2_8888, \d2_8888, \scratch2 +.endm + +/* + * OVER operation on single a8r8g8b8 source pixel (s_8888) and single a8r8g8b8 + * destination pixel (d_8888). It also requires maskLSR needed for rounding + * process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ +.macro OVER_8888_8888 s_8888, \ + d_8888, \ + out_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, scratch4 + not \scratch1, \s_8888 + srl \scratch1, \scratch1, 24 + + MIPS_UN8x4_MUL_UN8 \d_8888, \scratch1, \ + \out_8888, \maskLSR, \ + \scratch2, \scratch3, \scratch4 + + addu_s.qb \out_8888, \out_8888, \s_8888 +.endm + +.macro MIPS_UN8x4_MUL_UN8_ADD_UN8x4 s_8888, \ + m_8, \ + d_8888, \ + out_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3 + MIPS_UN8x4_MUL_UN8 \s_8888, \m_8, \ + \out_8888, \maskLSR, \ + \scratch1, \scratch2, \scratch3 + + addu_s.qb \out_8888, \out_8888, \d_8888 +.endm + +.macro BILINEAR_INTERPOLATE_SINGLE_PIXEL tl, tr, bl, br, \ + scratch1, scratch2, \ + alpha, red, green, blue \ + wt1, wt2, wb1, wb2 + andi \scratch1, \tl, 0xff + andi \scratch2, \tr, 0xff + andi \alpha, \bl, 0xff + andi \red, \br, 0xff + + multu $ac0, \wt1, \scratch1 + maddu $ac0, \wt2, \scratch2 + maddu $ac0, \wb1, \alpha + maddu $ac0, \wb2, \red + + ext \scratch1, \tl, 8, 8 + ext \scratch2, \tr, 8, 8 + ext \alpha, \bl, 8, 8 + ext \red, \br, 8, 8 + + multu $ac1, \wt1, \scratch1 + maddu $ac1, \wt2, \scratch2 + maddu $ac1, \wb1, \alpha + maddu $ac1, \wb2, \red + + ext \scratch1, \tl, 16, 8 + ext \scratch2, \tr, 16, 8 + ext \alpha, \bl, 16, 8 + ext \red, \br, 16, 8 + + mflo \blue, $ac0 + + multu $ac2, \wt1, \scratch1 + maddu $ac2, \wt2, \scratch2 + maddu $ac2, \wb1, \alpha + maddu $ac2, \wb2, \red + + ext \scratch1, \tl, 24, 8 + ext \scratch2, \tr, 24, 8 + ext \alpha, \bl, 24, 8 + ext \red, \br, 24, 8 + + mflo \green, $ac1 + + multu $ac3, \wt1, \scratch1 + maddu $ac3, \wt2, \scratch2 + maddu $ac3, \wb1, \alpha + maddu $ac3, \wb2, \red + + mflo \red, $ac2 + mflo \alpha, $ac3 + + precr.qb.ph \alpha, \alpha, \red + precr.qb.ph \scratch1, \green, \blue + precrq.qb.ph \tl, \alpha, \scratch1 +.endm + +#endif //PIXMAN_MIPS_DSPR2_ASM_H diff --git a/gfx/cairo/libpixman/src/pixman-mips-dspr2.c b/gfx/cairo/libpixman/src/pixman-mips-dspr2.c new file mode 100644 index 00000000000..63a0225a2e7 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nemanja Lukic (nlukic@mips.com) + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" +#include "pixman-mips-dspr2.h" + +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_x888_8888, + uint32_t, 1, uint32_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_8888_0565, + uint32_t, 1, uint16_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_0565_8888, + uint16_t, 1, uint32_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0565_0565, + uint16_t, 1, uint16_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_8888_8888, + uint32_t, 1, uint32_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0888_0888, + uint8_t, 3, uint8_t, 3) + +PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_8888_ca, + uint32_t, 1, uint32_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_0565_ca, + uint32_t, 1, uint16_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_8888, + uint8_t, 1, uint32_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_0565, + uint8_t, 1, uint16_t, 1) + +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_8888, SRC, + uint32_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_0565, SRC, + uint32_t, uint16_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 0565_8888, SRC, + uint16_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 0565_0565, SRC, + uint16_t, uint16_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, 8888_8888, OVER, + uint32_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, 8888_8888, ADD, + uint32_t, uint32_t) + +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 8888_8_8888, SRC, + uint32_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 8888_8_0565, SRC, + uint32_t, uint16_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 0565_8_x888, SRC, + uint16_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 0565_8_0565, SRC, + uint16_t, uint16_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_8888, OVER, + uint32_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_8888, ADD, + uint32_t, uint32_t) + +static pixman_bool_t +pixman_fill_mips (uint32_t *bits, + int stride, + int bpp, + int x, + int y, + int width, + int height, + uint32_t _xor) +{ + uint8_t *byte_line; + uint32_t byte_width; + switch (bpp) + { + case 16: + stride = stride * (int) sizeof (uint32_t) / 2; + byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x); + byte_width = width * 2; + stride *= 2; + + while (height--) + { + uint8_t *dst = byte_line; + byte_line += stride; + pixman_fill_buff16_mips (dst, byte_width, _xor & 0xffff); + } + return TRUE; + case 32: + stride = stride * (int) sizeof (uint32_t) / 4; + byte_line = (uint8_t *)(((uint32_t *)bits) + stride * y + x); + byte_width = width * 4; + stride *= 4; + + while (height--) + { + uint8_t *dst = byte_line; + byte_line += stride; + pixman_fill_buff32_mips (dst, byte_width, _xor); + } + return TRUE; + default: + return FALSE; + } +} + +static pixman_bool_t +pixman_blt_mips (uint32_t *src_bits, + uint32_t *dst_bits, + int src_stride, + int dst_stride, + int src_bpp, + int dst_bpp, + int src_x, + int src_y, + int dest_x, + int dest_y, + int width, + int height) +{ + if (src_bpp != dst_bpp) + return FALSE; + + uint8_t *src_bytes; + uint8_t *dst_bytes; + uint32_t byte_width; + + switch (src_bpp) + { + case 16: + src_stride = src_stride * (int) sizeof (uint32_t) / 2; + dst_stride = dst_stride * (int) sizeof (uint32_t) / 2; + src_bytes =(uint8_t *)(((uint16_t *)src_bits) + + src_stride * (src_y) + (src_x)); + dst_bytes = (uint8_t *)(((uint16_t *)dst_bits) + + dst_stride * (dest_y) + (dest_x)); + byte_width = width * 2; + src_stride *= 2; + dst_stride *= 2; + + while (height--) + { + uint8_t *src = src_bytes; + uint8_t *dst = dst_bytes; + src_bytes += src_stride; + dst_bytes += dst_stride; + pixman_mips_fast_memcpy (dst, src, byte_width); + } + return TRUE; + case 32: + src_stride = src_stride * (int) sizeof (uint32_t) / 4; + dst_stride = dst_stride * (int) sizeof (uint32_t) / 4; + src_bytes = (uint8_t *)(((uint32_t *)src_bits) + + src_stride * (src_y) + (src_x)); + dst_bytes = (uint8_t *)(((uint32_t *)dst_bits) + + dst_stride * (dest_y) + (dest_x)); + byte_width = width * 4; + src_stride *= 4; + dst_stride *= 4; + + while (height--) + { + uint8_t *src = src_bytes; + uint8_t *dst = dst_bytes; + src_bytes += src_stride; + dst_bytes += dst_stride; + pixman_mips_fast_memcpy (dst, src, byte_width); + } + return TRUE; + default: + return FALSE; + } +} + +static const pixman_fast_path_t mips_dspr2_fast_paths[] = +{ + PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, mips_composite_src_0565_0565), + PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, mips_composite_src_0565_0565), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, mips_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, mips_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, mips_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, mips_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, a8r8g8b8, mips_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, x8r8g8b8, mips_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, mips_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, mips_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, mips_composite_src_x888_8888), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, mips_composite_src_x888_8888), + PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, mips_composite_src_0888_0888), + + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, mips_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, mips_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, mips_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, mips_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, mips_composite_over_n_8888_0565_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, mips_composite_over_n_8888_0565_ca), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, mips_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, mips_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, mips_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, mips_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, mips_composite_over_n_8_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, mips_composite_over_n_8_0565), + + SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mips_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mips_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mips_8888_8888), + + SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, r5g6b5, mips_8888_0565), + SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, r5g6b5, mips_8888_0565), + + SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, x8r8g8b8, mips_0565_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, r5g6b5, mips_0565_0565), + + SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mips_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mips_8888_8888), + + SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, mips_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, mips_8888_8888), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mips_8888_8_8888), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mips_8888_8_8888), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mips_8888_8_8888), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, r5g6b5, mips_8888_8_0565), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, r5g6b5, mips_8888_8_0565), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, x8r8g8b8, mips_0565_8_x888), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, r5g6b5, mips_0565_8_0565), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mips_8888_8_8888), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mips_8888_8_8888), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, mips_8888_8_8888), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, mips_8888_8_8888), + { PIXMAN_OP_NONE }, +}; + +static pixman_bool_t +mips_dspr2_blt (pixman_implementation_t *imp, + uint32_t * src_bits, + uint32_t * dst_bits, + int src_stride, + int dst_stride, + int src_bpp, + int dst_bpp, + int src_x, + int src_y, + int dest_x, + int dest_y, + int width, + int height) +{ + if (!pixman_blt_mips ( + src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, + src_x, src_y, dest_x, dest_y, width, height)) + + { + return _pixman_implementation_blt ( + imp->delegate, + src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, + src_x, src_y, dest_x, dest_y, width, height); + } + + return TRUE; +} + +static pixman_bool_t +mips_dspr2_fill (pixman_implementation_t *imp, + uint32_t * bits, + int stride, + int bpp, + int x, + int y, + int width, + int height, + uint32_t xor) +{ + if (pixman_fill_mips (bits, stride, bpp, x, y, width, height, xor)) + return TRUE; + + return _pixman_implementation_fill ( + imp->delegate, bits, stride, bpp, x, y, width, height, xor); +} + +pixman_implementation_t * +_pixman_implementation_create_mips_dspr2 (pixman_implementation_t *fallback) +{ + pixman_implementation_t *imp = + _pixman_implementation_create (fallback, mips_dspr2_fast_paths); + + imp->blt = mips_dspr2_blt; + imp->fill = mips_dspr2_fill; + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman-mips-dspr2.h b/gfx/cairo/libpixman/src/pixman-mips-dspr2.h new file mode 100644 index 00000000000..a3d774fcbc3 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nemanja Lukic (nlukic@mips.com) + */ + +#ifndef PIXMAN_MIPS_DSPR2_H +#define PIXMAN_MIPS_DSPR2_H + +#include "pixman-private.h" +#include "pixman-inlines.h" + +#define SKIP_ZERO_SRC 1 +#define SKIP_ZERO_MASK 2 +#define DO_FAST_MEMCPY 3 + +void +pixman_mips_fast_memcpy (void *dst, void *src, uint32_t n_bytes); +void +pixman_fill_buff16_mips (void *dst, uint32_t n_bytes, uint16_t value); +void +pixman_fill_buff32_mips (void *dst, uint32_t n_bytes, uint32_t value); + +/****************************************************************/ + +#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST(flags, name, \ + src_type, src_cnt, \ + dst_type, dst_cnt) \ +void \ +pixman_composite_##name##_asm_mips (dst_type *dst, \ + src_type *src, \ + int32_t w); \ + \ +static void \ +mips_composite_##name (pixman_implementation_t *imp, \ + pixman_composite_info_t *info) \ +{ \ + PIXMAN_COMPOSITE_ARGS (info); \ + dst_type *dst_line, *dst; \ + src_type *src_line, *src; \ + int32_t dst_stride, src_stride; \ + int bpp = PIXMAN_FORMAT_BPP (dest_image->bits.format) / 8; \ + \ + PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \ + src_stride, src_line, src_cnt); \ + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \ + dst_stride, dst_line, dst_cnt); \ + \ + while (height--) \ + { \ + dst = dst_line; \ + dst_line += dst_stride; \ + src = src_line; \ + src_line += src_stride; \ + \ + if (flags == DO_FAST_MEMCPY) \ + pixman_mips_fast_memcpy (dst, src, width * bpp); \ + else \ + pixman_composite_##name##_asm_mips (dst, src, width); \ + } \ +} + +/*******************************************************************/ + +#define PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST(flags, name, \ + mask_type, mask_cnt, \ + dst_type, dst_cnt) \ +void \ +pixman_composite_##name##_asm_mips (dst_type *dst, \ + uint32_t src, \ + mask_type *mask, \ + int32_t w); \ + \ +static void \ +mips_composite_##name (pixman_implementation_t *imp, \ + pixman_composite_info_t *info) \ +{ \ + PIXMAN_COMPOSITE_ARGS (info); \ + dst_type *dst_line, *dst; \ + mask_type *mask_line, *mask; \ + int32_t dst_stride, mask_stride; \ + uint32_t src; \ + \ + src = _pixman_image_get_solid ( \ + imp, src_image, dest_image->bits.format); \ + \ + if ((flags & SKIP_ZERO_SRC) && src == 0) \ + return; \ + \ + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \ + dst_stride, dst_line, dst_cnt); \ + PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \ + mask_stride, mask_line, mask_cnt); \ + \ + while (height--) \ + { \ + dst = dst_line; \ + dst_line += dst_stride; \ + mask = mask_line; \ + mask_line += mask_stride; \ + pixman_composite_##name##_asm_mips (dst, src, mask, width); \ + } \ +} + +/****************************************************************************/ + +#define PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST(flags, name, op, \ + src_type, dst_type) \ +void \ +pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips( \ + dst_type * dst, \ + const src_type * src_top, \ + const src_type * src_bottom, \ + int32_t w, \ + int wt, \ + int wb, \ + pixman_fixed_t vx, \ + pixman_fixed_t unit_x); \ +static force_inline void \ +scaled_bilinear_scanline_mips_##name##_##op (dst_type * dst, \ + const uint32_t * mask, \ + const src_type * src_top, \ + const src_type * src_bottom, \ + int32_t w, \ + int wt, \ + int wb, \ + pixman_fixed_t vx, \ + pixman_fixed_t unit_x, \ + pixman_fixed_t max_vx, \ + pixman_bool_t zero_src) \ +{ \ + if ((flags & SKIP_ZERO_SRC) && zero_src) \ + return; \ + pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips (dst, src_top, \ + src_bottom, w, \ + wt, wb, \ + vx, unit_x); \ +} \ + \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_cover_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint32_t, dst_type, COVER, FLAG_NONE) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_none_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint32_t, dst_type, NONE, FLAG_NONE) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_pad_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint32_t, dst_type, PAD, FLAG_NONE) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_normal_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint32_t, dst_type, NORMAL, \ + FLAG_NONE) + +/*****************************************************************************/ + +#define PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST(flags, name, op, \ + src_type, dst_type) \ +void \ +pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips ( \ + dst_type * dst, \ + const uint8_t * mask, \ + const src_type * top, \ + const src_type * bottom, \ + int wt, \ + int wb, \ + pixman_fixed_t x, \ + pixman_fixed_t ux, \ + int width); \ + \ +static force_inline void \ +scaled_bilinear_scanline_mips_##name##_##op (dst_type * dst, \ + const uint8_t * mask, \ + const src_type * src_top, \ + const src_type * src_bottom, \ + int32_t w, \ + int wt, \ + int wb, \ + pixman_fixed_t vx, \ + pixman_fixed_t unit_x, \ + pixman_fixed_t max_vx, \ + pixman_bool_t zero_src) \ +{ \ + if ((flags & SKIP_ZERO_SRC) && zero_src) \ + return; \ + pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips ( \ + dst, mask, src_top, src_bottom, wt, wb, vx, unit_x, w); \ +} \ + \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_cover_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint8_t, dst_type, COVER, \ + FLAG_HAVE_NON_SOLID_MASK) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_none_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint8_t, dst_type, NONE, \ + FLAG_HAVE_NON_SOLID_MASK) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_pad_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint8_t, dst_type, PAD, \ + FLAG_HAVE_NON_SOLID_MASK) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_normal_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint8_t, dst_type, NORMAL, \ + FLAG_HAVE_NON_SOLID_MASK) + +#endif //PIXMAN_MIPS_DSPR2_H diff --git a/gfx/cairo/libpixman/src/pixman-mips-memcpy-asm.S b/gfx/cairo/libpixman/src/pixman-mips-memcpy-asm.S new file mode 100644 index 00000000000..9ad6da53786 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips-memcpy-asm.S @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "pixman-mips-dspr2-asm.h" + +/* + * This routine could be optimized for MIPS64. The current code only + * uses MIPS32 instructions. + */ + +#ifdef EB +# define LWHI lwl /* high part is left in big-endian */ +# define SWHI swl /* high part is left in big-endian */ +# define LWLO lwr /* low part is right in big-endian */ +# define SWLO swr /* low part is right in big-endian */ +#else +# define LWHI lwr /* high part is right in little-endian */ +# define SWHI swr /* high part is right in little-endian */ +# define LWLO lwl /* low part is left in big-endian */ +# define SWLO swl /* low part is left in big-endian */ +#endif + +LEAF_MIPS32R2(pixman_mips_fast_memcpy) + + slti AT, a2, 8 + bne AT, zero, $last8 + move v0, a0 /* memcpy returns the dst pointer */ + +/* Test if the src and dst are word-aligned, or can be made word-aligned */ + xor t8, a1, a0 + andi t8, t8, 0x3 /* t8 is a0/a1 word-displacement */ + + bne t8, zero, $unaligned + negu a3, a0 + + andi a3, a3, 0x3 /* we need to copy a3 bytes to make a0/a1 aligned */ + beq a3, zero, $chk16w /* when a3=0 then the dst (a0) is word-aligned */ + subu a2, a2, a3 /* now a2 is the remining bytes count */ + + LWHI t8, 0(a1) + addu a1, a1, a3 + SWHI t8, 0(a0) + addu a0, a0, a3 + +/* Now the dst/src are mutually word-aligned with word-aligned addresses */ +$chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */ + /* t8 is the byte count after 64-byte chunks */ + + beq a2, t8, $chk8w /* if a2==t8, no 64-byte chunks */ + /* There will be at most 1 32-byte chunk after it */ + subu a3, a2, t8 /* subtract from a2 the reminder */ + /* Here a3 counts bytes in 16w chunks */ + addu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */ + + addu t0, a0, a2 /* t0 is the "past the end" address */ + +/* + * When in the loop we exercise "pref 30, x(a0)", the a0+x should not be past + * the "t0-32" address + * This means: for x=128 the last "safe" a0 address is "t0-160" + * Alternatively, for x=64 the last "safe" a0 address is "t0-96" + * In the current version we use "pref 30, 128(a0)", so "t0-160" is the limit + */ + subu t9, t0, 160 /* t9 is the "last safe pref 30, 128(a0)" address */ + + pref 0, 0(a1) /* bring the first line of src, addr 0 */ + pref 0, 32(a1) /* bring the second line of src, addr 32 */ + pref 0, 64(a1) /* bring the third line of src, addr 64 */ + pref 30, 32(a0) /* safe, as we have at least 64 bytes ahead */ +/* In case the a0 > t9 don't use "pref 30" at all */ + sgtu v1, a0, t9 + bgtz v1, $loop16w /* skip "pref 30, 64(a0)" for too short arrays */ + nop +/* otherwise, start with using pref30 */ + pref 30, 64(a0) +$loop16w: + pref 0, 96(a1) + lw t0, 0(a1) + bgtz v1, $skip_pref30_96 /* skip "pref 30, 96(a0)" */ + lw t1, 4(a1) + pref 30, 96(a0) /* continue setting up the dest, addr 96 */ +$skip_pref30_96: + lw t2, 8(a1) + lw t3, 12(a1) + lw t4, 16(a1) + lw t5, 20(a1) + lw t6, 24(a1) + lw t7, 28(a1) + pref 0, 128(a1) /* bring the next lines of src, addr 128 */ + + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + + lw t0, 32(a1) + bgtz v1, $skip_pref30_128 /* skip "pref 30, 128(a0)" */ + lw t1, 36(a1) + pref 30, 128(a0) /* continue setting up the dest, addr 128 */ +$skip_pref30_128: + lw t2, 40(a1) + lw t3, 44(a1) + lw t4, 48(a1) + lw t5, 52(a1) + lw t6, 56(a1) + lw t7, 60(a1) + pref 0, 160(a1) /* bring the next lines of src, addr 160 */ + + sw t0, 32(a0) + sw t1, 36(a0) + sw t2, 40(a0) + sw t3, 44(a0) + sw t4, 48(a0) + sw t5, 52(a0) + sw t6, 56(a0) + sw t7, 60(a0) + + addiu a0, a0, 64 /* adding 64 to dest */ + sgtu v1, a0, t9 + bne a0, a3, $loop16w + addiu a1, a1, 64 /* adding 64 to src */ + move a2, t8 + +/* Here we have src and dest word-aligned but less than 64-bytes to go */ + +$chk8w: + pref 0, 0x0(a1) + andi t8, a2, 0x1f /* is there a 32-byte chunk? */ + /* the t8 is the reminder count past 32-bytes */ + beq a2, t8, $chk1w /* when a2=t8, no 32-byte chunk */ + nop + + lw t0, 0(a1) + lw t1, 4(a1) + lw t2, 8(a1) + lw t3, 12(a1) + lw t4, 16(a1) + lw t5, 20(a1) + lw t6, 24(a1) + lw t7, 28(a1) + addiu a1, a1, 32 + + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + addiu a0, a0, 32 + +$chk1w: + andi a2, t8, 0x3 /* now a2 is the reminder past 1w chunks */ + beq a2, t8, $last8 + subu a3, t8, a2 /* a3 is count of bytes in 1w chunks */ + addu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */ + +/* copying in words (4-byte chunks) */ +$wordCopy_loop: + lw t3, 0(a1) /* the first t3 may be equal t0 ... optimize? */ + addiu a1, a1, 4 + addiu a0, a0, 4 + bne a0, a3, $wordCopy_loop + sw t3, -4(a0) + +/* For the last (<8) bytes */ +$last8: + blez a2, leave + addu a3, a0, a2 /* a3 is the last dst address */ +$last8loop: + lb v1, 0(a1) + addiu a1, a1, 1 + addiu a0, a0, 1 + bne a0, a3, $last8loop + sb v1, -1(a0) + +leave: j ra + nop + +/* + * UNALIGNED case + */ + +$unaligned: + /* got here with a3="negu a0" */ + andi a3, a3, 0x3 /* test if the a0 is word aligned */ + beqz a3, $ua_chk16w + subu a2, a2, a3 /* bytes left after initial a3 bytes */ + + LWHI v1, 0(a1) + LWLO v1, 3(a1) + addu a1, a1, a3 /* a3 may be here 1, 2 or 3 */ + SWHI v1, 0(a0) + addu a0, a0, a3 /* below the dst will be word aligned (NOTE1) */ + +$ua_chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */ + /* t8 is the byte count after 64-byte chunks */ + beq a2, t8, $ua_chk8w /* if a2==t8, no 64-byte chunks */ + /* There will be at most 1 32-byte chunk after it */ + subu a3, a2, t8 /* subtract from a2 the reminder */ + /* Here a3 counts bytes in 16w chunks */ + addu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */ + + addu t0, a0, a2 /* t0 is the "past the end" address */ + + subu t9, t0, 160 /* t9 is the "last safe pref 30, 128(a0)" address */ + + pref 0, 0(a1) /* bring the first line of src, addr 0 */ + pref 0, 32(a1) /* bring the second line of src, addr 32 */ + pref 0, 64(a1) /* bring the third line of src, addr 64 */ + pref 30, 32(a0) /* safe, as we have at least 64 bytes ahead */ +/* In case the a0 > t9 don't use "pref 30" at all */ + sgtu v1, a0, t9 + bgtz v1, $ua_loop16w /* skip "pref 30, 64(a0)" for too short arrays */ + nop +/* otherwise, start with using pref30 */ + pref 30, 64(a0) +$ua_loop16w: + pref 0, 96(a1) + LWHI t0, 0(a1) + LWLO t0, 3(a1) + LWHI t1, 4(a1) + bgtz v1, $ua_skip_pref30_96 + LWLO t1, 7(a1) + pref 30, 96(a0) /* continue setting up the dest, addr 96 */ +$ua_skip_pref30_96: + LWHI t2, 8(a1) + LWLO t2, 11(a1) + LWHI t3, 12(a1) + LWLO t3, 15(a1) + LWHI t4, 16(a1) + LWLO t4, 19(a1) + LWHI t5, 20(a1) + LWLO t5, 23(a1) + LWHI t6, 24(a1) + LWLO t6, 27(a1) + LWHI t7, 28(a1) + LWLO t7, 31(a1) + pref 0, 128(a1) /* bring the next lines of src, addr 128 */ + + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + + LWHI t0, 32(a1) + LWLO t0, 35(a1) + LWHI t1, 36(a1) + bgtz v1, $ua_skip_pref30_128 + LWLO t1, 39(a1) + pref 30, 128(a0) /* continue setting up the dest, addr 128 */ +$ua_skip_pref30_128: + LWHI t2, 40(a1) + LWLO t2, 43(a1) + LWHI t3, 44(a1) + LWLO t3, 47(a1) + LWHI t4, 48(a1) + LWLO t4, 51(a1) + LWHI t5, 52(a1) + LWLO t5, 55(a1) + LWHI t6, 56(a1) + LWLO t6, 59(a1) + LWHI t7, 60(a1) + LWLO t7, 63(a1) + pref 0, 160(a1) /* bring the next lines of src, addr 160 */ + + sw t0, 32(a0) + sw t1, 36(a0) + sw t2, 40(a0) + sw t3, 44(a0) + sw t4, 48(a0) + sw t5, 52(a0) + sw t6, 56(a0) + sw t7, 60(a0) + + addiu a0, a0, 64 /* adding 64 to dest */ + sgtu v1, a0, t9 + bne a0, a3, $ua_loop16w + addiu a1, a1, 64 /* adding 64 to src */ + move a2, t8 + +/* Here we have src and dest word-aligned but less than 64-bytes to go */ + +$ua_chk8w: + pref 0, 0x0(a1) + andi t8, a2, 0x1f /* is there a 32-byte chunk? */ + /* the t8 is the reminder count */ + beq a2, t8, $ua_chk1w /* when a2=t8, no 32-byte chunk */ + + LWHI t0, 0(a1) + LWLO t0, 3(a1) + LWHI t1, 4(a1) + LWLO t1, 7(a1) + LWHI t2, 8(a1) + LWLO t2, 11(a1) + LWHI t3, 12(a1) + LWLO t3, 15(a1) + LWHI t4, 16(a1) + LWLO t4, 19(a1) + LWHI t5, 20(a1) + LWLO t5, 23(a1) + LWHI t6, 24(a1) + LWLO t6, 27(a1) + LWHI t7, 28(a1) + LWLO t7, 31(a1) + addiu a1, a1, 32 + + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + addiu a0, a0, 32 + +$ua_chk1w: + andi a2, t8, 0x3 /* now a2 is the reminder past 1w chunks */ + beq a2, t8, $ua_smallCopy + subu a3, t8, a2 /* a3 is count of bytes in 1w chunks */ + addu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */ + +/* copying in words (4-byte chunks) */ +$ua_wordCopy_loop: + LWHI v1, 0(a1) + LWLO v1, 3(a1) + addiu a1, a1, 4 + addiu a0, a0, 4 /* note: dst=a0 is word aligned here, see NOTE1 */ + bne a0, a3, $ua_wordCopy_loop + sw v1, -4(a0) + +/* Now less than 4 bytes (value in a2) left to copy */ +$ua_smallCopy: + beqz a2, leave + addu a3, a0, a2 /* a3 is the last dst address */ +$ua_smallCopy_loop: + lb v1, 0(a1) + addiu a1, a1, 1 + addiu a0, a0, 1 + bne a0, a3, $ua_smallCopy_loop + sb v1, -1(a0) + + j ra + nop + +END(pixman_mips_fast_memcpy) diff --git a/gfx/cairo/libpixman/src/pixman-mips.c b/gfx/cairo/libpixman/src/pixman-mips.c new file mode 100644 index 00000000000..2b280c6f164 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips.c @@ -0,0 +1,84 @@ +/* + * Copyright © 2000 SuSE, Inc. + * Copyright © 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" + +#if defined(USE_MIPS_DSPR2) || defined(USE_LOONGSON_MMI) + +#include +#include + +static pixman_bool_t +have_feature (const char *search_string) +{ +#if defined (__linux__) /* linux ELF */ + /* Simple detection of MIPS features at runtime for Linux. + * It is based on /proc/cpuinfo, which reveals hardware configuration + * to user-space applications. According to MIPS (early 2010), no similar + * facility is universally available on the MIPS architectures, so it's up + * to individual OSes to provide such. + */ + const char *file_name = "/proc/cpuinfo"; + char cpuinfo_line[256]; + FILE *f = NULL; + + if ((f = fopen (file_name, "r")) == NULL) + return FALSE; + + while (fgets (cpuinfo_line, sizeof (cpuinfo_line), f) != NULL) + { + if (strstr (cpuinfo_line, search_string) != NULL) + { + fclose (f); + return TRUE; + } + } + + fclose (f); +#endif + + /* Did not find string in the proc file, or not Linux ELF. */ + return FALSE; +} + +#endif + +pixman_implementation_t * +_pixman_mips_get_implementations (pixman_implementation_t *imp) +{ +#ifdef USE_LOONGSON_MMI + /* I really don't know if some Loongson CPUs don't have MMI. */ + if (!_pixman_disabled ("loongson-mmi") && have_feature ("Loongson")) + imp = _pixman_implementation_create_mmx (imp); +#endif + +#ifdef USE_MIPS_DSPR2 + /* Only currently available MIPS core that supports DSPr2 is 74K. */ + if (!_pixman_disabled ("mips-dspr2") && have_feature ("MIPS 74K")) + imp = _pixman_implementation_create_mips_dspr2 (imp); +#endif + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman-mmx.c b/gfx/cairo/libpixman/src/pixman-mmx.c index 9fd1a76f920..74a5e87a8f4 100644 --- a/gfx/cairo/libpixman/src/pixman-mmx.c +++ b/gfx/cairo/libpixman/src/pixman-mmx.c @@ -33,11 +33,16 @@ #include #endif -#if defined USE_X86_MMX || defined USE_ARM_IWMMXT +#if defined USE_X86_MMX || defined USE_ARM_IWMMXT || defined USE_LOONGSON_MMI +#ifdef USE_LOONGSON_MMI +#include +#else #include +#endif #include "pixman-private.h" #include "pixman-combine32.h" +#include "pixman-inlines.h" #define no_vERBOSE @@ -63,6 +68,19 @@ _mm_empty (void) /* We have to compile with -msse to use xmmintrin.h, but that causes SSE * instructions to be generated that we don't want. Just duplicate the * functions we want to use. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movemask_pi8 (__m64 __A) +{ + int ret; + + asm ("pmovmskb %1, %0\n\t" + : "=r" (ret) + : "y" (__A) + ); + + return ret; +} + extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_mulhi_pu16 (__m64 __A, __m64 __B) { @@ -87,8 +105,17 @@ _mm_shuffle_pi16 (__m64 __A, int8_t const __N) return ret; } # else -# define _mm_shuffle_pi16(A, N) \ - ((__m64) __builtin_ia32_pshufw ((__v4hi)(__m64)(A), (int)(N))) +# define _mm_shuffle_pi16(A, N) \ + ({ \ + __m64 ret; \ + \ + asm ("pshufw %2, %1, %0\n\t" \ + : "=y" (ret) \ + : "y" (A), "K" ((const int8_t)N) \ + ); \ + \ + ret; \ + }) # endif # endif #endif @@ -125,11 +152,14 @@ _mm_shuffle_pi16 (__m64 __A, int8_t const __N) * uint64_t and __m64 values, then define USE_CVT_INTRINSICS. * If __m64 and uint64_t values can just be cast to each other directly, * then define USE_M64_CASTS. + * If __m64 is a double datatype, then define USE_M64_DOUBLE. */ #ifdef _MSC_VER # define M64_MEMBER m64_u64 #elif defined(__ICC) # define USE_CVT_INTRINSICS +#elif defined(USE_LOONGSON_MMI) +# define USE_M64_DOUBLE #elif defined(__GNUC__) # define USE_M64_CASTS #elif defined(__SUNPRO_C) @@ -147,7 +177,7 @@ _mm_shuffle_pi16 (__m64 __A, int8_t const __N) # endif #endif -#if defined(USE_M64_CASTS) || defined(USE_CVT_INTRINSICS) +#if defined(USE_M64_CASTS) || defined(USE_CVT_INTRINSICS) || defined(USE_M64_DOUBLE) typedef uint64_t mmxdatafield; #else typedef __m64 mmxdatafield; @@ -159,15 +189,24 @@ typedef struct mmxdatafield mmx_4x0080; mmxdatafield mmx_565_rgb; mmxdatafield mmx_565_unpack_multiplier; + mmxdatafield mmx_565_pack_multiplier; mmxdatafield mmx_565_r; mmxdatafield mmx_565_g; mmxdatafield mmx_565_b; + mmxdatafield mmx_packed_565_rb; + mmxdatafield mmx_packed_565_g; + mmxdatafield mmx_expand_565_g; + mmxdatafield mmx_expand_565_b; + mmxdatafield mmx_expand_565_r; +#ifndef USE_LOONGSON_MMI mmxdatafield mmx_mask_0; mmxdatafield mmx_mask_1; mmxdatafield mmx_mask_2; mmxdatafield mmx_mask_3; +#endif mmxdatafield mmx_full_alpha; mmxdatafield mmx_4x0101; + mmxdatafield mmx_ff000000; } mmx_data_t; #if defined(_MSC_VER) @@ -184,21 +223,32 @@ static const mmx_data_t c = MMXDATA_INIT (.mmx_4x0080, 0x0080008000800080), MMXDATA_INIT (.mmx_565_rgb, 0x000001f0003f001f), MMXDATA_INIT (.mmx_565_unpack_multiplier, 0x0000008404100840), + MMXDATA_INIT (.mmx_565_pack_multiplier, 0x2000000420000004), MMXDATA_INIT (.mmx_565_r, 0x000000f800000000), MMXDATA_INIT (.mmx_565_g, 0x0000000000fc0000), MMXDATA_INIT (.mmx_565_b, 0x00000000000000f8), + MMXDATA_INIT (.mmx_packed_565_rb, 0x00f800f800f800f8), + MMXDATA_INIT (.mmx_packed_565_g, 0x0000fc000000fc00), + MMXDATA_INIT (.mmx_expand_565_g, 0x07e007e007e007e0), + MMXDATA_INIT (.mmx_expand_565_b, 0x001f001f001f001f), + MMXDATA_INIT (.mmx_expand_565_r, 0xf800f800f800f800), +#ifndef USE_LOONGSON_MMI MMXDATA_INIT (.mmx_mask_0, 0xffffffffffff0000), MMXDATA_INIT (.mmx_mask_1, 0xffffffff0000ffff), MMXDATA_INIT (.mmx_mask_2, 0xffff0000ffffffff), MMXDATA_INIT (.mmx_mask_3, 0x0000ffffffffffff), +#endif MMXDATA_INIT (.mmx_full_alpha, 0x00ff000000000000), MMXDATA_INIT (.mmx_4x0101, 0x0101010101010101), + MMXDATA_INIT (.mmx_ff000000, 0xff000000ff000000), }; #ifdef USE_CVT_INTRINSICS # define MC(x) to_m64 (c.mmx_ ## x) #elif defined(USE_M64_CASTS) # define MC(x) ((__m64)c.mmx_ ## x) +#elif defined(USE_M64_DOUBLE) +# define MC(x) (*(__m64 *)&c.mmx_ ## x) #else # define MC(x) c.mmx_ ## x #endif @@ -213,6 +263,8 @@ to_m64 (uint64_t x) res.M64_MEMBER = x; return res; +#elif defined USE_M64_DOUBLE + return *(__m64 *)&x; #else /* USE_M64_CASTS */ return (__m64)x; #endif @@ -226,6 +278,8 @@ to_uint64 (__m64 x) #elif defined M64_MEMBER /* __m64 is a struct, not an integral type */ uint64_t res = x.M64_MEMBER; return res; +#elif defined USE_M64_DOUBLE + return *(uint64_t *)&x; #else /* USE_M64_CASTS */ return (uint64_t)x; #endif @@ -324,7 +378,7 @@ in_over (__m64 src, __m64 srca, __m64 mask, __m64 dest) /* Elemental unaligned loads */ -static force_inline __m64 ldq_u(uint64_t *p) +static force_inline __m64 ldq_u(__m64 *p) { #ifdef USE_X86_MMX /* x86's alignment restrictions are very relaxed. */ @@ -337,7 +391,7 @@ static force_inline __m64 ldq_u(uint64_t *p) aligned_p = (__m64 *)((uintptr_t)p & ~7); return (__m64) _mm_align_si64 (aligned_p[0], aligned_p[1], align); #else - struct __una_u64 { uint64_t x __attribute__((packed)); }; + struct __una_u64 { __m64 x __attribute__((packed)); }; const struct __una_u64 *ptr = (const struct __una_u64 *) p; return (__m64) ptr->x; #endif @@ -355,17 +409,36 @@ static force_inline uint32_t ldl_u(const uint32_t *p) #endif } +static force_inline __m64 +load (const uint32_t *v) +{ +#ifdef USE_LOONGSON_MMI + __m64 ret; + asm ("lwc1 %0, %1\n\t" + : "=f" (ret) + : "m" (*v) + ); + return ret; +#else + return _mm_cvtsi32_si64 (*v); +#endif +} + static force_inline __m64 load8888 (const uint32_t *v) { - return _mm_unpacklo_pi8 (_mm_cvtsi32_si64 (*v), _mm_setzero_si64 ()); +#ifdef USE_LOONGSON_MMI + return _mm_unpacklo_pi8_f (*(__m32 *)v, _mm_setzero_si64 ()); +#else + return _mm_unpacklo_pi8 (load (v), _mm_setzero_si64 ()); +#endif } static force_inline __m64 load8888u (const uint32_t *v) { - uint32_t l = ldl_u(v); - return load8888(&l); + uint32_t l = ldl_u (v); + return load8888 (&l); } static force_inline __m64 @@ -374,11 +447,53 @@ pack8888 (__m64 lo, __m64 hi) return _mm_packs_pu16 (lo, hi); } +static force_inline void +store (uint32_t *dest, __m64 v) +{ +#ifdef USE_LOONGSON_MMI + asm ("swc1 %1, %0\n\t" + : "=m" (*dest) + : "f" (v) + : "memory" + ); +#else + *dest = _mm_cvtsi64_si32 (v); +#endif +} + static force_inline void store8888 (uint32_t *dest, __m64 v) { - v = pack8888 (v, _mm_setzero_si64()); - *dest = _mm_cvtsi64_si32 (v); + v = pack8888 (v, _mm_setzero_si64 ()); + store (dest, v); +} + +static force_inline pixman_bool_t +is_equal (__m64 a, __m64 b) +{ +#ifdef USE_LOONGSON_MMI + /* __m64 is double, we can compare directly. */ + return a == b; +#else + return _mm_movemask_pi8 (_mm_cmpeq_pi8 (a, b)) == 0xff; +#endif +} + +static force_inline pixman_bool_t +is_opaque (__m64 v) +{ +#ifdef USE_LOONGSON_MMI + return is_equal (_mm_and_si64 (v, MC (full_alpha)), MC (full_alpha)); +#else + __m64 ffs = _mm_cmpeq_pi8 (v, v); + return (_mm_movemask_pi8 (_mm_cmpeq_pi8 (v, ffs)) & 0x40); +#endif +} + +static force_inline pixman_bool_t +is_zero (__m64 v) +{ + return is_equal (v, _mm_setzero_si64 ()); } /* Expand 16 bits positioned at @pos (0-3) of a mmx register into @@ -402,7 +517,11 @@ expand565 (__m64 pixel, int pos) __m64 t1, t2; /* move pixel to low 16 bit and zero the rest */ +#ifdef USE_LOONGSON_MMI + p = loongson_extract_pi16 (p, pos); +#else p = shift (shift (p, (3 - pos) * 16), -48); +#endif t1 = shift (p, 36 - 11); t2 = shift (p, 16 - 5); @@ -415,6 +534,36 @@ expand565 (__m64 pixel, int pos) return _mm_srli_pi16 (pixel, 8); } +/* Expand 4 16 bit pixels in an mmx register into two mmx registers of + * + * AARRGGBBRRGGBB + */ +static force_inline void +expand_4xpacked565 (__m64 vin, __m64 *vout0, __m64 *vout1, int full_alpha) +{ + __m64 t0, t1, alpha = _mm_setzero_si64 ();; + __m64 r = _mm_and_si64 (vin, MC (expand_565_r)); + __m64 g = _mm_and_si64 (vin, MC (expand_565_g)); + __m64 b = _mm_and_si64 (vin, MC (expand_565_b)); + if (full_alpha) + alpha = _mm_cmpeq_pi32 (alpha, alpha); + + /* Replicate high bits into empty low bits. */ + r = _mm_or_si64 (_mm_srli_pi16 (r, 8), _mm_srli_pi16 (r, 13)); + g = _mm_or_si64 (_mm_srli_pi16 (g, 3), _mm_srli_pi16 (g, 9)); + b = _mm_or_si64 (_mm_slli_pi16 (b, 3), _mm_srli_pi16 (b, 2)); + + r = _mm_packs_pu16 (r, _mm_setzero_si64 ()); /* 00 00 00 00 R3 R2 R1 R0 */ + g = _mm_packs_pu16 (g, _mm_setzero_si64 ()); /* 00 00 00 00 G3 G2 G1 G0 */ + b = _mm_packs_pu16 (b, _mm_setzero_si64 ()); /* 00 00 00 00 B3 B2 B1 B0 */ + + t1 = _mm_unpacklo_pi8 (r, alpha); /* A3 R3 A2 R2 A1 R1 A0 R0 */ + t0 = _mm_unpacklo_pi8 (b, g); /* G3 B3 G2 B2 G1 B1 G0 B0 */ + + *vout0 = _mm_unpacklo_pi16 (t0, t1); /* A1 R1 G1 B1 A0 R0 G0 B0 */ + *vout1 = _mm_unpackhi_pi16 (t0, t1); /* A3 R3 G3 B3 A2 R2 G2 B2 */ +} + static force_inline __m64 expand8888 (__m64 in, int pos) { @@ -430,6 +579,17 @@ expandx888 (__m64 in, int pos) return _mm_or_si64 (expand8888 (in, pos), MC (full_alpha)); } +static force_inline void +expand_4x565 (__m64 vin, __m64 *vout0, __m64 *vout1, __m64 *vout2, __m64 *vout3, int full_alpha) +{ + __m64 v0, v1; + expand_4xpacked565 (vin, &v0, &v1, full_alpha); + *vout0 = expand8888 (v0, 0); + *vout1 = expand8888 (v0, 1); + *vout2 = expand8888 (v1, 0); + *vout3 = expand8888 (v1, 1); +} + static force_inline __m64 pack_565 (__m64 pixel, __m64 target, int pos) { @@ -441,6 +601,15 @@ pack_565 (__m64 pixel, __m64 target, int pos) g = _mm_and_si64 (p, MC (565_g)); b = _mm_and_si64 (p, MC (565_b)); +#ifdef USE_LOONGSON_MMI + r = shift (r, -(32 - 8)); + g = shift (g, -(16 - 3)); + b = shift (b, -(0 + 3)); + + p = _mm_or_si64 (r, g); + p = _mm_or_si64 (p, b); + return loongson_insert_pi16 (t, p, pos); +#else r = shift (r, -(32 - 8) + pos * 16); g = shift (g, -(16 - 3) + pos * 16); b = shift (b, -(0 + 3) + pos * 16); @@ -458,10 +627,42 @@ pack_565 (__m64 pixel, __m64 target, int pos) p = _mm_or_si64 (g, p); return _mm_or_si64 (b, p); +#endif +} + +static force_inline __m64 +pack_4xpacked565 (__m64 a, __m64 b) +{ + __m64 rb0 = _mm_and_si64 (a, MC (packed_565_rb)); + __m64 rb1 = _mm_and_si64 (b, MC (packed_565_rb)); + + __m64 t0 = _mm_madd_pi16 (rb0, MC (565_pack_multiplier)); + __m64 t1 = _mm_madd_pi16 (rb1, MC (565_pack_multiplier)); + + __m64 g0 = _mm_and_si64 (a, MC (packed_565_g)); + __m64 g1 = _mm_and_si64 (b, MC (packed_565_g)); + + t0 = _mm_or_si64 (t0, g0); + t1 = _mm_or_si64 (t1, g1); + + t0 = shift(t0, -5); +#ifdef USE_ARM_IWMMXT + t1 = shift(t1, -5); + return _mm_packs_pu32 (t0, t1); +#else + t1 = shift(t1, -5 + 16); + return _mm_shuffle_pi16 (_mm_or_si64 (t0, t1), _MM_SHUFFLE (3, 1, 2, 0)); +#endif } #ifndef _MSC_VER +static force_inline __m64 +pack_4x565 (__m64 v0, __m64 v1, __m64 v2, __m64 v3) +{ + return pack_4xpacked565 (pack8888 (v0, v1), pack8888 (v2, v3)); +} + static force_inline __m64 pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b) { @@ -473,6 +674,11 @@ pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b) #else +/* MSVC only handles a "pass by register" of up to three SSE intrinsics */ + +#define pack_4x565(v0, v1, v2, v3) \ + pack_4xpacked565 (pack8888 (v0, v1), pack8888 (v2, v3)) + #define pix_add_mul(x, a, y, b) \ ( x = pix_multiply (x, a), \ y = pix_multiply (y, b), \ @@ -482,23 +688,38 @@ pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b) /* --------------- MMX code patch for fbcompose.c --------------------- */ -static force_inline uint32_t +static force_inline __m64 combine (const uint32_t *src, const uint32_t *mask) { - uint32_t ssrc = *src; + __m64 vsrc = load8888 (src); if (mask) { __m64 m = load8888 (mask); - __m64 s = load8888 (&ssrc); m = expand_alpha (m); - s = pix_multiply (s, m); - - store8888 (&ssrc, s); + vsrc = pix_multiply (vsrc, m); } - return ssrc; + return vsrc; +} + +static force_inline __m64 +core_combine_over_u_pixel_mmx (__m64 vsrc, __m64 vdst) +{ + vsrc = _mm_unpacklo_pi8 (vsrc, _mm_setzero_si64 ()); + + if (is_opaque (vsrc)) + { + return vsrc; + } + else if (!is_zero (vsrc)) + { + return over (vsrc, expand_alpha (vsrc), + _mm_unpacklo_pi8 (vdst, _mm_setzero_si64 ())); + } + + return _mm_unpacklo_pi8 (vdst, _mm_setzero_si64 ()); } static void @@ -513,19 +734,16 @@ mmx_combine_over_u (pixman_implementation_t *imp, while (dest < end) { - uint32_t ssrc = combine (src, mask); - uint32_t a = ssrc >> 24; + __m64 vsrc = combine (src, mask); - if (a == 0xff) + if (is_opaque (vsrc)) { - *dest = ssrc; + store8888 (dest, vsrc); } - else if (ssrc) + else if (!is_zero (vsrc)) { - __m64 s, sa; - s = load8888 (&ssrc); - sa = expand_alpha (s); - store8888 (dest, over (s, sa, load8888 (dest))); + __m64 sa = expand_alpha (vsrc); + store8888 (dest, over (vsrc, sa, load8888 (dest))); } ++dest; @@ -549,11 +767,11 @@ mmx_combine_over_reverse_u (pixman_implementation_t *imp, while (dest < end) { __m64 d, da; - uint32_t s = combine (src, mask); + __m64 s = combine (src, mask); d = load8888 (dest); da = expand_alpha (d); - store8888 (dest, over (d, da, load8888 (&s))); + store8888 (dest, over (d, da, s)); ++dest; ++src; @@ -575,10 +793,9 @@ mmx_combine_in_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a; + __m64 x = combine (src, mask); - x = load8888 (&ssrc); a = load8888 (dest); a = expand_alpha (a); x = pix_multiply (x, a); @@ -605,11 +822,10 @@ mmx_combine_in_reverse_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a = combine (src, mask); + __m64 x; x = load8888 (dest); - a = load8888 (&ssrc); a = expand_alpha (a); x = pix_multiply (x, a); store8888 (dest, x); @@ -634,10 +850,9 @@ mmx_combine_out_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a; + __m64 x = combine (src, mask); - x = load8888 (&ssrc); a = load8888 (dest); a = expand_alpha (a); a = negate (a); @@ -664,11 +879,10 @@ mmx_combine_out_reverse_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a = combine (src, mask); + __m64 x; x = load8888 (dest); - a = load8888 (&ssrc); a = expand_alpha (a); a = negate (a); x = pix_multiply (x, a); @@ -695,10 +909,9 @@ mmx_combine_atop_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, da, d, sia; - uint32_t ssrc = combine (src, mask); + __m64 da, d, sia; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); sia = expand_alpha (s); sia = negate (sia); @@ -728,10 +941,9 @@ mmx_combine_atop_reverse_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, dia, d, sa; - uint32_t ssrc = combine (src, mask); + __m64 dia, d, sa; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); sa = expand_alpha (s); dia = expand_alpha (d); @@ -759,10 +971,9 @@ mmx_combine_xor_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, dia, d, sia; - uint32_t ssrc = combine (src, mask); + __m64 dia, d, sia; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); sia = expand_alpha (s); dia = expand_alpha (d); @@ -791,10 +1002,9 @@ mmx_combine_add_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, d; - uint32_t ssrc = combine (src, mask); + __m64 d; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); s = pix_add (s, d); store8888 (dest, s); @@ -819,12 +1029,14 @@ mmx_combine_saturate_u (pixman_implementation_t *imp, while (dest < end) { - uint32_t s = combine (src, mask); + uint32_t s, sa, da; uint32_t d = *dest; - __m64 ms = load8888 (&s); - __m64 md = load8888 (&d); - uint32_t sa = s >> 24; - uint32_t da = ~d >> 24; + __m64 ms = combine (src, mask); + __m64 md = load8888 (dest); + + store8888(&s, ms); + da = ~d >> 24; + sa = s >> 24; if (sa > da) { @@ -1270,16 +1482,17 @@ mmx_composite_over_n_0565 (pixman_implementation_t *imp, while (w >= 4) { - __m64 vdest; + __m64 vdest = *(__m64 *)dst; + __m64 v0, v1, v2, v3; - vdest = *(__m64 *)dst; + expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0); - vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 0)), vdest, 0); - vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 1)), vdest, 1); - vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 2)), vdest, 2); - vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 3)), vdest, 3); + v0 = over (vsrc, vsrca, v0); + v1 = over (vsrc, vsrca, v1); + v2 = over (vsrc, vsrca, v2); + v3 = over (vsrc, vsrca, v3); - *(__m64 *)dst = vdest; + *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3); dst += 4; w -= 4; @@ -1414,9 +1627,7 @@ mmx_composite_over_8888_n_8888 (pixman_implementation_t *imp, PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format); - mask &= 0xff000000; - mask = mask | mask >> 8 | mask >> 16 | mask >> 24; - vmask = load8888 (&mask); + vmask = expand_alpha (load8888 (&mask)); while (height--) { @@ -1440,7 +1651,7 @@ mmx_composite_over_8888_n_8888 (pixman_implementation_t *imp, while (w >= 2) { - __m64 vs = ldq_u((uint64_t *)src); + __m64 vs = ldq_u ((__m64 *)src); __m64 vd = *(__m64 *)dst; __m64 vsrc0 = expand8888 (vs, 0); __m64 vsrc1 = expand8888 (vs, 1); @@ -1485,9 +1696,7 @@ mmx_composite_over_x888_n_8888 (pixman_implementation_t *imp, PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format); - mask &= 0xff000000; - mask = mask | mask >> 8 | mask >> 16 | mask >> 24; - vmask = load8888 (&mask); + vmask = expand_alpha (load8888 (&mask)); srca = MC (4x00ff); while (height--) @@ -1522,14 +1731,14 @@ mmx_composite_over_x888_n_8888 (pixman_implementation_t *imp, __m64 vd6 = *(__m64 *)(dst + 12); __m64 vd7 = *(__m64 *)(dst + 14); - __m64 vs0 = ldq_u((uint64_t *)(src + 0)); - __m64 vs1 = ldq_u((uint64_t *)(src + 2)); - __m64 vs2 = ldq_u((uint64_t *)(src + 4)); - __m64 vs3 = ldq_u((uint64_t *)(src + 6)); - __m64 vs4 = ldq_u((uint64_t *)(src + 8)); - __m64 vs5 = ldq_u((uint64_t *)(src + 10)); - __m64 vs6 = ldq_u((uint64_t *)(src + 12)); - __m64 vs7 = ldq_u((uint64_t *)(src + 14)); + __m64 vs0 = ldq_u ((__m64 *)(src + 0)); + __m64 vs1 = ldq_u ((__m64 *)(src + 2)); + __m64 vs2 = ldq_u ((__m64 *)(src + 4)); + __m64 vs3 = ldq_u ((__m64 *)(src + 6)); + __m64 vs4 = ldq_u ((__m64 *)(src + 8)); + __m64 vs5 = ldq_u ((__m64 *)(src + 10)); + __m64 vs6 = ldq_u ((__m64 *)(src + 12)); + __m64 vs7 = ldq_u ((__m64 *)(src + 14)); vd0 = pack8888 ( in_over (expandx888 (vs0, 0), srca, vmask, expand8888 (vd0, 0)), @@ -1692,22 +1901,22 @@ mmx_composite_over_8888_0565 (pixman_implementation_t *imp, while (w >= 4) { - __m64 vsrc0, vsrc1, vsrc2, vsrc3; - __m64 vdest; + __m64 vdest = *(__m64 *)dst; + __m64 v0, v1, v2, v3; - vsrc0 = load8888 ((src + 0)); - vsrc1 = load8888 ((src + 1)); - vsrc2 = load8888 ((src + 2)); - vsrc3 = load8888 ((src + 3)); + expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0); - vdest = *(__m64 *)dst; + __m64 vsrc0 = load8888 ((src + 0)); + __m64 vsrc1 = load8888 ((src + 1)); + __m64 vsrc2 = load8888 ((src + 2)); + __m64 vsrc3 = load8888 ((src + 3)); - vdest = pack_565 (over (vsrc0, expand_alpha (vsrc0), expand565 (vdest, 0)), vdest, 0); - vdest = pack_565 (over (vsrc1, expand_alpha (vsrc1), expand565 (vdest, 1)), vdest, 1); - vdest = pack_565 (over (vsrc2, expand_alpha (vsrc2), expand565 (vdest, 2)), vdest, 2); - vdest = pack_565 (over (vsrc3, expand_alpha (vsrc3), expand565 (vdest, 3)), vdest, 3); + v0 = over (vsrc0, expand_alpha (vsrc0), v0); + v1 = over (vsrc1, expand_alpha (vsrc1), v1); + v2 = over (vsrc2, expand_alpha (vsrc2), v2); + v3 = over (vsrc3, expand_alpha (vsrc3), v3); - *(__m64 *)dst = vdest; + *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3); w -= 4; dst += 4; @@ -1995,6 +2204,62 @@ pixman_fill_mmx (uint32_t *bits, return TRUE; } +static void +mmx_composite_src_x888_0565 (pixman_implementation_t *imp, + pixman_composite_info_t *info) +{ + PIXMAN_COMPOSITE_ARGS (info); + uint16_t *dst_line, *dst; + uint32_t *src_line, *src, s; + int dst_stride, src_stride; + int32_t w; + + PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); + + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + src = src_line; + src_line += src_stride; + w = width; + + while (w && (unsigned long)dst & 7) + { + s = *src++; + *dst = CONVERT_8888_TO_0565 (s); + dst++; + w--; + } + + while (w >= 4) + { + __m64 vdest; + __m64 vsrc0 = ldq_u ((__m64 *)(src + 0)); + __m64 vsrc1 = ldq_u ((__m64 *)(src + 2)); + + vdest = pack_4xpacked565 (vsrc0, vsrc1); + + *(__m64 *)dst = vdest; + + w -= 4; + src += 4; + dst += 4; + } + + while (w) + { + s = *src++; + *dst = CONVERT_8888_TO_0565 (s); + dst++; + w--; + } + } + + _mm_empty (); +} + static void mmx_composite_src_n_8_8888 (pixman_implementation_t *imp, pixman_composite_info_t *info) @@ -2123,7 +2388,7 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp, int dst_stride, mask_stride; int32_t w; __m64 vsrc, vsrca, tmp; - uint64_t srcsrcsrcsrc, src16; + __m64 srcsrcsrcsrc; CHECKPOINT (); @@ -2140,11 +2405,7 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp, vsrca = expand_alpha (vsrc); tmp = pack_565 (vsrc, _mm_setzero_si64 (), 0); - src16 = to_uint64 (tmp); - - srcsrcsrcsrc = - (uint64_t)src16 << 48 | (uint64_t)src16 << 32 | - (uint64_t)src16 << 16 | (uint64_t)src16; + srcsrcsrcsrc = expand_alpha_rev (tmp); while (height--) { @@ -2188,29 +2449,28 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp, if (srca == 0xff && (m0 & m1 & m2 & m3) == 0xff) { - *(uint64_t *)dst = srcsrcsrcsrc; + *(__m64 *)dst = srcsrcsrcsrc; } else if (m0 | m1 | m2 | m3) { - __m64 vdest; - __m64 vm0, vm1, vm2, vm3; + __m64 vdest = *(__m64 *)dst; + __m64 v0, v1, v2, v3; - vdest = *(__m64 *)dst; + expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0); - vm0 = to_m64 (m0); - vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm0), - expand565 (vdest, 0)), vdest, 0); - vm1 = to_m64 (m1); - vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm1), - expand565 (vdest, 1)), vdest, 1); - vm2 = to_m64 (m2); - vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm2), - expand565 (vdest, 2)), vdest, 2); - vm3 = to_m64 (m3); - vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm3), - expand565 (vdest, 3)), vdest, 3); + __m64 vm0 = to_m64 (m0); + v0 = in_over (vsrc, vsrca, expand_alpha_rev (vm0), v0); - *(__m64 *)dst = vdest; + __m64 vm1 = to_m64 (m1); + v1 = in_over (vsrc, vsrca, expand_alpha_rev (vm1), v1); + + __m64 vm2 = to_m64 (m2); + v2 = in_over (vsrc, vsrca, expand_alpha_rev (vm2), v2); + + __m64 vm3 = to_m64 (m3); + v3 = in_over (vsrc, vsrca, expand_alpha_rev (vm3), v3); + + *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3);; } w -= 4; @@ -2307,24 +2567,31 @@ mmx_composite_over_pixbuf_0565 (pixman_implementation_t *imp, if ((a0 & a1 & a2 & a3) == 0xFF) { - __m64 vdest; - vdest = pack_565 (invert_colors (load8888 (&s0)), _mm_setzero_si64 (), 0); - vdest = pack_565 (invert_colors (load8888 (&s1)), vdest, 1); - vdest = pack_565 (invert_colors (load8888 (&s2)), vdest, 2); - vdest = pack_565 (invert_colors (load8888 (&s3)), vdest, 3); + __m64 v0 = invert_colors (load8888 (&s0)); + __m64 v1 = invert_colors (load8888 (&s1)); + __m64 v2 = invert_colors (load8888 (&s2)); + __m64 v3 = invert_colors (load8888 (&s3)); - *(__m64 *)dst = vdest; + *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3); } else if (s0 | s1 | s2 | s3) { __m64 vdest = *(__m64 *)dst; + __m64 v0, v1, v2, v3; - vdest = pack_565 (over_rev_non_pre (load8888 (&s0), expand565 (vdest, 0)), vdest, 0); - vdest = pack_565 (over_rev_non_pre (load8888 (&s1), expand565 (vdest, 1)), vdest, 1); - vdest = pack_565 (over_rev_non_pre (load8888 (&s2), expand565 (vdest, 2)), vdest, 2); - vdest = pack_565 (over_rev_non_pre (load8888 (&s3), expand565 (vdest, 3)), vdest, 3); + __m64 vsrc0 = load8888 (&s0); + __m64 vsrc1 = load8888 (&s1); + __m64 vsrc2 = load8888 (&s2); + __m64 vsrc3 = load8888 (&s3); - *(__m64 *)dst = vdest; + expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0); + + v0 = over_rev_non_pre (vsrc0, v0); + v1 = over_rev_non_pre (vsrc1, v1); + v2 = over_rev_non_pre (vsrc2, v2); + v3 = over_rev_non_pre (vsrc3, v3); + + *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3); } w -= 4; @@ -2498,13 +2765,16 @@ mmx_composite_over_n_8888_0565_ca (pixman_implementation_t *imp, if ((m0 | m1 | m2 | m3)) { __m64 vdest = *(__m64 *)q; + __m64 v0, v1, v2, v3; - vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m0), expand565 (vdest, 0)), vdest, 0); - vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m1), expand565 (vdest, 1)), vdest, 1); - vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m2), expand565 (vdest, 2)), vdest, 2); - vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m3), expand565 (vdest, 3)), vdest, 3); + expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0); - *(__m64 *)q = vdest; + v0 = in_over (vsrc, vsrca, load8888 (&m0), v0); + v1 = in_over (vsrc, vsrca, load8888 (&m1), v1); + v2 = in_over (vsrc, vsrca, load8888 (&m2), v2); + v3 = in_over (vsrc, vsrca, load8888 (&m3), v3); + + *(__m64 *)q = pack_4x565 (v0, v1, v2, v3); } twidth -= 4; p += 4; @@ -2809,7 +3079,7 @@ mmx_composite_add_8_8 (pixman_implementation_t *imp, while (w >= 8) { - *(__m64*)dst = _mm_adds_pu8 (ldq_u((uint64_t *)src), *(__m64*)dst); + *(__m64*)dst = _mm_adds_pu8 (ldq_u ((__m64 *)src), *(__m64*)dst); dst += 8; src += 8; w -= 8; @@ -2832,12 +3102,95 @@ mmx_composite_add_8_8 (pixman_implementation_t *imp, _mm_empty (); } +static void +mmx_composite_add_0565_0565 (pixman_implementation_t *imp, + pixman_composite_info_t *info) +{ + PIXMAN_COMPOSITE_ARGS (info); + uint16_t *dst_line, *dst; + uint32_t d; + uint16_t *src_line, *src; + uint32_t s; + int dst_stride, src_stride; + int32_t w; + + CHECKPOINT (); + + PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint16_t, src_stride, src_line, 1); + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); + + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + src = src_line; + src_line += src_stride; + w = width; + + while (w && (unsigned long)dst & 7) + { + s = *src++; + if (s) + { + d = *dst; + s = CONVERT_0565_TO_8888 (s); + if (d) + { + d = CONVERT_0565_TO_8888 (d); + UN8x4_ADD_UN8x4 (s, d); + } + *dst = CONVERT_8888_TO_0565 (s); + } + dst++; + w--; + } + + while (w >= 4) + { + __m64 vdest = *(__m64 *)dst; + __m64 vsrc = ldq_u ((__m64 *)src); + __m64 vd0, vd1; + __m64 vs0, vs1; + + expand_4xpacked565 (vdest, &vd0, &vd1, 0); + expand_4xpacked565 (vsrc, &vs0, &vs1, 0); + + vd0 = _mm_adds_pu8 (vd0, vs0); + vd1 = _mm_adds_pu8 (vd1, vs1); + + *(__m64 *)dst = pack_4xpacked565 (vd0, vd1); + + dst += 4; + src += 4; + w -= 4; + } + + while (w--) + { + s = *src++; + if (s) + { + d = *dst; + s = CONVERT_0565_TO_8888 (s); + if (d) + { + d = CONVERT_0565_TO_8888 (d); + UN8x4_ADD_UN8x4 (s, d); + } + *dst = CONVERT_8888_TO_0565 (s); + } + dst++; + } + } + + _mm_empty (); +} + static void mmx_composite_add_8888_8888 (pixman_implementation_t *imp, pixman_composite_info_t *info) { PIXMAN_COMPOSITE_ARGS (info); - __m64 dst64; uint32_t *dst_line, *dst; uint32_t *src_line, *src; int dst_stride, src_stride; @@ -2858,8 +3211,8 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp, while (w && (unsigned long)dst & 7) { - *dst = _mm_cvtsi64_si32 (_mm_adds_pu8 (_mm_cvtsi32_si64 (*src), - _mm_cvtsi32_si64 (*dst))); + store (dst, _mm_adds_pu8 (load ((const uint32_t *)src), + load ((const uint32_t *)dst))); dst++; src++; w--; @@ -2867,8 +3220,7 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp, while (w >= 2) { - dst64 = _mm_adds_pu8 (ldq_u((uint64_t *)src), *(__m64*)dst); - *(uint64_t*)dst = to_uint64 (dst64); + *(__m64 *)dst = _mm_adds_pu8 (ldq_u ((__m64 *)src), *(__m64*)dst); dst += 2; src += 2; w -= 2; @@ -2876,8 +3228,8 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp, if (w) { - *dst = _mm_cvtsi64_si32 (_mm_adds_pu8 (_mm_cvtsi32_si64 (*src), - _mm_cvtsi32_si64 (*dst))); + store (dst, _mm_adds_pu8 (load ((const uint32_t *)src), + load ((const uint32_t *)dst))); } } @@ -2958,7 +3310,7 @@ pixman_blt_mmx (uint32_t *src_bits, while (w >= 4 && ((unsigned long)d & 7)) { - *(uint32_t *)d = ldl_u((uint32_t *)s); + *(uint32_t *)d = ldl_u ((uint32_t *)s); w -= 4; s += 4; @@ -2992,14 +3344,14 @@ pixman_blt_mmx (uint32_t *src_bits, "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"); #else - __m64 v0 = ldq_u((uint64_t *)(s + 0)); - __m64 v1 = ldq_u((uint64_t *)(s + 8)); - __m64 v2 = ldq_u((uint64_t *)(s + 16)); - __m64 v3 = ldq_u((uint64_t *)(s + 24)); - __m64 v4 = ldq_u((uint64_t *)(s + 32)); - __m64 v5 = ldq_u((uint64_t *)(s + 40)); - __m64 v6 = ldq_u((uint64_t *)(s + 48)); - __m64 v7 = ldq_u((uint64_t *)(s + 56)); + __m64 v0 = ldq_u ((__m64 *)(s + 0)); + __m64 v1 = ldq_u ((__m64 *)(s + 8)); + __m64 v2 = ldq_u ((__m64 *)(s + 16)); + __m64 v3 = ldq_u ((__m64 *)(s + 24)); + __m64 v4 = ldq_u ((__m64 *)(s + 32)); + __m64 v5 = ldq_u ((__m64 *)(s + 40)); + __m64 v6 = ldq_u ((__m64 *)(s + 48)); + __m64 v7 = ldq_u ((__m64 *)(s + 56)); *(__m64 *)(d + 0) = v0; *(__m64 *)(d + 8) = v1; *(__m64 *)(d + 16) = v2; @@ -3016,7 +3368,7 @@ pixman_blt_mmx (uint32_t *src_bits, } while (w >= 4) { - *(uint32_t *)d = ldl_u((uint32_t *)s); + *(uint32_t *)d = ldl_u ((uint32_t *)s); w -= 4; s += 4; @@ -3109,6 +3461,490 @@ mmx_composite_over_x888_8_8888 (pixman_implementation_t *imp, _mm_empty (); } +static void +mmx_composite_over_reverse_n_8888 (pixman_implementation_t *imp, + pixman_composite_info_t *info) +{ + PIXMAN_COMPOSITE_ARGS (info); + uint32_t src; + uint32_t *dst_line, *dst; + int32_t w; + int dst_stride; + __m64 vsrc; + + CHECKPOINT (); + + src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); + + if (src == 0) + return; + + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); + + vsrc = load8888 (&src); + + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + w = width; + + CHECKPOINT (); + + while (w && (unsigned long)dst & 7) + { + __m64 vdest = load8888 (dst); + + store8888 (dst, over (vdest, expand_alpha (vdest), vsrc)); + + w--; + dst++; + } + + while (w >= 2) + { + __m64 vdest = *(__m64 *)dst; + __m64 dest0 = expand8888 (vdest, 0); + __m64 dest1 = expand8888 (vdest, 1); + + + dest0 = over (dest0, expand_alpha (dest0), vsrc); + dest1 = over (dest1, expand_alpha (dest1), vsrc); + + *(__m64 *)dst = pack8888 (dest0, dest1); + + dst += 2; + w -= 2; + } + + CHECKPOINT (); + + if (w) + { + __m64 vdest = load8888 (dst); + + store8888 (dst, over (vdest, expand_alpha (vdest), vsrc)); + } + } + + _mm_empty (); +} + +#define BSHIFT ((1 << BILINEAR_INTERPOLATION_BITS)) +#define BMSK (BSHIFT - 1) + +#define BILINEAR_DECLARE_VARIABLES \ + const __m64 mm_wt = _mm_set_pi16 (wt, wt, wt, wt); \ + const __m64 mm_wb = _mm_set_pi16 (wb, wb, wb, wb); \ + const __m64 mm_BSHIFT = _mm_set_pi16 (BSHIFT, BSHIFT, BSHIFT, BSHIFT); \ + const __m64 mm_addc7 = _mm_set_pi16 (0, 1, 0, 1); \ + const __m64 mm_xorc7 = _mm_set_pi16 (0, BMSK, 0, BMSK); \ + const __m64 mm_ux = _mm_set_pi16 (unit_x, unit_x, unit_x, unit_x); \ + const __m64 mm_zero = _mm_setzero_si64 (); \ + __m64 mm_x = _mm_set_pi16 (vx, vx, vx, vx) + +#define BILINEAR_INTERPOLATE_ONE_PIXEL(pix) \ +do { \ + /* fetch 2x2 pixel block into 2 mmx registers */ \ + __m64 t = ldq_u ((__m64 *)&src_top [pixman_fixed_to_int (vx)]); \ + __m64 b = ldq_u ((__m64 *)&src_bottom [pixman_fixed_to_int (vx)]); \ + vx += unit_x; \ + /* vertical interpolation */ \ + __m64 t_hi = _mm_mullo_pi16 (_mm_unpackhi_pi8 (t, mm_zero), mm_wt); \ + __m64 t_lo = _mm_mullo_pi16 (_mm_unpacklo_pi8 (t, mm_zero), mm_wt); \ + __m64 b_hi = _mm_mullo_pi16 (_mm_unpackhi_pi8 (b, mm_zero), mm_wb); \ + __m64 b_lo = _mm_mullo_pi16 (_mm_unpacklo_pi8 (b, mm_zero), mm_wb); \ + __m64 hi = _mm_add_pi16 (t_hi, b_hi); \ + __m64 lo = _mm_add_pi16 (t_lo, b_lo); \ + if (BILINEAR_INTERPOLATION_BITS < 8) \ + { \ + /* calculate horizontal weights */ \ + __m64 mm_wh = _mm_add_pi16 (mm_addc7, _mm_xor_si64 (mm_xorc7, \ + _mm_srli_pi16 (mm_x, \ + 16 - BILINEAR_INTERPOLATION_BITS))); \ + mm_x = _mm_add_pi16 (mm_x, mm_ux); \ + /* horizontal interpolation */ \ + __m64 p = _mm_unpacklo_pi16 (lo, hi); \ + __m64 q = _mm_unpackhi_pi16 (lo, hi); \ + lo = _mm_madd_pi16 (p, mm_wh); \ + hi = _mm_madd_pi16 (q, mm_wh); \ + } \ + else \ + { \ + /* calculate horizontal weights */ \ + __m64 mm_wh_lo = _mm_sub_pi16 (mm_BSHIFT, _mm_srli_pi16 (mm_x, \ + 16 - BILINEAR_INTERPOLATION_BITS)); \ + __m64 mm_wh_hi = _mm_srli_pi16 (mm_x, \ + 16 - BILINEAR_INTERPOLATION_BITS); \ + mm_x = _mm_add_pi16 (mm_x, mm_ux); \ + /* horizontal interpolation */ \ + __m64 mm_lo_lo = _mm_mullo_pi16 (lo, mm_wh_lo); \ + __m64 mm_lo_hi = _mm_mullo_pi16 (hi, mm_wh_hi); \ + __m64 mm_hi_lo = _mm_mulhi_pu16 (lo, mm_wh_lo); \ + __m64 mm_hi_hi = _mm_mulhi_pu16 (hi, mm_wh_hi); \ + lo = _mm_add_pi32 (_mm_unpacklo_pi16 (mm_lo_lo, mm_hi_lo), \ + _mm_unpacklo_pi16 (mm_lo_hi, mm_hi_hi)); \ + hi = _mm_add_pi32 (_mm_unpackhi_pi16 (mm_lo_lo, mm_hi_lo), \ + _mm_unpackhi_pi16 (mm_lo_hi, mm_hi_hi)); \ + } \ + /* shift and pack the result */ \ + hi = _mm_srli_pi32 (hi, BILINEAR_INTERPOLATION_BITS * 2); \ + lo = _mm_srli_pi32 (lo, BILINEAR_INTERPOLATION_BITS * 2); \ + lo = _mm_packs_pi32 (lo, hi); \ + lo = _mm_packs_pu16 (lo, lo); \ + pix = lo; \ +} while (0) + +#define BILINEAR_SKIP_ONE_PIXEL() \ +do { \ + vx += unit_x; \ + mm_x = _mm_add_pi16 (mm_x, mm_ux); \ +} while(0) + +static force_inline void +scaled_bilinear_scanline_mmx_8888_8888_SRC (uint32_t * dst, + const uint32_t * mask, + const uint32_t * src_top, + const uint32_t * src_bottom, + int32_t w, + int wt, + int wb, + pixman_fixed_t vx, + pixman_fixed_t unit_x, + pixman_fixed_t max_vx, + pixman_bool_t zero_src) +{ + BILINEAR_DECLARE_VARIABLES; + __m64 pix; + + while (w--) + { + BILINEAR_INTERPOLATE_ONE_PIXEL (pix); + store (dst, pix); + dst++; + } + + _mm_empty (); +} + +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_cover_SRC, + scaled_bilinear_scanline_mmx_8888_8888_SRC, + uint32_t, uint32_t, uint32_t, + COVER, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_pad_SRC, + scaled_bilinear_scanline_mmx_8888_8888_SRC, + uint32_t, uint32_t, uint32_t, + PAD, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_none_SRC, + scaled_bilinear_scanline_mmx_8888_8888_SRC, + uint32_t, uint32_t, uint32_t, + NONE, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_normal_SRC, + scaled_bilinear_scanline_mmx_8888_8888_SRC, + uint32_t, uint32_t, uint32_t, + NORMAL, FLAG_NONE) + +static force_inline void +scaled_bilinear_scanline_mmx_8888_8888_OVER (uint32_t * dst, + const uint32_t * mask, + const uint32_t * src_top, + const uint32_t * src_bottom, + int32_t w, + int wt, + int wb, + pixman_fixed_t vx, + pixman_fixed_t unit_x, + pixman_fixed_t max_vx, + pixman_bool_t zero_src) +{ + BILINEAR_DECLARE_VARIABLES; + __m64 pix1, pix2; + + while (w) + { + BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); + + if (!is_zero (pix1)) + { + pix2 = load (dst); + store8888 (dst, core_combine_over_u_pixel_mmx (pix1, pix2)); + } + + w--; + dst++; + } + + _mm_empty (); +} + +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_cover_OVER, + scaled_bilinear_scanline_mmx_8888_8888_OVER, + uint32_t, uint32_t, uint32_t, + COVER, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_pad_OVER, + scaled_bilinear_scanline_mmx_8888_8888_OVER, + uint32_t, uint32_t, uint32_t, + PAD, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_none_OVER, + scaled_bilinear_scanline_mmx_8888_8888_OVER, + uint32_t, uint32_t, uint32_t, + NONE, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_normal_OVER, + scaled_bilinear_scanline_mmx_8888_8888_OVER, + uint32_t, uint32_t, uint32_t, + NORMAL, FLAG_NONE) + +static force_inline void +scaled_bilinear_scanline_mmx_8888_8_8888_OVER (uint32_t * dst, + const uint8_t * mask, + const uint32_t * src_top, + const uint32_t * src_bottom, + int32_t w, + int wt, + int wb, + pixman_fixed_t vx, + pixman_fixed_t unit_x, + pixman_fixed_t max_vx, + pixman_bool_t zero_src) +{ + BILINEAR_DECLARE_VARIABLES; + __m64 pix1, pix2; + uint32_t m; + + while (w) + { + m = (uint32_t) *mask++; + + if (m) + { + BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); + + if (m == 0xff && is_opaque (pix1)) + { + store (dst, pix1); + } + else + { + __m64 ms, md, ma, msa; + + pix2 = load (dst); + ma = expand_alpha_rev (to_m64 (m)); + ms = _mm_unpacklo_pi8 (pix1, _mm_setzero_si64 ()); + md = _mm_unpacklo_pi8 (pix2, _mm_setzero_si64 ()); + + msa = expand_alpha (ms); + + store8888 (dst, (in_over (ms, msa, ma, md))); + } + } + else + { + BILINEAR_SKIP_ONE_PIXEL (); + } + + w--; + dst++; + } + + _mm_empty (); +} + +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_cover_OVER, + scaled_bilinear_scanline_mmx_8888_8_8888_OVER, + uint32_t, uint8_t, uint32_t, + COVER, FLAG_HAVE_NON_SOLID_MASK) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_pad_OVER, + scaled_bilinear_scanline_mmx_8888_8_8888_OVER, + uint32_t, uint8_t, uint32_t, + PAD, FLAG_HAVE_NON_SOLID_MASK) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_none_OVER, + scaled_bilinear_scanline_mmx_8888_8_8888_OVER, + uint32_t, uint8_t, uint32_t, + NONE, FLAG_HAVE_NON_SOLID_MASK) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_normal_OVER, + scaled_bilinear_scanline_mmx_8888_8_8888_OVER, + uint32_t, uint8_t, uint32_t, + NORMAL, FLAG_HAVE_NON_SOLID_MASK) + +static uint32_t * +mmx_fetch_x8r8g8b8 (pixman_iter_t *iter, const uint32_t *mask) +{ + int w = iter->width; + uint32_t *dst = iter->buffer; + uint32_t *src = (uint32_t *)iter->bits; + + iter->bits += iter->stride; + + while (w && ((unsigned long)dst) & 7) + { + *dst++ = (*src++) | 0xff000000; + w--; + } + + while (w >= 8) + { + __m64 vsrc1 = ldq_u ((__m64 *)(src + 0)); + __m64 vsrc2 = ldq_u ((__m64 *)(src + 2)); + __m64 vsrc3 = ldq_u ((__m64 *)(src + 4)); + __m64 vsrc4 = ldq_u ((__m64 *)(src + 6)); + + *(__m64 *)(dst + 0) = _mm_or_si64 (vsrc1, MC (ff000000)); + *(__m64 *)(dst + 2) = _mm_or_si64 (vsrc2, MC (ff000000)); + *(__m64 *)(dst + 4) = _mm_or_si64 (vsrc3, MC (ff000000)); + *(__m64 *)(dst + 6) = _mm_or_si64 (vsrc4, MC (ff000000)); + + dst += 8; + src += 8; + w -= 8; + } + + while (w) + { + *dst++ = (*src++) | 0xff000000; + w--; + } + + _mm_empty (); + return iter->buffer; +} + +static uint32_t * +mmx_fetch_r5g6b5 (pixman_iter_t *iter, const uint32_t *mask) +{ + int w = iter->width; + uint32_t *dst = iter->buffer; + uint16_t *src = (uint16_t *)iter->bits; + + iter->bits += iter->stride; + + while (w && ((unsigned long)dst) & 0x0f) + { + uint16_t s = *src++; + + *dst++ = CONVERT_0565_TO_8888 (s); + w--; + } + + while (w >= 4) + { + __m64 vsrc = ldq_u ((__m64 *)src); + __m64 mm0, mm1; + + expand_4xpacked565 (vsrc, &mm0, &mm1, 1); + + *(__m64 *)(dst + 0) = mm0; + *(__m64 *)(dst + 2) = mm1; + + dst += 4; + src += 4; + w -= 4; + } + + while (w) + { + uint16_t s = *src++; + + *dst++ = CONVERT_0565_TO_8888 (s); + w--; + } + + _mm_empty (); + return iter->buffer; +} + +static uint32_t * +mmx_fetch_a8 (pixman_iter_t *iter, const uint32_t *mask) +{ + int w = iter->width; + uint32_t *dst = iter->buffer; + uint8_t *src = iter->bits; + + iter->bits += iter->stride; + + while (w && (((unsigned long)dst) & 15)) + { + *dst++ = *(src++) << 24; + w--; + } + + while (w >= 8) + { + __m64 mm0 = ldq_u ((__m64 *)src); + + __m64 mm1 = _mm_unpacklo_pi8 (_mm_setzero_si64(), mm0); + __m64 mm2 = _mm_unpackhi_pi8 (_mm_setzero_si64(), mm0); + __m64 mm3 = _mm_unpacklo_pi16 (_mm_setzero_si64(), mm1); + __m64 mm4 = _mm_unpackhi_pi16 (_mm_setzero_si64(), mm1); + __m64 mm5 = _mm_unpacklo_pi16 (_mm_setzero_si64(), mm2); + __m64 mm6 = _mm_unpackhi_pi16 (_mm_setzero_si64(), mm2); + + *(__m64 *)(dst + 0) = mm3; + *(__m64 *)(dst + 2) = mm4; + *(__m64 *)(dst + 4) = mm5; + *(__m64 *)(dst + 6) = mm6; + + dst += 8; + src += 8; + w -= 8; + } + + while (w) + { + *dst++ = *(src++) << 24; + w--; + } + + _mm_empty (); + return iter->buffer; +} + +typedef struct +{ + pixman_format_code_t format; + pixman_iter_get_scanline_t get_scanline; +} fetcher_info_t; + +static const fetcher_info_t fetchers[] = +{ + { PIXMAN_x8r8g8b8, mmx_fetch_x8r8g8b8 }, + { PIXMAN_r5g6b5, mmx_fetch_r5g6b5 }, + { PIXMAN_a8, mmx_fetch_a8 }, + { PIXMAN_null } +}; + +static void +mmx_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) +{ + pixman_image_t *image = iter->image; + +#define FLAGS \ + (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM | \ + FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST) + + if ((iter->iter_flags & ITER_NARROW) && + (iter->image_flags & FLAGS) == FLAGS) + { + const fetcher_info_t *f; + + for (f = &fetchers[0]; f->format != PIXMAN_null; f++) + { + if (image->common.extended_format_code == f->format) + { + uint8_t *b = (uint8_t *)image->bits.bits; + int s = image->bits.rowstride * 4; + + iter->bits = b + s * iter->y + iter->x * PIXMAN_FORMAT_BPP (f->format) / 8; + iter->stride = s; + + iter->get_scanline = f->get_scanline; + return; + } + } + } + + imp->delegate->src_iter_init (imp->delegate, iter); +} + static const pixman_fast_path_t mmx_fast_paths[] = { PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, mmx_composite_over_n_8_0565 ), @@ -3155,11 +3991,20 @@ static const pixman_fast_path_t mmx_fast_paths[] = PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, mmx_composite_over_8888_8888 ), PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, mmx_composite_over_8888_0565 ), + PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, mmx_composite_over_reverse_n_8888), + PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, mmx_composite_over_reverse_n_8888), + + PIXMAN_STD_FAST_PATH (ADD, r5g6b5, null, r5g6b5, mmx_composite_add_0565_0565 ), + PIXMAN_STD_FAST_PATH (ADD, b5g6r5, null, b5g6r5, mmx_composite_add_0565_0565 ), PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, mmx_composite_add_8888_8888 ), PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, mmx_composite_add_8888_8888 ), PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, mmx_composite_add_8_8 ), PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, mmx_composite_add_n_8_8 ), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, mmx_composite_src_x888_0565 ), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, mmx_composite_src_x888_0565 ), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, mmx_composite_src_x888_0565 ), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, mmx_composite_src_x888_0565 ), PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, mmx_composite_src_n_8_8888 ), PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, mmx_composite_src_n_8_8888 ), PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, mmx_composite_src_n_8_8888 ), @@ -3176,6 +4021,23 @@ static const pixman_fast_path_t mmx_fast_paths[] = PIXMAN_STD_FAST_PATH (IN, a8, null, a8, mmx_composite_in_8_8 ), PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, mmx_composite_in_n_8_8 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, mmx_8888_8888 ), + + SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mmx_8888_8888 ), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mmx_8888_8_8888 ), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mmx_8888_8_8888 ), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mmx_8888_8_8888 ), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mmx_8888_8_8888 ), + { PIXMAN_OP_NONE }, }; @@ -3260,7 +4122,9 @@ _pixman_implementation_create_mmx (pixman_implementation_t *fallback) imp->blt = mmx_blt; imp->fill = mmx_fill; + imp->src_iter_init = mmx_src_iter_init; + return imp; } -#endif /* USE_X86_MMX || USE_ARM_IWMMXT */ +#endif /* USE_X86_MMX || USE_ARM_IWMMXT || USE_LOONGSON_MMI */ diff --git a/gfx/cairo/libpixman/src/pixman-noop.c b/gfx/cairo/libpixman/src/pixman-noop.c index d835de64f3a..7b017e8ecc8 100644 --- a/gfx/cairo/libpixman/src/pixman-noop.c +++ b/gfx/cairo/libpixman/src/pixman-noop.c @@ -71,18 +71,18 @@ noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) { iter->get_scanline = get_scanline_null; } - else if ((iter->flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == + else if ((iter->iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) { iter->get_scanline = _pixman_iter_get_scanline_noop; } else if (image->common.extended_format_code == PIXMAN_solid && - ((image->common.flags & (FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP)) == + ((iter->image_flags & (FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP)) == (FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP))) { bits_image_t *bits = &image->bits; - if (iter->flags & ITER_NARROW) + if (iter->iter_flags & ITER_NARROW) { uint32_t color = bits->fetch_pixel_32 (bits, 0, 0); uint32_t *buffer = iter->buffer; @@ -104,8 +104,8 @@ noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) iter->get_scanline = _pixman_iter_get_scanline_noop; } else if (image->common.extended_format_code == PIXMAN_a8r8g8b8 && - (iter->flags & ITER_NARROW) && - (image->common.flags & FLAGS) == FLAGS && + (iter->iter_flags & ITER_NARROW) && + (iter->image_flags & FLAGS) == FLAGS && iter->x >= 0 && iter->y >= 0 && iter->x + iter->width <= image->bits.width && iter->y + iter->height <= image->bits.height) @@ -125,8 +125,8 @@ static void noop_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) { pixman_image_t *image = iter->image; - uint32_t image_flags = image->common.flags; - uint32_t iter_flags = iter->flags; + uint32_t image_flags = iter->image_flags; + uint32_t iter_flags = iter->iter_flags; if ((image_flags & FAST_PATH_STD_DEST_FLAGS) == FAST_PATH_STD_DEST_FLAGS && (iter_flags & ITER_NARROW) == ITER_NARROW && diff --git a/gfx/cairo/libpixman/src/pixman-ppc.c b/gfx/cairo/libpixman/src/pixman-ppc.c new file mode 100644 index 00000000000..f1bea1eacf0 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-ppc.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2000 SuSE, Inc. + * Copyright © 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" + +#ifdef USE_VMX + +/* The CPU detection code needs to be in a file not compiled with + * "-maltivec -mabi=altivec", as gcc would try to save vector register + * across function calls causing SIGILL on cpus without Altivec/vmx. + */ +#ifdef __APPLE__ +#include + +static pixman_bool_t +pixman_have_vmx (void) +{ + size_t length = sizeof(have_vmx); + int error, have_mmx; + + sysctlbyname ("hw.optional.altivec", &have_vmx, &length, NULL, 0); + + if (error) + return FALSE; + + return have_vmx; +} + +#elif defined (__OpenBSD__) +#include +#include +#include + +static pixman_bool_t +pixman_have_vmx (void) +{ + int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC }; + size_t length = sizeof(have_vmx); + int error, have_vmx; + + error = sysctl (mib, 2, &have_vmx, &length, NULL, 0); + + if (error != 0) + return FALSE; + + return have_vmx; +} + +#elif defined (__linux__) + +#include +#include +#include +#include +#include +#include +#include + +static pixman_bool_t +pixman_have_vmx (void) +{ + int have_vmx = FALSE; + int fd; + struct + { + unsigned long type; + unsigned long value; + } aux; + + fd = open ("/proc/self/auxv", O_RDONLY); + if (fd >= 0) + { + while (read (fd, &aux, sizeof (aux)) == sizeof (aux)) + { + if (aux.type == AT_HWCAP && (aux.value & PPC_FEATURE_HAS_ALTIVEC)) + { + have_vmx = TRUE; + break; + } + } + + close (fd); + } + + return have_vmx; +} + +#else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */ +#include +#include + +static jmp_buf jump_env; + +static void +vmx_test (int sig, + siginfo_t *si, + void * unused) +{ + longjmp (jump_env, 1); +} + +static pixman_bool_t +pixman_have_vmx (void) +{ + struct sigaction sa, osa; + int jmp_result; + + sa.sa_flags = SA_SIGINFO; + sigemptyset (&sa.sa_mask); + sa.sa_sigaction = vmx_test; + sigaction (SIGILL, &sa, &osa); + jmp_result = setjmp (jump_env); + if (jmp_result == 0) + { + asm volatile ( "vor 0, 0, 0" ); + } + sigaction (SIGILL, &osa, NULL); + return (jmp_result == 0); +} + +#endif /* __APPLE__ */ +#endif /* USE_VMX */ + +pixman_implementation_t * +_pixman_ppc_get_implementations (pixman_implementation_t *imp) +{ +#ifdef USE_VMX + if (!_pixman_disabled ("vmx") && pixman_have_vmx ()) + imp = _pixman_implementation_create_vmx (imp); +#endif + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman-private.h b/gfx/cairo/libpixman/src/pixman-private.h index 4a273c9aca3..4de6261bb40 100644 --- a/gfx/cairo/libpixman/src/pixman-private.h +++ b/gfx/cairo/libpixman/src/pixman-private.h @@ -1,10 +1,33 @@ +#ifndef PIXMAN_PRIVATE_H +#define PIXMAN_PRIVATE_H + +/* + * The defines which are shared between C and assembly code + */ + +/* bilinear interpolation precision (must be <= 8) */ +#ifndef MOZILLA_VERSION +#error "Need mozilla headers" +#endif +#ifdef MOZ_GFX_OPTIMIZE_MOBILE +#define LOW_QUALITY_INTERPOLATION +#define LOWER_QUALITY_INTERPOLATION +#define BILINEAR_INTERPOLATION_BITS 4 +#else +#define BILINEAR_INTERPOLATION_BITS 8 +#endif +#define BILINEAR_INTERPOLATION_RANGE (1 << BILINEAR_INTERPOLATION_BITS) + +/* + * C specific part + */ + +#ifndef __ASSEMBLER__ + #ifndef PACKAGE # error config.h must be included before pixman-private.h #endif -#ifndef PIXMAN_PRIVATE_H -#define PIXMAN_PRIVATE_H - #define PIXMAN_DISABLE_DEPRECATED #define PIXMAN_USE_INTERNAL_API @@ -13,6 +36,7 @@ #include #include #include +#include #include "pixman-compiler.h" @@ -154,9 +178,6 @@ struct bits_image uint32_t * free_me; int rowstride; /* in number of uint32_t's */ - fetch_scanline_t get_scanline_32; - fetch_scanline_t get_scanline_64; - fetch_scanline_t fetch_scanline_16; fetch_scanline_t fetch_scanline_32; @@ -229,13 +250,15 @@ struct pixman_iter_t int x, y; int width; int height; - iter_flags_t flags; + iter_flags_t iter_flags; + uint32_t image_flags; /* These function pointers are initialized by the implementation */ pixman_iter_get_scanline_t get_scanline; pixman_iter_write_back_t write_back; /* These fields are scratch data that implementations can use */ + void * data; uint8_t * bits; int stride; }; @@ -530,7 +553,8 @@ _pixman_implementation_src_iter_init (pixman_implementation_t *imp, int width, int height, uint8_t *buffer, - iter_flags_t flags); + iter_flags_t flags, + uint32_t image_flags); void _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, @@ -541,7 +565,8 @@ _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, int width, int height, uint8_t *buffer, - iter_flags_t flags); + iter_flags_t flags, + uint32_t image_flags); /* Specific implementations */ pixman_implementation_t * @@ -553,7 +578,7 @@ _pixman_implementation_create_fast_path (pixman_implementation_t *fallback); pixman_implementation_t * _pixman_implementation_create_noop (pixman_implementation_t *fallback); -#if defined USE_X86_MMX || defined USE_ARM_IWMMXT +#if defined USE_X86_MMX || defined USE_ARM_IWMMXT || defined USE_LOONGSON_MMI pixman_implementation_t * _pixman_implementation_create_mmx (pixman_implementation_t *fallback); #endif @@ -583,14 +608,44 @@ pixman_implementation_t * _pixman_implementation_create_vmx (pixman_implementation_t *fallback); #endif +pixman_bool_t +_pixman_implementation_disabled (const char *name); + +pixman_implementation_t * +_pixman_x86_get_implementations (pixman_implementation_t *imp); + +pixman_implementation_t * +_pixman_arm_get_implementations (pixman_implementation_t *imp); + +pixman_implementation_t * +_pixman_ppc_get_implementations (pixman_implementation_t *imp); + +pixman_implementation_t * +_pixman_mips_get_implementations (pixman_implementation_t *imp); + pixman_implementation_t * _pixman_choose_implementation (void); +pixman_bool_t +_pixman_disabled (const char *name); /* * Utilities */ +pixman_bool_t +_pixman_compute_composite_region32 (pixman_region32_t * region, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dest_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height); uint32_t * _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask); @@ -699,6 +754,18 @@ _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask); dest, FAST_PATH_STD_DEST_FLAGS, \ func) } +extern pixman_implementation_t *global_implementation; + +static force_inline pixman_implementation_t * +get_implementation (void) +{ +#ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR + if (!global_implementation) + global_implementation = _pixman_choose_implementation (); +#endif + return global_implementation; +} + /* Memory allocation helpers */ void * pixman_malloc_ab (unsigned int n, unsigned int b); @@ -748,6 +815,50 @@ pixman_bool_t pixman_region16_copy_from_region32 (pixman_region16_t *dst, pixman_region32_t *src); +/* Doubly linked lists */ +typedef struct pixman_link_t pixman_link_t; +struct pixman_link_t +{ + pixman_link_t *next; + pixman_link_t *prev; +}; + +typedef struct pixman_list_t pixman_list_t; +struct pixman_list_t +{ + pixman_link_t *head; + pixman_link_t *tail; +}; + +static force_inline void +pixman_list_init (pixman_list_t *list) +{ + list->head = (pixman_link_t *)list; + list->tail = (pixman_link_t *)list; +} + +static force_inline void +pixman_list_prepend (pixman_list_t *list, pixman_link_t *link) +{ + link->next = list->head; + link->prev = (pixman_link_t *)list; + list->head->prev = link; + list->head = link; +} + +static force_inline void +pixman_list_unlink (pixman_link_t *link) +{ + link->prev->next = link->next; + link->next->prev = link->prev; +} + +static force_inline void +pixman_list_move_to_front (pixman_list_t *list, pixman_link_t *link) +{ + pixman_list_unlink (link); + pixman_list_prepend (list, link); +} /* Misc macros */ @@ -800,7 +911,8 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst, (PIXMAN_FORMAT_A (f) > 8 || \ PIXMAN_FORMAT_R (f) > 8 || \ PIXMAN_FORMAT_G (f) > 8 || \ - PIXMAN_FORMAT_B (f) > 8) + PIXMAN_FORMAT_B (f) > 8 || \ + PIXMAN_FORMAT_TYPE (f) == PIXMAN_TYPE_ARGB_SRGB) #ifdef WORDS_BIGENDIAN # define SCREEN_SHIFT_LEFT(x,n) ((x) << (n)) @@ -996,4 +1108,18 @@ void pixman_timer_register (pixman_timer_t *timer); #endif /* PIXMAN_TIMERS */ +/* sRGB<->linear conversion tables. Linear color space is the same + * as sRGB but the components are in linear light (gamma 1.0). + * + * linear_to_srgb maps linear value from 0 to 4095 ([0.0, 1.0]) + * and returns 8-bit sRGB value. + * + * srgb_to_linear maps 8-bit sRGB value to 16-bit linear value + * with range 0 to 65535 ([0.0, 1.0]). + */ +extern const uint8_t linear_to_srgb[4096]; +extern const uint16_t srgb_to_linear[256]; + +#endif /* __ASSEMBLER__ */ + #endif /* PIXMAN_PRIVATE_H */ diff --git a/gfx/cairo/libpixman/src/pixman-radial-gradient.c b/gfx/cairo/libpixman/src/pixman-radial-gradient.c index d31aa14d29f..9f43a53e805 100644 --- a/gfx/cairo/libpixman/src/pixman-radial-gradient.c +++ b/gfx/cairo/libpixman/src/pixman-radial-gradient.c @@ -671,9 +671,9 @@ radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) void _pixman_radial_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) { - if (iter->flags & ITER_16) + if (iter->iter_flags & ITER_16) iter->get_scanline = radial_get_scanline_16; - else if (iter->flags & ITER_NARROW) + else if (iter->iter_flags & ITER_NARROW) iter->get_scanline = radial_get_scanline_narrow; else iter->get_scanline = radial_get_scanline_wide; diff --git a/gfx/cairo/libpixman/src/pixman-region.c b/gfx/cairo/libpixman/src/pixman-region.c index 70c282d4091..4626f9cc68e 100644 --- a/gfx/cairo/libpixman/src/pixman-region.c +++ b/gfx/cairo/libpixman/src/pixman-region.c @@ -2041,10 +2041,10 @@ PREFIX (_subtract) (region_type_t *reg_d, * *----------------------------------------------------------------------- */ -pixman_bool_t -PIXMAN_EXPORT PREFIX (_inverse) (region_type_t *new_reg, /* Destination region */ - region_type_t *reg1, /* Region to invert */ - box_type_t * inv_rect) /* Bounding box for inversion */ +PIXMAN_EXPORT pixman_bool_t +PREFIX (_inverse) (region_type_t *new_reg, /* Destination region */ + region_type_t *reg1, /* Region to invert */ + box_type_t * inv_rect) /* Bounding box for inversion */ { region_type_t inv_reg; /* Quick and dirty region made from the * bounding box */ @@ -2137,9 +2137,9 @@ find_box_for_y (box_type_t *begin, box_type_t *end, int y) * partially in the region) or is outside the region (we reached a band * that doesn't overlap the box at all and part_in is false) */ -pixman_region_overlap_t -PIXMAN_EXPORT PREFIX (_contains_rectangle) (region_type_t * region, - box_type_t * prect) +PIXMAN_EXPORT pixman_region_overlap_t +PREFIX (_contains_rectangle) (region_type_t * region, + box_type_t * prect) { box_type_t * pbox; box_type_t * pbox_end; diff --git a/gfx/cairo/libpixman/src/pixman-solid-fill.c b/gfx/cairo/libpixman/src/pixman-solid-fill.c index 852e13568b5..8b25d5d08bc 100644 --- a/gfx/cairo/libpixman/src/pixman-solid-fill.c +++ b/gfx/cairo/libpixman/src/pixman-solid-fill.c @@ -29,7 +29,7 @@ void _pixman_solid_fill_iter_init (pixman_image_t *image, pixman_iter_t *iter) { - if (iter->flags & ITER_NARROW) + if (iter->iter_flags & ITER_NARROW) { uint32_t *b = (uint32_t *)iter->buffer; uint32_t *e = b + iter->width; diff --git a/gfx/cairo/libpixman/src/pixman-srgb.c b/gfx/cairo/libpixman/src/pixman-srgb.c new file mode 100644 index 00000000000..abe5cdb9793 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-srgb.c @@ -0,0 +1,455 @@ +/* WARNING: This file is generated by make-srgb.pl. + * Please edit that file instead of this one. + */ + +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" + +const uint8_t linear_to_srgb[4096] = +{ + 0, 1, 2, 2, 3, 4, 5, 6, 6, 7, + 8, 9, 10, 10, 11, 12, 13, 13, 14, 15, + 15, 16, 16, 17, 18, 18, 19, 19, 20, 20, + 21, 21, 22, 22, 23, 23, 23, 24, 24, 25, + 25, 25, 26, 26, 27, 27, 27, 28, 28, 29, + 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, + 32, 33, 33, 33, 34, 34, 34, 34, 35, 35, + 35, 36, 36, 36, 37, 37, 37, 37, 38, 38, + 38, 38, 39, 39, 39, 40, 40, 40, 40, 41, + 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, + 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, + 46, 46, 46, 46, 46, 47, 47, 47, 47, 48, + 48, 48, 48, 48, 49, 49, 49, 49, 49, 50, + 50, 50, 50, 50, 51, 51, 51, 51, 51, 52, + 52, 52, 52, 52, 53, 53, 53, 53, 53, 54, + 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, + 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, + 57, 58, 58, 58, 58, 58, 58, 59, 59, 59, + 59, 59, 59, 60, 60, 60, 60, 60, 60, 61, + 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, + 62, 63, 63, 63, 63, 63, 63, 64, 64, 64, + 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, + 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, + 67, 67, 67, 67, 68, 68, 68, 68, 68, 68, + 68, 69, 69, 69, 69, 69, 69, 69, 70, 70, + 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, + 71, 71, 72, 72, 72, 72, 72, 72, 72, 72, + 73, 73, 73, 73, 73, 73, 73, 74, 74, 74, + 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, + 75, 75, 75, 76, 76, 76, 76, 76, 76, 76, + 77, 77, 77, 77, 77, 77, 77, 77, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, + 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, + 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 82, 82, 82, 82, 82, 82, 82, 82, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 103, 103, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 111, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, + 113, 113, 113, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 175, 175, 175, 175, 175, + 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, + 175, 175, 175, 175, 175, 175, 175, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 179, 179, 179, 179, 179, + 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, + 179, 179, 179, 179, 179, 179, 179, 179, 180, 180, + 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, + 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, + 180, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 181, 181, 181, 181, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 183, 183, + 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 183, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 186, + 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 186, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 188, 188, + 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, + 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, + 188, 188, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 189, 189, 189, 189, 189, 189, 190, 190, 190, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 195, 195, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 195, 195, 195, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, + 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, + 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, + 198, 198, 198, 198, 198, 198, 199, 199, 199, 199, + 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, + 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, + 199, 199, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 201, + 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, + 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, + 201, 201, 201, 201, 201, 201, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 211, 211, 211, 211, 211, 211, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, + 211, 211, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 217, 217, 217, + 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, + 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, + 217, 217, 217, 217, 217, 217, 217, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 223, 223, 223, + 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, + 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, + 223, 223, 223, 223, 223, 223, 223, 223, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 226, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 227, 227, 228, 228, 228, 228, 228, 228, 228, 228, + 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, + 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, + 228, 228, 228, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 237, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, 239, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 241, 241, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, + 244, 244, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 249, 249, 249, 249, 249, 249, 249, 249, + 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, + 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, + 249, 249, 249, 249, 249, 249, 249, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 251, 251, 251, 251, 251, 251, 251, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 252, + 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, + 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, + 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, + 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, + 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, +}; + +const uint16_t srgb_to_linear[256] = +{ + 0, 20, 40, 64, 80, 99, 119, 144, 160, 179, + 199, 224, 241, 264, 288, 313, 340, 368, 396, 427, + 458, 491, 526, 562, 599, 637, 677, 718, 761, 805, + 851, 898, 947, 997, 1048, 1101, 1156, 1212, 1270, 1330, + 1391, 1453, 1517, 1583, 1651, 1720, 1790, 1863, 1937, 2013, + 2090, 2170, 2250, 2333, 2418, 2504, 2592, 2681, 2773, 2866, + 2961, 3058, 3157, 3258, 3360, 3464, 3570, 3678, 3788, 3900, + 4014, 4129, 4247, 4366, 4488, 4611, 4736, 4864, 4993, 5124, + 5257, 5392, 5530, 5669, 5810, 5953, 6099, 6246, 6395, 6547, + 6700, 6856, 7014, 7174, 7335, 7500, 7666, 7834, 8004, 8177, + 8352, 8528, 8708, 8889, 9072, 9258, 9445, 9635, 9828, 10022, + 10219, 10417, 10619, 10822, 11028, 11235, 11446, 11658, 11873, 12090, + 12309, 12530, 12754, 12980, 13209, 13440, 13673, 13909, 14146, 14387, + 14629, 14874, 15122, 15371, 15623, 15878, 16135, 16394, 16656, 16920, + 17187, 17456, 17727, 18001, 18277, 18556, 18837, 19121, 19407, 19696, + 19987, 20281, 20577, 20876, 21177, 21481, 21787, 22096, 22407, 22721, + 23038, 23357, 23678, 24002, 24329, 24658, 24990, 25325, 25662, 26001, + 26344, 26688, 27036, 27386, 27739, 28094, 28452, 28813, 29176, 29542, + 29911, 30282, 30656, 31033, 31412, 31794, 32179, 32567, 32957, 33350, + 33745, 34143, 34544, 34948, 35355, 35764, 36176, 36591, 37008, 37429, + 37852, 38278, 38706, 39138, 39572, 40009, 40449, 40891, 41337, 41785, + 42236, 42690, 43147, 43606, 44069, 44534, 45002, 45473, 45947, 46423, + 46903, 47385, 47871, 48359, 48850, 49344, 49841, 50341, 50844, 51349, + 51858, 52369, 52884, 53401, 53921, 54445, 54971, 55500, 56032, 56567, + 57105, 57646, 58190, 58737, 59287, 59840, 60396, 60955, 61517, 62082, + 62650, 63221, 63795, 64372, 64952, 65535, +}; diff --git a/gfx/cairo/libpixman/src/pixman-sse2.c b/gfx/cairo/libpixman/src/pixman-sse2.c index cafa5897889..636a74e431f 100644 --- a/gfx/cairo/libpixman/src/pixman-sse2.c +++ b/gfx/cairo/libpixman/src/pixman-sse2.c @@ -53,6 +53,9 @@ static __m128i mask_blue; static __m128i mask_565_fix_rb; static __m128i mask_565_fix_g; +static __m128i mask_565_rb; +static __m128i mask_565_pack_multiplier; + static force_inline __m128i unpack_32_1x128 (uint32_t data) { @@ -121,6 +124,29 @@ pack_2x128_128 (__m128i lo, __m128i hi) } static force_inline __m128i +pack_565_2packedx128_128 (__m128i lo, __m128i hi) +{ + __m128i rb0 = _mm_and_si128 (lo, mask_565_rb); + __m128i rb1 = _mm_and_si128 (hi, mask_565_rb); + + __m128i t0 = _mm_madd_epi16 (rb0, mask_565_pack_multiplier); + __m128i t1 = _mm_madd_epi16 (rb1, mask_565_pack_multiplier); + + __m128i g0 = _mm_and_si128 (lo, mask_green); + __m128i g1 = _mm_and_si128 (hi, mask_green); + + t0 = _mm_or_si128 (t0, g0); + t1 = _mm_or_si128 (t1, g1); + + /* Simulates _mm_packus_epi32 */ + t0 = _mm_slli_epi32 (t0, 16 - 5); + t1 = _mm_slli_epi32 (t1, 16 - 5); + t0 = _mm_srai_epi32 (t0, 16); + t1 = _mm_srai_epi32 (t1, 16); + return _mm_packs_epi32 (t0, t1); +} + +__m128i pack_565_2x128_128 (__m128i lo, __m128i hi) { __m128i data; @@ -2831,6 +2857,57 @@ sse2_composite_over_8888_n_8888 (pixman_implementation_t *imp, } +static void +sse2_composite_src_x888_0565 (pixman_implementation_t *imp, + pixman_composite_info_t *info) +{ + PIXMAN_COMPOSITE_ARGS (info); + uint16_t *dst_line, *dst; + uint32_t *src_line, *src, s; + int dst_stride, src_stride; + int32_t w; + + PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); + + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + src = src_line; + src_line += src_stride; + w = width; + + while (w && (unsigned long)dst & 15) + { + s = *src++; + *dst = CONVERT_8888_TO_0565 (s); + dst++; + w--; + } + + while (w >= 8) + { + __m128i xmm_src0 = load_128_unaligned ((__m128i *)src + 0); + __m128i xmm_src1 = load_128_unaligned ((__m128i *)src + 1); + + save_128_aligned ((__m128i*)dst, pack_565_2packedx128_128 (xmm_src0, xmm_src1)); + + w -= 8; + src += 8; + dst += 8; + } + + while (w) + { + s = *src++; + *dst = CONVERT_8888_TO_0565 (s); + dst++; + w--; + } + } +} + static void sse2_composite_src_x888_8888 (pixman_implementation_t *imp, pixman_composite_info_t *info) @@ -5317,11 +5394,15 @@ FAST_NEAREST_MAINLOOP_COMMON (sse2_8888_n_8888_normal_OVER, scaled_nearest_scanline_sse2_8888_n_8888_OVER, uint32_t, uint32_t, uint32_t, NORMAL, TRUE, TRUE) +#define BMSK ((1 << BILINEAR_INTERPOLATION_BITS) - 1) + #define BILINEAR_DECLARE_VARIABLES \ const __m128i xmm_wt = _mm_set_epi16 (wt, wt, wt, wt, wt, wt, wt, wt); \ const __m128i xmm_wb = _mm_set_epi16 (wb, wb, wb, wb, wb, wb, wb, wb); \ - const __m128i xmm_xorc = _mm_set_epi16 (0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff);\ - const __m128i xmm_addc = _mm_set_epi16 (0, 0, 0, 0, 1, 1, 1, 1); \ + const __m128i xmm_xorc8 = _mm_set_epi16 (0, 0, 0, 0, BMSK, BMSK, BMSK, BMSK);\ + const __m128i xmm_addc8 = _mm_set_epi16 (0, 0, 0, 0, 1, 1, 1, 1); \ + const __m128i xmm_xorc7 = _mm_set_epi16 (0, BMSK, 0, BMSK, 0, BMSK, 0, BMSK);\ + const __m128i xmm_addc7 = _mm_set_epi16 (0, 1, 0, 1, 0, 1, 0, 1); \ const __m128i xmm_ux = _mm_set_epi16 (unit_x, unit_x, unit_x, unit_x, \ unit_x, unit_x, unit_x, unit_x); \ const __m128i xmm_zero = _mm_setzero_si128 (); \ @@ -5330,30 +5411,41 @@ FAST_NEAREST_MAINLOOP_COMMON (sse2_8888_n_8888_normal_OVER, #define BILINEAR_INTERPOLATE_ONE_PIXEL(pix) \ do { \ __m128i xmm_wh, xmm_lo, xmm_hi, a; \ - /* fetch 2x2 pixel block into sse2 register */ \ - uint32_t tl = src_top [pixman_fixed_to_int (vx)]; \ - uint32_t tr = src_top [pixman_fixed_to_int (vx) + 1]; \ - uint32_t bl = src_bottom [pixman_fixed_to_int (vx)]; \ - uint32_t br = src_bottom [pixman_fixed_to_int (vx) + 1]; \ - a = _mm_set_epi32 (tr, tl, br, bl); \ + /* fetch 2x2 pixel block into sse2 registers */ \ + __m128i tltr = _mm_loadl_epi64 ( \ + (__m128i *)&src_top[pixman_fixed_to_int (vx)]); \ + __m128i blbr = _mm_loadl_epi64 ( \ + (__m128i *)&src_bottom[pixman_fixed_to_int (vx)]); \ vx += unit_x; \ /* vertical interpolation */ \ - a = _mm_add_epi16 (_mm_mullo_epi16 (_mm_unpackhi_epi8 (a, xmm_zero), \ + a = _mm_add_epi16 (_mm_mullo_epi16 (_mm_unpacklo_epi8 (tltr, xmm_zero), \ xmm_wt), \ - _mm_mullo_epi16 (_mm_unpacklo_epi8 (a, xmm_zero), \ + _mm_mullo_epi16 (_mm_unpacklo_epi8 (blbr, xmm_zero), \ xmm_wb)); \ - /* calculate horizontal weights */ \ - xmm_wh = _mm_add_epi16 (xmm_addc, \ - _mm_xor_si128 (xmm_xorc, \ - _mm_srli_epi16 (xmm_x, 8))); \ - xmm_x = _mm_add_epi16 (xmm_x, xmm_ux); \ - /* horizontal interpolation */ \ - xmm_lo = _mm_mullo_epi16 (a, xmm_wh); \ - xmm_hi = _mm_mulhi_epu16 (a, xmm_wh); \ - a = _mm_add_epi32 (_mm_unpacklo_epi16 (xmm_lo, xmm_hi), \ - _mm_unpackhi_epi16 (xmm_lo, xmm_hi)); \ + if (BILINEAR_INTERPOLATION_BITS < 8) \ + { \ + /* calculate horizontal weights */ \ + xmm_wh = _mm_add_epi16 (xmm_addc7, _mm_xor_si128 (xmm_xorc7, \ + _mm_srli_epi16 (xmm_x, 16 - BILINEAR_INTERPOLATION_BITS))); \ + xmm_x = _mm_add_epi16 (xmm_x, xmm_ux); \ + /* horizontal interpolation */ \ + a = _mm_madd_epi16 (_mm_unpackhi_epi16 (_mm_shuffle_epi32 ( \ + a, _MM_SHUFFLE (1, 0, 3, 2)), a), xmm_wh); \ + } \ + else \ + { \ + /* calculate horizontal weights */ \ + xmm_wh = _mm_add_epi16 (xmm_addc8, _mm_xor_si128 (xmm_xorc8, \ + _mm_srli_epi16 (xmm_x, 16 - BILINEAR_INTERPOLATION_BITS))); \ + xmm_x = _mm_add_epi16 (xmm_x, xmm_ux); \ + /* horizontal interpolation */ \ + xmm_lo = _mm_mullo_epi16 (a, xmm_wh); \ + xmm_hi = _mm_mulhi_epu16 (a, xmm_wh); \ + a = _mm_add_epi32 (_mm_unpacklo_epi16 (xmm_lo, xmm_hi), \ + _mm_unpackhi_epi16 (xmm_lo, xmm_hi)); \ + } \ /* shift and pack the result */ \ - a = _mm_srli_epi32 (a, 16); \ + a = _mm_srli_epi32 (a, BILINEAR_INTERPOLATION_BITS * 2); \ a = _mm_packs_epi32 (a, a); \ a = _mm_packus_epi16 (a, a); \ pix = _mm_cvtsi128_si32 (a); \ @@ -5735,6 +5827,7 @@ static const pixman_fast_path_t sse2_fast_paths[] = PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, sse2_composite_over_n_8888), PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, sse2_composite_over_n_8888), PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, sse2_composite_over_n_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, null, b5g6r5, sse2_composite_over_n_0565), PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, sse2_composite_over_8888_8888), PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, sse2_composite_over_8888_8888), PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, sse2_composite_over_8888_8888), @@ -5794,6 +5887,10 @@ static const pixman_fast_path_t sse2_fast_paths[] = PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, sse2_composite_src_n_8_8888), PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, sse2_composite_src_n_8_8888), PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8b8g8r8, sse2_composite_src_n_8_8888), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, sse2_composite_src_x888_0565), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, sse2_composite_src_x888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, sse2_composite_src_x888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, sse2_composite_src_x888_0565), PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, sse2_composite_src_x888_8888), PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, sse2_composite_src_x888_8888), PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, sse2_composite_copy_area), @@ -5839,6 +5936,9 @@ static const pixman_fast_path_t sse2_fast_paths[] = SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, sse2_8888_8888), SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, sse2_8888_8888), SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, sse2_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, sse2_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, sse2_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, sse2_8888_8888), SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_8888), SIMPLE_BILINEAR_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_8888), @@ -6056,19 +6156,13 @@ static void sse2_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) { pixman_image_t *image = iter->image; - int x = iter->x; - int y = iter->y; - int width = iter->width; - int height = iter->height; #define FLAGS \ - (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM | FAST_PATH_BITS_IMAGE) + (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM | \ + FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST) - if ((iter->flags & ITER_NARROW) && - (image->common.flags & FLAGS) == FLAGS && - x >= 0 && y >= 0 && - x + width <= image->bits.width && - y + height <= image->bits.height) + if ((iter->iter_flags & ITER_NARROW) && + (iter->image_flags & FLAGS) == FLAGS) { const fetcher_info_t *f; @@ -6079,7 +6173,7 @@ sse2_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) uint8_t *b = (uint8_t *)image->bits.bits; int s = image->bits.rowstride * 4; - iter->bits = b + s * iter->y + x * PIXMAN_FORMAT_BPP (f->format) / 8; + iter->bits = b + s * iter->y + iter->x * PIXMAN_FORMAT_BPP (f->format) / 8; iter->stride = s; iter->get_scanline = f->get_scanline; @@ -6115,6 +6209,8 @@ _pixman_implementation_create_sse2 (pixman_implementation_t *fallback) mask_ffff = create_mask_16_128 (0xffff); mask_ff000000 = create_mask_2x32_128 (0xff000000, 0xff000000); mask_alpha = create_mask_2x32_128 (0x00ff0000, 0x00000000); + mask_565_rb = create_mask_2x32_128 (0x00f800f8, 0x00f800f8); + mask_565_pack_multiplier = create_mask_2x32_128 (0x20000004, 0x20000004); /* Set up function pointers */ imp->combine_32[PIXMAN_OP_OVER] = sse2_combine_over_u; diff --git a/gfx/cairo/libpixman/src/pixman-utils.c b/gfx/cairo/libpixman/src/pixman-utils.c index de05c0e5203..83c011dfa6b 100644 --- a/gfx/cairo/libpixman/src/pixman-utils.c +++ b/gfx/cairo/libpixman/src/pixman-utils.c @@ -184,6 +184,22 @@ pixman_malloc_abc (unsigned int a, return malloc (a * b * c); } +static void +unorm_to_unorm_params (int in_width, int out_width, uint32_t *factor, int *shift) +{ + int w = 0; + + *factor = 0; + while (in_width != 0 && w < out_width) + { + *factor |= 1 << w; + w += in_width; + } + + /* Did we generate too many bits? */ + *shift = w - out_width; +} + /* * This function expands images from ARGB8 format to ARGB16. To preserve * precision, it needs to know the original source format. For example, if the @@ -213,8 +229,15 @@ pixman_expand (uint64_t * dst, r_mask = ~(~0 << r_size), g_mask = ~(~0 << g_size), b_mask = ~(~0 << b_size); + uint32_t au_factor, ru_factor, gu_factor, bu_factor; + int au_shift, ru_shift, gu_shift, bu_shift; int i; + unorm_to_unorm_params (a_size, 16, &au_factor, &au_shift); + unorm_to_unorm_params (r_size, 16, &ru_factor, &ru_shift); + unorm_to_unorm_params (g_size, 16, &gu_factor, &gu_shift); + unorm_to_unorm_params (b_size, 16, &bu_factor, &bu_shift); + /* Start at the end so that we can do the expansion in place * when src == dst */ @@ -227,7 +250,7 @@ pixman_expand (uint64_t * dst, if (a_size) { a = (pixel >> a_shift) & a_mask; - a16 = unorm_to_unorm (a, a_size, 16); + a16 = a * au_factor >> au_shift; } else { @@ -239,9 +262,9 @@ pixman_expand (uint64_t * dst, r = (pixel >> r_shift) & r_mask; g = (pixel >> g_shift) & g_mask; b = (pixel >> b_shift) & b_mask; - r16 = unorm_to_unorm (r, r_size, 16); - g16 = unorm_to_unorm (g, g_size, 16); - b16 = unorm_to_unorm (b, b_size, 16); + r16 = r * ru_factor >> ru_shift; + g16 = g * gu_factor >> gu_shift; + b16 = b * bu_factor >> bu_shift; } else { diff --git a/gfx/cairo/libpixman/src/pixman-version.h b/gfx/cairo/libpixman/src/pixman-version.h index c0f45a849aa..fac4225b076 100644 --- a/gfx/cairo/libpixman/src/pixman-version.h +++ b/gfx/cairo/libpixman/src/pixman-version.h @@ -32,10 +32,10 @@ #endif #define PIXMAN_VERSION_MAJOR 0 -#define PIXMAN_VERSION_MINOR 21 -#define PIXMAN_VERSION_MICRO 7 +#define PIXMAN_VERSION_MINOR 27 +#define PIXMAN_VERSION_MICRO 1 -#define PIXMAN_VERSION_STRING "0.21.7" +#define PIXMAN_VERSION_STRING "0.27.1" #define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \ ((major) * 10000) \ diff --git a/gfx/cairo/libpixman/src/pixman-vmx.c b/gfx/cairo/libpixman/src/pixman-vmx.c index 32dff3f390e..6868704a875 100644 --- a/gfx/cairo/libpixman/src/pixman-vmx.c +++ b/gfx/cairo/libpixman/src/pixman-vmx.c @@ -25,10 +25,7 @@ * Based on fbmmx.c by Owen Taylor, Søren Sandmann and Nicholas Miell */ -#ifdef HAVE_CONFIG_H #include -#endif - #include "pixman-private.h" #include "pixman-combine32.h" #include diff --git a/gfx/cairo/libpixman/src/pixman-x86.c b/gfx/cairo/libpixman/src/pixman-x86.c new file mode 100644 index 00000000000..57e4d1f351b --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-x86.c @@ -0,0 +1,237 @@ +/* + * Copyright © 2000 SuSE, Inc. + * Copyright © 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" + +#if defined(USE_X86_MMX) || defined (USE_SSE2) + +/* The CPU detection code needs to be in a file not compiled with + * "-mmmx -msse", as gcc would generate CMOV instructions otherwise + * that would lead to SIGILL instructions on old CPUs that don't have + * it. + */ + +typedef enum +{ + X86_MMX = (1 << 0), + X86_MMX_EXTENSIONS = (1 << 1), + X86_SSE = (1 << 2) | X86_MMX_EXTENSIONS, + X86_SSE2 = (1 << 3), + X86_CMOV = (1 << 4) +} cpu_features_t; + +#ifdef HAVE_GETISAX + +#include + +static cpu_features_t +detect_cpu_features (void) +{ + cpu_features_t features = 0; + unsigned int result = 0; + + if (getisax (&result, 1)) + { + if (result & AV_386_CMOV) + features |= X86_CMOV; + if (result & AV_386_MMX) + features |= X86_MMX; + if (result & AV_386_AMD_MMX) + features |= X86_MMX_EXTENSIONS; + if (result & AV_386_SSE) + features |= X86_SSE; + if (result & AV_386_SSE2) + features |= X86_SSE2; + } + + return features; +} + +#else + +#define _PIXMAN_X86_64 \ + (defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)) + +static pixman_bool_t +have_cpuid (void) +{ +#if _PIXMAN_X86_64 || defined (_MSC_VER) + + return TRUE; + +#elif defined (__GNUC__) + uint32_t result; + + __asm__ volatile ( + "pushf" "\n\t" + "pop %%eax" "\n\t" + "mov %%eax, %%ecx" "\n\t" + "xor $0x00200000, %%eax" "\n\t" + "push %%eax" "\n\t" + "popf" "\n\t" + "pushf" "\n\t" + "pop %%eax" "\n\t" + "xor %%ecx, %%eax" "\n\t" + "mov %%eax, %0" "\n\t" + : "=r" (result) + : + : "%eax", "%ecx"); + + return !!result; + +#else +#error "Unknown compiler" +#endif +} + +static void +pixman_cpuid (uint32_t feature, + uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) +{ +#if defined (__GNUC__) + +#if _PIXMAN_X86_64 + __asm__ volatile ( + "cpuid" "\n\t" + : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d) + : "a" (feature)); +#else + /* On x86-32 we need to be careful about the handling of %ebx + * and %esp. We can't declare either one as clobbered + * since they are special registers (%ebx is the "PIC + * register" holding an offset to global data, %esp the + * stack pointer), so we need to make sure that %ebx is + * preserved, and that %esp has its original value when + * accessing the output operands. + */ + __asm__ volatile ( + "xchg %%ebx, %1" "\n\t" + "cpuid" "\n\t" + "xchg %%ebx, %1" "\n\t" + : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d) + : "a" (feature)); +#endif + +#elif defined (_MSC_VER) + int info[4]; + + __cpuid (info, feature); + + *a = info[0]; + *b = info[1]; + *c = info[2]; + *d = info[3]; +#else +#error Unknown compiler +#endif +} + +static cpu_features_t +detect_cpu_features (void) +{ + uint32_t a, b, c, d; + cpu_features_t features = 0; + + if (!have_cpuid()) + return features; + + /* Get feature bits */ + pixman_cpuid (0x01, &a, &b, &c, &d); + if (d & (1 << 15)) + features |= X86_CMOV; + if (d & (1 << 23)) + features |= X86_MMX; + if (d & (1 << 25)) + features |= X86_SSE; + if (d & (1 << 26)) + features |= X86_SSE2; + + /* Check for AMD specific features */ + if ((features & X86_MMX) && !(features & X86_SSE)) + { + char vendor[13]; + + /* Get vendor string */ + memset (vendor, 0, sizeof vendor); + + pixman_cpuid (0x00, &a, &b, &c, &d); + memcpy (vendor + 0, &b, 4); + memcpy (vendor + 4, &d, 4); + memcpy (vendor + 8, &c, 4); + + if (strcmp (vendor, "AuthenticAMD") == 0 || + strcmp (vendor, "Geode by NSC") == 0) + { + pixman_cpuid (0x80000000, &a, &b, &c, &d); + if (a >= 0x80000001) + { + pixman_cpuid (0x80000001, &a, &b, &c, &d); + + if (d & (1 << 22)) + features |= X86_MMX_EXTENSIONS; + } + } + } + + return features; +} + +#endif + +static pixman_bool_t +have_feature (cpu_features_t feature) +{ + static pixman_bool_t initialized; + static cpu_features_t features; + + if (!initialized) + { + features = detect_cpu_features(); + initialized = TRUE; + } + + return (features & feature) == feature; +} + +#endif + +pixman_implementation_t * +_pixman_x86_get_implementations (pixman_implementation_t *imp) +{ +#define MMX_BITS (X86_MMX | X86_MMX_EXTENSIONS) +#define SSE2_BITS (X86_MMX | X86_MMX_EXTENSIONS | X86_SSE | X86_SSE2) + +#ifdef USE_X86_MMX + if (!_pixman_disabled ("mmx") && have_feature (MMX_BITS)) + imp = _pixman_implementation_create_mmx (imp); +#endif + +#ifdef USE_SSE2 + if (!_pixman_disabled ("sse2") && have_feature (SSE2_BITS)) + imp = _pixman_implementation_create_sse2 (imp); +#endif + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman.c b/gfx/cairo/libpixman/src/pixman.c index 8fb53568fbe..994ef388c7c 100644 --- a/gfx/cairo/libpixman/src/pixman.c +++ b/gfx/cairo/libpixman/src/pixman.c @@ -30,7 +30,7 @@ #include -static pixman_implementation_t *global_implementation; +pixman_implementation_t *global_implementation; #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR static void __attribute__((constructor)) @@ -40,16 +40,6 @@ pixman_constructor (void) } #endif -static force_inline pixman_implementation_t * -get_implementation (void) -{ -#ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR - if (!global_implementation) - global_implementation = _pixman_choose_implementation (); -#endif - return global_implementation; -} - typedef struct operator_info_t operator_info_t; struct operator_info_t @@ -234,19 +224,19 @@ clip_source_image (pixman_region32_t * region, * returns FALSE if the final region is empty. Indistinguishable from * an allocation failure, but rendering ignores those anyways. */ -static pixman_bool_t -pixman_compute_composite_region32 (pixman_region32_t * region, - pixman_image_t * src_image, - pixman_image_t * mask_image, - pixman_image_t * dest_image, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) +pixman_bool_t +_pixman_compute_composite_region32 (pixman_region32_t * region, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dest_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) { region->extents.x1 = dest_x; region->extents.x2 = dest_x + width; @@ -625,7 +615,7 @@ pixman_image_composite32 (pixman_op_t op, pixman_region32_init (®ion); - if (!pixman_compute_composite_region32 ( + if (!_pixman_compute_composite_region32 ( ®ion, src, mask, dest, src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height)) { @@ -1027,6 +1017,7 @@ pixman_format_supported_source (pixman_format_code_t format) case PIXMAN_a2r10g10b10: case PIXMAN_x2r10g10b10: case PIXMAN_a8r8g8b8: + case PIXMAN_a8r8g8b8_sRGB: case PIXMAN_x8r8g8b8: case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: @@ -1124,7 +1115,7 @@ pixman_compute_composite_region (pixman_region16_t * region, pixman_region32_init (&r32); - retval = pixman_compute_composite_region32 ( + retval = _pixman_compute_composite_region32 ( &r32, src_image, mask_image, dest_image, src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height); diff --git a/gfx/cairo/libpixman/src/pixman.h b/gfx/cairo/libpixman/src/pixman.h index 0c6ce62383e..bfb056d31e8 100644 --- a/gfx/cairo/libpixman/src/pixman.h +++ b/gfx/cairo/libpixman/src/pixman.h @@ -655,6 +655,7 @@ struct pixman_indexed #define PIXMAN_TYPE_YV12 7 #define PIXMAN_TYPE_BGRA 8 #define PIXMAN_TYPE_RGBA 9 +#define PIXMAN_TYPE_ARGB_SRGB 10 #define PIXMAN_FORMAT_COLOR(f) \ (PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ARGB || \ @@ -678,6 +679,9 @@ typedef enum { PIXMAN_x2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,10,10,10), PIXMAN_a2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,2,10,10,10), +/* sRGB formats */ + PIXMAN_a8r8g8b8_sRGB = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB_SRGB,8,8,8,8), + /* 24bpp formats */ PIXMAN_r8g8b8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8), PIXMAN_b8g8r8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ABGR,0,8,8,8), @@ -869,6 +873,65 @@ void pixman_image_composite32 (pixman_op_t op, */ void pixman_disable_out_of_bounds_workaround (void); +/* + * Glyphs + */ +typedef struct pixman_glyph_cache_t pixman_glyph_cache_t; +typedef struct +{ + int x, y; + const void *glyph; +} pixman_glyph_t; + +pixman_glyph_cache_t *pixman_glyph_cache_create (void); +void pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache); +void pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache); +void pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache); +const void * pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key); +const void * pixman_glyph_cache_insert (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key, + int origin_x, + int origin_y, + pixman_image_t *glyph_image); +void pixman_glyph_cache_remove (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key); +void pixman_glyph_get_extents (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs, + pixman_box32_t *extents); +pixman_format_code_t pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t * glyphs); +void pixman_composite_glyphs (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + pixman_format_code_t mask_format, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs); +void pixman_composite_glyphs_no_mask (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + int32_t src_x, + int32_t src_y, + int32_t dest_x, + int32_t dest_y, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs); + /* * Trapezoids */ diff --git a/gfx/layers/ImageContainer.h b/gfx/layers/ImageContainer.h index 40575a8553a..d7b92a8f5b6 100644 --- a/gfx/layers/ImageContainer.h +++ b/gfx/layers/ImageContainer.h @@ -443,15 +443,6 @@ public: return mPaintCount; } - /** - * Resets the paint count to zero. - * Can be called from any thread. - */ - void ResetPaintCount() { - ReentrantMonitorAutoEnter mon(mReentrantMonitor); - mPaintCount = 0; - } - /** * Increments mPaintCount if this is the first time aPainted has been * painted, and sets mPaintTime if the painted image is the current image. diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 1c0d2f520e6..b4a464fb9ac 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -260,13 +260,6 @@ LayerManager::GetScrollableLayers(nsTArray& aArray) } } -bool ThebesLayer::UseTiledThebes() -{ - static bool useTiledThebesLayer = - Preferences::GetBool("gfx.use_tiled_thebes", false); - return useTiledThebesLayer; -} - already_AddRefed LayerManager::CreateOptimalSurface(const gfxIntSize &aSize, gfxASurface::gfxImageFormat aFormat) diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 2644f9b0c90..a346b4f6a05 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -1286,8 +1286,6 @@ public: */ gfxPoint GetResidualTranslation() const { return mResidualTranslation; } - static bool UseTiledThebes(); - protected: ThebesLayer(LayerManager* aManager, void* aImplData) : Layer(aManager, aImplData) diff --git a/gfx/layers/TiledLayerBuffer.h b/gfx/layers/TiledLayerBuffer.h index 0c9001a91a1..70f9f3c559e 100644 --- a/gfx/layers/TiledLayerBuffer.h +++ b/gfx/layers/TiledLayerBuffer.h @@ -8,6 +8,11 @@ #define TILEDLAYERBUFFER_TILE_SIZE 256 // Debug defines +#ifdef MOZ_ANDROID_OMTC + // This needs to go away as we enabled tiled + // layers everywhere. + #define FORCE_BASICTILEDTHEBESLAYER +#endif //#define GFX_TILEDLAYER_DEBUG_OVERLAY //#define GFX_TILEDLAYER_PREF_WARNINGS diff --git a/gfx/layers/basic/BasicLayerManager.cpp b/gfx/layers/basic/BasicLayerManager.cpp index 6ec2d76c51e..a984708371c 100644 --- a/gfx/layers/basic/BasicLayerManager.cpp +++ b/gfx/layers/basic/BasicLayerManager.cpp @@ -1341,8 +1341,8 @@ already_AddRefed BasicShadowLayerManager::CreateThebesLayer() { NS_ASSERTION(InConstruction(), "Only allowed in construction phase"); - if (HasShadowManager() && GetParentBackendType() == LAYERS_OPENGL && - ThebesLayer::UseTiledThebes()) { +#ifdef FORCE_BASICTILEDTHEBESLAYER + if (HasShadowManager() && GetParentBackendType() == LAYERS_OPENGL) { // BasicTiledThebesLayer doesn't support main // thread compositing so only return this layer // type if we have a shadow manager. @@ -1351,6 +1351,7 @@ BasicShadowLayerManager::CreateThebesLayer() MAYBE_CREATE_SHADOW(Thebes); return layer.forget(); } else +#endif { nsRefPtr layer = new BasicShadowableThebesLayer(this); diff --git a/gfx/layers/opengl/LayerManagerOGL.cpp b/gfx/layers/opengl/LayerManagerOGL.cpp index 920babe9a42..2e96692f674 100644 --- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ b/gfx/layers/opengl/LayerManagerOGL.cpp @@ -1554,9 +1554,11 @@ LayerManagerOGL::CreateShadowThebesLayer() NS_WARNING("Call on destroyed layer manager"); return nullptr; } - if (ThebesLayer::UseTiledThebes()) - return nsRefPtr(new TiledThebesLayerOGL(this)).forget(); +#ifdef FORCE_BASICTILEDTHEBESLAYER + return nsRefPtr(new TiledThebesLayerOGL(this)).forget(); +#else return nsRefPtr(new ShadowThebesLayerOGL(this)).forget(); +#endif } already_AddRefed diff --git a/gfx/layers/opengl/ThebesLayerOGL.cpp b/gfx/layers/opengl/ThebesLayerOGL.cpp index ee339f9084a..432ada089aa 100644 --- a/gfx/layers/opengl/ThebesLayerOGL.cpp +++ b/gfx/layers/opengl/ThebesLayerOGL.cpp @@ -1027,8 +1027,9 @@ ShadowThebesLayerOGL::ShadowThebesLayerOGL(LayerManagerOGL *aManager) : ShadowThebesLayer(aManager, nullptr) , LayerOGL(aManager) { - if (ThebesLayer::UseTiledThebes()) - NS_ABORT(); +#ifdef FORCE_BASICTILEDTHEBESLAYER + NS_ABORT(); +#endif mImplData = static_cast(this); } diff --git a/js/src/ion/CodeGenerator.cpp b/js/src/ion/CodeGenerator.cpp index d77f26d0baf..31d6d44027c 100644 --- a/js/src/ion/CodeGenerator.cpp +++ b/js/src/ion/CodeGenerator.cpp @@ -735,6 +735,26 @@ CodeGenerator::visitElements(LElements *lir) return true; } +typedef bool (*ConvertElementsToDoublesFn)(JSContext *, uintptr_t); +static const VMFunction ConvertElementsToDoublesInfo = + FunctionInfo(ObjectElements::ConvertElementsToDoubles); + +bool +CodeGenerator::visitConvertElementsToDoubles(LConvertElementsToDoubles *lir) +{ + Register elements = ToRegister(lir->elements()); + + OutOfLineCode *ool = oolCallVM(ConvertElementsToDoublesInfo, lir, + (ArgList(), elements), StoreNothing()); + if (!ool) + return false; + + Address convertedAddress(elements, ObjectElements::offsetOfConvertDoubleElements()); + masm.branch32(Assembler::Equal, convertedAddress, Imm32(0), ool->entry()); + masm.bind(ool->rejoin()); + return true; +} + bool CodeGenerator::visitFunctionEnvironment(LFunctionEnvironment *lir) { diff --git a/js/src/ion/CodeGenerator.h b/js/src/ion/CodeGenerator.h index 8b4fb60c4c8..42bc16e86a6 100644 --- a/js/src/ion/CodeGenerator.h +++ b/js/src/ion/CodeGenerator.h @@ -76,6 +76,7 @@ class CodeGenerator : public CodeGeneratorSpecific bool visitSlots(LSlots *lir); bool visitStoreSlotV(LStoreSlotV *store); bool visitElements(LElements *lir); + bool visitConvertElementsToDoubles(LConvertElementsToDoubles *lir); bool visitTypeBarrier(LTypeBarrier *lir); bool visitMonitorTypes(LMonitorTypes *lir); bool visitCallNative(LCallNative *call); diff --git a/js/src/ion/Ion.h b/js/src/ion/Ion.h index 9a4299c7562..9ad6fb658b7 100644 --- a/js/src/ion/Ion.h +++ b/js/src/ion/Ion.h @@ -112,6 +112,16 @@ struct IonOptions // Default: 3 uint32_t maxInlineDepth; + // The maximum inlining depth for functions. + // + // Inlining small functions has almost no compiling overhead + // and removes the otherwise needed call overhead. + // The value is currently very low. + // Actually it is only needed to make sure we don't blow out the stack. + // + // Default: 10 + uint32_t smallFunctionMaxInlineDepth; + // The bytecode length limit for small function. // // The default for this was arrived at empirically via benchmarking. @@ -191,6 +201,7 @@ struct IonOptions usesBeforeInlining(usesBeforeCompile), maxStackArgs(4096), maxInlineDepth(3), + smallFunctionMaxInlineDepth(10), smallFunctionMaxBytecodeLength(100), smallFunctionUsesBeforeInlining(usesBeforeInlining / 4), polyInlineMax(4), diff --git a/js/src/ion/IonAnalysis.cpp b/js/src/ion/IonAnalysis.cpp index f894b964c02..2b7917606af 100644 --- a/js/src/ion/IonAnalysis.cpp +++ b/js/src/ion/IonAnalysis.cpp @@ -1361,6 +1361,11 @@ ion::EliminateRedundantChecks(MIRGraph &graph) } else if (iter->isTypeBarrier()) { if (!TryEliminateTypeBarrier(iter->toTypeBarrier(), &eliminated)) return false; + } else if (iter->isConvertElementsToDoubles()) { + // Now that code motion passes have finished, replace any + // ConvertElementsToDoubles with the actual elements. + MConvertElementsToDoubles *ins = iter->toConvertElementsToDoubles(); + ins->replaceAllUsesWith(ins->elements()); } if (eliminated) diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index 966d046272a..0c402607328 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -3097,9 +3097,6 @@ IonBuilder::makeInliningDecision(AutoObjectVector &targets, uint32_t argc) { AssertCanGC(); - if (inliningDepth >= js_IonOptions.maxInlineDepth) - return false; - // For "small" functions, we should be more aggressive about inlining. // This is based on the following intuition: // 1. The call overhead for a small function will likely be a much @@ -3115,6 +3112,7 @@ IonBuilder::makeInliningDecision(AutoObjectVector &targets, uint32_t argc) uint32_t totalSize = 0; uint32_t checkUses = js_IonOptions.usesBeforeInlining; + uint32_t maxInlineDepth = js_IonOptions.maxInlineDepth; bool allFunctionsAreSmall = true; RootedFunction target(cx); RootedScript targetScript(cx); @@ -3138,8 +3136,13 @@ IonBuilder::makeInliningDecision(AutoObjectVector &targets, uint32_t argc) return false; } } - if (allFunctionsAreSmall) + if (allFunctionsAreSmall) { checkUses = js_IonOptions.smallFunctionUsesBeforeInlining; + maxInlineDepth = js_IonOptions.smallFunctionMaxInlineDepth; + } + + if (inliningDepth >= maxInlineDepth) + return false; if (script()->getUseCount() < checkUses) { IonSpew(IonSpew_Inlining, "Not inlining, caller is not hot"); @@ -4373,6 +4376,9 @@ IonBuilder::jsop_newarray(uint32_t count) if (!templateObject) return false; + if (oracle->arrayResultShouldHaveDoubleConversion(script(), pc)) + templateObject->setShouldConvertDoubleElements(); + MNewArray *ins = new MNewArray(count, templateObject, MNewArray::NewArray_Allocating); current->add(ins); @@ -4431,6 +4437,12 @@ IonBuilder::jsop_initelem_array() MElements *elements = MElements::New(obj); current->add(elements); + if (obj->toNewArray()->templateObject()->shouldConvertDoubleElements()) { + MInstruction *valueDouble = MToDouble::New(value); + current->add(valueDouble); + value = valueDouble; + } + // Store the value. MStoreElement *store = MStoreElement::New(elements, id, value, /* needsHoleCheck = */ false); current->add(store); @@ -5413,9 +5425,20 @@ IonBuilder::jsop_getelem_dense() id = idInt32; // Get the elements vector. - MElements *elements = MElements::New(obj); + MInstruction *elements = MElements::New(obj); current->add(elements); + // If we can load the element as a definite double, make sure to check that + // the array has been converted to homogenous doubles first. + bool loadDouble = !barrier && + loopDepth_ && + !readOutOfBounds && + oracle->elementReadShouldAlwaysLoadDoubles(script(), pc); + if (loadDouble) { + JS_ASSERT(!needsHoleCheck && knownType == JSVAL_TYPE_DOUBLE); + elements = addConvertElementsToDoubles(elements); + } + MInitializedLength *initLength = MInitializedLength::New(elements); current->add(initLength); @@ -5428,7 +5451,7 @@ IonBuilder::jsop_getelem_dense() // hoisting. id = addBoundsCheck(id, initLength); - load = MLoadElement::New(elements, id, needsHoleCheck); + load = MLoadElement::New(elements, id, needsHoleCheck, loadDouble); current->add(load); } else { // This load may return undefined, so assume that we *can* read holes, @@ -5638,6 +5661,13 @@ IonBuilder::jsop_setelem_dense() current->add(idInt32); id = idInt32; + // Ensure the value is a double, if double conversion might be needed. + if (oracle->elementWriteNeedsDoubleConversion(script(), pc)) { + MInstruction *valueDouble = MToDouble::New(value); + current->add(valueDouble); + value = valueDouble; + } + // Get the elements vector. MElements *elements = MElements::New(obj); current->add(elements); @@ -6997,6 +7027,14 @@ IonBuilder::jsop_instanceof() return resumeAfter(ins); } +MInstruction * +IonBuilder::addConvertElementsToDoubles(MDefinition *elements) +{ + MInstruction *convert = MConvertElementsToDoubles::New(elements); + current->add(convert); + return convert; +} + MInstruction * IonBuilder::addBoundsCheck(MDefinition *index, MDefinition *length) { diff --git a/js/src/ion/IonBuilder.h b/js/src/ion/IonBuilder.h index 429187937a6..402c7fab280 100644 --- a/js/src/ion/IonBuilder.h +++ b/js/src/ion/IonBuilder.h @@ -284,6 +284,7 @@ class IonBuilder : public MIRGenerator MDefinition *walkScopeChain(unsigned hops); + MInstruction *addConvertElementsToDoubles(MDefinition *elements); MInstruction *addBoundsCheck(MDefinition *index, MDefinition *length); MInstruction *addShapeGuard(MDefinition *obj, const UnrootedShape shape, BailoutKind bailoutKind); diff --git a/js/src/ion/IonMacroAssembler.cpp b/js/src/ion/IonMacroAssembler.cpp index d1bca696c29..e3445cd185f 100644 --- a/js/src/ion/IonMacroAssembler.cpp +++ b/js/src/ion/IonMacroAssembler.cpp @@ -356,6 +356,8 @@ MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject) Address(obj, elementsOffset + ObjectElements::offsetOfInitializedLength())); store32(Imm32(templateObject->getArrayLength()), Address(obj, elementsOffset + ObjectElements::offsetOfLength())); + store32(Imm32(templateObject->shouldConvertDoubleElements() ? 1 : 0), + Address(obj, elementsOffset + ObjectElements::offsetOfConvertDoubleElements())); } else { storePtr(ImmWord(emptyObjectElements), Address(obj, JSObject::offsetOfElements())); diff --git a/js/src/ion/LIR-Common.h b/js/src/ion/LIR-Common.h index 2b7f869f785..cfeb0aadc5b 100644 --- a/js/src/ion/LIR-Common.h +++ b/js/src/ion/LIR-Common.h @@ -2123,6 +2123,21 @@ class LElements : public LInstructionHelper<1, 1, 0> } }; +// If necessary, convert any int32 elements in a vector into doubles. +class LConvertElementsToDoubles : public LInstructionHelper<0, 1, 0> +{ + public: + LIR_HEADER(ConvertElementsToDoubles) + + LConvertElementsToDoubles(const LAllocation &elements) { + setOperand(0, elements); + } + + const LAllocation *elements() { + return getOperand(0); + } +}; + // Load a dense array's initialized length from an elements vector. class LInitializedLength : public LInstructionHelper<1, 1, 0> { diff --git a/js/src/ion/LOpcodes.h b/js/src/ion/LOpcodes.h index 90415095d47..f9b7ef20fa8 100644 --- a/js/src/ion/LOpcodes.h +++ b/js/src/ion/LOpcodes.h @@ -111,6 +111,7 @@ _(ImplicitThis) \ _(Slots) \ _(Elements) \ + _(ConvertElementsToDoubles) \ _(LoadSlotV) \ _(LoadSlotT) \ _(StoreSlotV) \ diff --git a/js/src/ion/Lowering.cpp b/js/src/ion/Lowering.cpp index db721cfc81a..e074848bcb1 100644 --- a/js/src/ion/Lowering.cpp +++ b/js/src/ion/Lowering.cpp @@ -1396,6 +1396,13 @@ LIRGenerator::visitConstantElements(MConstantElements *ins) return define(new LPointer(ins->value(), LPointer::NON_GC_THING), ins); } +bool +LIRGenerator::visitConvertElementsToDoubles(MConvertElementsToDoubles *ins) +{ + LInstruction *check = new LConvertElementsToDoubles(useRegister(ins->elements())); + return add(check, ins) && assignSafepoint(check, ins); +} + bool LIRGenerator::visitLoadSlot(MLoadSlot *ins) { diff --git a/js/src/ion/Lowering.h b/js/src/ion/Lowering.h index 1c3ab7b0a2d..7a1f8c8c1d8 100644 --- a/js/src/ion/Lowering.h +++ b/js/src/ion/Lowering.h @@ -140,6 +140,7 @@ class LIRGenerator : public LIRGeneratorSpecific bool visitSlots(MSlots *ins); bool visitElements(MElements *ins); bool visitConstantElements(MConstantElements *ins); + bool visitConvertElementsToDoubles(MConvertElementsToDoubles *ins); bool visitLoadSlot(MLoadSlot *ins); bool visitFunctionEnvironment(MFunctionEnvironment *ins); bool visitStoreSlot(MStoreSlot *ins); diff --git a/js/src/ion/MCallOptimize.cpp b/js/src/ion/MCallOptimize.cpp index 7509e8ee1bf..1eea0ad8423 100644 --- a/js/src/ion/MCallOptimize.cpp +++ b/js/src/ion/MCallOptimize.cpp @@ -205,6 +205,10 @@ IonBuilder::inlineArray(uint32_t argc, bool constructing) if (!templateObject) return InliningStatus_Error; + bool convertDoubles = oracle->arrayResultShouldHaveDoubleConversion(script(), pc); + if (convertDoubles) + templateObject->setShouldConvertDoubleElements(); + MNewArray *ins = new MNewArray(initLength, templateObject, allocating); current->add(ins); current->push(ins); @@ -222,7 +226,14 @@ IonBuilder::inlineArray(uint32_t argc, bool constructing) id = MConstant::New(Int32Value(i)); current->add(id); - MStoreElement *store = MStoreElement::New(elements, id, argv[i + 1], + MDefinition *value = argv[i + 1]; + if (convertDoubles) { + MInstruction *valueDouble = MToDouble::New(value); + current->add(valueDouble); + value = valueDouble; + } + + MStoreElement *store = MStoreElement::New(elements, id, value, /* needsHoleCheck = */ false); current->add(store); } @@ -313,11 +324,24 @@ IonBuilder::inlineArrayPush(uint32_t argc, bool constructing) if (types::ArrayPrototypeHasIndexedProperty(cx, script)) return InliningStatus_NotInlined; + types::StackTypeSet::DoubleConversion conversion = thisTypes->convertDoubleElements(cx); + if (conversion == types::StackTypeSet::AmbiguousDoubleConversion) + return InliningStatus_NotInlined; + MDefinitionVector argv; if (!discardCall(argc, argv, current)) return InliningStatus_Error; - MArrayPush *ins = MArrayPush::New(argv[0], argv[1]); + MDefinition *value = argv[1]; + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles || + conversion == types::StackTypeSet::MaybeConvertToDoubles) + { + MInstruction *valueDouble = MToDouble::New(value); + current->add(valueDouble); + value = valueDouble; + } + + MArrayPush *ins = MArrayPush::New(argv[0], value); current->add(ins); current->push(ins); diff --git a/js/src/ion/MIR.h b/js/src/ion/MIR.h index 4d95f21e7bd..9d32999d2fe 100644 --- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -196,10 +196,11 @@ class AliasSet { DynamicSlot = 1 << 2, // A member of obj->slots. FixedSlot = 1 << 3, // A member of obj->fixedSlots(). TypedArrayElement = 1 << 4, // A typed array element. - Last = TypedArrayElement, + DOMProperty = 1 << 5, // A DOM property + Last = DOMProperty, Any = Last | (Last - 1), - NumCategories = 5, + NumCategories = 6, // Indicates load or store. Store_ = 1 << 31 @@ -3500,6 +3501,43 @@ class MConstantElements : public MNullaryInstruction } }; +// Passes through an object's elements, after ensuring it is entirely doubles. +class MConvertElementsToDoubles + : public MUnaryInstruction +{ + MConvertElementsToDoubles(MDefinition *elements) + : MUnaryInstruction(elements) + { + setGuard(); + setMovable(); + setResultType(MIRType_Elements); + } + + public: + INSTRUCTION_HEADER(ConvertElementsToDoubles) + + static MConvertElementsToDoubles *New(MDefinition *elements) { + return new MConvertElementsToDoubles(elements); + } + + MDefinition *elements() const { + return getOperand(0); + } + bool congruentTo(MDefinition *const &ins) const { + return congruentIfOperandsEqual(ins); + } + AliasSet getAliasSet() const { + // This instruction can read and write to the elements' contents. + // However, it is alright to hoist this from loops which explicitly + // read or write to the elements: such reads and writes will use double + // values and can be reordered freely wrt this conversion, except that + // definite double loads must follow the conversion. The latter + // property is ensured by chaining this instruction with the elements + // themselves, in the same manner as MBoundsCheck. + return AliasSet::None(); + } +}; + // Load a dense array's initialized length from an elements vector. class MInitializedLength : public MUnaryInstruction @@ -3792,10 +3830,12 @@ class MLoadElement public SingleObjectPolicy { bool needsHoleCheck_; + bool loadDoubles_; - MLoadElement(MDefinition *elements, MDefinition *index, bool needsHoleCheck) + MLoadElement(MDefinition *elements, MDefinition *index, bool needsHoleCheck, bool loadDoubles) : MBinaryInstruction(elements, index), - needsHoleCheck_(needsHoleCheck) + needsHoleCheck_(needsHoleCheck), + loadDoubles_(loadDoubles) { setResultType(MIRType_Value); setMovable(); @@ -3806,8 +3846,9 @@ class MLoadElement public: INSTRUCTION_HEADER(LoadElement) - static MLoadElement *New(MDefinition *elements, MDefinition *index, bool needsHoleCheck) { - return new MLoadElement(elements, index, needsHoleCheck); + static MLoadElement *New(MDefinition *elements, MDefinition *index, + bool needsHoleCheck, bool loadDoubles) { + return new MLoadElement(elements, index, needsHoleCheck, loadDoubles); } TypePolicy *typePolicy() { @@ -3822,6 +3863,9 @@ class MLoadElement bool needsHoleCheck() const { return needsHoleCheck_; } + bool loadDoubles() const { + return loadDoubles_; + } bool fallible() const { return needsHoleCheck(); } @@ -5394,7 +5438,7 @@ class MGetDOMProperty setOperand(1, guard); // We are movable iff the jitinfo says we can be. - if (jitinfo->isConstant) + if (jitinfo->isPure) setMovable(); setResultType(MIRType_Value); @@ -5422,6 +5466,9 @@ class MGetDOMProperty bool isDomConstant() const { return info_->isConstant; } + bool isDomPure() const { + return info_->isPure; + } MDefinition *object() { return getOperand(0); } @@ -5431,7 +5478,7 @@ class MGetDOMProperty } bool congruentTo(MDefinition *const &ins) const { - if (!isDomConstant()) + if (!isDomPure()) return false; if (!ins->isGetDOMProperty()) @@ -5449,6 +5496,10 @@ class MGetDOMProperty // conflict with anything if (isDomConstant()) return AliasSet::None(); + // Pure DOM attributes can only alias things that alias the world or + // explicitly alias DOM properties. + if (isDomPure()) + return AliasSet::Load(AliasSet::DOMProperty); return AliasSet::Store(AliasSet::Any); } diff --git a/js/src/ion/MOpcodes.h b/js/src/ion/MOpcodes.h index 0a476e780ac..aed4e50e966 100644 --- a/js/src/ion/MOpcodes.h +++ b/js/src/ion/MOpcodes.h @@ -88,6 +88,7 @@ namespace ion { _(Slots) \ _(Elements) \ _(ConstantElements) \ + _(ConvertElementsToDoubles) \ _(LoadSlot) \ _(StoreSlot) \ _(FunctionEnvironment) \ diff --git a/js/src/ion/TypeOracle.cpp b/js/src/ion/TypeOracle.cpp index 16309d5c083..811ac450714 100644 --- a/js/src/ion/TypeOracle.cpp +++ b/js/src/ion/TypeOracle.cpp @@ -359,6 +359,14 @@ TypeInferenceOracle::elementReadIsString(UnrootedScript script, jsbytecode *pc) return true; } +bool +TypeInferenceOracle::elementReadShouldAlwaysLoadDoubles(UnrootedScript script, jsbytecode *pc) +{ + StackTypeSet *types = script->analysis()->poppedTypes(pc, 1); + types::StackTypeSet::DoubleConversion conversion = types->convertDoubleElements(cx); + return conversion == StackTypeSet::AlwaysConvertToDoubles; +} + bool TypeInferenceOracle::elementReadHasExtraIndexedProperty(UnrootedScript script, jsbytecode *pc) { @@ -405,7 +413,10 @@ TypeInferenceOracle::elementWriteIsDenseNative(HandleScript script, jsbytecode * return false; Class *clasp = obj->getKnownClass(); - return clasp && clasp->isNative(); + if (!clasp || !clasp->isNative()) + return false; + + return obj->convertDoubleElements(cx) != StackTypeSet::AmbiguousDoubleConversion; } bool @@ -426,6 +437,15 @@ TypeInferenceOracle::elementWriteIsTypedArray(RawScript script, jsbytecode *pc, return true; } +bool +TypeInferenceOracle::elementWriteNeedsDoubleConversion(UnrootedScript script, jsbytecode *pc) +{ + StackTypeSet *types = script->analysis()->poppedTypes(pc, 2); + types::StackTypeSet::DoubleConversion conversion = types->convertDoubleElements(cx); + return conversion == StackTypeSet::AlwaysConvertToDoubles || + conversion == StackTypeSet::MaybeConvertToDoubles; +} + bool TypeInferenceOracle::elementWriteHasExtraIndexedProperty(UnrootedScript script, jsbytecode *pc) { @@ -483,6 +503,14 @@ TypeInferenceOracle::elementWrite(UnrootedScript script, jsbytecode *pc) return elementType; } +bool +TypeInferenceOracle::arrayResultShouldHaveDoubleConversion(UnrootedScript script, jsbytecode *pc) +{ + types::StackTypeSet::DoubleConversion conversion = + script->analysis()->pushedTypes(pc, 0)->convertDoubleElements(cx); + return conversion == types::StackTypeSet::AlwaysConvertToDoubles; +} + bool TypeInferenceOracle::canInlineCalls() { diff --git a/js/src/ion/TypeOracle.h b/js/src/ion/TypeOracle.h index 4e157aea712..4ca647b3025 100644 --- a/js/src/ion/TypeOracle.h +++ b/js/src/ion/TypeOracle.h @@ -90,6 +90,9 @@ class TypeOracle virtual bool elementReadIsString(UnrootedScript script, jsbytecode *pc) { return false; } + virtual bool elementReadShouldAlwaysLoadDoubles(UnrootedScript script, jsbytecode *pc) { + return false; + } virtual bool elementReadHasExtraIndexedProperty(UnrootedScript, jsbytecode *pc) { return false; } @@ -109,12 +112,18 @@ class TypeOracle virtual bool elementWriteIsTypedArray(RawScript script, jsbytecode *pc, int *arrayType) { return false; } + virtual bool elementWriteNeedsDoubleConversion(UnrootedScript script, jsbytecode *pc) { + return false; + } virtual bool elementWriteHasExtraIndexedProperty(UnrootedScript script, jsbytecode *pc) { return false; } virtual bool elementWriteIsPacked(UnrootedScript script, jsbytecode *pc) { return false; } + virtual bool arrayResultShouldHaveDoubleConversion(UnrootedScript script, jsbytecode *pc) { + return false; + } virtual bool propertyWriteCanSpecialize(UnrootedScript script, jsbytecode *pc) { return true; } @@ -237,13 +246,16 @@ class TypeInferenceOracle : public TypeOracle bool elementReadIsDenseNative(RawScript script, jsbytecode *pc); bool elementReadIsTypedArray(HandleScript script, jsbytecode *pc, int *atype); bool elementReadIsString(UnrootedScript script, jsbytecode *pc); + bool elementReadShouldAlwaysLoadDoubles(UnrootedScript script, jsbytecode *pc); bool elementReadHasExtraIndexedProperty(UnrootedScript, jsbytecode *pc); bool elementReadIsPacked(UnrootedScript script, jsbytecode *pc); void elementReadGeneric(UnrootedScript script, jsbytecode *pc, bool *cacheable, bool *monitorResult); bool elementWriteIsDenseNative(HandleScript script, jsbytecode *pc); bool elementWriteIsTypedArray(RawScript script, jsbytecode *pc, int *arrayType); + bool elementWriteNeedsDoubleConversion(UnrootedScript script, jsbytecode *pc); bool elementWriteHasExtraIndexedProperty(UnrootedScript script, jsbytecode *pc); bool elementWriteIsPacked(UnrootedScript script, jsbytecode *pc); + bool arrayResultShouldHaveDoubleConversion(UnrootedScript script, jsbytecode *pc); bool setElementHasWrittenHoles(UnrootedScript script, jsbytecode *pc); bool propertyWriteCanSpecialize(UnrootedScript script, jsbytecode *pc); bool propertyWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc, RawId id); diff --git a/js/src/ion/VMFunctions.h b/js/src/ion/VMFunctions.h index d86b6803c7f..4d25cff9551 100644 --- a/js/src/ion/VMFunctions.h +++ b/js/src/ion/VMFunctions.h @@ -465,6 +465,7 @@ bool OperatorIn(JSContext *cx, HandleValue key, HandleObject obj, JSBool *out); bool GetIntrinsicValue(JSContext *cx, HandlePropertyName name, MutableHandleValue rval); bool CreateThis(JSContext *cx, HandleObject callee, MutableHandleValue rval); + } // namespace ion } // namespace js diff --git a/js/src/ion/arm/CodeGenerator-arm.cpp b/js/src/ion/arm/CodeGenerator-arm.cpp index a10f2d8c904..012ac1fd35c 100644 --- a/js/src/ion/arm/CodeGenerator-arm.cpp +++ b/js/src/ion/arm/CodeGenerator-arm.cpp @@ -1456,11 +1456,19 @@ CodeGeneratorARM::visitLoadElementT(LLoadElementT *load) { Register base = ToRegister(load->elements()); if (load->mir()->type() == MIRType_Double) { + FloatRegister fpreg = ToFloatRegister(load->output()); if (load->index()->isConstant()) { Address source(base, ToInt32(load->index()) * sizeof(Value)); - masm.loadInt32OrDouble(source, ToFloatRegister(load->output())); + if (load->mir()->loadDoubles()) + masm.loadDouble(source, fpreg); + else + masm.loadInt32OrDouble(source, fpreg); } else { - masm.loadInt32OrDouble(base, ToRegister(load->index()), ToFloatRegister(load->output())); + Register index = ToRegister(load->index()); + if (load->mir()->loadDoubles()) + masm.loadDouble(BaseIndex(base, index, TimesEight), fpreg); + else + masm.loadInt32OrDouble(base, index, fpreg); } } else { if (load->index()->isConstant()) { diff --git a/js/src/ion/x64/Assembler-x64.h b/js/src/ion/x64/Assembler-x64.h index e0ba264d6e2..e45c7e68c30 100644 --- a/js/src/ion/x64/Assembler-x64.h +++ b/js/src/ion/x64/Assembler-x64.h @@ -189,6 +189,16 @@ class Operand disp_(disp) { } + Address toAddress() { + JS_ASSERT(kind() == REG_DISP); + return Address(Register::FromCode(base()), disp()); + } + + BaseIndex toBaseIndex() { + JS_ASSERT(kind() == SCALE); + return BaseIndex(Register::FromCode(base()), Register::FromCode(index()), scale(), disp()); + } + Kind kind() const { return kind_; } diff --git a/js/src/ion/x64/CodeGenerator-x64.cpp b/js/src/ion/x64/CodeGenerator-x64.cpp index 0c054cfc29c..8c2e3424b77 100644 --- a/js/src/ion/x64/CodeGenerator-x64.cpp +++ b/js/src/ion/x64/CodeGenerator-x64.cpp @@ -251,7 +251,16 @@ bool CodeGeneratorX64::visitLoadElementT(LLoadElementT *load) { Operand source = createArrayElementOperand(ToRegister(load->elements()), load->index()); - loadUnboxedValue(source, load->mir()->type(), load->output()); + + if (load->mir()->loadDoubles()) { + FloatRegister fpreg = ToFloatRegister(load->output()); + if (source.kind() == Operand::REG_DISP) + masm.loadDouble(source.toAddress(), fpreg); + else + masm.loadDouble(source.toBaseIndex(), fpreg); + } else { + loadUnboxedValue(source, load->mir()->type(), load->output()); + } JS_ASSERT(!load->mir()->needsHoleCheck()); return true; diff --git a/js/src/ion/x86/Assembler-x86.h b/js/src/ion/x86/Assembler-x86.h index 0456c5e6e73..d348bad77bf 100644 --- a/js/src/ion/x86/Assembler-x86.h +++ b/js/src/ion/x86/Assembler-x86.h @@ -144,6 +144,16 @@ class Operand base_(reinterpret_cast(address)) { } + Address toAddress() { + JS_ASSERT(kind() == REG_DISP); + return Address(Register::FromCode(base()), disp()); + } + + BaseIndex toBaseIndex() { + JS_ASSERT(kind() == SCALE); + return BaseIndex(Register::FromCode(base()), Register::FromCode(index()), scale(), disp()); + } + Kind kind() const { return kind_; } diff --git a/js/src/ion/x86/CodeGenerator-x86.cpp b/js/src/ion/x86/CodeGenerator-x86.cpp index 52f53c7c3f1..02db3c3b0fc 100644 --- a/js/src/ion/x86/CodeGenerator-x86.cpp +++ b/js/src/ion/x86/CodeGenerator-x86.cpp @@ -240,10 +240,19 @@ CodeGeneratorX86::visitLoadElementT(LLoadElementT *load) return false; } - if (load->mir()->type() == MIRType_Double) - masm.loadInt32OrDouble(source, ToFloatRegister(load->output())); - else + if (load->mir()->type() == MIRType_Double) { + FloatRegister fpreg = ToFloatRegister(load->output()); + if (load->mir()->loadDoubles()) { + if (source.kind() == Operand::REG_DISP) + masm.loadDouble(source.toAddress(), fpreg); + else + masm.loadDouble(source.toBaseIndex(), fpreg); + } else { + masm.loadInt32OrDouble(source, fpreg); + } + } else { masm.movl(masm.ToPayload(source), ToRegister(load->output())); + } return true; } diff --git a/js/src/jit-test/tests/ion/doubleArrays.js b/js/src/jit-test/tests/ion/doubleArrays.js new file mode 100644 index 00000000000..4622c3f29ea --- /dev/null +++ b/js/src/jit-test/tests/ion/doubleArrays.js @@ -0,0 +1,51 @@ + +function testPushConvert() { + var x = []; + for (var i = 0; i < 10; i++) + x.push(i + .5); + for (var i = 0; i < 5; i++) + x.push(i); + var res = 0; + for (var i = 0; i < x.length; i++) + res += x[i]; + assertEq(res, 60); +} +testPushConvert(); + +function testArrayInitializer() { + var x = [.5,1.5,2.5,3]; + var res = 0; + for (var i = 0; i < x.length; i++) + res += x[i]; + assertEq(res, 7.5); +} +for (var i = 0; i < 5; i++) + testArrayInitializer(); + +function testArrayConstructor() { + var x = Array(.5,1.5,2.5,3); + var res = 0; + for (var i = 0; i < x.length; i++) + res += x[i]; + assertEq(res, 7.5); +} +for (var i = 0; i < 5; i++) + testArrayConstructor(); + +function addInt(a) { + // inhibit ion + try { + a[0] = 10; + } catch (e) {} +} + +function testBaseline() { + var x = Array(.5,1.5,2.5,3); + addInt(x); + var res = 0; + for (var i = 0; i < x.length; i++) + res += x[i]; + assertEq(res, 17); +} +for (var i = 0; i < 5; i++) + testBaseline(); diff --git a/js/src/jsarray.h b/js/src/jsarray.h index f20ea1c42a8..68dc2e689bf 100644 --- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -15,9 +15,6 @@ #include "jsatom.h" #include "jsobj.h" -/* Small arrays are dense, no matter what. */ -const unsigned MIN_SPARSE_INDEX = 512; - namespace js { /* 2^32-2, inclusive */ const uint32_t MAX_ARRAY_INDEX = 4294967294u; @@ -28,14 +25,13 @@ js_IdIsIndex(jsid id, uint32_t *indexp) { if (JSID_IS_INT(id)) { int32_t i = JSID_TO_INT(id); - if (i < 0) - return JS_FALSE; + JS_ASSERT(i >= 0); *indexp = (uint32_t)i; - return JS_TRUE; + return true; } if (JS_UNLIKELY(!JSID_IS_STRING(id))) - return JS_FALSE; + return false; return js::StringIsArrayIndex(JSID_TO_ATOM(id), indexp); } diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 9a7e7eebc7b..6f23f369dc9 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1263,6 +1263,9 @@ struct JSJitInfo { OpType type; bool isInfallible; /* Is op fallible? False in setters. */ bool isConstant; /* Getting a construction-time constant? */ + bool isPure; /* As long as no non-pure DOM things happen, will + keep returning the same value for the given + "this" object" */ JSValueType returnType; /* The return type tag. Might be JSVAL_TYPE_UNKNOWN */ }; diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 24b2eaa6311..eb16baccaa6 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -1996,6 +1996,70 @@ StackTypeSet::filtersType(const StackTypeSet *other, Type filteredType) const return true; } +StackTypeSet::DoubleConversion +StackTypeSet::convertDoubleElements(JSContext *cx) +{ + if (unknownObject() || !getObjectCount()) + return AmbiguousDoubleConversion; + + bool alwaysConvert = true; + bool maybeConvert = false; + bool dontConvert = false; + + for (unsigned i = 0; i < getObjectCount(); i++) { + TypeObject *type = getTypeObject(i); + if (!type) { + if (JSObject *obj = getSingleObject(i)) { + type = obj->getType(cx); + if (!type) + return AmbiguousDoubleConversion; + } else { + continue; + } + } + + if (type->unknownProperties()) { + alwaysConvert = false; + continue; + } + + HeapTypeSet *types = type->getProperty(cx, JSID_VOID, false); + if (!types) + return AmbiguousDoubleConversion; + + // We can't convert to double elements for objects which do not have + // double in their element types (as the conversion may render the type + // information incorrect), nor for non-array objects (as their elements + // may point to emptyObjectElements, which cannot be converted). + if (!types->hasType(Type::DoubleType()) || type->clasp != &ArrayClass) { + dontConvert = true; + alwaysConvert = false; + continue; + } + + // Only bother with converting known packed arrays whose possible + // element types are int or double. Other arrays require type tests + // when elements are accessed regardless of the conversion. + if (types->getKnownTypeTag(cx) == JSVAL_TYPE_DOUBLE && + !HeapTypeSet::HasObjectFlags(cx, type, OBJECT_FLAG_NON_PACKED)) + { + maybeConvert = true; + } else { + alwaysConvert = false; + } + } + + JS_ASSERT_IF(alwaysConvert, maybeConvert); + + if (maybeConvert && dontConvert) + return AmbiguousDoubleConversion; + if (alwaysConvert) + return AlwaysConvertToDoubles; + if (maybeConvert) + return MaybeConvertToDoubles; + return DontConvertToDoubles; +} + bool HeapTypeSet::knownSubset(JSContext *cx, TypeSet *other) { diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h index 7afb207f582..d43ba287139 100644 --- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -637,6 +637,26 @@ class StackTypeSet : public TypeSet return true; } + + enum DoubleConversion { + /* All types in the set should use eager double conversion. */ + AlwaysConvertToDoubles, + + /* Some types in the set should use eager double conversion. */ + MaybeConvertToDoubles, + + /* No types should use eager double conversion. */ + DontConvertToDoubles, + + /* Some types should use eager double conversion, others cannot. */ + AmbiguousDoubleConversion + }; + + /* + * Whether known double optimizations are possible for element accesses on + * objects in this type set. + */ + DoubleConversion convertDoubleElements(JSContext *cx); }; /* diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index 238b04019bc..67f431ae2de 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -359,7 +359,7 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, HandleValue lval, HandleValu } else { RootedValue rref(cx, rval); bool strict = cx->stack.currentScript()->strict; - if (!js_NativeSet(cx, obj, obj, shape, false, strict, &rref)) + if (!js_NativeSet(cx, obj, obj, shape, strict, &rref)) return false; } return true; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 7c8cb2be4f9..d02914772e4 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2524,10 +2524,10 @@ JSObject::willBeSparseElements(unsigned requiredCapacity, unsigned newElementsHi unsigned cap = getDenseCapacity(); JS_ASSERT(requiredCapacity >= cap); - if (requiredCapacity >= JSObject::NELEMENTS_LIMIT) + if (requiredCapacity >= NELEMENTS_LIMIT) return true; - unsigned minimalDenseCount = requiredCapacity / 4; + unsigned minimalDenseCount = requiredCapacity / SPARSE_DENSITY_RATIO; if (newElementsHint >= minimalDenseCount) return false; minimalDenseCount -= newElementsHint; @@ -2544,6 +2544,119 @@ JSObject::willBeSparseElements(unsigned requiredCapacity, unsigned newElementsHi return true; } +/* static */ JSObject::EnsureDenseResult +JSObject::maybeDensifySparseElements(JSContext *cx, HandleObject obj) +{ + /* This should only be called after adding a sparse index to an object. */ + JS_ASSERT(JSID_IS_INT(obj->lastProperty()->propid())); + + /* + * Wait until after the object goes into dictionary mode, which must happen + * when sparsely packing any array with more than MIN_SPARSE_INDEX elements + * (see PropertyTree::MAX_HEIGHT). + */ + if (!obj->inDictionaryMode()) + return ED_SPARSE; + + /* + * Only measure the number of indexed properties every log(n) times when + * populating the object. + */ + uint32_t slotSpan = obj->slotSpan(); + if (slotSpan != RoundUpPow2(slotSpan)) + return ED_SPARSE; + + /* Watch for conditions under which an object's elements cannot be dense. */ + if (!obj->isExtensible() || obj->watched()) + return ED_SPARSE; + + /* + * The indexes in the object need to be sufficiently dense before they can + * be converted to dense mode. + */ + uint32_t numDenseElements = 0; + uint32_t newInitializedLength = 0; + + RootedShape shape(cx, obj->lastProperty()); + while (!shape->isEmptyShape()) { + uint32_t index; + if (js_IdIsIndex(shape->propid(), &index)) { + if (shape->attributes() == JSPROP_ENUMERATE && + shape->hasDefaultGetter() && + shape->hasDefaultSetter()) + { + numDenseElements++; + newInitializedLength = Max(newInitializedLength, index + 1); + } else { + /* + * For simplicity, only densify the object if all indexed + * properties can be converted to dense elements. + */ + return ED_SPARSE; + } + } + shape = shape->previous(); + } + + if (numDenseElements * SPARSE_DENSITY_RATIO < newInitializedLength) + return ED_SPARSE; + + if (newInitializedLength >= NELEMENTS_LIMIT) + return ED_SPARSE; + + /* + * This object meets all necessary restrictions, convert all indexed + * properties into dense elements. + */ + + if (!obj->growElements(cx, newInitializedLength)) + return ED_FAILED; + + obj->ensureDenseInitializedLength(cx, newInitializedLength, 0); + + RootedValue value(cx); + + shape = obj->lastProperty(); + while (!shape->isEmptyShape()) { + jsid id = shape->propid(); + uint32_t index; + if (js_IdIsIndex(id, &index)) { + value = obj->getSlot(shape->slot()); + + /* + * When removing a property from a dictionary, the specified + * property will be removed from the dictionary list and the + * last property will then be changed due to reshaping the object. + * Compute the next shape in the traverse, watching for such + * removals from the list. + */ + if (shape != obj->lastProperty()) { + shape = shape->previous(); + if (!obj->removeProperty(cx, id)) + return ED_FAILED; + } else { + if (!obj->removeProperty(cx, id)) + return ED_FAILED; + shape = obj->lastProperty(); + } + + obj->setDenseElement(index, value); + } else { + shape = shape->previous(); + } + } + + /* + * All indexed properties on the object are now dense, clear the indexed + * flag so that we will not start using sparse indexes again if we need + * to grow the object. + */ + if (!obj->clearFlag(cx, BaseShape::INDEXED)) + return ED_FAILED; + + return ED_OK; +} + bool JSObject::growElements(JSContext *cx, unsigned newcap) { @@ -3055,8 +3168,10 @@ CallAddPropertyHook(JSContext *cx, Class *clasp, HandleObject obj, HandleShape s RootedValue value(cx, nominal); Rooted id(cx, shape->propid()); - if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, &value)) + if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, &value)) { + obj->removeProperty(cx, shape->propid()); return false; + } if (value.get() != nominal) { if (shape->hasSlot()) JSObject::nativeSetSlotWithType(cx, obj, shape, value); @@ -3082,14 +3197,75 @@ CallAddPropertyHookDense(JSContext *cx, Class *clasp, HandleObject obj, uint32_t RootedValue value(cx, nominal); Rooted id(cx, INT_TO_JSID(index)); - if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, &value)) + if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, &value)) { + JSObject::setDenseElementHole(cx, obj, index); return false; + } if (value.get() != nominal) JSObject::setDenseElementWithType(cx, obj, index, value); } return true; } +static inline bool +DefinePropertyOrElement(JSContext *cx, HandleObject obj, HandleId id, + PropertyOp getter, StrictPropertyOp setter, + unsigned attrs, unsigned flags, int shortid, + HandleValue value, bool callSetterAfterwards, bool setterIsStrict) +{ + /* Use dense storage for new indexed properties where possible. */ + if (JSID_IS_INT(id) && + getter == JS_PropertyStub && + setter == JS_StrictPropertyStub && + attrs == JSPROP_ENUMERATE && + (!obj->isIndexed() || !obj->nativeContains(cx, id))) + { + uint32_t index = JSID_TO_INT(id); + JSObject::EnsureDenseResult result = obj->ensureDenseElements(cx, index, 1); + if (result == JSObject::ED_FAILED) + return false; + if (result == JSObject::ED_OK) { + obj->setDenseElementMaybeConvertDouble(index, value); + return CallAddPropertyHookDense(cx, obj->getClass(), obj, index, value); + } + } + + AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter); + + RootedShape shape(cx, JSObject::putProperty(cx, obj, id, getter, setter, SHAPE_INVALID_SLOT, + attrs, flags, shortid)); + if (!shape) + return false; + + if (shape->hasSlot()) + obj->nativeSetSlot(shape->slot(), value); + + /* + * Clear any existing dense index after adding a sparse indexed property, + * and investigate converting the object to dense indexes. + */ + if (JSID_IS_INT(id)) { + uint32_t index = JSID_TO_INT(id); + JSObject::removeDenseElementForSparseIndex(cx, obj, index); + JSObject::EnsureDenseResult result = JSObject::maybeDensifySparseElements(cx, obj); + if (result == JSObject::ED_FAILED) + return false; + if (result == JSObject::ED_OK) { + JS_ASSERT(setter == JS_StrictPropertyStub); + return CallAddPropertyHookDense(cx, obj->getClass(), obj, index, value); + } + } + + if (!CallAddPropertyHook(cx, obj->getClass(), obj, shape, value)) + return false; + + if (callSetterAfterwards && setter != JS_StrictPropertyStub) { + RootedValue nvalue(cx, value); + return js_NativeSet(cx, obj, obj, shape, setterIsStrict, &nvalue); + } + return true; +} + bool js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs, @@ -3148,7 +3324,7 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal /* * Purge the property cache of any properties named by id that are about * to be shadowed in obj's scope chain unless it is known a priori that it - * is not possible. We do this before locking obj to avoid nesting locks. + * is not possible. */ if (!(defineHow & DNP_DONT_PURGE)) { if (!js_PurgeScopeChain(cx, obj, id)) @@ -3173,47 +3349,14 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal } if (!shape) { - /* Use dense storage for new indexed properties where possible. */ - if (JSID_IS_INT(id) && - getter == JS_PropertyStub && - setter == JS_StrictPropertyStub && - attrs == JSPROP_ENUMERATE && - (!obj->isIndexed() || !obj->nativeContains(cx, id))) - { - uint32_t index = JSID_TO_INT(id); - JSObject::EnsureDenseResult result = obj->ensureDenseElements(cx, index, 1); - if (result == JSObject::ED_FAILED) - return false; - if (result == JSObject::ED_OK) { - obj->setDenseElement(index, value); - if (!CallAddPropertyHookDense(cx, clasp, obj, index, value)) { - JSObject::setDenseElementHole(cx, obj, index); - return false; - } - return true; - } - } - - shape = JSObject::putProperty(cx, obj, id, getter, setter, SHAPE_INVALID_SLOT, - attrs, flags, shortid); - if (!shape) - return false; - - /* Clear any existing dense index after adding a sparse indexed property. */ - if (JSID_IS_INT(id)) - JSObject::removeDenseElementForSparseIndex(cx, obj, JSID_TO_INT(id)); + return DefinePropertyOrElement(cx, obj, id, getter, setter, + attrs, flags, shortid, value, false, false); } - /* Store valueCopy before calling addProperty, in case the latter GC's. */ if (shape->hasSlot()) obj->nativeSetSlot(shape->slot(), value); - if (!CallAddPropertyHook(cx, clasp, obj, shape, value)) { - obj->removeProperty(cx, id); - return false; - } - - return shape; + return CallAddPropertyHook(cx, clasp, obj, shape, value); } /* @@ -3554,7 +3697,7 @@ js_NativeGet(JSContext *cx, Handle obj, Handle pobj, Handl JSBool js_NativeSet(JSContext *cx, Handle obj, Handle receiver, - HandleShape shape, bool added, bool strict, MutableHandleValue vp) + HandleShape shape, bool strict, MutableHandleValue vp) { JS_ASSERT(obj->isNative()); @@ -3898,7 +4041,6 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive Class *clasp; PropertyOp getter; StrictPropertyOp setter; - bool added; JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_UNQUALIFIED)) == 0); @@ -4038,7 +4180,6 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive return true; } - added = false; if (!shape) { if (!obj->isExtensible()) { /* Error in strict mode code, warn with strict option, otherwise do nothing. */ @@ -4046,65 +4187,24 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive return obj->reportNotExtensible(cx); if (cx->hasStrictOption()) return obj->reportNotExtensible(cx, JSREPORT_STRICT | JSREPORT_WARNING); - return JS_TRUE; + return true; } - /* Use dense storage for new indexed properties where possible. */ - if (JSID_IS_INT(id) && - getter == JS_PropertyStub && - setter == JS_StrictPropertyStub && - attrs == JSPROP_ENUMERATE) - { - uint32_t index = JSID_TO_INT(id); - JSObject::EnsureDenseResult result = obj->ensureDenseElements(cx, index, 1); - if (result == JSObject::ED_FAILED) - return false; - if (result == JSObject::ED_OK) { - obj->setDenseElement(index, UndefinedValue()); - if (!CallAddPropertyHookDense(cx, clasp, obj, index, vp)) { - JSObject::setDenseElementHole(cx, obj, index); - return false; - } - JSObject::setDenseElementWithType(cx, obj, index, vp); - return true; - } - } - - /* - * Purge the property cache of now-shadowed id in obj's scope chain. - * Do this early, before locking obj to avoid nesting locks. - */ + /* Purge the property cache of now-shadowed id in obj's scope chain. */ if (!js_PurgeScopeChain(cx, obj, id)) - return JS_FALSE; + return false; - shape = JSObject::putProperty(cx, obj, id, getter, setter, SHAPE_INVALID_SLOT, - attrs, flags, shortid); - if (!shape) - return JS_FALSE; + if (getter == JS_PropertyStub) + AddTypePropertyId(cx, obj, id, vp); - /* Clear any existing dense index after adding a sparse indexed property. */ - if (JSID_IS_INT(id)) - JSObject::removeDenseElementForSparseIndex(cx, obj, JSID_TO_INT(id)); - - /* - * Initialize the new property value (passed to setter) to undefined. - * Note that we store before calling addProperty, to match the order - * in DefineNativeProperty. - */ - if (shape->hasSlot()) - obj->nativeSetSlot(shape->slot(), UndefinedValue()); - - if (!CallAddPropertyHook(cx, clasp, obj, shape, vp)) { - obj->removeProperty(cx, id); - return JS_FALSE; - } - added = true; + return DefinePropertyOrElement(cx, obj, id, getter, setter, + attrs, flags, shortid, vp, true, strict); } - if ((defineHow & DNP_CACHE_RESULT) && !added) + if (defineHow & DNP_CACHE_RESULT) cx->propertyCache().fill(cx, obj, obj, shape); - return js_NativeSet(cx, obj, receiver, shape, added, strict, vp); + return js_NativeSet(cx, obj, receiver, shape, strict, vp); } JSBool diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 2d3e717c9a1..41001253da8 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -367,6 +367,7 @@ class JSObject : public js::ObjectImpl bool setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag, GenerateShape generateShape = GENERATE_NONE); + bool clearFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag); public: inline bool nativeEmpty() const; @@ -589,6 +590,7 @@ class JSObject : public js::ObjectImpl inline void ensureDenseInitializedLength(JSContext *cx, unsigned index, unsigned extra); inline void setDenseElement(unsigned idx, const js::Value &val); inline void initDenseElement(unsigned idx, const js::Value &val); + inline void setDenseElementMaybeConvertDouble(unsigned idx, const js::Value &val); static inline void setDenseElementWithType(JSContext *cx, js::HandleObject obj, unsigned idx, const js::Value &val); static inline void initDenseElementWithType(JSContext *cx, js::HandleObject obj, @@ -600,6 +602,8 @@ class JSObject : public js::ObjectImpl inline void initDenseElements(unsigned dstStart, const js::Value *src, unsigned count); inline void moveDenseElements(unsigned dstStart, unsigned srcStart, unsigned count); inline void moveDenseElementsUnbarriered(unsigned dstStart, unsigned srcStart, unsigned count); + inline bool shouldConvertDoubleElements(); + inline void setShouldConvertDoubleElements(); /* Packed information for this object's elements. */ inline void markDenseElementsNotPacked(JSContext *cx); @@ -624,12 +628,27 @@ class JSObject : public js::ObjectImpl /* Convert all dense elements to sparse properties. */ static bool sparsifyDenseElements(JSContext *cx, js::HandleObject obj); + /* Small objects are dense, no matter what. */ + static const unsigned MIN_SPARSE_INDEX = 1000; + + /* + * Element storage for an object will be sparse if fewer than 1/8 indexes + * are filled in. + */ + static const unsigned SPARSE_DENSITY_RATIO = 8; + /* * Check if after growing the object's elements will be too sparse. * newElementsHint is an estimated number of elements to be added. */ bool willBeSparseElements(unsigned requiredCapacity, unsigned newElementsHint); + /* + * After adding a sparse index to obj, see if it should be converted to use + * dense elements. + */ + static EnsureDenseResult maybeDensifySparseElements(JSContext *cx, js::HandleObject obj); + /* Array specific accessors. */ inline uint32_t getArrayLength() const; static inline void setArrayLength(JSContext *cx, js::HandleObject obj, uint32_t length); @@ -1328,7 +1347,7 @@ js_NativeGet(JSContext *cx, js::Handle obj, js::Handle pob extern JSBool js_NativeSet(JSContext *cx, js::Handle obj, js::Handle receiver, - js::Handle shape, bool added, bool strict, js::MutableHandleValue vp); + js::Handle shape, bool strict, js::MutableHandleValue vp); namespace js { diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index c3da9ea2148..efa77baf8d8 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -388,10 +388,7 @@ JSObject::setArrayLength(JSContext *cx, js::HandleObject obj, uint32_t length) JS_ASSERT(obj->isArray()); if (length > INT32_MAX) { - /* - * Mark the type of this object as possibly not a dense array, per the - * requirements of OBJECT_FLAG_NON_DENSE_ARRAY. - */ + /* Track objects with overflowing lengths in type information. */ js::types::MarkTypeObjectFlags(cx, obj, js::types::OBJECT_FLAG_LENGTH_OVERFLOW); jsid lengthId = js::NameToId(cx->names().length); @@ -427,6 +424,20 @@ JSObject::getDenseCapacity() return getElementsHeader()->capacity; } +inline bool +JSObject::shouldConvertDoubleElements() +{ + JS_ASSERT(isNative()); + return getElementsHeader()->convertDoubleElements; +} + +inline void +JSObject::setShouldConvertDoubleElements() +{ + JS_ASSERT(isArray() && !hasEmptyElements()); + getElementsHeader()->convertDoubleElements = 1; +} + inline bool JSObject::ensureElements(JSContext *cx, uint32_t capacity) { @@ -450,6 +461,15 @@ JSObject::setDenseElement(unsigned idx, const js::Value &val) elements[idx].set(this, js::HeapSlot::Element, idx, val); } +inline void +JSObject::setDenseElementMaybeConvertDouble(unsigned idx, const js::Value &val) +{ + if (val.isInt32() && shouldConvertDoubleElements()) + setDenseElement(idx, js::DoubleValue(val.toInt32())); + else + setDenseElement(idx, val); +} + inline void JSObject::initDenseElement(unsigned idx, const js::Value &val) { @@ -462,13 +482,14 @@ JSObject::setDenseElementWithType(JSContext *cx, js::HandleObject obj, unsigned const js::Value &val) { js::types::AddTypePropertyId(cx, obj, JSID_VOID, val); - obj->setDenseElement(idx, val); + obj->setDenseElementMaybeConvertDouble(idx, val); } /* static */ inline void JSObject::initDenseElementWithType(JSContext *cx, js::HandleObject obj, unsigned idx, const js::Value &val) { + JS_ASSERT(!obj->shouldConvertDoubleElements()); js::types::AddTypePropertyId(cx, obj, JSID_VOID, val); obj->initDenseElement(idx, val); } diff --git a/js/src/jstypedarrayinlines.h b/js/src/jstypedarrayinlines.h index 2e498b0a3ba..a8d3fff0b7e 100644 --- a/js/src/jstypedarrayinlines.h +++ b/js/src/jstypedarrayinlines.h @@ -28,7 +28,7 @@ js::ArrayBufferObject::setElementsHeader(js::ObjectElements *header, uint32_t by header->capacity = bytes / sizeof(js::Value); header->initializedLength = bytes; header->length = 0; - header->unused = 0; + header->convertDoubleElements = 0; } inline uint32_t diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index d26f14cc54b..4ace5cdb0e7 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -1412,6 +1412,8 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegiste Address(result, elementsOffset + ObjectElements::offsetOfInitializedLength())); store32(Imm32(templateObject->getArrayLength()), Address(result, elementsOffset + ObjectElements::offsetOfLength())); + store32(Imm32(templateObject->shouldConvertDoubleElements() ? 1 : 0), + Address(result, elementsOffset + ObjectElements::offsetOfConvertDoubleElements())); } else { /* * Fixed slots of non-array objects are required to be initialized; diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 5d309770218..fa7174ab466 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -6980,10 +6980,15 @@ mjit::Compiler::jsop_newinit() } JSObject *templateObject; - if (isArray) + if (isArray) { templateObject = NewDenseUnallocatedArray(cx, count); - else + types::StackTypeSet::DoubleConversion conversion = + script->analysis()->pushedTypes(PC, 0)->convertDoubleElements(cx); + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles) + templateObject->setShouldConvertDoubleElements(); + } else { templateObject = CopyInitializerObject(cx, baseobj); + } if (!templateObject) return false; templateObject->setType(type); diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 962220a0d15..bcf1d0e1ccb 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -716,7 +716,7 @@ private: void jsop_initmethod(); void jsop_initprop(); void jsop_initelem_array(); - void jsop_setelem_dense(); + void jsop_setelem_dense(types::StackTypeSet::DoubleConversion conversion); #ifdef JS_METHODJIT_TYPED_ARRAY void jsop_setelem_typed(int atype); void convertForTypedArray(int atype, ValueRemat *vr, bool *allocated); @@ -780,7 +780,8 @@ private: CompileStatus compileMathMinMaxInt(FrameEntry *arg1, FrameEntry *arg2, Assembler::Condition cond); CompileStatus compileMathPowSimple(FrameEntry *arg1, FrameEntry *arg2); - CompileStatus compileArrayPush(FrameEntry *thisv, FrameEntry *arg); + CompileStatus compileArrayPush(FrameEntry *thisv, FrameEntry *arg, + types::StackTypeSet::DoubleConversion conversion); CompileStatus compileArrayConcat(types::TypeSet *thisTypes, types::TypeSet *argTypes, FrameEntry *thisValue, FrameEntry *argValue); CompileStatus compileArrayPopShift(FrameEntry *thisv, bool isPacked, bool isArrayPop); diff --git a/js/src/methodjit/FastBuiltins.cpp b/js/src/methodjit/FastBuiltins.cpp index ad55c0ef164..5415930e9ab 100644 --- a/js/src/methodjit/FastBuiltins.cpp +++ b/js/src/methodjit/FastBuiltins.cpp @@ -414,7 +414,8 @@ mjit::Compiler::compileStringFromCode(FrameEntry *arg) } CompileStatus -mjit::Compiler::compileArrayPush(FrameEntry *thisValue, FrameEntry *arg) +mjit::Compiler::compileArrayPush(FrameEntry *thisValue, FrameEntry *arg, + types::StackTypeSet::DoubleConversion conversion) { /* This behaves like an assignment this[this.length] = arg; */ @@ -422,6 +423,12 @@ mjit::Compiler::compileArrayPush(FrameEntry *thisValue, FrameEntry *arg) if (frame.haveSameBacking(thisValue, arg) || thisValue->isConstant()) return Compile_InlineAbort; + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles || + conversion == types::StackTypeSet::MaybeConvertToDoubles) + { + frame.ensureDouble(arg); + } + /* Allocate registers. */ ValueRemat vr; frame.pinEntry(arg, vr, /* breakDouble = */ false); @@ -765,6 +772,16 @@ mjit::Compiler::compileArrayWithArgs(uint32_t argc) JS_ASSERT(templateObject->getDenseCapacity() >= argc); + types::StackTypeSet::DoubleConversion conversion = + script->analysis()->pushedTypes(PC, 0)->convertDoubleElements(cx); + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles) { + templateObject->setShouldConvertDoubleElements(); + for (unsigned i = 0; i < argc; i++) { + FrameEntry *arg = frame.peek(-(int32_t)argc + i); + frame.ensureDouble(arg); + } + } + RegisterID result = frame.allocReg(); Jump emptyFreeList = getNewObject(cx, result, templateObject); stubcc.linkExit(emptyFreeList, Uses(0)); @@ -1004,7 +1021,9 @@ mjit::Compiler::inlineNativeFunction(uint32_t argc, bool callingNew) !thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPARSE_INDEXES | types::OBJECT_FLAG_LENGTH_OVERFLOW) && !types::ArrayPrototypeHasIndexedProperty(cx, outerScript)) { - return compileArrayPush(thisValue, arg); + types::StackTypeSet::DoubleConversion conversion = thisTypes->convertDoubleElements(cx); + if (conversion != types::StackTypeSet::AmbiguousDoubleConversion) + return compileArrayPush(thisValue, arg, conversion); } } if (native == js::array_concat && argType == JSVAL_TYPE_OBJECT && diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp index 2a4849fb16f..b104730dcb1 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -858,7 +858,7 @@ IsCacheableSetElem(FrameEntry *obj, FrameEntry *id, FrameEntry *value) } void -mjit::Compiler::jsop_setelem_dense() +mjit::Compiler::jsop_setelem_dense(types::StackTypeSet::DoubleConversion conversion) { FrameEntry *obj = frame.peek(-3); FrameEntry *id = frame.peek(-2); @@ -866,6 +866,14 @@ mjit::Compiler::jsop_setelem_dense() frame.forgetMismatchedObject(obj); + // If the array being written to might need integer elements converted to + // doubles, make the conversion before writing. + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles || + conversion == types::StackTypeSet::MaybeConvertToDoubles) + { + frame.ensureDouble(value); + } + // We might not know whether this is an object, but if it is an object we // know it is a dense array. if (!obj->isTypeKnown()) { @@ -1340,13 +1348,18 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed) if (cx->typeInferenceEnabled()) { types::StackTypeSet *types = analysis->poppedTypes(PC, 2); + types::StackTypeSet::DoubleConversion conversion = types->convertDoubleElements(cx); if (types->getKnownClass() == &ArrayClass && !types->hasObjectFlags(cx, types::OBJECT_FLAG_SPARSE_INDEXES | types::OBJECT_FLAG_LENGTH_OVERFLOW) && - !types::ArrayPrototypeHasIndexedProperty(cx, outerScript)) + !types::ArrayPrototypeHasIndexedProperty(cx, outerScript) && + conversion != types::StackTypeSet::AmbiguousDoubleConversion && + (conversion == types::StackTypeSet::DontConvertToDoubles || + value->isType(JSVAL_TYPE_DOUBLE) || + popGuaranteed)) { // Inline dense array path. - jsop_setelem_dense(); + jsop_setelem_dense(conversion); return true; } @@ -2515,6 +2528,13 @@ mjit::Compiler::jsop_initelem_array() FrameEntry *obj = frame.peek(-2); FrameEntry *fe = frame.peek(-1); + if (cx->typeInferenceEnabled()) { + types::StackTypeSet::DoubleConversion conversion = + script_->analysis()->poppedTypes(PC, 1)->convertDoubleElements(cx); + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles) + frame.ensureDouble(fe); + } + uint32_t index = GET_UINT24(PC); RegisterID objReg = frame.copyDataIntoReg(obj); diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index 470b439524e..b4a57f6743c 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -150,6 +150,30 @@ static ObjectElements emptyElementsHeader(0, 0); HeapSlot *js::emptyObjectElements = reinterpret_cast(uintptr_t(&emptyElementsHeader) + sizeof(ObjectElements)); +/* static */ bool +ObjectElements::ConvertElementsToDoubles(JSContext *cx, uintptr_t elementsPtr) +{ + /* + * This function is infallible, but has a fallible interface so that it can + * be called directly from Ion code. Only arrays can have their dense + * elements converted to doubles, and arrays never have empty elements. + */ + HeapSlot *elementsHeapPtr = (HeapSlot *) elementsPtr; + JS_ASSERT(elementsHeapPtr != emptyObjectElements); + + ObjectElements *header = ObjectElements::fromElements(elementsHeapPtr); + JS_ASSERT(!header->convertDoubleElements); + + Value *vp = (Value *) elementsPtr; + for (size_t i = 0; i < header->initializedLength; i++) { + if (vp[i].isInt32()) + vp[i].setDouble(vp[i].toInt32()); + } + + header->convertDoubleElements = 1; + return true; +} + #ifdef DEBUG void js::ObjectImpl::checkShapeConsistency() diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h index 04665b78832..1c0b25d7c81 100644 --- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -935,8 +935,8 @@ class ObjectElements /* 'length' property of array objects, unused for other objects. */ uint32_t length; - /* :XXX: bug 586842 store state about sparse slots. */ - uint32_t unused; + /* If non-zero, integer elements should be converted to doubles. */ + uint32_t convertDoubleElements; void staticAsserts() { MOZ_STATIC_ASSERT(sizeof(ObjectElements) == VALUES_PER_HEADER * sizeof(Value), @@ -946,7 +946,7 @@ class ObjectElements public: ObjectElements(uint32_t capacity, uint32_t length) - : capacity(capacity), initializedLength(0), length(length) + : capacity(capacity), initializedLength(0), length(length), convertDoubleElements(0) {} HeapSlot *elements() { return (HeapSlot *)(uintptr_t(this) + sizeof(ObjectElements)); } @@ -963,6 +963,11 @@ class ObjectElements static int offsetOfLength() { return (int)offsetof(ObjectElements, length) - (int)sizeof(ObjectElements); } + static int offsetOfConvertDoubleElements() { + return (int)offsetof(ObjectElements, convertDoubleElements) - (int)sizeof(ObjectElements); + } + + static bool ConvertElementsToDoubles(JSContext *cx, uintptr_t elements); static const size_t VALUES_PER_HEADER = 2; }; diff --git a/js/src/vm/Shape-inl.h b/js/src/vm/Shape-inl.h index 10a916a836a..01af9c7025d 100644 --- a/js/src/vm/Shape-inl.h +++ b/js/src/vm/Shape-inl.h @@ -158,8 +158,6 @@ BaseShape::adoptUnowned(UnrootedUnownedBaseShape other) * unowned base shape of a new last property. */ JS_ASSERT(isOwned()); - mozilla::DebugOnly flags = getObjectFlags(); - JS_ASSERT((flags & other->getObjectFlags()) == flags); uint32_t span = slotSpan(); ShapeTable *table = &this->table(); diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index 3d3309642dd..f91ba856b90 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1092,6 +1092,24 @@ JSObject::setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag_, GenerateSha return true; } +bool +JSObject::clearFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag) +{ + JS_ASSERT(inDictionaryMode()); + JS_ASSERT(lastProperty()->getObjectFlags() & flag); + + RootedObject self(cx, this); + + StackBaseShape base(self->lastProperty()); + base.flags &= ~flag; + UnrootedUnownedBaseShape nbase = BaseShape::getUnowned(cx, base); + if (!nbase) + return false; + + self->lastProperty()->base()->adoptUnowned(nbase); + return true; +} + /* static */ UnrootedShape Shape::setObjectFlag(JSContext *cx, BaseShape::Flag flag, TaggedProto proto, Shape *last) { diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index 88df2485b30..8cfc602ffd4 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -245,8 +245,9 @@ class BaseShape : public js::gc::Cell /* * Flags set which describe the referring object. Once set these cannot - * be unset, and are transferred from shape to shape as the object's - * last property changes. + * be unset (except during object densification of sparse indexes), and + * are transferred from shape to shape as the object's last property + * changes. */ DELEGATE = 0x8, diff --git a/js/xpconnect/src/XPCJSID.cpp b/js/xpconnect/src/XPCJSID.cpp index 6970676adf9..b07d2102969 100644 --- a/js/xpconnect/src/XPCJSID.cpp +++ b/js/xpconnect/src/XPCJSID.cpp @@ -486,9 +486,19 @@ nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper, JSObject* cur = unsafeObj ? unsafeObj : obj; nsISupports *identity; if (mozilla::dom::UnwrapDOMObjectToISupports(cur, identity)) { - nsCOMPtr supp; - identity->QueryInterface(*iid, getter_AddRefs(supp)); - *bp = supp; + nsCOMPtr ci = do_QueryInterface(identity); + if (!ci) { + // No classinfo means we're not implementing interfaces and all + return NS_OK; + } + + XPCCallContext ccx(JS_CALLER, cx); + + AutoMarkingNativeSetPtr set(ccx); + set = XPCNativeSet::GetNewOrUsed(ccx, ci); + if (!set) + return NS_ERROR_FAILURE; + *bp = set->HasInterfaceWithAncestor(iid); return NS_OK; } } diff --git a/js/xpconnect/src/dom_quickstubs.qsconf b/js/xpconnect/src/dom_quickstubs.qsconf index 9eea0a43b37..266f7d176c6 100644 --- a/js/xpconnect/src/dom_quickstubs.qsconf +++ b/js/xpconnect/src/dom_quickstubs.qsconf @@ -46,7 +46,12 @@ members = [ 'nsIDOMWindow.onmouseleave', 'nsIDOMWindowPerformance.performance', 'nsIDOMJSWindow.dump', + 'nsIDOMScreen.top', + 'nsIDOMScreen.height', + 'nsIDOMScreen.width', + 'nsIDOMScreen.left', 'nsIDOMClientRect.*', + 'nsIDOMPaintRequest.*', # nsLocationSH has ~ALLOW_PROP_MODS_TO_PROTOTYPE, so don't try. #'nsIDOMLocation.hostname', #'nsIDOMLocation.href', @@ -59,11 +64,18 @@ members = [ 'nsIDOMCanvasPattern.*', # dom/interfaces/core + 'nsIDOMCharacterData.data', + 'nsIDOMCharacterData.length', 'nsIDOMNamedNodeMap.item', 'nsIDOMNamedNodeMap.length', + 'nsIDOMText.splitText', 'nsIDOMDOMStringList.*', 'nsIDOMXULDocument.getBoxObjectFor', + # dom/interfaces/css + 'nsIDOMElementCSSInlineStyle.*', + 'nsIDOMRect.*', + 'nsIDOMEvent.type', 'nsIDOMEvent.target', 'nsIDOMEvent.currentTarget', @@ -229,6 +241,9 @@ members = [ 'nsIDOMXPathResult.singleNodeValue', 'nsIDOMNSXPathExpression.evaluateWithContext', + # dom/interfaces/xul + 'nsIDOMXULElement.*', + # layout/xul/base/public 'nsIBoxObject.x', 'nsIBoxObject.y', @@ -296,8 +311,20 @@ irregularFilenames = { } customIncludes = [ + 'nsINode.h', + 'nsIContent.h', + 'nsIDocument.h', + 'nsCSSPropertiesQS.h', + 'nsDOMTokenList.h', + 'nsGenericDOMDataNode.h', + 'mozilla/dom/Element.h', + 'nsGenericHTMLElement.h', + 'nsSVGElement.h', 'nsDOMQS.h', + 'nsDOMStringMap.h', + 'HTMLPropertiesCollection.h', 'nsHTMLMenuElement.h', + 'nsICSSDeclaration.h', 'mozilla/dom/NodeBinding.h', 'mozilla/dom/ElementBinding.h', 'mozilla/dom/HTMLElementBinding.h', @@ -323,6 +350,15 @@ customMethodCalls = { 'nsIDOMStorage_Clear': { 'code': nsIDOMStorage_Clear_customMethodCallCode }, + 'nsIDOMElementCSSInlineStyle_GetStyle': { + 'thisType': 'nsStyledElement', + 'code': ' /* XXXbz MathML elements inherit from nsStyledElement but\n' + ' don\'t actually implement GetStyle. */\n' + ' if (self->GetNameSpaceID() == kNameSpaceID_MathML)\n' + ' return xpc_qsThrow(cx, NS_ERROR_XPC_BAD_CONVERT_JS);\n' + ' nsIDOMCSSStyleDeclaration* result = self->Style();', + 'canFail': False + }, 'nsIDOMWindow_GetOnmouseenter' : { 'thisType' : 'nsIDOMWindow', 'unwrapThisFailureFatal' : False diff --git a/js/xpconnect/src/nsCSSPropertiesQS.h b/js/xpconnect/src/nsCSSPropertiesQS.h new file mode 100644 index 00000000000..c52fa07bb38 --- /dev/null +++ b/js/xpconnect/src/nsCSSPropertiesQS.h @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsCSSPropertiesQS_h__ +#define nsCSSPropertiesQS_h__ + +#include "nsICSSDeclaration.h" + +#define CSS_PROP_DOMPROP_PREFIXED(prop_) Moz ## prop_ +#define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, kwtable_, \ + stylestruct_, stylestructoffset_, animtype_) \ +static const nsCSSProperty QS_CSS_PROP_##method_ = eCSSProperty_##id_; + +#define CSS_PROP_LIST_EXCLUDE_INTERNAL +#define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, pref_) \ + CSS_PROP(name_, id_, method_, flags_, pref_, X, X, X, X, X) +#include "nsCSSPropList.h" + +#define CSS_PROP_ALIAS(aliasname_, propid_, aliasmethod_, pref_) \ + CSS_PROP(X, propid_, aliasmethod_, X, pref_, X, X, X, X, X) +#include "nsCSSPropAliasList.h" +#undef CSS_PROP_ALIAS + +#undef CSS_PROP_SHORTHAND +#undef CSS_PROP_LIST_EXCLUDE_INTERNAL +#undef CSS_PROP +#undef CSS_PROP_DOMPROP_PREFIXED + +#endif /* nsCSSPropertiesQS_h__ */ diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 5ab9f069063..d3c7ffbe626 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1567,6 +1567,17 @@ nsDisplayBackgroundImage::~nsDisplayBackgroundImage() #endif } +#ifdef MOZ_DUMP_PAINTING +void +nsDisplayBackgroundImage::WriteDebugInfo(FILE *aOutput) +{ + if (mIsThemed) { + fprintf(aOutput, "(themed, appearance:%d) ", mFrame->GetStyleDisplay()->mAppearance); + } + +} +#endif + /*static*/ nsresult nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, @@ -2179,10 +2190,6 @@ nsDisplayBackgroundImage::GetBoundsInternal() { } nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize()); - if (mFrame->GetType() == nsGkAtoms::canvasFrame) { - nsCanvasFrame* frame = static_cast(mFrame); - borderBox = frame->CanvasArea() + ToReferenceFrame(); - } const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer]; return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame, borderBox, *mBackgroundStyle, layer); diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 48b6283bb81..6fbff13457f 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -1056,6 +1056,8 @@ public: * For debugging and stuff */ virtual const char* Name() = 0; + + virtual void WriteDebugInfo(FILE *aOutput) {} #endif nsDisplayItem* GetAbove() { return mAbove; } @@ -1905,6 +1907,10 @@ public: static nsRegion GetInsideClipRegion(nsDisplayItem* aItem, nsPresContext* aPresContext, uint8_t aClip, const nsRect& aRect, bool* aSnap); + +#ifdef MOZ_DUMP_PAINTING + virtual void WriteDebugInfo(FILE *aOutput); +#endif protected: typedef class mozilla::layers::ImageContainer ImageContainer; typedef class mozilla::layers::ImageLayer ImageLayer; @@ -1961,6 +1967,14 @@ public: } NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR) +#ifdef MOZ_DUMP_PAINTING + virtual void WriteDebugInfo(FILE *aOutput) { + fprintf(aOutput, "(rgba %d,%d,%d,%d)", + NS_GET_R(mColor), NS_GET_G(mColor), + NS_GET_B(mColor), NS_GET_A(mColor)); + + } +#endif protected: const nsStyleBackground* mBackgroundStyle; @@ -2288,6 +2302,11 @@ public: // We don't need to compute an invalidation region since we have LayerTreeInvalidation } NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY) +#ifdef MOZ_DUMP_PAINTING + virtual void WriteDebugInfo(FILE *aOutput) { + fprintf(aOutput, "(opacity %f)", mFrame->GetStyleDisplay()->mOpacity); + } +#endif bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder); }; diff --git a/layout/base/nsLayoutDebugger.cpp b/layout/base/nsLayoutDebugger.cpp index 43808129d3f..79c13b330bd 100644 --- a/layout/base/nsLayoutDebugger.cpp +++ b/layout/base/nsLayoutDebugger.cpp @@ -185,8 +185,9 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, i->IsUniform(aBuilder, &color) ? " uniform" : ""); nsRegionRectIterator iter(opaque); for (const nsRect* r = iter.Next(); r; r = iter.Next()) { - printf("(opaque %d,%d,%d,%d)", r->x, r->y, r->width, r->height); + fprintf(aOutput, "(opaque %d,%d,%d,%d)", r->x, r->y, r->width, r->height); } + i->WriteDebugInfo(aOutput); if (aDumpHtml && i->Painted()) { fprintf(aOutput, ""); } diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index b8ffe99c873..f879a496229 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -4005,6 +4005,7 @@ PresShell::DocumentStatesChanged(nsIDocument* aDocument, if (root->HasView()) { root->GetView()->SetForcedRepaint(true); } + root->SchedulePaint(); } } } diff --git a/layout/svg/nsSVGMarkerFrame.cpp b/layout/svg/nsSVGMarkerFrame.cpp index 065e456a27e..cebe817f433 100644 --- a/layout/svg/nsSVGMarkerFrame.cpp +++ b/layout/svg/nsSVGMarkerFrame.cpp @@ -10,7 +10,7 @@ #include "gfxContext.h" #include "nsRenderingContext.h" #include "nsSVGEffects.h" -#include "nsSVGMarkerElement.h" +#include "mozilla/dom/SVGMarkerElement.h" #include "nsSVGPathGeometryElement.h" #include "nsSVGPathGeometryFrame.h" @@ -80,7 +80,7 @@ nsSVGMarkerFrame::GetCanvasTM(uint32_t aFor) return gfxMatrix(); } - nsSVGMarkerElement *content = static_cast(mContent); + SVGMarkerElement *content = static_cast(mContent); mInUse2 = true; gfxMatrix markedTM = mMarkedFrame->GetCanvasTM(aFor); @@ -106,7 +106,7 @@ nsSVGMarkerFrame::PaintMark(nsRenderingContext *aContext, AutoMarkerReferencer markerRef(this, aMarkedFrame); - nsSVGMarkerElement *marker = static_cast(mContent); + SVGMarkerElement *marker = static_cast(mContent); const nsSVGViewBoxRect viewBox = marker->GetViewBoxRect(); @@ -164,7 +164,7 @@ nsSVGMarkerFrame::GetMarkBBoxContribution(const gfxMatrix &aToBBoxUserspace, AutoMarkerReferencer markerRef(this, aMarkedFrame); - nsSVGMarkerElement *content = static_cast(mContent); + SVGMarkerElement *content = static_cast(mContent); const nsSVGViewBoxRect viewBox = content->GetViewBoxRect(); @@ -204,7 +204,7 @@ nsSVGMarkerFrame::GetMarkBBoxContribution(const gfxMatrix &aToBBoxUserspace, void nsSVGMarkerFrame::SetParentCoordCtxProvider(SVGSVGElement *aContext) { - nsSVGMarkerElement *marker = static_cast(mContent); + SVGMarkerElement *marker = static_cast(mContent); marker->SetParentCoordCtxProvider(aContext); } diff --git a/media/mtransport/build/Makefile.in b/media/mtransport/build/Makefile.in index 7eb850b5894..ca9d1ad28e7 100644 --- a/media/mtransport/build/Makefile.in +++ b/media/mtransport/build/Makefile.in @@ -37,6 +37,7 @@ EXPORTS_mtransport = \ ../transportlayerprsock.h \ ../m_cpp_utils.h \ ../runnable_utils.h \ + ../runnable_utils_generated.h \ ../sigslot.h \ $(NULL) diff --git a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp index 8434363e12f..f1a20e60dcc 100644 --- a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp +++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp @@ -3,6 +3,13 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AudioConduit.h" +#include "nsCOMPtr.h" +#include "mozilla/Services.h" +#include "nsServiceManagerUtils.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" +#include "nsThreadUtils.h" + #include "CSFLog.h" #include "voice_engine/include/voe_errors.h" @@ -17,11 +24,13 @@ const unsigned int WebrtcAudioConduit::CODEC_PLNAME_SIZE = 32; /** * Factory Method for AudioConduit */ -mozilla::RefPtr AudioSessionConduit::Create() +mozilla::RefPtr AudioSessionConduit::Create(AudioSessionConduit *aOther) { CSFLogDebug(logTag, "%s ", __FUNCTION__); + NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); + WebrtcAudioConduit* obj = new WebrtcAudioConduit(); - if(obj->Init() != kMediaConduitNoError) + if(obj->Init(static_cast(aOther)) != kMediaConduitNoError) { CSFLogError(logTag, "%s AudioConduit Init Failed ", __FUNCTION__); delete obj; @@ -36,6 +45,8 @@ mozilla::RefPtr AudioSessionConduit::Create() */ WebrtcAudioConduit::~WebrtcAudioConduit() { + NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); + CSFLogDebug(logTag, "%s ", __FUNCTION__); for(std::vector::size_type i=0;i < mRecvCodecList.size();i++) { @@ -44,17 +55,27 @@ WebrtcAudioConduit::~WebrtcAudioConduit() delete mCurSendCodecConfig; + // The first one of a pair to be deleted shuts down media for both if(mPtrVoEXmedia) { - mPtrVoEXmedia->SetExternalRecordingStatus(false); - mPtrVoEXmedia->SetExternalPlayoutStatus(false); + if (!mShutDown) { + mPtrVoEXmedia->SetExternalRecordingStatus(false); + mPtrVoEXmedia->SetExternalPlayoutStatus(false); + } mPtrVoEXmedia->Release(); } + if(mPtrVoEProcessing) + { + mPtrVoEProcessing->Release(); + } + //Deal with the transport if(mPtrVoENetwork) { - mPtrVoENetwork->DeRegisterExternalTransport(mChannel); + if (!mShutDown) { + mPtrVoENetwork->DeRegisterExternalTransport(mChannel); + } mPtrVoENetwork->Release(); } @@ -65,47 +86,69 @@ WebrtcAudioConduit::~WebrtcAudioConduit() if(mPtrVoEBase) { - mPtrVoEBase->StopPlayout(mChannel); - mPtrVoEBase->StopSend(mChannel); - mPtrVoEBase->StopReceive(mChannel); - mPtrVoEBase->DeleteChannel(mChannel); - mPtrVoEBase->Terminate(); + if (!mShutDown) { + mPtrVoEBase->StopPlayout(mChannel); + mPtrVoEBase->StopSend(mChannel); + mPtrVoEBase->StopReceive(mChannel); + mPtrVoEBase->DeleteChannel(mChannel); + mPtrVoEBase->Terminate(); + } mPtrVoEBase->Release(); } - if(mVoiceEngine) + if (mOtherDirection) { - webrtc::VoiceEngine::Delete(mVoiceEngine); + // mOtherDirection owns these now! + mOtherDirection->mOtherDirection = NULL; + // let other side we terminated the channel + mOtherDirection->mShutDown = true; + mVoiceEngine = nullptr; + } else { + // only one opener can call Delete. Have it be the last to close. + if(mVoiceEngine) + { + webrtc::VoiceEngine::Delete(mVoiceEngine); + } } } /* * WebRTCAudioConduit Implementation */ -MediaConduitErrorCode WebrtcAudioConduit::Init() +MediaConduitErrorCode WebrtcAudioConduit::Init(WebrtcAudioConduit *other) { - CSFLogDebug(logTag, "%s ", __FUNCTION__); + CSFLogDebug(logTag, "%s this=%p other=%p", __FUNCTION__, this, other); - //Per WebRTC APIs below function calls return NULL on failure - if(!(mVoiceEngine = webrtc::VoiceEngine::Create())) - { - CSFLogError(logTag, "%s Unable to create voice engine", __FUNCTION__); - return kMediaConduitSessionNotInited; - } + if (other) { + MOZ_ASSERT(!other->mOtherDirection); + other->mOtherDirection = this; + mOtherDirection = other; - PRLogModuleInfo *logs = GetWebRTCLogInfo(); - if (!gWebrtcTraceLoggingOn && logs && logs->level > 0) { - // no need to a critical section or lock here - gWebrtcTraceLoggingOn = 1; - - const char *file = PR_GetEnv("WEBRTC_TRACE_FILE"); - if (!file) { - file = "WebRTC.log"; + // only one can call ::Create()/GetVoiceEngine() + MOZ_ASSERT(other->mVoiceEngine); + mVoiceEngine = other->mVoiceEngine; + } else { + //Per WebRTC APIs below function calls return NULL on failure + if(!(mVoiceEngine = webrtc::VoiceEngine::Create())) + { + CSFLogError(logTag, "%s Unable to create voice engine", __FUNCTION__); + return kMediaConduitSessionNotInited; + } + + PRLogModuleInfo *logs = GetWebRTCLogInfo(); + if (!gWebrtcTraceLoggingOn && logs && logs->level > 0) { + // no need to a critical section or lock here + gWebrtcTraceLoggingOn = 1; + + const char *file = PR_GetEnv("WEBRTC_TRACE_FILE"); + if (!file) { + file = "WebRTC.log"; + } + CSFLogDebug(logTag, "%s Logging webrtc to %s level %d", __FUNCTION__, + file, logs->level); + mVoiceEngine->SetTraceFilter(logs->level); + mVoiceEngine->SetTraceFile(file); } - CSFLogDebug(logTag, "%s Logging webrtc to %s level %d", __FUNCTION__, - file, logs->level); - mVoiceEngine->SetTraceFilter(logs->level); - mVoiceEngine->SetTraceFile(file); } if(!(mPtrVoEBase = VoEBase::GetInterface(mVoiceEngine))) @@ -126,51 +169,60 @@ MediaConduitErrorCode WebrtcAudioConduit::Init() return kMediaConduitSessionNotInited; } + if(!(mPtrVoEProcessing = VoEAudioProcessing::GetInterface(mVoiceEngine))) + { + CSFLogError(logTag, "%s Unable to initialize VoEProcessing", __FUNCTION__); + return kMediaConduitSessionNotInited; + } + if(!(mPtrVoEXmedia = VoEExternalMedia::GetInterface(mVoiceEngine))) { CSFLogError(logTag, "%s Unable to initialize VoEExternalMedia", __FUNCTION__); return kMediaConduitSessionNotInited; } - // init the engine with our audio device layer - if(mPtrVoEBase->Init() == -1) - { - CSFLogError(logTag, "%s VoiceEngine Base Not Initialized", __FUNCTION__); - return kMediaConduitSessionNotInited; - } + if (other) { + mChannel = other->mChannel; + } else { + // init the engine with our audio device layer + if(mPtrVoEBase->Init() == -1) + { + CSFLogError(logTag, "%s VoiceEngine Base Not Initialized", __FUNCTION__); + return kMediaConduitSessionNotInited; + } - if( (mChannel = mPtrVoEBase->CreateChannel()) == -1) - { - CSFLogError(logTag, "%s VoiceEngine Channel creation failed",__FUNCTION__); - return kMediaConduitChannelError; - } + if( (mChannel = mPtrVoEBase->CreateChannel()) == -1) + { + CSFLogError(logTag, "%s VoiceEngine Channel creation failed",__FUNCTION__); + return kMediaConduitChannelError; + } - CSFLogDebug(logTag, "%s Channel Created %d ",__FUNCTION__, mChannel); + CSFLogDebug(logTag, "%s Channel Created %d ",__FUNCTION__, mChannel); - if(mPtrVoENetwork->RegisterExternalTransport(mChannel, *this) == -1) - { - CSFLogError(logTag, "%s VoiceEngine, External Transport Failed",__FUNCTION__); - return kMediaConduitTransportRegistrationFail; - } + if(mPtrVoENetwork->RegisterExternalTransport(mChannel, *this) == -1) + { + CSFLogError(logTag, "%s VoiceEngine, External Transport Failed",__FUNCTION__); + return kMediaConduitTransportRegistrationFail; + } - if(mPtrVoEXmedia->SetExternalRecordingStatus(true) == -1) - { - CSFLogError(logTag, "%s SetExternalRecordingStatus Failed %d",__FUNCTION__, - mPtrVoEBase->LastError()); - return kMediaConduitExternalPlayoutError; - } + if(mPtrVoEXmedia->SetExternalRecordingStatus(true) == -1) + { + CSFLogError(logTag, "%s SetExternalRecordingStatus Failed %d",__FUNCTION__, + mPtrVoEBase->LastError()); + return kMediaConduitExternalPlayoutError; + } - if(mPtrVoEXmedia->SetExternalPlayoutStatus(true) == -1) - { - CSFLogError(logTag, "%s SetExternalPlayoutStatus Failed %d ",__FUNCTION__, - mPtrVoEBase->LastError()); - return kMediaConduitExternalRecordingError; + if(mPtrVoEXmedia->SetExternalPlayoutStatus(true) == -1) + { + CSFLogError(logTag, "%s SetExternalPlayoutStatus Failed %d ",__FUNCTION__, + mPtrVoEBase->LastError()); + return kMediaConduitExternalRecordingError; + } + CSFLogDebug(logTag , "%s AudioSessionConduit Initialization Done (%p)",__FUNCTION__, this); } - CSFLogDebug(logTag , "%s AudioSessionConduit Initialization Done",__FUNCTION__); return kMediaConduitNoError; } - // AudioSessionConduit Implementation MediaConduitErrorCode WebrtcAudioConduit::AttachTransport(mozilla::RefPtr aTransport) @@ -235,6 +287,33 @@ WebrtcAudioConduit::ConfigureSendMediaCodec(const AudioCodecConfig* codecConfig) return kMediaConduitUnknownError; } + // TEMPORARY - see bug 694814 comment 2 + nsresult rv; + nsCOMPtr prefs = do_GetService("@mozilla.org/preferences-service;1", &rv); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr branch = do_QueryInterface(prefs); + + if (branch) { + int32_t aec = 0; // 0 == unchanged + bool aec_on = false; + + branch->GetBoolPref("media.peerconnection.aec_enabled", &aec_on); + branch->GetIntPref("media.peerconnection.aec", &aec); + + CSFLogDebug(logTag,"Audio config: aec: %d", aec_on ? aec : -1); + mEchoOn = aec_on; + if (static_cast(aec) != webrtc::kEcUnchanged) + mEchoCancel = static_cast(aec); + + branch->GetIntPref("media.peerconnection.capture_delay", &mCaptureDelay); + } + } + + if (0 != (error = mPtrVoEProcessing->SetEcStatus(mEchoOn, mEchoCancel))) { + CSFLogError(logTag,"%s Error setting EVStatus: %d ",__FUNCTION__, error); + return kMediaConduitUnknownError; + } + //Let's Send Transport State-machine on the Engine if(mPtrVoEBase->StartSend(mChannel) == -1) { @@ -404,7 +483,7 @@ WebrtcAudioConduit::SendAudioFrame(const int16_t audio_data[], return kMediaConduitSessionNotInited; } - + capture_delay = mCaptureDelay; //Insert the samples if(mPtrVoEXmedia->ExternalRecordingInsertData(audio_data, lengthSamples, @@ -544,34 +623,53 @@ WebrtcAudioConduit::ReceivedRTCPPacket(const void *data, int len) int WebrtcAudioConduit::SendPacket(int channel, const void* data, int len) { - CSFLogDebug(logTag, "%s : channel %d",__FUNCTION__,channel); + CSFLogDebug(logTag, "%s : channel %d %s",__FUNCTION__,channel, + (mEngineReceiving && mOtherDirection) ? "(using mOtherDirection)" : ""); - if(mTransport && (mTransport->SendRtpPacket(data, len) == NS_OK)) - { + if (mEngineReceiving) + { + if (mOtherDirection) + { + return mOtherDirection->SendPacket(channel, data, len); + } + CSFLogDebug(logTag, "%s : Asked to send RTP without an RTP sender", + __FUNCTION__, channel); + return -1; + } else { + if(mTransport && (mTransport->SendRtpPacket(data, len) == NS_OK)) + { CSFLogDebug(logTag, "%s Sent RTP Packet ", __FUNCTION__); return len; - } else { - CSFLogError(logTag, "%s RTP Packet Send Failed ", __FUNCTION__); - return -1; - } - + } else { + CSFLogError(logTag, "%s RTP Packet Send Failed ", __FUNCTION__); + return -1; + } + } } int WebrtcAudioConduit::SendRTCPPacket(int channel, const void* data, int len) { CSFLogDebug(logTag, "%s : channel %d", __FUNCTION__, channel); - // can't enable this assertion, because we do. Suppress it - // NS_ASSERTION(mEngineReceiving,"We shouldn't send RTCP on the receiver side"); - if(mEngineReceiving && mTransport && mTransport->SendRtcpPacket(data, len) == NS_OK) + if (mEngineTransmitting) { - CSFLogDebug(logTag, "%s Sent RTCP Packet ", __FUNCTION__); - return len; - } else { - CSFLogError(logTag, "%s RTCP Packet Send Failed ", __FUNCTION__); + if (mOtherDirection) + { + return mOtherDirection->SendRTCPPacket(channel, data, len); + } + CSFLogDebug(logTag, "%s : Asked to send RTCP without an RTP receiver", + __FUNCTION__, channel); return -1; + } else { + if(mTransport && mTransport->SendRtcpPacket(data, len) == NS_OK) + { + CSFLogDebug(logTag, "%s Sent RTCP Packet ", __FUNCTION__); + return len; + } else { + CSFLogError(logTag, "%s RTCP Packet Send Failed ", __FUNCTION__); + return -1; + } } - } /** @@ -748,4 +846,3 @@ WebrtcAudioConduit::DumpCodecDB() const } } }// end namespace - diff --git a/media/webrtc/signaling/src/media-conduit/AudioConduit.h b/media/webrtc/signaling/src/media-conduit/AudioConduit.h index 9b484f4b9a2..7869b6fddfb 100755 --- a/media/webrtc/signaling/src/media-conduit/AudioConduit.h +++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.h @@ -18,12 +18,14 @@ #include "voice_engine/include/voe_file.h" #include "voice_engine/include/voe_network.h" #include "voice_engine/include/voe_external_media.h" +#include "voice_engine/include/voe_audio_processing.h" //Some WebRTC types for short notations using webrtc::VoEBase; using webrtc::VoENetwork; using webrtc::VoECodec; using webrtc::VoEExternalMedia; + using webrtc::VoEAudioProcessing; /** This file hosts several structures identifying different aspects * of a RTP Session. @@ -141,18 +143,23 @@ public: WebrtcAudioConduit(): + mOtherDirection(NULL), + mShutDown(false), mVoiceEngine(NULL), mTransport(NULL), mEngineTransmitting(false), mEngineReceiving(false), mChannel(-1), - mCurSendCodecConfig(NULL) + mCurSendCodecConfig(NULL), + mCaptureDelay(150), + mEchoOn(true), + mEchoCancel(webrtc::kEcAec) { } virtual ~WebrtcAudioConduit(); - MediaConduitErrorCode Init(); + MediaConduitErrorCode Init(WebrtcAudioConduit *other); private: WebrtcAudioConduit(const WebrtcAudioConduit& other) MOZ_DELETE; @@ -185,12 +192,19 @@ private: //Utility function to dump recv codec database void DumpCodecDB() const; + WebrtcAudioConduit* mOtherDirection; + // Other side has shut down our channel and related items already + bool mShutDown; + + // These are shared by both directions. They're released by the last + // conduit to die webrtc::VoiceEngine* mVoiceEngine; mozilla::RefPtr mTransport; webrtc::VoENetwork* mPtrVoENetwork; webrtc::VoEBase* mPtrVoEBase; webrtc::VoECodec* mPtrVoECodec; webrtc::VoEExternalMedia* mPtrVoEXmedia; + webrtc::VoEAudioProcessing* mPtrVoEProcessing; //engine states of our interets bool mEngineTransmitting; // If true => VoiceEngine Send-subsystem is up @@ -200,6 +214,12 @@ private: int mChannel; RecvCodecList mRecvCodecList; AudioCodecConfig* mCurSendCodecConfig; + + // Current "capture" delay (really output plus input delay) + int32_t mCaptureDelay; + + bool mEchoOn; + webrtc::EcModes mEchoCancel; }; } // end namespace diff --git a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h index 7988f6b15dc..0f1437b577e 100755 --- a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h +++ b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h @@ -226,7 +226,7 @@ public: * return: Concrete VideoSessionConduitObject or NULL in the case * of failure */ - static mozilla::RefPtr Create(); + static mozilla::RefPtr Create(AudioSessionConduit *aOther); virtual ~AudioSessionConduit() {} diff --git a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp index aa1bcdbbe62..2aaf579728c 100644 --- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp +++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp @@ -1303,12 +1303,18 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, if (CC_IS_AUDIO(mcap_id)) { std::vector configs; + // Instantiate an appropriate conduit + mozilla::RefPtr tx_conduit = + pc.impl()->media()->GetConduit(level, false); + mozilla::RefPtr conduit = - mozilla::AudioSessionConduit::Create(); + mozilla::AudioSessionConduit::Create(tx_conduit); if(!conduit) return VCM_ERROR; + pc.impl()->media()->AddConduit(level, true, conduit); + mozilla::AudioCodecConfig *config_raw; for(int i=0; i config(config_raw); // Instantiate an appropriate conduit + mozilla::RefPtr rx_conduit = + pc.impl()->media()->GetConduit(level, true); + mozilla::RefPtr conduit = - mozilla::AudioSessionConduit::Create(); + mozilla::AudioSessionConduit::Create(rx_conduit); if (!conduit || conduit->ConfigureSendMediaCodec(config)) return VCM_ERROR; + pc.impl()->media()->AddConduit(level, false, conduit); + mozilla::RefPtr pipeline = new mozilla::MediaPipelineTransmit( pc.impl()->GetHandle(), diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h index cc5f776ebd0..26cd23ecbb7 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h @@ -293,9 +293,28 @@ class PeerConnectionMedia : public sigslot::has_slots<> { mozilla::RefPtr aFlow) { int index_inner = aIndex * 2 + (aRtcp ? 1 : 0); + MOZ_ASSERT(!mTransportFlows[index_inner]); mTransportFlows[index_inner] = aFlow; } + mozilla::RefPtr GetConduit(int aStreamIndex, bool aReceive) { + int index_inner = aStreamIndex * 2 + (aReceive ? 0 : 1); + + if (mAudioConduits.find(index_inner) == mAudioConduits.end()) + return NULL; + + return mAudioConduits[index_inner]; + } + + // Add a conduit + void AddConduit(int aIndex, bool aReceive, + const mozilla::RefPtr &aConduit) { + int index_inner = aIndex * 2 + (aReceive ? 0 : 1); + + MOZ_ASSERT(!mAudioConduits[index_inner]); + mAudioConduits[index_inner] = aConduit; + } + // ICE state signals sigslot::signal1 SignalIceGatheringCompleted; // Done gathering sigslot::signal1 SignalIceCompleted; // Done handshaking @@ -331,6 +350,10 @@ class PeerConnectionMedia : public sigslot::has_slots<> { // Transport flows: even is RTP, odd is RTCP std::map > mTransportFlows; + // Conduits: even is receive, odd is transmit (for easier correlation with + // flows) + std::map > mAudioConduits; + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PeerConnectionMedia) }; diff --git a/media/webrtc/signaling/test/mediaconduit_unittests.cpp b/media/webrtc/signaling/test/mediaconduit_unittests.cpp index 318a0959a06..afde93e5325 100644 --- a/media/webrtc/signaling/test/mediaconduit_unittests.cpp +++ b/media/webrtc/signaling/test/mediaconduit_unittests.cpp @@ -490,11 +490,11 @@ class TransportConduitTest : public ::testing::Test { //get pointer to AudioSessionConduit int err=0; - mAudioSession = mozilla::AudioSessionConduit::Create(); + mAudioSession = mozilla::AudioSessionConduit::Create(NULL); if( !mAudioSession ) ASSERT_NE(mAudioSession, (void*)NULL); - mAudioSession2 = mozilla::AudioSessionConduit::Create(); + mAudioSession2 = mozilla::AudioSessionConduit::Create(NULL); if( !mAudioSession2 ) ASSERT_NE(mAudioSession2, (void*)NULL); diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index 128423dd11d..27dccf05ac8 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -48,7 +48,7 @@ class TestAgent { audio_prsock_(new TransportLayerPrsock()), audio_dtls_(new TransportLayerDtls()), audio_config_(109, "opus", 48000, 480, 1, 64000), - audio_conduit_(mozilla::AudioSessionConduit::Create()), + audio_conduit_(mozilla::AudioSessionConduit::Create(NULL)), audio_(), audio_pipeline_(), video_flow_(new TransportFlow()), diff --git a/media/webrtc/signaling/test/signaling_unittests.cpp b/media/webrtc/signaling/test/signaling_unittests.cpp index 957dc26415d..945dbd78343 100644 --- a/media/webrtc/signaling/test/signaling_unittests.cpp +++ b/media/webrtc/signaling/test/signaling_unittests.cpp @@ -467,7 +467,7 @@ class ParsedSDP { //generate our final sdp in string format std::string sdp; - for(int i=0; i < sdp_lines.size(); i++) + for (size_t i = 0; i < sdp_lines.size(); i++) { sdp += sdp_lines[i]; } @@ -760,7 +760,7 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer, void CloseReceiveStreams() { std::vector streams = pObserver->GetStreams(); - for(int i=0; i < streams.size(); i++) { + for (size_t i = 0; i < streams.size(); i++) { streams[i]->GetStream()->AsSourceStream()->StopStream(); } } diff --git a/media/webrtc/webrtc_config.gypi b/media/webrtc/webrtc_config.gypi index b504d3d8c56..c7195fcfc02 100644 --- a/media/webrtc/webrtc_config.gypi +++ b/media/webrtc/webrtc_config.gypi @@ -3,6 +3,9 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # definitions to control what gets built in webrtc +# NOTE!!! if you change something here, due to .gyp files not +# being reprocessed on .gypi changes, run this before building: +# "find . -name '*.gyp' | xargs touch" { 'variables': { # basic stuff for everything @@ -13,6 +16,8 @@ 'include_tests': 0, 'use_system_libjpeg': 1, 'use_system_libvpx': 1, +# Creates AEC internal sample dump files in current directory +# 'aec_debug_dump': 1, # codec enable/disables: # Note: if you change one here, you must modify shared_libs.mk! diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index e0319a243f1..61a9d7b086b 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -674,6 +674,3 @@ pref("app.orientation.default", ""); // On memory pressure, release dirty but unused pages held by jemalloc // back to the system. pref("memory.free_dirty_pages", true); - -// Enable tiled layers rendering by default on android -pref("gfx.use_tiled_thebes", true); diff --git a/mobile/android/base/GeckoActivity.java.in b/mobile/android/base/GeckoActivity.java.in index 1b8c2d9b0fa..f8fb7cdbe1f 100644 --- a/mobile/android/base/GeckoActivity.java.in +++ b/mobile/android/base/GeckoActivity.java.in @@ -2,11 +2,23 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#filter substitution + package org.mozilla.gecko; import android.app.Activity; +import android.content.ComponentName; +import android.content.Intent; + +interface GeckoActivityStatus { + public boolean isGeckoActivityOpened(); + public boolean isFinishing(); // typically from android.app.Activity +}; + +public class GeckoActivity extends Activity implements GeckoActivityStatus { + // has this activity recently started another Gecko activity? + private boolean mGeckoActivityOpened = false; -public class GeckoActivity extends Activity { @Override public void onPause() { super.onPause(); @@ -22,9 +34,39 @@ public class GeckoActivity extends Activity { if (getApplication() instanceof GeckoApplication) { ((GeckoApplication) getApplication()).onActivityResume(this); + mGeckoActivityOpened = false; } } + @Override + public void startActivity(Intent intent) { + checkIfGeckoActivity(intent); + super.startActivity(intent); + } + + @Override + public void startActivityForResult(Intent intent, int request) { + checkIfGeckoActivity(intent); + super.startActivityForResult(intent, request); + } + + private void checkIfGeckoActivity(Intent intent) { + // Whenever we call our own activity, the component and it's package name is set. + // If we call an activity from another package, or an open intent (leaving android to resolve) + // component has a different package name or it is null. + ComponentName component = intent.getComponent(); + mGeckoActivityOpened = false; + if (component != null && + component.getPackageName() != null && + component.getPackageName().equals("@ANDROID_PACKAGE_NAME@")) { + mGeckoActivityOpened = true; + } + } + + public boolean isGeckoActivityOpened() { + return mGeckoActivityOpened; + } + public boolean isApplicationInBackground() { return ((GeckoApplication) getApplication()).isApplicationInBackground(); } diff --git a/mobile/android/base/GeckoApplication.java b/mobile/android/base/GeckoApplication.java index c2d094e445f..d47df61821e 100644 --- a/mobile/android/base/GeckoApplication.java +++ b/mobile/android/base/GeckoApplication.java @@ -10,6 +10,7 @@ public class GeckoApplication extends Application { private boolean mInited; private boolean mInBackground; + private boolean mPausedGecko; private LightweightTheme mLightweightTheme; @@ -32,17 +33,28 @@ public class GeckoApplication extends Application { mInited = true; } - protected void onActivityPause(GeckoActivity activity) { + protected void onActivityPause(GeckoActivityStatus activity) { mInBackground = true; - GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true)); + if ((activity.isFinishing() == false) && + (activity.isGeckoActivityOpened() == false)) { + // Notify Gecko that we are pausing; the cache service will be + // shutdown, closing the disk cache cleanly. If the android + // low memory killer subsequently kills us, the disk cache will + // be left in a consistent state, avoiding costly cleanup and + // re-creation. + GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true)); + mPausedGecko = true; + } GeckoConnectivityReceiver.getInstance().stop(); GeckoNetworkManager.getInstance().stop(); } - protected void onActivityResume(GeckoActivity activity) { - if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) + protected void onActivityResume(GeckoActivityStatus activity) { + if (mPausedGecko) { GeckoAppShell.sendEventToGecko(GeckoEvent.createResumeEvent(true)); + mPausedGecko = false; + } GeckoConnectivityReceiver.getInstance().start(); GeckoNetworkManager.getInstance().start(); diff --git a/mobile/android/base/GeckoPreferences.java b/mobile/android/base/GeckoPreferences.java index ed9e75db76b..6432ffed38d 100644 --- a/mobile/android/base/GeckoPreferences.java +++ b/mobile/android/base/GeckoPreferences.java @@ -43,7 +43,7 @@ import java.util.ArrayList; public class GeckoPreferences extends PreferenceActivity - implements OnPreferenceChangeListener, GeckoEventListener + implements OnPreferenceChangeListener, GeckoEventListener, GeckoActivityStatus { private static final String LOGTAG = "GeckoPreferences"; @@ -85,6 +85,24 @@ public class GeckoPreferences unregisterEventListener("Sanitize:Finished"); } + @Override + public void onPause() { + super.onPause(); + + if (getApplication() instanceof GeckoApplication) { + ((GeckoApplication) getApplication()).onActivityPause(this); + } + } + + @Override + public void onResume() { + super.onResume(); + + if (getApplication() instanceof GeckoApplication) { + ((GeckoApplication) getApplication()).onActivityResume(this); + } + } + public void handleMessage(String event, JSONObject message) { try { if (event.equals("Sanitize:Finished")) { @@ -445,4 +463,8 @@ public class GeckoPreferences private void unregisterEventListener(String event) { GeckoAppShell.getEventDispatcher().unregisterEventListener(event, this); } + + public boolean isGeckoActivityOpened() { + return false; + } } diff --git a/modules/libjar/Makefile.in b/modules/libjar/Makefile.in index c4dd63b2172..c375524018c 100644 --- a/modules/libjar/Makefile.in +++ b/modules/libjar/Makefile.in @@ -29,6 +29,7 @@ IS_COMPONENT = 1 MODULE_NAME = nsJarModule GRE_MODULE = 1 LIBXUL_LIBRARY = 1 +FAIL_ON_WARNINGS = 1 CPPSRCS = $(MODULES_LIBJAR_LCPPSRCS) diff --git a/modules/libjar/nsJARChannel.cpp b/modules/libjar/nsJARChannel.cpp index 348ebbc7a38..c6eb053e71c 100644 --- a/modules/libjar/nsJARChannel.cpp +++ b/modules/libjar/nsJARChannel.cpp @@ -36,6 +36,12 @@ static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID); //----------------------------------------------------------------------------- +// Ignore any LOG macro that we inherit from arbitrary headers. (We define our +// own LOG macro below.) +#ifdef LOG +#undef LOG +#endif + #if defined(PR_LOGGING) // // set NSPR_LOG_MODULES=nsJarProtocol:5 @@ -43,6 +49,7 @@ static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID); static PRLogModuleInfo *gJarProtocolLog = nullptr; #endif +// If you ever want to define PR_FORCE_LOGGING in this file, see bug 545995 #define LOG(args) PR_LOG(gJarProtocolLog, PR_LOG_DEBUG, args) #define LOG_ENABLED() PR_LOG_TEST(gJarProtocolLog, 4) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 897300bcc08..69705b5634a 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -178,6 +178,15 @@ pref("media.gstreamer.enabled", true); pref("media.navigator.enabled", true); pref("media.peerconnection.enabled", false); pref("media.navigator.permission.disabled", false); +// These values (aec, agc, and noice) are from media/webrtc/trunk/webrtc/common_types.h +// kXxxUnchanged = 0, kXxxDefault = 1, and higher values are specific to each +// setting (for Xxx = Ec, Agc, or Ns). Defaults are all set to kXxxDefault here. +pref("media.peerconnection.aec_enabled", true); +pref("media.peerconnection.aec", 1); +pref("media.peerconnection.agc_enabled", false); +pref("media.peerconnection.agc", 1); +pref("media.peerconnection.noise_enabled", false); +pref("media.peerconnection.noise", 1); #else #ifdef ANDROID pref("media.navigator.enabled", true); diff --git a/netwerk/base/public/nsISocketTransport.idl b/netwerk/base/public/nsISocketTransport.idl index cf43807f5b8..0c8c585aadd 100644 --- a/netwerk/base/public/nsISocketTransport.idl +++ b/netwerk/base/public/nsISocketTransport.idl @@ -163,6 +163,12 @@ interface nsISocketTransport : nsITransport */ const unsigned long NO_PERMANENT_STORAGE = (1 << 3); + /** + * If set, we will skip all IPv4 addresses the host may have and only + * connect to IPv6 ones. + */ + const unsigned long DISABLE_IPV4 = (1 << 4); + /** * Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or * IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index 0396e75b99d..7dd872ad19c 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -926,6 +926,12 @@ nsSocketTransport::ResolveHost() dnsFlags = nsIDNSService::RESOLVE_BYPASS_CACHE; if (mConnectionFlags & nsSocketTransport::DISABLE_IPV6) dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6; + if (mConnectionFlags & nsSocketTransport::DISABLE_IPV4) + dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4; + + NS_ASSERTION(!(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV6) || + !(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV4), + "Setting both RESOLVE_DISABLE_IPV6 and RESOLVE_DISABLE_IPV4"); SendStatus(NS_NET_STATUS_RESOLVING_HOST); rv = dns->AsyncResolve(SocketHost(), dnsFlags, this, nullptr, @@ -1267,12 +1273,12 @@ nsSocketTransport::RecoverFromError() bool tryAgain = false; - if (mConnectionFlags & DISABLE_IPV6 && + if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4) && mCondition == NS_ERROR_UNKNOWN_HOST && mState == STATE_RESOLVING && !mProxyTransparentResolvesHost) { SOCKET_LOG((" trying lookup again with both ipv4/ipv6 enabled\n")); - mConnectionFlags &= ~DISABLE_IPV6; + mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); tryAgain = true; } @@ -1285,14 +1291,15 @@ nsSocketTransport::RecoverFromError() SOCKET_LOG((" trying again with next ip address\n")); tryAgain = true; } - else if (mConnectionFlags & DISABLE_IPV6) { + else if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4)) { // Drop state to closed. This will trigger new round of DNS // resolving bellow. - // XXX Here should idealy be set now non-existing flag DISABLE_IPV4 - SOCKET_LOG((" failed to connect all ipv4 hosts," + // XXX Could be optimized to only switch the flags to save duplicate + // connection attempts. + SOCKET_LOG((" failed to connect all ipv4-only or ipv6-only hosts," " trying lookup/connect again with both ipv4/ipv6\n")); mState = STATE_CLOSED; - mConnectionFlags &= ~DISABLE_IPV6; + mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); tryAgain = true; } } diff --git a/netwerk/cache/nsDiskCacheDeviceSQL.cpp b/netwerk/cache/nsDiskCacheDeviceSQL.cpp index a092a560076..88a1ff9bed3 100644 --- a/netwerk/cache/nsDiskCacheDeviceSQL.cpp +++ b/netwerk/cache/nsDiskCacheDeviceSQL.cpp @@ -26,6 +26,8 @@ #include "nsIArray.h" #include "nsIVariant.h" #include "nsThreadUtils.h" +#include "nsISerializable.h" +#include "nsSerializationHelper.h" #include "mozIStorageService.h" #include "mozIStorageStatement.h" @@ -476,6 +478,19 @@ CreateCacheEntry(nsOfflineCacheDevice *device, entry->UnflattenMetaData((const char *) rec.metaData, rec.metaDataLen); + // Restore security info, if present + const char* info = entry->GetMetaDataElement("security-info"); + if (info) { + nsCOMPtr infoObj; + rv = NS_DeserializeObject(nsDependentCString(info), + getter_AddRefs(infoObj)); + if (NS_FAILED(rv)) { + delete entry; + return nullptr; + } + entry->SetSecurityInfo(infoObj); + } + // create a binding object for this entry nsOfflineCacheBinding *binding = nsOfflineCacheBinding::Create(device->CacheDirectory(), @@ -918,6 +933,21 @@ nsOfflineCacheDevice::UpdateEntry(nsCacheEntry *entry) if (!DecomposeCacheEntryKey(entry->Key(), &cid, &key, keyBuf)) return NS_ERROR_UNEXPECTED; + // Store security info, if it is serializable + nsCOMPtr infoObj = entry->SecurityInfo(); + nsCOMPtr serializable = do_QueryInterface(infoObj); + if (infoObj && !serializable) + return NS_ERROR_UNEXPECTED; + + if (serializable) { + nsCString info; + nsresult rv = NS_SerializeToString(serializable, info); + NS_ENSURE_SUCCESS(rv, rv); + + rv = entry->SetMetaDataElement("security-info", info.get()); + NS_ENSURE_SUCCESS(rv, rv); + } + nsCString metaDataBuf; uint32_t mdSize = entry->MetaDataSize(); if (!EnsureStringLength(metaDataBuf, mdSize)) diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp index f1fe85b2460..05be514c72f 100644 --- a/netwerk/dns/nsDNSService2.cpp +++ b/netwerk/dns/nsDNSService2.cpp @@ -850,6 +850,9 @@ nsDNSService::GetAFForLookup(const nsACString &host, uint32_t flags) } while (*end); } + if ((af != PR_AF_INET) && (flags & RESOLVE_DISABLE_IPV4)) + af = PR_AF_INET6; + return af; } diff --git a/netwerk/dns/nsIDNSService.idl b/netwerk/dns/nsIDNSService.idl index 6b06a194f83..183ca004422 100644 --- a/netwerk/dns/nsIDNSService.idl +++ b/netwerk/dns/nsIDNSService.idl @@ -134,4 +134,9 @@ interface nsIDNSService : nsISupports * asyncResolve. */ const unsigned long RESOLVE_OFFLINE = (1 << 6); + + /** + * If set, only IPv6 addresses will be returned from resolve/asyncResolve. + */ + const unsigned long RESOLVE_DISABLE_IPV4 = (1 << 7); }; diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 4eca5e109cd..d15af44d21e 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -4484,8 +4484,10 @@ nsHttpChannel::BeginConnect() // Force-Reload should reset the persistent connection pool for this host if (mLoadFlags & LOAD_FRESH_CONNECTION) { // just the initial document resets the whole pool - if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) + if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) { gHttpHandler->ConnMgr()->ClosePersistentConnections(); + gHttpHandler->ConnMgr()->ResetIPFamillyPreference(mConnectionInfo); + } // each sub resource gets a fresh connection mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE | NS_HTTP_ALLOW_PIPELINING); } diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index e079b15e6bd..d46a1fa6362 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -2521,8 +2521,13 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, // IPv6 on the backup connection gives them a much better user experience // with dual-stack hosts, though they still pay the 250ms delay for each new // connection. This strategy is also known as "happy eyeballs". - if (isBackup && gHttpHandler->FastFallbackToIPv4()) + if (mEnt->mPreferIPv6) { + tmpFlags |= nsISocketTransport::DISABLE_IPV4; + } + else if (mEnt->mPreferIPv4 || + (isBackup && gHttpHandler->FastFallbackToIPv4())) { tmpFlags |= nsISocketTransport::DISABLE_IPV6; + } socketTransport->SetConnectionFlags(tmpFlags); @@ -2714,6 +2719,7 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) LOG(("nsHalfOpenSocket::OnOutputStreamReady " "Created new nshttpconnection %p\n", conn.get())); + NetAddr peeraddr; nsCOMPtr callbacks; mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks)); if (out == mStreamOut) { @@ -2724,6 +2730,9 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); + if (NS_SUCCEEDED(mSocketTransport->GetPeerAddr(&peeraddr))) + mEnt->RecordIPFamilyPreference(peeraddr.raw.family); + // The nsHttpConnection object now owns these streams and sockets mStreamOut = nullptr; mStreamIn = nullptr; @@ -2737,6 +2746,9 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); + if (NS_SUCCEEDED(mBackupTransport->GetPeerAddr(&peeraddr))) + mEnt->RecordIPFamilyPreference(peeraddr.raw.family); + // The nsHttpConnection object now owns these streams and sockets mBackupStreamOut = nullptr; mBackupStreamIn = nullptr; @@ -2949,6 +2961,8 @@ nsConnectionEntry::nsConnectionEntry(nsHttpConnectionInfo *ci) , mUsingSpdy(false) , mTestedSpdy(false) , mSpdyPreferred(false) + , mPreferIPv4(false) + , mPreferIPv6(false) { NS_ADDREF(mConnInfo); if (gHttpHandler->GetPipelineAggressive()) { @@ -3104,7 +3118,8 @@ nsConnectionEntry::SetYellowConnection(nsHttpConnection *conn) } void -nsHttpConnectionMgr::nsConnectionEntry::OnYellowComplete() +nsHttpConnectionMgr:: +nsConnectionEntry::OnYellowComplete() { if (mPipelineState == PS_YELLOW) { if (mYellowGoodEvents && !mYellowBadEvents) { @@ -3127,7 +3142,8 @@ nsHttpConnectionMgr::nsConnectionEntry::OnYellowComplete() } void -nsHttpConnectionMgr::nsConnectionEntry::CreditPenalty() +nsHttpConnectionMgr:: +nsConnectionEntry::CreditPenalty() { if (mLastCreditTime.IsNull()) return; @@ -3223,8 +3239,17 @@ nsHttpConnectionMgr::GetConnectionData(nsTArray *aA return true; } +void +nsHttpConnectionMgr::ResetIPFamillyPreference(nsHttpConnectionInfo *ci) +{ + nsConnectionEntry *ent = LookupConnectionEntry(ci, nullptr, nullptr); + if (ent) + ent->ResetIPFamilyPreference(); +} + uint32_t -nsHttpConnectionMgr::nsConnectionEntry::UnconnectedHalfOpens() +nsHttpConnectionMgr:: +nsConnectionEntry::UnconnectedHalfOpens() { uint32_t unconnectedHalfOpens = 0; for (uint32_t i = 0; i < mHalfOpens.Length(); ++i) { @@ -3250,3 +3275,22 @@ nsConnectionEntry::RemoveHalfOpen(nsHalfOpenSocket *halfOpen) // altering the pending q vector from an arbitrary stack gHttpHandler->ConnMgr()->ProcessPendingQ(mConnInfo); } + +void +nsHttpConnectionMgr:: +nsConnectionEntry::RecordIPFamilyPreference(uint16_t family) +{ + if (family == PR_AF_INET && !mPreferIPv6) + mPreferIPv4 = true; + + if (family == PR_AF_INET6 && !mPreferIPv4) + mPreferIPv6 = true; +} + +void +nsHttpConnectionMgr:: +nsConnectionEntry::ResetIPFamilyPreference() +{ + mPreferIPv4 = false; + mPreferIPv6 = false; +} diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h index a27b9598959..30d917bc6ea 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -225,6 +225,9 @@ public: bool SupportsPipelining(nsHttpConnectionInfo *); bool GetConnectionData(nsTArray *); + + void ResetIPFamillyPreference(nsHttpConnectionInfo *); + private: virtual ~nsHttpConnectionMgr(); @@ -343,6 +346,20 @@ private: bool mTestedSpdy; bool mSpdyPreferred; + + // Flags to remember our happy-eyeballs decision. + // Reset only by Ctrl-F5 reload. + // True when we've first connected an IPv4 server for this host, + // initially false. + bool mPreferIPv4 : 1; + // True when we've first connected an IPv6 server for this host, + // initially false. + bool mPreferIPv6 : 1; + + // Set the IP family preference flags according the connected family + void RecordIPFamilyPreference(uint16_t family); + // Resets all flags to their default values + void ResetIPFamilyPreference(); }; // nsConnectionHandle diff --git a/rdf/base/src/nsInMemoryDataSource.cpp b/rdf/base/src/nsInMemoryDataSource.cpp index b711778626a..42189a38a3e 100644 --- a/rdf/base/src/nsInMemoryDataSource.cpp +++ b/rdf/base/src/nsInMemoryDataSource.cpp @@ -1758,8 +1758,6 @@ InMemoryDataSource::ResourceEnumerator(PLDHashTable* aTable, NS_IMETHODIMP InMemoryDataSource::GetAllResources(nsISimpleEnumerator** aResult) { - nsresult rv; - nsCOMArray nodes; if (!nodes.SetCapacity(mForwardArcs.entryCount)) { return NS_ERROR_OUT_OF_MEMORY; diff --git a/testing/jetpack/jetpack-location.txt b/testing/jetpack/jetpack-location.txt index 59321cff4b1..00e2024b1b0 100644 --- a/testing/jetpack/jetpack-location.txt +++ b/testing/jetpack/jetpack-location.txt @@ -1 +1 @@ -http://hg.mozilla.org/projects/addon-sdk/archive/03fc0406c5e2.tar.bz2 +http://hg.mozilla.org/projects/addon-sdk/archive/f68c6b75d728.tar.bz2 diff --git a/toolkit/components/places/PlacesUtils.jsm b/toolkit/components/places/PlacesUtils.jsm index f08178087a1..4528d47f699 100644 --- a/toolkit/components/places/PlacesUtils.jsm +++ b/toolkit/components/places/PlacesUtils.jsm @@ -66,7 +66,6 @@ function QI_node(aNode, aIID) { return result; } function asVisit(aNode) QI_node(aNode, Ci.nsINavHistoryVisitResultNode); -function asFullVisit(aNode) QI_node(aNode, Ci.nsINavHistoryFullVisitResultNode); function asContainer(aNode) QI_node(aNode, Ci.nsINavHistoryContainerResultNode); function asQuery(aNode) QI_node(aNode, Ci.nsINavHistoryQueryResultNode); @@ -104,7 +103,6 @@ this.PlacesUtils = { TOPIC_BOOKMARKS_RESTORE_FAILED: "bookmarks-restore-failed", asVisit: function(aNode) asVisit(aNode), - asFullVisit: function(aNode) asFullVisit(aNode), asContainer: function(aNode) asContainer(aNode), asQuery: function(aNode) asQuery(aNode), @@ -182,8 +180,7 @@ this.PlacesUtils = { */ nodeIsVisit: function PU_nodeIsVisit(aNode) { var type = aNode.type; - return type == Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT || - type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FULL_VISIT; + return type == Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT; }, /** @@ -193,8 +190,7 @@ this.PlacesUtils = { * @returns true if the node is a URL item, false otherwise */ uriTypes: [Ci.nsINavHistoryResultNode.RESULT_TYPE_URI, - Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT, - Ci.nsINavHistoryResultNode.RESULT_TYPE_FULL_VISIT], + Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT], nodeIsURI: function PU_nodeIsURI(aNode) { return this.uriTypes.indexOf(aNode.type) != -1; }, diff --git a/toolkit/components/places/nsINavHistoryService.idl b/toolkit/components/places/nsINavHistoryService.idl index 977f2400fed..8409986a5c1 100644 --- a/toolkit/components/places/nsINavHistoryService.idl +++ b/toolkit/components/places/nsINavHistoryService.idl @@ -51,10 +51,15 @@ interface nsINavHistoryResultNode : nsISupports */ const unsigned long RESULT_TYPE_URI = 0; // nsINavHistoryResultNode const unsigned long RESULT_TYPE_VISIT = 1; // nsINavHistoryVisitResultNode - const unsigned long RESULT_TYPE_FULL_VISIT = 2; // nsINavHistoryFullVisitResultNode + + // Full visit nodes are deprecated and unsupported. + // This line exists just to avoid reusing the value: + // const unsigned long RESULT_TYPE_FULL_VISIT = 2; // nsINavHistoryFullVisitResultNode + // Dynamic containers are deprecated and unsupported. - // This const exists just to avoid reusing the value. - const unsigned long RESULT_TYPE_DYNAMIC_CONTAINER = 4; // nsINavHistoryContainerResultNode + // This const exists just to avoid reusing the value: + // const unsigned long RESULT_TYPE_DYNAMIC_CONTAINER = 4; // nsINavHistoryContainerResultNode + const unsigned long RESULT_TYPE_QUERY = 5; // nsINavHistoryQueryResultNode const unsigned long RESULT_TYPE_FOLDER = 6; // nsINavHistoryQueryResultNode const unsigned long RESULT_TYPE_SEPARATOR = 7; // nsINavHistoryResultNode @@ -165,33 +170,6 @@ interface nsINavHistoryVisitResultNode : nsINavHistoryResultNode }; -/** - * This structure will be returned when you request RESULT_TYPE_FULL_VISIT in - * the query options. This includes uncommonly used information about each - * visit. - */ -[scriptable, uuid(c49fd9d5-56e2-43eb-932c-f933f28cba85)] -interface nsINavHistoryFullVisitResultNode : nsINavHistoryVisitResultNode -{ - /** - * This indicates the visit ID of the visit. - */ - readonly attribute long long visitId; - - /** - * This indicates the referring visit ID of the visit. The referrer should - * have the same sessionId. - */ - readonly attribute long long referringVisitId; - - /** - * Indicates the transition type of the visit. - * One of nsINavHistoryService.TRANSITION_* - */ - readonly attribute long transitionType; -}; - - /** * Base class for container results. This includes all types of groupings. * Bookmark folders and places queries will be QueryResultNodes which extends diff --git a/toolkit/components/places/nsNavHistoryResult.cpp b/toolkit/components/places/nsNavHistoryResult.cpp index d519c603117..10530862780 100644 --- a/toolkit/components/places/nsNavHistoryResult.cpp +++ b/toolkit/components/places/nsNavHistoryResult.cpp @@ -302,24 +302,6 @@ nsNavHistoryVisitResultNode::nsNavHistoryVisitResultNode( { } - -NS_IMPL_ISUPPORTS_INHERITED1(nsNavHistoryFullVisitResultNode, - nsNavHistoryVisitResultNode, - nsINavHistoryFullVisitResultNode) - -nsNavHistoryFullVisitResultNode::nsNavHistoryFullVisitResultNode( - const nsACString& aURI, const nsACString& aTitle, uint32_t aAccessCount, - PRTime aTime, const nsACString& aIconURI, int64_t aSession, - int64_t aVisitId, int64_t aReferringVisitId, int32_t aTransitionType) : - nsNavHistoryVisitResultNode(aURI, aTitle, aAccessCount, aTime, aIconURI, - aSession), - mVisitId(aVisitId), - mReferringVisitId(aReferringVisitId), - mTransitionType(aTransitionType) -{ -} - - NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsNavHistoryContainerResultNode, nsNavHistoryResultNode) NS_IMPL_CYCLE_COLLECTION_UNLINK(mResult) NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildren) diff --git a/toolkit/components/places/nsNavHistoryResult.h b/toolkit/components/places/nsNavHistoryResult.h index b2f216681c0..d71fb8f7758 100644 --- a/toolkit/components/places/nsNavHistoryResult.h +++ b/toolkit/components/places/nsNavHistoryResult.h @@ -303,8 +303,7 @@ public: } static bool IsTypeURI(uint32_t type) { return (type == nsINavHistoryResultNode::RESULT_TYPE_URI || - type == nsINavHistoryResultNode::RESULT_TYPE_VISIT || - type == nsINavHistoryResultNode::RESULT_TYPE_FULL_VISIT); + type == nsINavHistoryResultNode::RESULT_TYPE_VISIT); } bool IsURI() { uint32_t type; @@ -312,8 +311,7 @@ public: return IsTypeURI(type); } static bool IsTypeVisit(uint32_t type) { - return (type == nsINavHistoryResultNode::RESULT_TYPE_VISIT || - type == nsINavHistoryResultNode::RESULT_TYPE_FULL_VISIT); + return type == nsINavHistoryResultNode::RESULT_TYPE_VISIT; } bool IsVisit() { uint32_t type; @@ -384,7 +382,7 @@ public: bool mHidden; // Transition type used when this node represents a single visit. - int32_t mTransitionType; + uint32_t mTransitionType; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResultNode, NS_NAVHISTORYRESULTNODE_IID) @@ -416,39 +414,6 @@ public: }; -// nsNavHistoryFullVisitResultNode - -#define NS_IMPLEMENT_FULLVISITRESULT \ - NS_IMPLEMENT_VISITRESULT \ - NS_IMETHOD GetVisitId(int64_t *aVisitId) \ - { *aVisitId = mVisitId; return NS_OK; } \ - NS_IMETHOD GetReferringVisitId(int64_t *aReferringVisitId) \ - { *aReferringVisitId = mReferringVisitId; return NS_OK; } \ - NS_IMETHOD GetTransitionType(int32_t *aTransitionType) \ - { *aTransitionType = mTransitionType; return NS_OK; } - -class nsNavHistoryFullVisitResultNode : public nsNavHistoryVisitResultNode, - public nsINavHistoryFullVisitResultNode -{ -public: - nsNavHistoryFullVisitResultNode( - const nsACString& aURI, const nsACString& aTitle, uint32_t aAccessCount, - PRTime aTime, const nsACString& aIconURI, int64_t aSession, - int64_t aVisitId, int64_t aReferringVisitId, int32_t aTransitionType); - - NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_COMMON_RESULTNODE_TO_BASE - NS_IMETHOD GetType(uint32_t* type) - { *type = nsNavHistoryResultNode::RESULT_TYPE_FULL_VISIT; return NS_OK; } - NS_IMPLEMENT_FULLVISITRESULT - -public: - int64_t mVisitId; - int64_t mReferringVisitId; - int32_t mTransitionType; -}; - - // nsNavHistoryContainerResultNode // // This is the base class for all nodes that can have children. It is diff --git a/tools/profiler/JSCustomObjectBuilder.cpp b/tools/profiler/JSCustomObjectBuilder.cpp index 741ebf75515..66d501e1b24 100644 --- a/tools/profiler/JSCustomObjectBuilder.cpp +++ b/tools/profiler/JSCustomObjectBuilder.cpp @@ -208,7 +208,7 @@ operator<<(std::ostream& stream, JSCustomArray* entry) { bool needsComma = false; stream << "["; - for (int i = 0; i < entry->mValues.Length(); i++) { + for (size_t i = 0; i < entry->mValues.Length(); i++) { if (needsComma) { stream << ","; } diff --git a/tools/profiler/Makefile.in b/tools/profiler/Makefile.in index 009ffb69bf8..e5e615e2bff 100644 --- a/tools/profiler/Makefile.in +++ b/tools/profiler/Makefile.in @@ -37,6 +37,9 @@ LIBRARY_NAME = profiler EXPORT_LIBRARY = 1 LIBXUL_LIBRARY = 1 IS_COMPONENT = 1 +ifndef _MSC_VER +FAIL_ON_WARNINGS = 1 +endif # !_MSC_VER CPPSRCS = \ nsProfilerFactory.cpp \ diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index 6acf8a1ec1c..c39e04f6c48 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -820,11 +820,6 @@ void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample) // Start with the current function. StackWalkCallback(aSample->pc, aSample->sp, &array); - void *platformData = nullptr; -#ifdef XP_WIN - platformData = aSample->context; -#endif - uint32_t maxFrames = array.size - array.count; #ifdef XP_MACOSX pthread_t pt = GetProfiledThread(platform_data()); @@ -837,6 +832,11 @@ void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample) maxFrames, &array, reinterpret_cast(aSample->fp), stackEnd); #else + void *platformData = nullptr; +#ifdef XP_WIN + platformData = aSample->context; +#endif // XP_WIN + nsresult rv = NS_StackWalk(StackWalkCallback, /* skipFrames */ 0, maxFrames, &array, thread, platformData); #endif @@ -844,7 +844,7 @@ void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample) aProfile.addTag(ProfileEntry('s', "(root)")); ProfileStack* stack = aProfile.GetStack(); - int pseudoStackPos = 0; + uint32_t pseudoStackPos = 0; /* We have two stacks, the native C stack we extracted from unwinding, * and the pseudostack we managed during execution. We want to consolidate diff --git a/xpfe/appshell/src/nsXULWindow.cpp b/xpfe/appshell/src/nsXULWindow.cpp index e4e05f16ea1..194d80d9423 100644 --- a/xpfe/appshell/src/nsXULWindow.cpp +++ b/xpfe/appshell/src/nsXULWindow.cpp @@ -1494,8 +1494,8 @@ NS_IMETHODIMP nsXULWindow::SavePersistentAttributes() nsCOMPtr ownerDoc; docShellElement->GetOwnerDocument(getter_AddRefs(ownerDoc)); ownerXULDoc = do_QueryInterface(ownerDoc); - nsCOMPtr XULElement(do_QueryInterface(docShellElement)); - if (XULElement && XULElement->IsXUL()) + nsCOMPtr XULElement(do_QueryInterface(docShellElement)); + if (XULElement) XULElement->GetId(windowElementId); }