From 561e0ebe908734eaae72d5f02dd74bcd0c3f3ee9 Mon Sep 17 00:00:00 2001 From: Imanol Fernandez Date: Thu, 28 Feb 2019 16:10:23 +0100 Subject: [PATCH] Implement dynamic switch between flat and curved display --- .../mozilla/vrbrowser/VRBrowserActivity.java | 1 + .../ui/widgets/WidgetManagerDelegate.java | 1 + .../widgets/options/DisplayOptionsWidget.java | 5 +- app/src/main/cpp/BrowserWorld.cpp | 16 +++- app/src/main/cpp/DeviceDelegate.h | 2 + app/src/main/cpp/Widget.cpp | 87 +++++++++++++++---- app/src/main/cpp/Widget.h | 2 + .../oculusvr/cpp/DeviceDelegateOculusVR.cpp | 74 ++++++++++++++-- app/src/oculusvr/cpp/DeviceDelegateOculusVR.h | 2 + 9 files changed, 163 insertions(+), 27 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java index 2897a9a9e..121c14da8 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java @@ -989,6 +989,7 @@ public void resetUIYaw() { queueRunnable(this::resetUIYawNative); } + @Override public void setCylinderDensity(final float aDensity) { queueRunnable(() -> setCylinderDensityNative(aDensity)); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WidgetManagerDelegate.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WidgetManagerDelegate.java index 9b7f2b492..ee10943a2 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WidgetManagerDelegate.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WidgetManagerDelegate.java @@ -45,6 +45,7 @@ interface WorldClickListener { void showVRVideo(int aWindowHandle, @VideoProjectionMenuWidget.VideoProjectionFlags int aVideoProjection); void hideVRVideo(); void resetUIYaw(); + void setCylinderDensity(float aDensity); void addFocusChangeListener(@NonNull FocusChangeListener aListener); void removeFocusChangeListener(@NonNull FocusChangeListener aListener); void addPermissionListener(PermissionListener aListener); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/options/DisplayOptionsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/options/DisplayOptionsWidget.java index e1e7053a3..c1cbb20d5 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/options/DisplayOptionsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/options/DisplayOptionsWidget.java @@ -82,8 +82,9 @@ private void initialize(Context aContext) { mCurvedDisplaySwitch = findViewById(R.id.curved_display_switch); mCurvedDisplaySwitch.setChecked(SettingsStore.getInstance(getContext()).getCylinderDensity() > 0.0f); mCurvedDisplaySwitch.setOnCheckedChangeListener((compoundButton, enabled, apply) -> { - SettingsStore.getInstance(getContext()).setCylinderDensity(enabled ? SettingsStore.CYLINDER_DENSITY_ENABLED_DEFAULT : 0.0f); - showRestartDialog(); + float density = enabled ? SettingsStore.CYLINDER_DENSITY_ENABLED_DEFAULT : 0.0f; + SettingsStore.getInstance(getContext()).setCylinderDensity(density); + mWidgetManager.setCylinderDensity(density); }); int uaMode = SettingsStore.getInstance(getContext()).getUaMode(); diff --git a/app/src/main/cpp/BrowserWorld.cpp b/app/src/main/cpp/BrowserWorld.cpp index 9a17a72f6..9416feaf2 100644 --- a/app/src/main/cpp/BrowserWorld.cpp +++ b/app/src/main/cpp/BrowserWorld.cpp @@ -933,7 +933,21 @@ void BrowserWorld::SetCylinderDensity(const float aDensity) { m.cylinderDensity = aDensity; for (WidgetPtr& widget: m.widgets) { - widget->SetCylinderDensity(aDensity); + const bool useCylinder = m.cylinderDensity > 0 && widget->GetPlacement()->cylinder; + if (useCylinder && widget->GetCylinder()) { + widget->SetCylinderDensity(aDensity); + } else if (useCylinder && !widget->GetCylinder()) { + VRLayerCylinderPtr layer = m.device->CreateLayerCylinder(widget->GetLayer()); + CylinderPtr cylinder = Cylinder::Create(m.create, layer); + widget->SetCylinder(cylinder); + widget->SetCylinderDensity(aDensity); + } else if (widget->GetCylinder()) { + float w = 0, h = 0; + widget->GetWorldSize(w, h); + VRLayerQuadPtr layer = m.device->CreateLayerQuad(widget->GetLayer()); + QuadPtr quad = Quad::Create(m.create, w, h, layer); + widget->SetQuad(quad); + } } } diff --git a/app/src/main/cpp/DeviceDelegate.h b/app/src/main/cpp/DeviceDelegate.h index ff3a80a9b..ff99625e6 100644 --- a/app/src/main/cpp/DeviceDelegate.h +++ b/app/src/main/cpp/DeviceDelegate.h @@ -64,8 +64,10 @@ class DeviceDelegate { virtual void EndFrame(bool aDiscard = false) = 0; virtual VRLayerQuadPtr CreateLayerQuad(int32_t aWidth, int32_t aHeight, VRLayerSurface::SurfaceType aSurfaceType) { return nullptr; } + virtual VRLayerQuadPtr CreateLayerQuad(const VRLayerSurfacePtr& aMoveLayer) { return nullptr; } virtual VRLayerCylinderPtr CreateLayerCylinder(int32_t aWidth, int32_t aHeight, VRLayerSurface::SurfaceType aSurfaceType) { return nullptr; } + virtual VRLayerCylinderPtr CreateLayerCylinder(const VRLayerSurfacePtr& aMoveLayer) { return nullptr; } virtual VRLayerCubePtr CreateLayerCube(int32_t aWidth, int32_t aHeight, GLint aInternalFormat) { return nullptr; } virtual VRLayerEquirectPtr CreateLayerEquirect(const VRLayerPtr &aSource) { return nullptr; } virtual void DeleteLayer(const VRLayerPtr& aLayer) {}; diff --git a/app/src/main/cpp/Widget.cpp b/app/src/main/cpp/Widget.cpp index 6f1ceaea4..bdc4e4a37 100644 --- a/app/src/main/cpp/Widget.cpp +++ b/app/src/main/cpp/Widget.cpp @@ -62,23 +62,7 @@ struct Widget::State { quad = aQuad; cylinder = aCylinder; - VRLayerPtr layer = GetLayer(); - - if (layer) { - layer->SetSurfaceChangedDelegate([=](const VRLayer& aLayer, VRLayer::SurfaceChange aChange, const std::function& aCallback) { - const VRLayerQuad& layerQuad = static_cast(aLayer); - VRBrowser::DispatchCreateWidgetLayer((jint)aHandle, layerQuad.GetSurface(), layerQuad.GetWidth(), layerQuad.GetHeight(), aCallback); - }); - } else { - surface = vrb::TextureSurface::Create(render, name); - if (quad) { - quad->SetTexture(surface, aTextureWidth, aTextureHeight); - quad->SetMaterial(vrb::Color(0.4f, 0.4f, 0.4f), vrb::Color(1.0f, 1.0f, 1.0f), vrb::Color(0.0f, 0.0f, 0.0f), 0.0f); - } else if (cylinder) { - cylinder->SetTexture(surface, aTextureWidth, aTextureHeight); - cylinder->SetMaterial(vrb::Color(0.4f, 0.4f, 0.4f), vrb::Color(1.0f, 1.0f, 1.0f), vrb::Color(0.0f, 0.0f, 0.0f), 0.0f); - } - } + UpdateSurface(aTextureWidth, aTextureHeight); vrb::CreationContextPtr create = render->GetRenderThreadCreationContext(); transform = vrb::Transform::Create(create); @@ -90,7 +74,7 @@ struct Widget::State { transform->AddNode(cylinder->GetRoot()); } - if (layer) { + if (GetLayer()) { toggleState = true; root->ToggleAll(true); } else { @@ -98,6 +82,28 @@ struct Widget::State { } } + void UpdateSurface(const int32_t aTextureWidth, const int32_t aTextureHeight) { + VRLayerPtr layer = GetLayer(); + if (layer) { + layer->SetSurfaceChangedDelegate([=](const VRLayer& aLayer, VRLayer::SurfaceChange aChange, const std::function& aCallback) { + const VRLayerQuad& layerQuad = static_cast(aLayer); + VRBrowser::DispatchCreateWidgetLayer((jint)handle, layerQuad.GetSurface(), layerQuad.GetWidth(), layerQuad.GetHeight(), aCallback); + }); + } else { + if (!surface) { + vrb::RenderContextPtr render = context.lock(); + surface = vrb::TextureSurface::Create(render, name); + } + if (quad) { + quad->SetTexture(surface, aTextureWidth, aTextureHeight); + quad->SetMaterial(vrb::Color(0.4f, 0.4f, 0.4f), vrb::Color(1.0f, 1.0f, 1.0f), vrb::Color(0.0f, 0.0f, 0.0f), 0.0f); + } else if (cylinder) { + cylinder->SetTexture(surface, aTextureWidth, aTextureHeight); + cylinder->SetMaterial(vrb::Color(0.4f, 0.4f, 0.4f), vrb::Color(1.0f, 1.0f, 1.0f), vrb::Color(0.0f, 0.0f, 0.0f), 0.0f); + } + } + } + bool FirstDraw() { if (!placement) { return false; @@ -150,6 +156,13 @@ struct Widget::State { cylinder->SetTransform(translation.PostMultiply(scaleMatrix)); } } + + void RemoveResizer() { + if (resizer) { + resizer->GetRoot()->RemoveFromParents(); + resizer = nullptr; + } + } }; WidgetPtr @@ -326,6 +339,44 @@ Widget::GetCylinder() const { return m.cylinder; } +void +Widget::SetQuad(const QuadPtr& aQuad) const { + int32_t textureWidth, textureHeight; + GetSurfaceTextureSize(textureWidth, textureHeight); + if (m.cylinder) { + m.cylinder->GetRoot()->RemoveFromParents(); + m.cylinder = nullptr; + } + if (m.quad) { + m.quad->GetRoot()->RemoveFromParents(); + } + + m.quad = aQuad; + m.transform->AddNode(aQuad->GetRoot()); + + m.RemoveResizer(); + m.UpdateSurface(textureWidth, textureHeight); +} + +void +Widget::SetCylinder(const CylinderPtr& aCylinder) const { + int32_t textureWidth, textureHeight; + GetSurfaceTextureSize(textureWidth, textureHeight); + if (m.quad) { + m.quad->GetRoot()->RemoveFromParents(); + m.quad = nullptr; + } + if (m.cylinder) { + m.cylinder->GetRoot()->RemoveFromParents(); + } + + m.cylinder = aCylinder; + m.transform->AddNode(aCylinder->GetRoot()); + + m.RemoveResizer(); + m.UpdateSurface(textureWidth, textureHeight); +} + VRLayerSurfacePtr Widget::GetLayer() const { return m.GetLayer(); diff --git a/app/src/main/cpp/Widget.h b/app/src/main/cpp/Widget.h index a36158704..cd8bcafc5 100644 --- a/app/src/main/cpp/Widget.h +++ b/app/src/main/cpp/Widget.h @@ -58,6 +58,8 @@ class Widget { vrb::NodePtr GetRoot() const; QuadPtr GetQuad() const; CylinderPtr GetCylinder() const; + void SetQuad(const QuadPtr& aQuad) const; + void SetCylinder(const CylinderPtr& aCylinder) const; VRLayerSurfacePtr GetLayer() const; vrb::TransformPtr GetTransformNode() const; const WidgetPlacementPtr& GetPlacement() const; diff --git a/app/src/oculusvr/cpp/DeviceDelegateOculusVR.cpp b/app/src/oculusvr/cpp/DeviceDelegateOculusVR.cpp index 423c5df22..61e877d99 100644 --- a/app/src/oculusvr/cpp/DeviceDelegateOculusVR.cpp +++ b/app/src/oculusvr/cpp/DeviceDelegateOculusVR.cpp @@ -225,14 +225,13 @@ class OculusLayerSurface: public OculusLayerBase { OculusLayer::BindDelegate bindDelegate; void Init(JNIEnv * aEnv, vrb::RenderContextPtr& aContext) override { - if (this->swapChain) { - return; - } - this->jniEnv = aEnv; this->contextWeak = aContext; this->ovrLayer.Header.SrcBlend = VRAPI_FRAME_LAYER_BLEND_ONE; this->ovrLayer.Header.DstBlend = VRAPI_FRAME_LAYER_BLEND_ONE_MINUS_SRC_ALPHA; + if (this->swapChain) { + return; + } InitSwapChain(this->swapChain, this->surface, this->fbo); this->layer->SetResizeDelegate([=]{ @@ -285,6 +284,19 @@ class OculusLayerSurface: public OculusLayerBase { }); } +protected: + void TakeSurface(const OculusLayerPtr& aSource) { + this->swapChain = aSource->GetSwapChain(); + VRLayerSurfacePtr sourceLayer = std::dynamic_pointer_cast(aSource->GetLayer()); + if (sourceLayer) { + this->surface = sourceLayer->GetSurface(); + } + this->composited = aSource->IsComposited(); + this->layer->SetInitialized(aSource->GetLayer()->IsInitialized()); + this->layer->SetResizeDelegate([=]{ + Resize(); + }); + } private: void InitSwapChain(ovrTextureSwapChain*& swapChainOut, jobject & surfaceOut, vrb::FBOPtr& fboOut) { if (this->layer->GetSurfaceType() == VRLayerQuad::SurfaceType::AndroidSurface) { @@ -325,9 +337,12 @@ typedef std::shared_ptr OculusLayerQuadPtr; class OculusLayerQuad: public OculusLayerSurface { public: - static OculusLayerQuadPtr Create(const VRLayerQuadPtr& aLayer) { + static OculusLayerQuadPtr Create(const VRLayerQuadPtr& aLayer, const OculusLayerPtr& aSource = nullptr) { auto result = std::make_shared(); result->layer = aLayer; + if (aSource) { + result->TakeSurface(aSource); + } return result; } @@ -374,9 +389,12 @@ typedef std::shared_ptr OculusLayerCylinderPtr; class OculusLayerCylinder: public OculusLayerSurface { public: - static OculusLayerCylinderPtr Create(const VRLayerCylinderPtr& aLayer) { + static OculusLayerCylinderPtr Create(const VRLayerCylinderPtr& aLayer, const OculusLayerPtr& aSource = nullptr) { auto result = std::make_shared(); result->layer = aLayer; + if (aSource) { + result->TakeSurface(aSource); + } return result; } @@ -1227,6 +1245,28 @@ DeviceDelegateOculusVR::CreateLayerQuad(int32_t aWidth, int32_t aHeight, return layer; } +VRLayerQuadPtr +DeviceDelegateOculusVR::CreateLayerQuad(const VRLayerSurfacePtr& aMoveLayer) { + if (!m.layersEnabled) { + return nullptr; + } + + VRLayerQuadPtr layer = VRLayerQuad::Create(aMoveLayer->GetWidth(), aMoveLayer->GetHeight(), aMoveLayer->GetSurfaceType()); + OculusLayerQuadPtr oculusLayer; + + for (int i = 0; i < m.uiLayers.size(); ++i) { + if (m.uiLayers[i]->GetLayer() == aMoveLayer) { + oculusLayer = OculusLayerQuad::Create(layer, m.uiLayers[i]); + m.uiLayers.erase(m.uiLayers.begin() + i); + break; + } + } + if (oculusLayer) { + m.AddUILayer(oculusLayer, aMoveLayer->GetSurfaceType()); + } + return layer; +} + VRLayerCylinderPtr DeviceDelegateOculusVR::CreateLayerCylinder(int32_t aWidth, int32_t aHeight, VRLayerSurface::SurfaceType aSurfaceType) { @@ -1239,6 +1279,28 @@ DeviceDelegateOculusVR::CreateLayerCylinder(int32_t aWidth, int32_t aHeight, return layer; } +VRLayerCylinderPtr +DeviceDelegateOculusVR::CreateLayerCylinder(const VRLayerSurfacePtr& aMoveLayer) { + if (!m.layersEnabled) { + return nullptr; + } + + VRLayerCylinderPtr layer = VRLayerCylinder::Create(aMoveLayer->GetWidth(), aMoveLayer->GetHeight(), aMoveLayer->GetSurfaceType()); + OculusLayerCylinderPtr oculusLayer; + + for (int i = 0; i < m.uiLayers.size(); ++i) { + if (m.uiLayers[i]->GetLayer() == aMoveLayer) { + oculusLayer = OculusLayerCylinder::Create(layer, m.uiLayers[i]); + m.uiLayers.erase(m.uiLayers.begin() + i); + break; + } + } + if (oculusLayer) { + m.AddUILayer(oculusLayer, aMoveLayer->GetSurfaceType()); + } + return layer; +} + VRLayerCubePtr DeviceDelegateOculusVR::CreateLayerCube(int32_t aWidth, int32_t aHeight, GLint aInternalFormat) { diff --git a/app/src/oculusvr/cpp/DeviceDelegateOculusVR.h b/app/src/oculusvr/cpp/DeviceDelegateOculusVR.h index 0f38aa9ff..41cd2ea5d 100644 --- a/app/src/oculusvr/cpp/DeviceDelegateOculusVR.h +++ b/app/src/oculusvr/cpp/DeviceDelegateOculusVR.h @@ -43,8 +43,10 @@ class DeviceDelegateOculusVR : public DeviceDelegate { void EndFrame(const bool aDiscard) override; VRLayerQuadPtr CreateLayerQuad(int32_t aWidth, int32_t aHeight, VRLayerSurface::SurfaceType aSurfaceType) override; + VRLayerQuadPtr CreateLayerQuad(const VRLayerSurfacePtr& aMoveLayer) override; VRLayerCylinderPtr CreateLayerCylinder(int32_t aWidth, int32_t aHeight, VRLayerSurface::SurfaceType aSurfaceType) override; + VRLayerCylinderPtr CreateLayerCylinder(const VRLayerSurfacePtr& aMoveLayer) override; VRLayerCubePtr CreateLayerCube(int32_t aWidth, int32_t aHeight, GLint aInternalFormat) override; VRLayerEquirectPtr CreateLayerEquirect(const VRLayerPtr &aSource) override; void DeleteLayer(const VRLayerPtr& aLayer) override;