Allow VRWM to show 2D apps
2D apps appear as a single app layer at the front of the stack. We can
distinguish them from VR apps as VR has two layers at the front.
When we detect a 2D app we don't skip the first layers for rendering
Test: launch VR app, launch calculator
Bug: None
Change-Id: Iea8420870852b84ab790b5185ac1a44103c2aae5
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index 72a9c1a..8075bf9 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -194,16 +194,22 @@
}
// Determine if ths frame should be shown or hidden.
-bool CalculateVisibilityFromLayerConfig(const HwcCallback::Frame& frame,
- uint32_t vr_app) {
+ViewMode CalculateVisibilityFromLayerConfig(const HwcCallback::Frame& frame,
+ uint32_t vr_app) {
auto& layers = frame.layers();
// We assume the first two layers are the VR app.
if (layers.size() < kVRAppLayerCount)
- return false;
+ return ViewMode::Hidden;
- if (vr_app != layers[0].appid || layers[0].appid == 0)
- return false;
+ if (vr_app != layers[0].appid || layers[0].appid == 0 ||
+ layers[1].appid != layers[0].appid) {
+ if (layers[1].appid != layers[0].appid && layers[0].appid) {
+ // This might be a 2D app.
+ return ViewMode::App;
+ }
+ return ViewMode::Hidden;
+ }
// If a non-VR-app, non-skipped layer appears, show.
size_t index = kVRAppLayerCount;
@@ -219,11 +225,12 @@
// If any non-skipped layers exist now then we show, otherwise hide.
for (size_t i = index; i < layers.size(); i++) {
if (!layers[i].should_skip_layer())
- return true;
+ return ViewMode::VR;
}
- return false;
+ return ViewMode::Hidden;
}
+
} // namespace
ShellView::ShellView() {
@@ -308,7 +315,7 @@
if (!pending_frames_.empty()) {
// Check if we should advance the frame.
auto& frame = pending_frames_.front();
- if (!frame.visibility ||
+ if (frame.visibility == ViewMode::Hidden ||
frame.frame->Finish() == HwcCallback::FrameStatus::kFinished) {
current_frame_ = std::move(frame);
pending_frames_.pop_front();
@@ -316,17 +323,20 @@
}
}
- if (!debug_mode_ && current_frame_.visibility != is_visible_) {
- SetVisibility(current_frame_.visibility);
+ bool visible = current_frame_.visibility != ViewMode::Hidden;
+
+ if (!debug_mode_ && visible != is_visible_) {
+ SetVisibility(current_frame_.visibility != ViewMode::Hidden);
}
- if (!current_frame_.visibility)
+ if (!visible)
return;
ime_texture_ = TextureLayer();
surface_flinger_view_->GetTextures(*current_frame_.frame.get(), &textures_,
- &ime_texture_, debug_mode_);
+ &ime_texture_, debug_mode_,
+ view_mode_ == ViewMode::VR);
has_ime_ = ime_texture_.texture != nullptr;
}
@@ -373,14 +383,17 @@
if (!frame || frame->layers().empty())
return;
- bool visibility = debug_mode_ || CalculateVisibilityFromLayerConfig(
- *frame.get(), current_vr_app_);
+ ViewMode visibility =
+ CalculateVisibilityFromLayerConfig(*frame.get(), current_vr_app_);
+
+ if (visibility == ViewMode::Hidden && debug_mode_)
+ visibility = ViewMode::VR;
current_vr_app_ = frame->layers().front().appid;
// If we are not showing the frame there's no need to keep anything around.
- if (!visibility) {
+ if (visibility == ViewMode::Hidden) {
// Hidden, no change so drop it completely
- if (!current_frame_.visibility)
+ if (current_frame_.visibility == ViewMode::Hidden)
return;
frame.reset(nullptr);
@@ -395,7 +408,7 @@
// If we are showing ourselves the main thread is not processing anything,
// so give it a kick.
- if (visibility && !current_frame_.visibility) {
+ if (visibility != ViewMode::Hidden && current_frame_.visibility == ViewMode::Hidden) {
QueueTask(MainThreadTask::EnteringVrMode);
QueueTask(MainThreadTask::Show);
}
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index 589902e..e19a71d 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -14,6 +14,12 @@
namespace android {
namespace dvr {
+enum class ViewMode {
+ Hidden,
+ VR,
+ App,
+};
+
class ShellView : public Application, public HwcCallback::Client {
public:
ShellView();
@@ -64,6 +70,8 @@
std::unique_ptr<ShaderProgram> overlay_program_;
std::unique_ptr<ShaderProgram> controller_program_;
+ ViewMode view_mode_ = ViewMode::Hidden;
+
uint32_t current_vr_app_;
// Used to center the scene when the shell becomes visible.
@@ -92,7 +100,7 @@
struct PendingFrame {
PendingFrame() = default;
- PendingFrame(std::unique_ptr<HwcCallback::Frame>&& frame, bool visibility)
+ PendingFrame(std::unique_ptr<HwcCallback::Frame>&& frame, ViewMode visibility)
: frame(std::move(frame)), visibility(visibility) {}
PendingFrame(PendingFrame&& r)
: frame(std::move(r.frame)), visibility(r.visibility) {}
@@ -103,7 +111,7 @@
}
std::unique_ptr<HwcCallback::Frame> frame;
- bool visibility = false;
+ ViewMode visibility = ViewMode::Hidden;
};
std::deque<PendingFrame> pending_frames_;
std::mutex pending_frame_mutex_;
diff --git a/services/vr/vr_window_manager/surface_flinger_view.cpp b/services/vr/vr_window_manager/surface_flinger_view.cpp
index d38fcc0..6cc654a 100644
--- a/services/vr/vr_window_manager/surface_flinger_view.cpp
+++ b/services/vr/vr_window_manager/surface_flinger_view.cpp
@@ -38,13 +38,13 @@
bool SurfaceFlingerView::GetTextures(const HwcCallback::Frame& frame,
std::vector<TextureLayer>* texture_layers,
TextureLayer* ime_layer,
- bool debug) const {
+ bool debug, bool skip_first_layer) const {
auto& layers = frame.layers();
texture_layers->clear();
size_t start = 0;
// Skip the second layer if it is from the VR app.
- if (!debug) {
+ if (!debug && skip_first_layer) {
start = 1;
if (layers[0].appid && layers[0].appid == layers[1].appid)
start = 2;
diff --git a/services/vr/vr_window_manager/surface_flinger_view.h b/services/vr/vr_window_manager/surface_flinger_view.h
index e079cdb..c39ab41 100644
--- a/services/vr/vr_window_manager/surface_flinger_view.h
+++ b/services/vr/vr_window_manager/surface_flinger_view.h
@@ -33,7 +33,8 @@
bool GetTextures(const HwcCallback::Frame& layers,
std::vector<TextureLayer>* texture_layers,
- TextureLayer* ime_layer, bool debug) const;
+ TextureLayer* ime_layer, bool debug,
+ bool skip_first_layer) const;
private:
sp<IVrComposerView> composer_service_;