--- a/browser/base/content/browser-fullScreen.js
+++ b/browser/base/content/browser-fullScreen.js
@@ -152,19 +152,24 @@ var FullScreen = {
case "MozDOMFullscreen:Exited":
this.cleanupDomFullscreen();
break;
}
},
receiveMessage: function(aMessage) {
let browser = aMessage.target;
+ let data = aMessage.data;
switch (aMessage.name) {
case "DOMFullscreen:Request": {
- this._windowUtils.remoteFrameFullscreenChanged(browser);
+ let hmd = 0;
+ if (data && data.vrDeviceID) {
+ hmd = aMessage.data.vrDeviceID;
+ }
+ this._windowUtils.remoteFrameFullscreenChanged(browser, hmd);
break;
}
case "DOMFullscreen:NewOrigin": {
this._WarningBox.show(aMessage.data.originNoSuffix);
break;
}
case "DOMFullscreen:Exit": {
this._windowUtils.remoteFrameFullscreenReverted();
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -643,17 +643,21 @@ var DOMFullscreenHandler = {
break;
}
}
},
handleEvent: function(aEvent) {
switch (aEvent.type) {
case "MozDOMFullscreen:Request": {
- sendAsyncMessage("DOMFullscreen:Request");
+ let data = {
+ // will be 0 if not VR
+ vrDeviceID: this._windowUtils.vrHMDDeviceID
+ };
+ sendAsyncMessage("DOMFullscreen:Request", data);
break;
}
case "MozDOMFullscreen:NewOrigin": {
this._fullscreenDoc = aEvent.target;
sendAsyncMessage("DOMFullscreen:NewOrigin", {
originNoSuffix: this._fullscreenDoc.nodePrincipal.originNoSuffix,
});
break;
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3290,17 +3290,17 @@ Element::MozRequestFullScreen(JSContext*
if (convertible) {
if (!fsOptions.Init(aCx, aOptions)) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
if (fsOptions.mVrDisplay) {
- request->mVRHMDDevice = fsOptions.mVrDisplay->GetHMD();
+ request->mVRHMDDeviceIndex = fsOptions.mVrDisplay->GetHMD()->GetDeviceInfo().GetDeviceID();
}
}
}
OwnerDoc()->AsyncRequestFullScreen(Move(request));
}
void
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -3029,22 +3029,23 @@ nsDOMWindowUtils::SetScrollPositionClamp
}
nsLayoutUtils::SetScrollPositionClampingScrollPortSize(presShell, CSSSize(aWidth, aHeight));
return NS_OK;
}
nsresult
-nsDOMWindowUtils::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement)
+nsDOMWindowUtils::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
+ PRInt32 aVRDeviceIndex)
{
nsCOMPtr<nsIDocument> doc = GetDocument();
NS_ENSURE_STATE(doc);
- doc->RemoteFrameFullscreenChanged(aFrameElement);
+ doc->RemoteFrameFullscreenChanged(aFrameElement, aVRDeviceIndex);
return NS_OK;
}
nsresult
nsDOMWindowUtils::RemoteFrameFullscreenReverted()
{
nsCOMPtr<nsIDocument> doc = GetDocument();
NS_ENSURE_STATE(doc);
@@ -3861,16 +3862,30 @@ nsDOMWindowUtils::SetNextPaintSyncId(int
return NS_OK;
}
}
NS_WARNING("Paint sync id could not be set on the ClientLayerManager");
return NS_OK;
}
+NS_IMETHODIMP
+nsDOMWindowUtils::GetVrHMDDeviceID(uint32_t* aResult)
+{
+ if (!nsContentUtils::IsCallerChrome()) {
+ return NS_ERROR_DOM_SECURITY_ERR;
+ }
+
+ nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+ NS_ENSURE_STATE(window);
+
+ *aResult = window->GetVRHMDDeviceIndex();
+ return NS_OK;
+}
+
NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsTranslationNodeList)
NS_IMPL_RELEASE(nsTranslationNodeList)
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -235,18 +235,18 @@
#include "nsIStructuredCloneContainer.h"
#include "nsIMutableArray.h"
#include "nsContentPermissionHelper.h"
#include "mozilla/dom/DOMStringList.h"
#include "nsWindowMemoryReporter.h"
#include "nsLocation.h"
#include "mozilla/dom/FontFaceSet.h"
#include "mozilla/dom/BoxObject.h"
-#include "gfxVR.h"
#include "gfxPrefs.h"
+#include "VRManager.h"
#include "nsISupportsPrimitives.h"
#include "mozilla/DocLoadingTimelineMarker.h"
#include "nsISpeculativeConnect.h"
#ifdef MOZ_MEDIA_NAVIGATOR
#include "mozilla/MediaManager.h"
@@ -11040,16 +11040,17 @@ public:
// MozDOMFullscreen:Entered dispatched.
nsIDocument* lastDocument = mDocuments[mDocuments.Length() - 1];
nsContentUtils::DispatchEventOnlyToChrome(
lastDocument, ToSupports(lastDocument),
NS_LITERAL_STRING("MozDOMFullscreen:Exited"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
// Ensure the window exits fullscreen.
if (nsPIDOMWindow* win = mDocuments[0]->GetWindow()) {
+ win->SetVRHMDDeviceIndex(0);
win->SetFullscreenInternal(nsPIDOMWindow::eForForceExitFullscreen, false);
}
return NS_OK;
}
private:
nsCOMArray<nsIDocument> mDocuments;
};
@@ -11427,44 +11428,40 @@ IsInActiveTab(nsIDocument* aDoc)
fm->GetActiveWindow(getter_AddRefs(activeWindow));
if (!activeWindow) {
return false;
}
return activeWindow == rootWin;
}
-nsresult nsDocument::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement)
+nsresult nsDocument::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
+ PRInt32 aVRDeviceIndex)
{
// Ensure the frame element is the fullscreen element in this document.
// If the frame element is already the fullscreen element in this document,
// this has no effect.
nsCOMPtr<nsIContent> content(do_QueryInterface(aFrameElement));
auto request = MakeUnique<FullscreenRequest>(content->AsElement());
request->mIsCallerChrome = false;
request->mShouldNotifyNewOrigin = false;
+ if (aVRDeviceIndex > 0) {
+ request->mVRHMDDeviceIndex = aVRDeviceIndex;
+ }
RequestFullScreen(Move(request));
return NS_OK;
}
nsresult nsDocument::RemoteFrameFullscreenReverted()
{
RestorePreviousFullScreenState();
return NS_OK;
}
-static void
-ReleaseVRDeviceProxyRef(void *, nsIAtom*, void *aPropertyValue, void *)
-{
- if (aPropertyValue) {
- static_cast<gfx::VRDeviceProxy*>(aPropertyValue)->Release();
- }
-}
-
bool
nsDocument::FullscreenElementReadyCheck(Element* aElement,
bool aWasCallerChrome)
{
NS_ASSERTION(aElement,
"Must pass non-null element to nsDocument::RequestFullScreen");
if (!aElement || aElement == GetFullScreenElement()) {
return false;
@@ -11700,28 +11697,36 @@ nsDocument::RequestFullScreen(UniquePtr<
// We don't need to check element ready before this point, because
// if we called ApplyFullscreen, it would check that for us.
Element* elem = aRequest->GetElement();
if (!FullscreenElementReadyCheck(elem, aRequest->mIsCallerChrome)) {
return;
}
PendingFullscreenRequestList::Add(Move(aRequest));
+ const FullscreenRequest*
+ lastRequest = PendingFullscreenRequestList::GetLast();
if (XRE_GetProcessType() == GeckoProcessType_Content) {
// If we are not the top level process, dispatch an event to make
// our parent process go fullscreen first.
+
+ // First, if we have a HMD, inform the root window
+ if (lastRequest->mVRHMDDeviceIndex) {
+ rootWin->SetVRHMDDeviceIndex(lastRequest->mVRHMDDeviceIndex);
+ }
+
+ // Then send an event to chrome, which will be turned into a message
+ // to the parent.
nsContentUtils::DispatchEventOnlyToChrome(
this, ToSupports(this), NS_LITERAL_STRING("MozDOMFullscreen:Request"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
} else {
// Make the window fullscreen.
- const FullscreenRequest*
- lastRequest = PendingFullscreenRequestList::GetLast();
rootWin->SetFullscreenInternal(nsPIDOMWindow::eForFullscreenAPI, true,
- lastRequest->mVRHMDDevice);
+ lastRequest->mVRHMDDeviceIndex);
}
}
/* static */ bool
nsIDocument::HandlePendingFullscreenRequests(nsIDocument* aDoc)
{
bool handled = false;
PendingFullscreenRequestList::Iterator iter(
@@ -11768,21 +11773,21 @@ nsDocument::ApplyFullscreen(const Fullsc
// Remember the root document, so that if a full-screen document is hidden
// we can reset full-screen state in the remaining visible full-screen documents.
nsIDocument* fullScreenRootDoc = nsContentUtils::GetRootDocument(this);
// If a document is already in fullscreen, then unlock the mouse pointer
// before setting a new document to fullscreen
UnlockPointer();
- // Process options -- in this case, just HMD
- if (aRequest.mVRHMDDevice) {
- RefPtr<gfx::VRDeviceProxy> hmdRef = aRequest.mVRHMDDevice;
- elem->SetProperty(nsGkAtoms::vr_state, hmdRef.forget().take(),
- ReleaseVRDeviceProxyRef, true);
+ // vr_state
+ if (aRequest.mVRHMDDeviceIndex) {
+ elem->SetProperty(nsGkAtoms::vr_state,
+ reinterpret_cast<void*>(aRequest.mVRHMDDeviceIndex),
+ nullptr, true);
}
// Set the full-screen element. This sets the full-screen style on the
// element, and the full-screen-ancestor styles on ancestors of the element
// in this document.
DebugOnly<bool> x = FullScreenStackPush(elem);
NS_ASSERTION(x, "Full-screen state of requesting doc should always change!");
// Set the iframe fullscreen flag.
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -106,27 +106,28 @@ struct FullscreenRequest : public Linked
Element* GetElement() const { return mElement; }
nsDocument* GetDocument() const { return mDocument; }
private:
RefPtr<Element> mElement;
RefPtr<nsDocument> mDocument;
public:
- RefPtr<gfx::VRDeviceProxy> mVRHMDDevice;
// This value should be true if the fullscreen request is
// originated from chrome code.
bool mIsCallerChrome = false;
// This value denotes whether we should trigger a NewOrigin event if
// requesting fullscreen in its document causes the origin which is
// fullscreen to change. We may want *not* to trigger that event if
// we're calling RequestFullScreen() as part of a continuation of a
// request in a subdocument in different process, whereupon the caller
// need to send some notification itself with the real origin.
bool mShouldNotifyNewOrigin = true;
+ // The VR device index, if any.
+ uint32_t mVRHMDDeviceIndex = 0;
};
} // namespace dom
} // namespace mozilla
/**
* Right now our identifier map entries contain information for 'name'
* and 'id' mappings of a given string. This is so that
@@ -1193,18 +1194,18 @@ public:
virtual Element* GetFullScreenElement() override;
virtual nsTArray<Element*> GetFullscreenStack() const override;
virtual void AsyncRequestFullScreen(
mozilla::UniquePtr<FullscreenRequest>&& aRequest) override;
virtual void RestorePreviousFullScreenState() override;
virtual bool IsFullscreenLeaf() override;
virtual bool IsFullScreenDoc() override;
- virtual nsresult
- RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement) override;
+ virtual nsresult RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
+ PRInt32 aVRDeviceIndex = 0) override;
virtual nsresult RemoteFrameFullscreenReverted() override;
virtual nsIDocument* GetFullscreenRoot() override;
virtual void SetFullscreenRoot(nsIDocument* aRoot) override;
// Returns the size of the mBlockedTrackingNodes array. (nsIDocument.h)
//
// This array contains nodes that have been blocked to prevent
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -186,16 +186,17 @@
#include "mozilla/dom/indexedDB/IDBFactory.h"
#include "mozilla/dom/Promise.h"
#ifdef MOZ_GAMEPAD
#include "mozilla/dom/Gamepad.h"
#include "mozilla/dom/GamepadService.h"
#endif
+#include "VRManager.h"
#include "mozilla/dom/VRDevice.h"
#include "nsRefreshDriver.h"
#include "Layers.h"
#include "mozilla/AddonPathService.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/Services.h"
@@ -5987,17 +5988,17 @@ FullscreenTransitionTask::Observer::Obse
obs->RemoveObserver(this, kPaintedTopic);
mTask->mTimer = nullptr;
mTask->Run();
}
return NS_OK;
}
static bool
-MakeWidgetFullscreen(nsGlobalWindow* aWindow, gfx::VRDeviceProxy* aHMD,
+MakeWidgetFullscreen(nsGlobalWindow* aWindow, uint32_t aVRDeviceIndex,
nsPIDOMWindow::FullscreenReason aReason, bool aFullscreen)
{
nsCOMPtr<nsIWidget> widget = aWindow->GetMainWidget();
if (!widget) {
return false;
}
FullscreenTransitionDuration duration;
@@ -6005,32 +6006,41 @@ MakeWidgetFullscreen(nsGlobalWindow* aWi
nsCOMPtr<nsISupports> transitionData;
if (aReason == nsPIDOMWindow::eForFullscreenAPI) {
GetFullscreenTransitionDuration(aFullscreen, &duration);
if (!duration.IsSuppressed()) {
performTransition = widget->
PrepareForFullscreenTransition(getter_AddRefs(transitionData));
}
}
- nsCOMPtr<nsIScreen> screen = aHMD ? aHMD->GetScreen() : nullptr;
+
+ nsCOMPtr<nsIScreen> screen;
+ RefPtr<gfx::VRHMDInfo> hmd;
+ if (!XRE_IsContentProcess() && aVRDeviceIndex) {
+ hmd = gfx::VRManager::Get()->GetDevice(aVRDeviceIndex);
+ screen = hmd->GetScreen();
+ }
+
+ widget->SetAttachedHMD(hmd);
+
if (!performTransition) {
return aWindow->SetWidgetFullscreen(aReason, aFullscreen, widget, screen);
- } else {
- nsCOMPtr<nsIRunnable> task =
- new FullscreenTransitionTask(duration, aWindow, aFullscreen,
- widget, screen, transitionData);
- task->Run();
- return true;
- }
+ }
+
+ nsCOMPtr<nsIRunnable> task =
+ new FullscreenTransitionTask(duration, aWindow, aFullscreen,
+ widget, screen, transitionData);
+ task->Run();
+ return true;
}
nsresult
nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
bool aFullScreen,
- gfx::VRDeviceProxy* aHMD)
+ uint32_t aVRDeviceIndex)
{
MOZ_ASSERT(IsOuterWindow());
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript(),
"Requires safe to run script as it "
"may call FinishDOMFullscreenChange");
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
@@ -6048,17 +6058,17 @@ nsGlobalWindow::SetFullscreenInternal(Fu
// via the DocShell tree, and if we are not already the root,
// call SetFullScreen on that window instead.
nsCOMPtr<nsIDocShellTreeItem> rootItem;
mDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
nsCOMPtr<nsPIDOMWindow> window = rootItem ? rootItem->GetWindow() : nullptr;
if (!window)
return NS_ERROR_FAILURE;
if (rootItem != mDocShell)
- return window->SetFullscreenInternal(aReason, aFullScreen, aHMD);
+ return window->SetFullscreenInternal(aReason, aFullScreen, aVRDeviceIndex);
// make sure we don't try to set full screen on a non-chrome window,
// which might happen in embedding world
if (mDocShell->ItemType() != nsIDocShellTreeItem::typeChrome)
return NS_ERROR_FAILURE;
// If we are already in full screen mode, just return.
if (mFullScreen == aFullScreen)
@@ -6099,17 +6109,17 @@ nsGlobalWindow::SetFullscreenInternal(Fu
// gone full screen, the state trap above works.
mFullScreen = aFullScreen;
// Sometimes we don't want the top-level widget to actually go fullscreen,
// for example in the B2G desktop client, we don't want the emulated screen
// dimensions to appear to increase when entering fullscreen mode; we just
// want the content to fill the entire client area of the emulator window.
if (!Preferences::GetBool("full-screen-api.ignore-widgets", false)) {
- if (MakeWidgetFullscreen(this, aHMD, aReason, aFullScreen)) {
+ if (MakeWidgetFullscreen(this, aVRDeviceIndex, aReason, aFullScreen)) {
// The rest of code for switching fullscreen is in nsGlobalWindow::
// FinishFullscreenChange() which will be called after sizemodechange
// event is dispatched.
return NS_OK;
}
}
// If we didn't setup the widget, we may need to manually set this
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -466,17 +466,17 @@ public:
virtual void RefreshCompartmentPrincipal() override;
// For accessing protected field mFullScreen
friend class FullscreenTransitionTask;
// Outer windows only.
virtual nsresult SetFullscreenInternal(
FullscreenReason aReason, bool aIsFullscreen,
- mozilla::gfx::VRDeviceProxy *aHMD = nullptr) override final;
+ uint32_t aVRDeviceIndex = 0) override final;
virtual void FinishFullscreenChange(bool aIsFullscreen) override final;
bool SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen,
nsIWidget* aWidget, nsIScreen* aScreen);
bool FullScreen() const;
// Inner windows only.
virtual void SetHasGamepadEventListener(bool aHasGamepad = true) override;
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -1156,19 +1156,22 @@ public:
virtual void AsyncRequestFullScreen(
mozilla::UniquePtr<FullscreenRequest>&& aRequest) = 0;
/**
* Called when a frame in a child process has entered fullscreen or when a
* fullscreen frame in a child process changes to another origin.
* aFrameElement is the frame element which contains the child-process
* fullscreen document.
+ *
+ * If nonzero, the fullscreen happens on the given VR HMD device index.
*/
virtual nsresult
- RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement) = 0;
+ RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
+ PRInt32 aVRDeviceIndex = 0) = 0;
/**
* Called when a frame in a remote child document has rolled back fullscreen
* so that all its fullscreen element stacks are empty; we must continue the
* rollback in this parent process' doc tree branch which is fullscreen.
* Note that only one branch of the document tree can have its documents in
* fullscreen state at one time. We're in inconsistent state if a
* fullscreen document has a parent and that parent isn't fullscreen. We
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -36,19 +36,16 @@ class nsXBLPrototypeHandler;
struct nsTimeout;
namespace mozilla {
namespace dom {
class AudioContext;
class Element;
class ServiceWorkerRegistrationMainThread;
} // namespace dom
-namespace gfx {
-class VRDeviceProxy;
-} // namespace gfx
} // namespace mozilla
// Popup control state enum. The values in this enum must go from most
// permissive to least permissive so that it's safe to push state in
// all situations. Pushing popup state onto the stack never makes the
// current popup state less permissive (see
// nsGlobalWindow::PushPopupControlState()).
enum PopupControlState {
@@ -500,24 +497,24 @@ public:
// suppress the fullscreen transition.
eForForceExitFullscreen
};
/**
* Moves the top-level window into fullscreen mode if aIsFullScreen is true,
* otherwise exits fullscreen.
*
- * If aHMD is not null, the window is made full screen on the given VR HMD
+ * If aVRDeviceIndex is not 0, the window is made full screen on the given VR HMD
* device instead of its currrent display.
*
* Outer windows only.
*/
virtual nsresult SetFullscreenInternal(
FullscreenReason aReason, bool aIsFullscreen,
- mozilla::gfx::VRDeviceProxy *aHMD = nullptr) = 0;
+ uint32_t aVRDeviceIndex = 0) = 0;
/**
* This function should be called when the fullscreen state is flipped.
* If no widget is involved the fullscreen change, this method is called
* by SetFullscreenInternal, otherwise, it is called when the widget
* finishes its change to or from fullscreen.
*
* @param aIsFullscreen indicates whether the widget is in fullscreen.
@@ -815,16 +812,19 @@ public:
virtual nsresult SetFullScreen(bool aFullScreen) = 0;
virtual nsresult Focus() = 0;
virtual nsresult Close() = 0;
virtual nsresult MoveBy(int32_t aXDif, int32_t aYDif) = 0;
virtual nsresult UpdateCommands(const nsAString& anAction, nsISelection* aSel, int16_t aReason) = 0;
+ virtual void SetVRHMDDeviceIndex(uint32_t aDeviceIndex) { mVRHMDDeviceIndex = aDeviceIndex; }
+ virtual uint32_t GetVRHMDDeviceIndex() const { return mVRHMDDeviceIndex; }
+
protected:
// The nsPIDOMWindow constructor. The aOuterWindow argument should
// be null if and only if the created window itself is an outer
// window. In all other cases aOuterWindow should be the outer
// window for the inner window that is being created.
explicit nsPIDOMWindow(nsPIDOMWindow *aOuterWindow);
~nsPIDOMWindow();
@@ -922,16 +922,19 @@ protected:
// the (chrome|content)-document-global-created notification.
bool mHasNotifiedGlobalCreated;
uint32_t mMarkedCCGeneration;
// Let the service workers plumbing know that some feature are enabled while
// testing.
bool mServiceWorkersTestingEnabled;
+
+ // The VR HMD device index attached to this window, if any
+ uint32_t mVRHMDDeviceIndex = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindow, NS_PIDOMWINDOW_IID)
#ifdef MOZILLA_INTERNAL_API
PopupControlState
PushPopupControlState(PopupControlState aState, bool aForce);
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1175,18 +1175,22 @@ interface nsIDOMWindowUtils : nsISupport
*/
const unsigned long QUERY_CHARACTER_AT_POINT = 3208;
/**
* Called when the remote child frame has changed its fullscreen state,
* when entering fullscreen, and when the origin which is fullscreen changes.
* aFrameElement is the iframe element which contains the child-process
* fullscreen document.
+ *
+ * If specified and nonzero, the fullscreen takes place on the given HMD
+ * device index.
*/
- void remoteFrameFullscreenChanged(in nsIDOMElement aFrameElement);
+ void remoteFrameFullscreenChanged(in nsIDOMElement aFrameElement,
+ [optional] in long aVRHMDDeviceIndex);
/**
* Called when the remote frame has popped all fullscreen elements off its
* stack, so that the operation can complete on the parent side.
*/
void remoteFrameFullscreenReverted();
/**
@@ -1843,16 +1847,24 @@ interface nsIDOMWindowUtils : nsISupport
* document's counters. Normally, use counters are flushed to telemetry
* upon document destruction, but as document destruction is somewhat
* non-deterministic, we have this method here for more determinism when
* running tests.
*/
void forceUseCounterFlush(in nsIDOMNode aNode);
void setNextPaintSyncId(in long aSyncId);
+
+ /**
+ * The VR HMD device ID currently attached to this window.
+ * 0 if no VR HMD device is not attached.
+ *
+ * Will throw a DOM security error if called without chrome privileges.
+ */
+ readonly attribute unsigned long vrHMDDeviceID;
};
[scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)]
interface nsITranslationNodeList : nsISupports {
readonly attribute unsigned long length;
nsIDOMNode item(in unsigned long index);
// A translation root is a block element, or an inline element
--- a/gfx/thebes/gfxVsync.cpp
+++ b/gfx/thebes/gfxVsync.cpp
@@ -234,17 +234,16 @@ VsyncManager::Shutdown()
* SoftwareVsyncSource implementation
*/
SoftwareVsyncSource::SoftwareVsyncSource(const nsID& aSourceID, double aInterval)
: VsyncSource(aSourceID)
, mCurrentVsyncTask(nullptr)
, mVsyncEnabled(false)
{
- MOZ_ASSERT(NS_IsMainThread());
mVsyncInterval = mozilla::TimeDuration::FromMilliseconds(aInterval);
mVsyncThread = new base::Thread("SoftwareVsyncThread");
MOZ_RELEASE_ASSERT(mVsyncThread->Start(), "Could not start software vsync thread");
}
SoftwareVsyncSource::~SoftwareVsyncSource()
{
}
@@ -294,17 +293,16 @@ SoftwareVsyncSource::InternalDisableVsyn
mCurrentVsyncTask->Cancel();
mCurrentVsyncTask = nullptr;
}
}
bool
SoftwareVsyncSource::IsVsyncEnabled()
{
- MOZ_ASSERT(NS_IsMainThread());
return mVsyncEnabled;
}
bool
SoftwareVsyncSource::IsInSoftwareVsyncThread()
{
return mVsyncThread->thread_id() == PlatformThread::CurrentId();
}
--- a/gfx/vr/VRDeviceProxy.cpp
+++ b/gfx/vr/VRDeviceProxy.cpp
@@ -8,17 +8,16 @@
#include "prlink.h"
#include "prmem.h"
#include "prenv.h"
#include "gfxPrefs.h"
#include "nsString.h"
#include "mozilla/Preferences.h"
#include "mozilla/unused.h"
#include "nsServiceManagerUtils.h"
-#include "nsIScreenManager.h"
#ifdef XP_WIN
#include "../layers/d3d11/CompositorD3D11.h"
#endif
#include "VRDeviceProxy.h"
#include "VRManagerChild.h"
@@ -26,34 +25,16 @@
using namespace mozilla;
using namespace mozilla::gfx;
VRDeviceProxy::VRDeviceProxy(const VRDeviceUpdate& aDeviceUpdate)
: mDeviceInfo(aDeviceUpdate.mDeviceInfo)
, mSensorState(aDeviceUpdate.mSensorState)
{
MOZ_COUNT_CTOR(VRDeviceProxy);
-
- if (mDeviceInfo.mScreenRect.width && mDeviceInfo.mScreenRect.height) {
- if (mDeviceInfo.mIsFakeScreen) {
- mScreen = MakeFakeScreen(mDeviceInfo.mScreenRect);
- } else {
- nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
- if (screenmgr) {
- screenmgr->ScreenForRect(mDeviceInfo.mScreenRect.x, mDeviceInfo.mScreenRect.y,
- mDeviceInfo.mScreenRect.width, mDeviceInfo.mScreenRect.height,
- getter_AddRefs(mScreen));
- }
- }
-#ifdef DEBUG
- printf_stderr("VR DEVICE SCREEN: %d %d %d %d\n",
- mDeviceInfo.mScreenRect.x, mDeviceInfo.mScreenRect.y,
- mDeviceInfo.mScreenRect.width, mDeviceInfo.mScreenRect.height);
-#endif
- }
}
VRDeviceProxy::~VRDeviceProxy() {
MOZ_COUNT_DTOR(VRDeviceProxy);
}
void
VRDeviceProxy::UpdateDeviceInfo(const VRDeviceUpdate& aDeviceUpdate)
@@ -86,68 +67,8 @@ VRDeviceProxy::GetSensorState(double tim
return mSensorState;
}
void
VRDeviceProxy::UpdateSensorState(const VRHMDSensorState& aSensorState)
{
mSensorState = aSensorState;
}
-
-// 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)
-
-
-/* static */ already_AddRefed<nsIScreen>
-VRDeviceProxy::MakeFakeScreen(const IntRect& aScreenRect)
-{
- nsCOMPtr<nsIScreen> screen = new FakeScreen(aScreenRect);
- return screen.forget();
-}
-
--- a/gfx/vr/VRDeviceProxy.h
+++ b/gfx/vr/VRDeviceProxy.h
@@ -1,17 +1,16 @@
/* -*- 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_PROXY_H
#define GFX_VR_PROXY_H
-#include "nsIScreen.h"
#include "nsCOMPtr.h"
#include "mozilla/RefPtr.h"
#include "gfxVR.h"
namespace mozilla {
namespace gfx {
@@ -30,28 +29,19 @@ public:
const VRDeviceInfo& GetDeviceInfo() const { return mDeviceInfo; }
virtual VRHMDSensorState GetSensorState(double timeOffset = 0.0);
bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
double zNear, double zFar);
virtual void ZeroSensor();
-
- // The nsIScreen that represents this device
- nsIScreen* GetScreen() { return mScreen; }
-
protected:
virtual ~VRDeviceProxy();
VRDeviceInfo mDeviceInfo;
VRHMDSensorState mSensorState;
-
- nsCOMPtr<nsIScreen> mScreen;
-
- static already_AddRefed<nsIScreen> MakeFakeScreen(const IntRect& aScreenRect);
-
};
} // namespace gfx
} // namespace mozilla
#endif /* GFX_VR_PROXY_H */
--- a/gfx/vr/gfxVR.cpp
+++ b/gfx/vr/gfxVR.cpp
@@ -4,26 +4,28 @@
* 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 "nsIScreenManager.h"
#include "gfxPrefs.h"
#include "gfxVR.h"
#if defined(XP_WIN)
#include "gfxVROculus.h"
#endif
#if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_LINUX)
#include "gfxVROculus050.h"
#endif
#include "gfxVRCardboard.h"
+#include "gfxVsync.h"
#include "mozilla/unused.h"
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/TextureHost.h"
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
@@ -34,23 +36,54 @@ using namespace mozilla::gfx;
Atomic<uint32_t> VRHMDManager::sDeviceBase(0);
VRHMDInfo::VRHMDInfo(VRHMDType aType, bool aUseMainThreadOrientation)
{
MOZ_COUNT_CTOR(VRHMDInfo);
mDeviceInfo.mType = aType;
mDeviceInfo.mDeviceID = VRHMDManager::AllocateDeviceID();
mDeviceInfo.mUseMainThreadOrientation = aUseMainThreadOrientation;
+ mDeviceInfo.mVsyncSourceID = VsyncManager::kGlobalDisplaySourceID;
}
VRHMDInfo::~VRHMDInfo()
{
MOZ_COUNT_DTOR(VRHMDInfo);
}
+nsIScreen*
+VRHMDInfo::GetScreen()
+{
+ if (mDeviceInfo.mIsFakeScreen &&
+ mDeviceInfo.mScreenRect.width &&
+ mDeviceInfo.mScreenRect.height)
+ {
+ mScreen = MakeFakeScreen(mDeviceInfo.mScreenRect);
+ } else {
+ nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
+ if (screenmgr) {
+ screenmgr->ScreenForRect(mDeviceInfo.mScreenRect.x, mDeviceInfo.mScreenRect.y,
+ mDeviceInfo.mScreenRect.width, mDeviceInfo.mScreenRect.height,
+ getter_AddRefs(mScreen));
+ if (mScreen) {
+ mScreen->GetRect(&mDeviceInfo.mScreenRect.x, &mDeviceInfo.mScreenRect.y,
+ &mDeviceInfo.mScreenRect.width, &mDeviceInfo.mScreenRect.height);
+ }
+ }
+ }
+
+#ifdef DEBUG
+ printf_stderr("VR DEVICE SCREEN RECT: %d %d %d %d\n",
+ mDeviceInfo.mScreenRect.x, mDeviceInfo.mScreenRect.y,
+ mDeviceInfo.mScreenRect.width, mDeviceInfo.mScreenRect.height);
+#endif
+
+ return mScreen;
+}
+
/* static */ uint32_t
VRHMDManager::AllocateDeviceID()
{
return ++sDeviceBase;
}
VRHMDRenderingSupport::RenderTargetSet::RenderTargetSet()
: currentRenderTarget(0)
@@ -88,8 +121,68 @@ VRFieldOfView::ConstructProjectionMatrix
m[2*4+2] = zFar / (zNear - zFar) * -handednessScale;
m[3*4+2] = (zFar * zNear) / (zNear - zFar);
m[2*4+3] = handednessScale;
m[3*4+3] = 0.0f;
return mobj;
}
+
+// 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)
+
+
+/* static */ already_AddRefed<nsIScreen>
+VRHMDInfo::MakeFakeScreen(const IntRect& aScreenRect)
+{
+ nsCOMPtr<nsIScreen> screen = new FakeScreen(aScreenRect);
+ return screen.forget();
+}
+
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -2,18 +2,20 @@
* 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_H
#define GFX_VR_H
#include "nsTArray.h"
+#include "nsID.h"
#include "nsString.h"
#include "nsCOMPtr.h"
+#include "nsIScreen.h"
#include "mozilla/RefPtr.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/Atomics.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/TypedEnumBits.h"
@@ -99,16 +101,18 @@ struct VRDeviceInfo
const VRFieldOfView& GetMaximumEyeFOV(uint32_t whichEye) const { return mMaximumEyeFOV[whichEye]; }
const IntSize& SuggestedEyeResolution() const { return mEyeResolution; }
const Point3D& GetEyeTranslation(uint32_t whichEye) const { return mEyeTranslation[whichEye]; }
const Matrix4x4& GetEyeProjectionMatrix(uint32_t whichEye) const { return mEyeProjectionMatrix[whichEye]; }
const VRFieldOfView& GetEyeFOV(uint32_t whichEye) const { return mEyeFOV[whichEye]; }
bool GetUseMainThreadOrientation() const { return mUseMainThreadOrientation; }
+ const nsID& GetVsyncSourceID() const { return mVsyncSourceID; }
+
enum Eye {
Eye_Left,
Eye_Right,
NumEyes
};
uint32_t mDeviceID;
VRHMDType mType;
@@ -124,17 +128,17 @@ struct VRDeviceInfo
* XXX fix this for vertical displays
*/
IntSize mEyeResolution;
IntRect mScreenRect;
bool mIsFakeScreen;
bool mUseMainThreadOrientation;
-
+ nsID mVsyncSourceID;
bool operator==(const VRDeviceInfo& other) const {
return mType == other.mType &&
mDeviceID == other.mDeviceID &&
mDeviceName == other.mDeviceName &&
mSupportedSensorBits == other.mSupportedSensorBits &&
mEyeResolution == other.mEyeResolution &&
mScreenRect == other.mScreenRect &&
@@ -144,17 +148,18 @@ struct VRDeviceInfo
mMaximumEyeFOV[1] == other.mMaximumEyeFOV[1] &&
mRecommendedEyeFOV[0] == other.mRecommendedEyeFOV[0] &&
mRecommendedEyeFOV[1] == other.mRecommendedEyeFOV[1] &&
mEyeFOV[0] == other.mEyeFOV[0] &&
mEyeFOV[1] == other.mEyeFOV[1] &&
mEyeTranslation[0] == other.mEyeTranslation[0] &&
mEyeTranslation[1] == other.mEyeTranslation[1] &&
mEyeProjectionMatrix[0] == other.mEyeProjectionMatrix[0] &&
- mEyeProjectionMatrix[1] == other.mEyeProjectionMatrix[1];
+ mEyeProjectionMatrix[1] == other.mEyeProjectionMatrix[1] &&
+ mVsyncSourceID == other.mVsyncSourceID;
}
bool operator!=(const VRDeviceInfo& other) const {
return !(*this == other);
}
};
@@ -262,16 +267,20 @@ public:
double zNear, double zFar) = 0;
virtual bool KeepSensorTracking() = 0;
virtual void NotifyVsync(const TimeStamp& aVsyncTimestamp) = 0;
virtual VRHMDSensorState GetSensorState(double timeOffset = 0.0) = 0;
virtual void ZeroSensor() = 0;
+ // The nsIScreen for this device -- really just the boundaries, will
+ // likely be a fake screen.
+ nsIScreen* GetScreen();
+
// if rendering is offloaded
virtual VRHMDRenderingSupport *GetRenderingSupport() { return nullptr; }
// distortion mesh stuff; we should implement renderingsupport for this
virtual void FillDistortionConstants(uint32_t whichEye,
const IntSize& textureSize, // the full size of the texture
const IntRect& eyeViewport, // the viewport within the texture for the current eye
const Size& destViewport, // the size of the destination viewport
@@ -281,16 +290,19 @@ public:
const VRDistortionMesh& GetDistortionMesh(uint32_t whichEye) const { return mDistortionMesh[whichEye]; }
protected:
explicit VRHMDInfo(VRHMDType aType, bool aUseMainThreadOrientation);
virtual ~VRHMDInfo();
VRHMDConfiguration mConfiguration;
VRDeviceInfo mDeviceInfo;
VRDistortionMesh mDistortionMesh[VRDeviceInfo::NumEyes];
+ nsCOMPtr<nsIScreen> mScreen;
+
+ static already_AddRefed<nsIScreen> MakeFakeScreen(const IntRect& aScreenRect);
};
class VRHMDManager {
public:
static uint32_t AllocateDeviceID();
protected:
static Atomic<uint32_t> sDeviceBase;
--- a/gfx/vr/gfxVRCardboard.cpp
+++ b/gfx/vr/gfxVRCardboard.cpp
@@ -41,17 +41,17 @@ HMDInfoCardboard::HMDInfoCardboard()
mDeviceInfo.mMaximumEyeFOV[VRDeviceInfo::Eye_Right] = gfx::VRFieldOfView(45.0, 45.0, 45.0, 45.0);
SetFOV(mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Left], mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Right], 0.01, 10000.0);
mDeviceInfo.mScreenRect.x = 0;
mDeviceInfo.mScreenRect.y = 0;
mDeviceInfo.mScreenRect.width = 1920;
mDeviceInfo.mScreenRect.height = 1080;
- mDeviceInfo.mIsFakeScreen = true;
+ mDeviceInfo.mIsFakeScreen = false;
}
VRHMDSensorState
HMDInfoCardboard::GetSensorState(double timeOffset)
{
// Actual sensor state is calculated on the main thread,
// within VRDeviceProxyOrientationFallBack
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -3,22 +3,27 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <math.h>
#include "prlink.h"
#include "prmem.h"
#include "prenv.h"
+#include "gfxPlatform.h"
#include "gfxPrefs.h"
+#include "gfxUtils.h"
#include "nsString.h"
+#include "gfxVsync.h"
#include "mozilla/Preferences.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/gfx/Quaternion.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIScreenManager.h"
#ifdef XP_WIN
#include "../layers/d3d11/CompositorD3D11.h"
#endif
#include "gfxVROculus.h"
#ifndef M_PI
@@ -245,16 +250,18 @@ FromFovPort(const ovrFovPort& aFOV)
} // namespace
HMDInfoOculus::HMDInfoOculus(ovrSession aSession)
: VRHMDInfo(VRHMDType::Oculus, false)
, mSession(aSession)
, mPerfHudMode(0)
{
+ MOZ_ASSERT(XRE_IsParentProcess(),
+ "Can only create HMDInfoOculus in XRE parent process!");
MOZ_ASSERT(sizeof(HMDInfoOculus::DistortionVertex) == sizeof(VRDistortionVertex),
"HMDInfoOculus::DistortionVertex must match the size of VRDistortionVertex");
MOZ_COUNT_CTOR_INHERITED(HMDInfoOculus, VRHMDInfo);
mDeviceInfo.mDeviceName.AssignLiteral("Oculus VR HMD");
mDesc = ovr_GetHmdDesc(aSession);
@@ -268,30 +275,41 @@ HMDInfoOculus::HMDInfoOculus(ovrSession
}
mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Left] = FromFovPort(mDesc.DefaultEyeFov[ovrEye_Left]);
mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Right] = FromFovPort(mDesc.DefaultEyeFov[ovrEye_Right]);
mDeviceInfo.mMaximumEyeFOV[VRDeviceInfo::Eye_Left] = FromFovPort(mDesc.MaxEyeFov[ovrEye_Left]);
mDeviceInfo.mMaximumEyeFOV[VRDeviceInfo::Eye_Right] = FromFovPort(mDesc.MaxEyeFov[ovrEye_Right]);
+ // create a vsync source for this display and register it
+ mDeviceInfo.mVsyncSourceID = gfxUtils::GenerateUUID();
+ mVsyncSource = new SoftwareVsyncSource(mDeviceInfo.mVsyncSourceID, 1000.0 / mDesc.DisplayRefreshRate);
+ gfxPlatform::GetPlatform()->GetHardwareVsync()->RegisterSource(mVsyncSource);
+
uint32_t w = mDesc.Resolution.w;
uint32_t h = mDesc.Resolution.h;
mDeviceInfo.mScreenRect.x = 0;
mDeviceInfo.mScreenRect.y = 0;
mDeviceInfo.mScreenRect.width = std::max(w, h);
mDeviceInfo.mScreenRect.height = std::min(w, h);
mDeviceInfo.mIsFakeScreen = true;
SetFOV(mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Left], mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Right], 0.01, 10000.0);
}
void
HMDInfoOculus::Destroy()
{
+ if (mVsyncSource) {
+ gfxPlatform::GetPlatform()->GetHardwareVsync()->UnregisterSource(mDeviceInfo.mVsyncSourceID);
+ mVsyncSource->Shutdown();
+ mVsyncSource = nullptr;
+ }
+
if (mSession) {
ovr_Destroy(mSession);
mSession = nullptr;
}
}
bool
HMDInfoOculus::SetFOV(const gfx::VRFieldOfView& aFOVLeft, const gfx::VRFieldOfView& aFOVRight,
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -14,16 +14,18 @@
#include "gfxVR.h"
//#include <OVR_CAPI.h>
//#include <OVR_CAPI_D3D.h>
#include "ovr_capi_dynamic.h"
namespace mozilla {
namespace gfx {
+class VsyncSource;
+
namespace impl {
class HMDInfoOculus : public VRHMDInfo, public VRHMDRenderingSupport {
public:
explicit HMDInfoOculus(ovrSession aSession);
bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
double zNear, double zFar) override;
@@ -64,16 +66,18 @@ protected:
float genericAttribs[4];
};
ovrSession mSession;
ovrHmdDesc mDesc;
ovrFovPort mFOVPort[2];
ovrTrackingState mLastTrackingState;
int32_t mPerfHudMode;
+
+ RefPtr<VsyncSource> mVsyncSource;
};
} // namespace impl
class VRHMDManagerOculus : public VRHMDManager
{
public:
static already_AddRefed<VRHMDManagerOculus> Create();
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -6225,35 +6225,35 @@ nsDisplaySVGEffects::nsDisplaySVGEffects
#ifdef NS_BUILD_REFCNT_LOGGING
nsDisplaySVGEffects::~nsDisplaySVGEffects()
{
MOZ_COUNT_DTOR(nsDisplaySVGEffects);
}
#endif
nsDisplayVR::nsDisplayVR(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
- nsDisplayList* aList, mozilla::gfx::VRDeviceProxy* aHMD)
+ nsDisplayList* aList, uint32_t aVRDeviceID)
: nsDisplayOwnLayer(aBuilder, aFrame, aList)
- , mHMD(aHMD)
+ , mVRDeviceID(aVRDeviceID)
{
}
already_AddRefed<Layer>
nsDisplayVR::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters)
{
ContainerLayerParameters newContainerParameters = aContainerParameters;
uint32_t flags = FrameLayerBuilder::CONTAINER_NOT_CLIPPED_BY_ANCESTORS |
FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR;
RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
newContainerParameters, nullptr, flags);
- container->SetVRDeviceID(mHMD->GetDeviceInfo().GetDeviceID());
+ container->SetVRDeviceID(mVRDeviceID);
container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(),
/*the value is irrelevant*/nullptr);
return container.forget();
}
nsRegion nsDisplaySVGEffects::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap)
{
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -4328,26 +4328,26 @@ public:
/**
* A wrapper layer that wraps its children in a container, then renders
* everything with an appropriate VR effect based on the HMDInfo.
*/
class nsDisplayVR : public nsDisplayOwnLayer {
public:
nsDisplayVR(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
- nsDisplayList* aList, mozilla::gfx::VRDeviceProxy* aHMD);
+ nsDisplayList* aList, uint32_t aVRDeviceID);
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override
{
return mozilla::LAYER_ACTIVE;
}
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
protected:
- RefPtr<mozilla::gfx::VRDeviceProxy> mHMD;
+ uint32_t mVRDeviceID;
};
#endif /*NSDISPLAYLIST_H_*/
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2042,19 +2042,19 @@ nsIFrame::BuildDisplayListForStackingCon
IsScrollFrameActive(aBuilder,
nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
nsLayoutUtils::SCROLLABLE_SAME_DOC |
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN));
nsDisplayListBuilder::AutoBuildingDisplayList
buildingDisplayList(aBuilder, this, dirtyRect, true);
- mozilla::gfx::VRDeviceProxy* vrHMDInfo = nullptr;
+ uint32_t vrDeviceIndex = 0;
if ((GetStateBits() & NS_FRAME_HAS_VR_CONTENT)) {
- vrHMDInfo = static_cast<mozilla::gfx::VRDeviceProxy*>(mContent->GetProperty(nsGkAtoms::vr_state));
+ vrDeviceIndex = (uint32_t) reinterpret_cast<uintptr_t>(mContent->GetProperty(nsGkAtoms::vr_state));
}
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
nsDisplayListBuilder::AutoSaveRestorePerspectiveIndex perspectiveIndex(aBuilder, this);
if (isTransformed || useBlendMode || usingSVGEffects || useStickyPosition) {
// We don't need to pass ancestor clipping down to our children;
@@ -2275,19 +2275,19 @@ nsIFrame::BuildDisplayListForStackingCon
*/
if (useStickyPosition) {
resultList.AppendNewToTop(
new (aBuilder) nsDisplayStickyPosition(aBuilder, this, &resultList));
}
/* If we're doing VR rendering, then we need to wrap everything in a nsDisplayVR
*/
- if (vrHMDInfo && !resultList.IsEmpty()) {
+ if (vrDeviceIndex && !resultList.IsEmpty()) {
resultList.AppendNewToTop(
- new (aBuilder) nsDisplayVR(aBuilder, this, &resultList, vrHMDInfo));
+ new (aBuilder) nsDisplayVR(aBuilder, this, &resultList, vrDeviceIndex));
}
/* If adding both a nsDisplayBlendContainer and a nsDisplayMixBlendMode to the
* same list, the nsDisplayBlendContainer should be added first. This only
* happens when the element creating this stacking context has mix-blend-mode
* and also contains a child which has mix-blend-mode.
* The nsDisplayBlendContainer must be added to the list first, so it does not
* isolate the containing element blending as well.
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -72,17 +72,16 @@
#include "nsAccessibilityService.h"
#endif
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
PRLogModuleInfo *gVsyncLog = nullptr;
#define VSYNC_LOG(...) MOZ_LOG(gVsyncLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-#define PARENT_OR_CHILD (XRE_IsParentProcess() ? "Parent" : "Child")
#ifdef DEBUG
#include "nsIObserver.h"
static void debug_RegisterPrefCallbacks();
#endif
@@ -1420,17 +1419,17 @@ VsyncChildCreateCallback::CreateVsyncAct
RefPtr<layout::VsyncChild> child = sVsyncChildTable->GetWeak(aSourceID);
if (!child) {
// no, we need to construct it
layout::PVsyncChild* actor = aPBackgroundChild->SendPVsyncConstructor(aSourceID);
child = static_cast<layout::VsyncChild*>(actor);
// add it to the table
sVsyncChildTable->Put(aSourceID, child);
- VSYNC_LOG("[%s]: Vsync actor %p created for display ID %s\n", PARENT_OR_CHILD, child.get(), nsIDToCString(aSourceID).get());
+ VSYNC_LOG("[%s]: Vsync actor %p created for display ID %s\n", XRE_GetProcessTypeString(), child.get(), nsIDToCString(aSourceID).get());
}
gfx::VsyncSource* display = static_cast<gfx::VsyncSource*>(child.get());
aObserver->ObserveSource(display);
}
// impl for nsIWidget's generic version
@@ -1474,37 +1473,37 @@ nsBaseWidget::UpdateVsyncObserver()
{
// If we were already notified of shutdown, don't try to set up vsync
if (!mShutdownObserver) {
return;
}
if (!mIncomingVsyncObserver) {
mIncomingVsyncObserver = new VsyncForwardingObserver();
- VSYNC_LOG("[%s]: Widget %p creating incoming vsync observer %p\n", PARENT_OR_CHILD, this, mIncomingVsyncObserver.get());
+ VSYNC_LOG("[%s]: Widget %p creating incoming vsync observer %p\n", XRE_GetProcessTypeString(), this, mIncomingVsyncObserver.get());
#ifdef MOZ_NUWA_PROCESS
// After NUWA fork, make sure we set up the observer connection properly
NuwaAddConstructor((void (*)(void *))&ForceUpdateVSyncObserver, this);
#endif
}
if (GetTopLevelWidget() != this) {
// if we're not the root widget, then just observe the root widget which will
// forward to our own listeners.
mIncomingVsyncObserver->ObserveWidget(GetTopLevelWidget());
- VSYNC_LOG("[%s]: Widget %p observing root widget %p (vsync ID %s)\n", PARENT_OR_CHILD, this, GetTopLevelWidget(),
+ VSYNC_LOG("[%s]: Widget %p observing root widget %p (vsync ID %s)\n", XRE_GetProcessTypeString(), this, GetTopLevelWidget(),
nsIDToCString(mIncomingVsyncObserver->GetObservedSourceID()).get());
return;
}
mIncomingVsyncObserver->ObserveSourceID(mDesiredVsyncSourceID);
- VSYNC_LOG("[%s]: Widget %p observing vsync ID %s\n", PARENT_OR_CHILD, this, nsIDToCString(mDesiredVsyncSourceID).get());
+ VSYNC_LOG("[%s]: Widget %p observing vsync ID %s\n", XRE_GetProcessTypeString(), this, nsIDToCString(mDesiredVsyncSourceID).get());
}
void
nsBaseWidget::AddVsyncObserver(gfx::VsyncObserver *aObserver)
{
MOZ_ASSERT(mIncomingVsyncObserver);
mIncomingVsyncObserver->AddVsyncObserver(aObserver);
}
@@ -2353,16 +2352,45 @@ nsBaseWidget::UnregisterPluginWindowForR
return;
}
MOZ_ASSERT(sPluginWidgetList);
sPluginWidgetList->Remove(id);
#endif
}
void
+nsBaseWidget::SetAttachedHMD(mozilla::gfx::VRHMDInfo* aHMD)
+{
+ VSYNC_LOG("%p SetAttachedHMD %p\n", this, aHMD);
+
+ if (GetTopLevelWidget() != this) {
+ GetTopLevelWidget()->SetAttachedHMD(aHMD);
+ return;
+ }
+
+ mHMD = aHMD;
+
+ if (aHMD) {
+ mIncomingVsyncObserver->ObserveSourceID(aHMD->GetDeviceInfo().GetVsyncSourceID());
+ } else {
+ mIncomingVsyncObserver->ObserveSourceID(mDesiredVsyncSourceID);
+ }
+}
+
+mozilla::gfx::VRHMDInfo*
+nsBaseWidget::GetAttachedHMD()
+{
+ if (GetTopLevelWidget() != this) {
+ return GetTopLevelWidget()->GetAttachedHMD();
+ }
+
+ return mHMD;
+}
+
+void
nsBaseWidget::ParentChanged()
{
// Our hierarchy changed, so make sure we're still observing
// the right widget (if we have a parent) or source (if we don't).
if (mIncomingVsyncObserver) {
UpdateVsyncObserver();
}
}
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -353,16 +353,19 @@ public:
virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override;
virtual bool CaptureWidgetOnScreen(RefPtr<mozilla::gfx::DrawTarget> aDT) override {
return false;
}
virtual void StartAsyncScrollbarDrag(const AsyncDragMetrics& aDragMetrics) override;
+ void SetAttachedHMD(mozilla::gfx::VRHMDInfo* aHMD) override;
+ mozilla::gfx::VRHMDInfo* GetAttachedHMD() override;
+
/**
* Use this when GetLayerManager() returns a BasicLayerManager
* (nsBaseWidget::GetLayerManager() does). This sets up the widget's
* layer manager to temporarily render into aTarget.
*
* |aNaturalWidgetBounds| is the un-rotated bounds of |aWidget|.
* |aRotation| is the "virtual rotation" to apply when rendering to
* the target. When |aRotation| is ROTATION_0,
@@ -561,16 +564,19 @@ protected:
SizeConstraints mSizeConstraints;
bool mUpdateCursor;
bool mUseAttachedEvents;
bool mIMEHasFocus;
#ifdef XP_WIN
bool mAccessibilityInUseFlag;
#endif
+
+ RefPtr<mozilla::gfx::VRHMDInfo> mHMD;
+
static nsIRollupListener* gRollupListener;
// the last rolled up popup. Only set this when an nsAutoRollup is in scope,
// so it can be cleared automatically.
static nsIContent* mLastRollup;
struct InitialZoomConstraints {
InitialZoomConstraints(const uint32_t& aPresShellID,
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -55,18 +55,18 @@ class CompositorChild;
class LayerManager;
class LayerManagerComposite;
class PLayerTransactionChild;
struct ScrollableLayerGuid;
} // namespace layers
namespace gfx {
class DrawTarget;
class SourceSurface;
+class VsyncObserver;
class VRHMDInfo;
-class VsyncObserver;
} // namespace gfx
namespace widget {
class TextEventDispatcher;
} // namespace widget
} // namespace mozilla
/**
* Callback function that processes events.
@@ -1740,16 +1740,22 @@ class nsIWidget : public nsISupports {
* Implementation of SnapshotWidgetOnScreen. This is invoked by the
* compositor for SnapshotWidgetOnScreen(), and should not be called
* otherwise.
*/
virtual bool CaptureWidgetOnScreen(RefPtr<mozilla::gfx::DrawTarget> aDT) = 0;
virtual void StartAsyncScrollbarDrag(const AsyncDragMetrics& aDragMetrics) = 0;
+ /**
+ * If the widget is being displayed on a VR HMD, that HMD is accessible here.
+ */
+ virtual void SetAttachedHMD(mozilla::gfx::VRHMDInfo* aHMD) {}
+ virtual mozilla::gfx::VRHMDInfo* GetAttachedHMD() { return nullptr; }
+
private:
class LongTapInfo
{
public:
LongTapInfo(int32_t aPointerId, ScreenIntPoint& aPoint,
mozilla::TimeDuration aDuration,
nsIObserver* aObserver) :
mPointerId(aPointerId),