summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Steven Thomas <steventhomas@google.com> 2017-07-26 18:48:28 -0700
committer Steven Thomas <steventhomas@google.com> 2017-08-07 15:25:05 -0700
commit94e35b93537c7f9da018688ac8a8ba87f4689915 (patch)
treed8f228e6a3aa571814187030f9b9b7e97b8140b8
parent021a23991e6ddd5e6a625f283d992cd63aa7073a (diff)
Use a separate hwcomposer hidl instance for vr flinger
Improve robustness of vr flinger <--> surface flinger switching by having vr flinger use a separate hardware composer hidl instance instead of sharing the instance with surface flinger. Sharing the hardware composer instance has proven to be error prone, with situations where both the vr flinger thread and surface flinger main thread would write to the composer at the same time, causing hard to diagnose crashes (b/62925812). Instead of sharing the hardware composer instance, when switching to vr flinger we now delete the existing instance, create a new instance directed to the vr hardware composer shim, and vr flinger creates its own composer instance connected to the real hardware composer. By creating a separate composer instance for vr flinger, crashes like the ones found in b/62925812 are no longer impossible. Most of the changes in this commit are related to enabling surface flinger to delete HWComposer instances cleanly. In particular: - Previously the hardware composer callbacks (which come in on a hwbinder thread) would land in HWC2::Device and bubble up to the SurfaceFlinger object. But with the new behavior the HWC2::Device might be dead or in the process of being destroyed, so instead we have SurfaceFlinger receive the composer callbacks directly, and forward them to HWComposer and HWC2::Device. We include a composer id field in the callbacks so surface flinger can ignore stale callbacks from dead composer instances. - Object ownership for HWC2::Display and HWC2::Layer was shared by passing around shared_ptrs to these objects. This was problematic because they referenced and used the HWC2::Device, which can now be destroyed when switching to vr flinger. Simplify the ownership model by having HWC2::Device own (via unique_ptr<>) instances of HWC2::Display, which owns (again via unique_ptr<>) instances of HWC2::Layer. In cases where we previously passed std::shared_ptr<> to HWC2::Display or HWC2::Layer, instead pass non-owning HWC2::Display* and HWC2::Layer* pointers. This ensures clean composer instance teardown with no stale references to the deleted HWC2::Device. - When the hardware composer instance is destroyed and the HWC2::Layers are removed, notify the android::Layer via a callback, so it can remove the HWC2::Layer from its internal table of hardware composer layers. This removes the burden to explicitly clear out all hardware composer layers when switching to vr flinger, which has been a source of bugs. - We were missing an mStateLock lock in SurfaceFlinger::setVsyncEnabled(), which was necessary to ensure we were setting vsync on the correct hardware composer instance. Once that lock was added, surface flinger would sometimes deadlock when transitioning to vr flinger, because the surface flinger main thread would acquire mStateLock and then EventControlThread::mMutex, whereas the event control thread would acquire the locks in the opposite order. The changes in EventControlThread.cpp are to ensure it doesn't hold a lock on EventControlThread::mMutex while calling setVsyncEnabled(), to avoid the deadlock. I found that without a composer callback registered in vr flinger the vsync_event file wasn't getting vsync timestamps written, so vr flinger would get stuck in an infinite loop trying to parse a vsync timestamp. Since we need to have a callback anyway I changed the code in hardware_composer.cpp to get the vsync timestamp from the callback, as surface flinger does. I confirmed the timestamps are the same with either method, and this lets us remove some extra code for extracting the vsync timestamp that (probably) wasn't compatible with all devices we want to run on anyway. I also added a timeout to the vysnc wait so we'll see an error message in the log if we fail to wait for vsync, instead of looping forever. Bug: 62925812 Test: - Confirmed surface flinger <--> vr flinger switching is robust by switching devices on and off hundreds of times and observing no hardware composer related issues, surface flinger crashes, or hardware composer service crashes. - Confirmed 2d in vr works as before by going through the OOBE flow on a standalone. This also exercises virtual display creation and usage through surface flinger. - Added logs to confirm perfect layer/display cleanup when destroying hardware composer instances. - Tested normal 2d phone usage to confirm basic layer create/destroy functionality works as before. - Monitored surface flinger file descriptor usage across dozens of surface flinger <--> vr flinger transitions and observed no file descriptor leaks. - Confirmed the HWC1 code path still compiles. - Ran the surface flinger tests and confirmed there are no new test failures. - Ran the hardware composer hidl in passthrough mode on a Marlin and confirmed it works. - Ran CTS tests for virtual displays and confirmed they all pass. - Tested Android Auto and confirmed basic graphics functionality still works. Change-Id: I17dc0e060bfb5cb447ffbaa573b279fc6d2d8bd1
-rw-r--r--libs/vr/libvrflinger/display_service.cpp10
-rw-r--r--libs/vr/libvrflinger/display_service.h3
-rw-r--r--libs/vr/libvrflinger/hardware_composer.cpp352
-rw-r--r--libs/vr/libvrflinger/hardware_composer.h110
-rw-r--r--libs/vr/libvrflinger/include/dvr/vr_flinger.h3
-rw-r--r--libs/vr/libvrflinger/vr_flinger.cpp4
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp6
-rw-r--r--services/surfaceflinger/DisplayHardware/ComposerHal.cpp4
-rw-r--r--services/surfaceflinger/DisplayHardware/ComposerHal.h5
-rw-r--r--services/surfaceflinger/DisplayHardware/HWC2.cpp549
-rw-r--r--services/surfaceflinger/DisplayHardware/HWC2.h124
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp131
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h39
-rw-r--r--services/surfaceflinger/EventControlThread.cpp43
-rwxr-xr-xservices/surfaceflinger/Layer.cpp50
-rw-r--r--services/surfaceflinger/Layer.h34
-rw-r--r--services/surfaceflinger/RenderEngine/RenderEngine.cpp33
-rw-r--r--services/surfaceflinger/RenderEngine/RenderEngine.h2
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp294
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h60
-rw-r--r--services/surfaceflinger/SurfaceFlinger_hwc1.cpp4
21 files changed, 844 insertions, 1016 deletions
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 733edc659c..f350762e79 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -40,10 +40,8 @@ namespace dvr {
DisplayService::DisplayService(Hwc2::Composer* hidl,
RequestDisplayCallback request_display_callback)
: BASE("DisplayService",
- Endpoint::Create(display::DisplayProtocol::kClientPath)),
- hardware_composer_(hidl, request_display_callback),
- request_display_callback_(request_display_callback) {
- hardware_composer_.Initialize();
+ Endpoint::Create(display::DisplayProtocol::kClientPath)) {
+ hardware_composer_.Initialize(hidl, request_display_callback);
}
bool DisplayService::IsInitialized() const {
@@ -398,10 +396,6 @@ pdx::Status<void> DisplayService::DeleteGlobalBuffer(DvrGlobalBufferKey key) {
return {0};
}
-void DisplayService::OnHardwareComposerRefresh() {
- hardware_composer_.OnHardwareComposerRefresh();
-}
-
void DisplayService::SetDisplayConfigurationUpdateNotifier(
DisplayConfigurationUpdateNotifier update_notifier) {
update_notifier_ = update_notifier;
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index 6efe264b09..55e33ab852 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -72,8 +72,6 @@ class DisplayService : public pdx::ServiceBase<DisplayService> {
void GrantDisplayOwnership() { hardware_composer_.Enable(); }
void SeizeDisplayOwnership() { hardware_composer_.Disable(); }
- void OnHardwareComposerRefresh();
-
private:
friend BASE;
friend DisplaySurface;
@@ -119,7 +117,6 @@ class DisplayService : public pdx::ServiceBase<DisplayService> {
pdx::Status<void> HandleSurfaceMessage(pdx::Message& message);
HardwareComposer hardware_composer_;
- RequestDisplayCallback request_display_callback_;
EpollEventDispatcher dispatcher_;
DisplayConfigurationUpdateNotifier update_notifier_;
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 11c137063e..f9a5dcd987 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -28,6 +28,8 @@
#include <private/dvr/clock_ns.h>
#include <private/dvr/ion_buffer.h>
+using android::hardware::Return;
+using android::hardware::Void;
using android::pdx::LocalHandle;
using android::pdx::rpc::EmptyVariant;
using android::pdx::rpc::IfAnyOf;
@@ -42,9 +44,6 @@ namespace {
const char kBacklightBrightnessSysFile[] =
"/sys/class/leds/lcd-backlight/brightness";
-const char kPrimaryDisplayVSyncEventFile[] =
- "/sys/class/graphics/fb0/vsync_event";
-
const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp";
const char kDvrPerformanceProperty[] = "sys.dvr.performance";
@@ -86,22 +85,11 @@ bool SetThreadPolicy(const std::string& scheduler_class,
} // anonymous namespace
-// Layer static data.
-Hwc2::Composer* Layer::hwc2_hidl_;
-const HWCDisplayMetrics* Layer::display_metrics_;
-
// HardwareComposer static data;
constexpr size_t HardwareComposer::kMaxHardwareLayers;
HardwareComposer::HardwareComposer()
- : HardwareComposer(nullptr, RequestDisplayCallback()) {}
-
-HardwareComposer::HardwareComposer(
- Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback)
- : initialized_(false),
- hwc2_hidl_(hwc2_hidl),
- request_display_callback_(request_display_callback),
- callbacks_(new ComposerCallback) {}
+ : initialized_(false), request_display_callback_(nullptr) {}
HardwareComposer::~HardwareComposer(void) {
UpdatePostThreadState(PostThreadState::Quit, true);
@@ -109,16 +97,19 @@ HardwareComposer::~HardwareComposer(void) {
post_thread_.join();
}
-bool HardwareComposer::Initialize() {
+bool HardwareComposer::Initialize(
+ Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) {
if (initialized_) {
ALOGE("HardwareComposer::Initialize: already initialized.");
return false;
}
+ request_display_callback_ = request_display_callback;
+
HWC::Error error = HWC::Error::None;
Hwc2::Config config;
- error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+ error = hidl->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
if (error != HWC::Error::None) {
ALOGE("HardwareComposer: Failed to get current display config : %d",
@@ -126,8 +117,8 @@ bool HardwareComposer::Initialize() {
return false;
}
- error =
- GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
+ error = GetDisplayMetrics(hidl, HWC_DISPLAY_PRIMARY, config,
+ &native_display_metrics_);
if (error != HWC::Error::None) {
ALOGE(
@@ -149,9 +140,6 @@ bool HardwareComposer::Initialize() {
display_transform_ = HWC_TRANSFORM_NONE;
display_metrics_ = native_display_metrics_;
- // Pass hwc instance and metrics to setup globals for Layer.
- Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_);
-
post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
LOG_ALWAYS_FATAL_IF(
!post_thread_event_fd_,
@@ -210,15 +198,11 @@ void HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
}
void HardwareComposer::OnPostThreadResumed() {
- hwc2_hidl_->resetCommands();
+ hidl_.reset(new Hwc2::Composer("default"));
+ hidl_callback_ = new ComposerCallback;
+ hidl_->registerCallback(hidl_callback_);
- // HIDL HWC seems to have an internal race condition. If we submit a frame too
- // soon after turning on VSync we don't get any VSync signals. Give poor HWC
- // implementations a chance to enable VSync before we continue.
- EnableVsync(false);
- std::this_thread::sleep_for(100ms);
EnableVsync(true);
- std::this_thread::sleep_for(100ms);
// TODO(skiazyk): We need to do something about accessing this directly,
// supposedly there is a backlight service on the way.
@@ -240,9 +224,12 @@ void HardwareComposer::OnPostThreadPaused() {
}
active_layer_count_ = 0;
- EnableVsync(false);
+ if (hidl_) {
+ EnableVsync(false);
+ }
- hwc2_hidl_->resetCommands();
+ hidl_callback_ = nullptr;
+ hidl_.reset(nullptr);
// Trigger target-specific performance mode change.
property_set(kDvrPerformanceProperty, "idle");
@@ -252,21 +239,21 @@ HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
uint32_t num_types;
uint32_t num_requests;
HWC::Error error =
- hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
+ hidl_->validateDisplay(display, &num_types, &num_requests);
if (error == HWC2_ERROR_HAS_CHANGES) {
// TODO(skiazyk): We might need to inspect the requested changes first, but
// so far it seems like we shouldn't ever hit a bad state.
// error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
// display);
- error = hwc2_hidl_->acceptDisplayChanges(display);
+ error = hidl_->acceptDisplayChanges(display);
}
return error;
}
-int32_t HardwareComposer::EnableVsync(bool enabled) {
- return (int32_t)hwc2_hidl_->setVsyncEnabled(
+HWC::Error HardwareComposer::EnableVsync(bool enabled) {
+ return hidl_->setVsyncEnabled(
HWC_DISPLAY_PRIMARY,
(Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
: HWC2_VSYNC_DISABLE));
@@ -274,7 +261,7 @@ int32_t HardwareComposer::EnableVsync(bool enabled) {
HWC::Error HardwareComposer::Present(hwc2_display_t display) {
int32_t present_fence;
- HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence);
+ HWC::Error error = hidl_->presentDisplay(display, &present_fence);
// According to the documentation, this fence is signaled at the time of
// vsync/DMA for physical displays.
@@ -288,20 +275,21 @@ HWC::Error HardwareComposer::Present(hwc2_display_t display) {
return error;
}
-HWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
+HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* hidl,
+ hwc2_display_t display,
hwc2_config_t config,
hwc2_attribute_t attribute,
int32_t* out_value) const {
- return hwc2_hidl_->getDisplayAttribute(
+ return hidl->getDisplayAttribute(
display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
}
HWC::Error HardwareComposer::GetDisplayMetrics(
- hwc2_display_t display, hwc2_config_t config,
+ Hwc2::Composer* hidl, hwc2_display_t display, hwc2_config_t config,
HWCDisplayMetrics* out_metrics) const {
HWC::Error error;
- error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
+ error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_WIDTH,
&out_metrics->width);
if (error != HWC::Error::None) {
ALOGE(
@@ -310,7 +298,7 @@ HWC::Error HardwareComposer::GetDisplayMetrics(
return error;
}
- error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
+ error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_HEIGHT,
&out_metrics->height);
if (error != HWC::Error::None) {
ALOGE(
@@ -319,7 +307,8 @@ HWC::Error HardwareComposer::GetDisplayMetrics(
return error;
}
- error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
+ error = GetDisplayAttribute(hidl, display, config,
+ HWC2_ATTRIBUTE_VSYNC_PERIOD,
&out_metrics->vsync_period_ns);
if (error != HWC::Error::None) {
ALOGE(
@@ -328,7 +317,7 @@ HWC::Error HardwareComposer::GetDisplayMetrics(
return error;
}
- error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
+ error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_X,
&out_metrics->dpi.x);
if (error != HWC::Error::None) {
ALOGE(
@@ -337,7 +326,7 @@ HWC::Error HardwareComposer::GetDisplayMetrics(
return error;
}
- error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
+ error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_Y,
&out_metrics->dpi.y);
if (error != HWC::Error::None) {
ALOGE(
@@ -374,7 +363,7 @@ std::string HardwareComposer::Dump() {
if (post_thread_resumed_) {
stream << "Hardware Composer Debug Info:" << std::endl;
- stream << hwc2_hidl_->dumpDebugInfo();
+ stream << hidl_->dumpDebugInfo();
}
return stream.str();
@@ -446,8 +435,8 @@ void HardwareComposer::PostLayers() {
std::vector<Hwc2::Layer> out_layers;
std::vector<int> out_fences;
- error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
- &out_fences);
+ error = hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
+ &out_fences);
ALOGE_IF(error != HWC::Error::None,
"HardwareComposer::PostLayers: Failed to get release fences: %s",
error.to_string().c_str());
@@ -546,7 +535,7 @@ void HardwareComposer::UpdateConfigBuffer() {
}
int HardwareComposer::PostThreadPollInterruptible(
- const pdx::LocalHandle& event_fd, int requested_events) {
+ const pdx::LocalHandle& event_fd, int requested_events, int timeout_ms) {
pollfd pfd[2] = {
{
.fd = event_fd.Get(),
@@ -561,7 +550,7 @@ int HardwareComposer::PostThreadPollInterruptible(
};
int ret, error;
do {
- ret = poll(pfd, 2, -1);
+ ret = poll(pfd, 2, timeout_ms);
error = errno;
ALOGW_IF(ret < 0,
"HardwareComposer::PostThreadPollInterruptible: Error during "
@@ -571,6 +560,8 @@ int HardwareComposer::PostThreadPollInterruptible(
if (ret < 0) {
return -error;
+ } else if (ret == 0) {
+ return -ETIMEDOUT;
} else if (pfd[0].revents != 0) {
return 0;
} else if (pfd[1].revents != 0) {
@@ -623,114 +614,17 @@ int HardwareComposer::ReadWaitPPState() {
}
}
-// Reads the timestamp of the last vsync from the display driver.
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
-int HardwareComposer::ReadVSyncTimestamp(int64_t* timestamp) {
- const int event_fd = primary_display_vsync_event_fd_.Get();
- int ret, error;
-
- // The driver returns data in the form "VSYNC=<timestamp ns>".
- std::array<char, 32> data;
- data.fill('\0');
-
- // Seek back to the beginning of the event file.
- ret = lseek(event_fd, 0, SEEK_SET);
- if (ret < 0) {
- error = errno;
- ALOGE(
- "HardwareComposer::ReadVSyncTimestamp: Failed to seek vsync event fd: "
- "%s",
- strerror(error));
- return -error;
- }
-
- // Read the vsync event timestamp.
- ret = read(event_fd, data.data(), data.size());
- if (ret < 0) {
- error = errno;
- ALOGE_IF(
- error != EAGAIN,
- "HardwareComposer::ReadVSyncTimestamp: Error while reading timestamp: "
- "%s",
- strerror(error));
- return -error;
- }
-
- ret = sscanf(data.data(), "VSYNC=%" PRIu64,
- reinterpret_cast<uint64_t*>(timestamp));
- if (ret < 0) {
- error = errno;
- ALOGE(
- "HardwareComposer::ReadVSyncTimestamp: Error while parsing timestamp: "
- "%s",
- strerror(error));
- return -error;
- }
-
- return 0;
-}
-
-// Blocks until the next vsync event is signaled by the display driver.
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
-int HardwareComposer::BlockUntilVSync() {
- // Vsync is signaled by POLLPRI on the fb vsync node.
- return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI);
-}
-
// Waits for the next vsync and returns the timestamp of the vsync event. If
// vsync already passed since the last call, returns the latest vsync timestamp
-// instead of blocking. This method updates the last_vsync_timeout_ in the
-// process.
-//
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
+// instead of blocking.
int HardwareComposer::WaitForVSync(int64_t* timestamp) {
- int error;
-
- // Get the current timestamp and decide what to do.
- while (true) {
- int64_t current_vsync_timestamp;
- error = ReadVSyncTimestamp(&current_vsync_timestamp);
- if (error < 0 && error != -EAGAIN)
- return error;
-
- if (error == -EAGAIN) {
- // Vsync was turned off, wait for the next vsync event.
- error = BlockUntilVSync();
- if (error < 0 || error == kPostThreadInterrupted)
- return error;
-
- // Try again to get the timestamp for this new vsync interval.
- continue;
- }
-
- // Check that we advanced to a later vsync interval.
- if (TimestampGT(current_vsync_timestamp, last_vsync_timestamp_)) {
- *timestamp = last_vsync_timestamp_ = current_vsync_timestamp;
- return 0;
- }
-
- // See how close we are to the next expected vsync. If we're within 1ms,
- // sleep for 1ms and try again.
- const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
- const int64_t threshold_ns = 1000000; // 1ms
-
- const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame;
- const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs();
-
- if (distance_to_vsync_est > threshold_ns) {
- // Wait for vsync event notification.
- error = BlockUntilVSync();
- if (error < 0 || error == kPostThreadInterrupted)
- return error;
- } else {
- // Sleep for a short time (1 millisecond) before retrying.
- error = SleepUntil(GetSystemClockNs() + threshold_ns);
- if (error < 0 || error == kPostThreadInterrupted)
- return error;
- }
+ int error = PostThreadPollInterruptible(
+ hidl_callback_->GetVsyncEventFd(), POLLIN, /*timeout_ms*/ 1000);
+ if (error == kPostThreadInterrupted || error < 0) {
+ return error;
+ } else {
+ *timestamp = hidl_callback_->GetVsyncTime();
+ return 0;
}
}
@@ -749,7 +643,8 @@ int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
return -error;
}
- return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN);
+ return PostThreadPollInterruptible(
+ vsync_sleep_timer_fd_, POLLIN, /*timeout_ms*/ -1);
}
void HardwareComposer::PostThread() {
@@ -772,15 +667,6 @@ void HardwareComposer::PostThread() {
strerror(errno));
#endif // ENABLE_BACKLIGHT_BRIGHTNESS
- // Open the vsync event node for the primary display.
- // TODO(eieio): Move this into a platform-specific class.
- primary_display_vsync_event_fd_ =
- LocalHandle(kPrimaryDisplayVSyncEventFile, O_RDONLY);
- ALOGE_IF(!primary_display_vsync_event_fd_,
- "HardwareComposer: Failed to open vsync event node for primary "
- "display: %s",
- strerror(errno));
-
// Open the wait pingpong status node for the primary display.
// TODO(eieio): Move this into a platform-specific class.
primary_display_wait_pp_fd_ =
@@ -951,7 +837,8 @@ bool HardwareComposer::UpdateLayerConfig() {
// The bottom layer is opaque, other layers blend.
HWC::BlendMode blending =
layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
- layers_[layer_index].Setup(surfaces[layer_index], blending,
+ layers_[layer_index].Setup(surfaces[layer_index], native_display_metrics_,
+ hidl_.get(), blending,
display_transform_, HWC::Composition::Device,
layer_index);
display_surfaces_.push_back(surfaces[layer_index]);
@@ -979,50 +866,67 @@ void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
vsync_callback_ = callback;
}
-void HardwareComposer::HwcRefresh(hwc2_callback_data_t /*data*/,
- hwc2_display_t /*display*/) {
- // TODO(eieio): implement invalidate callbacks.
+void HardwareComposer::SetBacklightBrightness(int brightness) {
+ if (backlight_brightness_fd_) {
+ std::array<char, 32> text;
+ const int length = snprintf(text.data(), text.size(), "%d", brightness);
+ write(backlight_brightness_fd_.Get(), text.data(), length);
+ }
}
-void HardwareComposer::HwcVSync(hwc2_callback_data_t /*data*/,
- hwc2_display_t /*display*/,
- int64_t /*timestamp*/) {
- ATRACE_NAME(__PRETTY_FUNCTION__);
- // Intentionally empty. HWC may require a callback to be set to enable vsync
- // signals. We bypass this callback thread by monitoring the vsync event
- // directly, but signals still need to be enabled.
+HardwareComposer::ComposerCallback::ComposerCallback() {
+ vsync_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+ LOG_ALWAYS_FATAL_IF(
+ !vsync_event_fd_,
+ "Failed to create vsync event fd : %s",
+ strerror(errno));
}
-void HardwareComposer::HwcHotplug(hwc2_callback_data_t /*callbackData*/,
- hwc2_display_t /*display*/,
- hwc2_connection_t /*connected*/) {
- // TODO(eieio): implement display hotplug callbacks.
+Return<void> HardwareComposer::ComposerCallback::onHotplug(
+ Hwc2::Display /*display*/,
+ IComposerCallback::Connection /*conn*/) {
+ return Void();
}
-void HardwareComposer::OnHardwareComposerRefresh() {
- // TODO(steventhomas): Handle refresh.
+Return<void> HardwareComposer::ComposerCallback::onRefresh(
+ Hwc2::Display /*display*/) {
+ return hardware::Void();
}
-void HardwareComposer::SetBacklightBrightness(int brightness) {
- if (backlight_brightness_fd_) {
- std::array<char, 32> text;
- const int length = snprintf(text.data(), text.size(), "%d", brightness);
- write(backlight_brightness_fd_.Get(), text.data(), length);
+Return<void> HardwareComposer::ComposerCallback::onVsync(
+ Hwc2::Display display, int64_t timestamp) {
+ if (display == HWC_DISPLAY_PRIMARY) {
+ std::lock_guard<std::mutex> lock(vsync_mutex_);
+ vsync_time_ = timestamp;
+ int error = eventfd_write(vsync_event_fd_.Get(), 1);
+ LOG_ALWAYS_FATAL_IF(error != 0, "Failed writing to vsync event fd");
}
+ return Void();
+}
+
+const pdx::LocalHandle&
+HardwareComposer::ComposerCallback::GetVsyncEventFd() const {
+ return vsync_event_fd_;
}
-void Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl,
- const HWCDisplayMetrics* metrics) {
- hwc2_hidl_ = hwc2_hidl;
- display_metrics_ = metrics;
+int64_t HardwareComposer::ComposerCallback::GetVsyncTime() {
+ std::lock_guard<std::mutex> lock(vsync_mutex_);
+ eventfd_t event;
+ eventfd_read(vsync_event_fd_.Get(), &event);
+ LOG_ALWAYS_FATAL_IF(vsync_time_ < 0,
+ "Attempt to read vsync time before vsync event");
+ int64_t return_val = vsync_time_;
+ vsync_time_ = -1;
+ return return_val;
}
void Layer::Reset() {
- if (hwc2_hidl_ != nullptr && hardware_composer_layer_) {
- hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
+ if (hidl_ != nullptr && hardware_composer_layer_) {
+ hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
hardware_composer_layer_ = 0;
}
+ hidl_ = nullptr;
z_order_ = 0;
blending_ = HWC::BlendMode::None;
transform_ = HWC::Transform::None;
@@ -1034,29 +938,35 @@ void Layer::Reset() {
}
void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
- HWC::BlendMode blending, HWC::Transform transform,
- HWC::Composition composition_type, size_t z_order) {
+ const HWCDisplayMetrics& display_metrics,
+ Hwc2::Composer* hidl, HWC::BlendMode blending,
+ HWC::Transform transform, HWC::Composition composition_type,
+ size_t z_order) {
Reset();
+ hidl_ = hidl;
z_order_ = z_order;
blending_ = blending;
transform_ = transform;
composition_type_ = HWC::Composition::Invalid;
target_composition_type_ = composition_type;
source_ = SourceSurface{surface};
- CommonLayerSetup();
+ CommonLayerSetup(display_metrics);
}
void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
- HWC::BlendMode blending, HWC::Transform transform,
- HWC::Composition composition_type, size_t z_order) {
+ const HWCDisplayMetrics& display_metrics,
+ Hwc2::Composer* hidl, HWC::BlendMode blending,
+ HWC::Transform transform, HWC::Composition composition_type,
+ size_t z_order) {
Reset();
+ hidl_ = hidl;
z_order_ = z_order;
blending_ = blending;
transform_ = transform;
composition_type_ = HWC::Composition::Invalid;
target_composition_type_ = composition_type;
source_ = SourceBuffer{buffer};
- CommonLayerSetup();
+ CommonLayerSetup(display_metrics);
}
void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
@@ -1076,7 +986,7 @@ IonBuffer* Layer::GetBuffer() {
return source_.Visit(Visitor{});
}
-void Layer::UpdateLayerSettings() {
+void Layer::UpdateLayerSettings(const HWCDisplayMetrics& display_metrics) {
if (!IsLayerSetup()) {
ALOGE(
"HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
@@ -1087,7 +997,7 @@ void Layer::UpdateLayerSettings() {
HWC::Error error;
hwc2_display_t display = HWC_DISPLAY_PRIMARY;
- error = hwc2_hidl_->setLayerCompositionType(
+ error = hidl_->setLayerCompositionType(
display, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
ALOGE_IF(
@@ -1095,7 +1005,7 @@ void Layer::UpdateLayerSettings() {
"Layer::UpdateLayerSettings: Error setting layer composition type: %s",
error.to_string().c_str());
- error = hwc2_hidl_->setLayerBlendMode(
+ error = hidl_->setLayerBlendMode(
display, hardware_composer_layer_,
blending_.cast<Hwc2::IComposerClient::BlendMode>());
ALOGE_IF(error != HWC::Error::None,
@@ -1104,41 +1014,39 @@ void Layer::UpdateLayerSettings() {
// TODO(eieio): Use surface attributes or some other mechanism to control
// the layer display frame.
- error = hwc2_hidl_->setLayerDisplayFrame(
+ error = hidl_->setLayerDisplayFrame(
display, hardware_composer_layer_,
- {0, 0, display_metrics_->width, display_metrics_->height});
+ {0, 0, display_metrics.width, display_metrics.height});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer display frame: %s",
error.to_string().c_str());
- error = hwc2_hidl_->setLayerVisibleRegion(
+ error = hidl_->setLayerVisibleRegion(
display, hardware_composer_layer_,
- {{0, 0, display_metrics_->width, display_metrics_->height}});
+ {{0, 0, display_metrics.width, display_metrics.height}});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer visible region: %s",
error.to_string().c_str());
- error =
- hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
+ error = hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
error.to_string().c_str());
- error =
- hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
+ error = hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting z_ order: %s",
error.to_string().c_str());
}
-void Layer::CommonLayerSetup() {
+void Layer::CommonLayerSetup(const HWCDisplayMetrics& display_metrics) {
HWC::Error error =
- hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
+ hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
ALOGE_IF(
error != HWC::Error::None,
"Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
error.to_string().c_str());
- UpdateLayerSettings();
+ UpdateLayerSettings(display_metrics);
}
void Layer::Prepare() {
@@ -1157,12 +1065,12 @@ void Layer::Prepare() {
if (!handle.get()) {
if (composition_type_ == HWC::Composition::Invalid) {
composition_type_ = HWC::Composition::SolidColor;
- hwc2_hidl_->setLayerCompositionType(
+ hidl_->setLayerCompositionType(
HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
- hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
- layer_color);
+ hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ layer_color);
} else {
// The composition type is already set. Nothing else to do until a
// buffer arrives.
@@ -1170,15 +1078,15 @@ void Layer::Prepare() {
} else {
if (composition_type_ != target_composition_type_) {
composition_type_ = target_composition_type_;
- hwc2_hidl_->setLayerCompositionType(
+ hidl_->setLayerCompositionType(
HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
}
HWC::Error error{HWC::Error::None};
- error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
- hardware_composer_layer_, 0, handle,
- acquire_fence_.Get());
+ error = hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
+ hardware_composer_layer_, 0, handle,
+ acquire_fence_.Get());
ALOGE_IF(error != HWC::Error::None,
"Layer::Prepare: Error setting layer buffer: %s",
@@ -1187,9 +1095,9 @@ void Layer::Prepare() {
if (!surface_rect_functions_applied_) {
const float float_right = right;
const float float_bottom = bottom;
- error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
- hardware_composer_layer_,
- {0, 0, float_right, float_bottom});
+ error = hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
+ hardware_composer_layer_,
+ {0, 0, float_right, float_bottom});
ALOGE_IF(error != HWC::Error::None,
"Layer::Prepare: Error setting layer source crop: %s",
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index a0c50e14d8..fc0efeeeb4 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -54,11 +54,6 @@ class Layer {
public:
Layer() {}
- // Sets up the global state used by all Layer instances. This must be called
- // before using any Layer methods.
- static void InitializeGlobals(Hwc2::Composer* hwc2_hidl,
- const HWCDisplayMetrics* metrics);
-
// Releases any shared pointers and fence handles held by this instance.
void Reset();
@@ -72,6 +67,7 @@ class Layer {
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
// |index| is the index of this surface in the DirectDisplaySurface array.
void Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
+ const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl,
HWC::BlendMode blending, HWC::Transform transform,
HWC::Composition composition_type, size_t z_roder);
@@ -83,9 +79,10 @@ class Layer {
// |transform| receives HWC_TRANSFORM_* values.
// |composition_type| receives either HWC_FRAMEBUFFER for most layers or
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
- void Setup(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
- HWC::Transform transform, HWC::Composition composition_type,
- size_t z_order);
+ void Setup(const std::shared_ptr<IonBuffer>& buffer,
+ const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl,
+ HWC::BlendMode blending, HWC::Transform transform,
+ HWC::Composition composition_type, size_t z_order);
// Layers that use a direct IonBuffer should call this each frame to update
// which buffer will be used for the next PostLayers.
@@ -121,7 +118,7 @@ class Layer {
bool IsLayerSetup() const { return !source_.empty(); }
// Applies all of the settings to this layer using the hwc functions
- void UpdateLayerSettings();
+ void UpdateLayerSettings(const HWCDisplayMetrics& display_metrics);
int GetSurfaceId() const {
int surface_id = -1;
@@ -142,10 +139,9 @@ class Layer {
}
private:
- void CommonLayerSetup();
+ void CommonLayerSetup(const HWCDisplayMetrics& display_metrics);
- static Hwc2::Composer* hwc2_hidl_;
- static const HWCDisplayMetrics* display_metrics_;
+ Hwc2::Composer* hidl_ = nullptr;
// The hardware composer layer and metrics to use during the prepare cycle.
hwc2_layer_t hardware_composer_layer_ = 0;
@@ -263,11 +259,10 @@ class HardwareComposer {
static constexpr size_t kMaxHardwareLayers = 4;
HardwareComposer();
- HardwareComposer(Hwc2::Composer* hidl,
- RequestDisplayCallback request_display_callback);
~HardwareComposer();
- bool Initialize();
+ bool Initialize(Hwc2::Composer* hidl,
+ RequestDisplayCallback request_display_callback);
bool IsInitialized() const { return initialized_; }
@@ -281,11 +276,6 @@ class HardwareComposer {
// Get the HMD display metrics for the current display.
display::Metrics GetHmdDisplayMetrics() const;
- HWC::Error GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
- hwc2_attribute_t attributes,
- int32_t* out_value) const;
- HWC::Error GetDisplayMetrics(hwc2_display_t display, hwc2_config_t config,
- HWCDisplayMetrics* out_metrics) const;
std::string Dump();
void SetVSyncCallback(VSyncCallback callback);
@@ -308,34 +298,31 @@ class HardwareComposer {
int OnNewGlobalBuffer(DvrGlobalBufferKey key, IonBuffer& ion_buffer);
void OnDeletedGlobalBuffer(DvrGlobalBufferKey key);
- void OnHardwareComposerRefresh();
-
private:
- int32_t EnableVsync(bool enabled);
+ HWC::Error GetDisplayAttribute(Hwc2::Composer* hidl, hwc2_display_t display,
+ hwc2_config_t config,
+ hwc2_attribute_t attributes,
+ int32_t* out_value) const;
+ HWC::Error GetDisplayMetrics(Hwc2::Composer* hidl, hwc2_display_t display,
+ hwc2_config_t config,
+ HWCDisplayMetrics* out_metrics) const;
+
+ HWC::Error EnableVsync(bool enabled);
class ComposerCallback : public Hwc2::IComposerCallback {
public:
- ComposerCallback() {}
-
- hardware::Return<void> onHotplug(Hwc2::Display /*display*/,
- Connection /*connected*/) override {
- // TODO(skiazyk): depending on how the server is implemented, we might
- // have to set it up to synchronize with receiving this event, as it can
- // potentially be a critical event for setting up state within the
- // hwc2 module. That is, we (technically) should not call any other hwc
- // methods until this method has been called after registering the
- // callbacks.
- return hardware::Void();
- }
-
- hardware::Return<void> onRefresh(Hwc2::Display /*display*/) override {
- return hardware::Void();
- }
-
- hardware::Return<void> onVsync(Hwc2::Display /*display*/,
- int64_t /*timestamp*/) override {
- return hardware::Void();
- }
+ ComposerCallback();
+ hardware::Return<void> onHotplug(Hwc2::Display display,
+ Connection conn) override;
+ hardware::Return<void> onRefresh(Hwc2::Display display) override;
+ hardware::Return<void> onVsync(Hwc2::Display display,
+ int64_t timestamp) override;
+ const pdx::LocalHandle& GetVsyncEventFd() const;
+ int64_t GetVsyncTime();
+ private:
+ std::mutex vsync_mutex_;
+ pdx::LocalHandle vsync_event_fd_;
+ int64_t vsync_time_ = -1;
};
HWC::Error Validate(hwc2_display_t display);
@@ -364,17 +351,18 @@ class HardwareComposer {
void UpdatePostThreadState(uint32_t state, bool suspend);
// Blocks until either event_fd becomes readable, or we're interrupted by a
- // control thread. Any errors are returned as negative errno values. If we're
- // interrupted, kPostThreadInterrupted will be returned.
+ // control thread, or timeout_ms is reached before any events occur. Any
+ // errors are returned as negative errno values, with -ETIMEDOUT returned in
+ // the case of a timeout. If we're interrupted, kPostThreadInterrupted will be
+ // returned.
int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd,
- int requested_events);
+ int requested_events,
+ int timeout_ms);
- // BlockUntilVSync, WaitForVSync, and SleepUntil are all blocking calls made
- // on the post thread that can be interrupted by a control thread. If
- // interrupted, these calls return kPostThreadInterrupted.
+ // WaitForVSync and SleepUntil are blocking calls made on the post thread that
+ // can be interrupted by a control thread. If interrupted, these calls return
+ // kPostThreadInterrupted.
int ReadWaitPPState();
- int BlockUntilVSync();
- int ReadVSyncTimestamp(int64_t* timestamp);
int WaitForVSync(int64_t* timestamp);
int SleepUntil(int64_t wakeup_timestamp);
@@ -398,11 +386,9 @@ class HardwareComposer {
bool initialized_;
- // Hardware composer HAL device from SurfaceFlinger. VrFlinger does not own
- // this pointer.
- Hwc2::Composer* hwc2_hidl_;
+ std::unique_ptr<Hwc2::Composer> hidl_;
+ sp<ComposerCallback> hidl_callback_;
RequestDisplayCallback request_display_callback_;
- sp<ComposerCallback> callbacks_;
// Display metrics of the physical display.
HWCDisplayMetrics native_display_metrics_;
@@ -433,7 +419,8 @@ class HardwareComposer {
std::thread post_thread_;
// Post thread state machine and synchronization primitives.
- PostThreadStateType post_thread_state_{PostThreadState::Idle};
+ PostThreadStateType post_thread_state_{
+ PostThreadState::Idle | PostThreadState::Suspended};
std::atomic<bool> post_thread_quiescent_{true};
bool post_thread_resumed_{false};
pdx::LocalHandle post_thread_event_fd_;
@@ -444,9 +431,6 @@ class HardwareComposer {
// Backlight LED brightness sysfs node.
pdx::LocalHandle backlight_brightness_fd_;
- // Primary display vsync event sysfs node.
- pdx::LocalHandle primary_display_vsync_event_fd_;
-
// Primary display wait_pingpong state sysfs node.
pdx::LocalHandle primary_display_wait_pp_fd_;
@@ -478,12 +462,6 @@ class HardwareComposer {
static constexpr int kPostThreadInterrupted = 1;
- static void HwcRefresh(hwc2_callback_data_t data, hwc2_display_t display);
- static void HwcVSync(hwc2_callback_data_t data, hwc2_display_t display,
- int64_t timestamp);
- static void HwcHotplug(hwc2_callback_data_t callbackData,
- hwc2_display_t display, hwc2_connection_t connected);
-
HardwareComposer(const HardwareComposer&) = delete;
void operator=(const HardwareComposer&) = delete;
};
diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
index e7f41a7379..33cbc84d7d 100644
--- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h
+++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
@@ -29,9 +29,6 @@ class VrFlinger {
void GrantDisplayOwnership();
void SeizeDisplayOwnership();
- // Called on a binder thread.
- void OnHardwareComposerRefresh();
-
// dump all vr flinger state.
std::string Dump();
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index 56405deeaa..fcf94f0865 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -133,10 +133,6 @@ void VrFlinger::SeizeDisplayOwnership() {
display_service_->SeizeDisplayOwnership();
}
-void VrFlinger::OnHardwareComposerRefresh() {
- display_service_->OnHardwareComposerRefresh();
-}
-
std::string VrFlinger::Dump() {
// TODO(karthikrs): Add more state information here.
return display_service_->DumpState(0/*unused*/);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 744dd50df5..248ef53f55 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -134,9 +134,11 @@ DisplayDevice::DisplayDevice(
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (config == EGL_NO_CONFIG) {
#ifdef USE_HWC2
- config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888);
+ config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888,
+ /*logConfig*/ false);
#else
- config = RenderEngine::chooseEglConfig(display, format);
+ config = RenderEngine::chooseEglConfig(display, format,
+ /*logConfig*/ false);
#endif
}
eglSurface = eglCreateWindowSurface(display, config, window, NULL);
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 704b17ef43..433a224e25 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -215,6 +215,10 @@ void Composer::registerCallback(const sp<IComposerCallback>& callback)
}
}
+bool Composer::isRemote() {
+ return mClient->isRemote();
+}
+
void Composer::resetCommands() {
mWriter.reset();
}
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 40d2a4c3aa..31a3c1d785 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -143,6 +143,11 @@ public:
void registerCallback(const sp<IComposerCallback>& callback);
+ // Returns true if the connected composer service is running in a remote
+ // process, false otherwise. This will return false if the service is
+ // configured in passthrough mode, for example.
+ bool isRemote();
+
// Reset all pending commands in the command buffer. Useful if you want to
// skip a frame but have already queued some commands.
void resetCommands();
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index b749ce630d..78c0c8567a 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -33,45 +33,6 @@
#include <algorithm>
#include <inttypes.h>
-extern "C" {
- static void hotplug_hook(hwc2_callback_data_t callbackData,
- hwc2_display_t displayId, int32_t intConnected) {
- auto device = static_cast<HWC2::Device*>(callbackData);
- auto display = device->getDisplayById(displayId);
- if (display) {
- auto connected = static_cast<HWC2::Connection>(intConnected);
- device->callHotplug(std::move(display), connected);
- } else {
- ALOGE("Hotplug callback called with unknown display %" PRIu64,
- displayId);
- }
- }
-
- static void refresh_hook(hwc2_callback_data_t callbackData,
- hwc2_display_t displayId) {
- auto device = static_cast<HWC2::Device*>(callbackData);
- auto display = device->getDisplayById(displayId);
- if (display) {
- device->callRefresh(std::move(display));
- } else {
- ALOGE("Refresh callback called with unknown display %" PRIu64,
- displayId);
- }
- }
-
- static void vsync_hook(hwc2_callback_data_t callbackData,
- hwc2_display_t displayId, int64_t timestamp) {
- auto device = static_cast<HWC2::Device*>(callbackData);
- auto display = device->getDisplayById(displayId);
- if (display) {
- device->callVsync(std::move(display), timestamp);
- } else {
- ALOGE("Vsync callback called with unknown display %" PRIu64,
- displayId);
- }
- }
-}
-
using android::Fence;
using android::FloatRect;
using android::GraphicBuffer;
@@ -86,51 +47,78 @@ namespace HWC2 {
namespace Hwc2 = android::Hwc2;
+namespace {
+
+class ComposerCallbackBridge : public Hwc2::IComposerCallback {
+public:
+ ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId)
+ : mCallback(callback), mSequenceId(sequenceId),
+ mHasPrimaryDisplay(false) {}
+
+ Return<void> onHotplug(Hwc2::Display display,
+ IComposerCallback::Connection conn) override
+ {
+ HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
+ if (!mHasPrimaryDisplay) {
+ LOG_ALWAYS_FATAL_IF(connection != HWC2::Connection::Connected,
+ "Initial onHotplug callback should be "
+ "primary display connected");
+ mHasPrimaryDisplay = true;
+ mCallback->onHotplugReceived(mSequenceId, display,
+ connection, true);
+ } else {
+ mCallback->onHotplugReceived(mSequenceId, display,
+ connection, false);
+ }
+ return Void();
+ }
+
+ Return<void> onRefresh(Hwc2::Display display) override
+ {
+ mCallback->onRefreshReceived(mSequenceId, display);
+ return Void();
+ }
+
+ Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
+ {
+ mCallback->onVsyncReceived(mSequenceId, display, timestamp);
+ return Void();
+ }
+
+ bool HasPrimaryDisplay() { return mHasPrimaryDisplay; }
+
+private:
+ ComposerCallback* mCallback;
+ int32_t mSequenceId;
+ bool mHasPrimaryDisplay;
+};
+
+} // namespace anonymous
+
+
// Device methods
Device::Device(const std::string& serviceName)
: mComposer(std::make_unique<Hwc2::Composer>(serviceName)),
mCapabilities(),
mDisplays(),
- mHotplug(),
- mPendingHotplugs(),
- mRefresh(),
- mPendingRefreshes(),
- mVsync(),
- mPendingVsyncs()
+ mRegisteredCallback(false)
{
loadCapabilities();
- registerCallbacks();
}
-Device::~Device()
-{
- for (auto element : mDisplays) {
- auto display = element.second.lock();
- if (!display) {
- ALOGE("~Device: Found a display (%" PRId64 " that has already been"
- " destroyed", element.first);
- continue;
- }
-
- DisplayType displayType = HWC2::DisplayType::Invalid;
- auto error = display->getType(&displayType);
- if (error != Error::None) {
- ALOGE("~Device: Failed to determine type of display %" PRIu64
- ": %s (%d)", display->getId(), to_string(error).c_str(),
- static_cast<int32_t>(error));
- continue;
- }
-
- if (displayType == HWC2::DisplayType::Physical) {
- error = display->setVsyncEnabled(HWC2::Vsync::Disable);
- if (error != Error::None) {
- ALOGE("~Device: Failed to disable vsync for display %" PRIu64
- ": %s (%d)", display->getId(), to_string(error).c_str(),
- static_cast<int32_t>(error));
- }
- }
+void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) {
+ if (mRegisteredCallback) {
+ ALOGW("Callback already registered. Ignored extra registration "
+ "attempt.");
+ return;
}
+ mRegisteredCallback = true;
+ sp<ComposerCallbackBridge> callbackBridge(
+ new ComposerCallbackBridge(callback, sequenceId));
+ mComposer->registerCallback(callbackBridge);
+ LOG_ALWAYS_FATAL_IF(!callbackBridge->HasPrimaryDisplay(),
+ "Registered composer callback but didn't get primary display");
}
// Required by HWC2 device
@@ -146,7 +134,7 @@ uint32_t Device::getMaxVirtualDisplayCount() const
}
Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
- android_pixel_format_t* format, std::shared_ptr<Display>* outDisplay)
+ android_pixel_format_t* format, Display** outDisplay)
{
ALOGI("Creating virtual display");
@@ -159,104 +147,66 @@ Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
return error;
}
- ALOGI("Created virtual display");
+ auto display = std::make_unique<Display>(
+ *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual);
+ *outDisplay = display.get();
*format = static_cast<android_pixel_format_t>(intFormat);
- *outDisplay = getDisplayById(displayId);
- if (!*outDisplay) {
- ALOGE("Failed to get display by id");
- return Error::BadDisplay;
- }
- (*outDisplay)->setConnected(true);
+ mDisplays.emplace(displayId, std::move(display));
+ ALOGI("Created virtual display");
return Error::None;
}
-void Device::registerHotplugCallback(HotplugCallback hotplug)
+void Device::destroyDisplay(hwc2_display_t displayId)
{
- ALOGV("registerHotplugCallback");
- mHotplug = hotplug;
- for (auto& pending : mPendingHotplugs) {
- auto& display = pending.first;
- auto connected = pending.second;
- ALOGV("Sending pending hotplug(%" PRIu64 ", %s)", display->getId(),
- to_string(connected).c_str());
- mHotplug(std::move(display), connected);
- }
+ ALOGI("Destroying display %" PRIu64, displayId);
+ mDisplays.erase(displayId);
}
-void Device::registerRefreshCallback(RefreshCallback refresh)
-{
- mRefresh = refresh;
- for (auto& pending : mPendingRefreshes) {
- mRefresh(std::move(pending));
- }
-}
-
-void Device::registerVsyncCallback(VsyncCallback vsync)
-{
- mVsync = vsync;
- for (auto& pending : mPendingVsyncs) {
- auto& display = pending.first;
- auto timestamp = pending.second;
- mVsync(std::move(display), timestamp);
- }
-}
-
-// For use by Device callbacks
+void Device::onHotplug(hwc2_display_t displayId, Connection connection) {
+ if (connection == Connection::Connected) {
+ auto display = getDisplayById(displayId);
+ if (display) {
+ if (display->isConnected()) {
+ ALOGW("Attempt to hotplug connect display %" PRIu64
+ " , which is already connected.", displayId);
+ } else {
+ display->setConnected(true);
+ }
+ } else {
+ DisplayType displayType;
+ auto intError = mComposer->getDisplayType(displayId,
+ reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(
+ &displayType));
+ auto error = static_cast<Error>(intError);
+ if (error != Error::None) {
+ ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). "
+ "Aborting hotplug attempt.",
+ displayId, to_string(error).c_str(), intError);
+ return;
+ }
-void Device::callHotplug(std::shared_ptr<Display> display, Connection connected)
-{
- if (connected == Connection::Connected) {
- if (!display->isConnected()) {
- mComposer->setClientTargetSlotCount(display->getId());
- display->loadConfigs();
- display->setConnected(true);
+ auto newDisplay = std::make_unique<Display>(
+ *mComposer.get(), mCapabilities, displayId, displayType);
+ mDisplays.emplace(displayId, std::move(newDisplay));
+ }
+ } else if (connection == Connection::Disconnected) {
+ // The display will later be destroyed by a call to
+ // destroyDisplay(). For now we just mark it disconnected.
+ auto display = getDisplayById(displayId);
+ if (display) {
+ display->setConnected(false);
+ } else {
+ ALOGW("Attempted to disconnect unknown display %" PRIu64,
+ displayId);
}
- } else {
- display->setConnected(false);
- mDisplays.erase(display->getId());
- }
-
- if (mHotplug) {
- mHotplug(std::move(display), connected);
- } else {
- ALOGV("callHotplug called, but no valid callback registered, storing");
- mPendingHotplugs.emplace_back(std::move(display), connected);
- }
-}
-
-void Device::callRefresh(std::shared_ptr<Display> display)
-{
- if (mRefresh) {
- mRefresh(std::move(display));
- } else {
- ALOGV("callRefresh called, but no valid callback registered, storing");
- mPendingRefreshes.emplace_back(std::move(display));
- }
-}
-
-void Device::callVsync(std::shared_ptr<Display> display, nsecs_t timestamp)
-{
- if (mVsync) {
- mVsync(std::move(display), timestamp);
- } else {
- ALOGV("callVsync called, but no valid callback registered, storing");
- mPendingVsyncs.emplace_back(std::move(display), timestamp);
}
}
// Other Device methods
-std::shared_ptr<Display> Device::getDisplayById(hwc2_display_t id) {
- if (mDisplays.count(id) != 0) {
- auto strongDisplay = mDisplays[id].lock();
- ALOGE_IF(!strongDisplay, "Display %" PRId64 " is in mDisplays but is no"
- " longer alive", id);
- return strongDisplay;
- }
-
- auto display = std::make_shared<Display>(*this, id);
- mDisplays.emplace(id, display);
- return display;
+Display* Device::getDisplayById(hwc2_display_t id) {
+ auto iter = mDisplays.find(id);
+ return iter == mDisplays.end() ? nullptr : iter->second.get();
}
// Device initialization methods
@@ -271,84 +221,37 @@ void Device::loadCapabilities()
}
}
-bool Device::hasCapability(HWC2::Capability capability) const
-{
- return std::find(mCapabilities.cbegin(), mCapabilities.cend(),
- capability) != mCapabilities.cend();
-}
-
-namespace {
-class ComposerCallback : public Hwc2::IComposerCallback {
-public:
- ComposerCallback(Device* device) : mDevice(device) {}
-
- Return<void> onHotplug(Hwc2::Display display,
- Connection connected) override
- {
- hotplug_hook(mDevice, display, static_cast<int32_t>(connected));
- return Void();
- }
-
- Return<void> onRefresh(Hwc2::Display display) override
- {
- refresh_hook(mDevice, display);
- return Void();
- }
-
- Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
- {
- vsync_hook(mDevice, display, timestamp);
- return Void();
- }
-
-private:
- Device* mDevice;
-};
-} // namespace anonymous
-
-void Device::registerCallbacks()
-{
- sp<ComposerCallback> callback = new ComposerCallback(this);
- mComposer->registerCallback(callback);
-}
-
-
-// For use by Display
-
-void Device::destroyVirtualDisplay(hwc2_display_t display)
-{
- ALOGI("Destroying virtual display");
- auto intError = mComposer->destroyVirtualDisplay(display);
- auto error = static_cast<Error>(intError);
- ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
- " %s (%d)", display, to_string(error).c_str(), intError);
- mDisplays.erase(display);
-}
-
// Display methods
-Display::Display(Device& device, hwc2_display_t id)
- : mDevice(device),
+Display::Display(android::Hwc2::Composer& composer,
+ const std::unordered_set<Capability>& capabilities,
+ hwc2_display_t id, DisplayType type)
+ : mComposer(composer),
+ mCapabilities(capabilities),
mId(id),
mIsConnected(false),
- mType(DisplayType::Invalid)
+ mType(type)
{
ALOGV("Created display %" PRIu64, id);
-
- auto intError = mDevice.mComposer->getDisplayType(mId,
- reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
- id, to_string(error).c_str(), intError);
- }
+ setConnected(true);
}
-Display::~Display()
-{
- ALOGV("Destroyed display %" PRIu64, mId);
+Display::~Display() {
+ mLayers.clear();
+
if (mType == DisplayType::Virtual) {
- mDevice.destroyVirtualDisplay(mId);
+ ALOGV("Destroying virtual display");
+ auto intError = mComposer.destroyVirtualDisplay(mId);
+ auto error = static_cast<Error>(intError);
+ ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64
+ ") failed: %s (%d)", mId, to_string(error).c_str(), intError);
+ } else if (mType == DisplayType::Physical) {
+ auto error = setVsyncEnabled(HWC2::Vsync::Disable);
+ if (error != Error::None) {
+ ALOGE("~Display: Failed to disable vsync for display %" PRIu64
+ ": %s (%d)", mId, to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ }
}
}
@@ -383,22 +286,35 @@ float Display::Config::Builder::getDefaultDensity() {
Error Display::acceptChanges()
{
- auto intError = mDevice.mComposer->acceptDisplayChanges(mId);
+ auto intError = mComposer.acceptDisplayChanges(mId);
return static_cast<Error>(intError);
}
-Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
+Error Display::createLayer(Layer** outLayer)
{
+ if (!outLayer) {
+ return Error::BadParameter;
+ }
hwc2_layer_t layerId = 0;
- auto intError = mDevice.mComposer->createLayer(mId, &layerId);
+ auto intError = mComposer.createLayer(mId, &layerId);
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
}
- auto layer = std::make_shared<Layer>(shared_from_this(), layerId);
- mLayers.emplace(layerId, layer);
- *outLayer = std::move(layer);
+ auto layer = std::make_unique<Layer>(
+ mComposer, mCapabilities, mId, layerId);
+ *outLayer = layer.get();
+ mLayers.emplace(layerId, std::move(layer));
+ return Error::None;
+}
+
+Error Display::destroyLayer(Layer* layer)
+{
+ if (!layer) {
+ return Error::BadParameter;
+ }
+ mLayers.erase(layer->getId());
return Error::None;
}
@@ -407,7 +323,7 @@ Error Display::getActiveConfig(
{
ALOGV("[%" PRIu64 "] getActiveConfig", mId);
hwc2_config_t configId = 0;
- auto intError = mDevice.mComposer->getActiveConfig(mId, &configId);
+ auto intError = mComposer.getActiveConfig(mId, &configId);
auto error = static_cast<Error>(intError);
if (error != Error::None) {
@@ -430,12 +346,12 @@ Error Display::getActiveConfig(
}
Error Display::getChangedCompositionTypes(
- std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
+ std::unordered_map<Layer*, Composition>* outTypes)
{
std::vector<Hwc2::Layer> layerIds;
std::vector<Hwc2::IComposerClient::Composition> types;
- auto intError = mDevice.mComposer->getChangedCompositionTypes(mId,
- &layerIds, &types);
+ auto intError = mComposer.getChangedCompositionTypes(
+ mId, &layerIds, &types);
uint32_t numElements = layerIds.size();
auto error = static_cast<Error>(intError);
error = static_cast<Error>(intError);
@@ -464,7 +380,7 @@ Error Display::getChangedCompositionTypes(
Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
{
std::vector<Hwc2::ColorMode> modes;
- auto intError = mDevice.mComposer->getColorModes(mId, &modes);
+ auto intError = mComposer.getColorModes(mId, &modes);
uint32_t numModes = modes.size();
auto error = static_cast<Error>(intError);
if (error != Error::None) {
@@ -489,19 +405,18 @@ std::vector<std::shared_ptr<const Display::Config>> Display::getConfigs() const
Error Display::getName(std::string* outName) const
{
- auto intError = mDevice.mComposer->getDisplayName(mId, outName);
+ auto intError = mComposer.getDisplayName(mId, outName);
return static_cast<Error>(intError);
}
Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
- std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
- outLayerRequests)
+ std::unordered_map<Layer*, LayerRequest>* outLayerRequests)
{
uint32_t intDisplayRequests;
std::vector<Hwc2::Layer> layerIds;
std::vector<uint32_t> layerRequests;
- auto intError = mDevice.mComposer->getDisplayRequests(mId,
- &intDisplayRequests, &layerIds, &layerRequests);
+ auto intError = mComposer.getDisplayRequests(
+ mId, &intDisplayRequests, &layerIds, &layerRequests);
uint32_t numElements = layerIds.size();
auto error = static_cast<Error>(intError);
if (error != Error::None) {
@@ -535,7 +450,7 @@ Error Display::getType(DisplayType* outType) const
Error Display::supportsDoze(bool* outSupport) const
{
bool intSupport = false;
- auto intError = mDevice.mComposer->getDozeSupport(mId, &intSupport);
+ auto intError = mComposer.getDozeSupport(mId, &intSupport);
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -552,7 +467,7 @@ Error Display::getHdrCapabilities(
float maxAverageLuminance = -1.0f;
float minLuminance = -1.0f;
std::vector<Hwc2::Hdr> intTypes;
- auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes,
+ auto intError = mComposer.getHdrCapabilities(mId, &intTypes,
&maxLuminance, &maxAverageLuminance, &minLuminance);
auto error = static_cast<HWC2::Error>(intError);
@@ -571,25 +486,24 @@ Error Display::getHdrCapabilities(
}
Error Display::getReleaseFences(
- std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
+ std::unordered_map<Layer*, sp<Fence>>* outFences) const
{
std::vector<Hwc2::Layer> layerIds;
std::vector<int> fenceFds;
- auto intError = mDevice.mComposer->getReleaseFences(mId,
- &layerIds, &fenceFds);
+ auto intError = mComposer.getReleaseFences(mId, &layerIds, &fenceFds);
auto error = static_cast<Error>(intError);
uint32_t numElements = layerIds.size();
if (error != Error::None) {
return error;
}
- std::unordered_map<std::shared_ptr<Layer>, sp<Fence>> releaseFences;
+ std::unordered_map<Layer*, sp<Fence>> releaseFences;
releaseFences.reserve(numElements);
for (uint32_t element = 0; element < numElements; ++element) {
auto layer = getLayerById(layerIds[element]);
if (layer) {
sp<Fence> fence(new Fence(fenceFds[element]));
- releaseFences.emplace(std::move(layer), fence);
+ releaseFences.emplace(layer, fence);
} else {
ALOGE("getReleaseFences: invalid layer %" PRIu64
" found on display %" PRIu64, layerIds[element], mId);
@@ -607,7 +521,7 @@ Error Display::getReleaseFences(
Error Display::present(sp<Fence>* outPresentFence)
{
int32_t presentFenceFd = -1;
- auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd);
+ auto intError = mComposer.presentDisplay(mId, &presentFenceFd);
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -625,7 +539,7 @@ Error Display::setActiveConfig(const std::shared_ptr<const Config>& config)
config->getDisplayId(), mId);
return Error::BadConfig;
}
- auto intError = mDevice.mComposer->setActiveConfig(mId, config->getId());
+ auto intError = mComposer.setActiveConfig(mId, config->getId());
return static_cast<Error>(intError);
}
@@ -634,7 +548,7 @@ Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target,
{
// TODO: Properly encode client target surface damage
int32_t fenceFd = acquireFence->dup();
- auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
+ auto intError = mComposer.setClientTarget(mId, slot, target,
fenceFd, static_cast<Hwc2::Dataspace>(dataspace),
std::vector<Hwc2::IComposerClient::Rect>());
return static_cast<Error>(intError);
@@ -642,15 +556,15 @@ Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target,
Error Display::setColorMode(android_color_mode_t mode)
{
- auto intError = mDevice.mComposer->setColorMode(mId,
- static_cast<Hwc2::ColorMode>(mode));
+ auto intError = mComposer.setColorMode(
+ mId, static_cast<Hwc2::ColorMode>(mode));
return static_cast<Error>(intError);
}
Error Display::setColorTransform(const android::mat4& matrix,
android_color_transform_t hint)
{
- auto intError = mDevice.mComposer->setColorTransform(mId,
+ auto intError = mComposer.setColorTransform(mId,
matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint));
return static_cast<Error>(intError);
}
@@ -660,7 +574,7 @@ Error Display::setOutputBuffer(const sp<GraphicBuffer>& buffer,
{
int32_t fenceFd = releaseFence->dup();
auto handle = buffer->getNativeBuffer()->handle;
- auto intError = mDevice.mComposer->setOutputBuffer(mId, handle, fenceFd);
+ auto intError = mComposer.setOutputBuffer(mId, handle, fenceFd);
close(fenceFd);
return static_cast<Error>(intError);
}
@@ -668,14 +582,14 @@ Error Display::setOutputBuffer(const sp<GraphicBuffer>& buffer,
Error Display::setPowerMode(PowerMode mode)
{
auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
- auto intError = mDevice.mComposer->setPowerMode(mId, intMode);
+ auto intError = mComposer.setPowerMode(mId, intMode);
return static_cast<Error>(intError);
}
Error Display::setVsyncEnabled(Vsync enabled)
{
auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled);
- auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled);
+ auto intError = mComposer.setVsyncEnabled(mId, intEnabled);
return static_cast<Error>(intError);
}
@@ -683,8 +597,7 @@ Error Display::validate(uint32_t* outNumTypes, uint32_t* outNumRequests)
{
uint32_t numTypes = 0;
uint32_t numRequests = 0;
- auto intError = mDevice.mComposer->validateDisplay(mId,
- &numTypes, &numRequests);
+ auto intError = mComposer.validateDisplay(mId, &numTypes, &numRequests);
auto error = static_cast<Error>(intError);
if (error != Error::None && error != Error::HasChanges) {
return error;
@@ -701,7 +614,8 @@ Error Display::presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests
uint32_t numTypes = 0;
uint32_t numRequests = 0;
int32_t presentFenceFd = -1;
- auto intError = mDevice.mComposer->presentOrValidateDisplay(mId, &numTypes, &numRequests, &presentFenceFd, state);
+ auto intError = mComposer.presentOrValidateDisplay(
+ mId, &numTypes, &numRequests, &presentFenceFd, state);
auto error = static_cast<Error>(intError);
if (error != Error::None && error != Error::HasChanges) {
return error;
@@ -720,15 +634,23 @@ Error Display::presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests
void Display::discardCommands()
{
- mDevice.mComposer->resetCommands();
+ mComposer.resetCommands();
}
// For use by Device
+void Display::setConnected(bool connected) {
+ if (!mIsConnected && connected && mType == DisplayType::Physical) {
+ mComposer.setClientTargetSlotCount(mId);
+ loadConfigs();
+ }
+ mIsConnected = connected;
+}
+
int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
{
int32_t value = 0;
- auto intError = mDevice.mComposer->getDisplayAttribute(mId, configId,
+ auto intError = mComposer.getDisplayAttribute(mId, configId,
static_cast<Hwc2::IComposerClient::Attribute>(attribute),
&value);
auto error = static_cast<Error>(intError);
@@ -760,7 +682,7 @@ void Display::loadConfigs()
ALOGV("[%" PRIu64 "] loadConfigs", mId);
std::vector<Hwc2::Config> configIds;
- auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds);
+ auto intError = mComposer.getDisplayConfigs(mId, &configIds);
auto error = static_cast<Error>(intError);
if (error != Error::None) {
ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
@@ -773,54 +695,51 @@ void Display::loadConfigs()
}
}
-// For use by Layer
-
-void Display::destroyLayer(hwc2_layer_t layerId)
-{
- auto intError =mDevice.mComposer->destroyLayer(mId, layerId);
- auto error = static_cast<Error>(intError);
- ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
- " failed: %s (%d)", mId, layerId, to_string(error).c_str(),
- intError);
- mLayers.erase(layerId);
-}
-
// Other Display methods
-std::shared_ptr<Layer> Display::getLayerById(hwc2_layer_t id) const
+Layer* Display::getLayerById(hwc2_layer_t id) const
{
if (mLayers.count(id) == 0) {
return nullptr;
}
- auto layer = mLayers.at(id).lock();
- return layer;
+ return mLayers.at(id).get();
}
// Layer methods
-Layer::Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id)
- : mDisplay(display),
- mDisplayId(display->getId()),
- mDevice(display->getDevice()),
- mId(id)
+Layer::Layer(android::Hwc2::Composer& composer,
+ const std::unordered_set<Capability>& capabilities,
+ hwc2_display_t displayId, hwc2_layer_t layerId)
+ : mComposer(composer),
+ mCapabilities(capabilities),
+ mDisplayId(displayId),
+ mId(layerId)
{
- ALOGV("Created layer %" PRIu64 " on display %" PRIu64, id,
- display->getId());
+ ALOGV("Created layer %" PRIu64 " on display %" PRIu64, layerId, displayId);
}
Layer::~Layer()
{
- auto display = mDisplay.lock();
- if (display) {
- display->destroyLayer(mId);
+ auto intError = mComposer.destroyLayer(mDisplayId, mId);
+ auto error = static_cast<Error>(intError);
+ ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
+ " failed: %s (%d)", mDisplayId, mId, to_string(error).c_str(),
+ intError);
+ if (mLayerDestroyedListener) {
+ mLayerDestroyedListener(this);
}
}
+void Layer::setLayerDestroyedListener(std::function<void(Layer*)> listener) {
+ LOG_ALWAYS_FATAL_IF(mLayerDestroyedListener && listener,
+ "Attempt to set layer destroyed listener multiple times");
+ mLayerDestroyedListener = listener;
+}
+
Error Layer::setCursorPosition(int32_t x, int32_t y)
{
- auto intError = mDevice.mComposer->setCursorPosition(mDisplayId,
- mId, x, y);
+ auto intError = mComposer.setCursorPosition(mDisplayId, mId, x, y);
return static_cast<Error>(intError);
}
@@ -828,8 +747,8 @@ Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer,
const sp<Fence>& acquireFence)
{
int32_t fenceFd = acquireFence->dup();
- auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
- mId, slot, buffer, fenceFd);
+ auto intError = mComposer.setLayerBuffer(mDisplayId, mId, slot, buffer,
+ fenceFd);
return static_cast<Error>(intError);
}
@@ -839,7 +758,7 @@ Error Layer::setSurfaceDamage(const Region& damage)
// rects for HWC
Hwc2::Error intError = Hwc2::Error::NONE;
if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
- intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
+ intError = mComposer.setLayerSurfaceDamage(mDisplayId,
mId, std::vector<Hwc2::IComposerClient::Rect>());
} else {
size_t rectCount = 0;
@@ -851,8 +770,7 @@ Error Layer::setSurfaceDamage(const Region& damage)
rectArray[rect].right, rectArray[rect].bottom});
}
- intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
- mId, hwcRects);
+ intError = mComposer.setLayerSurfaceDamage(mDisplayId, mId, hwcRects);
}
return static_cast<Error>(intError);
@@ -861,24 +779,22 @@ Error Layer::setSurfaceDamage(const Region& damage)
Error Layer::setBlendMode(BlendMode mode)
{
auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode);
- auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId,
- mId, intMode);
+ auto intError = mComposer.setLayerBlendMode(mDisplayId, mId, intMode);
return static_cast<Error>(intError);
}
Error Layer::setColor(hwc_color_t color)
{
Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a};
- auto intError = mDevice.mComposer->setLayerColor(mDisplayId,
- mId, hwcColor);
+ auto intError = mComposer.setLayerColor(mDisplayId, mId, hwcColor);
return static_cast<Error>(intError);
}
Error Layer::setCompositionType(Composition type)
{
auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
- auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId,
- mId, intType);
+ auto intError = mComposer.setLayerCompositionType(
+ mDisplayId, mId, intType);
return static_cast<Error>(intError);
}
@@ -889,8 +805,7 @@ Error Layer::setDataspace(android_dataspace_t dataspace)
}
mDataSpace = dataspace;
auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
- auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
- mId, intDataspace);
+ auto intError = mComposer.setLayerDataspace(mDisplayId, mId, intDataspace);
return static_cast<Error>(intError);
}
@@ -898,27 +813,24 @@ Error Layer::setDisplayFrame(const Rect& frame)
{
Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top,
frame.right, frame.bottom};
- auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId,
- mId, hwcRect);
+ auto intError = mComposer.setLayerDisplayFrame(mDisplayId, mId, hwcRect);
return static_cast<Error>(intError);
}
Error Layer::setPlaneAlpha(float alpha)
{
- auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId,
- mId, alpha);
+ auto intError = mComposer.setLayerPlaneAlpha(mDisplayId, mId, alpha);
return static_cast<Error>(intError);
}
Error Layer::setSidebandStream(const native_handle_t* stream)
{
- if (!mDevice.hasCapability(Capability::SidebandStream)) {
+ if (mCapabilities.count(Capability::SidebandStream) == 0) {
ALOGE("Attempted to call setSidebandStream without checking that the "
"device supports sideband streams");
return Error::Unsupported;
}
- auto intError = mDevice.mComposer->setLayerSidebandStream(mDisplayId,
- mId, stream);
+ auto intError = mComposer.setLayerSidebandStream(mDisplayId, mId, stream);
return static_cast<Error>(intError);
}
@@ -926,16 +838,14 @@ Error Layer::setSourceCrop(const FloatRect& crop)
{
Hwc2::IComposerClient::FRect hwcRect{
crop.left, crop.top, crop.right, crop.bottom};
- auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId,
- mId, hwcRect);
+ auto intError = mComposer.setLayerSourceCrop(mDisplayId, mId, hwcRect);
return static_cast<Error>(intError);
}
Error Layer::setTransform(Transform transform)
{
auto intTransform = static_cast<Hwc2::Transform>(transform);
- auto intError = mDevice.mComposer->setLayerTransform(mDisplayId,
- mId, intTransform);
+ auto intError = mComposer.setLayerTransform(mDisplayId, mId, intTransform);
return static_cast<Error>(intError);
}
@@ -950,20 +860,19 @@ Error Layer::setVisibleRegion(const Region& region)
rectArray[rect].right, rectArray[rect].bottom});
}
- auto intError = mDevice.mComposer->setLayerVisibleRegion(mDisplayId,
- mId, hwcRects);
+ auto intError = mComposer.setLayerVisibleRegion(mDisplayId, mId, hwcRects);
return static_cast<Error>(intError);
}
Error Layer::setZOrder(uint32_t z)
{
- auto intError = mDevice.mComposer->setLayerZOrder(mDisplayId, mId, z);
+ auto intError = mComposer.setLayerZOrder(mDisplayId, mId, z);
return static_cast<Error>(intError);
}
Error Layer::setInfo(uint32_t type, uint32_t appId)
{
- auto intError = mDevice.mComposer->setLayerInfo(mDisplayId, mId, type, appId);
+ auto intError = mComposer.setLayerInfo(mDisplayId, mId, type, appId);
return static_cast<Error>(intError);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 9bcda1eb0a..fbe4c7ebed 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -53,10 +53,26 @@ namespace HWC2 {
class Display;
class Layer;
-typedef std::function<void(std::shared_ptr<Display>, Connection)>
- HotplugCallback;
-typedef std::function<void(std::shared_ptr<Display>)> RefreshCallback;
-typedef std::function<void(std::shared_ptr<Display>, nsecs_t)> VsyncCallback;
+// Implement this interface to receive hardware composer events.
+//
+// These callback functions will generally be called on a hwbinder thread, but
+// when first registering the callback the onHotplugReceived() function will
+// immediately be called on the thread calling registerCallback().
+//
+// All calls receive a sequenceId, which will be the value that was supplied to
+// HWC2::Device::registerCallback(). It's used to help differentiate callbacks
+// from different hardware composer instances.
+class ComposerCallback {
+ public:
+ virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+ Connection connection,
+ bool primaryDisplay) = 0;
+ virtual void onRefreshReceived(int32_t sequenceId,
+ hwc2_display_t display) = 0;
+ virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
+ int64_t timestamp) = 0;
+ virtual ~ComposerCallback() = default;
+};
// C++ Wrapper around hwc2_device_t. Load all functions pointers
// and handle callback registration.
@@ -66,10 +82,8 @@ public:
// Service name is expected to be 'default' or 'vr' for normal use.
// 'vr' will slightly modify the behavior of the mComposer.
Device(const std::string& serviceName);
- ~Device();
- friend class HWC2::Display;
- friend class HWC2::Layer;
+ void registerCallback(ComposerCallback* callback, int32_t sequenceId);
// Required by HWC2
@@ -81,27 +95,14 @@ public:
uint32_t getMaxVirtualDisplayCount() const;
Error createVirtualDisplay(uint32_t width, uint32_t height,
- android_pixel_format_t* format,
- std::shared_ptr<Display>* outDisplay);
-
- void registerHotplugCallback(HotplugCallback hotplug);
- void registerRefreshCallback(RefreshCallback refresh);
- void registerVsyncCallback(VsyncCallback vsync);
+ android_pixel_format_t* format, Display** outDisplay);
+ void destroyDisplay(hwc2_display_t displayId);
- // For use by callbacks
-
- void callHotplug(std::shared_ptr<Display> display, Connection connected);
- void callRefresh(std::shared_ptr<Display> display);
- void callVsync(std::shared_ptr<Display> display, nsecs_t timestamp);
+ void onHotplug(hwc2_display_t displayId, Connection connection);
// Other Device methods
- // This will create a Display if one is not found, but it will not be marked
- // as connected. This Display may be null if the display has been torn down
- // but has not been removed from the map yet.
- std::shared_ptr<Display> getDisplayById(hwc2_display_t id);
-
- bool hasCapability(HWC2::Capability capability) const;
+ Display* getDisplayById(hwc2_display_t id);
android::Hwc2::Composer* getComposer() { return mComposer.get(); }
@@ -109,37 +110,23 @@ private:
// Initialization methods
void loadCapabilities();
- void registerCallbacks();
-
- // For use by Display
-
- void destroyVirtualDisplay(hwc2_display_t display);
// Member variables
std::unique_ptr<android::Hwc2::Composer> mComposer;
-
std::unordered_set<Capability> mCapabilities;
- std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays;
-
- HotplugCallback mHotplug;
- std::vector<std::pair<std::shared_ptr<Display>, Connection>>
- mPendingHotplugs;
- RefreshCallback mRefresh;
- std::vector<std::shared_ptr<Display>> mPendingRefreshes;
- VsyncCallback mVsync;
- std::vector<std::pair<std::shared_ptr<Display>, nsecs_t>> mPendingVsyncs;
+ std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
+ bool mRegisteredCallback;
};
// Convenience C++ class to access hwc2_device_t Display functions directly.
-class Display : public std::enable_shared_from_this<Display>
+class Display
{
public:
- Display(Device& device, hwc2_display_t id);
+ Display(android::Hwc2::Composer& composer,
+ const std::unordered_set<Capability>& capabilities,
+ hwc2_display_t id, DisplayType type);
~Display();
- friend class HWC2::Device;
- friend class HWC2::Layer;
-
class Config
{
public:
@@ -212,12 +199,12 @@ public:
// Required by HWC2
[[clang::warn_unused_result]] Error acceptChanges();
- [[clang::warn_unused_result]] Error createLayer(
- std::shared_ptr<Layer>* outLayer);
+ [[clang::warn_unused_result]] Error createLayer(Layer** outLayer);
+ [[clang::warn_unused_result]] Error destroyLayer(Layer* layer);
[[clang::warn_unused_result]] Error getActiveConfig(
std::shared_ptr<const Config>* outConfig) const;
[[clang::warn_unused_result]] Error getChangedCompositionTypes(
- std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes);
+ std::unordered_map<Layer*, Composition>* outTypes);
[[clang::warn_unused_result]] Error getColorModes(
std::vector<android_color_mode_t>* outModes) const;
@@ -227,14 +214,13 @@ public:
[[clang::warn_unused_result]] Error getName(std::string* outName) const;
[[clang::warn_unused_result]] Error getRequests(
DisplayRequest* outDisplayRequests,
- std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
- outLayerRequests);
+ std::unordered_map<Layer*, LayerRequest>* outLayerRequests);
[[clang::warn_unused_result]] Error getType(DisplayType* outType) const;
[[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const;
[[clang::warn_unused_result]] Error getHdrCapabilities(
std::unique_ptr<android::HdrCapabilities>* outCapabilities) const;
[[clang::warn_unused_result]] Error getReleaseFences(
- std::unordered_map<std::shared_ptr<Layer>,
+ std::unordered_map<Layer*,
android::sp<android::Fence>>* outFences) const;
[[clang::warn_unused_result]] Error present(
android::sp<android::Fence>* outPresentFence);
@@ -266,32 +252,31 @@ public:
// Other Display methods
- Device& getDevice() const { return mDevice; }
hwc2_display_t getId() const { return mId; }
bool isConnected() const { return mIsConnected; }
+ void setConnected(bool connected); // For use by Device only
private:
- // For use by Device
-
- void setConnected(bool connected) { mIsConnected = connected; }
int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
void loadConfig(hwc2_config_t configId);
void loadConfigs();
- // For use by Layer
- void destroyLayer(hwc2_layer_t layerId);
-
// This may fail (and return a null pointer) if no layer with this ID exists
// on this display
- std::shared_ptr<Layer> getLayerById(hwc2_layer_t id) const;
+ Layer* getLayerById(hwc2_layer_t id) const;
// Member variables
- Device& mDevice;
+ // These are references to data owned by HWC2::Device, which will outlive
+ // this HWC2::Display, so these references are guaranteed to be valid for
+ // the lifetime of this object.
+ android::Hwc2::Composer& mComposer;
+ const std::unordered_set<Capability>& mCapabilities;
+
hwc2_display_t mId;
bool mIsConnected;
DisplayType mType;
- std::unordered_map<hwc2_layer_t, std::weak_ptr<Layer>> mLayers;
+ std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
// The ordering in this map matters, for getConfigs(), when it is
// converted to a vector
std::map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
@@ -301,12 +286,18 @@ private:
class Layer
{
public:
- Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id);
+ Layer(android::Hwc2::Composer& composer,
+ const std::unordered_set<Capability>& capabilities,
+ hwc2_display_t displayId, hwc2_layer_t layerId);
~Layer();
- bool isAbandoned() const { return mDisplay.expired(); }
hwc2_layer_t getId() const { return mId; }
+ // Register a listener to be notified when the layer is destroyed. When the
+ // listener function is called, the Layer will be in the process of being
+ // destroyed, so it's not safe to call methods on it.
+ void setLayerDestroyedListener(std::function<void(Layer*)> listener);
+
[[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
[[clang::warn_unused_result]] Error setBuffer(uint32_t slot,
const android::sp<android::GraphicBuffer>& buffer,
@@ -333,11 +324,16 @@ public:
[[clang::warn_unused_result]] Error setInfo(uint32_t type, uint32_t appId);
private:
- std::weak_ptr<Display> mDisplay;
+ // These are references to data owned by HWC2::Device, which will outlive
+ // this HWC2::Layer, so these references are guaranteed to be valid for
+ // the lifetime of this object.
+ android::Hwc2::Composer& mComposer;
+ const std::unordered_set<Capability>& mCapabilities;
+
hwc2_display_t mDisplayId;
- Device& mDevice;
hwc2_layer_t mId;
android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN;
+ std::function<void(Layer*)> mLayerDestroyedListener;
};
} // namespace HWC2
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index abf7dd12d0..b096a3ae57 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -65,7 +65,6 @@ HWComposer::HWComposer(const std::string& serviceName)
mFreeDisplaySlots(),
mHwcDisplaySlots(),
mCBContext(),
- mEventHandler(nullptr),
mVSyncCounts(),
mRemainingHwcVirtualDisplays(0)
{
@@ -74,41 +73,15 @@ HWComposer::HWComposer(const std::string& serviceName)
mVSyncCounts[i] = 0;
}
- loadHwcModule(serviceName);
+ mHwcDevice = std::make_unique<HWC2::Device>(serviceName);
+ mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
}
HWComposer::~HWComposer() {}
-void HWComposer::setEventHandler(EventHandler* handler)
-{
- if (handler == nullptr) {
- ALOGE("setEventHandler: Rejected attempt to clear handler");
- return;
- }
-
- bool wasNull = (mEventHandler == nullptr);
- mEventHandler = handler;
-
- if (wasNull) {
- auto hotplugHook = std::bind(&HWComposer::hotplug, this,
- std::placeholders::_1, std::placeholders::_2);
- mHwcDevice->registerHotplugCallback(hotplugHook);
- auto invalidateHook = std::bind(&HWComposer::invalidate, this,
- std::placeholders::_1);
- mHwcDevice->registerRefreshCallback(invalidateHook);
- auto vsyncHook = std::bind(&HWComposer::vsync, this,
- std::placeholders::_1, std::placeholders::_2);
- mHwcDevice->registerVsyncCallback(vsyncHook);
- }
-}
-
-// Load and prepare the hardware composer module. Sets mHwc.
-void HWComposer::loadHwcModule(const std::string& serviceName)
-{
- ALOGV("loadHwcModule");
- mHwcDevice = std::make_unique<HWC2::Device>(serviceName);
-
- mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
+void HWComposer::registerCallback(HWC2::ComposerCallback* callback,
+ int32_t sequenceId) {
+ mHwcDevice->registerCallback(callback, sequenceId);
}
bool HWComposer::hasCapability(HWC2::Capability capability) const
@@ -146,54 +119,51 @@ void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) {
}
}
-void HWComposer::hotplug(const std::shared_ptr<HWC2::Display>& display,
- HWC2::Connection connected) {
- ALOGV("hotplug: %" PRIu64 ", %s", display->getId(),
- to_string(connected).c_str());
- int32_t disp = 0;
+void HWComposer::onHotplug(hwc2_display_t displayId,
+ HWC2::Connection connection) {
+ ALOGV("hotplug: %" PRIu64 ", %s", displayId,
+ to_string(connection).c_str());
+ mHwcDevice->onHotplug(displayId, connection);
if (!mDisplayData[0].hwcDisplay) {
- ALOGE_IF(connected != HWC2::Connection::Connected, "Assumed primary"
+ ALOGE_IF(connection != HWC2::Connection::Connected, "Assumed primary"
" display would be connected");
- mDisplayData[0].hwcDisplay = display;
- mHwcDisplaySlots[display->getId()] = 0;
- disp = DisplayDevice::DISPLAY_PRIMARY;
+ mDisplayData[0].hwcDisplay = mHwcDevice->getDisplayById(displayId);
+ mHwcDisplaySlots[displayId] = 0;
} else {
// Disconnect is handled through HWComposer::disconnectDisplay via
// SurfaceFlinger's onHotplugReceived callback handling
- if (connected == HWC2::Connection::Connected) {
- mDisplayData[1].hwcDisplay = display;
- mHwcDisplaySlots[display->getId()] = 1;
+ if (connection == HWC2::Connection::Connected) {
+ mDisplayData[1].hwcDisplay = mHwcDevice->getDisplayById(displayId);
+ mHwcDisplaySlots[displayId] = 1;
}
- disp = DisplayDevice::DISPLAY_EXTERNAL;
}
- mEventHandler->onHotplugReceived(this, disp,
- connected == HWC2::Connection::Connected);
}
-void HWComposer::invalidate(const std::shared_ptr<HWC2::Display>& /*display*/) {
- mEventHandler->onInvalidateReceived(this);
-}
-
-void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display,
- int64_t timestamp) {
+bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp,
+ int32_t* outDisplay) {
+ auto display = mHwcDevice->getDisplayById(displayId);
+ if (!display) {
+ ALOGE("onVsync Failed to find display %" PRIu64, displayId);
+ return false;
+ }
auto displayType = HWC2::DisplayType::Invalid;
auto error = display->getType(&displayType);
if (error != HWC2::Error::None) {
- ALOGE("vsync: Failed to determine type of display %" PRIu64,
+ ALOGE("onVsync: Failed to determine type of display %" PRIu64,
display->getId());
- return;
+ return false;
}
if (displayType == HWC2::DisplayType::Virtual) {
ALOGE("Virtual display %" PRIu64 " passed to vsync callback",
display->getId());
- return;
+ return false;
}
if (mHwcDisplaySlots.count(display->getId()) == 0) {
ALOGE("Unknown physical display %" PRIu64 " passed to vsync callback",
display->getId());
- return;
+ return false;
}
int32_t disp = mHwcDisplaySlots[display->getId()];
@@ -207,17 +177,21 @@ void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display,
if (timestamp == mLastHwVSync[disp]) {
ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
timestamp);
- return;
+ return false;
}
mLastHwVSync[disp] = timestamp;
}
+ if (outDisplay) {
+ *outDisplay = disp;
+ }
+
char tag[16];
snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
- mEventHandler->onVSyncReceived(this, disp, timestamp);
+ return true;
}
status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
@@ -236,7 +210,7 @@ status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
return INVALID_OPERATION;
}
- std::shared_ptr<HWC2::Display> display;
+ HWC2::Display* display;
auto error = mHwcDevice->createVirtualDisplay(width, height, format,
&display);
if (error != HWC2::Error::None) {
@@ -265,13 +239,13 @@ status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
return NO_ERROR;
}
-std::shared_ptr<HWC2::Layer> HWComposer::createLayer(int32_t displayId) {
+HWC2::Layer* HWComposer::createLayer(int32_t displayId) {
if (!isValidDisplay(displayId)) {
ALOGE("Failed to create layer on invalid display %d", displayId);
return nullptr;
}
auto display = mDisplayData[displayId].hwcDisplay;
- std::shared_ptr<HWC2::Layer> layer;
+ HWC2::Layer* layer;
auto error = display->createLayer(&layer);
if (error != HWC2::Error::None) {
ALOGE("Failed to create layer on display %d: %s (%d)", displayId,
@@ -281,6 +255,19 @@ std::shared_ptr<HWC2::Layer> HWComposer::createLayer(int32_t displayId) {
return layer;
}
+void HWComposer::destroyLayer(int32_t displayId, HWC2::Layer* layer) {
+ if (!isValidDisplay(displayId)) {
+ ALOGE("Failed to destroy layer on invalid display %d", displayId);
+ return;
+ }
+ auto display = mDisplayData[displayId].hwcDisplay;
+ auto error = display->destroyLayer(layer);
+ if (error != HWC2::Error::None) {
+ ALOGE("Failed to destroy layer on display %d: %s (%d)", displayId,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ }
+}
+
nsecs_t HWComposer::getRefreshTimestamp(int32_t displayId) const {
// this returns the last refresh timestamp.
// if the last one is not available, we estimate it based on
@@ -348,10 +335,8 @@ std::vector<android_color_mode_t> HWComposer::getColorModes(int32_t displayId) c
displayId);
return modes;
}
- const std::shared_ptr<HWC2::Display>& hwcDisplay =
- mDisplayData[displayId].hwcDisplay;
- auto error = hwcDisplay->getColorModes(&modes);
+ auto error = mDisplayData[displayId].hwcDisplay->getColorModes(&modes);
if (error != HWC2::Error::None) {
ALOGE("getColorModes failed for display %d: %s (%d)", displayId,
to_string(error).c_str(), static_cast<int32_t>(error));
@@ -471,7 +456,7 @@ status_t HWComposer::prepare(DisplayDevice& displayDevice) {
return UNKNOWN_ERROR;
}
if (state == 1) { //Present Succeeded.
- std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+ std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
error = hwcDisplay->getReleaseFences(&releaseFences);
displayData.releaseFences = std::move(releaseFences);
displayData.lastPresentFence = outPresentFence;
@@ -490,8 +475,7 @@ status_t HWComposer::prepare(DisplayDevice& displayDevice) {
return BAD_INDEX;
}
- std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::Composition>
- changedTypes;
+ std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes;
changedTypes.reserve(numTypes);
error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
if (error != HWC2::Error::None) {
@@ -503,8 +487,7 @@ status_t HWComposer::prepare(DisplayDevice& displayDevice) {
displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0);
- std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::LayerRequest>
- layerRequests;
+ std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests;
layerRequests.reserve(numRequests);
error = hwcDisplay->getRequests(&displayData.displayRequests,
&layerRequests);
@@ -598,7 +581,7 @@ sp<Fence> HWComposer::getPresentFence(int32_t displayId) const {
}
sp<Fence> HWComposer::getLayerReleaseFence(int32_t displayId,
- const std::shared_ptr<HWC2::Layer>& layer) const {
+ HWC2::Layer* layer) const {
if (!isValidDisplay(displayId)) {
ALOGE("getLayerReleaseFence: Invalid display");
return Fence::NO_FENCE;
@@ -639,7 +622,7 @@ status_t HWComposer::presentAndGetReleaseFences(int32_t displayId) {
return UNKNOWN_ERROR;
}
- std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+ std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
error = hwcDisplay->getReleaseFences(&releaseFences);
if (error != HWC2::Error::None) {
ALOGE("presentAndGetReleaseFences: Failed to get release fences "
@@ -787,6 +770,8 @@ void HWComposer::disconnectDisplay(int displayId) {
auto hwcId = displayData.hwcDisplay->getId();
mHwcDisplaySlots.erase(hwcId);
displayData.reset();
+
+ mHwcDevice->destroyDisplay(hwcId);
}
status_t HWComposer::setOutputBuffer(int32_t displayId,
@@ -885,7 +870,7 @@ void HWComposer::dump(String8& result) const {
HWComposer::DisplayData::DisplayData()
: hasClientComposition(false),
hasDeviceComposition(false),
- hwcDisplay(),
+ hwcDisplay(nullptr),
lastPresentFence(Fence::NO_FENCE),
outbufHandle(nullptr),
outbufAcquireFence(Fence::NO_FENCE),
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 3dfb65b1e3..3640bb5a98 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -65,23 +65,14 @@ class String8;
class HWComposer
{
public:
- class EventHandler {
- friend class HWComposer;
- virtual void onVSyncReceived(
- HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
- virtual void onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) = 0;
- virtual void onInvalidateReceived(HWComposer* composer) = 0;
- protected:
- virtual ~EventHandler() {}
- };
-
// Uses the named composer service. Valid choices for normal use
// are 'default' and 'vr'.
HWComposer(const std::string& serviceName);
~HWComposer();
- void setEventHandler(EventHandler* handler);
+ void registerCallback(HWC2::ComposerCallback* callback,
+ int32_t sequenceId);
bool hasCapability(HWC2::Capability capability) const;
@@ -91,7 +82,9 @@ public:
android_pixel_format_t* format, int32_t* outId);
// Attempts to create a new layer on this display
- std::shared_ptr<HWC2::Layer> createLayer(int32_t displayId);
+ HWC2::Layer* createLayer(int32_t displayId);
+ // Destroy a previously created layer
+ void destroyLayer(int32_t displayId, HWC2::Layer* layer);
// Asks the HAL what it can do
status_t prepare(DisplayDevice& displayDevice);
@@ -126,7 +119,7 @@ public:
// Get last release fence for the given layer
sp<Fence> getLayerReleaseFence(int32_t displayId,
- const std::shared_ptr<HWC2::Layer>& layer) const;
+ HWC2::Layer* layer) const;
// Set the output buffer and acquire fence for a virtual display.
// Returns INVALID_OPERATION if displayId is not a virtual display.
@@ -142,6 +135,12 @@ public:
// Events handling ---------------------------------------------------------
+ // Returns true if successful, false otherwise. The
+ // DisplayDevice::DisplayType of the display is returned as an output param.
+ bool onVsync(hwc2_display_t displayId, int64_t timestamp,
+ int32_t* outDisplay);
+ void onHotplug(hwc2_display_t displayId, HWC2::Connection connection);
+
void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled);
// Query display parameters. Pass in a display index (e.g.
@@ -169,19 +168,11 @@ public:
private:
static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
- void loadHwcModule(const std::string& serviceName);
-
bool isValidDisplay(int32_t displayId) const;
static void validateChange(HWC2::Composition from, HWC2::Composition to);
struct cb_context;
- void invalidate(const std::shared_ptr<HWC2::Display>& display);
- void vsync(const std::shared_ptr<HWC2::Display>& display,
- int64_t timestamp);
- void hotplug(const std::shared_ptr<HWC2::Display>& display,
- HWC2::Connection connected);
-
struct DisplayData {
DisplayData();
~DisplayData();
@@ -189,11 +180,10 @@ private:
bool hasClientComposition;
bool hasDeviceComposition;
- std::shared_ptr<HWC2::Display> hwcDisplay;
+ HWC2::Display* hwcDisplay;
HWC2::DisplayRequest displayRequests;
sp<Fence> lastPresentFence; // signals when the last set op retires
- std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>>
- releaseFences;
+ std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
buffer_handle_t outbufHandle;
sp<Fence> outbufAcquireFence;
mutable std::unordered_map<int32_t,
@@ -214,7 +204,6 @@ private:
mutable Mutex mDisplayLock;
cb_context* mCBContext;
- EventHandler* mEventHandler;
size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
uint32_t mRemainingHwcVirtualDisplays;
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp
index ee6e886d12..052a959724 100644
--- a/services/surfaceflinger/EventControlThread.cpp
+++ b/services/surfaceflinger/EventControlThread.cpp
@@ -31,34 +31,35 @@ void EventControlThread::setVsyncEnabled(bool enabled) {
}
bool EventControlThread::threadLoop() {
- Mutex::Autolock lock(mMutex);
-
- bool vsyncEnabled = mVsyncEnabled;
-
-#ifdef USE_HWC2
- mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);
-#else
- mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC,
- mVsyncEnabled);
-#endif
+ enum class VsyncState {Unset, On, Off};
+ auto currentVsyncState = VsyncState::Unset;
while (true) {
- status_t err = mCond.wait(mMutex);
- if (err != NO_ERROR) {
- ALOGE("error waiting for new events: %s (%d)",
- strerror(-err), err);
- return false;
+ auto requestedVsyncState = VsyncState::On;
+ {
+ Mutex::Autolock lock(mMutex);
+ requestedVsyncState =
+ mVsyncEnabled ? VsyncState::On : VsyncState::Off;
+ while (currentVsyncState == requestedVsyncState) {
+ status_t err = mCond.wait(mMutex);
+ if (err != NO_ERROR) {
+ ALOGE("error waiting for new events: %s (%d)",
+ strerror(-err), err);
+ return false;
+ }
+ requestedVsyncState =
+ mVsyncEnabled ? VsyncState::On : VsyncState::Off;
+ }
}
- if (vsyncEnabled != mVsyncEnabled) {
+ bool enable = requestedVsyncState == VsyncState::On;
#ifdef USE_HWC2
- mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);
+ mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable);
#else
- mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
- SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);
+ mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
+ SurfaceFlinger::EVENT_VSYNC, enable);
#endif
- vsyncEnabled = mVsyncEnabled;
- }
+ currentVsyncState = requestedVsyncState;
}
return false;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3903a5546f..54d4cbd613 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -201,6 +201,12 @@ Layer::~Layer() {
}
mFlinger->deleteTextureAsync(mTextureName);
mFrameTracker.logAndResetStats(mName);
+
+#ifdef USE_HWC2
+ ALOGE_IF(!mHwcLayers.empty(),
+ "Found stale hardware composer layers when destroying "
+ "surface flinger layer");
+#endif
}
// ---------------------------------------------------------------------------
@@ -303,7 +309,7 @@ void Layer::onRemoved() {
mSurfaceFlingerConsumer->abandon();
#ifdef USE_HWC2
- clearHwcLayers();
+ destroyAllHwcLayers();
#endif
for (const auto& child : mCurrentChildren) {
@@ -364,6 +370,48 @@ sp<IGraphicBufferProducer> Layer::getProducer() const {
// h/w composer set-up
// ---------------------------------------------------------------------------
+#ifdef USE_HWC2
+bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) {
+ LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
+ "Already have a layer for hwcId %d", hwcId);
+ HWC2::Layer* layer = hwc->createLayer(hwcId);
+ if (!layer) {
+ return false;
+ }
+ HWCInfo& hwcInfo = mHwcLayers[hwcId];
+ hwcInfo.hwc = hwc;
+ hwcInfo.layer = layer;
+ layer->setLayerDestroyedListener(
+ [this, hwcId] (HWC2::Layer* /*layer*/){mHwcLayers.erase(hwcId);});
+ return true;
+}
+
+void Layer::destroyHwcLayer(int32_t hwcId) {
+ if (mHwcLayers.count(hwcId) == 0) {
+ return;
+ }
+ auto& hwcInfo = mHwcLayers[hwcId];
+ LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr,
+ "Attempt to destroy null layer");
+ LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
+ hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer);
+ // The layer destroyed listener should have cleared the entry from
+ // mHwcLayers. Verify that.
+ LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
+ "Stale layer entry in mHwcLayers");
+}
+
+void Layer::destroyAllHwcLayers() {
+ size_t numLayers = mHwcLayers.size();
+ for (size_t i = 0; i < numLayers; ++i) {
+ LOG_ALWAYS_FATAL_IF(mHwcLayers.empty(), "destroyAllHwcLayers failed");
+ destroyHwcLayer(mHwcLayers.begin()->first);
+ }
+ LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(),
+ "All hardware composer layers should have been destroyed");
+}
+#endif
+
Rect Layer::getContentCrop() const {
// this is the crop rectangle that applies to the buffer
// itself (as opposed to the window)
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8df8c49bbe..1b7d0759d5 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -447,37 +447,21 @@ public:
#ifdef USE_HWC2
// -----------------------------------------------------------------------
+ bool createHwcLayer(HWComposer* hwc, int32_t hwcId);
+ void destroyHwcLayer(int32_t hwcId);
+ void destroyAllHwcLayers();
+
bool hasHwcLayer(int32_t hwcId) {
- if (mHwcLayers.count(hwcId) == 0) {
- return false;
- }
- if (mHwcLayers[hwcId].layer->isAbandoned()) {
- ALOGI("Erasing abandoned layer %s on %d", mName.string(), hwcId);
- mHwcLayers.erase(hwcId);
- return false;
- }
- return true;
+ return mHwcLayers.count(hwcId) > 0;
}
- std::shared_ptr<HWC2::Layer> getHwcLayer(int32_t hwcId) {
+ HWC2::Layer* getHwcLayer(int32_t hwcId) {
if (mHwcLayers.count(hwcId) == 0) {
return nullptr;
}
return mHwcLayers[hwcId].layer;
}
- void setHwcLayer(int32_t hwcId, std::shared_ptr<HWC2::Layer>&& layer) {
- if (layer) {
- mHwcLayers[hwcId].layer = layer;
- } else {
- mHwcLayers.erase(hwcId);
- }
- }
-
- void clearHwcLayers() {
- mHwcLayers.clear();
- }
-
#endif
// -----------------------------------------------------------------------
@@ -766,12 +750,14 @@ private:
// HWC items, accessed from the main thread
struct HWCInfo {
HWCInfo()
- : layer(),
+ : hwc(nullptr),
+ layer(nullptr),
forceClientComposition(false),
compositionType(HWC2::Composition::Invalid),
clearClientTarget(false) {}
- std::shared_ptr<HWC2::Layer> layer;
+ HWComposer* hwc;
+ HWC2::Layer* layer;
bool forceClientComposition;
HWC2::Composition compositionType;
bool clearClientTarget;
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index ac2d8b2aba..57f468d2fa 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -64,7 +64,7 @@ RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat, uint32_t f
"EGL_ANDROIDX_no_config_context") &&
!findExtension(eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
"EGL_KHR_no_config_context")) {
- config = chooseEglConfig(display, hwcFormat);
+ config = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
}
EGLint renderableType = 0;
@@ -108,7 +108,7 @@ RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat, uint32_t f
EGLConfig dummyConfig = config;
if (dummyConfig == EGL_NO_CONFIG) {
- dummyConfig = chooseEglConfig(display, hwcFormat);
+ dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
}
EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE };
EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
@@ -406,7 +406,8 @@ static status_t selectEGLConfig(EGLDisplay display, EGLint format,
return err;
}
-EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) {
+EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format,
+ bool logConfig) {
status_t err;
EGLConfig config;
@@ -427,18 +428,20 @@ EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) {
}
}
- // print some debugging info
- EGLint r,g,b,a;
- eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
- eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
- eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
- eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
- ALOGI("EGL information:");
- ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
- ALOGI("version : %s", eglQueryString(display, EGL_VERSION));
- ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
- ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
- ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+ if (logConfig) {
+ // print some debugging info
+ EGLint r,g,b,a;
+ eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
+ eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
+ eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
+ eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
+ ALOGI("EGL information:");
+ ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
+ ALOGI("version : %s", eglQueryString(display, EGL_VERSION));
+ ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
+ ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+ ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+ }
return config;
}
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 56f582755e..954457946e 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -64,7 +64,7 @@ public:
};
static RenderEngine* create(EGLDisplay display, int hwcFormat, uint32_t featureFlags);
- static EGLConfig chooseEglConfig(EGLDisplay display, int format);
+ static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
void primeCache() const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4154d6a87f..9dfdaa1d99 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -77,6 +77,7 @@
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
+#include "DisplayHardware/ComposerHal.h"
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
@@ -101,10 +102,24 @@ EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint na
namespace android {
-
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
+namespace {
+class ConditionalLock {
+public:
+ ConditionalLock(Mutex& mutex, bool lock) : mMutex(mutex), mLocked(lock) {
+ if (lock) {
+ mMutex.lock();
+ }
+ }
+ ~ConditionalLock() { if (mLocked) mMutex.unlock(); }
+private:
+ Mutex& mMutex;
+ bool mLocked;
+};
+} // namespace anonymous
+
// ---------------------------------------------------------------------------
const String16 sHardwareTest("android.permission.HARDWARE_TEST");
@@ -147,9 +162,6 @@ SurfaceFlinger::SurfaceFlinger()
mLayersRemoved(false),
mLayersAdded(false),
mRepaintEverything(0),
- mHwc(nullptr),
- mRealHwc(nullptr),
- mVrHwc(nullptr),
mHwcServiceName(getHwcServiceName()),
mRenderEngine(nullptr),
mBootTime(systemTime()),
@@ -177,7 +189,9 @@ SurfaceFlinger::SurfaceFlinger()
mTotalTime(0),
mLastSwapTime(0),
mNumLayers(0),
- mVrFlingerRequestsDisplay(false)
+ mVrFlingerRequestsDisplay(false),
+ mMainThreadId(std::this_thread::get_id()),
+ mComposerSequenceId(0)
{
ALOGI("SurfaceFlinger is starting");
@@ -583,48 +597,46 @@ void SurfaceFlinger::init() {
ALOGI("Phase offset NS: %" PRId64 "", vsyncPhaseOffsetNs);
- { // Autolock scope
- Mutex::Autolock _l(mStateLock);
+ Mutex::Autolock _l(mStateLock);
- // initialize EGL for the default display
- mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglInitialize(mEGLDisplay, NULL, NULL);
-
- // start the EventThread
- sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc, *this, false);
- sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
- mEventQueue.setEventThread(mSFEventThread);
+ // initialize EGL for the default display
+ mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ eglInitialize(mEGLDisplay, NULL, NULL);
- // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
- struct sched_param param = {0};
- param.sched_priority = 2;
- if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != 0) {
- ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
- }
- if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 0) {
- ALOGE("Couldn't set SCHED_FIFO for EventThread");
- }
+ // start the EventThread
+ sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+ vsyncPhaseOffsetNs, true, "app");
+ mEventThread = new EventThread(vsyncSrc, *this, false);
+ sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+ sfVsyncPhaseOffsetNs, true, "sf");
+ mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
+ mEventQueue.setEventThread(mSFEventThread);
- // Get a RenderEngine for the given display / config (can't fail)
- mRenderEngine = RenderEngine::create(mEGLDisplay,
- HAL_PIXEL_FORMAT_RGBA_8888,
- hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
+ // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
+ struct sched_param param = {0};
+ param.sched_priority = 2;
+ if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != 0) {
+ ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
+ }
+ if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 0) {
+ ALOGE("Couldn't set SCHED_FIFO for EventThread");
}
- // 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.
- LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
- "Starting with vr flinger active is not currently supported.");
- mRealHwc = new HWComposer(mHwcServiceName);
- mHwc = mRealHwc;
- mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
+ // Get a RenderEngine for the given display / config (can't fail)
+ mRenderEngine = RenderEngine::create(mEGLDisplay,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
- Mutex::Autolock _l(mStateLock);
+ // retrieve the EGL context that was selected/created
+ mEGLContext = mRenderEngine->getEGLContext();
+
+ LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
+ "couldn't create EGLContext");
+
+ LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
+ "Starting with vr flinger active is not currently supported.");
+ mHwc.reset(new HWComposer(mHwcServiceName));
+ mHwc->registerCallback(this, mComposerSequenceId);
if (useVrFlinger) {
auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
@@ -639,16 +651,6 @@ void SurfaceFlinger::init() {
}
}
- // retrieve the EGL context that was selected/created
- mEGLContext = mRenderEngine->getEGLContext();
-
- LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
- "couldn't create EGLContext");
-
- // make the GLContext current so that we can create textures when creating
- // Layers (which may happens before we render something)
- getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
-
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -1218,11 +1220,16 @@ void SurfaceFlinger::resyncWithRateLimit() {
sLastResyncAttempted = now;
}
-void SurfaceFlinger::onVSyncReceived(HWComposer* composer, int32_t type,
- nsecs_t timestamp) {
+void SurfaceFlinger::onVsyncReceived(int32_t sequenceId,
+ hwc2_display_t displayId, int64_t timestamp) {
Mutex::Autolock lock(mStateLock);
- // Ignore any vsyncs from the non-active hardware composer.
- if (composer != mHwc) {
+ // Ignore any vsyncs from a previous hardware composer.
+ if (sequenceId != mComposerSequenceId) {
+ return;
+ }
+
+ int32_t type;
+ if (!mHwc->onVsync(displayId, timestamp, &type)) {
return;
}
@@ -1230,7 +1237,7 @@ void SurfaceFlinger::onVSyncReceived(HWComposer* composer, int32_t type,
{ // Scope for the lock
Mutex::Autolock _l(mHWVsyncLock);
- if (type == 0 && mPrimaryHWVsyncEnabled) {
+ if (type == DisplayDevice::DISPLAY_PRIMARY && mPrimaryHWVsyncEnabled) {
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
}
}
@@ -1248,7 +1255,7 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
}
void SurfaceFlinger::createDefaultDisplayDevice() {
- const int32_t type = DisplayDevice::DISPLAY_PRIMARY;
+ const DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_PRIMARY;
wp<IBinder> token = mBuiltinDisplays[type];
// All non-virtual displays are currently considered secure.
@@ -1279,28 +1286,49 @@ void SurfaceFlinger::createDefaultDisplayDevice() {
mDisplays.add(token, hw);
setActiveColorModeInternal(hw, HAL_COLOR_MODE_NATIVE);
hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
-}
-void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) {
- ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false");
+ // Add the primary display token to mDrawingState so we don't try to
+ // recreate the DisplayDevice for the primary display.
+ mDrawingState.displays.add(token, DisplayDeviceState(type, true));
- if (composer->isUsingVrComposer()) {
- // We handle initializing the primary display device for the VR
- // window manager hwc explicitly at the time of transition.
- if (disp != DisplayDevice::DISPLAY_PRIMARY) {
- ALOGE("External displays are not supported by the vr hardware composer.");
+ // make the GLContext current so that we can create textures when creating
+ // Layers (which may happens before we render something)
+ hw->makeCurrent(mEGLDisplay, mEGLContext);
+}
+
+void SurfaceFlinger::onHotplugReceived(int32_t sequenceId,
+ hwc2_display_t display, HWC2::Connection connection,
+ bool primaryDisplay) {
+ ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s, %s)",
+ sequenceId, display,
+ connection == HWC2::Connection::Connected ?
+ "connected" : "disconnected",
+ primaryDisplay ? "primary" : "external");
+
+ // Only lock if we're not on the main thread. This function is normally
+ // called on a hwbinder thread, but for the primary display it's called on
+ // the main thread with the state lock already held, so don't attempt to
+ // acquire it here.
+ ConditionalLock lock(mStateLock,
+ std::this_thread::get_id() != mMainThreadId);
+
+ if (primaryDisplay) {
+ mHwc->onHotplug(display, connection);
+ if (!mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY].get()) {
+ createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
}
- return;
- }
-
- if (disp == DisplayDevice::DISPLAY_PRIMARY) {
- Mutex::Autolock lock(mStateLock);
- createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
createDefaultDisplayDevice();
} else {
+ if (sequenceId != mComposerSequenceId) {
+ return;
+ }
+ if (mHwc->isUsingVrComposer()) {
+ ALOGE("External displays are not supported by the vr hardware composer.");
+ return;
+ }
+ mHwc->onHotplug(display, connection);
auto type = DisplayDevice::DISPLAY_EXTERNAL;
- Mutex::Autolock _l(mStateLock);
- if (connected) {
+ if (connection == HWC2::Connection::Connected) {
createBuiltinDisplayLocked(type);
} else {
mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
@@ -1312,46 +1340,31 @@ void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool
}
}
-void SurfaceFlinger::onInvalidateReceived(HWComposer* composer) {
+void SurfaceFlinger::onRefreshReceived(int sequenceId,
+ hwc2_display_t /*display*/) {
Mutex::Autolock lock(mStateLock);
- if (composer == mHwc) {
- repaintEverything();
- } else {
- // This isn't from our current hardware composer. If it's a callback
- // from the real composer, forward the refresh request to vr
- // flinger. Otherwise ignore it.
- if (!composer->isUsingVrComposer()) {
- mVrFlinger->OnHardwareComposerRefresh();
- }
+ if (sequenceId != mComposerSequenceId) {
+ return;
}
+ repaintEverything();
}
void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) {
ATRACE_CALL();
+ Mutex::Autolock lock(mStateLock);
getHwComposer().setVsyncEnabled(disp,
enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
}
// Note: it is assumed the caller holds |mStateLock| when this is called
-void SurfaceFlinger::resetHwcLocked() {
+void SurfaceFlinger::resetDisplayState() {
disableHardwareVsync(true);
- clearHwcLayers(mDrawingState.layersSortedByZ);
- clearHwcLayers(mCurrentState.layersSortedByZ);
- for (size_t disp = 0; disp < mDisplays.size(); ++disp) {
- clearHwcLayers(mDisplays[disp]->getVisibleLayersSortedByZ());
- }
// 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();
- // Release virtual display hwcId during vr mode transition.
- for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
- const sp<DisplayDevice>& displayDevice = mDisplays[displayId];
- if (displayDevice->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL) {
- displayDevice->disconnect(getHwComposer());
- }
- }
+ eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
mDisplays.clear();
}
@@ -1363,57 +1376,54 @@ void SurfaceFlinger::updateVrFlinger() {
return;
}
- if (vrFlingerRequestsDisplay && !mVrHwc) {
- // Construct new HWComposer without holding any locks.
- mVrHwc = new HWComposer("vr");
-
- // Set up the event handlers. This step is neccessary to initialize the internal state of
- // the hardware composer object properly. Our callbacks are designed such that if they are
- // triggered between now and the point where the display is properly re-initialized, they
- // will not have any effect, so this is safe to do here, before the lock is aquired.
- mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
- ALOGV("Vr HWC created");
+ if (vrFlingerRequestsDisplay && !mHwc->getComposer()->isRemote()) {
+ ALOGE("Vr flinger is only supported for remote hardware composer"
+ " service connections. Ignoring request to transition to vr"
+ " flinger.");
+ mVrFlingerRequestsDisplay = false;
+ return;
}
Mutex::Autolock _l(mStateLock);
- if (vrFlingerRequestsDisplay) {
- resetHwcLocked();
-
- mHwc = mVrHwc;
- mVrFlinger->GrantDisplayOwnership();
+ int currentDisplayPowerMode = getDisplayDeviceLocked(
+ mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])->getPowerMode();
- } else {
+ if (!vrFlingerRequestsDisplay) {
mVrFlinger->SeizeDisplayOwnership();
+ }
- resetHwcLocked();
+ resetDisplayState();
+ mHwc.reset(); // Delete the current instance before creating the new one
+ mHwc.reset(new HWComposer(
+ vrFlingerRequestsDisplay ? "vr" : mHwcServiceName));
+ mHwc->registerCallback(this, ++mComposerSequenceId);
- mHwc = mRealHwc;
+ LOG_ALWAYS_FATAL_IF(!mHwc->getComposer()->isRemote(),
+ "Switched to non-remote hardware composer");
+
+ if (vrFlingerRequestsDisplay) {
+ mVrFlinger->GrantDisplayOwnership();
+ } else {
enableHardwareVsync();
}
mVisibleRegionsDirty = true;
invalidateHwcGeometry();
- // Explicitly re-initialize the primary display. This is because some other
- // parts of this class rely on the primary display always being available.
- createDefaultDisplayDevice();
-
// Re-enable default display.
- sp<LambdaMessage> requestMessage = new LambdaMessage([&]() {
- sp<DisplayDevice> hw(getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]));
- setPowerModeInternal(hw, HWC_POWER_MODE_NORMAL);
+ sp<DisplayDevice> hw(getDisplayDeviceLocked(
+ mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]));
+ setPowerModeInternal(hw, currentDisplayPowerMode, /*stateLockHeld*/ true);
- // Reset the timing values to account for the period of the swapped in HWC
- const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
- const nsecs_t period = activeConfig->getVsyncPeriod();
- mAnimFrameTracker.setDisplayRefreshPeriod(period);
+ // Reset the timing values to account for the period of the swapped in HWC
+ const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+ const nsecs_t period = activeConfig->getVsyncPeriod();
+ mAnimFrameTracker.setDisplayRefreshPeriod(period);
- // Use phase of 0 since phase is not known.
- // Use latency of 0, which will snap to the ideal latency.
- setCompositorTimingSnapped(0, period, 0);
- });
- postMessageAsync(requestMessage);
+ // Use phase of 0 since phase is not known.
+ // Use latency of 0, which will snap to the ideal latency.
+ setCompositorTimingSnapped(0, period, 0);
android_atomic_or(1, &mRepaintEverything);
setTransactionFlags(eDisplayTransactionNeeded);
@@ -1749,15 +1759,14 @@ void SurfaceFlinger::rebuildLayerStacks() {
} else {
// Clear out the HWC layer if this layer was
// previously visible, but no longer is
- layer->setHwcLayer(displayDevice->getHwcDisplayId(),
- nullptr);
+ layer->destroyHwcLayer(
+ displayDevice->getHwcDisplayId());
}
} else {
// WM changes displayDevice->layerStack upon sleep/awake.
// Here we make sure we delete the HWC layers even if
// WM changed their layer stack.
- layer->setHwcLayer(displayDevice->getHwcDisplayId(),
- nullptr);
+ layer->destroyHwcLayer(displayDevice->getHwcDisplayId());
}
});
}
@@ -1872,10 +1881,7 @@ void SurfaceFlinger::setUpHWComposer() {
for (size_t i = 0; i < currentLayers.size(); i++) {
const auto& layer = currentLayers[i];
if (!layer->hasHwcLayer(hwcId)) {
- auto hwcLayer = mHwc->createLayer(hwcId);
- if (hwcLayer) {
- layer->setHwcLayer(hwcId, std::move(hwcLayer));
- } else {
+ if (!layer->createHwcLayer(mHwc.get(), hwcId)) {
layer->forceClientComposition(hwcId);
continue;
}
@@ -2161,7 +2167,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
if (state.surface != NULL) {
// Allow VR composer to use virtual displays.
- if (mUseHwcVirtualDisplays || mHwc == mVrHwc) {
+ if (mUseHwcVirtualDisplays || mHwc->isUsingVrComposer()) {
int width = 0;
int status = state.surface->query(
NATIVE_WINDOW_WIDTH, &width);
@@ -3285,7 +3291,8 @@ void SurfaceFlinger::onInitializeDisplays() {
d.height = 0;
displays.add(d);
setTransactionState(state, displays, 0);
- setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
+ setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL,
+ /*stateLockHeld*/ false);
const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
const nsecs_t period = activeConfig->getVsyncPeriod();
@@ -3311,7 +3318,7 @@ void SurfaceFlinger::initializeDisplays() {
}
void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
- int mode) {
+ int mode, bool stateLockHeld) {
ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
this);
int32_t type = hw->getDisplayType();
@@ -3328,7 +3335,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
}
if (mInterceptor.isEnabled()) {
- Mutex::Autolock _l(mStateLock);
+ ConditionalLock lock(mStateLock, !stateLockHeld);
ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
if (idx < 0) {
ALOGW("Surface Interceptor SavePowerMode: invalid display token");
@@ -3414,7 +3421,8 @@ void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) {
ALOGW("Attempt to set power mode = %d for virtual display",
mMode);
} else {
- mFlinger.setPowerModeInternal(hw, mMode);
+ mFlinger.setPowerModeInternal(
+ hw, mMode, /*stateLockHeld*/ false);
}
return true;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5123b58913..058f4a1d3b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -60,13 +60,20 @@
#include "SurfaceInterceptor.h"
#include "StartPropertySetThread.h"
+#ifdef USE_HWC2
+#include "DisplayHardware/HWC2.h"
#include "DisplayHardware/HWComposer.h"
+#else
+#include "DisplayHardware/HWComposer_hwc1.h"
+#endif
+
#include "Effects/Daltonizer.h"
#include <map>
#include <mutex>
#include <queue>
#include <string>
+#include <thread>
#include <utility>
namespace android {
@@ -99,7 +106,11 @@ enum {
class SurfaceFlinger : public BnSurfaceComposer,
private IBinder::DeathRecipient,
+#ifdef USE_HWC2
+ private HWC2::ComposerCallback
+#else
private HWComposer::EventHandler
+#endif
{
public:
@@ -314,11 +325,20 @@ private:
virtual void onFirstRef();
/* ------------------------------------------------------------------------
- * HWComposer::EventHandler interface
+ * HWC2::ComposerCallback / HWComposer::EventHandler interface
*/
- virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp);
- virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected);
- virtual void onInvalidateReceived(HWComposer* composer);
+#ifdef USE_HWC2
+ void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
+ int64_t timestamp) override;
+ void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+ HWC2::Connection connection,
+ bool primaryDisplay) override;
+ void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override;
+#else
+ void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp) override;
+ void onHotplugReceived(HWComposer* composer, int disp, bool connected) override;
+ void onInvalidateReceived(HWComposer* composer) override;
+#endif
/* ------------------------------------------------------------------------
* Message handling
@@ -333,7 +353,12 @@ private:
// called on the main thread in response to setActiveConfig()
void setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode);
// called on the main thread in response to setPowerMode()
+#ifdef USE_HWC2
+ void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode,
+ bool stateLockHeld);
+#else
void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
+#endif
// Called on the main thread in response to setActiveColorMode()
void setActiveColorModeInternal(const sp<DisplayDevice>& hw, android_color_mode_t colorMode);
@@ -591,13 +616,7 @@ private:
/* ------------------------------------------------------------------------
* VrFlinger
*/
- template<typename T>
- void clearHwcLayers(const T& layers) {
- for (size_t i = 0; i < layers.size(); ++i) {
- layers[i]->clearHwcLayers();
- }
- }
- void resetHwcLocked();
+ void resetDisplayState();
// Check to see if we should handoff to vr flinger.
void updateVrFlinger();
@@ -624,13 +643,14 @@ private:
// access must be protected by mInvalidateLock
volatile int32_t mRepaintEverything;
- // current, real and vr hardware composers.
- HWComposer* mHwc;
+ // The current hardware composer interface. When switching into and out of
+ // vr, our HWComposer instance will be recreated.
+ std::unique_ptr<HWComposer> mHwc;
+
#ifdef USE_HWC2
- HWComposer* mRealHwc;
- HWComposer* mVrHwc;
const std::string mHwcServiceName; // "default" for real use, something else for testing.
#endif
+
// constant members (no synchronization needed for access)
RenderEngine* mRenderEngine;
nsecs_t mBootTime;
@@ -644,10 +664,6 @@ private:
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{LayerVector::StateSet::Drawing};
@@ -769,8 +785,14 @@ private:
status_t CheckTransactCodeCredentials(uint32_t code);
#ifdef USE_HWC2
+ std::unique_ptr<dvr::VrFlinger> mVrFlinger;
std::atomic<bool> mVrFlingerRequestsDisplay;
static bool useVrFlinger;
+ std::thread::id mMainThreadId;
+ // The composer sequence id is a monotonically increasing integer that we
+ // use to differentiate callbacks from different hardware composer
+ // instances. Each hardware composer instance gets a different sequence id.
+ int32_t mComposerSequenceId;
#endif
float mSaturation = 1.0f;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 7aaa42aa4b..78a04e08e1 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -535,8 +535,8 @@ void SurfaceFlinger::init() {
// Initialize the H/W composer object. There may or may not be an
// actual hardware composer underneath.
- mHwc = new HWComposer(this,
- *static_cast<HWComposer::EventHandler *>(this));
+ mHwc.reset(new HWComposer(this,
+ *static_cast<HWComposer::EventHandler *>(this)));
// get a RenderEngine for the given display / config (can't fail)
mRenderEngine = RenderEngine::create(mEGLDisplay,