Allow surfaceflinger to run vrflinger
* Allows surface flinger to switch in and out of vr mode
Bug: None
Test: Manually ran various vr test programs.
Change-Id: I15fbba0eb67cbcffeef41be31429550448a1db9c
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 0e05d54..aa8f189 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -49,14 +49,11 @@
LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-ifeq ($(TARGET_IN_VR_MODE),true)
- LOCAL_CFLAGS += -DIN_VR_MODE
-endif
-
ifeq ($(TARGET_USES_HWC2),true)
LOCAL_CFLAGS += -DUSE_HWC2
LOCAL_SRC_FILES += \
SurfaceFlinger.cpp \
+ VrStateCallbacks.cpp \
DisplayHardware/HWComposer.cpp
ifeq ($(TARGET_USES_HWC2ON1ADAPTER), true)
LOCAL_CFLAGS += -DBYPASS_IHWC
@@ -134,7 +131,13 @@
LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
-LOCAL_STATIC_LIBRARIES := libhwcomposer-command-buffer libtrace_proto libvkjson
+LOCAL_STATIC_LIBRARIES := \
+ libhwcomposer-command-buffer \
+ libtrace_proto \
+ libvkjson \
+ libvr_manager \
+ libvrflinger
+
LOCAL_SHARED_LIBRARIES := \
android.dvr.composer@1.0 \
android.hardware.graphics.allocator@2.0 \
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 6cb1af1..3e9ef24 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -124,13 +124,11 @@
endCommand();
}
-Composer::Composer() : mWriter(kWriterInitialSize)
+Composer::Composer(bool useVrComposer)
+ : mWriter(kWriterInitialSize),
+ mIsUsingVrComposer(useVrComposer)
{
-#if defined(IN_VR_MODE)
- mIsInVrMode = true;
-#endif
-
- if (mIsInVrMode) {
+ if (mIsUsingVrComposer) {
mComposer = IComposer::getService("vr_hwcomposer");
} else {
mComposer = IComposer::getService("hwcomposer");
@@ -622,8 +620,7 @@
Error Composer::setLayerInfo(Display display, Layer layer, uint32_t type,
uint32_t appId)
{
- if (mIsInVrMode)
- {
+ if (mIsUsingVrComposer) {
mWriter.selectDisplay(display);
mWriter.selectLayer(layer);
mWriter.setLayerInfo(type, appId);
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 1ede705..18af9dd 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -26,7 +26,6 @@
#include <android/hardware/graphics/composer/2.1/IComposer.h>
#include <utils/StrongPointer.h>
#include <IComposerCommandBuffer.h>
-#include <MessageQueue.h>
namespace android {
@@ -128,7 +127,7 @@
// Composer is a wrapper to IComposer, a proxy to server-side composer.
class Composer {
public:
- Composer();
+ Composer(bool useVrComposer);
std::vector<IComposer::Capability> getCapabilities();
std::string dumpDebugInfo();
@@ -136,6 +135,7 @@
void registerCallback(const sp<IComposerCallback>& callback);
uint32_t getMaxVirtualDisplayCount();
+ bool isUsingVrComposer() const { return mIsUsingVrComposer; }
Error createVirtualDisplay(uint32_t width, uint32_t height,
PixelFormat* format, Display* outDisplay);
Error destroyVirtualDisplay(Display display);
@@ -248,7 +248,9 @@
CommandWriter mWriter;
CommandReader mReader;
- bool mIsInVrMode = false;
+ // When true, the we attach to the vr_hwcomposer service instead of the
+ // hwcomposer. This allows us to redirect surfaces to 3d surfaces in vr.
+ const bool mIsUsingVrComposer;
};
} // namespace Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 99a6d71..a25e8a1 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -135,8 +135,8 @@
mSetLayerVisibleRegion(nullptr),
mSetLayerZOrder(nullptr),
#else
-Device::Device()
- : mComposer(std::make_unique<Hwc2::Composer>()),
+Device::Device(bool useVrComposer)
+ : mComposer(std::make_unique<Hwc2::Composer>(useVrComposer)),
#endif // BYPASS_IHWC
mCapabilities(),
mDisplays(),
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index d770f22..93eb999 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -67,7 +67,10 @@
#ifdef BYPASS_IHWC
explicit Device(hwc2_device_t* device);
#else
- Device();
+ // useVrComposer is passed to the composer HAL. When true, the composer HAL
+ // will use the vr composer service, otherwise it uses the real hardware
+ // composer.
+ Device(bool useVrComposer);
#endif
~Device();
@@ -106,6 +109,12 @@
bool hasCapability(HWC2::Capability capability) const;
+#ifdef BYPASS_IHWC
+ android::Hwc2::Composer* getComposer() { return nullptr; }
+#else
+ android::Hwc2::Composer* getComposer() { return mComposer.get(); }
+#endif
+
private:
// Initialization methods
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index e86a071..1c99036 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -49,6 +49,7 @@
#include "HWComposer.h"
#include "HWC2On1Adapter.h"
#include "HWC2.h"
+#include "ComposerHal.h"
#include "../Layer.h" // needed only for debugging
#include "../SurfaceFlinger.h"
@@ -59,7 +60,7 @@
// ---------------------------------------------------------------------------
-HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger)
+HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger, bool useVrComposer)
: mFlinger(flinger),
mAdapter(),
mHwcDevice(),
@@ -76,7 +77,7 @@
mVSyncCounts[i] = 0;
}
- loadHwcModule();
+ loadHwcModule(useVrComposer);
}
HWComposer::~HWComposer() {}
@@ -105,11 +106,13 @@
}
// Load and prepare the hardware composer module. Sets mHwc.
-void HWComposer::loadHwcModule()
+void HWComposer::loadHwcModule(bool useVrComposer)
{
ALOGV("loadHwcModule");
#ifdef BYPASS_IHWC
+ (void)useVrComposer; // Silence unused parameter warning.
+
hw_module_t const* module;
if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
@@ -142,7 +145,7 @@
static_cast<hwc2_device_t*>(mAdapter.get()));
}
#else
- mHwcDevice = std::make_unique<HWC2::Device>();
+ mHwcDevice = std::make_unique<HWC2::Device>(useVrComposer);
#endif
mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
@@ -867,6 +870,14 @@
}
*/
+bool HWComposer::isUsingVrComposer() const {
+#ifdef BYPASS_IHWC
+ return false;
+#else
+ return getComposer()->isUsingVrComposer();
+#endif
+}
+
void HWComposer::dump(String8& result) const {
// TODO: In order to provide a dump equivalent to HWC1, we need to shadow
// all the state going into the layers. This is probably better done in
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 37f12e4..7b61e0e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -77,7 +77,10 @@
virtual ~EventHandler() {}
};
- HWComposer(const sp<SurfaceFlinger>& flinger);
+ // useVrComposer is passed to the composer HAL. When true, the composer HAL
+ // will use the vr composer service, otherwise it uses the real hardware
+ // composer.
+ HWComposer(const sp<SurfaceFlinger>& flinger, bool useVrComposer);
~HWComposer();
@@ -165,13 +168,16 @@
status_t setActiveColorMode(int32_t displayId, android_color_mode_t mode);
+ bool isUsingVrComposer() const;
+
// for debugging ----------------------------------------------------------
void dump(String8& out) const;
+ android::Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
private:
static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
- void loadHwcModule();
+ void loadHwcModule(bool useVrComposer);
bool isValidDisplay(int32_t displayId) const;
static void validateChange(HWC2::Composition from, HWC2::Composition to);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 76c710a..12166a8 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -413,6 +413,10 @@
}
}
+ void clearHwcLayers() {
+ mHwcLayers.clear();
+ }
+
#endif
// -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index de7795b..6289bdb 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -36,6 +36,8 @@
#include <binder/MemoryHeapBase.h>
#include <binder/PermissionCache.h>
+#include <dvr/vr_flinger.h>
+
#include <ui/DisplayInfo.h>
#include <ui/DisplayStatInfo.h>
@@ -73,6 +75,7 @@
#include "LayerDim.h"
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
+#include "VrStateCallbacks.h"
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
@@ -155,7 +158,10 @@
mLayersRemoved(false),
mLayersAdded(false),
mRepaintEverything(0),
- mRenderEngine(NULL),
+ mHwc(nullptr),
+ mRealHwc(nullptr),
+ mVrHwc(nullptr),
+ mRenderEngine(nullptr),
mBootTime(systemTime()),
mBuiltinDisplays(),
mVisibleRegionsDirty(false),
@@ -180,7 +186,8 @@
mFrameBuckets(),
mTotalTime(0),
mLastSwapTime(0),
- mNumLayers(0)
+ mNumLayers(0),
+ mEnterVrMode(false)
{
ALOGI("SurfaceFlinger is starting");
@@ -227,6 +234,14 @@
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglTerminate(display);
+
+ if (mVrStateCallbacks.get()) {
+ sp<IVrManager> vrManagerService = interface_cast<IVrManager>(
+ defaultServiceManager()->checkService(String16("vrmanager")));
+ if (vrManagerService.get()) {
+ vrManagerService->unregisterListener(mVrStateCallbacks);
+ }
+ }
}
void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
@@ -361,6 +376,13 @@
const int LOGTAG_SF_STOP_BOOTANIM = 60110;
LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
+
+ sp<IVrManager> vrManagerService = interface_cast<IVrManager>(
+ defaultServiceManager()->checkService(String16("vrmanager")));
+ if (vrManagerService.get()) {
+ mVrStateCallbacks = new VrStateCallbacks(*this);
+ vrManagerService->registerListener(mVrStateCallbacks);
+ }
}
void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
@@ -556,7 +578,9 @@
// Drop the state lock while we initialize the hardware composer. We drop
// the lock because on creation, it will call back into SurfaceFlinger to
// initialize the primary display.
- mHwc = new HWComposer(this);
+ LOG_ALWAYS_FATAL_IF(mEnterVrMode, "Starting in vr mode is not currently supported.");
+ mRealHwc = new HWComposer(this, false);
+ mHwc = mRealHwc;
mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
Mutex::Autolock _l(mStateLock);
@@ -1104,7 +1128,13 @@
bool isSecure = true;
int32_t type = DisplayDevice::DISPLAY_PRIMARY;
- createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
+
+ // When we're using the vr composer, the assumption is that we've
+ // already created the IBinder object for the primary display.
+ if (!mHwc->isUsingVrComposer()) {
+ createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
+ }
+
wp<IBinder> token = mBuiltinDisplays[type];
sp<IGraphicBufferProducer> producer;
@@ -1139,10 +1169,79 @@
enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
}
+void SurfaceFlinger::clearHwcLayers(const LayerVector& layers) {
+ for (size_t i = 0; i < layers.size(); ++i) {
+ layers[i]->clearHwcLayers();
+ }
+}
+
+void SurfaceFlinger::resetHwc() {
+ disableHardwareVsync(true);
+ clearHwcLayers(mDrawingState.layersSortedByZ);
+ clearHwcLayers(mCurrentState.layersSortedByZ);
+ // Clear the drawing state so that the logic inside of
+ // handleTransactionLocked will fire. It will determine the delta between
+ // mCurrentState and mDrawingState and re-apply all changes when we make the
+ // transition.
+ mDrawingState.displays.clear();
+ mDisplays.clear();
+}
+
+void SurfaceFlinger::updateVrMode() {
+ {
+ Mutex::Autolock _l(mStateLock);
+ bool enteringVrMode = mEnterVrMode;
+ if (enteringVrMode == mHwc->isUsingVrComposer()) {
+ return;
+ }
+
+ if (enteringVrMode) {
+ // Start vrflinger thread, if it hasn't been started already.
+ if (!mVrFlinger) {
+ mVrFlinger = std::make_unique<dvr::VrFlinger>();
+ int err = mVrFlinger->Run(mHwc->getComposer());
+ if (err != NO_ERROR) {
+ ALOGE("Failed to run vrflinger: %s (%d)", strerror(-err), err);
+ mVrFlinger.reset();
+ mEnterVrMode = false;
+ return;
+ }
+ }
+
+ if (!mVrHwc) {
+ mVrHwc = new HWComposer(this, true);
+ ALOGV("Vr HWC created");
+ }
+
+ resetHwc();
+
+ mHwc = mVrHwc;
+ mVrFlinger->EnterVrMode();
+ } else {
+ mVrFlinger->ExitVrMode();
+
+ resetHwc();
+
+ mHwc = mRealHwc;
+ enableHardwareVsync();
+ }
+
+ mVisibleRegionsDirty = true;
+ invalidateHwcGeometry();
+ android_atomic_or(1, &mRepaintEverything);
+ setTransactionFlags(eDisplayTransactionNeeded);
+ }
+ if (mVrHwc) {
+ mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
+ }
+}
+
void SurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL();
switch (what) {
case MessageQueue::INVALIDATE: {
+ updateVrMode();
+
bool frameMissed = !mHadClientComposition &&
mPreviousPresentFence != Fence::NO_FENCE &&
mPreviousPresentFence->getSignalTime() == INT64_MAX;
@@ -1763,16 +1862,10 @@
"adding a supported display, but rendering "
"surface is provided (%p), ignoring it",
state.surface.get());
- if (state.type == DisplayDevice::DISPLAY_EXTERNAL) {
- hwcId = DisplayDevice::DISPLAY_EXTERNAL;
- dispSurface = new FramebufferSurface(*mHwc,
- DisplayDevice::DISPLAY_EXTERNAL,
- bqConsumer);
- producer = bqProducer;
- } else {
- ALOGE("Attempted to add non-external non-virtual"
- " display");
- }
+
+ hwcId = state.type;
+ dispSurface = new FramebufferSurface(*mHwc, hwcId, bqConsumer);
+ producer = bqProducer;
}
const wp<IBinder>& display(curr.keyAt(i));
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 55735b1..384e345 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_SURFACE_FLINGER_H
#define ANDROID_SURFACE_FLINGER_H
+#include <memory>
#include <stdint.h>
#include <sys/types.h>
@@ -81,6 +82,11 @@
class EventControlThread;
class VSyncSource;
class InjectVSyncSource;
+class VrStateCallbacks;
+
+namespace dvr {
+class VrFlinger;
+} // namespace dvr
// ---------------------------------------------------------------------------
@@ -156,6 +162,7 @@
friend class EventThread;
friend class Layer;
friend class MonitoredProducer;
+ friend class VrStateCallbacks;
// This value is specified in number of frames. Log frame stats at most
// every half hour.
@@ -460,6 +467,19 @@
bool isLayerTripleBufferingDisabled() const {
return this->mLayerTripleBufferingDisabled;
}
+
+#ifdef USE_HWC2
+ /* ------------------------------------------------------------------------
+ * VrFlinger
+ */
+ void clearHwcLayers(const LayerVector& layers);
+ void resetHwc();
+
+ // Check to see if we should change to or from vr mode, and if so, perform
+ // the handoff.
+ void updateVrMode();
+#endif
+
/* ------------------------------------------------------------------------
* Attributes
*/
@@ -481,8 +501,13 @@
// access must be protected by mInvalidateLock
volatile int32_t mRepaintEverything;
- // constant members (no synchronization needed for access)
+ // current, real and vr hardware composers.
HWComposer* mHwc;
+#ifdef USE_HWC2
+ HWComposer* mRealHwc;
+ HWComposer* mVrHwc;
+#endif
+ // constant members (no synchronization needed for access)
RenderEngine* mRenderEngine;
nsecs_t mBootTime;
bool mGpuToCpuSupported;
@@ -495,6 +520,10 @@
EGLDisplay mEGLDisplay;
sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
+#ifdef USE_HWC2
+ std::unique_ptr<dvr::VrFlinger> mVrFlinger;
+#endif
+
// Can only accessed from the main thread, these members
// don't need synchronization
State mDrawingState;
@@ -601,6 +630,12 @@
// Verify that transaction is being called by an approved process:
// either AID_GRAPHICS or AID_SYSTEM.
status_t CheckTransactCodeCredentials(uint32_t code);
+
+#ifdef USE_HWC2
+ sp<VrStateCallbacks> mVrStateCallbacks;
+
+ std::atomic<bool> mEnterVrMode;
+#endif
};
}; // namespace android
diff --git a/services/surfaceflinger/VrStateCallbacks.cpp b/services/surfaceflinger/VrStateCallbacks.cpp
new file mode 100644
index 0000000..a924def
--- /dev/null
+++ b/services/surfaceflinger/VrStateCallbacks.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VrStateCallbacks.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+
+VrStateCallbacks::VrStateCallbacks(SurfaceFlinger& flinger)
+ : mFlinger(flinger) {}
+
+void VrStateCallbacks::onVrStateChanged(bool enabled) {
+ mFlinger.mEnterVrMode = enabled;
+ mFlinger.signalTransaction();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/VrStateCallbacks.h b/services/surfaceflinger/VrStateCallbacks.h
new file mode 100644
index 0000000..4e655d3
--- /dev/null
+++ b/services/surfaceflinger/VrStateCallbacks.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VR_STATE_CALLBACKS_H
+#define ANDROID_VR_STATE_CALLBACKS_H
+
+#include <vr/vr_manager/vr_manager.h>
+
+namespace android {
+
+class SurfaceFlinger;
+
+class VrStateCallbacks : public BnVrStateCallbacks {
+public:
+ VrStateCallbacks(SurfaceFlinger& flinger);
+ void onVrStateChanged(bool enabled) override;
+
+private:
+ SurfaceFlinger& mFlinger;
+};
+
+} // namespace android
+
+#endif // ANDROID_VR_STATE_CALLBACKS_H