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
--- 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(¶ms, 0, sizeof(params));
params.Flags = ovrInit_RequestVersion;
params.RequestedMinorVersion = OVR_MINOR_VERSION;
params.LogCallback = nullptr;
params.ConnectionTimeoutMS = 0;
ovrResult orv = ovr_Initialize(¶ms);
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(¶ms, 0, sizeof(params));
params.Flags = ovrInit_RequestVersion;
params.RequestedMinorVersion = LIBOVR_MINOR_VERSION;
params.LogCallback = nullptr;
params.ConnectionTimeoutMS = 0;
bool ok = ovr_Initialize(¶ms);
if (ok) {