Bug 1251886 - Correct inputFrameID selection when using e10s draft
authorkearwood
Tue, 01 Mar 2016 18:00:07 -0800
changeset 336014 5a3a0eb8d65cd72498a3df4a043287e56eb713e7
parent 335982 eb25b90a05c194bfd4f498ff3ffee7440f85f1cd
child 515271 36a7dbb9f612f19cb902813ce5e32ab63c5505ab
push id11937
push userkgilbert@mozilla.com
push dateWed, 02 Mar 2016 02:00:21 +0000
bugs1251886
milestone47.0a1
Bug 1251886 - Correct inputFrameID selection when using e10s - ContainerLayerComposite::ContainerRenderVR failed to find a CanvasLayerComposite and get an inputFrameId as it was only looking at immediate children layers. - Initialize Oculus SDK structures with 0 to ensure code is less brittle when Oculus SDK is updated in the future. - Added assert and sanity check to ensure that valid inputFrameID's are used when indexing the Oculus pose buffers. MozReview-Commit-ID: 136lf8aMWms
gfx/layers/composite/ContainerLayerComposite.cpp
gfx/vr/gfxVROculus.cpp
gfx/vr/gfxVROculus050.cpp
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -134,18 +134,17 @@ struct PreparedLayer
   RenderTargetIntRect mClipRect;
 };
 
 
 template<class ContainerT> void
 ContainerRenderVR(ContainerT* aContainer,
                   LayerManagerComposite* aManager,
                   const gfx::IntRect& aClipRect,
-                  RefPtr<gfx::VRHMDInfo> aHMD,
-                  int32_t aInputFrameID)
+                  RefPtr<gfx::VRHMDInfo> aHMD)
 {
   int32_t inputFrameID = -1;
 
   RefPtr<CompositingRenderTarget> surface;
 
   Compositor* compositor = aManager->GetCompositor();
 
   RefPtr<CompositingRenderTarget> previousTarget = compositor->GetCurrentRenderTarget();
@@ -266,21 +265,39 @@ ContainerRenderVR(ContainerT* aContainer
       }
 
       // XXX these are both clip rects, which end up as scissor rects in the compositor.  So we just
       // pass the full target surface rect here.
       layerToRender->Prepare(RenderTargetIntRect(surfaceRect.x, surfaceRect.y,
                                                  surfaceRect.width, surfaceRect.height));
       layerToRender->RenderLayer(surfaceRect);
 
-      CompositableHost *ch = layerToRender->GetCompositableHost();
-      if (ch) {
-        int32_t compositableInputFrameID = ch->GetLastInputFrameID();
-        if (compositableInputFrameID != -1) {
-          inputFrameID = compositableInputFrameID;
+      // Search all children recursively until we find the canvas with
+      // an inputFrameID
+      std::stack<LayerComposite*> searchLayers;
+      searchLayers.push(layerToRender);
+      while (!searchLayers.empty() && inputFrameID == -1) {
+        LayerComposite* searchLayer = searchLayers.top();
+        searchLayers.pop();
+        if (searchLayer) {
+          searchLayers.push(searchLayer->GetFirstChildComposite());
+          Layer* sibling = searchLayer->GetLayer();
+          if (sibling) {
+            sibling = sibling->GetNextSibling();
+          }
+          if (sibling) {
+            searchLayers.push(sibling->AsLayerComposite());
+          }
+          CompositableHost *ch = searchLayer->GetCompositableHost();
+          if (ch) {
+            int32_t compositableInputFrameID = ch->GetLastInputFrameID();
+            if (compositableInputFrameID != -1) {
+              inputFrameID = compositableInputFrameID;
+            }
+          }
         }
       }
 
       if (restoreTransform) {
         layer->ReplaceEffectiveTransform(childTransform);
       }
     } else {
       // Gecko-rendered CSS VR -- not supported yet, so just don't render this layer!
@@ -709,17 +726,17 @@ template<class ContainerT> void
 ContainerRender(ContainerT* aContainer,
                  LayerManagerComposite* aManager,
                  const gfx::IntRect& aClipRect)
 {
   MOZ_ASSERT(aContainer->mPrepared);
 
   RefPtr<gfx::VRHMDInfo> hmdInfo = gfx::VRManager::Get()->GetDevice(aContainer->GetVRDeviceID());
   if (hmdInfo && hmdInfo->GetConfiguration().IsValid()) {
-    ContainerRenderVR(aContainer, aManager, aClipRect, hmdInfo, aContainer->GetInputFrameID());
+    ContainerRenderVR(aContainer, aManager, aClipRect, hmdInfo);
     aContainer->mPrepared = nullptr;
     return;
   }
 
   if (aContainer->UseIntermediateSurface()) {
     RefPtr<CompositingRenderTarget> surface;
 
     if (aContainer->mPrepared->mNeedsSurfaceCopy) {
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -521,25 +521,32 @@ HMDInfoOculus::DestroyRenderTargetSet(Re
 }
 
 void
 HMDInfoOculus::SubmitFrame(RenderTargetSet *aRTSet, int32_t aInputFrameID)
 {
   RenderTargetSetOculus *rts = static_cast<RenderTargetSetOculus*>(aRTSet);
   MOZ_ASSERT(rts->hmd != nullptr);
   MOZ_ASSERT(rts->textureSet != nullptr);
+  MOZ_ASSERT(aInputFrameID >= 0);
+  if (aInputFrameID < 0) {
+    // Sanity check to prevent invalid memory access on builds with assertions
+    // disabled.
+    aInputFrameID = 0;
+  }
 
   VRHMDSensorState sensorState = mLastSensorState[aInputFrameID % kMaxLatencyFrames];
   // It is possible to get a cache miss on mLastSensorState if latency is
   // longer than kMaxLatencyFrames.  An optimization would be to find a frame
   // that is closer than the one selected with the modulus.
   // If we hit this; however, latency is already so high that the site is
   // un-viewable and a more accurate pose prediction is not likely to
   // compensate.
   ovrLayerEyeFov layer;
+  memset(&layer, 0, sizeof(layer));
   layer.Header.Type = ovrLayerType_EyeFov;
   layer.Header.Flags = 0;
   layer.ColorTexture[0] = rts->textureSet;
   layer.ColorTexture[1] = nullptr;
   layer.Fov[0] = mFOVPort[0];
   layer.Fov[1] = mFOVPort[1];
   layer.Viewport[0].Pos.x = 0;
   layer.Viewport[0].Pos.y = 0;
@@ -602,16 +609,17 @@ bool
 VRHMDManagerOculus::Init()
 {
   if (!mOculusInitialized) {
     nsIThread* thread = nullptr;
     NS_GetCurrentThread(&thread);
     mOculusThread = already_AddRefed<nsIThread>(thread);
 
     ovrInitParams params;
+    memset(&params, 0, sizeof(params));
     params.Flags = ovrInit_RequestVersion;
     params.RequestedMinorVersion = OVR_MINOR_VERSION;
     params.LogCallback = nullptr;
     params.ConnectionTimeoutMS = 0;
 
     ovrResult orv = ovr_Initialize(&params);
 
     if (orv == ovrSuccess) {
--- a/gfx/vr/gfxVROculus050.cpp
+++ b/gfx/vr/gfxVROculus050.cpp
@@ -538,16 +538,17 @@ bool
 VRHMDManagerOculus050::Init()
 {
   if (!mOculusInitialized) {
     nsIThread* thread = nullptr;
     NS_GetCurrentThread(&thread);
     mOculusThread = already_AddRefed<nsIThread>(thread);
 
     ovrInitParams params;
+    memset(&params, 0, sizeof(params));
     params.Flags = ovrInit_RequestVersion;
     params.RequestedMinorVersion = LIBOVR_MINOR_VERSION;
     params.LogCallback = nullptr;
     params.ConnectionTimeoutMS = 0;
 
     bool ok = ovr_Initialize(&params);
 
     if (ok) {