mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Merge inbound to m-c a=merge
This commit is contained in:
commit
5d721ab157
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,6 +8,7 @@ TAGS
|
||||
tags
|
||||
ID
|
||||
.DS_Store*
|
||||
*.pdb
|
||||
|
||||
# Vim swap files.
|
||||
.*.sw[a-z]
|
||||
|
@ -145,34 +145,33 @@
|
||||
#endif
|
||||
@RESPATH@/components/accessibility.xpt
|
||||
#endif
|
||||
@RESPATH@/components/appshell.xpt
|
||||
@RESPATH@/components/appstartup.xpt
|
||||
@RESPATH@/components/autocomplete.xpt
|
||||
@RESPATH@/components/autoconfig.xpt
|
||||
@RESPATH@/components/browsercompsbase.xpt
|
||||
@RESPATH@/components/browser-element.xpt
|
||||
@RESPATH@/components/browser-feeds.xpt
|
||||
@RESPATH@/components/caps.xpt
|
||||
@RESPATH@/components/chardet.xpt
|
||||
@RESPATH@/components/chrome.xpt
|
||||
@RESPATH@/components/commandhandler.xpt
|
||||
@RESPATH@/components/commandlines.xpt
|
||||
@RESPATH@/components/compartments.xpt
|
||||
@RESPATH@/components/composer.xpt
|
||||
@RESPATH@/components/content_events.xpt
|
||||
@RESPATH@/components/content_html.xpt
|
||||
@RESPATH@/components/content_xslt.xpt
|
||||
@RESPATH@/components/cookie.xpt
|
||||
@RESPATH@/components/devtools_security.xpt
|
||||
@RESPATH@/components/directory.xpt
|
||||
@RESPATH@/components/diskspacewatcher.xpt
|
||||
@RESPATH@/components/docshell.xpt
|
||||
@RESPATH@/components/dom.xpt
|
||||
@RESPATH@/components/dom_activities.xpt
|
||||
@RESPATH@/components/dom_apps.xpt
|
||||
@RESPATH@/components/dom_audiochannel.xpt
|
||||
@RESPATH@/components/dom_base.xpt
|
||||
@RESPATH@/components/dom_system.xpt
|
||||
@BINPATH@/components/appshell.xpt
|
||||
@BINPATH@/components/appstartup.xpt
|
||||
@BINPATH@/components/autocomplete.xpt
|
||||
@BINPATH@/components/autoconfig.xpt
|
||||
@BINPATH@/components/browsercompsbase.xpt
|
||||
@BINPATH@/components/browser-element.xpt
|
||||
@BINPATH@/components/browser-feeds.xpt
|
||||
@BINPATH@/components/caps.xpt
|
||||
@BINPATH@/components/chardet.xpt
|
||||
@BINPATH@/components/chrome.xpt
|
||||
@BINPATH@/components/commandhandler.xpt
|
||||
@BINPATH@/components/commandlines.xpt
|
||||
@BINPATH@/components/composer.xpt
|
||||
@BINPATH@/components/content_events.xpt
|
||||
@BINPATH@/components/content_html.xpt
|
||||
@BINPATH@/components/content_xslt.xpt
|
||||
@BINPATH@/components/cookie.xpt
|
||||
@BINPATH@/components/devtools_security.xpt
|
||||
@BINPATH@/components/directory.xpt
|
||||
@BINPATH@/components/diskspacewatcher.xpt
|
||||
@BINPATH@/components/docshell.xpt
|
||||
@BINPATH@/components/dom.xpt
|
||||
@BINPATH@/components/dom_activities.xpt
|
||||
@BINPATH@/components/dom_apps.xpt
|
||||
@BINPATH@/components/dom_audiochannel.xpt
|
||||
@BINPATH@/components/dom_base.xpt
|
||||
@BINPATH@/components/dom_system.xpt
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@RESPATH@/components/dom_wifi.xpt
|
||||
@RESPATH@/components/dom_system_gonk.xpt
|
||||
@ -326,6 +325,7 @@
|
||||
@RESPATH@/components/toolkit_finalizationwitness.xpt
|
||||
@RESPATH@/components/toolkit_formautofill.xpt
|
||||
@RESPATH@/components/toolkit_osfile.xpt
|
||||
@RESPATH@/components/toolkit_perfmonitoring.xpt
|
||||
@RESPATH@/components/toolkit_xulstore.xpt
|
||||
@RESPATH@/components/toolkitprofile.xpt
|
||||
#ifdef MOZ_ENABLE_XREMOTE
|
||||
|
@ -3779,8 +3779,7 @@
|
||||
};
|
||||
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
|
||||
let event = gContextMenuContentData.event;
|
||||
let pos = browser.mapScreenCoordinatesFromContent(event.screenX, event.screenY);
|
||||
popup.openPopupAtScreen(pos.x, pos.y, true);
|
||||
popup.openPopupAtScreen(event.screenX, event.screenY, true);
|
||||
break;
|
||||
}
|
||||
case "DOMWebNotificationClicked": {
|
||||
|
@ -327,7 +327,7 @@ function waitForEvents(event)
|
||||
if (painted && loaded) {
|
||||
subwindow.removeEventListener("MozAfterPaint", waitForEvents, false);
|
||||
subwindow.onload = null;
|
||||
startTest();
|
||||
SimpleTest.waitForFocus(startTest, subwindow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
let AddonManager = Cu.import("resource://gre/modules/AddonManager.jsm", {}).AddonManager;
|
||||
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
|
||||
let AddonWatcher = Cu.import("resource://gre/modules/AddonWatcher.jsm", {}).AddonWatcher;
|
||||
|
||||
const ADDON_TYPE_SERVICE = "service";
|
||||
const ID_SUFFIX = "@services.mozilla.org";
|
||||
|
@ -180,7 +180,6 @@
|
||||
@RESPATH@/components/chrome.xpt
|
||||
@RESPATH@/components/commandhandler.xpt
|
||||
@RESPATH@/components/commandlines.xpt
|
||||
@RESPATH@/components/compartments.xpt
|
||||
@RESPATH@/components/composer.xpt
|
||||
@RESPATH@/components/content_events.xpt
|
||||
@RESPATH@/components/content_html.xpt
|
||||
@ -328,6 +327,7 @@
|
||||
@RESPATH@/components/toolkit_finalizationwitness.xpt
|
||||
@RESPATH@/components/toolkit_formautofill.xpt
|
||||
@RESPATH@/components/toolkit_osfile.xpt
|
||||
@RESPATH@/components/toolkit_perfmonitoring.xpt
|
||||
@RESPATH@/components/toolkit_xulstore.xpt
|
||||
@RESPATH@/components/toolkitprofile.xpt
|
||||
#ifdef MOZ_ENABLE_XREMOTE
|
||||
|
@ -75,7 +75,7 @@ static RedirEntry kRedirMap[] = {
|
||||
nsIAboutModule::ALLOW_SCRIPT
|
||||
},
|
||||
{
|
||||
"compartments", "chrome://global/content/aboutCompartments.xhtml",
|
||||
"performance", "chrome://global/content/aboutPerformance.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT
|
||||
},
|
||||
{
|
||||
|
@ -166,9 +166,8 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "buildconfig", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "license", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "neterror", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "compartments", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "memory", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "compartments", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "performance", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "addons", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "newaddon", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "support", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
/* static functions */
|
||||
const DEBUG = false;
|
||||
const REQUEST_CPU_LOCK_TIMEOUT = 10 * 1000; // 10 seconds.
|
||||
|
||||
function debug(aStr) {
|
||||
if (DEBUG)
|
||||
@ -18,8 +19,15 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gPowerManagerService",
|
||||
"@mozilla.org/power/powermanagerservice;1",
|
||||
"nsIPowerManagerService");
|
||||
|
||||
function AlarmsManager() {
|
||||
debug("Constructor");
|
||||
|
||||
// A <requestId, {cpuLock, timer}> map.
|
||||
this._cpuLockDict = new Map();
|
||||
}
|
||||
|
||||
AlarmsManager.prototype = {
|
||||
@ -71,8 +79,10 @@ AlarmsManager.prototype = {
|
||||
data = JSON.parse(Cu.evalInSandbox("JSON.stringify(data)", sandbox));
|
||||
}
|
||||
let request = this.createRequest();
|
||||
let requestId = this.getRequestId(request);
|
||||
this._lockCpuForRequest(requestId);
|
||||
this._cpmm.sendAsyncMessage("AlarmsManager:Add",
|
||||
{ requestId: this.getRequestId(request),
|
||||
{ requestId: requestId,
|
||||
date: aDate,
|
||||
ignoreTimezone: isIgnoreTimezone,
|
||||
data: data,
|
||||
@ -111,6 +121,7 @@ AlarmsManager.prototype = {
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "AlarmsManager:Add:Return:OK":
|
||||
this._unlockCpuForRequest(json.requestId);
|
||||
Services.DOMRequest.fireSuccess(request, json.id);
|
||||
break;
|
||||
|
||||
@ -131,6 +142,7 @@ AlarmsManager.prototype = {
|
||||
break;
|
||||
|
||||
case "AlarmsManager:Add:Return:KO":
|
||||
this._unlockCpuForRequest(json.requestId);
|
||||
Services.DOMRequest.fireError(request, json.errorMsg);
|
||||
break;
|
||||
|
||||
@ -172,6 +184,44 @@ AlarmsManager.prototype = {
|
||||
uninit: function uninit() {
|
||||
debug("uninit()");
|
||||
},
|
||||
|
||||
_lockCpuForRequest: function (aRequestId) {
|
||||
if (this._cpuLockDict.has(aRequestId)) {
|
||||
debug('Cpu wakelock for request ' + aRequestId + ' has been acquired. ' +
|
||||
'You may call this function repeatedly or requestId is collision.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Acquire a lock for given request and save for lookup lately.
|
||||
debug('Acquire cpu lock for request ' + aRequestId);
|
||||
let cpuLockInfo = {
|
||||
cpuLock: gPowerManagerService.newWakeLock("cpu"),
|
||||
timer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer)
|
||||
};
|
||||
this._cpuLockDict.set(aRequestId, cpuLockInfo);
|
||||
|
||||
// Start a timer to prevent from non-responding request.
|
||||
cpuLockInfo.timer.initWithCallback(() => {
|
||||
debug('Request timeout! Release the cpu lock');
|
||||
this._unlockCpuForRequest(aRequestId);
|
||||
}, REQUEST_CPU_LOCK_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
|
||||
_unlockCpuForRequest: function(aRequestId) {
|
||||
let cpuLockInfo = this._cpuLockDict.get(aRequestId);
|
||||
if (!cpuLockInfo) {
|
||||
debug('The cpu lock for requestId ' + aRequestId + ' is either invalid ' +
|
||||
'or has been released.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Release the cpu lock and cancel the timer.
|
||||
debug('Release the cpu lock for ' + aRequestId);
|
||||
cpuLockInfo.cpuLock.unlock();
|
||||
cpuLockInfo.timer.cancel();
|
||||
this._cpuLockDict.delete(aRequestId);
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AlarmsManager])
|
||||
|
@ -884,8 +884,7 @@ nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
|
||||
|
||||
// Don't show remote iframe if we are waiting for the completion of reflow.
|
||||
if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
nsIntPoint chromeDisp = aFrame->GetChromeDisplacement();
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1383,6 +1382,12 @@ nsFrameLoader::StartDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
// If the TabParent has installed any event listeners on the window, this is
|
||||
// its last chance to remove them while we're still in the document.
|
||||
if (mRemoteBrowser) {
|
||||
mRemoteBrowser->RemoveWindowListeners();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
bool dynamicSubframeRemoval = false;
|
||||
if (mOwnerContent) {
|
||||
@ -2058,8 +2063,7 @@ nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame *aIFrame)
|
||||
ScreenIntSize size = aIFrame->GetSubdocumentSize();
|
||||
nsIntRect dimensions;
|
||||
NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
|
||||
nsIntPoint chromeDisp = aIFrame->GetChromeDisplacement();
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -229,6 +229,9 @@ public:
|
||||
void ActivateUpdateHitRegion();
|
||||
void DeactivateUpdateHitRegion();
|
||||
|
||||
// Properly retrieves documentSize of any subdocument type.
|
||||
nsresult GetWindowDimensions(nsIntRect& aRect);
|
||||
|
||||
private:
|
||||
|
||||
void SetOwnerContent(mozilla::dom::Element* aContent);
|
||||
@ -284,9 +287,6 @@ private:
|
||||
nsresult MaybeCreateDocShell();
|
||||
nsresult EnsureMessageManager();
|
||||
|
||||
// Properly retrieves documentSize of any subdocument type.
|
||||
nsresult GetWindowDimensions(nsIntRect& aRect);
|
||||
|
||||
// Updates the subdocument position and size. This gets called only
|
||||
// when we have our own in-process DocShell.
|
||||
void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame);
|
||||
|
@ -1265,15 +1265,6 @@ DOMInterfaces = {
|
||||
'wrapperCache': False,
|
||||
}],
|
||||
|
||||
'VRFieldOfView': {
|
||||
'wrapperCache': False,
|
||||
},
|
||||
|
||||
'VRFieldOfViewReadOnly': {
|
||||
'concrete': False,
|
||||
'wrapperCache': False,
|
||||
},
|
||||
|
||||
'VRDevice': {
|
||||
'concrete': False
|
||||
},
|
||||
|
@ -694,6 +694,10 @@ void HTMLMediaElement::AbortExistingLoads()
|
||||
mSuspendedForPreloadNone = false;
|
||||
mDownloadSuspendedByCache = false;
|
||||
mMediaInfo = MediaInfo();
|
||||
mIsEncrypted = false;
|
||||
#ifdef MOZ_EME
|
||||
mPendingEncryptedInitData.mInitDatas.Clear();
|
||||
#endif // MOZ_EME
|
||||
mSourcePointer = nullptr;
|
||||
mLastNextFrameStatus = NEXT_FRAME_UNINITIALIZED;
|
||||
|
||||
@ -3088,7 +3092,11 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
|
||||
nsAutoPtr<const MetadataTags> aTags)
|
||||
{
|
||||
mMediaInfo = *aInfo;
|
||||
mIsEncrypted = aInfo->IsEncrypted();
|
||||
mIsEncrypted = aInfo->IsEncrypted()
|
||||
#ifdef MOZ_EME
|
||||
|| mPendingEncryptedInitData.IsEncrypted()
|
||||
#endif // MOZ_EME
|
||||
;
|
||||
mTags = aTags.forget();
|
||||
mLoadedDataFired = false;
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||
@ -3115,8 +3123,12 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
DispatchEncrypted(aInfo->mCrypto.mInitData, aInfo->mCrypto.mType);
|
||||
#endif
|
||||
// Dispatch a distinct 'encrypted' event for each initData we have.
|
||||
for (const auto& initData : mPendingEncryptedInitData.mInitDatas) {
|
||||
DispatchEncrypted(initData.mInitData, initData.mType);
|
||||
}
|
||||
mPendingEncryptedInitData.mInitDatas.Clear();
|
||||
#endif // MOZ_EME
|
||||
}
|
||||
|
||||
// Expose the tracks to JS directly.
|
||||
@ -4479,6 +4491,13 @@ void
|
||||
HTMLMediaElement::DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
|
||||
const nsAString& aInitDataType)
|
||||
{
|
||||
if (mReadyState == nsIDOMHTMLMediaElement::HAVE_NOTHING) {
|
||||
// Ready state not HAVE_METADATA (yet), don't dispatch encrypted now.
|
||||
// Queueing for later dispatch in MetadataLoaded.
|
||||
mPendingEncryptedInitData.AddInitData(aInitDataType, aInitData);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<MediaEncryptedEvent> event;
|
||||
if (IsCORSSameOrigin()) {
|
||||
event = MediaEncryptedEvent::Constructor(this, aInitDataType, aInitData);
|
||||
|
@ -561,7 +561,6 @@ public:
|
||||
void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
|
||||
const nsAString& aInitDataType) override;
|
||||
|
||||
|
||||
bool IsEventAttributeName(nsIAtom* aName) override;
|
||||
|
||||
// Returns the principal of the "top level" document; the origin displayed
|
||||
@ -1322,6 +1321,11 @@ protected:
|
||||
// True if the media has encryption information.
|
||||
bool mIsEncrypted;
|
||||
|
||||
#ifdef MOZ_EME
|
||||
// Init Data that needs to be sent in 'encrypted' events in MetadataLoaded().
|
||||
EncryptionInfo mPendingEncryptedInitData;
|
||||
#endif // MOZ_EME
|
||||
|
||||
// True if the media's channel's download has been suspended.
|
||||
bool mDownloadSuspendedByCache;
|
||||
|
||||
|
@ -2026,8 +2026,8 @@ TabChild::RecvUpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
|
||||
mOrientation = orientation;
|
||||
ScreenIntSize oldScreenSize = mInnerSize;
|
||||
mInnerSize = size;
|
||||
mWidget->Resize(0, 0, size.width, size.height,
|
||||
true);
|
||||
mWidget->Resize(rect.x + chromeDisp.x, rect.y + chromeDisp.y, size.width, size.height,
|
||||
true);
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
|
||||
baseWin->SetPositionAndSize(0, 0, size.width, size.height,
|
||||
|
@ -80,6 +80,7 @@
|
||||
#include "nsICancelable.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "nsILoginManagerPrompter.h"
|
||||
#include "nsPIWindowRoot.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla::dom;
|
||||
@ -267,6 +268,7 @@ TabParent::TabParent(nsIContentParent* aManager,
|
||||
, mDefaultScale(0)
|
||||
, mShown(false)
|
||||
, mUpdatedDimensions(false)
|
||||
, mChromeOffset(0, 0)
|
||||
, mManager(aManager)
|
||||
, mMarkedDestroying(false)
|
||||
, mIsDestroyed(false)
|
||||
@ -325,10 +327,36 @@ TabParent::CacheFrameLoader(nsFrameLoader* aFrameLoader)
|
||||
void
|
||||
TabParent::SetOwnerElement(Element* aElement)
|
||||
{
|
||||
// If we held previous content then unregister for its events.
|
||||
RemoveWindowListeners();
|
||||
|
||||
// Update to the new content, and register to listen for events from it.
|
||||
mFrameElement = aElement;
|
||||
if (mFrameElement && mFrameElement->OwnerDoc()->GetWindow()) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = mFrameElement->OwnerDoc()->GetWindow();
|
||||
nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot();
|
||||
if (eventTarget) {
|
||||
eventTarget->AddEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
|
||||
this, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
TryCacheDPIAndScale();
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::RemoveWindowListeners()
|
||||
{
|
||||
if (mFrameElement && mFrameElement->OwnerDoc()->GetWindow()) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = mFrameElement->OwnerDoc()->GetWindow();
|
||||
nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot();
|
||||
if (eventTarget) {
|
||||
eventTarget->RemoveEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
|
||||
this, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::GetAppType(nsAString& aOut)
|
||||
{
|
||||
@ -880,8 +908,7 @@ TabParent::RecvSetDimensions(const uint32_t& aFlags,
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
|
||||
const nsIntPoint& aChromeDisp)
|
||||
TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size)
|
||||
{
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
@ -889,15 +916,25 @@ TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
|
||||
hal::ScreenConfiguration config;
|
||||
hal::GetCurrentScreenConfiguration(&config);
|
||||
ScreenOrientation orientation = config.orientation();
|
||||
nsIntPoint chromeOffset = -LayoutDevicePixel::ToUntyped(GetChildProcessOffset());
|
||||
|
||||
if (!mUpdatedDimensions || mOrientation != orientation ||
|
||||
mDimensions != size || !mRect.IsEqualEdges(rect)) {
|
||||
mDimensions != size || !mRect.IsEqualEdges(rect) ||
|
||||
chromeOffset != mChromeOffset) {
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
nsIntRect contentRect = rect;
|
||||
if (widget) {
|
||||
contentRect.x += widget->GetClientOffset().x;
|
||||
contentRect.y += widget->GetClientOffset().y;
|
||||
}
|
||||
|
||||
mUpdatedDimensions = true;
|
||||
mRect = rect;
|
||||
mRect = contentRect;
|
||||
mDimensions = size;
|
||||
mOrientation = orientation;
|
||||
mChromeOffset = chromeOffset;
|
||||
|
||||
unused << SendUpdateDimensions(mRect, mDimensions, mOrientation, aChromeDisp);
|
||||
unused << SendUpdateDimensions(mRect, mDimensions, mOrientation, mChromeOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2740,6 +2777,27 @@ TabParent::DeallocPPluginWidgetParent(mozilla::plugins::PPluginWidgetParent* aAc
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TabParent::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsAutoString eventType;
|
||||
aEvent->GetType(eventType);
|
||||
|
||||
if (eventType.EqualsLiteral("MozUpdateWindowPos") && !mIsDestroyed) {
|
||||
// This event is sent when the widget moved. Therefore we only update
|
||||
// the position.
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
if (!frameLoader) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsIntRect windowDims;
|
||||
NS_ENSURE_SUCCESS(frameLoader->GetWindowDimensions(windowDims), NS_ERROR_FAILURE);
|
||||
UpdateDimensions(windowDims, mDimensions);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class FakeChannel final : public nsIChannel,
|
||||
public nsIAuthPromptCallback,
|
||||
public nsIInterfaceRequestor,
|
||||
|
@ -60,6 +60,7 @@ class Element;
|
||||
struct StructuredCloneData;
|
||||
|
||||
class TabParent final : public PBrowserParent
|
||||
, public nsIDOMEventListener
|
||||
, public nsITabParent
|
||||
, public nsIAuthPromptProvider
|
||||
, public nsISecureBrowserUI
|
||||
@ -73,6 +74,8 @@ class TabParent final : public PBrowserParent
|
||||
public:
|
||||
// nsITabParent
|
||||
NS_DECL_NSITABPARENT
|
||||
// nsIDOMEventListener interfaces
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
TabParent(nsIContentParent* aManager,
|
||||
const TabId& aTabId,
|
||||
@ -107,6 +110,8 @@ public:
|
||||
|
||||
void Destroy();
|
||||
|
||||
void RemoveWindowListeners();
|
||||
|
||||
virtual bool RecvMoveFocus(const bool& aForward) override;
|
||||
virtual bool RecvEvent(const RemoteDOMEvent& aEvent) override;
|
||||
virtual bool RecvReplyKeyEvent(const WidgetKeyboardEvent& aEvent) override;
|
||||
@ -225,8 +230,7 @@ public:
|
||||
// message-sending functions under a layer of indirection and
|
||||
// eating the return values
|
||||
void Show(const ScreenIntSize& size, bool aParentIsActive);
|
||||
void UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
|
||||
const nsIntPoint& chromeDisp);
|
||||
void UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size);
|
||||
void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
|
||||
void UIResolutionChanged();
|
||||
void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
|
||||
@ -427,6 +431,7 @@ protected:
|
||||
CSSToLayoutDeviceScale mDefaultScale;
|
||||
bool mShown;
|
||||
bool mUpdatedDimensions;
|
||||
nsIntPoint mChromeOffset;
|
||||
|
||||
private:
|
||||
already_AddRefed<nsFrameLoader> GetFrameLoader(bool aUseCachedFrameLoaderAfterDestroy = false) const;
|
||||
|
@ -136,11 +136,11 @@ public:
|
||||
|
||||
#ifdef MOZ_EME
|
||||
// Dispatches a "encrypted" event to the HTMLMediaElement, with the
|
||||
// provided init data.
|
||||
// provided init data. Actual dispatch may be delayed until HAVE_METADATA.
|
||||
// Main thread only.
|
||||
virtual void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
|
||||
const nsAString& aInitDataType) = 0;
|
||||
#endif
|
||||
#endif // MOZ_EME
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -105,16 +105,41 @@ public:
|
||||
|
||||
class EncryptionInfo {
|
||||
public:
|
||||
EncryptionInfo() : mIsEncrypted(false) {}
|
||||
struct InitData {
|
||||
template<typename AInitDatas>
|
||||
InitData(const nsAString& aType, AInitDatas&& aInitData)
|
||||
: mType(aType)
|
||||
, mInitData(Forward<AInitDatas>(aInitData))
|
||||
{
|
||||
}
|
||||
|
||||
// Encryption type to be passed to JS. Usually `cenc'.
|
||||
nsString mType;
|
||||
// Encryption type to be passed to JS. Usually `cenc'.
|
||||
nsString mType;
|
||||
|
||||
// Encryption data.
|
||||
nsTArray<uint8_t> mInitData;
|
||||
// Encryption data.
|
||||
nsTArray<uint8_t> mInitData;
|
||||
};
|
||||
typedef nsTArray<InitData> InitDatas;
|
||||
|
||||
// True if the stream has encryption metadata
|
||||
bool mIsEncrypted;
|
||||
bool IsEncrypted() const
|
||||
{
|
||||
return !mInitDatas.IsEmpty();
|
||||
}
|
||||
|
||||
template<typename AInitDatas>
|
||||
void AddInitData(const nsAString& aType, AInitDatas&& aInitData)
|
||||
{
|
||||
mInitDatas.AppendElement(InitData(aType, Forward<AInitDatas>(aInitData)));
|
||||
}
|
||||
|
||||
void AddInitData(const EncryptionInfo& aInfo)
|
||||
{
|
||||
mInitDatas.AppendElements(aInfo.mInitDatas);
|
||||
}
|
||||
|
||||
// One 'InitData' per encrypted buffer.
|
||||
InitDatas mInitDatas;
|
||||
};
|
||||
|
||||
class MediaInfo {
|
||||
@ -131,7 +156,7 @@ public:
|
||||
|
||||
bool IsEncrypted() const
|
||||
{
|
||||
return mCrypto.mIsEncrypted;
|
||||
return mCrypto.IsEncrypted();
|
||||
}
|
||||
|
||||
bool HasValidMedia() const
|
||||
|
@ -264,6 +264,34 @@ MP4Reader::Init(MediaDecoderReader* aCloneDonor)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
class DispatchKeyNeededEvent : public nsRunnable {
|
||||
public:
|
||||
DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder,
|
||||
nsTArray<uint8_t>& aInitData,
|
||||
const nsString& aInitDataType)
|
||||
: mDecoder(aDecoder)
|
||||
, mInitData(aInitData)
|
||||
, mInitDataType(aInitDataType)
|
||||
{
|
||||
}
|
||||
NS_IMETHOD Run() {
|
||||
// Note: Null check the owner, as the decoder could have been shutdown
|
||||
// since this event was dispatched.
|
||||
MediaDecoderOwner* owner = mDecoder->GetOwner();
|
||||
if (owner) {
|
||||
owner->DispatchEncrypted(mInitData, mInitDataType);
|
||||
}
|
||||
mDecoder = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsRefPtr<AbstractMediaDecoder> mDecoder;
|
||||
nsTArray<uint8_t> mInitData;
|
||||
nsString mInitDataType;
|
||||
};
|
||||
#endif // MOZ_EME
|
||||
|
||||
void MP4Reader::RequestCodecResource() {
|
||||
if (mVideo.mDecoder) {
|
||||
mVideo.mDecoder->AllocateMediaResources();
|
||||
@ -368,7 +396,7 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
|
||||
{
|
||||
MonitorAutoUnlock unlock(mDemuxerMonitor);
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mInfo.mCrypto.mIsEncrypted = mIsEncrypted = mCrypto.valid;
|
||||
mIsEncrypted = mCrypto.valid;
|
||||
}
|
||||
|
||||
// Remember that we've initialized the demuxer, so that if we're decoding
|
||||
@ -400,15 +428,21 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
|
||||
}
|
||||
}
|
||||
|
||||
if (mIsEncrypted) {
|
||||
if (mCrypto.valid) {
|
||||
nsTArray<uint8_t> initData;
|
||||
ExtractCryptoInitData(initData);
|
||||
if (initData.Length() == 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mInfo.mCrypto.mInitData = initData;
|
||||
mInfo.mCrypto.mType = NS_LITERAL_STRING("cenc");
|
||||
#ifdef MOZ_EME
|
||||
// Try and dispatch 'encrypted'. Won't go if ready state still HAVE_NOTHING.
|
||||
NS_DispatchToMainThread(
|
||||
new DispatchKeyNeededEvent(mDecoder, initData, NS_LITERAL_STRING("cenc")));
|
||||
#endif // MOZ_EME
|
||||
// Add init data to info, will get sent from HTMLMediaElement::MetadataLoaded
|
||||
// (i.e., when transitioning from HAVE_NOTHING to HAVE_METADATA).
|
||||
mInfo.mCrypto.AddInitData(NS_LITERAL_STRING("cenc"), Move(initData));
|
||||
}
|
||||
|
||||
// Get the duration, and report it to the decoder if we have it.
|
||||
|
@ -275,8 +275,6 @@ private:
|
||||
|
||||
layers::LayersBackend mLayersBackendType;
|
||||
|
||||
nsTArray<nsTArray<uint8_t>> mInitDataEncountered;
|
||||
|
||||
// True if we've read the streams' metadata.
|
||||
bool mDemuxerInitialized;
|
||||
|
||||
|
@ -1068,22 +1068,6 @@ MediaSourceReader::MaybeNotifyHaveData()
|
||||
IsSeeking(), haveAudio, haveVideo, ended);
|
||||
}
|
||||
|
||||
static void
|
||||
CombineEncryptionData(EncryptionInfo& aTo, const EncryptionInfo& aFrom)
|
||||
{
|
||||
if (!aFrom.mIsEncrypted) {
|
||||
return;
|
||||
}
|
||||
aTo.mIsEncrypted = true;
|
||||
|
||||
if (!aTo.mType.IsEmpty() && !aTo.mType.Equals(aFrom.mType)) {
|
||||
NS_WARNING("mismatched encryption types");
|
||||
}
|
||||
|
||||
aTo.mType = aFrom.mType;
|
||||
aTo.mInitData.AppendElements(aFrom.mInitData);
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
||||
{
|
||||
@ -1107,7 +1091,7 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
||||
const MediaInfo& info = GetAudioReader()->GetMediaInfo();
|
||||
MOZ_ASSERT(info.HasAudio());
|
||||
mInfo.mAudio = info.mAudio;
|
||||
CombineEncryptionData(mInfo.mCrypto, info.mCrypto);
|
||||
mInfo.mCrypto.AddInitData(info.mCrypto);
|
||||
MSE_DEBUG("audio reader=%p duration=%lld",
|
||||
mAudioSourceDecoder.get(),
|
||||
mAudioSourceDecoder->GetReader()->GetDecoder()->GetMediaDuration());
|
||||
@ -1120,7 +1104,7 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
||||
const MediaInfo& info = GetVideoReader()->GetMediaInfo();
|
||||
MOZ_ASSERT(info.HasVideo());
|
||||
mInfo.mVideo = info.mVideo;
|
||||
CombineEncryptionData(mInfo.mCrypto, info.mCrypto);
|
||||
mInfo.mCrypto.AddInitData(info.mCrypto);
|
||||
MSE_DEBUG("video reader=%p duration=%lld",
|
||||
GetVideoReader(),
|
||||
GetVideoReader()->GetDecoder()->GetMediaDuration());
|
||||
|
@ -664,6 +664,7 @@ var gEMETests = [
|
||||
"7e571d047e571d047e571d047e571d04" : "7e5744447e5744447e5744447e574444",
|
||||
},
|
||||
sessionType:"temporary",
|
||||
sessionCount:1,
|
||||
duration:1.60,
|
||||
},
|
||||
{
|
||||
@ -684,6 +685,7 @@ var gEMETests = [
|
||||
"7e571d047e571d047e571d047e571d04" : "7e5744447e5744447e5744447e574444",
|
||||
},
|
||||
sessionType:"temporary",
|
||||
sessionCount:1,
|
||||
crossOrigin:true,
|
||||
duration:1.60,
|
||||
},
|
||||
@ -714,6 +716,7 @@ var gEMETests = [
|
||||
"7e571d047e571d047e571d047e571d04" : "7e5744447e5744447e5744447e574444",
|
||||
},
|
||||
sessionType:"temporary",
|
||||
sessionCount:2,
|
||||
duration:1.60,
|
||||
},
|
||||
{
|
||||
@ -743,6 +746,7 @@ var gEMETests = [
|
||||
"7e571d047e571d047e571d047e571d04" : "7e5744447e5744447e5744447e574444",
|
||||
},
|
||||
sessionType:"temporary",
|
||||
sessionCount:2,
|
||||
crossOrigin:true,
|
||||
duration:1.60,
|
||||
},
|
||||
|
@ -48,11 +48,11 @@ function startTest(test, token)
|
||||
}
|
||||
);
|
||||
|
||||
var gotEncrypted = false;
|
||||
var gotEncrypted = 0;
|
||||
var gotPlaying = false;
|
||||
|
||||
v.addEventListener("encrypted", function(ev) {
|
||||
gotEncrypted = true;
|
||||
gotEncrypted += 1;
|
||||
});
|
||||
|
||||
v.addEventListener("playing", function () { gotPlaying = true; });
|
||||
@ -66,7 +66,9 @@ function startTest(test, token)
|
||||
v.addEventListener("ended", function(ev) {
|
||||
ok(true, TimeStamp(token) + " got ended event");
|
||||
|
||||
ok(gotEncrypted, TimeStamp(token) + " encrypted event should have fired");
|
||||
is(gotEncrypted, test.sessionCount,
|
||||
TimeStamp(token) + " encrypted events expected: " + test.sessionCount
|
||||
+ ", actual: " + gotEncrypted);
|
||||
ok(gotPlaying, TimeStamp(token) + " playing event should have fired");
|
||||
|
||||
ok(Math.abs(test.duration - v.duration) < 0.1,
|
||||
|
@ -11,6 +11,9 @@
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Turn off the authentication dialog blocking for this test.
|
||||
SpecialPowers.setIntPref("network.auth.allow-subresource-auth", 2)
|
||||
|
||||
var tests = [
|
||||
// Not the same origin no CORS asked for, should have silence
|
||||
{ url: "http://example.org:80/tests/dom/media/webaudio/test/small-shot.ogg",
|
||||
|
@ -790,7 +790,6 @@ NPBool nsPluginInstanceOwner::ConvertPointPuppet(PuppetWidget *widget,
|
||||
tabContentBounds.ScaleInverseRoundOut(scaleFactor);
|
||||
int32_t windowH = tabContentBounds.height + int(chromeSize.y);
|
||||
|
||||
// This is actually relative to window-chrome.
|
||||
nsPoint pluginPosition = AsNsPoint(pluginFrame->GetScreenRect().TopLeft());
|
||||
|
||||
// Convert (sourceX, sourceY) to 'real' (not PuppetWidget) screen space.
|
||||
@ -800,8 +799,8 @@ NPBool nsPluginInstanceOwner::ConvertPointPuppet(PuppetWidget *widget,
|
||||
nsPoint screenPoint;
|
||||
switch (sourceSpace) {
|
||||
case NPCoordinateSpacePlugin:
|
||||
screenPoint = sourcePoint + pluginFrame->GetContentRectRelativeToSelf().TopLeft() +
|
||||
chromeSize + pluginPosition + windowPosition;
|
||||
screenPoint = sourcePoint + pluginPosition +
|
||||
pluginFrame->GetContentRectRelativeToSelf().TopLeft() / nsPresContext::AppUnitsPerCSSPixel();
|
||||
break;
|
||||
case NPCoordinateSpaceWindow:
|
||||
screenPoint = nsPoint(sourcePoint.x, windowH-sourcePoint.y) +
|
||||
@ -824,8 +823,8 @@ NPBool nsPluginInstanceOwner::ConvertPointPuppet(PuppetWidget *widget,
|
||||
nsPoint destPoint;
|
||||
switch (destSpace) {
|
||||
case NPCoordinateSpacePlugin:
|
||||
destPoint = screenPoint - pluginFrame->GetContentRectRelativeToSelf().TopLeft() -
|
||||
chromeSize - pluginPosition - windowPosition;
|
||||
destPoint = screenPoint - pluginPosition -
|
||||
pluginFrame->GetContentRectRelativeToSelf().TopLeft() / nsPresContext::AppUnitsPerCSSPixel();
|
||||
break;
|
||||
case NPCoordinateSpaceWindow:
|
||||
destPoint = screenPoint - windowPosition;
|
||||
|
@ -17,30 +17,109 @@ using namespace mozilla::gfx;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
VRFieldOfView*
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRFieldOfViewReadOnly, mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRFieldOfViewReadOnly, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRFieldOfViewReadOnly, Release)
|
||||
|
||||
JSObject*
|
||||
VRFieldOfViewReadOnly::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return VRFieldOfViewReadOnlyBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
already_AddRefed<VRFieldOfView>
|
||||
VRFieldOfView::Constructor(const GlobalObject& aGlobal, const VRFieldOfViewInit& aParams,
|
||||
ErrorResult& aRV)
|
||||
{
|
||||
return new VRFieldOfView(aParams.mUpDegrees, aParams.mRightDegrees,
|
||||
aParams.mDownDegrees, aParams.mLeftDegrees);
|
||||
nsRefPtr<VRFieldOfView> fov =
|
||||
new VRFieldOfView(aGlobal.GetAsSupports(),
|
||||
aParams.mUpDegrees, aParams.mRightDegrees,
|
||||
aParams.mDownDegrees, aParams.mLeftDegrees);
|
||||
return fov.forget();
|
||||
}
|
||||
|
||||
VRFieldOfView*
|
||||
already_AddRefed<VRFieldOfView>
|
||||
VRFieldOfView::Constructor(const GlobalObject& aGlobal,
|
||||
double aUpDegrees, double aRightDegrees,
|
||||
double aDownDegrees, double aLeftDegrees,
|
||||
ErrorResult& aRV)
|
||||
{
|
||||
return new VRFieldOfView(aUpDegrees, aRightDegrees, aDownDegrees,
|
||||
aLeftDegrees);
|
||||
nsRefPtr<VRFieldOfView> fov =
|
||||
new VRFieldOfView(aGlobal.GetAsSupports(),
|
||||
aUpDegrees, aRightDegrees, aDownDegrees,
|
||||
aLeftDegrees);
|
||||
return fov.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
JSObject*
|
||||
VRFieldOfView::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aReflector)
|
||||
JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return VRFieldOfViewBinding::Wrap(aCx, this, aGivenProto, aReflector);
|
||||
return VRFieldOfViewBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VREyeParameters, mParent, mMinFOV, mMaxFOV, mRecFOV, mCurFOV, mEyeTranslation, mRenderRect)
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VREyeParameters, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VREyeParameters, Release)
|
||||
|
||||
VREyeParameters::VREyeParameters(nsISupports* aParent,
|
||||
const gfx::VRFieldOfView& aMinFOV,
|
||||
const gfx::VRFieldOfView& aMaxFOV,
|
||||
const gfx::VRFieldOfView& aRecFOV,
|
||||
const gfx::Point3D& aEyeTranslation,
|
||||
const gfx::VRFieldOfView& aCurFOV,
|
||||
const gfx::IntRect& aRenderRect)
|
||||
: mParent(aParent)
|
||||
{
|
||||
mMinFOV = new VRFieldOfView(aParent, aMinFOV);
|
||||
mMaxFOV = new VRFieldOfView(aParent, aMaxFOV);
|
||||
mRecFOV = new VRFieldOfView(aParent, aRecFOV);
|
||||
mCurFOV = new VRFieldOfView(aParent, aCurFOV);
|
||||
|
||||
mEyeTranslation = new DOMPoint(aParent, aEyeTranslation.x, aEyeTranslation.y, aEyeTranslation.z, 0.0);
|
||||
mRenderRect = new DOMRect(aParent, aRenderRect.x, aRenderRect.y, aRenderRect.width, aRenderRect.height);
|
||||
}
|
||||
|
||||
VRFieldOfView*
|
||||
VREyeParameters::MinimumFieldOfView()
|
||||
{
|
||||
return mMinFOV;
|
||||
}
|
||||
|
||||
VRFieldOfView*
|
||||
VREyeParameters::MaximumFieldOfView()
|
||||
{
|
||||
return mMaxFOV;
|
||||
}
|
||||
|
||||
VRFieldOfView*
|
||||
VREyeParameters::RecommendedFieldOfView()
|
||||
{
|
||||
return mRecFOV;
|
||||
}
|
||||
|
||||
VRFieldOfView*
|
||||
VREyeParameters::CurrentFieldOfView()
|
||||
{
|
||||
return mCurFOV;
|
||||
}
|
||||
|
||||
DOMPoint*
|
||||
VREyeParameters::EyeTranslation()
|
||||
{
|
||||
return mEyeTranslation;
|
||||
}
|
||||
|
||||
DOMRect*
|
||||
VREyeParameters::RenderRect()
|
||||
{
|
||||
return mRenderRect;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
VREyeParameters::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return VREyeParametersBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRPositionState, mParent)
|
||||
@ -126,37 +205,8 @@ PositionSensorVRDevice::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenP
|
||||
return PositionSensorVRDeviceBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
static void
|
||||
ReleaseHMDInfoRef(void *, nsIAtom*, void *aPropertyValue, void *)
|
||||
{
|
||||
if (aPropertyValue) {
|
||||
static_cast<VRHMDInfo*>(aPropertyValue)->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HMDVRDevice::XxxToggleElementVR(Element& aElement)
|
||||
{
|
||||
VRHMDInfo* hmdPtr = static_cast<VRHMDInfo*>(aElement.GetProperty(nsGkAtoms::vr_state));
|
||||
if (hmdPtr) {
|
||||
aElement.DeleteProperty(nsGkAtoms::vr_state);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<VRHMDInfo> hmdRef = mHMD;
|
||||
aElement.SetProperty(nsGkAtoms::vr_state, hmdRef.forget().take(),
|
||||
ReleaseHMDInfoRef,
|
||||
true);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
gfx::VRHMDInfo::Eye
|
||||
EyeToEye(const VREye& aEye)
|
||||
{
|
||||
return aEye == VREye::Left ? gfx::VRHMDInfo::Eye_Left : gfx::VRHMDInfo::Eye_Right;
|
||||
}
|
||||
|
||||
class HMDInfoVRDevice : public HMDVRDevice
|
||||
{
|
||||
public:
|
||||
@ -164,9 +214,21 @@ public:
|
||||
: HMDVRDevice(aParent, aHMD)
|
||||
{
|
||||
// XXX TODO use real names/IDs
|
||||
mHWID.AppendPrintf("HMDInfo-0x%llx", aHMD);
|
||||
mDeviceId.AssignLiteral("somedevid");
|
||||
mDeviceName.AssignLiteral("HMD Device");
|
||||
uint64_t hmdid = reinterpret_cast<uint64_t>(aHMD);
|
||||
|
||||
mHWID.Truncate();
|
||||
mHWID.AppendPrintf("HMDInfo-0x%llx", hmdid);
|
||||
|
||||
mDeviceId.Truncate();
|
||||
mDeviceId.AppendPrintf("HMDInfo-dev-0x%llx", hmdid);
|
||||
|
||||
if (aHMD->GetType() == VRHMDType::Oculus) {
|
||||
mDeviceName.AssignLiteral("VR HMD Device (oculus)");
|
||||
} else if (aHMD->GetType() == VRHMDType::Cardboard) {
|
||||
mDeviceName.AssignLiteral("VR HMD Device (cardboard)");
|
||||
} else {
|
||||
mDeviceName.AssignLiteral("VR HMD Device (unknown)");
|
||||
}
|
||||
|
||||
mValid = true;
|
||||
}
|
||||
@ -193,46 +255,22 @@ public:
|
||||
mHMD->SetFOV(left, right, zNear, zFar);
|
||||
}
|
||||
|
||||
virtual already_AddRefed<DOMPoint> GetEyeTranslation(VREye aEye) override
|
||||
virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye) override
|
||||
{
|
||||
gfx::Point3D p = mHMD->GetEyeTranslation(EyeToEye(aEye));
|
||||
|
||||
nsRefPtr<DOMPoint> obj = new DOMPoint(mParent, p.x, p.y, p.z, 0.0);
|
||||
return obj.forget();
|
||||
}
|
||||
|
||||
virtual VRFieldOfView* GetCurrentEyeFieldOfView(VREye aEye) override
|
||||
{
|
||||
return CopyFieldOfView(mHMD->GetEyeFOV(EyeToEye(aEye)));
|
||||
}
|
||||
|
||||
virtual VRFieldOfView* GetRecommendedEyeFieldOfView(VREye aEye) override
|
||||
{
|
||||
return CopyFieldOfView(mHMD->GetRecommendedEyeFOV(EyeToEye(aEye)));
|
||||
}
|
||||
|
||||
virtual VRFieldOfView* GetMaximumEyeFieldOfView(VREye aEye) override
|
||||
{
|
||||
return CopyFieldOfView(mHMD->GetMaximumEyeFOV(EyeToEye(aEye)));
|
||||
}
|
||||
|
||||
virtual already_AddRefed<DOMRect> GetRecommendedEyeRenderRect(VREye aEye) override
|
||||
{
|
||||
const IntSize& a(mHMD->SuggestedEyeResolution());
|
||||
nsRefPtr<DOMRect> obj =
|
||||
new DOMRect(mParent,
|
||||
(aEye == VREye::Left) ? 0 : a.width, 0,
|
||||
a.width, a.height);
|
||||
return obj.forget();
|
||||
gfx::IntSize sz(mHMD->SuggestedEyeResolution());
|
||||
gfx::VRHMDInfo::Eye eye = aEye == VREye::Left ? gfx::VRHMDInfo::Eye_Left : gfx::VRHMDInfo::Eye_Right;
|
||||
nsRefPtr<VREyeParameters> params =
|
||||
new VREyeParameters(mParent,
|
||||
gfx::VRFieldOfView(15, 15, 15, 15), // XXX min?
|
||||
mHMD->GetMaximumEyeFOV(eye),
|
||||
mHMD->GetRecommendedEyeFOV(eye),
|
||||
mHMD->GetEyeTranslation(eye),
|
||||
mHMD->GetEyeFOV(eye),
|
||||
gfx::IntRect((aEye == VREye::Left) ? 0 : sz.width, 0, sz.width, sz.height));
|
||||
return params.forget();
|
||||
}
|
||||
|
||||
protected:
|
||||
VRFieldOfView*
|
||||
CopyFieldOfView(const gfx::VRFieldOfView& aSrc)
|
||||
{
|
||||
return new VRFieldOfView(aSrc.upDegrees, aSrc.rightDegrees,
|
||||
aSrc.downDegrees, aSrc.leftDegrees);
|
||||
}
|
||||
};
|
||||
|
||||
class HMDPositionVRDevice : public PositionSensorVRDevice
|
||||
@ -244,9 +282,21 @@ public:
|
||||
, mTracking(false)
|
||||
{
|
||||
// XXX TODO use real names/IDs
|
||||
mHWID.AppendPrintf("HMDInfo-0x%llx", aHMD);
|
||||
mDeviceId.AssignLiteral("somedevid");
|
||||
mDeviceName.AssignLiteral("HMD Position Device");
|
||||
uint64_t hmdid = reinterpret_cast<uint64_t>(aHMD);
|
||||
|
||||
mHWID.Truncate();
|
||||
mHWID.AppendPrintf("HMDInfo-0x%llx", hmdid);
|
||||
|
||||
mDeviceId.Truncate();
|
||||
mDeviceId.AppendPrintf("HMDInfo-dev-0x%llx", hmdid);
|
||||
|
||||
if (aHMD->GetType() == VRHMDType::Oculus) {
|
||||
mDeviceName.AssignLiteral("VR Position Device (oculus)");
|
||||
} else if (aHMD->GetType() == VRHMDType::Cardboard) {
|
||||
mDeviceName.AssignLiteral("VR Position Device (cardboard)");
|
||||
} else {
|
||||
mDeviceName.AssignLiteral("VR Position Device (unknown)");
|
||||
}
|
||||
|
||||
mValid = true;
|
||||
}
|
||||
@ -258,20 +308,33 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual already_AddRefed<VRPositionState> GetState(double timeOffset) override
|
||||
virtual already_AddRefed<VRPositionState> GetState() override
|
||||
{
|
||||
if (!mTracking) {
|
||||
mHMD->StartSensorTracking();
|
||||
mTracking = true;
|
||||
}
|
||||
|
||||
gfx::VRHMDSensorState state = mHMD->GetSensorState(timeOffset);
|
||||
gfx::VRHMDSensorState state = mHMD->GetSensorState();
|
||||
nsRefPtr<VRPositionState> obj = new VRPositionState(mParent, state);
|
||||
|
||||
return obj.forget();
|
||||
}
|
||||
|
||||
virtual void ZeroSensor() override
|
||||
virtual already_AddRefed<VRPositionState> GetImmediateState() override
|
||||
{
|
||||
if (!mTracking) {
|
||||
mHMD->StartSensorTracking();
|
||||
mTracking = true;
|
||||
}
|
||||
|
||||
gfx::VRHMDSensorState state = mHMD->GetSensorState();
|
||||
nsRefPtr<VRPositionState> obj = new VRPositionState(mParent, state);
|
||||
|
||||
return obj.forget();
|
||||
}
|
||||
|
||||
virtual void ResetSensor() override
|
||||
{
|
||||
mHMD->ZeroSensor();
|
||||
}
|
||||
@ -286,13 +349,8 @@ protected:
|
||||
bool
|
||||
VRDevice::CreateAllKnownVRDevices(nsISupports *aParent, nsTArray<nsRefPtr<VRDevice>>& aDevices)
|
||||
{
|
||||
if (!gfx::VRHMDManagerOculus::Init()) {
|
||||
NS_WARNING("Failed to initialize Oculus HMD Manager");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<gfx::VRHMDInfo>> hmds;
|
||||
gfx::VRHMDManagerOculus::GetOculusHMDs(hmds);
|
||||
gfx::VRHMDManager::GetAllHMDs(hmds);
|
||||
|
||||
for (size_t i = 0; i < hmds.Length(); ++i) {
|
||||
uint32_t sensorBits = hmds[i]->GetSupportedSensorStateBits();
|
||||
|
@ -26,24 +26,36 @@ namespace dom {
|
||||
|
||||
class Element;
|
||||
|
||||
class VRFieldOfViewReadOnly : public NonRefcountedDOMObject
|
||||
class VRFieldOfViewReadOnly : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
VRFieldOfViewReadOnly(double aUpDegrees, double aRightDegrees,
|
||||
VRFieldOfViewReadOnly(nsISupports* aParent,
|
||||
double aUpDegrees, double aRightDegrees,
|
||||
double aDownDegrees, double aLeftDegrees)
|
||||
: mUpDegrees(aUpDegrees)
|
||||
: mParent(aParent)
|
||||
, mUpDegrees(aUpDegrees)
|
||||
, mRightDegrees(aRightDegrees)
|
||||
, mDownDegrees(aDownDegrees)
|
||||
, mLeftDegrees(aLeftDegrees)
|
||||
{
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRFieldOfViewReadOnly)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRFieldOfViewReadOnly)
|
||||
|
||||
double UpDegrees() const { return mUpDegrees; }
|
||||
double RightDegrees() const { return mRightDegrees; }
|
||||
double DownDegrees() const { return mDownDegrees; }
|
||||
double LeftDegrees() const { return mLeftDegrees; }
|
||||
|
||||
nsISupports* GetParentObject() const { return mParent; }
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
protected:
|
||||
virtual ~VRFieldOfViewReadOnly() {}
|
||||
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
|
||||
double mUpDegrees;
|
||||
double mRightDegrees;
|
||||
double mDownDegrees;
|
||||
@ -53,22 +65,30 @@ protected:
|
||||
class VRFieldOfView final : public VRFieldOfViewReadOnly
|
||||
{
|
||||
public:
|
||||
explicit VRFieldOfView(double aUpDegrees = 0.0, double aRightDegrees = 0.0,
|
||||
double aDownDegrees = 0.0, double aLeftDegrees = 0.0)
|
||||
: VRFieldOfViewReadOnly(aUpDegrees, aRightDegrees, aDownDegrees, aLeftDegrees)
|
||||
VRFieldOfView(nsISupports* aParent, const gfx::VRFieldOfView& aSrc)
|
||||
: VRFieldOfViewReadOnly(aParent,
|
||||
aSrc.upDegrees, aSrc.rightDegrees,
|
||||
aSrc.downDegrees, aSrc.leftDegrees)
|
||||
{}
|
||||
|
||||
static VRFieldOfView*
|
||||
explicit VRFieldOfView(nsISupports* aParent,
|
||||
double aUpDegrees = 0.0, double aRightDegrees = 0.0,
|
||||
double aDownDegrees = 0.0, double aLeftDegrees = 0.0)
|
||||
: VRFieldOfViewReadOnly(aParent,
|
||||
aUpDegrees, aRightDegrees, aDownDegrees, aLeftDegrees)
|
||||
{}
|
||||
|
||||
static already_AddRefed<VRFieldOfView>
|
||||
Constructor(const GlobalObject& aGlobal, const VRFieldOfViewInit& aParams,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static VRFieldOfView*
|
||||
static already_AddRefed<VRFieldOfView>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
double aUpDegrees, double aRightDegrees,
|
||||
double aDownDegrees, double aLeftDegrees,
|
||||
ErrorResult& aRv);
|
||||
|
||||
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void SetUpDegrees(double aVal) { mUpDegrees = aVal; }
|
||||
void SetRightDegrees(double aVal) { mRightDegrees = aVal; }
|
||||
@ -80,7 +100,7 @@ class VRPositionState final : public nsWrapperCache
|
||||
{
|
||||
~VRPositionState() {}
|
||||
public:
|
||||
explicit VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState);
|
||||
VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState);
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRPositionState)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRPositionState)
|
||||
@ -117,6 +137,43 @@ protected:
|
||||
nsRefPtr<DOMPoint> mAngularAcceleration;
|
||||
};
|
||||
|
||||
class VREyeParameters final : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
VREyeParameters(nsISupports* aParent,
|
||||
const gfx::VRFieldOfView& aMinFOV,
|
||||
const gfx::VRFieldOfView& aMaxFOV,
|
||||
const gfx::VRFieldOfView& aRecFOV,
|
||||
const gfx::Point3D& aEyeTranslation,
|
||||
const gfx::VRFieldOfView& aCurFOV,
|
||||
const gfx::IntRect& aRenderRect);
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VREyeParameters)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VREyeParameters)
|
||||
|
||||
VRFieldOfView* MinimumFieldOfView();
|
||||
VRFieldOfView* MaximumFieldOfView();
|
||||
VRFieldOfView* RecommendedFieldOfView();
|
||||
DOMPoint* EyeTranslation();
|
||||
|
||||
VRFieldOfView* CurrentFieldOfView();
|
||||
DOMRect* RenderRect();
|
||||
|
||||
nsISupports* GetParentObject() const { return mParent; }
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
protected:
|
||||
~VREyeParameters() {}
|
||||
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
|
||||
nsRefPtr<VRFieldOfView> mMinFOV;
|
||||
nsRefPtr<VRFieldOfView> mMaxFOV;
|
||||
nsRefPtr<VRFieldOfView> mRecFOV;
|
||||
nsRefPtr<DOMPoint> mEyeTranslation;
|
||||
nsRefPtr<VRFieldOfView> mCurFOV;
|
||||
nsRefPtr<DOMRect> mRenderRect;
|
||||
};
|
||||
|
||||
class VRDevice : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
@ -176,20 +233,14 @@ protected:
|
||||
class HMDVRDevice : public VRDevice
|
||||
{
|
||||
public:
|
||||
virtual already_AddRefed<DOMPoint> GetEyeTranslation(VREye aEye) = 0;
|
||||
virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye) = 0;
|
||||
|
||||
virtual void SetFieldOfView(const VRFieldOfViewInit& aLeftFOV,
|
||||
const VRFieldOfViewInit& aRightFOV,
|
||||
double zNear, double zFar) = 0;
|
||||
virtual VRFieldOfView* GetCurrentEyeFieldOfView(VREye aEye) = 0;
|
||||
virtual VRFieldOfView* GetRecommendedEyeFieldOfView(VREye aEye) = 0;
|
||||
virtual VRFieldOfView* GetMaximumEyeFieldOfView(VREye aEye) = 0;
|
||||
virtual already_AddRefed<DOMRect> GetRecommendedEyeRenderRect(VREye aEye) = 0;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void XxxToggleElementVR(Element& aElement);
|
||||
|
||||
gfx::VRHMDInfo *GetHMD() { return mHMD.get(); }
|
||||
|
||||
protected:
|
||||
@ -206,9 +257,11 @@ protected:
|
||||
class PositionSensorVRDevice : public VRDevice
|
||||
{
|
||||
public:
|
||||
virtual already_AddRefed<VRPositionState> GetState(double timeOffset) = 0;
|
||||
virtual already_AddRefed<VRPositionState> GetState() = 0;
|
||||
|
||||
virtual void ZeroSensor() = 0;
|
||||
virtual already_AddRefed<VRPositionState> GetImmediateState() = 0;
|
||||
|
||||
virtual void ResetSensor() = 0;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
|
@ -52,6 +52,20 @@ interface VRPositionState {
|
||||
readonly attribute DOMPoint? angularAcceleration;
|
||||
};
|
||||
|
||||
[Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDevice.h"]
|
||||
interface VREyeParameters {
|
||||
/* These values are expected to be static per-device/per-user */
|
||||
[Constant, Cached] readonly attribute VRFieldOfView minimumFieldOfView;
|
||||
[Constant, Cached] readonly attribute VRFieldOfView maximumFieldOfView;
|
||||
[Constant, Cached] readonly attribute VRFieldOfView recommendedFieldOfView;
|
||||
[Constant, Cached] readonly attribute DOMPoint eyeTranslation;
|
||||
|
||||
/* These values will vary after a FOV has been set */
|
||||
[Constant, Cached] readonly attribute VRFieldOfView currentFieldOfView;
|
||||
[Constant, Cached] readonly attribute DOMRect renderRect;
|
||||
};
|
||||
|
||||
[Pref="dom.vr.enabled"]
|
||||
interface VRDevice {
|
||||
/**
|
||||
@ -59,38 +73,26 @@ interface VRDevice {
|
||||
* VR Device is a part of. All VRDevice/Sensors that come
|
||||
* from the same hardware will have the same hardwareId
|
||||
*/
|
||||
[Pure] readonly attribute DOMString hardwareUnitId;
|
||||
[Constant] readonly attribute DOMString hardwareUnitId;
|
||||
|
||||
/**
|
||||
* An identifier for this distinct sensor/device on a physical
|
||||
* hardware device. This shouldn't change across browser
|
||||
* restrats, allowing configuration data to be saved based on it.
|
||||
*/
|
||||
[Pure] readonly attribute DOMString deviceId;
|
||||
[Constant] readonly attribute DOMString deviceId;
|
||||
|
||||
/**
|
||||
* a device name, a user-readable name identifying it
|
||||
*/
|
||||
[Pure] readonly attribute DOMString deviceName;
|
||||
[Constant] readonly attribute DOMString deviceName;
|
||||
};
|
||||
|
||||
[Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDevice.h"]
|
||||
interface HMDVRDevice : VRDevice {
|
||||
/* The translation that should be applied to the view matrix for rendering each eye */
|
||||
DOMPoint getEyeTranslation(VREye whichEye);
|
||||
|
||||
// the FOV that the HMD was configured with
|
||||
[NewObject]
|
||||
VRFieldOfView getCurrentEyeFieldOfView(VREye whichEye);
|
||||
|
||||
// the recommended FOV, per eye.
|
||||
[NewObject]
|
||||
VRFieldOfView getRecommendedEyeFieldOfView(VREye whichEye);
|
||||
|
||||
// the maximum FOV, per eye. Above this, rendering will look broken.
|
||||
[NewObject]
|
||||
VRFieldOfView getMaximumEyeFieldOfView(VREye whichEye);
|
||||
// Return the current VREyeParameters for the given eye
|
||||
VREyeParameters getEyeParameters(VREye whichEye);
|
||||
|
||||
// Set a field of view. If either of the fields of view is null,
|
||||
// or if their values are all zeros, then the recommended field of view
|
||||
@ -99,34 +101,30 @@ interface HMDVRDevice : VRDevice {
|
||||
optional VRFieldOfViewInit rightFOV,
|
||||
optional double zNear = 0.01,
|
||||
optional double zFar = 10000.0);
|
||||
|
||||
// return a recommended rect for this eye. Only useful for Canvas rendering,
|
||||
// the x/y coordinates will be the location in the canvas where this eye should
|
||||
// begin, and the width/height are the dimensions. Any canvas in the appropriate
|
||||
// ratio will work.
|
||||
DOMRect getRecommendedEyeRenderRect(VREye whichEye);
|
||||
|
||||
// hack for testing
|
||||
void xxxToggleElementVR(Element element);
|
||||
};
|
||||
|
||||
[Pref="dom.vr.enabled" ,
|
||||
HeaderFile="mozilla/dom/VRDevice.h"]
|
||||
interface PositionSensorVRDevice : VRDevice {
|
||||
/*
|
||||
* Return a VRPositionState dictionary containing the state of this position sensor,
|
||||
* at an optional past time or predicted for a future time if timeOffset is != 0.
|
||||
* Return a VRPositionState dictionary containing the state of this position sensor
|
||||
* for the current frame if within a requestAnimationFrame callback, or for the
|
||||
* previous frame if not.
|
||||
*
|
||||
* The VRPositionState will contain the position, orientation, and velocity
|
||||
* and acceleration of each of these properties. Use "hasPosition" and "hasOrientation"
|
||||
* to check if the associated members are valid; if these are false, those members
|
||||
* will be null.
|
||||
*/
|
||||
[NewObject]
|
||||
VRPositionState getState(optional double timeOffset = 0.0);
|
||||
[NewObject] VRPositionState getState();
|
||||
|
||||
/* Zero this sensor, treating its current position and orientation
|
||||
/*
|
||||
* Return the current instantaneous sensor state.
|
||||
*/
|
||||
[NewObject] VRPositionState getImmediateState();
|
||||
|
||||
/* Reset this sensor, treating its current position and orientation
|
||||
* as the "origin/zero" values.
|
||||
*/
|
||||
void zeroSensor();
|
||||
void resetSensor();
|
||||
};
|
||||
|
@ -4223,7 +4223,8 @@ WorkerDebugger::WorkerDebugger(WorkerPrivate* aWorkerPrivate)
|
||||
mCondVar(mMutex, "WorkerDebugger::mCondVar"),
|
||||
mWorkerPrivate(aWorkerPrivate),
|
||||
mIsEnabled(false),
|
||||
mIsInitialized(false)
|
||||
mIsInitialized(false),
|
||||
mIsFrozen(false)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnParentThread();
|
||||
}
|
||||
@ -4277,6 +4278,21 @@ WorkerDebugger::GetIsChrome(bool* aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerDebugger::GetIsFrozen(bool* aResult)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (!mWorkerPrivate) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
*aResult = mIsFrozen;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerDebugger::GetParent(nsIWorkerDebugger** aResult)
|
||||
{
|
||||
@ -4474,6 +4490,52 @@ WorkerDebugger::Disable()
|
||||
NotifyIsEnabled(false);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebugger::Freeze()
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(this, &WorkerDebugger::FreezeOnMainThread);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebugger::FreezeOnMainThread()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
mIsFrozen = true;
|
||||
|
||||
for (size_t index = 0; index < mListeners.Length(); ++index) {
|
||||
mListeners[index]->OnFreeze();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebugger::Thaw()
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(this, &WorkerDebugger::ThawOnMainThread);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebugger::ThawOnMainThread()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
mIsFrozen = false;
|
||||
|
||||
for (size_t index = 0; index < mListeners.Length(); ++index) {
|
||||
mListeners[index]->OnThaw();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebugger::PostMessageToDebugger(const nsAString& aMessage)
|
||||
{
|
||||
@ -5693,6 +5755,7 @@ WorkerPrivate::FreezeInternal(JSContext* aCx)
|
||||
NS_ASSERTION(!mFrozen, "Already frozen!");
|
||||
|
||||
mFrozen = true;
|
||||
mDebugger->Freeze();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5704,6 +5767,7 @@ WorkerPrivate::ThawInternal(JSContext* aCx)
|
||||
NS_ASSERTION(mFrozen, "Not yet frozen!");
|
||||
|
||||
mFrozen = false;
|
||||
mDebugger->Thaw();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -727,6 +727,7 @@ class WorkerDebugger : public nsIWorkerDebugger {
|
||||
|
||||
// Only touched on the main thread.
|
||||
bool mIsInitialized;
|
||||
bool mIsFrozen;
|
||||
nsTArray<nsCOMPtr<nsIWorkerDebuggerListener>> mListeners;
|
||||
|
||||
public:
|
||||
@ -747,6 +748,12 @@ public:
|
||||
void
|
||||
Disable();
|
||||
|
||||
void
|
||||
Freeze();
|
||||
|
||||
void
|
||||
Thaw();
|
||||
|
||||
void
|
||||
PostMessageToDebugger(const nsAString& aMessage);
|
||||
|
||||
@ -761,6 +768,12 @@ private:
|
||||
void
|
||||
NotifyIsEnabled(bool aIsEnabled);
|
||||
|
||||
void
|
||||
FreezeOnMainThread();
|
||||
|
||||
void
|
||||
ThawOnMainThread();
|
||||
|
||||
void
|
||||
PostMessageToDebuggerOnMainThread(const nsAString& aMessage);
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
interface nsIDOMWindow;
|
||||
|
||||
[scriptable, uuid(55d54034-1573-4889-b1d9-93ba12fc33c7)]
|
||||
[scriptable, uuid(530db841-1b2c-485a-beeb-f2b1acb9714e)]
|
||||
interface nsIWorkerDebuggerListener : nsISupports
|
||||
{
|
||||
void onClose();
|
||||
@ -10,10 +10,14 @@ interface nsIWorkerDebuggerListener : nsISupports
|
||||
void onError(in DOMString filename, in unsigned long lineno,
|
||||
in DOMString message);
|
||||
|
||||
void onFreeze();
|
||||
|
||||
void onMessage(in DOMString message);
|
||||
|
||||
void onThaw();
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(28e0a60c-ff10-446c-8c2a-5fbdc01394ea)]
|
||||
[scriptable, builtinclass, uuid(d7c73e54-3c41-4393-9d13-fa2ed4Ba6764)]
|
||||
interface nsIWorkerDebugger : nsISupports
|
||||
{
|
||||
const unsigned long TYPE_DEDICATED = 0;
|
||||
@ -24,6 +28,8 @@ interface nsIWorkerDebugger : nsISupports
|
||||
|
||||
readonly attribute bool isChrome;
|
||||
|
||||
readonly attribute bool isFrozen;
|
||||
|
||||
readonly attribute nsIWorkerDebugger parent;
|
||||
|
||||
readonly attribute unsigned long type;
|
||||
|
15
dom/workers/test/WorkerDebugger.isFrozen_iframe1.html
Normal file
15
dom/workers/test/WorkerDebugger.isFrozen_iframe1.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
var worker = new Worker("WorkerDebugger.isFrozen_worker1.js");
|
||||
worker.onmessage = function () {
|
||||
parent.postMessage("ready", "*");
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
This is page 1.
|
||||
</body>
|
||||
<html>
|
15
dom/workers/test/WorkerDebugger.isFrozen_iframe2.html
Normal file
15
dom/workers/test/WorkerDebugger.isFrozen_iframe2.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
var worker = new Worker("WorkerDebugger.isFrozen_worker2.js");
|
||||
worker.onmessage = function () {
|
||||
parent.postMessage("ready", "*");
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
This is page 2.
|
||||
</body>
|
||||
<html>
|
5
dom/workers/test/WorkerDebugger.isFrozen_worker1.js
Normal file
5
dom/workers/test/WorkerDebugger.isFrozen_worker1.js
Normal file
@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
onmessage = function () {};
|
||||
|
||||
postMessage("ready");
|
5
dom/workers/test/WorkerDebugger.isFrozen_worker2.js
Normal file
5
dom/workers/test/WorkerDebugger.isFrozen_worker2.js
Normal file
@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
onmessage = function () {};
|
||||
|
||||
postMessage("ready");
|
@ -4,6 +4,10 @@ support-files =
|
||||
WorkerDebugger.initialize_childWorker.js
|
||||
WorkerDebugger.initialize_debugger.js
|
||||
WorkerDebugger.initialize_worker.js
|
||||
WorkerDebugger.isFrozen_iframe1.html
|
||||
WorkerDebugger.isFrozen_iframe2.html
|
||||
WorkerDebugger.isFrozen_worker1.js
|
||||
WorkerDebugger.isFrozen_worker2.js
|
||||
WorkerDebugger.postMessage_childWorker.js
|
||||
WorkerDebugger.postMessage_debugger.js
|
||||
WorkerDebugger.postMessage_worker.js
|
||||
@ -47,6 +51,7 @@ support-files =
|
||||
|
||||
[test_WorkerDebugger.xul]
|
||||
[test_WorkerDebugger.initialize.xul]
|
||||
[test_WorkerDebugger.isFrozen.xul]
|
||||
[test_WorkerDebugger.postMessage.xul]
|
||||
[test_WorkerDebuggerGlobalScope.createSandbox.xul]
|
||||
[test_WorkerDebuggerGlobalScope.enterEventLoop.xul]
|
||||
|
@ -130,6 +130,41 @@ function waitForDebuggerMessage(dbg, message) {
|
||||
});
|
||||
}
|
||||
|
||||
function waitForDebuggerFreeze(dbg) {
|
||||
return new Promise(function (resolve) {
|
||||
dbg.addListener({
|
||||
onFreeze: function () {
|
||||
dbg.removeListener(this);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForDebuggerThaw(dbg) {
|
||||
return new Promise(function (resolve) {
|
||||
dbg.addListener({
|
||||
onThaw: function () {
|
||||
dbg.removeListener(this);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForWindowMessage(window, message) {
|
||||
return new Promise(function (resolve) {
|
||||
let onmessage = function (event) {
|
||||
if (event.data !== event.data) {
|
||||
return;
|
||||
}
|
||||
window.removeEventListener("message", onmessage, false);
|
||||
resolve();
|
||||
};
|
||||
window.addEventListener("message", onmessage, false);
|
||||
});
|
||||
}
|
||||
|
||||
function waitForWorkerMessage(worker, message) {
|
||||
return new Promise(function (resolve) {
|
||||
worker.addEventListener("message", function onmessage(event) {
|
||||
|
98
dom/workers/test/test_WorkerDebugger.isFrozen.xul
Normal file
98
dom/workers/test/test_WorkerDebugger.isFrozen.xul
Normal file
@ -0,0 +1,98 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<window title="Test for WorkerDebugger.isFrozen"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="test();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
|
||||
<script type="application/javascript" src="dom_worker_helper.js"/>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
const CACHE_SUBFRAMES = "browser.sessionhistory.cache_subframes";
|
||||
const MAX_TOTAL_VIEWERS = "browser.sessionhistory.max_total_viewers";
|
||||
|
||||
const IFRAME1_URL = "WorkerDebugger.isFrozen_iframe1.html";
|
||||
const IFRAME2_URL = "WorkerDebugger.isFrozen_iframe2.html";
|
||||
|
||||
const WORKER1_URL = "WorkerDebugger.isFrozen_worker1.js";
|
||||
const WORKER2_URL = "WorkerDebugger.isFrozen_worker2.js";
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var oldMaxTotalViewers = SpecialPowers.getIntPref(MAX_TOTAL_VIEWERS);
|
||||
|
||||
SpecialPowers.setBoolPref(CACHE_SUBFRAMES, true);
|
||||
SpecialPowers.setIntPref(MAX_TOTAL_VIEWERS, 10);
|
||||
|
||||
let iframe = $("iframe");
|
||||
|
||||
let promise = waitForMultiple([
|
||||
waitForRegister(WORKER1_URL),
|
||||
waitForWindowMessage(window, "ready"),
|
||||
]);
|
||||
iframe.src = IFRAME1_URL;
|
||||
let [dbg1] = yield promise;
|
||||
is(dbg1.isClosed, false,
|
||||
"debugger for worker on page 1 should not be closed");
|
||||
is(dbg1.isFrozen, false,
|
||||
"debugger for worker on page 1 should not be frozen");
|
||||
|
||||
promise = waitForMultiple([
|
||||
waitForDebuggerFreeze(dbg1),
|
||||
waitForRegister(WORKER2_URL),
|
||||
waitForWindowMessage(window, "ready"),
|
||||
]);
|
||||
iframe.src = IFRAME2_URL;
|
||||
let [_, dbg2] = yield promise;
|
||||
is(dbg1.isClosed, false,
|
||||
"debugger for worker on page 1 should not be closed");
|
||||
is(dbg1.isFrozen, true,
|
||||
"debugger for worker on page 1 should be frozen");
|
||||
is(dbg2.isClosed, false,
|
||||
"debugger for worker on page 2 should not be closed");
|
||||
is(dbg2.isFrozen, false,
|
||||
"debugger for worker on page 2 should not be frozen");
|
||||
|
||||
promise = waitForMultiple([
|
||||
waitForDebuggerFreeze(dbg2),
|
||||
waitForDebuggerThaw(dbg1),
|
||||
]);
|
||||
iframe.contentWindow.history.back();
|
||||
yield promise;
|
||||
is(dbg1.isClosed, false,
|
||||
"debugger for worker on page 1 should not be closed")
|
||||
is(dbg1.isFrozen, false,
|
||||
"debugger for worker on page 1 should not be frozen");
|
||||
is(dbg2.isClosed, false,
|
||||
"debugger for worker on page 2 should not be closed");
|
||||
is(dbg2.isFrozen, true,
|
||||
"debugger for worker on page 2 should be frozen");
|
||||
|
||||
SpecialPowers.clearUserPref(CACHE_SUBFRAMES);
|
||||
SpecialPowers.setIntPref(MAX_TOTAL_VIEWERS, oldMaxTotalViewers);
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display:none;"></div>
|
||||
<pre id="test"></pre>
|
||||
<iframe id="iframe"></iframe>
|
||||
</body>
|
||||
<label id="test-result"/>
|
||||
</window>
|
@ -1452,9 +1452,15 @@ ChromeTooltipListener::sTooltipCallback(nsITimer *aTimer,
|
||||
if (textFound) {
|
||||
nsString tipText(tooltipText);
|
||||
LayoutDeviceIntPoint screenDot = widget->WidgetToScreenOffset();
|
||||
self->ShowTooltip(self->mMouseScreenX - screenDot.x,
|
||||
self->mMouseScreenY - screenDot.y,
|
||||
tipText);
|
||||
double scaleFactor = 1.0;
|
||||
if (shell->GetPresContext()) {
|
||||
scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/
|
||||
shell->GetPresContext()->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom();
|
||||
}
|
||||
// ShowTooltip expects widget-relative position.
|
||||
self->ShowTooltip(self->mMouseScreenX - screenDot.x / scaleFactor,
|
||||
self->mMouseScreenY - screenDot.y / scaleFactor,
|
||||
tipText);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "Point.h"
|
||||
#include "Rect.h"
|
||||
#include "Matrix.h"
|
||||
#include "Quaternion.h"
|
||||
#include "UserData.h"
|
||||
|
||||
// GenericRefCountedBase allows us to hold on to refcounted objects of any type
|
||||
|
@ -4,6 +4,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Matrix.h"
|
||||
#include "Quaternion.h"
|
||||
#include "Tools.h"
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
@ -28,6 +29,17 @@ operator<<(std::ostream& aStream, const Matrix& aMatrix)
|
||||
<< "; ]";
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& aStream, const Matrix4x4& aMatrix)
|
||||
{
|
||||
const Float *f = &aMatrix._11;
|
||||
aStream << "[ " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
|
||||
aStream << " " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
|
||||
aStream << " " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
|
||||
aStream << " " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ]" << std::endl;
|
||||
return aStream;
|
||||
}
|
||||
|
||||
Matrix
|
||||
Matrix::Rotation(Float aAngle)
|
||||
{
|
||||
@ -283,5 +295,32 @@ Matrix4x4::SetNAN()
|
||||
_44 = UnspecifiedNaN<Float>();
|
||||
}
|
||||
|
||||
void
|
||||
Matrix4x4::SetRotationFromQuaternion(const Quaternion& q)
|
||||
{
|
||||
const Float x2 = q.x + q.x, y2 = q.y + q.y, z2 = q.z + q.z;
|
||||
const Float xx = q.x * x2, xy = q.x * y2, xz = q.x * z2;
|
||||
const Float yy = q.y * y2, yz = q.y * z2, zz = q.z * z2;
|
||||
const Float wx = q.w * x2, wy = q.w * y2, wz = q.w * z2;
|
||||
|
||||
_11 = 1.0f - (yy + zz);
|
||||
_21 = xy + wz;
|
||||
_31 = xz - wy;
|
||||
_41 = 0.0f;
|
||||
|
||||
_12 = xy - wz;
|
||||
_22 = 1.0f - (xx + zz);
|
||||
_32 = yz + wx;
|
||||
_42 = 0.0f;
|
||||
|
||||
_13 = xz + wy;
|
||||
_23 = yz - wx;
|
||||
_33 = 1.0f - (xx + yy);
|
||||
_43 = 0.0f;
|
||||
|
||||
_14 = _42 = _43 = 0.0f;
|
||||
_44 = 1.0f;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class Quaternion;
|
||||
|
||||
static bool FuzzyEqual(Float aV1, Float aV2) {
|
||||
// XXX - Check if fabs does the smart thing and just negates the sign bit.
|
||||
return fabs(aV2 - aV1) < 1e-6;
|
||||
@ -390,6 +392,8 @@ public:
|
||||
Float _31, _32, _33, _34;
|
||||
Float _41, _42, _43, _44;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& aStream, const Matrix4x4& aMatrix);
|
||||
|
||||
Point4D& operator[](int aIndex)
|
||||
{
|
||||
MOZ_ASSERT(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
|
||||
@ -872,6 +876,11 @@ public:
|
||||
*((&_41)+aIndex) = aVector.w;
|
||||
}
|
||||
|
||||
// Sets this matrix to a rotation matrix given by aQuat.
|
||||
// This quaternion *MUST* be normalized!
|
||||
// Implemented in Quaternion.cpp
|
||||
void SetRotationFromQuaternion(const Quaternion& aQuat);
|
||||
|
||||
// Set all the members of the matrix to NaN
|
||||
void SetNAN();
|
||||
};
|
||||
|
57
gfx/2d/Quaternion.cpp
Normal file
57
gfx/2d/Quaternion.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 20; 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 "Quaternion.h"
|
||||
#include "Matrix.h"
|
||||
#include "Tools.h"
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
#include <math.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& aStream, const Quaternion& aQuat)
|
||||
{
|
||||
return aStream << "< " << aQuat.x << " " << aQuat.y << " " << aQuat.z << " " << aQuat.w << ">";
|
||||
}
|
||||
|
||||
void
|
||||
Quaternion::SetFromRotationMatrix(const Matrix4x4& m)
|
||||
{
|
||||
// see http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
|
||||
const Float trace = m._11 + m._22 + m._33;
|
||||
if (trace > 0.0) {
|
||||
const Float s = 0.5f / sqrt(trace + 1.0f);
|
||||
w = 0.25f / s;
|
||||
x = (m._32 - m._23) * s;
|
||||
y = (m._13 - m._31) * s;
|
||||
z = (m._21 - m._12) * s;
|
||||
} else if (m._11 > m._22 && m._11 > m._33) {
|
||||
const Float s = 2.0f * sqrt(1.0f + m._11 - m._22 - m._33);
|
||||
w = (m._32 - m._23) / s;
|
||||
x = 0.25f * s;
|
||||
y = (m._12 + m._21) / s;
|
||||
z = (m._13 + m._31) / s;
|
||||
} else if (m._22 > m._33) {
|
||||
const Float s = 2.0 * sqrt(1.0f + m._22 - m._11 - m._33);
|
||||
w = (m._13 - m._31) / s;
|
||||
x = (m._12 + m._21) / s;
|
||||
y = 0.25f * s;
|
||||
z = (m._23 + m._32) / s;
|
||||
} else {
|
||||
const Float s = 2.0 * sqrt(1.0f + m._33 - m._11 - m._22);
|
||||
w = (m._21 - m._12) / s;
|
||||
x = (m._13 + m._31) / s;
|
||||
y = (m._23 + m._32) / s;
|
||||
z = 0.25f * s;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
100
gfx/2d/Quaternion.h
Normal file
100
gfx/2d/Quaternion.h
Normal file
@ -0,0 +1,100 @@
|
||||
/* -*- Mode: C++; tab-width: 20; 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/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_QUATERNION_H_
|
||||
#define MOZILLA_GFX_QUATERNION_H_
|
||||
|
||||
#include "Types.h"
|
||||
#include <math.h>
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class Matrix4x4;
|
||||
|
||||
class Quaternion
|
||||
{
|
||||
public:
|
||||
Quaternion()
|
||||
: x(0.0f), y(0.0f), z(0.0f), w(1.0f)
|
||||
{}
|
||||
|
||||
Quaternion(Float aX, Float aY, Float aZ, Float aW)
|
||||
: x(aX), y(aY), z(aZ), w(aW)
|
||||
{}
|
||||
|
||||
|
||||
Quaternion(const Quaternion& aOther)
|
||||
{
|
||||
memcpy(this, &aOther, sizeof(*this));
|
||||
}
|
||||
|
||||
Float x, y, z, w;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& aStream, const Quaternion& aQuat);
|
||||
|
||||
void Set(Float aX, Float aY, Float aZ, Float aW)
|
||||
{
|
||||
x = aX; y = aY; z = aZ; w = aW;
|
||||
}
|
||||
|
||||
// Assumes upper 3x3 of aMatrix is a pure rotation matrix (no scaling)
|
||||
void SetFromRotationMatrix(const Matrix4x4& aMatrix);
|
||||
|
||||
// result = this * aQuat
|
||||
Quaternion operator*(const Quaternion &aQuat) const
|
||||
{
|
||||
Quaternion o;
|
||||
const Float bx = aQuat.x, by = aQuat.y, bz = aQuat.z, bw = aQuat.w;
|
||||
|
||||
o.x = x*bw + w*bx + y*bz - z*by;
|
||||
o.y = y*bw + w*by + z*bx - x*bz;
|
||||
o.z = z*bw + w*bz + x*by - y*bx;
|
||||
o.w = w*bw - x*bx - y*by - z*bz;
|
||||
return o;
|
||||
}
|
||||
|
||||
Quaternion& operator*=(const Quaternion &aQuat)
|
||||
{
|
||||
*this = *this * aQuat;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Float Length() const
|
||||
{
|
||||
return sqrt(x*x + y*y + z*z + w*w);
|
||||
}
|
||||
|
||||
Quaternion& Conjugate()
|
||||
{
|
||||
x *= -1.f; y *= -1.f; z *= -1.f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Quaternion& Normalize()
|
||||
{
|
||||
Float l = Length();
|
||||
if (l) {
|
||||
l = 1.0f / l;
|
||||
x *= l; y *= l; z *= l; w *= l;
|
||||
} else {
|
||||
x = y = z = 0.f;
|
||||
w = 1.f;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Quaternion& Invert()
|
||||
{
|
||||
return Conjugate().Normalize();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -29,6 +29,7 @@ EXPORTS.mozilla.gfx += [
|
||||
'PathHelpers.h',
|
||||
'PatternHelpers.h',
|
||||
'Point.h',
|
||||
'Quaternion.h',
|
||||
'Rect.h',
|
||||
'Scale.h',
|
||||
'ScaleFactor.h',
|
||||
@ -120,6 +121,7 @@ UNIFIED_SOURCES += [
|
||||
'Path.cpp',
|
||||
'PathCairo.cpp',
|
||||
'PathRecording.cpp',
|
||||
'Quaternion.cpp',
|
||||
'RecordedEvent.cpp',
|
||||
'Scale.cpp',
|
||||
'ScaledFontBase.cpp',
|
||||
|
@ -73,17 +73,19 @@ struct DeviceAttachmentsD3D11
|
||||
//
|
||||
// VR pieces
|
||||
//
|
||||
RefPtr<ID3D11InputLayout> mVRDistortionInputLayout;
|
||||
RefPtr<ID3D11Buffer> mVRDistortionConstants;
|
||||
|
||||
typedef EnumeratedArray<VRHMDType, VRHMDType::NumHMDTypes, RefPtr<ID3D11InputLayout>>
|
||||
VRDistortionInputLayoutArray;
|
||||
typedef EnumeratedArray<VRHMDType, VRHMDType::NumHMDTypes, RefPtr<ID3D11VertexShader>>
|
||||
VRVertexShaderArray;
|
||||
typedef EnumeratedArray<VRHMDType, VRHMDType::NumHMDTypes, RefPtr<ID3D11PixelShader>>
|
||||
VRPixelShaderArray;
|
||||
|
||||
VRDistortionInputLayoutArray mVRDistortionInputLayout;
|
||||
VRVertexShaderArray mVRDistortionVS;
|
||||
VRPixelShaderArray mVRDistortionPS;
|
||||
|
||||
RefPtr<ID3D11Buffer> mVRDistortionConstants;
|
||||
|
||||
// These will be created/filled in as needed during rendering whenever the configuration
|
||||
// changes.
|
||||
VRHMDConfiguration mVRConfiguration;
|
||||
@ -334,7 +336,12 @@ CompositorD3D11::Initialize()
|
||||
sizeof(vrlayout) / sizeof(D3D11_INPUT_ELEMENT_DESC),
|
||||
OculusVRDistortionVS,
|
||||
sizeof(OculusVRDistortionVS),
|
||||
byRef(mAttachments->mVRDistortionInputLayout));
|
||||
byRef(mAttachments->mVRDistortionInputLayout[VRHMDType::Oculus]));
|
||||
|
||||
// XXX shared for now, rename
|
||||
mAttachments->mVRDistortionInputLayout[VRHMDType::Cardboard] =
|
||||
mAttachments->mVRDistortionInputLayout[VRHMDType::Oculus];
|
||||
|
||||
cBufferDesc.ByteWidth = sizeof(gfx::VRDistortionConstants);
|
||||
hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, byRef(mAttachments->mVRDistortionConstants));
|
||||
if (FAILED(hr)) {
|
||||
@ -661,6 +668,7 @@ CompositorD3D11::DrawVRDistortion(const gfx::Rect& aRect,
|
||||
gfx::IntSize size = vrEffect->mRenderTarget->GetSize(); // XXX source->GetSize()
|
||||
|
||||
VRHMDInfo* hmdInfo = vrEffect->mHMD;
|
||||
VRHMDType hmdType = hmdInfo->GetType();
|
||||
VRDistortionConstants shaderConstants;
|
||||
|
||||
// do we need to recreate the VR buffers, since the config has changed?
|
||||
@ -709,20 +717,17 @@ CompositorD3D11::DrawVRDistortion(const gfx::Rect& aRect,
|
||||
|
||||
// Triangle lists and same layout for both eyes
|
||||
mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
mContext->IASetInputLayout(mAttachments->mVRDistortionInputLayout);
|
||||
|
||||
// Shaders for this HMD
|
||||
mContext->VSSetShader(mAttachments->mVRDistortionVS[mAttachments->mVRConfiguration.hmdType], nullptr, 0);
|
||||
mContext->PSSetShader(mAttachments->mVRDistortionPS[mAttachments->mVRConfiguration.hmdType], nullptr, 0);
|
||||
mContext->IASetInputLayout(mAttachments->mVRDistortionInputLayout[hmdType]);
|
||||
mContext->VSSetShader(mAttachments->mVRDistortionVS[hmdType], nullptr, 0);
|
||||
mContext->PSSetShader(mAttachments->mVRDistortionPS[hmdType], nullptr, 0);
|
||||
|
||||
// This is the source texture SRV for the pixel shader
|
||||
// XXX, um should we cache this SRV?
|
||||
// XXX, um should we cache this SRV on the source?
|
||||
RefPtr<ID3D11ShaderResourceView> view;
|
||||
mDevice->CreateShaderResourceView(source->GetD3D11Texture(), nullptr, byRef(view));
|
||||
ID3D11ShaderResourceView* srView = view;
|
||||
mContext->PSSetShaderResources(0, 1, &srView);
|
||||
|
||||
|
||||
gfx::IntSize vpSizeInt = mCurrentRT->GetSize();
|
||||
gfx::Size vpSize(vpSizeInt.width, vpSizeInt.height);
|
||||
ID3D11Buffer* vbuffer;
|
||||
@ -1343,6 +1348,11 @@ CompositorD3D11::CreateShaders()
|
||||
return false;
|
||||
}
|
||||
|
||||
// These are shared
|
||||
// XXX rename Oculus shaders to something more generic
|
||||
mAttachments->mVRDistortionVS[VRHMDType::Cardboard] = mAttachments->mVRDistortionVS[VRHMDType::Oculus];
|
||||
mAttachments->mVRDistortionPS[VRHMDType::Cardboard] = mAttachments->mVRDistortionPS[VRHMDType::Oculus];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -104,10 +103,10 @@ ret
|
||||
|
||||
const BYTE LayerQuadVS[] =
|
||||
{
|
||||
68, 88, 66, 67, 67, 61,
|
||||
27, 151, 57, 33, 48, 19,
|
||||
55, 6, 95, 77, 254, 163,
|
||||
118, 237, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 200, 251,
|
||||
64, 251, 166, 240, 101, 137,
|
||||
191, 140, 75, 217, 9, 168,
|
||||
61, 163, 1, 0, 0, 0,
|
||||
180, 6, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
152, 1, 0, 0, 160, 3,
|
||||
@ -262,7 +261,7 @@ const BYTE LayerQuadVS[] =
|
||||
65, 84, 116, 0, 0, 0,
|
||||
13, 0, 0, 0, 2, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
3, 0, 0, 0, 6, 0,
|
||||
3, 0, 0, 0, 12, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -272,7 +271,7 @@ const BYTE LayerQuadVS[] =
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 2, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -363,10 +362,10 @@ const BYTE LayerQuadVS[] =
|
||||
41, 32, 72, 76, 83, 76,
|
||||
32, 83, 104, 97, 100, 101,
|
||||
114, 32, 67, 111, 109, 112,
|
||||
105, 108, 101, 114, 32, 57,
|
||||
46, 51, 48, 46, 57, 50,
|
||||
48, 48, 46, 50, 48, 53,
|
||||
52, 54, 0, 171, 73, 83,
|
||||
105, 108, 101, 114, 32, 54,
|
||||
46, 51, 46, 57, 54, 48,
|
||||
48, 46, 49, 54, 51, 56,
|
||||
52, 0, 171, 171, 73, 83,
|
||||
71, 78, 44, 0, 0, 0,
|
||||
1, 0, 0, 0, 8, 0,
|
||||
0, 0, 32, 0, 0, 0,
|
||||
@ -393,10 +392,9 @@ const BYTE LayerQuadVS[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -460,10 +458,10 @@ ret
|
||||
|
||||
const BYTE SolidColorShader[] =
|
||||
{
|
||||
68, 88, 66, 67, 182, 98,
|
||||
102, 100, 187, 218, 19, 40,
|
||||
99, 74, 29, 228, 47, 107,
|
||||
160, 122, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 30, 148,
|
||||
104, 202, 165, 39, 58, 182,
|
||||
100, 205, 95, 195, 52, 137,
|
||||
197, 241, 1, 0, 0, 0,
|
||||
224, 3, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
132, 0, 0, 0, 204, 0,
|
||||
@ -508,7 +506,7 @@ const BYTE SolidColorShader[] =
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
2, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -599,9 +597,9 @@ const BYTE SolidColorShader[] =
|
||||
76, 83, 76, 32, 83, 104,
|
||||
97, 100, 101, 114, 32, 67,
|
||||
111, 109, 112, 105, 108, 101,
|
||||
114, 32, 57, 46, 51, 48,
|
||||
46, 57, 50, 48, 48, 46,
|
||||
50, 48, 53, 52, 54, 0,
|
||||
114, 32, 54, 46, 51, 46,
|
||||
57, 54, 48, 48, 46, 49,
|
||||
54, 51, 56, 52, 0, 171,
|
||||
73, 83, 71, 78, 80, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
8, 0, 0, 0, 56, 0,
|
||||
@ -629,10 +627,9 @@ const BYTE SolidColorShader[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -716,10 +713,10 @@ ret
|
||||
|
||||
const BYTE RGBShader[] =
|
||||
{
|
||||
68, 88, 66, 67, 195, 54,
|
||||
227, 44, 79, 159, 121, 69,
|
||||
60, 252, 145, 90, 151, 241,
|
||||
175, 162, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 239, 198,
|
||||
87, 206, 69, 92, 245, 30,
|
||||
125, 195, 239, 77, 37, 241,
|
||||
175, 187, 1, 0, 0, 0,
|
||||
232, 4, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
204, 0, 0, 0, 136, 1,
|
||||
@ -795,7 +792,7 @@ const BYTE RGBShader[] =
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -899,9 +896,9 @@ const BYTE RGBShader[] =
|
||||
76, 83, 76, 32, 83, 104,
|
||||
97, 100, 101, 114, 32, 67,
|
||||
111, 109, 112, 105, 108, 101,
|
||||
114, 32, 57, 46, 51, 48,
|
||||
46, 57, 50, 48, 48, 46,
|
||||
50, 48, 53, 52, 54, 0,
|
||||
114, 32, 54, 46, 51, 46,
|
||||
57, 54, 48, 48, 46, 49,
|
||||
54, 51, 56, 52, 0, 171,
|
||||
73, 83, 71, 78, 80, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
8, 0, 0, 0, 56, 0,
|
||||
@ -929,10 +926,9 @@ const BYTE RGBShader[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -1014,10 +1010,10 @@ ret
|
||||
|
||||
const BYTE RGBAShader[] =
|
||||
{
|
||||
68, 88, 66, 67, 124, 18,
|
||||
8, 218, 34, 168, 20, 218,
|
||||
144, 232, 183, 104, 152, 211,
|
||||
5, 26, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 230, 59,
|
||||
90, 23, 60, 77, 18, 113,
|
||||
14, 129, 183, 152, 233, 55,
|
||||
111, 42, 1, 0, 0, 0,
|
||||
196, 4, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
192, 0, 0, 0, 100, 1,
|
||||
@ -1087,7 +1083,7 @@ const BYTE RGBAShader[] =
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -1191,9 +1187,9 @@ const BYTE RGBAShader[] =
|
||||
76, 83, 76, 32, 83, 104,
|
||||
97, 100, 101, 114, 32, 67,
|
||||
111, 109, 112, 105, 108, 101,
|
||||
114, 32, 57, 46, 51, 48,
|
||||
46, 57, 50, 48, 48, 46,
|
||||
50, 48, 53, 52, 54, 0,
|
||||
114, 32, 54, 46, 51, 46,
|
||||
57, 54, 48, 48, 46, 49,
|
||||
54, 51, 56, 52, 0, 171,
|
||||
73, 83, 71, 78, 80, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
8, 0, 0, 0, 56, 0,
|
||||
@ -1221,10 +1217,9 @@ const BYTE RGBAShader[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -1324,10 +1319,10 @@ ret
|
||||
|
||||
const BYTE ComponentAlphaShader[] =
|
||||
{
|
||||
68, 88, 66, 67, 152, 37,
|
||||
117, 77, 87, 153, 20, 62,
|
||||
92, 142, 77, 134, 246, 203,
|
||||
174, 59, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 186, 162,
|
||||
72, 42, 69, 36, 160, 68,
|
||||
108, 121, 216, 238, 108, 37,
|
||||
6, 145, 1, 0, 0, 0,
|
||||
68, 6, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
64, 1, 0, 0, 160, 2,
|
||||
@ -1450,7 +1445,7 @@ const BYTE ComponentAlphaShader[] =
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
3, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -1561,9 +1556,9 @@ const BYTE ComponentAlphaShader[] =
|
||||
76, 83, 76, 32, 83, 104,
|
||||
97, 100, 101, 114, 32, 67,
|
||||
111, 109, 112, 105, 108, 101,
|
||||
114, 32, 57, 46, 51, 48,
|
||||
46, 57, 50, 48, 48, 46,
|
||||
50, 48, 53, 52, 54, 0,
|
||||
114, 32, 54, 46, 51, 46,
|
||||
57, 54, 48, 48, 46, 49,
|
||||
54, 51, 56, 52, 0, 171,
|
||||
73, 83, 71, 78, 80, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
8, 0, 0, 0, 56, 0,
|
||||
@ -1595,10 +1590,9 @@ const BYTE ComponentAlphaShader[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -1714,10 +1708,10 @@ ret
|
||||
|
||||
const BYTE YCbCrShader[] =
|
||||
{
|
||||
68, 88, 66, 67, 26, 187,
|
||||
43, 127, 28, 135, 212, 40,
|
||||
57, 230, 160, 198, 151, 242,
|
||||
106, 110, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 181, 118,
|
||||
100, 53, 248, 120, 136, 92,
|
||||
59, 190, 18, 201, 139, 224,
|
||||
32, 141, 1, 0, 0, 0,
|
||||
212, 7, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
220, 1, 0, 0, 44, 4,
|
||||
@ -1896,7 +1890,7 @@ const BYTE YCbCrShader[] =
|
||||
0, 0, 15, 0, 0, 0,
|
||||
3, 0, 0, 0, 0, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
6, 0, 0, 0, 0, 0,
|
||||
10, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -1906,7 +1900,7 @@ const BYTE YCbCrShader[] =
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
2, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -2022,9 +2016,9 @@ const BYTE YCbCrShader[] =
|
||||
76, 32, 83, 104, 97, 100,
|
||||
101, 114, 32, 67, 111, 109,
|
||||
112, 105, 108, 101, 114, 32,
|
||||
57, 46, 51, 48, 46, 57,
|
||||
50, 48, 48, 46, 50, 48,
|
||||
53, 52, 54, 0, 73, 83,
|
||||
54, 46, 51, 46, 57, 54,
|
||||
48, 48, 46, 49, 54, 51,
|
||||
56, 52, 0, 171, 73, 83,
|
||||
71, 78, 80, 0, 0, 0,
|
||||
2, 0, 0, 0, 8, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
@ -2051,10 +2045,9 @@ const BYTE YCbCrShader[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -2165,10 +2158,10 @@ ret
|
||||
|
||||
const BYTE LayerQuadMaskVS[] =
|
||||
{
|
||||
68, 88, 66, 67, 229, 18,
|
||||
238, 182, 176, 120, 118, 84,
|
||||
74, 135, 103, 188, 146, 51,
|
||||
229, 207, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 223, 251,
|
||||
10, 17, 13, 90, 47, 25,
|
||||
119, 198, 20, 157, 124, 193,
|
||||
251, 234, 1, 0, 0, 0,
|
||||
120, 7, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
224, 1, 0, 0, 76, 4,
|
||||
@ -2352,7 +2345,7 @@ const BYTE LayerQuadMaskVS[] =
|
||||
116, 0, 0, 0, 16, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 4, 0,
|
||||
0, 0, 8, 0, 0, 0,
|
||||
0, 0, 14, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -2362,7 +2355,7 @@ const BYTE LayerQuadMaskVS[] =
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -2453,10 +2446,10 @@ const BYTE LayerQuadMaskVS[] =
|
||||
72, 76, 83, 76, 32, 83,
|
||||
104, 97, 100, 101, 114, 32,
|
||||
67, 111, 109, 112, 105, 108,
|
||||
101, 114, 32, 57, 46, 51,
|
||||
48, 46, 57, 50, 48, 48,
|
||||
46, 50, 48, 53, 52, 54,
|
||||
0, 171, 73, 83, 71, 78,
|
||||
101, 114, 32, 54, 46, 51,
|
||||
46, 57, 54, 48, 48, 46,
|
||||
49, 54, 51, 56, 52, 0,
|
||||
171, 171, 73, 83, 71, 78,
|
||||
44, 0, 0, 0, 1, 0,
|
||||
0, 0, 8, 0, 0, 0,
|
||||
32, 0, 0, 0, 0, 0,
|
||||
@ -2487,10 +2480,9 @@ const BYTE LayerQuadMaskVS[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -2605,10 +2597,10 @@ ret
|
||||
|
||||
const BYTE LayerQuadMask3DVS[] =
|
||||
{
|
||||
68, 88, 66, 67, 81, 198,
|
||||
45, 88, 207, 133, 27, 66,
|
||||
4, 235, 107, 238, 69, 93,
|
||||
43, 232, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 151, 141,
|
||||
11, 11, 111, 244, 17, 242,
|
||||
119, 116, 248, 53, 235, 192,
|
||||
38, 193, 1, 0, 0, 0,
|
||||
204, 7, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
24, 2, 0, 0, 160, 4,
|
||||
@ -2806,7 +2798,7 @@ const BYTE LayerQuadMask3DVS[] =
|
||||
116, 0, 0, 0, 17, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 4, 0,
|
||||
0, 0, 9, 0, 0, 0,
|
||||
0, 0, 15, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -2816,7 +2808,7 @@ const BYTE LayerQuadMask3DVS[] =
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -2907,10 +2899,10 @@ const BYTE LayerQuadMask3DVS[] =
|
||||
72, 76, 83, 76, 32, 83,
|
||||
104, 97, 100, 101, 114, 32,
|
||||
67, 111, 109, 112, 105, 108,
|
||||
101, 114, 32, 57, 46, 51,
|
||||
48, 46, 57, 50, 48, 48,
|
||||
46, 50, 48, 53, 52, 54,
|
||||
0, 171, 73, 83, 71, 78,
|
||||
101, 114, 32, 54, 46, 51,
|
||||
46, 57, 54, 48, 48, 46,
|
||||
49, 54, 51, 56, 52, 0,
|
||||
171, 171, 73, 83, 71, 78,
|
||||
44, 0, 0, 0, 1, 0,
|
||||
0, 0, 8, 0, 0, 0,
|
||||
32, 0, 0, 0, 0, 0,
|
||||
@ -2941,10 +2933,9 @@ const BYTE LayerQuadMask3DVS[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -3028,10 +3019,10 @@ ret
|
||||
|
||||
const BYTE SolidColorShaderMask[] =
|
||||
{
|
||||
68, 88, 66, 67, 110, 173,
|
||||
179, 170, 121, 56, 16, 38,
|
||||
131, 202, 191, 200, 149, 158,
|
||||
191, 136, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 236, 109,
|
||||
19, 151, 23, 187, 157, 205,
|
||||
112, 188, 91, 187, 108, 106,
|
||||
138, 14, 1, 0, 0, 0,
|
||||
232, 4, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
204, 0, 0, 0, 112, 1,
|
||||
@ -3103,7 +3094,7 @@ const BYTE SolidColorShaderMask[] =
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -3207,9 +3198,9 @@ const BYTE SolidColorShaderMask[] =
|
||||
76, 83, 76, 32, 83, 104,
|
||||
97, 100, 101, 114, 32, 67,
|
||||
111, 109, 112, 105, 108, 101,
|
||||
114, 32, 57, 46, 51, 48,
|
||||
46, 57, 50, 48, 48, 46,
|
||||
50, 48, 53, 52, 54, 0,
|
||||
114, 32, 54, 46, 51, 46,
|
||||
57, 54, 48, 48, 46, 49,
|
||||
54, 51, 56, 52, 0, 171,
|
||||
73, 83, 71, 78, 104, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
8, 0, 0, 0, 80, 0,
|
||||
@ -3241,10 +3232,9 @@ const BYTE SolidColorShaderMask[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -3339,10 +3329,10 @@ ret
|
||||
|
||||
const BYTE RGBShaderMask[] =
|
||||
{
|
||||
68, 88, 66, 67, 90, 156,
|
||||
108, 215, 2, 184, 95, 225,
|
||||
139, 102, 23, 57, 234, 197,
|
||||
48, 52, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 30, 30,
|
||||
87, 58, 114, 156, 251, 151,
|
||||
29, 94, 34, 100, 228, 250,
|
||||
37, 251, 1, 0, 0, 0,
|
||||
192, 5, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
8, 1, 0, 0, 32, 2,
|
||||
@ -3443,7 +3433,7 @@ const BYTE RGBShaderMask[] =
|
||||
0, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 2, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -3554,9 +3544,9 @@ const BYTE RGBShaderMask[] =
|
||||
76, 83, 76, 32, 83, 104,
|
||||
97, 100, 101, 114, 32, 67,
|
||||
111, 109, 112, 105, 108, 101,
|
||||
114, 32, 57, 46, 51, 48,
|
||||
46, 57, 50, 48, 48, 46,
|
||||
50, 48, 53, 52, 54, 0,
|
||||
114, 32, 54, 46, 51, 46,
|
||||
57, 54, 48, 48, 46, 49,
|
||||
54, 51, 56, 52, 0, 171,
|
||||
73, 83, 71, 78, 104, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
8, 0, 0, 0, 80, 0,
|
||||
@ -3588,10 +3578,9 @@ const BYTE RGBShaderMask[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -3684,10 +3673,10 @@ ret
|
||||
|
||||
const BYTE RGBAShaderMask[] =
|
||||
{
|
||||
68, 88, 66, 67, 106, 15,
|
||||
51, 47, 230, 18, 55, 40,
|
||||
97, 21, 143, 67, 32, 99,
|
||||
176, 32, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 188, 13,
|
||||
191, 168, 231, 201, 42, 209,
|
||||
88, 243, 29, 35, 226, 31,
|
||||
145, 20, 1, 0, 0, 0,
|
||||
156, 5, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
252, 0, 0, 0, 252, 1,
|
||||
@ -3782,7 +3771,7 @@ const BYTE RGBAShaderMask[] =
|
||||
0, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -3893,9 +3882,9 @@ const BYTE RGBAShaderMask[] =
|
||||
76, 83, 76, 32, 83, 104,
|
||||
97, 100, 101, 114, 32, 67,
|
||||
111, 109, 112, 105, 108, 101,
|
||||
114, 32, 57, 46, 51, 48,
|
||||
46, 57, 50, 48, 48, 46,
|
||||
50, 48, 53, 52, 54, 0,
|
||||
114, 32, 54, 46, 51, 46,
|
||||
57, 54, 48, 48, 46, 49,
|
||||
54, 51, 56, 52, 0, 171,
|
||||
73, 83, 71, 78, 104, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
8, 0, 0, 0, 80, 0,
|
||||
@ -3927,10 +3916,9 @@ const BYTE RGBAShaderMask[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -4028,10 +4016,10 @@ ret
|
||||
|
||||
const BYTE RGBAShaderMask3D[] =
|
||||
{
|
||||
68, 88, 66, 67, 176, 186,
|
||||
72, 64, 199, 228, 205, 219,
|
||||
97, 152, 199, 132, 157, 124,
|
||||
226, 212, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 113, 141,
|
||||
78, 23, 128, 223, 235, 10,
|
||||
0, 97, 49, 111, 47, 53,
|
||||
229, 55, 1, 0, 0, 0,
|
||||
24, 6, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
24, 1, 0, 0, 64, 2,
|
||||
@ -4138,7 +4126,7 @@ const BYTE RGBAShaderMask3D[] =
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -4258,9 +4246,9 @@ const BYTE RGBAShaderMask3D[] =
|
||||
76, 32, 83, 104, 97, 100,
|
||||
101, 114, 32, 67, 111, 109,
|
||||
112, 105, 108, 101, 114, 32,
|
||||
57, 46, 51, 48, 46, 57,
|
||||
50, 48, 48, 46, 50, 48,
|
||||
53, 52, 54, 0, 73, 83,
|
||||
54, 46, 51, 46, 57, 54,
|
||||
48, 48, 46, 49, 54, 51,
|
||||
56, 52, 0, 171, 73, 83,
|
||||
71, 78, 104, 0, 0, 0,
|
||||
3, 0, 0, 0, 8, 0,
|
||||
0, 0, 80, 0, 0, 0,
|
||||
@ -4291,10 +4279,9 @@ const BYTE RGBAShaderMask3D[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -4421,10 +4408,10 @@ ret
|
||||
|
||||
const BYTE YCbCrShaderMask[] =
|
||||
{
|
||||
68, 88, 66, 67, 115, 10,
|
||||
33, 43, 108, 217, 72, 92,
|
||||
140, 65, 97, 68, 194, 221,
|
||||
95, 25, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 103, 162,
|
||||
223, 236, 236, 142, 143, 151,
|
||||
73, 154, 187, 112, 81, 114,
|
||||
229, 251, 1, 0, 0, 0,
|
||||
168, 8, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
24, 2, 0, 0, 196, 4,
|
||||
@ -4628,7 +4615,7 @@ const BYTE YCbCrShaderMask[] =
|
||||
116, 0, 0, 0, 17, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0,
|
||||
0, 0, 7, 0, 0, 0,
|
||||
0, 0, 11, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -4638,7 +4625,7 @@ const BYTE YCbCrShaderMask[] =
|
||||
4, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -4760,9 +4747,9 @@ const BYTE YCbCrShaderMask[] =
|
||||
76, 83, 76, 32, 83, 104,
|
||||
97, 100, 101, 114, 32, 67,
|
||||
111, 109, 112, 105, 108, 101,
|
||||
114, 32, 57, 46, 51, 48,
|
||||
46, 57, 50, 48, 48, 46,
|
||||
50, 48, 53, 52, 54, 0,
|
||||
114, 32, 54, 46, 51, 46,
|
||||
57, 54, 48, 48, 46, 49,
|
||||
54, 51, 56, 52, 0, 171,
|
||||
73, 83, 71, 78, 104, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
8, 0, 0, 0, 80, 0,
|
||||
@ -4794,10 +4781,9 @@ const BYTE YCbCrShaderMask[] =
|
||||
};
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
|
||||
//
|
||||
//
|
||||
///
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer $Globals
|
||||
@ -4908,10 +4894,10 @@ ret
|
||||
|
||||
const BYTE ComponentAlphaShaderMask[] =
|
||||
{
|
||||
68, 88, 66, 67, 66, 175,
|
||||
106, 103, 136, 76, 200, 80,
|
||||
95, 179, 74, 140, 138, 144,
|
||||
12, 21, 1, 0, 0, 0,
|
||||
68, 88, 66, 67, 245, 71,
|
||||
211, 223, 156, 101, 223, 204,
|
||||
145, 138, 53, 12, 16, 220,
|
||||
106, 83, 1, 0, 0, 0,
|
||||
20, 7, 0, 0, 6, 0,
|
||||
0, 0, 56, 0, 0, 0,
|
||||
124, 1, 0, 0, 52, 3,
|
||||
@ -5058,7 +5044,7 @@ const BYTE ComponentAlphaShaderMask[] =
|
||||
0, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
@ -5176,9 +5162,9 @@ const BYTE ComponentAlphaShaderMask[] =
|
||||
76, 32, 83, 104, 97, 100,
|
||||
101, 114, 32, 67, 111, 109,
|
||||
112, 105, 108, 101, 114, 32,
|
||||
57, 46, 51, 48, 46, 57,
|
||||
50, 48, 48, 46, 50, 48,
|
||||
53, 52, 54, 0, 73, 83,
|
||||
54, 46, 51, 46, 57, 54,
|
||||
48, 48, 46, 49, 54, 51,
|
||||
56, 52, 0, 171, 73, 83,
|
||||
71, 78, 104, 0, 0, 0,
|
||||
3, 0, 0, 0, 8, 0,
|
||||
0, 0, 80, 0, 0, 0,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -37,13 +37,16 @@ SamplerState Linear
|
||||
AddressV = Clamp;
|
||||
};
|
||||
|
||||
/*
|
||||
* Oculus basic distortion, with chroma aberration correction
|
||||
*/
|
||||
VS_VR_OUTPUT OculusVRDistortionVS(const VS_VR_INPUT aVertex)
|
||||
{
|
||||
VS_VR_OUTPUT res;
|
||||
|
||||
float2 tc0 = VREyeToSource.xy * aVertex.vTexCoord0 + VREyeToSource.zw;
|
||||
float2 tc1 = VREyeToSource.xy * aVertex.vTexCoord1 + VREyeToSource.zw;
|
||||
float2 tc2 = VREyeToSource.xy * aVertex.vTexCoord2 + VREyeToSource.zw;
|
||||
float2 tc0 = aVertex.vTexCoord0 * VREyeToSource.zw + VREyeToSource.xy;
|
||||
float2 tc1 = aVertex.vTexCoord1 * VREyeToSource.zw + VREyeToSource.xy;
|
||||
float2 tc2 = aVertex.vTexCoord2 * VREyeToSource.zw + VREyeToSource.xy;
|
||||
|
||||
//res.vPosition.xy = aVertex.vPosition.xy;
|
||||
res.vPosition.xy = aVertex.vPosition.xy * VRDestinationScaleAndOffset.zw + VRDestinationScaleAndOffset.xy;
|
||||
|
@ -178,6 +178,7 @@ struct CompositorOGLVRObjects {
|
||||
GLint mUTexture[2];
|
||||
GLint mUVREyeToSource[2];
|
||||
GLint mUVRDestionatinScaleAndOffset[2];
|
||||
GLint mUHeight[2];
|
||||
};
|
||||
|
||||
// If you want to make this class not final, first remove calls to virtual
|
||||
|
@ -55,6 +55,7 @@ CompositorOGL::InitializeVR()
|
||||
|
||||
vs << "uniform vec4 uVREyeToSource;\n";
|
||||
vs << "uniform vec4 uVRDestinationScaleAndOffset;\n";
|
||||
vs << "uniform float uHeight;\n";
|
||||
vs << "attribute vec2 aPosition;\n";
|
||||
vs << "attribute vec2 aTexCoord0;\n";
|
||||
vs << "attribute vec2 aTexCoord1;\n";
|
||||
@ -66,12 +67,12 @@ CompositorOGL::InitializeVR()
|
||||
vs << "varying vec4 vGenericAttribs;\n";
|
||||
vs << "void main() {\n";
|
||||
vs << " gl_Position = vec4(aPosition.xy * uVRDestinationScaleAndOffset.zw + uVRDestinationScaleAndOffset.xy, 0.5, 1.0);\n";
|
||||
vs << " vTexCoord0 = uVREyeToSource.xy * aTexCoord0 + uVREyeToSource.zw;\n";
|
||||
vs << " vTexCoord1 = uVREyeToSource.xy * aTexCoord1 + uVREyeToSource.zw;\n";
|
||||
vs << " vTexCoord2 = uVREyeToSource.xy * aTexCoord2 + uVREyeToSource.zw;\n";
|
||||
vs << " vTexCoord0.y = 1.0 - vTexCoord0.y;\n";
|
||||
vs << " vTexCoord1.y = 1.0 - vTexCoord1.y;\n";
|
||||
vs << " vTexCoord2.y = 1.0 - vTexCoord2.y;\n";
|
||||
vs << " vTexCoord0 = uVREyeToSource.zw * aTexCoord0 + uVREyeToSource.xy;\n";
|
||||
vs << " vTexCoord1 = uVREyeToSource.zw * aTexCoord1 + uVREyeToSource.xy;\n";
|
||||
vs << " vTexCoord2 = uVREyeToSource.zw * aTexCoord2 + uVREyeToSource.xy;\n";
|
||||
vs << " vTexCoord0.y = uHeight - vTexCoord0.y;\n";
|
||||
vs << " vTexCoord1.y = uHeight - vTexCoord1.y;\n";
|
||||
vs << " vTexCoord2.y = uHeight - vTexCoord2.y;\n";
|
||||
vs << " vGenericAttribs = aGenericAttribs;\n";
|
||||
vs << "}\n";
|
||||
|
||||
@ -97,7 +98,6 @@ CompositorOGL::InitializeVR()
|
||||
}
|
||||
|
||||
fs << "uniform " << sampler2D << " uTexture;\n";
|
||||
|
||||
fs << "varying vec2 vTexCoord0;\n";
|
||||
fs << "varying vec2 vTexCoord1;\n";
|
||||
fs << "varying vec2 vTexCoord2;\n";
|
||||
@ -179,6 +179,7 @@ CompositorOGL::InitializeVR()
|
||||
mVR.mUTexture[programIndex] = gl()->fGetUniformLocation(prog, "uTexture");
|
||||
mVR.mUVREyeToSource[programIndex] = gl()->fGetUniformLocation(prog, "uVREyeToSource");
|
||||
mVR.mUVRDestionatinScaleAndOffset[programIndex] = gl()->fGetUniformLocation(prog, "uVRDestinationScaleAndOffset");
|
||||
mVR.mUHeight[programIndex] = gl()->fGetUniformLocation(prog, "uHeight");
|
||||
|
||||
mVR.mDistortionProgram[programIndex] = prog;
|
||||
|
||||
@ -267,6 +268,10 @@ CompositorOGL::DrawVRDistortion(const gfx::Rect& aRect,
|
||||
gl()->fClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
gl()->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Make sure that the cached current program is reset for the
|
||||
// rest of the compositor, since we're using a custom program here
|
||||
ResetProgram();
|
||||
|
||||
gl()->fUseProgram(mVR.mDistortionProgram[programIndex]);
|
||||
|
||||
gl()->fEnableVertexAttribArray(mVR.mAPosition);
|
||||
@ -293,21 +298,32 @@ CompositorOGL::DrawVRDistortion(const gfx::Rect& aRect,
|
||||
vpSize, aRect,
|
||||
shaderConstants);
|
||||
|
||||
float height = 1.0f;
|
||||
float texScaleAndOffset[4] = { shaderConstants.eyeToSourceScaleAndOffset[0],
|
||||
shaderConstants.eyeToSourceScaleAndOffset[1],
|
||||
shaderConstants.eyeToSourceScaleAndOffset[2],
|
||||
shaderConstants.eyeToSourceScaleAndOffset[3] };
|
||||
if (textureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) {
|
||||
texScaleAndOffset[0] *= size.width;
|
||||
texScaleAndOffset[1] *= size.height;
|
||||
texScaleAndOffset[2] *= size.width;
|
||||
texScaleAndOffset[3] *= size.height;
|
||||
height = size.height;
|
||||
}
|
||||
|
||||
gl()->fUniform4fv(mVR.mUVRDestionatinScaleAndOffset[programIndex], 1, shaderConstants.destinationScaleAndOffset);
|
||||
gl()->fUniform4fv(mVR.mUVREyeToSource[programIndex], 1, shaderConstants.eyeToSourceScaleAndOffset);
|
||||
gl()->fUniform4fv(mVR.mUVREyeToSource[programIndex], 1, texScaleAndOffset);
|
||||
gl()->fUniform1f(mVR.mUHeight[programIndex], height);
|
||||
|
||||
gl()->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mVR.mDistortionVertices[eye]);
|
||||
|
||||
gl()->fVertexAttribPointer(mVR.mAPosition, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex),
|
||||
(void*) offsetof(gfx::VRDistortionVertex, pos));
|
||||
gl()->fVertexAttribPointer(mVR.mATexCoord0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex),
|
||||
(void*) offsetof(gfx::VRDistortionVertex, texR));
|
||||
gl()->fVertexAttribPointer(mVR.mATexCoord1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex),
|
||||
(void*) offsetof(gfx::VRDistortionVertex, texG));
|
||||
gl()->fVertexAttribPointer(mVR.mATexCoord2, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex),
|
||||
(void*) offsetof(gfx::VRDistortionVertex, texB));
|
||||
gl()->fVertexAttribPointer(mVR.mAGenericAttribs, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex),
|
||||
(void*) offsetof(gfx::VRDistortionVertex, genericAttribs));
|
||||
/* This is for Oculus DistortionVertex */
|
||||
|
||||
gl()->fVertexAttribPointer(mVR.mAPosition, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex), (void*) (sizeof(float) * 0));
|
||||
gl()->fVertexAttribPointer(mVR.mATexCoord0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex), (void*) (sizeof(float) * 2));
|
||||
gl()->fVertexAttribPointer(mVR.mATexCoord1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex), (void*) (sizeof(float) * 4));
|
||||
gl()->fVertexAttribPointer(mVR.mATexCoord2, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex), (void*) (sizeof(float) * 6));
|
||||
gl()->fVertexAttribPointer(mVR.mAGenericAttribs, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex), (void*) (sizeof(float) * 8));
|
||||
|
||||
gl()->fBindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER, mVR.mDistortionIndices[eye]);
|
||||
gl()->fDrawElements(LOCAL_GL_TRIANGLES, mVR.mDistortionIndexCount[eye], LOCAL_GL_UNSIGNED_SHORT, 0);
|
||||
|
@ -23,6 +23,7 @@ DIRS += [
|
||||
'ots/src',
|
||||
'thebes',
|
||||
'ipc',
|
||||
'vr',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_ENABLE_SKIA']:
|
||||
|
@ -403,9 +403,8 @@ gfxPlatform::gfxPlatform()
|
||||
contentMask, BackendType::CAIRO);
|
||||
mTotalSystemMemory = mozilla::hal::GetTotalSystemMemory();
|
||||
|
||||
// give ovr_Initialize a chance to be called very early on; we don't
|
||||
// care if it succeeds or not
|
||||
VRHMDManagerOculus::PlatformInit();
|
||||
// give HMDs a chance to be initialized very early on
|
||||
VRHMDManager::ManagerInit();
|
||||
}
|
||||
|
||||
gfxPlatform*
|
||||
@ -700,7 +699,7 @@ gfxPlatform::~gfxPlatform()
|
||||
mScreenReferenceDrawTarget = nullptr;
|
||||
|
||||
// Clean up any VR stuff
|
||||
VRHMDManagerOculus::Destroy();
|
||||
VRHMDManager::ManagerDestroy();
|
||||
|
||||
// The cairo folks think we should only clean up in debug builds,
|
||||
// but we're generally in the habit of trying to shut down as
|
||||
|
@ -929,8 +929,15 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
|
||||
}
|
||||
|
||||
if (aMetrics) {
|
||||
*aMetrics = MeasureText(aStart, charsFit - trimmableChars,
|
||||
*aMetrics = MeasureText(aStart, charsFit,
|
||||
aBoundingBoxType, aRefContext, aProvider);
|
||||
if (trimmableChars) {
|
||||
Metrics trimMetrics =
|
||||
MeasureText(aStart + charsFit - trimmableChars,
|
||||
trimmableChars, aBoundingBoxType,
|
||||
aRefContext, aProvider);
|
||||
aMetrics->mAdvanceWidth -= trimMetrics.mAdvanceWidth;
|
||||
}
|
||||
}
|
||||
if (aTrimWhitespace) {
|
||||
*aTrimWhitespace = trimmableAdvance;
|
||||
|
@ -1875,7 +1875,6 @@ gfxWindowsPlatform::InitD3D11Devices()
|
||||
MOZ_ASSERT(!mD3D11Device);
|
||||
|
||||
bool useWARP = false;
|
||||
ScopedGfxFeatureReporter reporterWARP("D3D11-WARP", gfxPrefs::LayersD3D11ForceWARP());
|
||||
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
|
||||
if (gfxInfo) {
|
||||
@ -1962,6 +1961,7 @@ gfxWindowsPlatform::InitD3D11Devices()
|
||||
MOZ_ASSERT(!mD3D11Device);
|
||||
MOZ_ASSERT(!adapter);
|
||||
|
||||
ScopedGfxFeatureReporter reporterWARP("D3D11-WARP", gfxPrefs::LayersD3D11ForceWARP());
|
||||
hr = d3d11CreateDevice(nullptr, D3D_DRIVER_TYPE_WARP, nullptr,
|
||||
// Use
|
||||
// D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
|
||||
|
@ -49,7 +49,6 @@ EXPORTS += [
|
||||
'gfxTypes.h',
|
||||
'gfxUserFontSet.h',
|
||||
'gfxUtils.h',
|
||||
'gfxVR.h',
|
||||
'GraphicsFilter.h',
|
||||
'RoundedRect.h',
|
||||
'SoftwareVsyncSource.h',
|
||||
@ -244,7 +243,6 @@ UNIFIED_SOURCES += [
|
||||
'gfxTextRun.cpp',
|
||||
'gfxUserFontSet.cpp',
|
||||
'gfxUtils.cpp',
|
||||
'gfxVR.cpp',
|
||||
'nsUnicodeRange.cpp',
|
||||
'SoftwareVsyncSource.cpp',
|
||||
'VsyncSource.cpp',
|
||||
|
@ -1,228 +0,0 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/* This file contains just the needed struct definitions for
|
||||
* interacting with the Oculus VR C API, without needing to #include
|
||||
* OVR_CAPI.h directly. Note that it uses the same type names as the
|
||||
* CAPI, and cannot be #included at the same time as OVR_CAPI.h. It
|
||||
* does not include the entire C API, just want's needed.
|
||||
*/
|
||||
|
||||
#ifdef OVR_CAPI_h
|
||||
#warning OVR_CAPI.h included before ovr_capi_dynamic.h, skpping this
|
||||
#define mozilla_ovr_capi_dynamic_h_
|
||||
#endif
|
||||
|
||||
#ifndef mozilla_ovr_capi_dynamic_h_
|
||||
#define mozilla_ovr_capi_dynamic_h_
|
||||
|
||||
#define OVR_CAPI_LIMITED_MOZILLA 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef char ovrBool;
|
||||
typedef struct { int x, y; } ovrVector2i;
|
||||
typedef struct { int w, h; } ovrSizei;
|
||||
typedef struct { ovrVector2i Pos; ovrSizei Size; } ovrRecti;
|
||||
typedef struct { float x, y, z, w; } ovrQuatf;
|
||||
typedef struct { float x, y; } ovrVector2f;
|
||||
typedef struct { float x, y, z; } ovrVector3f;
|
||||
typedef struct { float M[4][4]; } ovrMatrix4f;
|
||||
|
||||
typedef struct {
|
||||
ovrQuatf Orientation;
|
||||
ovrVector3f Position;
|
||||
} ovrPosef;
|
||||
|
||||
typedef struct {
|
||||
ovrPosef ThePose;
|
||||
ovrVector3f AngularVelocity;
|
||||
ovrVector3f LinearVelocity;
|
||||
ovrVector3f AngularAcceleration;
|
||||
ovrVector3f LinearAcceleration;
|
||||
double TimeInSeconds;
|
||||
} ovrPoseStatef;
|
||||
|
||||
typedef struct {
|
||||
float UpTan;
|
||||
float DownTan;
|
||||
float LeftTan;
|
||||
float RightTan;
|
||||
} ovrFovPort;
|
||||
|
||||
typedef enum {
|
||||
ovrHmd_None = 0,
|
||||
ovrHmd_DK1 = 3,
|
||||
ovrHmd_DKHD = 4,
|
||||
ovrHmd_DK2 = 6,
|
||||
ovrHmd_Other
|
||||
} ovrHmdType;
|
||||
|
||||
typedef enum {
|
||||
ovrHmdCap_Present = 0x0001,
|
||||
ovrHmdCap_Available = 0x0002,
|
||||
ovrHmdCap_Captured = 0x0004,
|
||||
ovrHmdCap_ExtendDesktop = 0x0008,
|
||||
ovrHmdCap_DisplayOff = 0x0040,
|
||||
ovrHmdCap_LowPersistence = 0x0080,
|
||||
ovrHmdCap_DynamicPrediction = 0x0200,
|
||||
ovrHmdCap_NoVSync = 0x1000,
|
||||
ovrHmdCap_NoMirrorToWindow = 0x2000
|
||||
} ovrHmdCapBits;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ovrTrackingCap_Orientation = 0x0010,
|
||||
ovrTrackingCap_MagYawCorrection = 0x0020,
|
||||
ovrTrackingCap_Position = 0x0040,
|
||||
ovrTrackingCap_Idle = 0x0100
|
||||
} ovrTrackingCaps;
|
||||
|
||||
typedef enum {
|
||||
ovrDistortionCap_Chromatic = 0x01,
|
||||
ovrDistortionCap_TimeWarp = 0x02,
|
||||
ovrDistortionCap_Vignette = 0x08,
|
||||
ovrDistortionCap_NoRestore = 0x10,
|
||||
ovrDistortionCap_FlipInput = 0x20,
|
||||
ovrDistortionCap_SRGB = 0x40,
|
||||
ovrDistortionCap_Overdrive = 0x80,
|
||||
ovrDistortionCap_ProfileNoTimewarpSpinWaits = 0x10000
|
||||
} ovrDistortionCaps;
|
||||
|
||||
typedef enum {
|
||||
ovrEye_Left = 0,
|
||||
ovrEye_Right = 1,
|
||||
ovrEye_Count = 2
|
||||
} ovrEyeType;
|
||||
|
||||
typedef struct ovrHmdDesc_ {
|
||||
void* Handle;
|
||||
ovrHmdType Type;
|
||||
const char* ProductName;
|
||||
const char* Manufacturer;
|
||||
short VendorId;
|
||||
short ProductId;
|
||||
char SerialNumber[24];
|
||||
short FirmwareMajor;
|
||||
short FirmwareMinor;
|
||||
float CameraFrustumHFovInRadians;
|
||||
float CameraFrustumVFovInRadians;
|
||||
float CameraFrustumNearZInMeters;
|
||||
float CameraFrustumFarZInMeters;
|
||||
|
||||
unsigned int HmdCaps;
|
||||
unsigned int TrackingCaps;
|
||||
unsigned int DistortionCaps;
|
||||
|
||||
ovrFovPort DefaultEyeFov[ovrEye_Count];
|
||||
ovrFovPort MaxEyeFov[ovrEye_Count];
|
||||
ovrEyeType EyeRenderOrder[ovrEye_Count];
|
||||
|
||||
ovrSizei Resolution;
|
||||
ovrVector2i WindowsPos;
|
||||
|
||||
const char* DisplayDeviceName;
|
||||
int DisplayId;
|
||||
} ovrHmdDesc;
|
||||
|
||||
typedef const ovrHmdDesc* ovrHmd;
|
||||
|
||||
typedef enum {
|
||||
ovrStatus_OrientationTracked = 0x0001,
|
||||
ovrStatus_PositionTracked = 0x0002,
|
||||
ovrStatus_CameraPoseTracked = 0x0004,
|
||||
ovrStatus_PositionConnected = 0x0020,
|
||||
ovrStatus_HmdConnected = 0x0080
|
||||
} ovrStatusBits;
|
||||
|
||||
typedef struct ovrSensorData_ {
|
||||
ovrVector3f Accelerometer;
|
||||
ovrVector3f Gyro;
|
||||
ovrVector3f Magnetometer;
|
||||
float Temperature;
|
||||
float TimeInSeconds;
|
||||
} ovrSensorData;
|
||||
|
||||
|
||||
typedef struct ovrTrackingState_ {
|
||||
ovrPoseStatef HeadPose;
|
||||
ovrPosef CameraPose;
|
||||
ovrPosef LeveledCameraPose;
|
||||
ovrSensorData RawSensorData;
|
||||
unsigned int StatusFlags;
|
||||
double LastVisionProcessingTime;
|
||||
double LastVisionFrameLatency;
|
||||
uint32_t LastCameraFrameCounter;
|
||||
} ovrTrackingState;
|
||||
|
||||
typedef struct ovrFrameTiming_ {
|
||||
float DeltaSeconds;
|
||||
double ThisFrameSeconds;
|
||||
double TimewarpPointSeconds;
|
||||
double NextFrameSeconds;
|
||||
double ScanoutMidpointSeconds;
|
||||
double EyeScanoutSeconds[2];
|
||||
} ovrFrameTiming;
|
||||
|
||||
typedef struct ovrEyeRenderDesc_ {
|
||||
ovrEyeType Eye;
|
||||
ovrFovPort Fov;
|
||||
ovrRecti DistortedViewport;
|
||||
ovrVector2f PixelsPerTanAngleAtCenter;
|
||||
ovrVector3f ViewAdjust;
|
||||
} ovrEyeRenderDesc;
|
||||
|
||||
typedef struct ovrDistortionVertex_ {
|
||||
ovrVector2f ScreenPosNDC;
|
||||
float TimeWarpFactor;
|
||||
float VignetteFactor;
|
||||
ovrVector2f TanEyeAnglesR;
|
||||
ovrVector2f TanEyeAnglesG;
|
||||
ovrVector2f TanEyeAnglesB;
|
||||
} ovrDistortionVertex;
|
||||
|
||||
typedef struct ovrDistortionMesh_ {
|
||||
ovrDistortionVertex* pVertexData;
|
||||
unsigned short* pIndexData;
|
||||
unsigned int VertexCount;
|
||||
unsigned int IndexCount;
|
||||
} ovrDistortionMesh;
|
||||
|
||||
typedef ovrBool (*pfn_ovr_Initialize)();
|
||||
typedef void (*pfn_ovr_Shutdown)();
|
||||
typedef int (*pfn_ovrHmd_Detect)();
|
||||
typedef ovrHmd (*pfn_ovrHmd_Create)(int index);
|
||||
typedef void (*pfn_ovrHmd_Destroy)(ovrHmd hmd);
|
||||
typedef ovrHmd (*pfn_ovrHmd_CreateDebug)(ovrHmdType type);
|
||||
typedef const char* (*pfn_ovrHmd_GetLastError)(ovrHmd hmd);
|
||||
typedef ovrBool (*pfn_ovrHmd_AttachToWindow)(ovrHmd hmd, void* window, const ovrRecti* destMirrorRect, const ovrRecti* sourceRenderTargetRect);
|
||||
typedef unsigned int (*pfn_ovrHmd_GetEnabledCaps)(ovrHmd hmd);
|
||||
typedef void (*pfn_ovrHmd_SetEnabledCaps)(ovrHmd hmd, unsigned int hmdCaps);
|
||||
typedef ovrBool (*pfn_ovrHmd_ConfigureTracking)(ovrHmd hmd, unsigned int supportedTrackingCaps, unsigned int requiredTrackingCaps);
|
||||
typedef void (*pfn_ovrHmd_RecenterPose)(ovrHmd hmd);
|
||||
typedef ovrTrackingState (*pfn_ovrHmd_GetTrackingState)(ovrHmd hmd, double absTime);
|
||||
typedef ovrSizei (*pfn_ovrHmd_GetFovTextureSize)(ovrHmd hmd, ovrEyeType eye, ovrFovPort fov, float pixelsPerDisplayPixel);
|
||||
typedef ovrEyeRenderDesc (*pfn_ovrHmd_GetRenderDesc)(ovrHmd hmd, ovrEyeType eyeType, ovrFovPort fov);
|
||||
typedef ovrBool (*pfn_ovrHmd_CreateDistortionMesh)(ovrHmd hmd, ovrEyeType eyeType, ovrFovPort fov, unsigned int distortionCaps, ovrDistortionMesh *meshData);
|
||||
typedef void (*pfn_ovrHmd_DestroyDistortionMesh)(ovrDistortionMesh* meshData);
|
||||
typedef void (*pfn_ovrHmd_GetRenderScaleAndOffset)(ovrFovPort fov, ovrSizei textureSize, ovrRecti renderViewport, ovrVector2f uvScaleOffsetOut[2]);
|
||||
typedef ovrFrameTiming (*pfn_ovrHmd_GetFrameTiming)(ovrHmd hmd, unsigned int frameIndex);
|
||||
typedef ovrFrameTiming (*pfn_ovrHmd_BeginFrameTiming)(ovrHmd hmd, unsigned int frameIndex);
|
||||
typedef void (*pfn_ovrHmd_EndFrameTiming)(ovrHmd hmd);
|
||||
typedef void (*pfn_ovrHmd_ResetFrameTiming)(ovrHmd hmd, unsigned int frameIndex, bool vsync);
|
||||
typedef void (*pfn_ovrHmd_GetEyePoses)(ovrHmd hmd, unsigned int frameIndex, ovrVector3f hmdToEyeViewOffset[2], ovrPosef outEyePoses[2], ovrTrackingState* outHmdTrackingState);
|
||||
typedef ovrPosef (*pfn_ovrHmd_GetHmdPosePerEye)(ovrHmd hmd, ovrEyeType eye);
|
||||
typedef void (*pfn_ovrHmd_GetEyeTimewarpMatrices)(ovrHmd hmd, ovrEyeType eye, ovrPosef renderPose, ovrMatrix4f twmOut[2]);
|
||||
typedef ovrMatrix4f (*pfn_ovrMatrix4f_Projection) (ovrFovPort fov, float znear, float zfar, ovrBool rightHanded );
|
||||
typedef ovrMatrix4f (*pfn_ovrMatrix4f_OrthoSubProjection) (ovrFovPort fov, ovrVector2f orthoScale, float orthoDistance, float eyeViewAdjustX);
|
||||
typedef double (*pfn_ovr_GetTimeInSeconds)();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_ovr_capi_dynamic_h_ */
|
118
gfx/vr/gfxVR.cpp
Normal file
118
gfx/vr/gfxVR.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/* -*- Mode: C++; tab-width: 20; 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 <math.h>
|
||||
|
||||
#include "prlink.h"
|
||||
#include "prmem.h"
|
||||
#include "prenv.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "gfxPrefs.h"
|
||||
#include "gfxVR.h"
|
||||
#include "gfxVROculus.h"
|
||||
#include "gfxVRCardboard.h"
|
||||
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIScreenManager.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
// Dummy nsIScreen implementation, for when we just need to specify a size
|
||||
class FakeScreen : public nsIScreen
|
||||
{
|
||||
public:
|
||||
explicit FakeScreen(const IntRect& aScreenRect)
|
||||
: mScreenRect(aScreenRect)
|
||||
{ }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD GetRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
|
||||
*l = mScreenRect.x;
|
||||
*t = mScreenRect.y;
|
||||
*w = mScreenRect.width;
|
||||
*h = mScreenRect.height;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHOD GetAvailRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
|
||||
return GetRect(l, t, w, h);
|
||||
}
|
||||
NS_IMETHOD GetRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
|
||||
return GetRect(l, t, w, h);
|
||||
}
|
||||
NS_IMETHOD GetAvailRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
|
||||
return GetAvailRect(l, t, w, h);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetId(uint32_t* aId) override { *aId = (uint32_t)-1; return NS_OK; }
|
||||
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override { *aPixelDepth = 24; return NS_OK; }
|
||||
NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override { *aColorDepth = 24; return NS_OK; }
|
||||
|
||||
NS_IMETHOD LockMinimumBrightness(uint32_t aBrightness) override { return NS_ERROR_NOT_AVAILABLE; }
|
||||
NS_IMETHOD UnlockMinimumBrightness(uint32_t aBrightness) override { return NS_ERROR_NOT_AVAILABLE; }
|
||||
NS_IMETHOD GetRotation(uint32_t* aRotation) override {
|
||||
*aRotation = nsIScreen::ROTATION_0_DEG;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHOD SetRotation(uint32_t aRotation) override { return NS_ERROR_NOT_AVAILABLE; }
|
||||
NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) override {
|
||||
*aContentsScaleFactor = 1.0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~FakeScreen() {}
|
||||
|
||||
IntRect mScreenRect;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(FakeScreen, nsIScreen)
|
||||
|
||||
VRHMDManager::VRHMDManagerArray *VRHMDManager::sManagers = nullptr;
|
||||
|
||||
/* static */ void
|
||||
VRHMDManager::ManagerInit()
|
||||
{
|
||||
if (sManagers)
|
||||
return;
|
||||
|
||||
sManagers = new VRHMDManagerArray();
|
||||
|
||||
nsRefPtr<VRHMDManager> mgr;
|
||||
|
||||
mgr = new VRHMDManagerOculus();
|
||||
if (mgr->PlatformInit())
|
||||
sManagers->AppendElement(mgr);
|
||||
|
||||
mgr = new VRHMDManagerCardboard();
|
||||
if (mgr->PlatformInit())
|
||||
sManagers->AppendElement(mgr);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
VRHMDManager::ManagerDestroy()
|
||||
{
|
||||
if (!sManagers)
|
||||
return;
|
||||
|
||||
for (uint32_t i = 0; i < sManagers->Length(); ++i) {
|
||||
(*sManagers)[i]->Destroy();
|
||||
}
|
||||
|
||||
delete sManagers;
|
||||
sManagers = nullptr;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
VRHMDManager::GetAllHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult)
|
||||
{
|
||||
if (!sManagers)
|
||||
return;
|
||||
|
||||
for (uint32_t i = 0; i < sManagers->Length(); ++i) {
|
||||
(*sManagers)[i]->GetHMDs(aHMDResult);
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ namespace gfx {
|
||||
|
||||
enum class VRHMDType : uint16_t {
|
||||
Oculus,
|
||||
Cardboard,
|
||||
NumHMDTypes
|
||||
};
|
||||
|
||||
@ -69,11 +70,7 @@ struct VRDistortionConstants {
|
||||
};
|
||||
|
||||
struct VRDistortionVertex {
|
||||
float pos[2];
|
||||
float texR[2];
|
||||
float texG[2];
|
||||
float texB[2];
|
||||
float genericAttribs[4];
|
||||
float values[12];
|
||||
};
|
||||
|
||||
struct VRDistortionMesh {
|
||||
@ -201,14 +198,27 @@ protected:
|
||||
nsCOMPtr<nsIScreen> mScreen;
|
||||
};
|
||||
|
||||
class VRHMDManagerOculusImpl;
|
||||
class VRHMDManagerOculus {
|
||||
static VRHMDManagerOculusImpl *mImpl;
|
||||
class VRHMDManager {
|
||||
public:
|
||||
static bool PlatformInit();
|
||||
static bool Init();
|
||||
static void Destroy();
|
||||
static void GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo> >& aHMDResult);
|
||||
static void ManagerInit();
|
||||
static void ManagerDestroy();
|
||||
static void GetAllHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult);
|
||||
|
||||
protected:
|
||||
typedef nsTArray<nsRefPtr<VRHMDManager>> VRHMDManagerArray;
|
||||
static VRHMDManagerArray *sManagers;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRHMDManager)
|
||||
|
||||
virtual bool PlatformInit() = 0;
|
||||
virtual bool Init() = 0;
|
||||
virtual void Destroy() = 0;
|
||||
virtual void GetHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult) = 0;
|
||||
|
||||
protected:
|
||||
VRHMDManager() { }
|
||||
virtual ~VRHMDManager() { }
|
||||
};
|
||||
|
||||
} // namespace gfx
|
382
gfx/vr/gfxVRCardboard.cpp
Normal file
382
gfx/vr/gfxVRCardboard.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
/* -*- Mode: C++; tab-width: 20; 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 <math.h>
|
||||
|
||||
#include "prlink.h"
|
||||
#include "prmem.h"
|
||||
#include "prenv.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/dom/ScreenOrientation.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Hal.h"
|
||||
|
||||
#include "gfxVRCardboard.h"
|
||||
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIScreenManager.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoVR" , ## args)
|
||||
#else
|
||||
#define LOG(...) do { } while(0)
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
// 1/sqrt(2) (aka sqrt(2)/2)
|
||||
#ifndef M_SQRT1_2
|
||||
# define M_SQRT1_2 0.70710678118654752440
|
||||
#endif
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gfx::impl;
|
||||
|
||||
namespace {
|
||||
// some utility functions
|
||||
|
||||
// This remaps axes in the given matrix to a new configuration based on the
|
||||
// screen orientation. Similar to what Android SensorManager.remapCoordinateSystem
|
||||
// does, except only for a fixed number of transforms that we need.
|
||||
Matrix4x4
|
||||
RemapMatrixForOrientation(ScreenOrientation screenConfig, const Matrix4x4& aMatrix)
|
||||
{
|
||||
Matrix4x4 out;
|
||||
const float *in = &aMatrix._11;
|
||||
float *o = &out._11;
|
||||
|
||||
if (screenConfig == eScreenOrientation_LandscapePrimary) {
|
||||
// remap X,Y -> Y,-X
|
||||
o[0] = -in[1]; o[1] = in[0]; o[2] = in[2];
|
||||
o[4] = -in[5]; o[5] = in[4]; o[6] = in[6];
|
||||
o[8] = -in[9]; o[9] = in[8]; o[10] = in[10];
|
||||
} else if (screenConfig == eScreenOrientation_LandscapeSecondary) {
|
||||
// remap X,Y -> -Y,X
|
||||
o[0] = in[1]; o[1] = -in[0]; o[2] = in[2];
|
||||
o[4] = in[5]; o[5] = -in[4]; o[6] = in[6];
|
||||
o[8] = in[9]; o[9] = -in[8]; o[10] = in[10];
|
||||
} else if (screenConfig == eScreenOrientation_PortraitPrimary ||
|
||||
screenConfig == eScreenOrientation_PortraitSecondary)
|
||||
{
|
||||
// remap X,Y -> X,-Z
|
||||
o[0] = in[0]; o[1] = in[2]; o[2] = -in[1];
|
||||
o[4] = in[4]; o[5] = in[6]; o[6] = -in[5];
|
||||
o[8] = in[8]; o[9] = in[10]; o[10] = -in[9];
|
||||
} else {
|
||||
MOZ_ASSERT(0, "gfxVRCardboard::RemapMatrixForOrientation invalid screenConfig");
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HMDInfoCardboard::HMDInfoCardboard()
|
||||
: VRHMDInfo(VRHMDType::Cardboard)
|
||||
, mStartCount(0)
|
||||
, mOrient(eScreenOrientation_PortraitPrimary)
|
||||
{
|
||||
MOZ_ASSERT(sizeof(HMDInfoCardboard::DistortionVertex) == sizeof(VRDistortionVertex),
|
||||
"HMDInfoCardboard::DistortionVertex must match the size of VRDistortionVertex");
|
||||
|
||||
mSupportedSensorBits = State_Orientation;
|
||||
|
||||
mRecommendedEyeFOV[Eye_Left] = VRFieldOfView(45.0, 45.0, 45.0, 45.0);
|
||||
mRecommendedEyeFOV[Eye_Right] = VRFieldOfView(45.0, 45.0, 45.0, 45.0);
|
||||
|
||||
mMaximumEyeFOV[Eye_Left] = VRFieldOfView(45.0, 45.0, 45.0, 45.0);
|
||||
mMaximumEyeFOV[Eye_Right] = VRFieldOfView(45.0, 45.0, 45.0, 45.0);
|
||||
|
||||
SetFOV(mRecommendedEyeFOV[Eye_Left], mRecommendedEyeFOV[Eye_Right], 0.01, 10000.0);
|
||||
}
|
||||
|
||||
bool
|
||||
HMDInfoCardboard::StartSensorTracking()
|
||||
{
|
||||
LOG("HMDInfoCardboard::StartSensorTracking %d\n", mStartCount);
|
||||
if (mStartCount == 0) {
|
||||
// it's never been started before; initialize observers and
|
||||
// initial state.
|
||||
|
||||
mozilla::hal::ScreenConfiguration sconfig;
|
||||
mozilla::hal::GetCurrentScreenConfiguration(&sconfig);
|
||||
this->Notify(sconfig);
|
||||
|
||||
mozilla::hal::RegisterSensorObserver(mozilla::hal::SENSOR_GAME_ROTATION_VECTOR, this);
|
||||
mozilla::hal::RegisterScreenConfigurationObserver(this);
|
||||
|
||||
mLastSensorState.Clear();
|
||||
}
|
||||
|
||||
mStartCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HMDInfoCardboard::Notify(const mozilla::hal::ScreenConfiguration& config)
|
||||
{
|
||||
mOrient = config.orientation();
|
||||
|
||||
if (mOrient == eScreenOrientation_LandscapePrimary) {
|
||||
mScreenTransform = Quaternion(0.f, 0.f, M_SQRT1_2, M_SQRT1_2);
|
||||
} else if (mOrient == eScreenOrientation_LandscapeSecondary) {
|
||||
mScreenTransform = Quaternion(0.f, 0.f, -M_SQRT1_2, M_SQRT1_2);
|
||||
} else if (mOrient == eScreenOrientation_PortraitPrimary) {
|
||||
mScreenTransform = Quaternion();
|
||||
} else if (mOrient == eScreenOrientation_PortraitSecondary) {
|
||||
mScreenTransform = Quaternion(0.f, 0.f, 1.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HMDInfoCardboard::Notify(const mozilla::hal::SensorData& data)
|
||||
{
|
||||
if (data.sensor() != mozilla::hal::SENSOR_GAME_ROTATION_VECTOR)
|
||||
return;
|
||||
|
||||
const nsTArray<float>& sensorValues = data.values();
|
||||
|
||||
// This is super chatty
|
||||
//LOG("HMDInfoCardboard::Notify %f %f %f %f\n", sensorValues[0], sensorValues[1], sensorValues[2], sensorValues[3]);
|
||||
|
||||
mSavedLastSensor.Set(sensorValues[0], sensorValues[1], sensorValues[2], sensorValues[3]);
|
||||
mSavedLastSensorTime = data.timestamp();
|
||||
mNeedsSensorCompute = true;
|
||||
}
|
||||
|
||||
void
|
||||
HMDInfoCardboard::ComputeStateFromLastSensor()
|
||||
{
|
||||
if (!mNeedsSensorCompute)
|
||||
return;
|
||||
|
||||
// apply the zero orientation
|
||||
Quaternion q = mSensorZeroInverse * mSavedLastSensor;
|
||||
|
||||
// make a matrix from the quat
|
||||
Matrix4x4 qm;
|
||||
qm.SetRotationFromQuaternion(q);
|
||||
|
||||
// remap the coordinate space, based on the orientation
|
||||
Matrix4x4 qmRemapped = RemapMatrixForOrientation(mOrient, qm);
|
||||
|
||||
// turn it back into a quat
|
||||
q.SetFromRotationMatrix(qmRemapped);
|
||||
|
||||
// apply adjustment based on what's been done to the screen and the original zero
|
||||
// position of the base coordinate space
|
||||
q = mScreenTransform * q;
|
||||
|
||||
VRHMDSensorState& state = mLastSensorState;
|
||||
|
||||
state.flags |= State_Orientation;
|
||||
state.orientation[0] = q.x;
|
||||
state.orientation[1] = q.y;
|
||||
state.orientation[2] = q.z;
|
||||
state.orientation[3] = q.w;
|
||||
|
||||
state.timestamp = mSavedLastSensorTime / 1000000.0;
|
||||
|
||||
mNeedsSensorCompute = false;
|
||||
}
|
||||
|
||||
VRHMDSensorState
|
||||
HMDInfoCardboard::GetSensorState(double timeOffset)
|
||||
{
|
||||
ComputeStateFromLastSensor();
|
||||
return mLastSensorState;
|
||||
}
|
||||
|
||||
void
|
||||
HMDInfoCardboard::StopSensorTracking()
|
||||
{
|
||||
LOG("HMDInfoCardboard::StopSensorTracking, count %d\n", mStartCount);
|
||||
if (--mStartCount == 0) {
|
||||
mozilla::hal::UnregisterScreenConfigurationObserver(this);
|
||||
mozilla::hal::UnregisterSensorObserver(mozilla::hal::SENSOR_GAME_ROTATION_VECTOR, this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HMDInfoCardboard::ZeroSensor()
|
||||
{
|
||||
mSensorZeroInverse = mSavedLastSensor;
|
||||
mSensorZeroInverse.Invert();
|
||||
}
|
||||
|
||||
static Matrix4x4
|
||||
ConstructProjectionMatrix(const VRFieldOfView& fov, bool rightHanded, double zNear, double zFar)
|
||||
{
|
||||
float upTan = tan(fov.upDegrees * M_PI / 180.0);
|
||||
float downTan = tan(fov.downDegrees * M_PI / 180.0);
|
||||
float leftTan = tan(fov.leftDegrees * M_PI / 180.0);
|
||||
float rightTan = tan(fov.rightDegrees * M_PI / 180.0);
|
||||
|
||||
float handednessScale = rightHanded ? -1.0 : 1.0;
|
||||
|
||||
float pxscale = 2.0f / (leftTan + rightTan);
|
||||
float pxoffset = (leftTan - rightTan) * pxscale * 0.5;
|
||||
float pyscale = 2.0f / (upTan + downTan);
|
||||
float pyoffset = (upTan - downTan) * pyscale * 0.5;
|
||||
|
||||
Matrix4x4 mobj;
|
||||
float *m = &mobj._11;
|
||||
|
||||
m[0*4+0] = pxscale;
|
||||
m[0*4+2] = pxoffset * handednessScale;
|
||||
|
||||
m[1*4+1] = pyscale;
|
||||
m[1*4+2] = -pyoffset * handednessScale;
|
||||
|
||||
m[2*4+2] = zFar / (zNear - zFar) * -handednessScale;
|
||||
m[2*4+3] = (zFar * zNear) / (zNear - zFar);
|
||||
|
||||
m[3*4+2] = handednessScale;
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
||||
bool
|
||||
HMDInfoCardboard::SetFOV(const VRFieldOfView& aFOVLeft,
|
||||
const VRFieldOfView& aFOVRight,
|
||||
double zNear, double zFar)
|
||||
{
|
||||
const float standardIPD = 0.064f;
|
||||
|
||||
for (uint32_t eye = 0; eye < NumEyes; eye++) {
|
||||
mEyeFOV[eye] = eye == Eye_Left ? aFOVLeft : aFOVRight;
|
||||
mEyeTranslation[eye] = Point3D(standardIPD * (eye == Eye_Left ? -1.0 : 1.0), 0.0, 0.0);
|
||||
mEyeProjectionMatrix[eye] = ConstructProjectionMatrix(mEyeFOV[eye], true, zNear, zFar);
|
||||
|
||||
mDistortionMesh[eye].mVertices.SetLength(4);
|
||||
mDistortionMesh[eye].mIndices.SetLength(6);
|
||||
|
||||
HMDInfoCardboard::DistortionVertex *destv = reinterpret_cast<HMDInfoCardboard::DistortionVertex*>(mDistortionMesh[eye].mVertices.Elements());
|
||||
float xoffs = eye == Eye_Left ? 0.0f : 1.0f;
|
||||
float txoffs = eye == Eye_Left ? 0.0f : 0.5f;
|
||||
destv[0].pos[0] = -1.0 + xoffs;
|
||||
destv[0].pos[1] = -1.0;
|
||||
destv[0].texR[0] = destv[0].texG[0] = destv[0].texB[0] = 0.0 + txoffs;
|
||||
destv[0].texR[1] = destv[0].texG[1] = destv[0].texB[1] = 1.0;
|
||||
destv[0].padding[0] = 1.0; // vignette factor
|
||||
|
||||
destv[1].pos[0] = 0.0 + xoffs;
|
||||
destv[1].pos[1] = -1.0;
|
||||
destv[1].texR[0] = destv[1].texG[0] = destv[1].texB[0] = 0.5 + txoffs;
|
||||
destv[1].texR[1] = destv[1].texG[1] = destv[1].texB[1] = 1.0;
|
||||
destv[1].padding[0] = 1.0; // vignette factor
|
||||
|
||||
destv[2].pos[0] = 0.0 + xoffs;
|
||||
destv[2].pos[1] = 1.0;
|
||||
destv[2].texR[0] = destv[2].texG[0] = destv[2].texB[0] = 0.5 + txoffs;
|
||||
destv[2].texR[1] = destv[2].texG[1] = destv[2].texB[1] = 0.0;
|
||||
destv[2].padding[0] = 1.0; // vignette factor
|
||||
|
||||
destv[3].pos[0] = -1.0 + xoffs;
|
||||
destv[3].pos[1] = 1.0;
|
||||
destv[3].texR[0] = destv[3].texG[0] = destv[3].texB[0] = 0.0 + txoffs;
|
||||
destv[3].texR[1] = destv[3].texG[1] = destv[3].texB[1] = 0.0;
|
||||
destv[3].padding[0] = 1.0; // vignette factor
|
||||
|
||||
uint16_t *iv = mDistortionMesh[eye].mIndices.Elements();
|
||||
iv[0] = 0; iv[1] = 1; iv[2] = 2;
|
||||
iv[3] = 2; iv[4] = 3; iv[5] = 0;
|
||||
}
|
||||
|
||||
// XXX find out the default screen size and use that
|
||||
mEyeResolution.width = 1920 / 2;
|
||||
mEyeResolution.height = 1080;
|
||||
|
||||
mConfiguration.hmdType = mType;
|
||||
mConfiguration.value = 0;
|
||||
mConfiguration.fov[0] = aFOVLeft;
|
||||
mConfiguration.fov[1] = aFOVRight;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HMDInfoCardboard::FillDistortionConstants(uint32_t whichEye,
|
||||
const IntSize& textureSize, const IntRect& eyeViewport,
|
||||
const Size& destViewport, const Rect& destRect,
|
||||
VRDistortionConstants& values)
|
||||
{
|
||||
// these modify the texture coordinates; texcoord * zw + xy
|
||||
values.eyeToSourceScaleAndOffset[0] = 0.0;
|
||||
values.eyeToSourceScaleAndOffset[1] = 0.0;
|
||||
values.eyeToSourceScaleAndOffset[2] = 1.0;
|
||||
values.eyeToSourceScaleAndOffset[3] = 1.0;
|
||||
|
||||
// Our mesh positions are in the [-1..1] clip space; we give appropriate offset
|
||||
// and scaling for the right viewport. (In the 0..2 space for sanity)
|
||||
|
||||
// this is the destRect in clip space
|
||||
float x0 = destRect.x / destViewport.width * 2.0 - 1.0;
|
||||
float x1 = (destRect.x + destRect.width) / destViewport.width * 2.0 - 1.0;
|
||||
|
||||
float y0 = destRect.y / destViewport.height * 2.0 - 1.0;
|
||||
float y1 = (destRect.y + destRect.height) / destViewport.height * 2.0 - 1.0;
|
||||
|
||||
// offset
|
||||
values.destinationScaleAndOffset[0] = (x0+x1) / 2.0;
|
||||
values.destinationScaleAndOffset[1] = (y0+y1) / 2.0;
|
||||
// scale
|
||||
values.destinationScaleAndOffset[2] = destRect.width / destViewport.width;
|
||||
values.destinationScaleAndOffset[3] = destRect.height / destViewport.height;
|
||||
}
|
||||
|
||||
void
|
||||
HMDInfoCardboard::Destroy()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
VRHMDManagerCardboard::PlatformInit()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
VRHMDManagerCardboard::Init()
|
||||
{
|
||||
if (mCardboardInitialized)
|
||||
return true;
|
||||
|
||||
nsRefPtr<HMDInfoCardboard> hmd = new HMDInfoCardboard();
|
||||
mCardboardHMDs.AppendElement(hmd);
|
||||
|
||||
mCardboardInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
VRHMDManagerCardboard::Destroy()
|
||||
{
|
||||
if (!mCardboardInitialized)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < mCardboardHMDs.Length(); ++i) {
|
||||
mCardboardHMDs[i]->Destroy();
|
||||
}
|
||||
|
||||
mCardboardHMDs.Clear();
|
||||
mCardboardInitialized = false;
|
||||
}
|
||||
|
||||
void
|
||||
VRHMDManagerCardboard::GetHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult)
|
||||
{
|
||||
Init();
|
||||
for (size_t i = 0; i < mCardboardHMDs.Length(); ++i) {
|
||||
aHMDResult.AppendElement(mCardboardHMDs[i]);
|
||||
}
|
||||
}
|
97
gfx/vr/gfxVRCardboard.h
Normal file
97
gfx/vr/gfxVRCardboard.h
Normal file
@ -0,0 +1,97 @@
|
||||
/* -*- Mode: C++; tab-width: 20; 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/. */
|
||||
|
||||
#ifndef GFX_VR_CARDBOARD_H
|
||||
#define GFX_VR_CARDBOARD_H
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/Quaternion.h"
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "mozilla/HalSensor.h"
|
||||
#include "mozilla/HalScreenConfiguration.h"
|
||||
|
||||
#include "gfxVR.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
namespace impl {
|
||||
|
||||
class HMDInfoCardboard :
|
||||
public VRHMDInfo,
|
||||
public hal::ISensorObserver,
|
||||
public hal::ScreenConfigurationObserver
|
||||
{
|
||||
public:
|
||||
explicit HMDInfoCardboard();
|
||||
|
||||
bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
|
||||
double zNear, double zFar) override;
|
||||
|
||||
bool StartSensorTracking() override;
|
||||
VRHMDSensorState GetSensorState(double timeOffset) override;
|
||||
void StopSensorTracking() override;
|
||||
void ZeroSensor() override;
|
||||
|
||||
void FillDistortionConstants(uint32_t whichEye,
|
||||
const IntSize& textureSize, const IntRect& eyeViewport,
|
||||
const Size& destViewport, const Rect& destRect,
|
||||
VRDistortionConstants& values) override;
|
||||
|
||||
void Destroy();
|
||||
|
||||
// ISensorObserver interface
|
||||
void Notify(const hal::SensorData& SensorData) override;
|
||||
// ScreenConfigurationObserver interface
|
||||
void Notify(const hal::ScreenConfiguration& ScreenConfiguration) override;
|
||||
|
||||
protected:
|
||||
// must match the size of VRDistortionVertex
|
||||
struct DistortionVertex {
|
||||
float pos[2];
|
||||
float texR[2];
|
||||
float texG[2];
|
||||
float texB[2];
|
||||
float padding[4];
|
||||
};
|
||||
|
||||
virtual ~HMDInfoCardboard() {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void ComputeStateFromLastSensor();
|
||||
|
||||
uint32_t mStartCount;
|
||||
VRHMDSensorState mLastSensorState;
|
||||
uint32_t mOrient;
|
||||
Quaternion mScreenTransform;
|
||||
Quaternion mSensorZeroInverse;
|
||||
|
||||
Quaternion mSavedLastSensor;
|
||||
double mSavedLastSensorTime;
|
||||
bool mNeedsSensorCompute; // if we need to compute the state from mSavedLastSensor
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
class VRHMDManagerCardboard : public VRHMDManager
|
||||
{
|
||||
public:
|
||||
VRHMDManagerCardboard()
|
||||
: mCardboardInitialized(false)
|
||||
{ }
|
||||
|
||||
virtual bool PlatformInit() override;
|
||||
virtual bool Init() override;
|
||||
virtual void Destroy() override;
|
||||
virtual void GetHMDs(nsTArray<nsRefPtr<VRHMDInfo> >& aHMDResult) override;
|
||||
protected:
|
||||
nsTArray<nsRefPtr<impl::HMDInfoCardboard>> mCardboardHMDs;
|
||||
bool mCardboardInitialized;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GFX_VR_CARDBOARD_H */
|
@ -9,23 +9,21 @@
|
||||
#include "prmem.h"
|
||||
#include "prenv.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "gfxVR.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "ovr_capi_dynamic.h"
|
||||
#include "gfxVROculus.h"
|
||||
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIScreenManager.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "gfxWindowsPlatform.h" // for gfxWindowsPlatform::GetDPIScale
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gfx::impl;
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef OVR_CAPI_LIMITED_MOZILLA
|
||||
@ -58,69 +56,98 @@ static pfn_ovrMatrix4f_Projection ovrMatrix4f_Projection = nullptr;
|
||||
static pfn_ovrMatrix4f_OrthoSubProjection ovrMatrix4f_OrthoSubProjection = nullptr;
|
||||
static pfn_ovr_GetTimeInSeconds ovr_GetTimeInSeconds = nullptr;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# ifdef HAVE_64BIT_BUILD
|
||||
# define OVR_LIB_NAME "libovr64.dll"
|
||||
# else
|
||||
# define OVR_LIB_NAME "libovr.dll"
|
||||
# endif
|
||||
#elif defined(XP_MACOSX)
|
||||
# define OVR_LIB_NAME "libovr.dylib"
|
||||
#ifdef HAVE_64BIT_BUILD
|
||||
#define BUILD_BITS 64
|
||||
#else
|
||||
# define OVR_LIB_NAME 0
|
||||
#define BUILD_BITS 32
|
||||
#endif
|
||||
|
||||
#define LIBOVR_PRODUCT_VERSION 0
|
||||
#define LIBOVR_MAJOR_VERSION 5
|
||||
#define LIBOVR_MINOR_VERSION 0
|
||||
|
||||
static bool
|
||||
InitializeOculusCAPI()
|
||||
{
|
||||
static PRLibrary *ovrlib = nullptr;
|
||||
|
||||
if (!ovrlib) {
|
||||
const char *libName = OVR_LIB_NAME;
|
||||
nsTArray<nsCString> libSearchPaths;
|
||||
nsCString libName;
|
||||
nsCString searchPath;
|
||||
|
||||
#if defined(_WIN32)
|
||||
static const char dirSep = '\\';
|
||||
#else
|
||||
static const char dirSep = '/';
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
static const int pathLen = 260;
|
||||
searchPath.SetCapacity(pathLen);
|
||||
int realLen = ::GetSystemDirectoryA(searchPath.BeginWriting(), pathLen);
|
||||
if (realLen != 0 && realLen < pathLen) {
|
||||
searchPath.SetLength(realLen);
|
||||
libSearchPaths.AppendElement(searchPath);
|
||||
}
|
||||
libName.AppendPrintf("LibOVRRT%d_%d_%d.dll", BUILD_BITS, LIBOVR_PRODUCT_VERSION, LIBOVR_MAJOR_VERSION);
|
||||
#elif defined(__APPLE__)
|
||||
searchPath.Truncate();
|
||||
searchPath.AppendPrintf("/Library/Frameworks/LibOVRRT_%d.framework/Versions/%d", LIBOVR_PRODUCT_VERSION, LIBOVR_MAJOR_VERSION);
|
||||
libSearchPaths.AppendElement(searchPath);
|
||||
|
||||
if (PR_GetEnv("HOME")) {
|
||||
searchPath.Truncate();
|
||||
searchPath.AppendPrintf("%s/Library/Frameworks/LibOVRRT_%d.framework/Versions/%d", PR_GetEnv("HOME"), LIBOVR_PRODUCT_VERSION, LIBOVR_MAJOR_VERSION);
|
||||
libSearchPaths.AppendElement(searchPath);
|
||||
}
|
||||
libName.AppendPrintf("LibOVRRT_%d", LIBOVR_PRODUCT_VERSION);
|
||||
#else
|
||||
libSearchPaths.AppendElement(nsCString("/usr/local/lib"));
|
||||
libSearchPaths.AppendElement(nsCString("/usr/lib"));
|
||||
libName.AppendPrintf("LibOVRRT%d_%d.so.%d", BUILD_BITS, LIBOVR_PRODUCT_VERSION, LIBOVR_MAJOR_VERSION);
|
||||
#endif
|
||||
|
||||
// If the pref is present, we override libName
|
||||
nsAdoptingCString prefLibName = mozilla::Preferences::GetCString("dom.vr.ovr_lib_path");
|
||||
if (prefLibName && prefLibName.get()) {
|
||||
libName = prefLibName.get();
|
||||
nsAdoptingCString prefLibPath = mozilla::Preferences::GetCString("dom.vr.ovr_lib_path");
|
||||
if (prefLibPath && prefLibPath.get()) {
|
||||
libSearchPaths.InsertElementsAt(0, 1, prefLibPath);
|
||||
}
|
||||
|
||||
nsAdoptingCString prefLibName = mozilla::Preferences::GetCString("dom.vr.ovr_lib_name");
|
||||
if (prefLibName && prefLibName.get()) {
|
||||
libName.Assign(prefLibName);
|
||||
}
|
||||
|
||||
// search the path/module dir
|
||||
libSearchPaths.InsertElementsAt(0, 1, nsCString());
|
||||
|
||||
// If the env var is present, we override libName
|
||||
if (PR_GetEnv("OVR_LIB_PATH")) {
|
||||
searchPath = PR_GetEnv("OVR_LIB_PATH");
|
||||
libSearchPaths.InsertElementsAt(0, 1, searchPath);
|
||||
}
|
||||
|
||||
if (PR_GetEnv("OVR_LIB_NAME")) {
|
||||
libName = PR_GetEnv("OVR_LIB_NAME");
|
||||
}
|
||||
|
||||
if (!libName) {
|
||||
printf_stderr("Don't know how to find Oculus VR library; missing dom.vr.ovr_lib_path or OVR_LIB_NAME\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ovrlib = PR_LoadLibrary(libName);
|
||||
|
||||
if (!ovrlib) {
|
||||
// Not found? Try harder. Needed mainly on OSX/etc. where
|
||||
// the binary location is not in the search path.
|
||||
const char *xulName = "libxul.so";
|
||||
#if defined(XP_MACOSX)
|
||||
xulName = "XUL";
|
||||
#endif
|
||||
|
||||
char *xulpath = PR_GetLibraryFilePathname(xulName, (PRFuncPtr) &InitializeOculusCAPI);
|
||||
if (xulpath) {
|
||||
char *xuldir = strrchr(xulpath, '/');
|
||||
if (xuldir) {
|
||||
*xuldir = 0;
|
||||
xuldir = xulpath;
|
||||
|
||||
char *ovrpath = PR_GetLibraryName(xuldir, libName);
|
||||
ovrlib = PR_LoadLibrary(ovrpath);
|
||||
PR_Free(ovrpath);
|
||||
}
|
||||
PR_Free(xulpath);
|
||||
for (uint32_t i = 0; i < libSearchPaths.Length(); ++i) {
|
||||
nsCString& libPath = libSearchPaths[i];
|
||||
nsCString fullName;
|
||||
if (libPath.Length() == 0) {
|
||||
fullName.Assign(libName);
|
||||
} else {
|
||||
fullName.AppendPrintf("%s%c%s", libPath.BeginReading(), dirSep, libName.BeginReading());
|
||||
}
|
||||
|
||||
ovrlib = PR_LoadLibrary(fullName.BeginReading());
|
||||
if (ovrlib)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ovrlib) {
|
||||
printf_stderr("Failed to load Oculus VR library, tried '%s'\n", libName);
|
||||
printf_stderr("Failed to load Oculus VR library!\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -181,93 +208,7 @@ static bool InitializeOculusCAPI()
|
||||
}
|
||||
#endif
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
// Dummy nsIScreen implementation, for when we just need to specify a size
|
||||
class FakeScreen : public nsIScreen
|
||||
{
|
||||
public:
|
||||
explicit FakeScreen(const IntRect& aScreenRect)
|
||||
: mScreenRect(aScreenRect)
|
||||
{ }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD GetRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
|
||||
*l = mScreenRect.x;
|
||||
*t = mScreenRect.y;
|
||||
*w = mScreenRect.width;
|
||||
*h = mScreenRect.height;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHOD GetAvailRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
|
||||
return GetRect(l, t, w, h);
|
||||
}
|
||||
NS_IMETHOD GetRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
|
||||
return GetRect(l, t, w, h);
|
||||
}
|
||||
NS_IMETHOD GetAvailRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
|
||||
return GetAvailRect(l, t, w, h);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetId(uint32_t* aId) override { *aId = (uint32_t)-1; return NS_OK; }
|
||||
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override { *aPixelDepth = 24; return NS_OK; }
|
||||
NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override { *aColorDepth = 24; return NS_OK; }
|
||||
|
||||
NS_IMETHOD LockMinimumBrightness(uint32_t aBrightness) override { return NS_ERROR_NOT_AVAILABLE; }
|
||||
NS_IMETHOD UnlockMinimumBrightness(uint32_t aBrightness) override { return NS_ERROR_NOT_AVAILABLE; }
|
||||
NS_IMETHOD GetRotation(uint32_t* aRotation) override {
|
||||
*aRotation = nsIScreen::ROTATION_0_DEG;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHOD SetRotation(uint32_t aRotation) override { return NS_ERROR_NOT_AVAILABLE; }
|
||||
NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) override {
|
||||
*aContentsScaleFactor = 1.0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~FakeScreen() {}
|
||||
|
||||
IntRect mScreenRect;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(FakeScreen, nsIScreen)
|
||||
|
||||
class HMDInfoOculus : public VRHMDInfo {
|
||||
friend class VRHMDManagerOculusImpl;
|
||||
public:
|
||||
explicit HMDInfoOculus(ovrHmd aHMD);
|
||||
|
||||
bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
|
||||
double zNear, double zFar) override;
|
||||
|
||||
bool StartSensorTracking() override;
|
||||
VRHMDSensorState GetSensorState(double timeOffset) override;
|
||||
void StopSensorTracking() override;
|
||||
void ZeroSensor() override;
|
||||
|
||||
void FillDistortionConstants(uint32_t whichEye,
|
||||
const IntSize& textureSize, const IntRect& eyeViewport,
|
||||
const Size& destViewport, const Rect& destRect,
|
||||
VRDistortionConstants& values) override;
|
||||
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
virtual ~HMDInfoOculus() {
|
||||
Destroy();
|
||||
MOZ_COUNT_DTOR_INHERITED(HMDInfoOculus, VRHMDInfo);
|
||||
}
|
||||
|
||||
ovrHmd mHMD;
|
||||
ovrFovPort mFOVPort[2];
|
||||
uint32_t mStartCount;
|
||||
};
|
||||
|
||||
static ovrFovPort
|
||||
ovrFovPort
|
||||
ToFovPort(const VRFieldOfView& aFOV)
|
||||
{
|
||||
ovrFovPort fovPort;
|
||||
@ -278,7 +219,7 @@ ToFovPort(const VRFieldOfView& aFOV)
|
||||
return fovPort;
|
||||
}
|
||||
|
||||
static VRFieldOfView
|
||||
VRFieldOfView
|
||||
FromFovPort(const ovrFovPort& aFOV)
|
||||
{
|
||||
VRFieldOfView fovInfo;
|
||||
@ -289,11 +230,16 @@ FromFovPort(const ovrFovPort& aFOV)
|
||||
return fovInfo;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
HMDInfoOculus::HMDInfoOculus(ovrHmd aHMD)
|
||||
: VRHMDInfo(VRHMDType::Oculus)
|
||||
, mHMD(aHMD)
|
||||
, mStartCount(0)
|
||||
{
|
||||
MOZ_ASSERT(sizeof(HMDInfoOculus::DistortionVertex) == sizeof(VRDistortionVertex),
|
||||
"HMDInfoOculus::DistortionVertex must match the size of VRDistortionVertex");
|
||||
|
||||
MOZ_COUNT_CTOR_INHERITED(HMDInfoOculus, VRHMDInfo);
|
||||
|
||||
mSupportedSensorBits = 0;
|
||||
@ -345,7 +291,7 @@ HMDInfoOculus::SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRi
|
||||
|
||||
// these values are negated so that content can add the adjustment to its camera position,
|
||||
// instead of subtracting
|
||||
mEyeTranslation[eye] = Point3D(-renderDesc.ViewAdjust.x, -renderDesc.ViewAdjust.y, -renderDesc.ViewAdjust.z);
|
||||
mEyeTranslation[eye] = Point3D(-renderDesc.HmdToEyeViewOffset.x, -renderDesc.HmdToEyeViewOffset.y, -renderDesc.HmdToEyeViewOffset.z);
|
||||
|
||||
// note that we are using a right-handed coordinate system here, to match CSS
|
||||
ovrMatrix4f projMatrix = ovrMatrix4f_Projection(mFOVPort[eye], zNear, zFar, true);
|
||||
@ -365,7 +311,7 @@ HMDInfoOculus::SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRi
|
||||
mDistortionMesh[eye].mIndices.SetLength(mesh.IndexCount);
|
||||
|
||||
ovrDistortionVertex *srcv = mesh.pVertexData;
|
||||
VRDistortionVertex *destv = mDistortionMesh[eye].mVertices.Elements();
|
||||
HMDInfoOculus::DistortionVertex *destv = reinterpret_cast<HMDInfoOculus::DistortionVertex*>(mDistortionMesh[eye].mVertices.Elements());
|
||||
memset(destv, 0, mesh.VertexCount * sizeof(VRDistortionVertex));
|
||||
for (uint32_t i = 0; i < mesh.VertexCount; ++i) {
|
||||
destv[i].pos[0] = srcv[i].ScreenPosNDC.x;
|
||||
@ -414,10 +360,10 @@ HMDInfoOculus::FillDistortionConstants(uint32_t whichEye,
|
||||
|
||||
ovrHmd_GetRenderScaleAndOffset(mFOVPort[whichEye], texSize, eyePort, scaleOut);
|
||||
|
||||
values.eyeToSourceScaleAndOffset[0] = scaleOut[0].x;
|
||||
values.eyeToSourceScaleAndOffset[1] = scaleOut[0].y;
|
||||
values.eyeToSourceScaleAndOffset[2] = scaleOut[1].x;
|
||||
values.eyeToSourceScaleAndOffset[3] = scaleOut[1].y;
|
||||
values.eyeToSourceScaleAndOffset[0] = scaleOut[1].x;
|
||||
values.eyeToSourceScaleAndOffset[1] = scaleOut[1].y;
|
||||
values.eyeToSourceScaleAndOffset[2] = scaleOut[0].x;
|
||||
values.eyeToSourceScaleAndOffset[3] = scaleOut[0].y;
|
||||
|
||||
// These values are in clip space [-1..1] range, but we're providing
|
||||
// scaling in the 0..2 space for sanity.
|
||||
@ -513,71 +459,8 @@ HMDInfoOculus::GetSensorState(double timeOffset)
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class VRHMDManagerOculusImpl {
|
||||
public:
|
||||
VRHMDManagerOculusImpl() : mOculusInitialized(false), mOculusPlatformInitialized(false)
|
||||
{ }
|
||||
|
||||
bool PlatformInit();
|
||||
bool Init();
|
||||
void Destroy();
|
||||
void GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo> >& aHMDResult);
|
||||
protected:
|
||||
nsTArray<nsRefPtr<HMDInfoOculus>> mOculusHMDs;
|
||||
bool mOculusInitialized;
|
||||
bool mOculusPlatformInitialized;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
VRHMDManagerOculusImpl *VRHMDManagerOculus::mImpl = nullptr;
|
||||
|
||||
// These just forward to the Impl class, to have a non-static container for various
|
||||
// objects.
|
||||
|
||||
bool
|
||||
VRHMDManagerOculus::PlatformInit()
|
||||
{
|
||||
if (!mImpl) {
|
||||
mImpl = new VRHMDManagerOculusImpl;
|
||||
}
|
||||
return mImpl->PlatformInit();
|
||||
}
|
||||
|
||||
bool
|
||||
VRHMDManagerOculus::Init()
|
||||
{
|
||||
if (!mImpl) {
|
||||
mImpl = new VRHMDManagerOculusImpl;
|
||||
}
|
||||
return mImpl->Init();
|
||||
}
|
||||
|
||||
void
|
||||
VRHMDManagerOculus::GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult)
|
||||
{
|
||||
if (!mImpl) {
|
||||
mImpl = new VRHMDManagerOculusImpl;
|
||||
}
|
||||
mImpl->GetOculusHMDs(aHMDResult);
|
||||
}
|
||||
|
||||
void
|
||||
VRHMDManagerOculus::Destroy()
|
||||
{
|
||||
if (!mImpl)
|
||||
return;
|
||||
mImpl->Destroy();
|
||||
delete mImpl;
|
||||
mImpl = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
VRHMDManagerOculusImpl::PlatformInit()
|
||||
{
|
||||
if (mOculusPlatformInitialized)
|
||||
return true;
|
||||
@ -588,7 +471,13 @@ VRHMDManagerOculusImpl::PlatformInit()
|
||||
if (!InitializeOculusCAPI())
|
||||
return false;
|
||||
|
||||
bool ok = ovr_Initialize();
|
||||
ovrInitParams params;
|
||||
params.Flags = ovrInit_RequestVersion;
|
||||
params.RequestedMinorVersion = LIBOVR_MINOR_VERSION;
|
||||
params.LogCallback = nullptr;
|
||||
params.ConnectionTimeoutMS = 0;
|
||||
|
||||
bool ok = ovr_Initialize(¶ms);
|
||||
|
||||
if (!ok)
|
||||
return false;
|
||||
@ -598,7 +487,7 @@ VRHMDManagerOculusImpl::PlatformInit()
|
||||
}
|
||||
|
||||
bool
|
||||
VRHMDManagerOculusImpl::Init()
|
||||
VRHMDManagerOculus::Init()
|
||||
{
|
||||
if (mOculusInitialized)
|
||||
return true;
|
||||
@ -610,10 +499,10 @@ VRHMDManagerOculusImpl::Init()
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ovrHmd hmd = ovrHmd_Create(i);
|
||||
if (!hmd)
|
||||
continue;
|
||||
nsRefPtr<HMDInfoOculus> oc = new HMDInfoOculus(hmd);
|
||||
mOculusHMDs.AppendElement(oc);
|
||||
if (hmd) {
|
||||
nsRefPtr<HMDInfoOculus> oc = new HMDInfoOculus(hmd);
|
||||
mOculusHMDs.AppendElement(oc);
|
||||
}
|
||||
}
|
||||
|
||||
// VRAddTestDevices == 1: add test device only if no real devices present
|
||||
@ -633,7 +522,7 @@ VRHMDManagerOculusImpl::Init()
|
||||
}
|
||||
|
||||
void
|
||||
VRHMDManagerOculusImpl::Destroy()
|
||||
VRHMDManagerOculus::Destroy()
|
||||
{
|
||||
if (!mOculusInitialized)
|
||||
return;
|
||||
@ -649,7 +538,7 @@ VRHMDManagerOculusImpl::Destroy()
|
||||
}
|
||||
|
||||
void
|
||||
VRHMDManagerOculusImpl::GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult)
|
||||
VRHMDManagerOculus::GetHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult)
|
||||
{
|
||||
Init();
|
||||
for (size_t i = 0; i < mOculusHMDs.Length(); ++i) {
|
85
gfx/vr/gfxVROculus.h
Normal file
85
gfx/vr/gfxVROculus.h
Normal file
@ -0,0 +1,85 @@
|
||||
/* -*- Mode: C++; tab-width: 20; 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/. */
|
||||
|
||||
#ifndef GFX_VR_OCULUS_H
|
||||
#define GFX_VR_OCULUS_H
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsIScreen.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsRefPtr.h"
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
|
||||
#include "gfxVR.h"
|
||||
#include "ovr_capi_dynamic.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
namespace impl {
|
||||
|
||||
class HMDInfoOculus : public VRHMDInfo {
|
||||
public:
|
||||
explicit HMDInfoOculus(ovrHmd aHMD);
|
||||
|
||||
bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
|
||||
double zNear, double zFar) override;
|
||||
|
||||
bool StartSensorTracking() override;
|
||||
VRHMDSensorState GetSensorState(double timeOffset) override;
|
||||
void StopSensorTracking() override;
|
||||
void ZeroSensor() override;
|
||||
|
||||
void FillDistortionConstants(uint32_t whichEye,
|
||||
const IntSize& textureSize, const IntRect& eyeViewport,
|
||||
const Size& destViewport, const Rect& destRect,
|
||||
VRDistortionConstants& values) override;
|
||||
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
// must match the size of VRDistortionVertex
|
||||
struct DistortionVertex {
|
||||
float pos[2];
|
||||
float texR[2];
|
||||
float texG[2];
|
||||
float texB[2];
|
||||
float genericAttribs[4];
|
||||
};
|
||||
|
||||
virtual ~HMDInfoOculus() {
|
||||
Destroy();
|
||||
MOZ_COUNT_DTOR_INHERITED(HMDInfoOculus, VRHMDInfo);
|
||||
}
|
||||
|
||||
ovrHmd mHMD;
|
||||
ovrFovPort mFOVPort[2];
|
||||
uint32_t mStartCount;
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
class VRHMDManagerOculus : public VRHMDManager
|
||||
{
|
||||
public:
|
||||
VRHMDManagerOculus()
|
||||
: mOculusInitialized(false), mOculusPlatformInitialized(false)
|
||||
{ }
|
||||
|
||||
virtual bool PlatformInit() override;
|
||||
virtual bool Init() override;
|
||||
virtual void Destroy() override;
|
||||
virtual void GetHMDs(nsTArray<nsRefPtr<VRHMDInfo> >& aHMDResult) override;
|
||||
protected:
|
||||
nsTArray<nsRefPtr<impl::HMDInfoOculus>> mOculusHMDs;
|
||||
bool mOculusInitialized;
|
||||
bool mOculusPlatformInitialized;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GFX_VR_OCULUS_H */
|
33
gfx/vr/moz.build
Normal file
33
gfx/vr/moz.build
Normal file
@ -0,0 +1,33 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
EXPORTS += [
|
||||
'gfxVR.h',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/gfx/thebes',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'gfxVR.cpp',
|
||||
'gfxVRCardboard.cpp',
|
||||
'gfxVROculus.cpp',
|
||||
]
|
||||
|
||||
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
|
||||
CXXFLAGS += CONFIG['TK_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
|
||||
CFLAGS += CONFIG['TK_CFLAGS']
|
||||
|
||||
FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']
|
||||
|
||||
MSVC_ENABLE_PGO = True
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
292
gfx/vr/ovr_capi_dynamic.h
Normal file
292
gfx/vr/ovr_capi_dynamic.h
Normal file
@ -0,0 +1,292 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/* This file contains just the needed struct definitions for
|
||||
* interacting with the Oculus VR C API, without needing to #include
|
||||
* OVR_CAPI.h directly. Note that it uses the same type names as the
|
||||
* CAPI, and cannot be #included at the same time as OVR_CAPI.h. It
|
||||
* does not include the entire C API, just want's needed.
|
||||
*/
|
||||
|
||||
#ifdef OVR_CAPI_h
|
||||
#warning OVR_CAPI.h included before ovr_capi_dynamic.h, skpping this
|
||||
#define mozilla_ovr_capi_dynamic_h_
|
||||
|
||||
#else
|
||||
|
||||
#ifndef mozilla_ovr_capi_dynamic_h_
|
||||
#define mozilla_ovr_capi_dynamic_h_
|
||||
|
||||
#define OVR_CAPI_LIMITED_MOZILLA 1
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define OVR_PFN __cdecl
|
||||
#else
|
||||
#define OVR_PFN
|
||||
#endif
|
||||
|
||||
#if !defined(OVR_ALIGNAS)
|
||||
#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L))
|
||||
#define OVR_ALIGNAS(n) alignas(n)
|
||||
#elif defined(__clang__) && !defined(__APPLE__) && (((__clang_major__ * 100) + __clang_minor__) >= 300) && (__cplusplus >= 201103L)
|
||||
#define OVR_ALIGNAS(n) alignas(n)
|
||||
#elif defined(__clang__) && defined(__APPLE__) && (((__clang_major__ * 100) + __clang_minor__) >= 401) && (__cplusplus >= 201103L)
|
||||
#define OVR_ALIGNAS(n) alignas(n)
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1900)
|
||||
#define OVR_ALIGNAS(n) alignas(n)
|
||||
#elif defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408)
|
||||
#define OVR_ALIGNAS(n) alignas(n)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define OVR_ALIGNAS(n) __attribute__((aligned(n)))
|
||||
#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
#define OVR_ALIGNAS(n) __declspec(align(n))
|
||||
#else
|
||||
#error Need to define OVR_ALIGNAS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef char ovrBool;
|
||||
typedef struct { int x, y; } ovrVector2i;
|
||||
typedef struct { int w, h; } ovrSizei;
|
||||
typedef struct { ovrVector2i Pos; ovrSizei Size; } ovrRecti;
|
||||
typedef struct { float x, y, z, w; } ovrQuatf;
|
||||
typedef struct { float x, y; } ovrVector2f;
|
||||
typedef struct { float x, y, z; } ovrVector3f;
|
||||
typedef struct { float M[4][4]; } ovrMatrix4f;
|
||||
|
||||
typedef struct {
|
||||
ovrQuatf Orientation;
|
||||
ovrVector3f Position;
|
||||
} ovrPosef;
|
||||
|
||||
typedef struct OVR_ALIGNAS(8) {
|
||||
ovrPosef ThePose;
|
||||
ovrVector3f AngularVelocity;
|
||||
ovrVector3f LinearVelocity;
|
||||
ovrVector3f AngularAcceleration;
|
||||
ovrVector3f LinearAcceleration;
|
||||
float Pad;
|
||||
double TimeInSeconds;
|
||||
} ovrPoseStatef;
|
||||
|
||||
typedef struct {
|
||||
float UpTan;
|
||||
float DownTan;
|
||||
float LeftTan;
|
||||
float RightTan;
|
||||
} ovrFovPort;
|
||||
|
||||
typedef enum {
|
||||
ovrHmd_None = 0,
|
||||
ovrHmd_DK1 = 3,
|
||||
ovrHmd_DKHD = 4,
|
||||
ovrHmd_DK2 = 6,
|
||||
ovrHmd_BlackStar = 7,
|
||||
ovrHmd_CB = 8,
|
||||
ovrHmd_Other = 9,
|
||||
ovrHmd_EnumSize = 0x7fffffff
|
||||
} ovrHmdType;
|
||||
|
||||
typedef enum {
|
||||
ovrHmdCap_Present = 0x0001,
|
||||
ovrHmdCap_Available = 0x0002,
|
||||
ovrHmdCap_Captured = 0x0004,
|
||||
ovrHmdCap_ExtendDesktop = 0x0008,
|
||||
ovrHmdCap_DebugDevice = 0x0010,
|
||||
ovrHmdCap_DisplayOff = 0x0040,
|
||||
ovrHmdCap_LowPersistence = 0x0080,
|
||||
ovrHmdCap_DynamicPrediction = 0x0200,
|
||||
ovrHmdCap_NoVSync = 0x1000,
|
||||
ovrHmdCap_NoMirrorToWindow = 0x2000
|
||||
} ovrHmdCapBits;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ovrTrackingCap_Orientation = 0x0010,
|
||||
ovrTrackingCap_MagYawCorrection = 0x0020,
|
||||
ovrTrackingCap_Position = 0x0040,
|
||||
ovrTrackingCap_Idle = 0x0100,
|
||||
ovrTrackingCap_EnumSize = 0x7fffffff
|
||||
} ovrTrackingCaps;
|
||||
|
||||
typedef enum {
|
||||
ovrDistortionCap_Chromatic = 0x01,
|
||||
ovrDistortionCap_TimeWarp = 0x02,
|
||||
ovrDistortionCap_Vignette = 0x08,
|
||||
ovrDistortionCap_NoRestore = 0x10,
|
||||
ovrDistortionCap_FlipInput = 0x20,
|
||||
ovrDistortionCap_SRGB = 0x40,
|
||||
ovrDistortionCap_Overdrive = 0x80,
|
||||
ovrDistortionCap_HqDistortion = 0x100,
|
||||
ovrDistortionCap_LinuxDevFullscreen = 0x200,
|
||||
ovrDistortionCap_ComputeShader = 0x400,
|
||||
ovrDistortionCap_TimewarpJitDelay = 0x1000,
|
||||
ovrDistortionCap_ProfileNoSpinWaits = 0x10000,
|
||||
ovrDistortionCap_EnumSize = 0x7fffffff
|
||||
} ovrDistortionCaps;
|
||||
|
||||
typedef enum {
|
||||
ovrEye_Left = 0,
|
||||
ovrEye_Right = 1,
|
||||
ovrEye_Count = 2,
|
||||
ovrEye_EnumSize = 0x7fffffff
|
||||
} ovrEyeType;
|
||||
|
||||
typedef struct ovrHmdDesc_ {
|
||||
void* Handle;
|
||||
ovrHmdType Type;
|
||||
const char* ProductName;
|
||||
const char* Manufacturer;
|
||||
short VendorId;
|
||||
short ProductId;
|
||||
char SerialNumber[24];
|
||||
short FirmwareMajor;
|
||||
short FirmwareMinor;
|
||||
float CameraFrustumHFovInRadians;
|
||||
float CameraFrustumVFovInRadians;
|
||||
float CameraFrustumNearZInMeters;
|
||||
float CameraFrustumFarZInMeters;
|
||||
|
||||
unsigned int HmdCaps;
|
||||
unsigned int TrackingCaps;
|
||||
unsigned int DistortionCaps;
|
||||
|
||||
ovrFovPort DefaultEyeFov[ovrEye_Count];
|
||||
ovrFovPort MaxEyeFov[ovrEye_Count];
|
||||
ovrEyeType EyeRenderOrder[ovrEye_Count];
|
||||
|
||||
ovrSizei Resolution;
|
||||
ovrVector2i WindowsPos;
|
||||
|
||||
const char* DisplayDeviceName;
|
||||
int DisplayId;
|
||||
} ovrHmdDesc;
|
||||
|
||||
typedef const ovrHmdDesc* ovrHmd;
|
||||
|
||||
typedef enum {
|
||||
ovrStatus_OrientationTracked = 0x0001,
|
||||
ovrStatus_PositionTracked = 0x0002,
|
||||
ovrStatus_CameraPoseTracked = 0x0004,
|
||||
ovrStatus_PositionConnected = 0x0020,
|
||||
ovrStatus_HmdConnected = 0x0080,
|
||||
ovrStatus_EnumSize = 0x7fffffff
|
||||
} ovrStatusBits;
|
||||
|
||||
typedef struct ovrSensorData_ {
|
||||
ovrVector3f Accelerometer;
|
||||
ovrVector3f Gyro;
|
||||
ovrVector3f Magnetometer;
|
||||
float Temperature;
|
||||
float TimeInSeconds;
|
||||
} ovrSensorData;
|
||||
|
||||
|
||||
typedef struct ovrTrackingState_ {
|
||||
ovrPoseStatef HeadPose;
|
||||
ovrPosef CameraPose;
|
||||
ovrPosef LeveledCameraPose;
|
||||
ovrSensorData RawSensorData;
|
||||
unsigned int StatusFlags;
|
||||
double LastVisionProcessingTime;
|
||||
uint32_t LastCameraFrameCounter;
|
||||
uint32_t Pad;
|
||||
} ovrTrackingState;
|
||||
|
||||
typedef struct OVR_ALIGNAS(8) ovrFrameTiming_ {
|
||||
float DeltaSeconds;
|
||||
float Pad;
|
||||
double ThisFrameSeconds;
|
||||
double TimewarpPointSeconds;
|
||||
double NextFrameSeconds;
|
||||
double ScanoutMidpointSeconds;
|
||||
double EyeScanoutSeconds[2];
|
||||
} ovrFrameTiming;
|
||||
|
||||
typedef struct ovrEyeRenderDesc_ {
|
||||
ovrEyeType Eye;
|
||||
ovrFovPort Fov;
|
||||
ovrRecti DistortedViewport;
|
||||
ovrVector2f PixelsPerTanAngleAtCenter;
|
||||
ovrVector3f HmdToEyeViewOffset;
|
||||
} ovrEyeRenderDesc;
|
||||
|
||||
typedef struct ovrDistortionVertex_ {
|
||||
ovrVector2f ScreenPosNDC;
|
||||
float TimeWarpFactor;
|
||||
float VignetteFactor;
|
||||
ovrVector2f TanEyeAnglesR;
|
||||
ovrVector2f TanEyeAnglesG;
|
||||
ovrVector2f TanEyeAnglesB;
|
||||
} ovrDistortionVertex;
|
||||
|
||||
typedef struct ovrDistortionMesh_ {
|
||||
ovrDistortionVertex* pVertexData;
|
||||
unsigned short* pIndexData;
|
||||
unsigned int VertexCount;
|
||||
unsigned int IndexCount;
|
||||
} ovrDistortionMesh;
|
||||
|
||||
typedef enum {
|
||||
ovrInit_Debug = 0x00000001,
|
||||
ovrInit_ServerOptional = 0x00000002,
|
||||
ovrInit_RequestVersion = 0x00000004,
|
||||
ovrInit_ForceNoDebug = 0x00000008
|
||||
} ovrInitFlags;
|
||||
|
||||
typedef enum {
|
||||
ovrLogLevel_Debug = 0,
|
||||
ovrLogLevel_Info = 1,
|
||||
ovrLogLevel_Error = 2
|
||||
} ovrLogLevel;
|
||||
|
||||
typedef void (OVR_PFN *ovrLogCallback)(int level, const char* message);
|
||||
|
||||
typedef struct {
|
||||
uint32_t Flags;
|
||||
uint32_t RequestedMinorVersion;
|
||||
ovrLogCallback LogCallback;
|
||||
uint32_t ConnectionTimeoutMS;
|
||||
} ovrInitParams;
|
||||
|
||||
typedef ovrBool (OVR_PFN *pfn_ovr_Initialize)(ovrInitParams const* params);
|
||||
typedef void (OVR_PFN *pfn_ovr_Shutdown)();
|
||||
typedef int (OVR_PFN *pfn_ovrHmd_Detect)();
|
||||
typedef ovrHmd (OVR_PFN *pfn_ovrHmd_Create)(int index);
|
||||
typedef void (OVR_PFN *pfn_ovrHmd_Destroy)(ovrHmd hmd);
|
||||
typedef ovrHmd (OVR_PFN *pfn_ovrHmd_CreateDebug)(ovrHmdType type);
|
||||
typedef const char* (OVR_PFN *pfn_ovrHmd_GetLastError)(ovrHmd hmd);
|
||||
typedef ovrBool (OVR_PFN *pfn_ovrHmd_AttachToWindow)(ovrHmd hmd, void* window, const ovrRecti* destMirrorRect, const ovrRecti* sourceRenderTargetRect);
|
||||
typedef unsigned int (OVR_PFN *pfn_ovrHmd_GetEnabledCaps)(ovrHmd hmd);
|
||||
typedef void (OVR_PFN *pfn_ovrHmd_SetEnabledCaps)(ovrHmd hmd, unsigned int hmdCaps);
|
||||
typedef ovrBool (OVR_PFN *pfn_ovrHmd_ConfigureTracking)(ovrHmd hmd, unsigned int supportedTrackingCaps, unsigned int requiredTrackingCaps);
|
||||
typedef void (OVR_PFN *pfn_ovrHmd_RecenterPose)(ovrHmd hmd);
|
||||
typedef ovrTrackingState (OVR_PFN *pfn_ovrHmd_GetTrackingState)(ovrHmd hmd, double absTime);
|
||||
typedef ovrSizei (OVR_PFN *pfn_ovrHmd_GetFovTextureSize)(ovrHmd hmd, ovrEyeType eye, ovrFovPort fov, float pixelsPerDisplayPixel);
|
||||
typedef ovrEyeRenderDesc (OVR_PFN *pfn_ovrHmd_GetRenderDesc)(ovrHmd hmd, ovrEyeType eyeType, ovrFovPort fov);
|
||||
typedef ovrBool (OVR_PFN *pfn_ovrHmd_CreateDistortionMesh)(ovrHmd hmd, ovrEyeType eyeType, ovrFovPort fov, unsigned int distortionCaps, ovrDistortionMesh *meshData);
|
||||
typedef void (OVR_PFN *pfn_ovrHmd_DestroyDistortionMesh)(ovrDistortionMesh* meshData);
|
||||
typedef void (OVR_PFN *pfn_ovrHmd_GetRenderScaleAndOffset)(ovrFovPort fov, ovrSizei textureSize, ovrRecti renderViewport, ovrVector2f uvScaleOffsetOut[2]);
|
||||
typedef ovrFrameTiming (OVR_PFN *pfn_ovrHmd_GetFrameTiming)(ovrHmd hmd, unsigned int frameIndex);
|
||||
typedef ovrFrameTiming (OVR_PFN *pfn_ovrHmd_BeginFrameTiming)(ovrHmd hmd, unsigned int frameIndex);
|
||||
typedef void (OVR_PFN *pfn_ovrHmd_EndFrameTiming)(ovrHmd hmd);
|
||||
typedef void (OVR_PFN *pfn_ovrHmd_ResetFrameTiming)(ovrHmd hmd, unsigned int frameIndex, bool vsync);
|
||||
typedef void (OVR_PFN *pfn_ovrHmd_GetEyePoses)(ovrHmd hmd, unsigned int frameIndex, ovrVector3f hmdToEyeViewOffset[2], ovrPosef outEyePoses[2], ovrTrackingState* outHmdTrackingState);
|
||||
typedef ovrPosef (OVR_PFN *pfn_ovrHmd_GetHmdPosePerEye)(ovrHmd hmd, ovrEyeType eye);
|
||||
typedef void (OVR_PFN *pfn_ovrHmd_GetEyeTimewarpMatrices)(ovrHmd hmd, ovrEyeType eye, ovrPosef renderPose, ovrMatrix4f twmOut[2]);
|
||||
typedef ovrMatrix4f (OVR_PFN *pfn_ovrMatrix4f_Projection) (ovrFovPort fov, float znear, float zfar, ovrBool rightHanded );
|
||||
typedef ovrMatrix4f (OVR_PFN *pfn_ovrMatrix4f_OrthoSubProjection) (ovrFovPort fov, ovrVector2f orthoScale, float orthoDistance, float eyeViewAdjustX);
|
||||
typedef double (OVR_PFN *pfn_ovr_GetTimeInSeconds)();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_ovr_capi_dynamic_h_ */
|
||||
#endif /* OVR_CAPI_h */
|
@ -15,15 +15,18 @@ namespace hal {
|
||||
/**
|
||||
* Enumeration of sensor types. They are used to specify type while
|
||||
* register or unregister an observer for a sensor of given type.
|
||||
* If you add or change any here, do the same in GeckoHalDefines.java.
|
||||
*/
|
||||
enum SensorType {
|
||||
SENSOR_UNKNOWN = -1,
|
||||
SENSOR_ORIENTATION,
|
||||
SENSOR_ACCELERATION,
|
||||
SENSOR_PROXIMITY,
|
||||
SENSOR_LINEAR_ACCELERATION,
|
||||
SENSOR_GYROSCOPE,
|
||||
SENSOR_LIGHT,
|
||||
SENSOR_ORIENTATION = 0,
|
||||
SENSOR_ACCELERATION = 1,
|
||||
SENSOR_PROXIMITY = 2,
|
||||
SENSOR_LINEAR_ACCELERATION = 3,
|
||||
SENSOR_GYROSCOPE = 4,
|
||||
SENSOR_LIGHT = 5,
|
||||
SENSOR_ROTATION_VECTOR = 6,
|
||||
SENSOR_GAME_ROTATION_VECTOR = 7,
|
||||
NUM_SENSOR_TYPE
|
||||
};
|
||||
|
||||
|
@ -38,6 +38,10 @@ namespace mozilla {
|
||||
// different orientation angles
|
||||
#define ACCELEROMETER_POLL_RATE 66667000 /*66.667ms*/
|
||||
|
||||
// This is present in Android from API level 18 onwards, which is 4.3. We might
|
||||
// be building on something before 4.3, so use a local define for its value
|
||||
#define MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR 15
|
||||
|
||||
double radToDeg(double a) {
|
||||
return a * (180.0 / M_PI);
|
||||
}
|
||||
@ -58,6 +62,10 @@ HardwareSensorToHalSensor(int type)
|
||||
return SENSOR_GYROSCOPE;
|
||||
case SENSOR_TYPE_LINEAR_ACCELERATION:
|
||||
return SENSOR_LINEAR_ACCELERATION;
|
||||
case SENSOR_TYPE_ROTATION_VECTOR:
|
||||
return SENSOR_ROTATION_VECTOR;
|
||||
case MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR:
|
||||
return SENSOR_GAME_ROTATION_VECTOR;
|
||||
default:
|
||||
return SENSOR_UNKNOWN;
|
||||
}
|
||||
@ -84,6 +92,10 @@ HalSensorToHardwareSensor(SensorType type)
|
||||
return SENSOR_TYPE_GYROSCOPE;
|
||||
case SENSOR_LINEAR_ACCELERATION:
|
||||
return SENSOR_TYPE_LINEAR_ACCELERATION;
|
||||
case SENSOR_ROTATION_VECTOR:
|
||||
return SENSOR_TYPE_ROTATION_VECTOR;
|
||||
case SENSOR_GAME_ROTATION_VECTOR:
|
||||
return MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -131,6 +143,28 @@ public:
|
||||
}
|
||||
} else if (mSensorData.sensor() == SENSOR_LIGHT) {
|
||||
mSensorValues.AppendElement(data.data[0]);
|
||||
} else if (mSensorData.sensor() == SENSOR_ROTATION_VECTOR) {
|
||||
mSensorValues.AppendElement(data.data[0]);
|
||||
mSensorValues.AppendElement(data.data[1]);
|
||||
mSensorValues.AppendElement(data.data[2]);
|
||||
if (data.data[3] == 0.0) {
|
||||
// data.data[3] was optional in Android <= API level 18. It can be computed from 012,
|
||||
// but it's better to take the actual value if one is provided. The computation is
|
||||
// v = 1 - d[0]*d[0] - d[1]*d[1] - d[2]*d[2]
|
||||
// d[3] = v > 0 ? sqrt(v) : 0;
|
||||
// I'm assuming that it will be 0 if it's not passed in. (The values form a unit
|
||||
// quaternion, so the angle can be computed from the direction vector.)
|
||||
float sx = data.data[0], sy = data.data[1], sz = data.data[2];
|
||||
float v = 1.0f - sx*sx - sy*sy - sz*sz;
|
||||
mSensorValues.AppendElement(v > 0.0f ? sqrt(v) : 0.0f);
|
||||
} else {
|
||||
mSensorValues.AppendElement(data.data[3]);
|
||||
}
|
||||
} else if (mSensorData.sensor() == SENSOR_GAME_ROTATION_VECTOR) {
|
||||
mSensorValues.AppendElement(data.data[0]);
|
||||
mSensorValues.AppendElement(data.data[1]);
|
||||
mSensorValues.AppendElement(data.data[2]);
|
||||
mSensorValues.AppendElement(data.data[3]);
|
||||
} else {
|
||||
mSensorValues.AppendElement(data.data[0]);
|
||||
mSensorValues.AppendElement(data.data[1]);
|
||||
@ -149,7 +183,7 @@ public:
|
||||
|
||||
private:
|
||||
SensorData mSensorData;
|
||||
InfallibleTArray<float> mSensorValues;
|
||||
nsAutoTArray<float, 4> mSensorValues;
|
||||
};
|
||||
|
||||
namespace hal_impl {
|
||||
|
@ -6,22 +6,20 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
#include "xpcprivate.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "CPOWTimer.h"
|
||||
|
||||
CPOWTimer::~CPOWTimer()
|
||||
{
|
||||
/* This is a best effort to find the compartment responsible for this CPOW call */
|
||||
nsIGlobalObject* global = mozilla::dom::GetIncumbentGlobal();
|
||||
if (!global)
|
||||
JSContext* cx = nsContentUtils::GetCurrentJSContextForThread();
|
||||
if (!cx)
|
||||
return;
|
||||
JSObject* obj = global->GetGlobalJSObject();
|
||||
if (!obj)
|
||||
|
||||
JSRuntime* runtime = JS_GetRuntime(cx);
|
||||
if (!js::IsStopwatchActive(runtime))
|
||||
return;
|
||||
JSCompartment* compartment = js::GetObjectCompartment(obj);
|
||||
xpc::CompartmentPrivate* compartmentPrivate = xpc::CompartmentPrivate::Get(compartment);
|
||||
if (!compartmentPrivate)
|
||||
return;
|
||||
PRIntervalTime time = PR_IntervalNow() - startInterval;
|
||||
compartmentPrivate->CPOWTime += time;
|
||||
|
||||
js::PerformanceData *performance = js::GetPerformanceData(runtime);
|
||||
uint64_t duration = PR_IntervalToMicroseconds(PR_IntervalNow() - startInterval);
|
||||
performance->totalCPOWTime += duration;
|
||||
}
|
||||
|
@ -12,12 +12,30 @@
|
||||
|
||||
class JSObject;
|
||||
|
||||
class MOZ_STACK_CLASS CPOWTimer {
|
||||
/**
|
||||
* A stopwatch measuring the duration of a CPOW call.
|
||||
*
|
||||
* As the process is consuming neither user time nor system time
|
||||
* during a CPOW call, we measure such durations using wallclock time.
|
||||
*
|
||||
* This stopwatch is active iff JSRuntime::stopwatch.isActive is set.
|
||||
* Upon destruction, update JSRuntime::stopwatch.data.totalCPOWTime.
|
||||
*/
|
||||
class MOZ_STACK_CLASS CPOWTimer final {
|
||||
public:
|
||||
CPOWTimer(): startInterval(PR_IntervalNow()) {}
|
||||
explicit inline CPOWTimer(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
|
||||
: startInterval(PR_IntervalNow())
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
~CPOWTimer();
|
||||
|
||||
private:
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
/**
|
||||
* The instant at which the stopwatch was started.
|
||||
*/
|
||||
PRIntervalTime startInterval;
|
||||
};
|
||||
|
||||
|
@ -35,6 +35,7 @@ LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
'/js/ipc',
|
||||
'/js/public',
|
||||
'/js/src',
|
||||
'/js/xpconnect/src',
|
||||
'/js/xpconnect/wrappers',
|
||||
]
|
||||
|
@ -15,6 +15,10 @@
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
namespace js {
|
||||
struct PerformanceGroup;
|
||||
}
|
||||
|
||||
struct JSPrincipals {
|
||||
/* Don't call "destroy"; use reference counting macros below. */
|
||||
mozilla::Atomic<int32_t> refcount;
|
||||
|
@ -2603,100 +2603,87 @@ BytecodeEmitter::enterBlockScope(StmtInfoBCE* stmtInfo, ObjectBox* objbox, JSOp
|
||||
MOZ_NEVER_INLINE bool
|
||||
BytecodeEmitter::emitSwitch(ParseNode* pn)
|
||||
{
|
||||
JSOp switchOp;
|
||||
bool hasDefault;
|
||||
ptrdiff_t top, off, defaultOffset;
|
||||
ParseNode* pn2, *pn3, *pn4;
|
||||
int32_t low, high;
|
||||
size_t switchSize;
|
||||
jsbytecode* pc;
|
||||
|
||||
/* Try for most optimal, fall back if not dense ints. */
|
||||
switchOp = JSOP_TABLESWITCH;
|
||||
hasDefault = false;
|
||||
defaultOffset = -1;
|
||||
|
||||
pn2 = pn->pn_right;
|
||||
MOZ_ASSERT(pn2->isKind(PNK_LEXICALSCOPE) || pn2->isKind(PNK_STATEMENTLIST));
|
||||
ParseNode* cases = pn->pn_right;
|
||||
MOZ_ASSERT(cases->isKind(PNK_LEXICALSCOPE) || cases->isKind(PNK_STATEMENTLIST));
|
||||
|
||||
/* Push the discriminant. */
|
||||
if (!emitTree(pn->pn_left))
|
||||
return false;
|
||||
|
||||
StmtInfoBCE stmtInfo(cx);
|
||||
if (pn2->isKind(PNK_LEXICALSCOPE)) {
|
||||
if (!enterBlockScope(&stmtInfo, pn2->pn_objbox, JSOP_UNINITIALIZED, 0))
|
||||
ptrdiff_t top;
|
||||
if (cases->isKind(PNK_LEXICALSCOPE)) {
|
||||
if (!enterBlockScope(&stmtInfo, cases->pn_objbox, JSOP_UNINITIALIZED, 0))
|
||||
return false;
|
||||
|
||||
stmtInfo.type = STMT_SWITCH;
|
||||
stmtInfo.update = top = offset();
|
||||
/* Advance pn2 to refer to the switch case list. */
|
||||
pn2 = pn2->expr();
|
||||
/* Advance |cases| to refer to the switch case list. */
|
||||
cases = cases->expr();
|
||||
} else {
|
||||
MOZ_ASSERT(pn2->isKind(PNK_STATEMENTLIST));
|
||||
MOZ_ASSERT(cases->isKind(PNK_STATEMENTLIST));
|
||||
top = offset();
|
||||
pushStatement(&stmtInfo, STMT_SWITCH, top);
|
||||
}
|
||||
|
||||
/* Switch bytecodes run from here till end of final case. */
|
||||
uint32_t caseCount = pn2->pn_count;
|
||||
uint32_t tableLength = 0;
|
||||
UniquePtr<ParseNode*[], JS::FreePolicy> table(nullptr);
|
||||
|
||||
uint32_t caseCount = cases->pn_count;
|
||||
if (caseCount > JS_BIT(16)) {
|
||||
parser->tokenStream.reportError(JSMSG_TOO_MANY_CASES);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Try for most optimal, fall back if not dense ints. */
|
||||
JSOp switchOp = JSOP_TABLESWITCH;
|
||||
uint32_t tableLength = 0;
|
||||
int32_t low, high;
|
||||
bool hasDefault = false;
|
||||
if (caseCount == 0 ||
|
||||
(caseCount == 1 &&
|
||||
(hasDefault = (pn2->pn_head->isKind(PNK_DEFAULT))))) {
|
||||
(hasDefault = cases->pn_head->isKind(PNK_DEFAULT)))) {
|
||||
caseCount = 0;
|
||||
low = 0;
|
||||
high = -1;
|
||||
} else {
|
||||
bool ok = true;
|
||||
#define INTMAP_LENGTH 256
|
||||
jsbitmap intmap_space[INTMAP_LENGTH];
|
||||
jsbitmap* intmap = nullptr;
|
||||
int32_t intmap_bitlen = 0;
|
||||
Vector<jsbitmap, 128, SystemAllocPolicy> intmap;
|
||||
int32_t intmapBitLength = 0;
|
||||
|
||||
low = JSVAL_INT_MAX;
|
||||
high = JSVAL_INT_MIN;
|
||||
|
||||
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
|
||||
if (pn3->isKind(PNK_DEFAULT)) {
|
||||
for (ParseNode* caseNode = cases->pn_head; caseNode; caseNode = caseNode->pn_next) {
|
||||
if (caseNode->isKind(PNK_DEFAULT)) {
|
||||
hasDefault = true;
|
||||
caseCount--; /* one of the "cases" was the default */
|
||||
continue;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(pn3->isKind(PNK_CASE));
|
||||
MOZ_ASSERT(caseNode->isKind(PNK_CASE));
|
||||
if (switchOp == JSOP_CONDSWITCH)
|
||||
continue;
|
||||
|
||||
MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
|
||||
|
||||
pn4 = pn3->pn_left;
|
||||
ParseNode* caseValue = caseNode->pn_left;
|
||||
|
||||
if (pn4->getKind() != PNK_NUMBER) {
|
||||
if (caseValue->getKind() != PNK_NUMBER) {
|
||||
switchOp = JSOP_CONDSWITCH;
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t i;
|
||||
if (!NumberIsInt32(pn4->pn_dval, &i)) {
|
||||
if (!NumberIsInt32(caseValue->pn_dval, &i)) {
|
||||
switchOp = JSOP_CONDSWITCH;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((unsigned)(i + (int)JS_BIT(15)) >= (unsigned)JS_BIT(16)) {
|
||||
if (unsigned(i + int(JS_BIT(15))) >= unsigned(JS_BIT(16))) {
|
||||
switchOp = JSOP_CONDSWITCH;
|
||||
continue;
|
||||
}
|
||||
if (i < low)
|
||||
low = i;
|
||||
if (high < i)
|
||||
if (i > high)
|
||||
high = i;
|
||||
|
||||
/*
|
||||
@ -2706,21 +2693,11 @@ BytecodeEmitter::emitSwitch(ParseNode* pn)
|
||||
*/
|
||||
if (i < 0)
|
||||
i += JS_BIT(16);
|
||||
if (i >= intmap_bitlen) {
|
||||
if (!intmap &&
|
||||
size_t(i) < (INTMAP_LENGTH * JS_BITMAP_NBITS)) {
|
||||
intmap = intmap_space;
|
||||
intmap_bitlen = INTMAP_LENGTH * JS_BITMAP_NBITS;
|
||||
} else {
|
||||
/* Just grab 8K for the worst-case bitmap. */
|
||||
intmap_bitlen = JS_BIT(16);
|
||||
intmap = cx->pod_malloc<jsbitmap>(JS_BIT(16) / JS_BITMAP_NBITS);
|
||||
if (!intmap) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
memset(intmap, 0, size_t(intmap_bitlen) / CHAR_BIT);
|
||||
if (i >= intmapBitLength) {
|
||||
size_t newLength = (i / JS_BITMAP_NBITS) + 1;
|
||||
if (!intmap.resize(newLength))
|
||||
return false;
|
||||
intmapBitLength = newLength * JS_BITMAP_NBITS;
|
||||
}
|
||||
if (JS_TEST_BIT(intmap, i)) {
|
||||
switchOp = JSOP_CONDSWITCH;
|
||||
@ -2729,17 +2706,12 @@ BytecodeEmitter::emitSwitch(ParseNode* pn)
|
||||
JS_SET_BIT(intmap, i);
|
||||
}
|
||||
|
||||
if (intmap && intmap != intmap_space)
|
||||
js_free(intmap);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Compute table length and select condswitch instead if overlarge or
|
||||
* more than half-sparse.
|
||||
*/
|
||||
if (switchOp == JSOP_TABLESWITCH) {
|
||||
tableLength = (uint32_t)(high - low + 1);
|
||||
tableLength = uint32_t(high - low + 1);
|
||||
if (tableLength >= JS_BIT(16) || tableLength > 2 * caseCount)
|
||||
switchOp = JSOP_CONDSWITCH;
|
||||
}
|
||||
@ -2750,6 +2722,7 @@ BytecodeEmitter::emitSwitch(ParseNode* pn)
|
||||
* second (if condswitch) tells offset to first JSOP_CASE.
|
||||
*/
|
||||
unsigned noteIndex;
|
||||
size_t switchSize;
|
||||
if (switchOp == JSOP_CONDSWITCH) {
|
||||
/* 0 bytes of immediate for unoptimized switch. */
|
||||
switchSize = 0;
|
||||
@ -2768,38 +2741,39 @@ BytecodeEmitter::emitSwitch(ParseNode* pn)
|
||||
if (!emitN(switchOp, switchSize))
|
||||
return false;
|
||||
|
||||
off = -1;
|
||||
Vector<ParseNode*, 32, SystemAllocPolicy> table;
|
||||
|
||||
ptrdiff_t condSwitchDefaultOff = -1;
|
||||
if (switchOp == JSOP_CONDSWITCH) {
|
||||
unsigned caseNoteIndex;
|
||||
bool beforeCases = true;
|
||||
ptrdiff_t prevCaseOffset;
|
||||
|
||||
/* Emit code for evaluating cases and jumping to case statements. */
|
||||
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
|
||||
pn4 = pn3->pn_left;
|
||||
if (pn4 && !emitTree(pn4))
|
||||
for (ParseNode* caseNode = cases->pn_head; caseNode; caseNode = caseNode->pn_next) {
|
||||
ParseNode* caseValue = caseNode->pn_left;
|
||||
if (caseValue && !emitTree(caseValue))
|
||||
return false;
|
||||
if (!beforeCases) {
|
||||
/* off is the previous JSOP_CASE's bytecode offset. */
|
||||
if (!setSrcNoteOffset(caseNoteIndex, 0, offset() - off))
|
||||
/* prevCaseOffset is the previous JSOP_CASE's bytecode offset. */
|
||||
if (!setSrcNoteOffset(caseNoteIndex, 0, offset() - prevCaseOffset))
|
||||
return false;
|
||||
}
|
||||
if (!pn4) {
|
||||
MOZ_ASSERT(pn3->isKind(PNK_DEFAULT));
|
||||
if (!caseValue) {
|
||||
MOZ_ASSERT(caseNode->isKind(PNK_DEFAULT));
|
||||
continue;
|
||||
}
|
||||
if (!newSrcNote2(SRC_NEXTCASE, 0, &caseNoteIndex))
|
||||
return false;
|
||||
if (!emitJump(JSOP_CASE, 0, &off))
|
||||
if (!emitJump(JSOP_CASE, 0, &prevCaseOffset))
|
||||
return false;
|
||||
pn3->pn_offset = off;
|
||||
caseNode->pn_offset = prevCaseOffset;
|
||||
if (beforeCases) {
|
||||
unsigned noteCount, noteCountDelta;
|
||||
|
||||
/* Switch note's second offset is to first JSOP_CASE. */
|
||||
noteCount = notes().length();
|
||||
if (!setSrcNoteOffset(noteIndex, 1, off - top))
|
||||
unsigned noteCount = notes().length();
|
||||
if (!setSrcNoteOffset(noteIndex, 1, prevCaseOffset - top))
|
||||
return false;
|
||||
noteCountDelta = notes().length() - noteCount;
|
||||
unsigned noteCountDelta = notes().length() - noteCount;
|
||||
if (noteCountDelta != 0)
|
||||
caseNoteIndex += noteCountDelta;
|
||||
beforeCases = false;
|
||||
@ -2813,18 +2787,18 @@ BytecodeEmitter::emitSwitch(ParseNode* pn)
|
||||
* the benefit of IonBuilder.
|
||||
*/
|
||||
if (!hasDefault &&
|
||||
caseNoteIndex != UINT_MAX &&
|
||||
!setSrcNoteOffset(caseNoteIndex, 0, offset() - off))
|
||||
!beforeCases &&
|
||||
!setSrcNoteOffset(caseNoteIndex, 0, offset() - prevCaseOffset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Emit default even if no explicit default statement. */
|
||||
if (!emitJump(JSOP_DEFAULT, 0, &defaultOffset))
|
||||
if (!emitJump(JSOP_DEFAULT, 0, &condSwitchDefaultOff))
|
||||
return false;
|
||||
} else {
|
||||
MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
|
||||
pc = code(top + JUMP_OFFSET_LEN);
|
||||
jsbytecode* pc = code(top + JUMP_OFFSET_LEN);
|
||||
|
||||
/* Fill in switch bounds, which we know fit in 16-bit offsets. */
|
||||
SET_JUMP_OFFSET(pc, low);
|
||||
@ -2832,67 +2806,65 @@ BytecodeEmitter::emitSwitch(ParseNode* pn)
|
||||
SET_JUMP_OFFSET(pc, high);
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
|
||||
/*
|
||||
* Use malloc to avoid arena bloat for programs with many switches.
|
||||
* UniquePtr takes care of freeing it on exit.
|
||||
*/
|
||||
if (tableLength != 0) {
|
||||
table = cx->make_zeroed_pod_array<ParseNode*>(tableLength);
|
||||
if (!table)
|
||||
if (!table.growBy(tableLength))
|
||||
return false;
|
||||
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
|
||||
if (pn3->isKind(PNK_DEFAULT))
|
||||
|
||||
for (ParseNode* caseNode = cases->pn_head; caseNode; caseNode = caseNode->pn_next) {
|
||||
if (caseNode->isKind(PNK_DEFAULT))
|
||||
continue;
|
||||
|
||||
MOZ_ASSERT(pn3->isKind(PNK_CASE));
|
||||
MOZ_ASSERT(caseNode->isKind(PNK_CASE));
|
||||
|
||||
pn4 = pn3->pn_left;
|
||||
MOZ_ASSERT(pn4->getKind() == PNK_NUMBER);
|
||||
ParseNode* caseValue = caseNode->pn_left;
|
||||
MOZ_ASSERT(caseValue->isKind(PNK_NUMBER));
|
||||
|
||||
int32_t i = int32_t(pn4->pn_dval);
|
||||
MOZ_ASSERT(double(i) == pn4->pn_dval);
|
||||
int32_t i = int32_t(caseValue->pn_dval);
|
||||
MOZ_ASSERT(double(i) == caseValue->pn_dval);
|
||||
|
||||
i -= low;
|
||||
MOZ_ASSERT(uint32_t(i) < tableLength);
|
||||
table[i] = pn3;
|
||||
MOZ_ASSERT(!table[i]);
|
||||
table[i] = caseNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit code for each case's statements, copying pn_offset up to pn3. */
|
||||
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
|
||||
if (switchOp == JSOP_CONDSWITCH && !pn3->isKind(PNK_DEFAULT))
|
||||
setJumpOffsetAt(pn3->pn_offset);
|
||||
pn4 = pn3->pn_right;
|
||||
if (!emitTree(pn4))
|
||||
ptrdiff_t defaultOffset = -1;
|
||||
|
||||
/* Emit code for each case's statements, copying pn_offset up to caseNode. */
|
||||
for (ParseNode* caseNode = cases->pn_head; caseNode; caseNode = caseNode->pn_next) {
|
||||
if (switchOp == JSOP_CONDSWITCH && !caseNode->isKind(PNK_DEFAULT))
|
||||
setJumpOffsetAt(caseNode->pn_offset);
|
||||
ParseNode* caseValue = caseNode->pn_right;
|
||||
if (!emitTree(caseValue))
|
||||
return false;
|
||||
pn3->pn_offset = pn4->pn_offset;
|
||||
if (pn3->isKind(PNK_DEFAULT))
|
||||
off = pn3->pn_offset - top;
|
||||
caseNode->pn_offset = caseValue->pn_offset;
|
||||
if (caseNode->isKind(PNK_DEFAULT))
|
||||
defaultOffset = caseNode->pn_offset - top;
|
||||
}
|
||||
|
||||
if (!hasDefault) {
|
||||
/* If no default case, offset for default is to end of switch. */
|
||||
off = offset() - top;
|
||||
defaultOffset = offset() - top;
|
||||
}
|
||||
|
||||
/* We better have set "off" by now. */
|
||||
MOZ_ASSERT(off != -1);
|
||||
/* We better have set "defaultOffset" by now. */
|
||||
MOZ_ASSERT(defaultOffset != -1);
|
||||
|
||||
/* Set the default offset (to end of switch if no default). */
|
||||
jsbytecode* pc;
|
||||
if (switchOp == JSOP_CONDSWITCH) {
|
||||
pc = nullptr;
|
||||
MOZ_ASSERT(defaultOffset != -1);
|
||||
SET_JUMP_OFFSET(code(defaultOffset), off - (defaultOffset - top));
|
||||
SET_JUMP_OFFSET(code(condSwitchDefaultOff), defaultOffset - (condSwitchDefaultOff - top));
|
||||
} else {
|
||||
pc = code(top);
|
||||
SET_JUMP_OFFSET(pc, off);
|
||||
SET_JUMP_OFFSET(pc, defaultOffset);
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
}
|
||||
|
||||
/* Set the SRC_SWITCH note's offset operand to tell end of switch. */
|
||||
off = offset() - top;
|
||||
if (!setSrcNoteOffset(unsigned(noteIndex), 0, off))
|
||||
if (!setSrcNoteOffset(noteIndex, 0, offset() - top))
|
||||
return false;
|
||||
|
||||
if (switchOp == JSOP_TABLESWITCH) {
|
||||
@ -2901,8 +2873,8 @@ BytecodeEmitter::emitSwitch(ParseNode* pn)
|
||||
|
||||
/* Fill in the jump table, if there is one. */
|
||||
for (uint32_t i = 0; i < tableLength; i++) {
|
||||
pn3 = table[i];
|
||||
off = pn3 ? pn3->pn_offset - top : 0;
|
||||
ParseNode* caseNode = table[i];
|
||||
ptrdiff_t off = caseNode ? caseNode->pn_offset - top : 0;
|
||||
SET_JUMP_OFFSET(pc, off);
|
||||
pc += JUMP_OFFSET_LEN;
|
||||
}
|
||||
|
@ -658,7 +658,7 @@ TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigne
|
||||
if (offset != NoOffset && !err.report.filename && cx->isJSContext()) {
|
||||
NonBuiltinFrameIter iter(cx->asJSContext(),
|
||||
FrameIter::ALL_CONTEXTS, FrameIter::GO_THROUGH_SAVED,
|
||||
cx->compartment()->principals);
|
||||
cx->compartment()->principals());
|
||||
if (!iter.done() && iter.scriptFilename()) {
|
||||
callerFilename = true;
|
||||
err.report.filename = iter.scriptFilename();
|
||||
|
11
js/src/jit-test/tests/basic/bug1146836.js
Normal file
11
js/src/jit-test/tests/basic/bug1146836.js
Normal file
@ -0,0 +1,11 @@
|
||||
function f() {
|
||||
var s = "switch (x) {";
|
||||
for (var i=8000; i<16400; i++) {
|
||||
s += "case " + i + ": return " + i + "; break;";
|
||||
}
|
||||
s += "case 8005: return -1; break;";
|
||||
s += "}";
|
||||
var g = Function("x", s);
|
||||
assertEq(g(8005), 8005);
|
||||
}
|
||||
f();
|
@ -94,6 +94,59 @@ BlockComputesConstant(MBasicBlock* block, MDefinition* value)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find phis that are redudant:
|
||||
//
|
||||
// 1) phi(a, a)
|
||||
// can get replaced by a
|
||||
//
|
||||
// 2) phi(filtertypeset(a, type1), filtertypeset(a, type1))
|
||||
// equals filtertypeset(a, type1)
|
||||
//
|
||||
// 3) phi(a, filtertypeset(a, type1))
|
||||
// equals filtertypeset(a, type1 union type(a))
|
||||
// equals filtertypeset(a, type(a))
|
||||
// equals a
|
||||
//
|
||||
// 4) phi(filtertypeset(a, type1), filtertypeset(a, type2))
|
||||
// equals filtertypeset(a, type1 union type2)
|
||||
//
|
||||
// This is the special case. We can only replace this with 'a' iif
|
||||
// type(a) == type1 union type2. Since optimizations could have
|
||||
// happened based on a more specific phi type.
|
||||
static bool
|
||||
IsPhiRedudantFilter(MPhi* phi)
|
||||
{
|
||||
// Handle (1) and (2)
|
||||
if (phi->operandIfRedundant())
|
||||
return true;
|
||||
|
||||
// Handle (3)
|
||||
bool onlyFilters = false;
|
||||
MDefinition* a = phi->getOperand(0);
|
||||
if (a->isFilterTypeSet()) {
|
||||
a = a->toFilterTypeSet()->input();
|
||||
onlyFilters = true;
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < phi->numOperands(); i++) {
|
||||
MDefinition* operand = phi->getOperand(i);
|
||||
if (operand == a) {
|
||||
onlyFilters = false;
|
||||
continue;
|
||||
}
|
||||
if (operand->isFilterTypeSet() && operand->toFilterTypeSet()->input() == a)
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
if (!onlyFilters)
|
||||
return true;
|
||||
|
||||
// Handle (4)
|
||||
MOZ_ASSERT(onlyFilters);
|
||||
return EqualTypes(a->type(), a->resultTypeSet(),
|
||||
phi->type(), phi->resultTypeSet());
|
||||
}
|
||||
|
||||
// Determine whether phiBlock/testBlock simply compute a phi and perform a
|
||||
// test on it.
|
||||
static bool
|
||||
@ -131,8 +184,13 @@ BlockIsSingleTest(MBasicBlock* phiBlock, MBasicBlock* testBlock, MPhi** pphi, MT
|
||||
}
|
||||
|
||||
for (MPhiIterator iter = phiBlock->phisBegin(); iter != phiBlock->phisEnd(); ++iter) {
|
||||
if (*iter != phi)
|
||||
return false;
|
||||
if (*iter == phi)
|
||||
continue;
|
||||
|
||||
if (IsPhiRedudantFilter(*iter))
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (phiBlock != testBlock && !testBlock->phisEmpty())
|
||||
@ -257,6 +315,23 @@ MaybeFoldConditionBlock(MIRGraph& graph, MBasicBlock* initialBlock)
|
||||
|
||||
// OK, we found the desired pattern, now transform the graph.
|
||||
|
||||
// Patch up phis that filter their input.
|
||||
for (MPhiIterator iter = phiBlock->phisBegin(); iter != phiBlock->phisEnd(); ++iter) {
|
||||
if (*iter == phi)
|
||||
continue;
|
||||
|
||||
MOZ_ASSERT(IsPhiRedudantFilter(*iter));
|
||||
MDefinition* redundant = (*iter)->operandIfRedundant();
|
||||
|
||||
if (!redundant) {
|
||||
redundant = (*iter)->getOperand(0);
|
||||
if (redundant->isFilterTypeSet())
|
||||
redundant = redundant->toFilterTypeSet()->input();
|
||||
}
|
||||
|
||||
(*iter)->replaceAllUsesWith(redundant);
|
||||
}
|
||||
|
||||
// Remove the phi from phiBlock.
|
||||
phiBlock->discardPhi(*phiBlock->phisBegin());
|
||||
|
||||
@ -305,112 +380,11 @@ MaybeFoldConditionBlock(MIRGraph& graph, MBasicBlock* initialBlock)
|
||||
graph.removeBlock(testBlock);
|
||||
}
|
||||
|
||||
static void
|
||||
MaybeFoldAndOrBlock(MIRGraph& graph, MBasicBlock* initialBlock)
|
||||
{
|
||||
// Optimize the MIR graph to improve the code generated for && and ||
|
||||
// operations when they are used in tests. This is very similar to the
|
||||
// above method for folding condition blocks, though the two are
|
||||
// separated (with as much common code as possible) for clarity. This
|
||||
// normally requires three blocks. The final test can always be eliminated,
|
||||
// though we don't try to constant fold away the branch block as well.
|
||||
|
||||
// Look for a triangle pattern:
|
||||
//
|
||||
// initialBlock
|
||||
// / |
|
||||
// branchBlock |
|
||||
// \ |
|
||||
// phiBlock
|
||||
// |
|
||||
// testBlock
|
||||
//
|
||||
// Where phiBlock contains a single phi combining values pushed onto the
|
||||
// stack by initialBlock and testBlock, and testBlock contains a test on
|
||||
// that phi. phiBlock and testBlock may be the same block; generated code
|
||||
// will use different blocks if the &&/|| is in an inlined function.
|
||||
|
||||
MInstruction* ins = initialBlock->lastIns();
|
||||
if (!ins->isTest())
|
||||
return;
|
||||
MTest* initialTest = ins->toTest();
|
||||
|
||||
bool branchIsTrue = true;
|
||||
MBasicBlock* branchBlock = initialTest->ifTrue();
|
||||
MBasicBlock* phiBlock = initialTest->ifFalse();
|
||||
if (branchBlock->numSuccessors() != 1 || branchBlock->getSuccessor(0) != phiBlock) {
|
||||
branchIsTrue = false;
|
||||
branchBlock = initialTest->ifFalse();
|
||||
phiBlock = initialTest->ifTrue();
|
||||
}
|
||||
|
||||
if (branchBlock->numSuccessors() != 1 || branchBlock->getSuccessor(0) != phiBlock)
|
||||
return;
|
||||
if (branchBlock->numPredecessors() != 1 || phiBlock->numPredecessors() != 2)
|
||||
return;
|
||||
|
||||
if (initialBlock->isLoopBackedge() || branchBlock->isLoopBackedge())
|
||||
return;
|
||||
|
||||
MBasicBlock* testBlock = phiBlock;
|
||||
if (testBlock->numSuccessors() == 1) {
|
||||
if (testBlock->isLoopBackedge())
|
||||
return;
|
||||
testBlock = testBlock->getSuccessor(0);
|
||||
if (testBlock->numPredecessors() != 1)
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the test block does not have any outgoing loop backedges.
|
||||
if (!SplitCriticalEdgesForBlock(graph, testBlock))
|
||||
CrashAtUnhandlableOOM("MaybeFoldAndOrBlock");
|
||||
|
||||
MPhi* phi;
|
||||
MTest* finalTest;
|
||||
if (!BlockIsSingleTest(phiBlock, testBlock, &phi, &finalTest))
|
||||
return;
|
||||
|
||||
MDefinition* branchResult = phi->getOperand(phiBlock->indexForPredecessor(branchBlock));
|
||||
MDefinition* initialResult = phi->getOperand(phiBlock->indexForPredecessor(initialBlock));
|
||||
|
||||
if (initialResult != initialTest->input())
|
||||
return;
|
||||
|
||||
// OK, we found the desired pattern, now transform the graph.
|
||||
|
||||
// Remove the phi from phiBlock.
|
||||
phiBlock->discardPhi(*phiBlock->phisBegin());
|
||||
|
||||
// Change the end of the initial and branch blocks to a test that jumps
|
||||
// directly to successors of testBlock, rather than to testBlock itself.
|
||||
|
||||
UpdateTestSuccessors(graph.alloc(), initialBlock, initialResult,
|
||||
branchIsTrue ? branchBlock : finalTest->ifTrue(),
|
||||
branchIsTrue ? finalTest->ifFalse() : branchBlock,
|
||||
testBlock);
|
||||
|
||||
UpdateTestSuccessors(graph.alloc(), branchBlock, branchResult,
|
||||
finalTest->ifTrue(), finalTest->ifFalse(), testBlock);
|
||||
|
||||
// Remove phiBlock, if different from testBlock.
|
||||
if (phiBlock != testBlock) {
|
||||
testBlock->removePredecessor(phiBlock);
|
||||
graph.removeBlock(phiBlock);
|
||||
}
|
||||
|
||||
// Remove testBlock itself.
|
||||
finalTest->ifTrue()->removePredecessor(testBlock);
|
||||
finalTest->ifFalse()->removePredecessor(testBlock);
|
||||
graph.removeBlock(testBlock);
|
||||
}
|
||||
|
||||
void
|
||||
jit::FoldTests(MIRGraph& graph)
|
||||
{
|
||||
for (MBasicBlockIterator block(graph.begin()); block != graph.end(); block++) {
|
||||
for (MBasicBlockIterator block(graph.begin()); block != graph.end(); block++)
|
||||
MaybeFoldConditionBlock(graph, *block);
|
||||
MaybeFoldAndOrBlock(graph, *block);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -475,8 +449,11 @@ jit::EliminateDeadResumePointOperands(MIRGenerator* mir, MIRGraph& graph)
|
||||
// parameter passing might be live. Rewriting uses of these terms
|
||||
// in resume points may affect the interpreter's behavior. Rather
|
||||
// than doing a more sophisticated analysis, just ignore these.
|
||||
if (ins->isUnbox() || ins->isParameter() || ins->isTypeBarrier() || ins->isComputeThis())
|
||||
if (ins->isUnbox() || ins->isParameter() || ins->isTypeBarrier() ||
|
||||
ins->isComputeThis() || ins->isFilterTypeSet())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Early intermediate values captured by resume points, such as
|
||||
// TypedObject, ArrayState and its allocation, may be legitimately
|
||||
|
@ -302,12 +302,12 @@ IonBuilder::CFGState::IfElse(jsbytecode* trueEnd, jsbytecode* falseEnd, MTest* t
|
||||
}
|
||||
|
||||
IonBuilder::CFGState
|
||||
IonBuilder::CFGState::AndOr(jsbytecode* join, MBasicBlock* joinStart)
|
||||
IonBuilder::CFGState::AndOr(jsbytecode* join, MBasicBlock* lhs)
|
||||
{
|
||||
CFGState state;
|
||||
state.state = AND_OR;
|
||||
state.stopAt = join;
|
||||
state.branch.ifFalse = joinStart;
|
||||
state.branch.ifFalse = lhs;
|
||||
state.branch.test = nullptr;
|
||||
return state;
|
||||
}
|
||||
@ -2706,16 +2706,25 @@ IonBuilder::processNextTableSwitchCase(CFGState& state)
|
||||
IonBuilder::ControlStatus
|
||||
IonBuilder::processAndOrEnd(CFGState& state)
|
||||
{
|
||||
// We just processed the RHS of an && or || expression.
|
||||
// Now jump to the join point (the false block).
|
||||
current->end(MGoto::New(alloc(), state.branch.ifFalse));
|
||||
MOZ_ASSERT(current);
|
||||
MBasicBlock* lhs = state.branch.ifFalse;
|
||||
|
||||
if (!state.branch.ifFalse->addPredecessor(alloc(), current))
|
||||
// Create a new block to represent the join.
|
||||
MBasicBlock* join = newBlock(current, state.stopAt);
|
||||
if (!join)
|
||||
return ControlStatus_Error;
|
||||
|
||||
if (!setCurrentAndSpecializePhis(state.branch.ifFalse))
|
||||
// End the rhs.
|
||||
current->end(MGoto::New(alloc(), join));
|
||||
|
||||
// End the lhs.
|
||||
lhs->end(MGoto::New(alloc(), join));
|
||||
if (!join->addPredecessor(alloc(), state.branch.ifFalse))
|
||||
return ControlStatus_Error;
|
||||
|
||||
// Set the join path as current path.
|
||||
if (!setCurrentAndSpecializePhis(join))
|
||||
return ControlStatus_Error;
|
||||
graph().moveBlockToEnd(current);
|
||||
pc = current->pc();
|
||||
return ControlStatus_Joined;
|
||||
}
|
||||
@ -4134,20 +4143,34 @@ IonBuilder::jsop_andor(JSOp op)
|
||||
// We have to leave the LHS on the stack.
|
||||
MDefinition* lhs = current->peek(-1);
|
||||
|
||||
MBasicBlock* evalLhs = newBlock(current, joinStart);
|
||||
MBasicBlock* evalRhs = newBlock(current, rhsStart);
|
||||
MBasicBlock* join = newBlock(current, joinStart);
|
||||
if (!evalRhs || !join)
|
||||
if (!evalLhs || !evalRhs)
|
||||
return false;
|
||||
|
||||
MTest* test = (op == JSOP_AND)
|
||||
? newTest(lhs, evalRhs, join)
|
||||
: newTest(lhs, join, evalRhs);
|
||||
? newTest(lhs, evalRhs, evalLhs)
|
||||
: newTest(lhs, evalLhs, evalRhs);
|
||||
current->end(test);
|
||||
|
||||
if (!cfgStack_.append(CFGState::AndOr(joinStart, join)))
|
||||
// Create the lhs block and specialize.
|
||||
if (!setCurrentAndSpecializePhis(evalLhs))
|
||||
return false;
|
||||
|
||||
return setCurrentAndSpecializePhis(evalRhs);
|
||||
if (!improveTypesAtTest(test->getOperand(0), test->ifTrue() == current, test))
|
||||
return false;
|
||||
|
||||
// Create the rhs block.
|
||||
if (!cfgStack_.append(CFGState::AndOr(joinStart, evalLhs)))
|
||||
return false;
|
||||
|
||||
if (!setCurrentAndSpecializePhis(evalRhs))
|
||||
return false;
|
||||
|
||||
if (!improveTypesAtTest(test->getOperand(0), test->ifTrue() == current, test))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -7504,36 +7527,6 @@ IonBuilder::getStaticName(JSObject* staticObject, PropertyName* name, bool* psuc
|
||||
rvalType, barrier, types);
|
||||
}
|
||||
|
||||
// Whether 'types' includes all possible values represented by input/inputTypes.
|
||||
bool
|
||||
jit::TypeSetIncludes(TypeSet* types, MIRType input, TypeSet* inputTypes)
|
||||
{
|
||||
if (!types)
|
||||
return inputTypes && inputTypes->empty();
|
||||
|
||||
switch (input) {
|
||||
case MIRType_Undefined:
|
||||
case MIRType_Null:
|
||||
case MIRType_Boolean:
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
case MIRType_Float32:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_MagicOptimizedArguments:
|
||||
return types->hasType(TypeSet::PrimitiveType(ValueTypeFromMIRType(input)));
|
||||
|
||||
case MIRType_Object:
|
||||
return types->unknownObject() || (inputTypes && inputTypes->isSubset(types));
|
||||
|
||||
case MIRType_Value:
|
||||
return types->unknown() || (inputTypes && inputTypes->isSubset(types));
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad input type");
|
||||
}
|
||||
}
|
||||
|
||||
// Whether a write of the given value may need a post-write barrier for GC purposes.
|
||||
bool
|
||||
jit::NeedsPostBarrier(CompileInfo& info, MDefinition* value)
|
||||
|
@ -206,7 +206,7 @@ class IonBuilder
|
||||
|
||||
static CFGState If(jsbytecode* join, MTest* test);
|
||||
static CFGState IfElse(jsbytecode* trueEnd, jsbytecode* falseEnd, MTest* test);
|
||||
static CFGState AndOr(jsbytecode* join, MBasicBlock* joinStart);
|
||||
static CFGState AndOr(jsbytecode* join, MBasicBlock* lhs);
|
||||
static CFGState TableSwitch(jsbytecode* exitpc, MTableSwitch* ins);
|
||||
static CFGState CondSwitch(IonBuilder* builder, jsbytecode* exitpc, jsbytecode* defaultTarget);
|
||||
static CFGState Label(jsbytecode* exitpc);
|
||||
@ -1351,8 +1351,6 @@ class CallInfo
|
||||
}
|
||||
};
|
||||
|
||||
bool TypeSetIncludes(TypeSet* types, MIRType input, TypeSet* inputTypes);
|
||||
|
||||
bool NeedsPostBarrier(CompileInfo& info, MDefinition* value);
|
||||
|
||||
} // namespace jit
|
||||
|
@ -1771,6 +1771,61 @@ jit::MergeTypes(MIRType* ptype, TemporaryTypeSet** ptypeSet,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Tests whether 'types' includes all possible values represented by
|
||||
// input/inputTypes.
|
||||
bool
|
||||
jit::TypeSetIncludes(TypeSet* types, MIRType input, TypeSet* inputTypes)
|
||||
{
|
||||
if (!types)
|
||||
return inputTypes && inputTypes->empty();
|
||||
|
||||
switch (input) {
|
||||
case MIRType_Undefined:
|
||||
case MIRType_Null:
|
||||
case MIRType_Boolean:
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
case MIRType_Float32:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_MagicOptimizedArguments:
|
||||
return types->hasType(TypeSet::PrimitiveType(ValueTypeFromMIRType(input)));
|
||||
|
||||
case MIRType_Object:
|
||||
return types->unknownObject() || (inputTypes && inputTypes->isSubset(types));
|
||||
|
||||
case MIRType_Value:
|
||||
return types->unknown() || (inputTypes && inputTypes->isSubset(types));
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad input type");
|
||||
}
|
||||
}
|
||||
|
||||
// Tests if two type combos (type/typeset) are equal.
|
||||
bool
|
||||
jit::EqualTypes(MIRType type1, TemporaryTypeSet* typeset1,
|
||||
MIRType type2, TemporaryTypeSet* typeset2)
|
||||
{
|
||||
// Types should equal.
|
||||
if (type1 != type2)
|
||||
return false;
|
||||
|
||||
// Both have equal type and no typeset.
|
||||
if (!typeset1 && !typeset2)
|
||||
return true;
|
||||
|
||||
// If only one instructions has a typeset.
|
||||
// Test if the typset contains the same information as the MIRType.
|
||||
if (typeset1 && !typeset2)
|
||||
return TypeSetIncludes(typeset1, type2, nullptr);
|
||||
if (!typeset1 && typeset2)
|
||||
return TypeSetIncludes(typeset2, type1, nullptr);
|
||||
|
||||
// Typesets should equal.
|
||||
return typeset1->equals(typeset2);
|
||||
}
|
||||
|
||||
bool
|
||||
MPhi::specializeType()
|
||||
{
|
||||
|
@ -2833,6 +2833,13 @@ bool
|
||||
MergeTypes(MIRType* ptype, TemporaryTypeSet** ptypeSet,
|
||||
MIRType newType, TemporaryTypeSet* newTypeSet);
|
||||
|
||||
bool
|
||||
TypeSetIncludes(TypeSet* types, MIRType input, TypeSet* inputTypes);
|
||||
|
||||
bool
|
||||
EqualTypes(MIRType type1, TemporaryTypeSet* typeset1,
|
||||
MIRType type2, TemporaryTypeSet* typeset2);
|
||||
|
||||
// Helper class to assert all GC pointers embedded in MIR instructions are
|
||||
// tenured. Off-thread Ion compilation and nursery GCs can happen in parallel,
|
||||
// so it's invalid to store pointers to nursery things. There's no need to root
|
||||
|
@ -270,30 +270,78 @@ JS_GetEmptyString(JSRuntime* rt)
|
||||
return rt->emptyString;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_GetCompartmentStats(JSRuntime* rt, CompartmentStatsVector& stats)
|
||||
{
|
||||
for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
|
||||
if (!stats.growBy(1))
|
||||
return false;
|
||||
namespace js {
|
||||
|
||||
CompartmentTimeStats* stat = &stats.back();
|
||||
stat->time = c.get()->totalTime;
|
||||
stat->compartment = c.get();
|
||||
stat->addonId = c.get()->addonId;
|
||||
if (rt->compartmentNameCallback) {
|
||||
(*rt->compartmentNameCallback)(rt, stat->compartment,
|
||||
stat->compartmentName,
|
||||
MOZ_ARRAY_LENGTH(stat->compartmentName));
|
||||
JS_PUBLIC_API(bool)
|
||||
GetPerformanceStats(JSRuntime* rt,
|
||||
PerformanceStatsVector& stats,
|
||||
PerformanceStats& processStats)
|
||||
{
|
||||
// As a PerformanceGroup is typically associated to several
|
||||
// compartments, use a HashSet to make sure that we only report
|
||||
// each PerformanceGroup once.
|
||||
typedef HashSet<js::PerformanceGroup*,
|
||||
js::DefaultHasher<js::PerformanceGroup*>,
|
||||
js::SystemAllocPolicy> Set;
|
||||
Set set;
|
||||
if (!set.init(100)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
|
||||
JSCompartment* compartment = c.get();
|
||||
if (!compartment->performanceMonitoring.isLinked()) {
|
||||
// Don't report compartments that do not even have a PerformanceGroup.
|
||||
continue;
|
||||
}
|
||||
PerformanceGroup* group = compartment->performanceMonitoring.getGroup();
|
||||
|
||||
if (group->data.ticks == 0) {
|
||||
// Don't report compartments that have never been used.
|
||||
continue;
|
||||
}
|
||||
|
||||
Set::AddPtr ptr = set.lookupForAdd(group);
|
||||
if (ptr) {
|
||||
// Don't report the same group twice.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!stats.growBy(1)) {
|
||||
// Memory issue
|
||||
return false;
|
||||
}
|
||||
PerformanceStats* stat = &stats.back();
|
||||
stat->isSystem = compartment->isSystem();
|
||||
if (compartment->addonId)
|
||||
stat->addonId = compartment->addonId;
|
||||
|
||||
if (compartment->addonId || !compartment->isSystem()) {
|
||||
if (rt->compartmentNameCallback) {
|
||||
(*rt->compartmentNameCallback)(rt, compartment,
|
||||
stat->name,
|
||||
mozilla::ArrayLength(stat->name));
|
||||
} else {
|
||||
strcpy(stat->name, "<unknown>");
|
||||
}
|
||||
} else {
|
||||
strcpy(stat->compartmentName, "<unknown>");
|
||||
strcpy(stat->name, "<platform>");
|
||||
}
|
||||
stat->performance = group->data;
|
||||
if (!set.add(ptr, group)) {
|
||||
// Memory issue
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
strcpy(processStats.name, "<process>");
|
||||
processStats.addonId = nullptr;
|
||||
processStats.isSystem = true;
|
||||
processStats.performance = rt->stopwatch.performance;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
void
|
||||
AssertHeapIsIdle(JSRuntime* rt)
|
||||
{
|
||||
|
269
js/src/jsapi.h
269
js/src/jsapi.h
@ -972,19 +972,6 @@ JS_GetEmptyStringValue(JSContext* cx);
|
||||
extern JS_PUBLIC_API(JSString*)
|
||||
JS_GetEmptyString(JSRuntime* rt);
|
||||
|
||||
struct CompartmentTimeStats {
|
||||
char compartmentName[1024];
|
||||
JSAddonId* addonId;
|
||||
JSCompartment* compartment;
|
||||
uint64_t time; // microseconds
|
||||
uint64_t cpowTime; // microseconds
|
||||
};
|
||||
|
||||
typedef js::Vector<CompartmentTimeStats, 0, js::SystemAllocPolicy> CompartmentStatsVector;
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_GetCompartmentStats(JSRuntime* rt, CompartmentStatsVector& stats);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_ValueToObject(JSContext* cx, JS::HandleValue v, JS::MutableHandleObject objp);
|
||||
|
||||
@ -998,7 +985,7 @@ extern JS_PUBLIC_API(JSString*)
|
||||
JS_ValueToSource(JSContext* cx, JS::Handle<JS::Value> v);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DoubleIsInt32(double d, int32_t* ip);
|
||||
JS_DoubleIsInt32(double d, int32_t *ip);
|
||||
|
||||
extern JS_PUBLIC_API(JSType)
|
||||
JS_TypeOfValue(JSContext* cx, JS::Handle<JS::Value> v);
|
||||
@ -5273,4 +5260,258 @@ BuildStackString(JSContext* cx, HandleObject stack, MutableHandleString stringp)
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
|
||||
/* Stopwatch-based CPU monitoring. */
|
||||
|
||||
namespace js {
|
||||
|
||||
struct AutoStopwatch;
|
||||
|
||||
// Container for performance data
|
||||
// All values are monotonic.
|
||||
struct PerformanceData {
|
||||
// Number of times we have spent at least 2^n consecutive
|
||||
// milliseconds executing code in this group.
|
||||
// durations[0] is increased whenever we spend at least 1 ms
|
||||
// executing code in this group
|
||||
// durations[1] whenever we spend 2ms+
|
||||
//
|
||||
// durations[i] whenever we spend 2^ims+
|
||||
uint64_t durations[10];
|
||||
|
||||
// Total amount of time spent executing code in this group, in
|
||||
// microseconds.
|
||||
uint64_t totalUserTime;
|
||||
uint64_t totalSystemTime;
|
||||
uint64_t totalCPOWTime;
|
||||
|
||||
// Total number of times code execution entered this group,
|
||||
// since process launch. This may be greater than the number
|
||||
// of times we have entered the event loop.
|
||||
uint64_t ticks;
|
||||
|
||||
PerformanceData()
|
||||
: totalUserTime(0)
|
||||
, totalSystemTime(0)
|
||||
, totalCPOWTime(0)
|
||||
, ticks(0)
|
||||
{
|
||||
mozilla::PodArrayZero(durations);
|
||||
}
|
||||
PerformanceData(const PerformanceData& from)
|
||||
: totalUserTime(from.totalUserTime)
|
||||
, totalSystemTime(from.totalSystemTime)
|
||||
, totalCPOWTime(from.totalCPOWTime)
|
||||
, ticks(from.ticks)
|
||||
{
|
||||
mozilla::PodArrayCopy(durations, from.durations);
|
||||
}
|
||||
PerformanceData& operator=(const PerformanceData& from)
|
||||
{
|
||||
mozilla::PodArrayCopy(durations, from.durations);
|
||||
totalUserTime = from.totalUserTime;
|
||||
totalSystemTime = from.totalSystemTime;
|
||||
totalCPOWTime = from.totalCPOWTime;
|
||||
ticks = from.ticks;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
// A group of compartments forming a single unit in terms of
|
||||
// performance monitoring.
|
||||
//
|
||||
// Two compartments belong to the same group if either:
|
||||
// - they are part of the same add-on;
|
||||
// - they are part of the same webpage;
|
||||
// - they are both system built-ins.
|
||||
//
|
||||
// This class is refcounted by instances of `JSCompartment`.
|
||||
// Do not attempt to hold to a pointer to a `PerformanceGroup`.
|
||||
struct PerformanceGroup {
|
||||
|
||||
// Performance data for this group.
|
||||
PerformanceData data;
|
||||
|
||||
// `true` if an instance of `AutoStopwatch` is already monitoring
|
||||
// the performance of this performance group for this iteration
|
||||
// of the event loop, `false` otherwise.
|
||||
bool hasStopwatch(uint64_t iteration) const {
|
||||
return stopwatch_ != nullptr && iteration_ == iteration;
|
||||
}
|
||||
|
||||
// Mark that an instance of `AutoStopwatch` is monitoring
|
||||
// the performance of this group for a given iteration.
|
||||
void acquireStopwatch(uint64_t iteration, const AutoStopwatch *stopwatch) {
|
||||
iteration_ = iteration;
|
||||
stopwatch_ = stopwatch;
|
||||
}
|
||||
|
||||
// Mark that no `AutoStopwatch` is monitoring the
|
||||
// performance of this group for the iteration.
|
||||
void releaseStopwatch(uint64_t iteration, const AutoStopwatch *stopwatch) {
|
||||
if (iteration_ != iteration)
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(stopwatch == stopwatch_ || stopwatch_ == nullptr);
|
||||
stopwatch_ = nullptr;
|
||||
}
|
||||
|
||||
PerformanceGroup()
|
||||
: stopwatch_(nullptr)
|
||||
, iteration_(0)
|
||||
, refCount_(0)
|
||||
{ }
|
||||
~PerformanceGroup()
|
||||
{
|
||||
MOZ_ASSERT(refCount_ == 0);
|
||||
}
|
||||
private:
|
||||
PerformanceGroup& operator=(const PerformanceGroup&) = delete;
|
||||
PerformanceGroup(const PerformanceGroup&) = delete;
|
||||
|
||||
// The stopwatch currently monitoring the group,
|
||||
// or `nullptr` if none. Used ony for comparison.
|
||||
const AutoStopwatch *stopwatch_;
|
||||
|
||||
// The current iteration of the event loop. If necessary,
|
||||
// may safely overflow.
|
||||
uint64_t iteration_;
|
||||
|
||||
// Increment/decrement the refcounter, return the updated value.
|
||||
uint64_t incRefCount() {
|
||||
MOZ_ASSERT(refCount_ + 1 > 0);
|
||||
return ++refCount_;
|
||||
}
|
||||
uint64_t decRefCount() {
|
||||
MOZ_ASSERT(refCount_ > 0);
|
||||
return --refCount_;
|
||||
}
|
||||
friend struct PerformanceGroupHolder;
|
||||
|
||||
private:
|
||||
// A reference counter. Maintained by PerformanceGroupHolder.
|
||||
uint64_t refCount_;
|
||||
};
|
||||
|
||||
//
|
||||
// Indirection towards a PerformanceGroup.
|
||||
// This structure handles reference counting for instances of PerformanceGroup.
|
||||
//
|
||||
struct PerformanceGroupHolder {
|
||||
// Get the group.
|
||||
// On first call, this causes a single Hashtable lookup.
|
||||
// Successive calls do not require further lookups.
|
||||
js::PerformanceGroup *getGroup();
|
||||
|
||||
// `true` if the this holder is currently associated to a
|
||||
// PerformanceGroup, `false` otherwise. Use this method to avoid
|
||||
// instantiating a PerformanceGroup if you only need to get
|
||||
// available performance data.
|
||||
inline bool isLinked() const {
|
||||
return group_ != nullptr;
|
||||
}
|
||||
|
||||
// Remove the link to the PerformanceGroup. This method is designed
|
||||
// as an invalidation mechanism if the JSCompartment changes nature
|
||||
// (new values of `isSystem()`, `principals()` or `addonId`).
|
||||
void unlink();
|
||||
|
||||
PerformanceGroupHolder(JSRuntime *runtime, JSCompartment *compartment)
|
||||
: runtime_(runtime)
|
||||
, compartment_(compartment)
|
||||
, group_(nullptr)
|
||||
{ }
|
||||
~PerformanceGroupHolder();
|
||||
private:
|
||||
// Return the key representing this PerformanceGroup in
|
||||
// Runtime::Stopwatch.
|
||||
// Do not deallocate the key.
|
||||
void* getHashKey();
|
||||
|
||||
JSRuntime *runtime_;
|
||||
JSCompartment *compartment_;
|
||||
|
||||
// The PerformanceGroup held by this object.
|
||||
// Initially set to `nullptr` until the first cal to `getGroup`.
|
||||
// May be reset to `nullptr` by a call to `unlink`.
|
||||
js::PerformanceGroup *group_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset any stopwatch currently measuring.
|
||||
*
|
||||
* This function is designed to be called when we process a new event.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
ResetStopwatches(JSRuntime*);
|
||||
|
||||
/**
|
||||
* Turn on/off stopwatch-based CPU monitoring.
|
||||
*
|
||||
* `SetStopwatchActive` may return `false` if monitoring could not be
|
||||
* activated, which may happen if we are out of memory.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
SetStopwatchActive(JSRuntime*, bool);
|
||||
extern JS_PUBLIC_API(bool)
|
||||
IsStopwatchActive(JSRuntime*);
|
||||
|
||||
/**
|
||||
* Access the performance information stored in a compartment.
|
||||
*/
|
||||
extern JS_PUBLIC_API(PerformanceData*)
|
||||
GetPerformanceData(JSRuntime*);
|
||||
|
||||
/**
|
||||
* Performance statistics for a performance group (a process, an
|
||||
* add-on, a webpage, the built-ins or a special compartment).
|
||||
*/
|
||||
struct PerformanceStats {
|
||||
/**
|
||||
* If this group represents an add-on, the ID of the addon,
|
||||
* otherwise `nullptr`.
|
||||
*/
|
||||
JSAddonId *addonId;
|
||||
|
||||
/**
|
||||
* If this group represents a webpage, the process itself or a special
|
||||
* compartment, a human-readable name. Unspecified for add-ons.
|
||||
*/
|
||||
char name[1024];
|
||||
|
||||
/**
|
||||
* `true` if the group represents in system compartments, `false`
|
||||
* otherwise. A group may never contain both system and non-system
|
||||
* compartments.
|
||||
*/
|
||||
bool isSystem;
|
||||
|
||||
/**
|
||||
* Performance information.
|
||||
*/
|
||||
js::PerformanceData performance;
|
||||
|
||||
PerformanceStats()
|
||||
: addonId(nullptr)
|
||||
, isSystem(false)
|
||||
{
|
||||
name[0] = '\0';
|
||||
}
|
||||
};
|
||||
|
||||
typedef js::Vector<PerformanceStats, 0, js::SystemAllocPolicy> PerformanceStatsVector;
|
||||
|
||||
/**
|
||||
* Extract the performance statistics.
|
||||
*
|
||||
* After a successful call, `stats` holds the `PerformanceStats` for
|
||||
* all performance groups, and `global` holds a `PerformanceStats`
|
||||
* representing the entire process.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
GetPerformanceStats(JSRuntime *rt, js::PerformanceStatsVector &stats, js::PerformanceStats &global);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
|
||||
#endif /* jsapi_h */
|
||||
|
@ -380,7 +380,7 @@ JSContext::setPendingException(js::Value v)
|
||||
inline bool
|
||||
JSContext::runningWithTrustedPrincipals() const
|
||||
{
|
||||
return !compartment() || compartment()->principals == runtime()->trustedPrincipals();
|
||||
return !compartment() || compartment()->principals() == runtime()->trustedPrincipals();
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -41,8 +41,8 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
|
||||
: options_(options),
|
||||
zone_(zone),
|
||||
runtime_(zone->runtimeFromMainThread()),
|
||||
principals(nullptr),
|
||||
isSystem(false),
|
||||
principals_(nullptr),
|
||||
isSystem_(false),
|
||||
isSelfHosting(false),
|
||||
marked(true),
|
||||
warnedAboutNoSuchMethod(false),
|
||||
@ -53,7 +53,7 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
|
||||
#endif
|
||||
global_(nullptr),
|
||||
enterCompartmentDepth(0),
|
||||
totalTime(0),
|
||||
performanceMonitoring(runtime_, this),
|
||||
data(nullptr),
|
||||
objectMetadataCallback(nullptr),
|
||||
lastAnimationTime(0),
|
||||
@ -871,7 +871,7 @@ void
|
||||
JSCompartment::reportTelemetry()
|
||||
{
|
||||
// Only report telemetry for web content, not add-ons or chrome JS.
|
||||
if (addonId || isSystem)
|
||||
if (addonId || isSystem_)
|
||||
return;
|
||||
|
||||
// Hazard analysis can't tell that the telemetry callbacks don't GC.
|
||||
@ -888,7 +888,7 @@ void
|
||||
JSCompartment::addTelemetry(const char* filename, DeprecatedLanguageExtension e)
|
||||
{
|
||||
// Only report telemetry for web content, not add-ons or chrome JS.
|
||||
if (addonId || isSystem || !filename || strncmp(filename, "http", 4) != 0)
|
||||
if (addonId || isSystem_ || !filename || strncmp(filename, "http", 4) != 0)
|
||||
return;
|
||||
|
||||
sawDeprecatedLanguageExtension[e] = true;
|
||||
|
@ -144,8 +144,50 @@ struct JSCompartment
|
||||
JSRuntime* runtime_;
|
||||
|
||||
public:
|
||||
JSPrincipals* principals;
|
||||
bool isSystem;
|
||||
/*
|
||||
* The principals associated with this compartment. Note that the
|
||||
* same several compartments may share the same principals and
|
||||
* that a compartment may change principals during its lifetime
|
||||
* (e.g. in case of lazy parsing).
|
||||
*/
|
||||
inline JSPrincipals* principals() {
|
||||
return principals_;
|
||||
}
|
||||
inline void setPrincipals(JSPrincipals* principals) {
|
||||
if (principals_ == principals)
|
||||
return;
|
||||
|
||||
// If we change principals, we need to unlink immediately this
|
||||
// compartment from its PerformanceGroup. For one thing, the
|
||||
// performance data we collect should not be improperly associated
|
||||
// with a group to which we do not belong anymore. For another thing,
|
||||
// we use `principals()` as part of the key to map compartments
|
||||
// to a `PerformanceGroup`, so if we do not unlink now, this will
|
||||
// be too late once we have updated `principals_`.
|
||||
performanceMonitoring.unlink();
|
||||
principals_ = principals;
|
||||
}
|
||||
inline bool isSystem() const {
|
||||
return isSystem_;
|
||||
}
|
||||
inline void setIsSystem(bool isSystem) {
|
||||
if (isSystem_ == isSystem)
|
||||
return;
|
||||
|
||||
// If we change `isSystem*(`, we need to unlink immediately this
|
||||
// compartment from its PerformanceGroup. For one thing, the
|
||||
// performance data we collect should not be improperly associated
|
||||
// to a group to which we do not belong anymore. For another thing,
|
||||
// we use `isSystem()` as part of the key to map compartments
|
||||
// to a `PerformanceGroup`, so if we do not unlink now, this will
|
||||
// be too late once we have updated `isSystem_`.
|
||||
performanceMonitoring.unlink();
|
||||
isSystem_ = isSystem;
|
||||
}
|
||||
private:
|
||||
JSPrincipals* principals_;
|
||||
bool isSystem_;
|
||||
public:
|
||||
bool isSelfHosting;
|
||||
bool marked;
|
||||
bool warnedAboutNoSuchMethod;
|
||||
@ -153,7 +195,7 @@ struct JSCompartment
|
||||
|
||||
// A null add-on ID means that the compartment is not associated with an
|
||||
// add-on.
|
||||
JSAddonId* addonId;
|
||||
JSAddonId* const addonId;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool firedOnNewGlobalObject;
|
||||
@ -171,18 +213,13 @@ struct JSCompartment
|
||||
int64_t startInterval;
|
||||
|
||||
public:
|
||||
int64_t totalTime;
|
||||
js::PerformanceGroupHolder performanceMonitoring;
|
||||
|
||||
void enter() {
|
||||
if (addonId && !enterCompartmentDepth) {
|
||||
startInterval = PRMJ_Now();
|
||||
}
|
||||
enterCompartmentDepth++;
|
||||
}
|
||||
void leave() {
|
||||
enterCompartmentDepth--;
|
||||
if (addonId && !enterCompartmentDepth) {
|
||||
totalTime += (PRMJ_Now() - startInterval);
|
||||
}
|
||||
}
|
||||
bool hasBeenEntered() { return !!enterCompartmentDepth; }
|
||||
|
||||
|
@ -156,14 +156,14 @@ JS_NewObjectWithoutMetadata(JSContext* cx, const JSClass* clasp, JS::Handle<JSOb
|
||||
JS_FRIEND_API(JSPrincipals*)
|
||||
JS_GetCompartmentPrincipals(JSCompartment* compartment)
|
||||
{
|
||||
return compartment->principals;
|
||||
return compartment->principals();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS_SetCompartmentPrincipals(JSCompartment* compartment, JSPrincipals* principals)
|
||||
{
|
||||
// Short circuit if there's no change.
|
||||
if (principals == compartment->principals)
|
||||
if (principals == compartment->principals())
|
||||
return;
|
||||
|
||||
// Any compartment with the trusted principals -- and there can be
|
||||
@ -172,24 +172,24 @@ JS_SetCompartmentPrincipals(JSCompartment* compartment, JSPrincipals* principals
|
||||
bool isSystem = principals && principals == trusted;
|
||||
|
||||
// Clear out the old principals, if any.
|
||||
if (compartment->principals) {
|
||||
JS_DropPrincipals(compartment->runtimeFromMainThread(), compartment->principals);
|
||||
compartment->principals = nullptr;
|
||||
if (compartment->principals()) {
|
||||
JS_DropPrincipals(compartment->runtimeFromMainThread(), compartment->principals());
|
||||
compartment->setPrincipals(nullptr);
|
||||
// We'd like to assert that our new principals is always same-origin
|
||||
// with the old one, but JSPrincipals doesn't give us a way to do that.
|
||||
// But we can at least assert that we're not switching between system
|
||||
// and non-system.
|
||||
MOZ_ASSERT(compartment->isSystem == isSystem);
|
||||
MOZ_ASSERT(compartment->isSystem() == isSystem);
|
||||
}
|
||||
|
||||
// Set up the new principals.
|
||||
if (principals) {
|
||||
JS_HoldPrincipals(principals);
|
||||
compartment->principals = principals;
|
||||
compartment->setPrincipals(principals);
|
||||
}
|
||||
|
||||
// Update the system flag.
|
||||
compartment->isSystem = isSystem;
|
||||
compartment->setIsSystem(isSystem);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSPrincipals*)
|
||||
@ -280,7 +280,7 @@ js::GetCompartmentZone(JSCompartment* comp)
|
||||
JS_FRIEND_API(bool)
|
||||
js::IsSystemCompartment(JSCompartment* comp)
|
||||
{
|
||||
return comp->isSystem;
|
||||
return comp->isSystem();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
|
@ -3529,8 +3529,8 @@ Zone::sweepCompartments(FreeOp* fop, bool keepAtleastOne, bool destroyingRuntime
|
||||
if ((!comp->marked && !dontDelete) || destroyingRuntime) {
|
||||
if (callback)
|
||||
callback(fop, comp);
|
||||
if (comp->principals)
|
||||
JS_DropPrincipals(rt, comp->principals);
|
||||
if (comp->principals())
|
||||
JS_DropPrincipals(rt, comp->principals());
|
||||
js_delete(comp);
|
||||
} else {
|
||||
*write++ = comp;
|
||||
|
@ -142,7 +142,7 @@ JSScript::global() const
|
||||
inline JSPrincipals*
|
||||
JSScript::principals()
|
||||
{
|
||||
return compartment()->principals;
|
||||
return compartment()->principals();
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -336,7 +336,7 @@ js::StartOffThreadParseScript(JSContext* cx, const ReadOnlyCompileOptions& optio
|
||||
if (!global)
|
||||
return false;
|
||||
|
||||
JS_SetCompartmentPrincipals(global->compartment(), cx->compartment()->principals);
|
||||
JS_SetCompartmentPrincipals(global->compartment(), cx->compartment()->principals());
|
||||
|
||||
RootedObject obj(cx);
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "vm/Interpreter-inl.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
@ -52,6 +53,13 @@
|
||||
#include "vm/ScopeObject-inl.h"
|
||||
#include "vm/Stack-inl.h"
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
#include <sys/resource.h>
|
||||
#elif defined(XP_WIN)
|
||||
#include <Processthreadsapi.h>
|
||||
#include <Windows.h>
|
||||
#endif // defined(XP_UNIX) || defined(XP_WIN)
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
@ -382,12 +390,234 @@ ExecuteState::pushInterpreterFrame(JSContext* cx)
|
||||
return cx->runtime()->interpreterStack().pushExecuteFrame(cx, script_, thisv_, scopeChain_,
|
||||
type_, evalInFrame_);
|
||||
}
|
||||
namespace js {
|
||||
|
||||
// Implementation of per-performance group performance measurement.
|
||||
//
|
||||
//
|
||||
// All mutable state is stored in `Runtime::stopwatch` (per-process
|
||||
// performance stats and logistics) and in `PerformanceGroup` (per
|
||||
// group performance stats).
|
||||
struct AutoStopwatch final
|
||||
{
|
||||
// If the stopwatch is active, constructing an instance of
|
||||
// AutoStopwatch causes it to become the current owner of the
|
||||
// stopwatch.
|
||||
//
|
||||
// Previous owner is restored upon destruction.
|
||||
explicit inline AutoStopwatch(JSContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: compartment_(nullptr)
|
||||
, runtime_(nullptr)
|
||||
, iteration_(0)
|
||||
, isActive_(false)
|
||||
, isTop_(false)
|
||||
, userTimeStart_(0)
|
||||
, systemTimeStart_(0)
|
||||
, CPOWTimeStart_(0)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
runtime_ = cx->runtime();
|
||||
if (!runtime_->stopwatch.isActive())
|
||||
return;
|
||||
compartment_ = cx->compartment();
|
||||
MOZ_ASSERT(compartment_);
|
||||
if (compartment_->scheduledForDestruction)
|
||||
return;
|
||||
iteration_ = runtime_->stopwatch.iteration;
|
||||
|
||||
PerformanceGroup *group = compartment_->performanceMonitoring.getGroup();
|
||||
MOZ_ASSERT(group);
|
||||
|
||||
if (group->hasStopwatch(iteration_)) {
|
||||
// Someone is already monitoring this group during this
|
||||
// tick, no need for further monitoring.
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the stopwatch.
|
||||
if (!this->getTimes(&userTimeStart_, &systemTimeStart_))
|
||||
return;
|
||||
isActive_ = true;
|
||||
CPOWTimeStart_ = runtime_->stopwatch.performance.totalCPOWTime;
|
||||
|
||||
// We are now in charge of monitoring this group for the tick,
|
||||
// until destruction of `this` or until we enter a nested event
|
||||
// loop and `iteration_` is incremented.
|
||||
group->acquireStopwatch(iteration_, this);
|
||||
|
||||
if (runtime_->stopwatch.isEmpty) {
|
||||
// This is the topmost stopwatch on the stack.
|
||||
// It will be in charge of updating the per-process
|
||||
// performance data.
|
||||
runtime_->stopwatch.isEmpty = false;
|
||||
runtime_->stopwatch.performance.ticks++;
|
||||
isTop_ = true;
|
||||
}
|
||||
}
|
||||
inline ~AutoStopwatch() {
|
||||
if (!isActive_) {
|
||||
// We are not in charge of monitoring anything.
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!compartment_->scheduledForDestruction);
|
||||
|
||||
if (!runtime_->stopwatch.isActive()) {
|
||||
// Monitoring has been stopped while we were
|
||||
// executing the code. Drop everything.
|
||||
return;
|
||||
}
|
||||
|
||||
if (iteration_ != runtime_->stopwatch.iteration) {
|
||||
// We have entered a nested event loop at some point.
|
||||
// Any information we may have is obsolete.
|
||||
return;
|
||||
}
|
||||
|
||||
PerformanceGroup *group = compartment_->performanceMonitoring.getGroup();
|
||||
MOZ_ASSERT(group);
|
||||
|
||||
// Compute time spent.
|
||||
group->releaseStopwatch(iteration_, this);
|
||||
uint64_t userTimeEnd, systemTimeEnd;
|
||||
if (!this->getTimes(&userTimeEnd, &systemTimeEnd))
|
||||
return;
|
||||
|
||||
uint64_t userTimeDelta = userTimeEnd - userTimeStart_;
|
||||
uint64_t systemTimeDelta = systemTimeEnd - systemTimeStart_;
|
||||
uint64_t CPOWTimeDelta = runtime_->stopwatch.performance.totalCPOWTime - CPOWTimeStart_;
|
||||
group->data.totalUserTime += userTimeDelta;
|
||||
group->data.totalSystemTime += systemTimeDelta;
|
||||
group->data.totalCPOWTime += CPOWTimeDelta;
|
||||
|
||||
uint64_t totalTimeDelta = userTimeDelta + systemTimeDelta;
|
||||
updateDurations(totalTimeDelta, group->data.durations);
|
||||
group->data.ticks++;
|
||||
|
||||
if (isTop_) {
|
||||
// This is the topmost stopwatch on the stack.
|
||||
// Record the timing information.
|
||||
runtime_->stopwatch.performance.totalUserTime = userTimeEnd;
|
||||
runtime_->stopwatch.performance.totalSystemTime = systemTimeEnd;
|
||||
updateDurations(totalTimeDelta, runtime_->stopwatch.performance.durations);
|
||||
runtime_->stopwatch.isEmpty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Update an array containing the number of times we have missed
|
||||
// at least 2^0 successive ms, 2^1 successive ms, ...
|
||||
// 2^i successive ms.
|
||||
template<int N>
|
||||
void updateDurations(uint64_t totalTimeDelta, uint64_t (&array)[N]) const {
|
||||
// Duration of one frame, i.e. 16ms in museconds
|
||||
size_t i = 0;
|
||||
uint64_t duration = 1000;
|
||||
for (i = 0, duration = 1000;
|
||||
i < N && duration < totalTimeDelta;
|
||||
++i, duration *= 2) {
|
||||
array[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the OS-reported time spent in userland/systemland,
|
||||
// in microseconds.
|
||||
bool getTimes(uint64_t *userTime, uint64_t *systemTime) const {
|
||||
MOZ_ASSERT(userTime);
|
||||
MOZ_ASSERT(systemTime);
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
|
||||
struct rusage rusage;
|
||||
#if defined(RUSAGE_THREAD)
|
||||
// Under Linux, we can obtain per-thread statistics
|
||||
int err = getrusage(RUSAGE_THREAD, &rusage);
|
||||
#else
|
||||
// Under other Unices, including MacOS X, we need to
|
||||
// do with more noisy per-process statistics.
|
||||
int err = getrusage(RUSAGE_SELF, &rusage);
|
||||
#endif // defined(RUSAGE_THREAD)
|
||||
MOZ_ASSERT(!err);
|
||||
if (err)
|
||||
return false;
|
||||
|
||||
*userTime = rusage.ru_utime.tv_usec
|
||||
+ rusage.ru_utime.tv_sec * 1000000;
|
||||
*systemTime = rusage.ru_stime.tv_usec
|
||||
+ rusage.ru_stime.tv_sec * 1000000;
|
||||
|
||||
#elif defined(XP_WIN)
|
||||
// Under Windows, we can obtain per-thread statistics,
|
||||
// although experience seems to suggest that they are
|
||||
// not very good under Windows XP.
|
||||
FILETIME creationFileTime; // Ignored
|
||||
FILETIME exitFileTime; // Ignored
|
||||
FILETIME kernelFileTime;
|
||||
FILETIME userFileTime;
|
||||
BOOL success = GetThreadTimes(GetCurrentThread(),
|
||||
&creationFileTime, &exitFileTime,
|
||||
&kernelFileTime, &userFileTime);
|
||||
MOZ_ASSERT(success);
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
ULARGE_INTEGER kernelTimeInt;
|
||||
ULARGE_INTEGER userTimeInt;
|
||||
kernelTimeInt.LowPart = kernelFileTime.dwLowDateTime;
|
||||
kernelTimeInt.HighPart = kernelFileTime.dwHighDateTime;
|
||||
*systemTime = kernelTimeInt.QuadPart / 10; // 100 ns to 1 us
|
||||
|
||||
userTimeInt.LowPart = userFileTime.dwLowDateTime;
|
||||
userTimeInt.HighPart = userFileTime.dwHighDateTime;
|
||||
*userTime = userTimeInt.QuadPart / 10; // 100 ns to 1 us
|
||||
#endif // defined(XP_UNIX) || defined(XP_WIN)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// The compartment with which this object was initialized.
|
||||
// Non-null.
|
||||
JSCompartment *compartment_;
|
||||
|
||||
// The runtime with which this object was initialized.
|
||||
// Non-null.
|
||||
JSRuntime *runtime_;
|
||||
|
||||
// An indication of the number of times we have entered the event
|
||||
// loop. Used only for comparison.
|
||||
uint64_t iteration_;
|
||||
|
||||
// `true` if this object is currently used to monitor performance,
|
||||
// `false` otherwise, i.e. if the stopwatch mechanism is off or if
|
||||
// another stopwatch is already in charge of monitoring for the
|
||||
// same PerformanceGroup.
|
||||
bool isActive_;
|
||||
|
||||
// `true` if this stopwatch is the topmost stopwatch on the stack
|
||||
// for this event, `false` otherwise.
|
||||
bool isTop_;
|
||||
|
||||
// Timestamps captured while starting the stopwatch.
|
||||
uint64_t userTimeStart_;
|
||||
uint64_t systemTimeStart_;
|
||||
uint64_t CPOWTimeStart_;
|
||||
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
js::RunScript(JSContext* cx, RunState& state)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
js::AutoStopwatch stopwatch(cx);
|
||||
#endif // defined(NIGHTLY_BUILD)
|
||||
|
||||
SPSEntryMarker marker(cx->runtime(), state.script());
|
||||
|
||||
state.script()->ensureNonLazyCanonicalFunction(cx);
|
||||
|
@ -795,7 +795,7 @@ JS::SystemCompartmentCount(JSRuntime* rt)
|
||||
{
|
||||
size_t n = 0;
|
||||
for (CompartmentsIter comp(rt, WithAtoms); !comp.done(); comp.next()) {
|
||||
if (comp->isSystem)
|
||||
if (comp->isSystem())
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
@ -806,7 +806,7 @@ JS::UserCompartmentCount(JSRuntime* rt)
|
||||
{
|
||||
size_t n = 0;
|
||||
for (CompartmentsIter comp(rt, WithAtoms); !comp.done(); comp.next()) {
|
||||
if (!comp->isSystem)
|
||||
if (!comp->isSystem())
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
|
@ -290,7 +290,7 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
|
||||
gc.zones.append(atomsZone.get());
|
||||
atomsZone->compartments.append(atomsCompartment.get());
|
||||
|
||||
atomsCompartment->isSystem = true;
|
||||
atomsCompartment->setIsSystem(true);
|
||||
|
||||
atomsZone.forget();
|
||||
this->atomsCompartment_ = atomsCompartment.forget();
|
||||
@ -859,3 +859,93 @@ JS::IsProfilingEnabledForRuntime(JSRuntime* runtime)
|
||||
MOZ_ASSERT(runtime);
|
||||
return runtime->spsProfiler.enabled();
|
||||
}
|
||||
|
||||
void
|
||||
js::ResetStopwatches(JSRuntime *rt)
|
||||
{
|
||||
MOZ_ASSERT(rt);
|
||||
rt->stopwatch.reset();
|
||||
}
|
||||
|
||||
bool
|
||||
js::SetStopwatchActive(JSRuntime *rt, bool isActive)
|
||||
{
|
||||
MOZ_ASSERT(rt);
|
||||
return rt->stopwatch.setIsActive(isActive);
|
||||
}
|
||||
|
||||
bool
|
||||
js::IsStopwatchActive(JSRuntime *rt)
|
||||
{
|
||||
MOZ_ASSERT(rt);
|
||||
return rt->stopwatch.isActive();
|
||||
}
|
||||
|
||||
js::PerformanceGroupHolder::~PerformanceGroupHolder()
|
||||
{
|
||||
unlink();
|
||||
}
|
||||
|
||||
void*
|
||||
js::PerformanceGroupHolder::getHashKey()
|
||||
{
|
||||
return compartment_->isSystem() ?
|
||||
(void*)compartment_->addonId :
|
||||
(void*)JS_GetCompartmentPrincipals(compartment_);
|
||||
// This key may be `nullptr` if we have `isSystem() == true`
|
||||
// and `compartment_->addonId`. This is absolutely correct,
|
||||
// and this represents the `PerformanceGroup` used to track
|
||||
// the performance of the the platform compartments.
|
||||
}
|
||||
|
||||
void
|
||||
js::PerformanceGroupHolder::unlink()
|
||||
{
|
||||
if (!group_) {
|
||||
// The group has never been instantiated.
|
||||
return;
|
||||
}
|
||||
|
||||
js::PerformanceGroup* group = group_;
|
||||
group_ = nullptr;
|
||||
|
||||
if (group->decRefCount() > 0) {
|
||||
// The group has at least another owner.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
JSRuntime::Stopwatch::Groups::Ptr ptr =
|
||||
runtime_->stopwatch.groups_.lookup(getHashKey());
|
||||
MOZ_ASSERT(ptr);
|
||||
runtime_->stopwatch.groups_.remove(ptr);
|
||||
js_delete(group);
|
||||
}
|
||||
|
||||
PerformanceGroup *
|
||||
js::PerformanceGroupHolder::getGroup()
|
||||
{
|
||||
if (group_)
|
||||
return group_;
|
||||
|
||||
void* key = getHashKey();
|
||||
JSRuntime::Stopwatch::Groups::AddPtr ptr =
|
||||
runtime_->stopwatch.groups_.lookupForAdd(key);
|
||||
if (ptr) {
|
||||
group_ = ptr->value();
|
||||
MOZ_ASSERT(group_);
|
||||
} else {
|
||||
group_ = runtime_->new_<PerformanceGroup>();
|
||||
runtime_->stopwatch.groups_.add(ptr, key, group_);
|
||||
}
|
||||
|
||||
group_->incRefCount();
|
||||
|
||||
return group_;
|
||||
}
|
||||
|
||||
PerformanceData*
|
||||
js::GetPerformanceData(JSRuntime *rt)
|
||||
{
|
||||
return &rt->stopwatch.performance;
|
||||
}
|
||||
|
@ -567,6 +567,7 @@ class PerThreadData : public PerThreadDataFriendFields
|
||||
|
||||
class AutoLockForExclusiveAccess;
|
||||
|
||||
struct AutoStopwatch;
|
||||
} // namespace js
|
||||
|
||||
struct JSRuntime : public JS::shadow::Runtime,
|
||||
@ -1453,6 +1454,113 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
|
||||
/* Last time at which an animation was played for this runtime. */
|
||||
int64_t lastAnimationTime;
|
||||
|
||||
public:
|
||||
|
||||
/* ------------------------------------------
|
||||
Performance measurements
|
||||
------------------------------------------ */
|
||||
struct Stopwatch {
|
||||
/**
|
||||
* The number of times we have entered the event loop.
|
||||
* Used to reset counters whenever we enter the loop,
|
||||
* which may be caused either by having completed the
|
||||
* previous run of the event loop, or by entering a
|
||||
* nested loop.
|
||||
*
|
||||
* Always incremented by 1, may safely overflow.
|
||||
*/
|
||||
uint64_t iteration;
|
||||
|
||||
/**
|
||||
* `true` if no stopwatch has been registered for the
|
||||
* current run of the event loop, `false` until then.
|
||||
*/
|
||||
bool isEmpty;
|
||||
|
||||
/**
|
||||
* Performance data on the entire runtime.
|
||||
*/
|
||||
js::PerformanceData performance;
|
||||
|
||||
Stopwatch()
|
||||
: iteration(0)
|
||||
, isEmpty(true)
|
||||
, isActive_(false)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Reset the stopwatch.
|
||||
*
|
||||
* This method is meant to be called whenever we start processing
|
||||
* an event, to ensure that stop any ongoing measurement that would
|
||||
* otherwise provide irrelevant results.
|
||||
*/
|
||||
void reset() {
|
||||
++iteration;
|
||||
isEmpty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate/deactivate stopwatch measurement.
|
||||
*
|
||||
* Noop if `value` is `true` and the stopwatch is already active,
|
||||
* or if `value` is `false` and the stopwatch is already inactive.
|
||||
*
|
||||
* Otherwise, any pending measurements are dropped, but previous
|
||||
* measurements remain stored.
|
||||
*
|
||||
* May return `false` if the underlying hashtable cannot be allocated.
|
||||
*/
|
||||
bool setIsActive(bool value) {
|
||||
if (isActive_ != value)
|
||||
reset();
|
||||
|
||||
if (value && !groups_.initialized()) {
|
||||
if (!groups_.init(128))
|
||||
return false;
|
||||
}
|
||||
|
||||
isActive_ = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* `true` if the stopwatch is currently monitoring, `false` otherwise.
|
||||
*/
|
||||
bool isActive() const {
|
||||
return isActive_;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* A map used to collapse compartments belonging to the same
|
||||
* add-on (respectively to the same webpage, to the platform)
|
||||
* into a single group.
|
||||
*
|
||||
* Keys: for system compartments, a `JSAddonId*` (which may be
|
||||
* `nullptr`), and for webpages, a `JSPrincipals*` (which may
|
||||
* not). Note that compartments may start as non-system
|
||||
* compartments and become compartments later during their
|
||||
* lifetime, which requires an invalidation.
|
||||
*
|
||||
* This map is meant to be accessed only by instances of
|
||||
* PerformanceGroupHolder, which handle both reference-counting
|
||||
* of the values and invalidation of the key/value pairs.
|
||||
*/
|
||||
typedef js::HashMap<void*, js::PerformanceGroup*,
|
||||
js::DefaultHasher<void*>,
|
||||
js::SystemAllocPolicy> Groups;
|
||||
|
||||
Groups groups_;
|
||||
friend struct js::PerformanceGroupHolder;
|
||||
|
||||
/**
|
||||
* `true` if stopwatch monitoring is active, `false` otherwise.
|
||||
*/
|
||||
bool isActive_;
|
||||
};
|
||||
Stopwatch stopwatch;
|
||||
};
|
||||
|
||||
namespace js {
|
||||
|
@ -370,7 +370,7 @@ GetFirstSubsumedFrame(JSContext* cx, HandleSavedFrame frame, bool& skippedAsync)
|
||||
if (!subsumes)
|
||||
return frame;
|
||||
|
||||
JSPrincipals* principals = cx->compartment()->principals;
|
||||
JSPrincipals* principals = cx->compartment()->principals();
|
||||
|
||||
RootedSavedFrame rootedFrame(cx, frame);
|
||||
while (rootedFrame && !subsumes(principals, rootedFrame->getPrincipals())) {
|
||||
@ -475,8 +475,8 @@ public:
|
||||
if (obj && cx->compartment() != obj->compartment())
|
||||
{
|
||||
JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes;
|
||||
if (subsumes && subsumes(cx->compartment()->principals,
|
||||
obj->compartment()->principals))
|
||||
if (subsumes && subsumes(cx->compartment()->principals(),
|
||||
obj->compartment()->principals()))
|
||||
{
|
||||
ac_.emplace(cx, obj);
|
||||
}
|
||||
@ -649,7 +649,7 @@ BuildStackString(JSContext* cx, HandleObject stack, MutableHandleString stringp)
|
||||
}
|
||||
|
||||
DebugOnly<JSSubsumesOp> subsumes = cx->runtime()->securityCallbacks->subsumes;
|
||||
DebugOnly<JSPrincipals*> principals = cx->compartment()->principals;
|
||||
DebugOnly<JSPrincipals*> principals = cx->compartment()->principals();
|
||||
|
||||
js::RootedSavedFrame parent(cx);
|
||||
do {
|
||||
@ -936,7 +936,7 @@ SavedStacks::insertFrames(JSContext* cx, FrameIter& iter, MutableHandleSavedFram
|
||||
iter.isNonEvalFunctionFrame() ? iter.functionDisplayAtom() : nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
iter.compartment()->principals
|
||||
iter.compartment()->principals()
|
||||
);
|
||||
|
||||
++iter;
|
||||
|
@ -1133,7 +1133,7 @@ JSRuntime::createSelfHostingGlobal(JSContext* cx)
|
||||
|
||||
cx->runtime()->selfHostingGlobal_ = shg;
|
||||
compartment->isSelfHosting = true;
|
||||
compartment->isSystem = true;
|
||||
compartment->setIsSystem(true);
|
||||
|
||||
if (!GlobalObject::initSelfHostingBuiltins(cx, shg, intrinsic_functions))
|
||||
return nullptr;
|
||||
|
@ -252,7 +252,7 @@ uint8_t*
|
||||
InterpreterStack::allocateFrame(JSContext* cx, size_t size)
|
||||
{
|
||||
size_t maxFrames;
|
||||
if (cx->compartment()->principals == cx->runtime()->trustedPrincipals())
|
||||
if (cx->compartment()->principals() == cx->runtime()->trustedPrincipals())
|
||||
maxFrames = MAX_FRAMES_TRUSTED;
|
||||
else
|
||||
maxFrames = MAX_FRAMES;
|
||||
|
@ -530,7 +530,7 @@ FrameIter::settleOnActivation()
|
||||
if (data_.principals_) {
|
||||
JSContext* cx = data_.cx_->asJSContext();
|
||||
if (JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes) {
|
||||
if (!subsumes(data_.principals_, activation->compartment()->principals)) {
|
||||
if (!subsumes(data_.principals_, activation->compartment()->principals())) {
|
||||
++data_.activations_;
|
||||
continue;
|
||||
}
|
||||
|
@ -348,13 +348,6 @@ xpc::TraceXPCGlobal(JSTracer* trc, JSObject* obj)
|
||||
|
||||
namespace xpc {
|
||||
|
||||
uint64_t
|
||||
GetCompartmentCPOWMicroseconds(JSCompartment* compartment)
|
||||
{
|
||||
xpc::CompartmentPrivate* compartmentPrivate = xpc::CompartmentPrivate::Get(compartment);
|
||||
return compartmentPrivate ? PR_IntervalToMicroseconds(compartmentPrivate->CPOWTime) : 0;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
CreateGlobalObject(JSContext* cx, const JSClass* clasp, nsIPrincipal* principal,
|
||||
JS::CompartmentOptions& aOptions)
|
||||
|
@ -627,6 +627,7 @@ public:
|
||||
void OnProcessNextEvent() {
|
||||
mSlowScriptCheckpoint = mozilla::TimeStamp::NowLoRes();
|
||||
mSlowScriptSecondHalf = false;
|
||||
js::ResetStopwatches(Get()->Runtime());
|
||||
}
|
||||
void OnAfterProcessNextEvent() {
|
||||
mSlowScriptCheckpoint = mozilla::TimeStamp();
|
||||
@ -3647,7 +3648,6 @@ public:
|
||||
, skipWriteToGlobalPrototype(false)
|
||||
, universalXPConnectEnabled(false)
|
||||
, forcePermissiveCOWs(false)
|
||||
, CPOWTime(0)
|
||||
, skipCOWCallableChecks(false)
|
||||
, scriptability(c)
|
||||
, scope(nullptr)
|
||||
@ -3701,9 +3701,6 @@ public:
|
||||
// Using it in production is inherently unsafe.
|
||||
bool forcePermissiveCOWs;
|
||||
|
||||
// A running count of how much time we've spent processing CPOWs.
|
||||
PRIntervalTime CPOWTime;
|
||||
|
||||
// Disables the XPConnect security checks that deny access to callables and
|
||||
// accessor descriptors on COWs. Do not use this unless you are bholley.
|
||||
bool skipCOWCallableChecks;
|
||||
|
@ -902,6 +902,7 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame,
|
||||
if (widget) {
|
||||
nsIntRect widgetBounds;
|
||||
widget->GetBounds(widgetBounds);
|
||||
widgetBounds.MoveTo(0,0);
|
||||
metrics.mCompositionBounds = ParentLayerRect(ViewAs<ParentLayerPixel>(widgetBounds));
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
if (frameBounds.height < metrics.mCompositionBounds.height) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user